Skip to content

Commit 51fcf26

Browse files
authored
Update GitHub Actions workflow for editorconfig sync
1 parent 069068e commit 51fcf26

1 file changed

Lines changed: 71 additions & 136 deletions

File tree

Lines changed: 71 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,106 @@
1-
name: Sync .editorconfig from canonical
1+
name: Sync .editorconfig from canonical (PR-only)
2+
23
on:
4+
# "Git-triggered polling": run on pushes in this repo
35
push:
6+
branches:
7+
- "**"
8+
branches-ignore:
9+
- "chore/sync-editorconfig" # bot branch created by this workflow
10+
# Fail early on PRs if branch is out-of-sync
411
pull_request:
12+
workflow_dispatch:
513

614
permissions:
715
contents: write
816
pull-requests: write
917

1018
env:
11-
# Replace with your canonical repo and branch if different
12-
CANONICAL_REPO: BionicCode/bioniccode-code-style
13-
CANONICAL_BRANCH: main
19+
CANONICAL_RAW_URL: https://raw.githubusercontent.com/BionicCode/bioniccode-code-style/main/.editorconfig
20+
SYNC_BRANCH: chore/sync-editorconfig
21+
22+
concurrency:
23+
group: editorconfig-sync
24+
cancel-in-progress: true
1425

1526
jobs:
16-
sync-editorconfig:
17-
# Determine the branch to target: for pull_request use the PR head branch, otherwise use ref_name
18-
env:
19-
TARGET_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }}
20-
# true when this run is a pull_request from a fork; used to avoid using secrets for forked PRs
21-
IS_FORK: ${{ github.event.pull_request != null && github.event.pull_request.head.repo.fork == true }}
27+
# 1) PR guard: make out-of-sync immediately visible to developers
28+
verify-on-pr:
29+
if: github.event_name == 'pull_request'
2230
runs-on: ubuntu-latest
23-
concurrency:
24-
group: sync-editorconfig-${{ github.ref_name }}
25-
cancel-in-progress: true
26-
2731
steps:
28-
- name: Exit if triggered by Actions bot (avoid loops)
29-
if: ${{ github.actor == 'github-actions[bot]' }}
30-
run: |
31-
echo "Triggered by github-actions[bot], exiting to avoid loop."
32-
exit 0
33-
34-
- name: Checkout repository
32+
- name: Checkout PR head
3533
uses: actions/checkout@v4
3634
with:
37-
fetch-depth: 0
38-
persist-credentials: true
35+
ref: ${{ github.head_ref }}
3936

40-
- name: Fetch canonical .editorconfig (token clone if available and not a fork, otherwise raw URL)
37+
- name: Download canonical .editorconfig
4138
run: |
42-
set -e
43-
CANONICAL_PATH="BionicCode.CodeStyle/BionicCode.CodeStyle/.editorconfig"
44-
RAW_URL="https://raw.githubusercontent.com/${{ env.CANONICAL_REPO }}/${{ env.CANONICAL_BRANCH }}/${CANONICAL_PATH}"
45-
echo "Canonical repo: ${{ env.CANONICAL_REPO }} (branch: ${{ env.CANONICAL_BRANCH }})"
46-
echo "Using raw URL: $RAW_URL"
39+
set -euo pipefail
40+
curl -fsSL "${CANONICAL_RAW_URL}" -o canonical.editorconfig
4741
48-
# Only attempt token clone if a token is present AND this is not a forked PR
49-
if [ -n "${{ secrets.CANONICAL_REPO_TOKEN }}" ] && [ "${{ env.IS_FORK }}" != "true" ]; then
50-
echo "Attempting authenticated clone of canonical repository"
51-
git clone --depth 1 https://x-access-token:${{ secrets.CANONICAL_REPO_TOKEN }}@github.com/${{ env.CANONICAL_REPO }} canonical-repo || true
52-
if [ -f canonical-repo/.editorconfig ]; then
53-
cp canonical-repo/.editorconfig canonical.editorconfig
54-
echo "Fetched canonical .editorconfig via authenticated clone."
55-
else
56-
echo "Authenticated clone succeeded but canonical .editorconfig not found in canonical-repo"
57-
fi
58-
else
59-
echo "No usable token (or forked PR). Falling back to public raw URL"
60-
curl -fsSL "$RAW_URL" -o canonical.editorconfig || true
61-
if [ -s canonical.editorconfig ]; then
62-
echo "Fetched canonical .editorconfig via public raw URL."
63-
else
64-
echo "Failed to fetch canonical.editorconfig from raw URL"
65-
fi
66-
fi
67-
68-
- name: Ensure we have a canonical file
42+
- name: Ensure exactly one tracked .editorconfig (optional strictness)
6943
run: |
70-
if [ ! -s canonical.editorconfig ]; then
71-
echo "Error: canonical.editorconfig not available. Aborting." >&2
44+
set -euo pipefail
45+
count=$(git ls-files '**/.editorconfig' | wc -l | tr -d ' ')
46+
if [ "$count" -eq 0 ]; then
47+
echo "::error::.editorconfig is missing in this repo."
48+
exit 1
49+
fi
50+
if [ "$count" -gt 1 ]; then
51+
echo "::error::Multiple .editorconfig files found. Keep only the repo-root .editorconfig to avoid overrides."
52+
git ls-files '**/.editorconfig'
7253
exit 1
7354
fi
7455
75-
- name: Compare with repository .editorconfig
76-
id: compare
56+
- name: Fail if branch .editorconfig is out of sync
7757
run: |
78-
if [ -f .editorconfig ] && cmp -s .editorconfig canonical.editorconfig; then
79-
echo "same=true" >> $GITHUB_OUTPUT
58+
set -euo pipefail
59+
if cmp -s .editorconfig canonical.editorconfig; then
60+
echo ".editorconfig is in sync with canonical."
8061
else
81-
echo "same=false" >> $GITHUB_OUTPUT
62+
echo "::error::.editorconfig is OUT OF SYNC with canonical. Merge the sync PR (or rerun the sync workflow)."
63+
exit 1
8264
fi
8365
84-
- name: Prepare workspace with canonical .editorconfig
85-
if: steps.compare.outputs.same == 'false'
86-
run: |
87-
# Overwrite or create the repo's .editorconfig with the canonical file
88-
cp canonical.editorconfig .editorconfig
89-
# Debug: show file summary to make sure the copy happened
90-
echo "Workspace .editorconfig:"
91-
ls -la .editorconfig || true
92-
echo "---- head of .editorconfig ----"
93-
sed -n '1,40p' .editorconfig || true
94-
echo "--------------------------------"
66+
# 2) PR creator/updater: always proposes canonical via one rolling PR
67+
open-or-update-sync-pr:
68+
if: github.event_name != 'pull_request' && github.actor != 'github-actions[bot]'
69+
runs-on: ubuntu-latest
70+
steps:
71+
- name: Checkout default branch
72+
uses: actions/checkout@v4
73+
with:
74+
ref: ${{ github.event.repository.default_branch }}
9575

96-
- name: Commit and attempt to push .editorconfig to target branch (sets push_succeeded)
97-
id: commit_push
98-
if: steps.compare.outputs.same == 'false'
76+
- name: Download canonical .editorconfig
9977
run: |
100-
# We'll always write an output push_succeeded (true/false). The step must succeed
101-
# so the workflow can run a fallback PR when push fails.
102-
set -o pipefail
103-
PUSH_SUCCEEDED=false
78+
set -euo pipefail
79+
curl -fsSL "${CANONICAL_RAW_URL}" -o canonical.editorconfig
10480
105-
echo "Preparing to commit .editorconfig to branch '${{ env.TARGET_BRANCH }}'"
106-
107-
# Configure git for the automated commit
108-
git config user.name "github-actions[bot]"
109-
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
110-
111-
# Only attempt push when this run is allowed to push (push events, or PRs from the same repo)
112-
if [ "${{ github.event_name }}" = "push" ] || \
113-
( [ "${{ github.event_name }}" = "pull_request" ] && [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ] ); then
114-
115-
echo "Push permitted for this run; attempting to commit and push."
116-
117-
# Ensure we have an up-to-date view of the remote target branch
118-
git fetch origin "${{ env.TARGET_BRANCH }}" || true
119-
120-
# Checkout the target branch (create it locally if it doesn't exist)
121-
if git rev-parse --verify "${{ env.TARGET_BRANCH }}" >/dev/null 2>&1; then
122-
git checkout "${{ env.TARGET_BRANCH }}"
123-
else
124-
git checkout -b "${{ env.TARGET_BRANCH }}"
125-
fi
126-
127-
# Add and commit .editorconfig
128-
git add .editorconfig
129-
130-
if git diff --staged --quiet; then
131-
echo "No staged changes to commit. Nothing to push."
132-
PUSH_SUCCEEDED=true
133-
else
134-
git commit -m "chore(sync): update .editorconfig from canonical" --author="github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" || true
135-
136-
# Push and capture exit code instead of failing the step
137-
echo "Pushing to origin/${{ env.TARGET_BRANCH }}..."
138-
if git push origin "${{ env.TARGET_BRANCH }}"; then
139-
echo "Push successful."
140-
PUSH_SUCCEEDED=true
141-
else
142-
echo "Push failed (remote rejected or permission error). Will fall back to PR."
143-
PUSH_SUCCEEDED=false
144-
fi
145-
fi
146-
else
147-
echo "This run is not permitted to push (e.g., forked PR). Skipping direct push and will fall back to PR."
148-
PUSH_SUCCEEDED=false
149-
fi
150-
151-
# Emit the result for later steps
152-
if [ "$PUSH_SUCCEEDED" = "true" ]; then
153-
echo "push_succeeded=true" >> $GITHUB_OUTPUT
81+
- name: Detect changes
82+
id: diff
83+
run: |
84+
set -euo pipefail
85+
if [ -f .editorconfig ] && cmp -s .editorconfig canonical.editorconfig; then
86+
echo "changed=false" >> "$GITHUB_OUTPUT"
15487
else
155-
echo "push_succeeded=false" >> $GITHUB_OUTPUT
88+
echo "changed=true" >> "$GITHUB_OUTPUT"
89+
mv canonical.editorconfig .editorconfig
15690
fi
15791
158-
- name: "Fallback: open PR if direct push was not possible/failed"
159-
if: steps.compare.outputs.same == 'false' && steps.commit_push.outputs.push_succeeded != 'true'
160-
uses: peter-evans/create-pull-request@v5
92+
- name: Create or update PR
93+
if: steps.diff.outputs.changed == 'true'
94+
uses: peter-evans/create-pull-request@v7
16195
with:
162-
branch: sync-editorconfig/${{ github.run_id }}
163-
base: ${{ env.TARGET_BRANCH }}
164-
title: "chore: sync .editorconfig with canonical"
165-
body: |
166-
This automated PR updates or adds .editorconfig from the canonical repository (${{ env.CANONICAL_REPO }}@${{ env.CANONICAL_BRANCH }}).
167-
Please merge or pull this update to ensure your local analyzers and formatting use the canonical rules.
96+
branch: ${{ env.SYNC_BRANCH }}
97+
base: ${{ github.event.repository.default_branch }}
98+
title: "chore: sync .editorconfig from canonical"
16899
commit-message: "chore(sync): update .editorconfig from canonical"
100+
body: |
101+
Automated sync of `.editorconfig` from the canonical repository.
102+
103+
Source: BionicCode/bioniccode-code-style (main)
104+
add-paths: |
105+
.editorconfig
169106
labels: automation
170-
add-paths: .editorconfig
171-
author: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"

0 commit comments

Comments
 (0)