14
permissions:
15
actions: read
16
contents: write
17
- pull-requests: write
17
+ pages: write
18
+ id-token: write
19
20
concurrency:
21
group: weekly-crawl
129
path: data/cache/
130
if-no-files-found: warn
131
131
- - name: Commit crawl data via PR
132
+ - name: Commit crawl data to data branch
133
env:
134
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
135
+ DATA_BRANCH: publish
136
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137
run: |
138
set -euo pipefail
139
git config user.name "github-actions[bot]"
140
git config user.email "github-actions[bot]@users.noreply.github.com"
139
- # Save crawl output before syncing with remote
141
+ # Save crawl output before switching branches
142
cp -r data/raw crawl-raw-backup
143
cp -r data/snapshots crawl-snapshots-backup
142
- git fetch origin "$DEFAULT_BRANCH"
143
- git checkout -B "$DEFAULT_BRANCH" "origin/$DEFAULT_BRANCH"
144
- # Restore crawl output on top of synced branch
144
+ # Fetch or create the unprotected data branch
145
+ if git fetch origin "$DATA_BRANCH" 2>/dev/null; then
146
+ git checkout -f -B "$DATA_BRANCH" "origin/$DATA_BRANCH"
147
+ else
148
+ git checkout -f -B "$DATA_BRANCH" "origin/$DEFAULT_BRANCH"
149
+ fi
150
+ # Restore crawl output on top of data branch
151
+ mkdir -p data/raw data/snapshots
152
cp -r crawl-raw-backup/* data/raw/ 2>/dev/null || true
153
cp -r crawl-snapshots-backup/* data/snapshots/ 2>/dev/null || true
154
rm -rf crawl-raw-backup crawl-snapshots-backup
160
COUNTER=$((COUNTER + 1))
161
printf '%s\n' "$COUNTER" > .squad/run-counter.txt
162
WEEK=$(date +%Y-W%V)
156
- BRANCH="data/weekly-crawl-${WEEK}-${GITHUB_RUN_ID}"
157
- git checkout -b "$BRANCH"
163
git add data/raw/ data/snapshots/ .squad/run-counter.txt
164
git diff --cached --quiet && exit 0
160
- git commit -m "data: weekly crawl $WEEK"
161
- git push origin "$BRANCH"
162
- gh pr create --base "$DEFAULT_BRANCH" --head "$BRANCH" \
163
- --title "data: weekly crawl $WEEK" \
164
- --body "Automated weekly crawl data commit from run #${GITHUB_RUN_ID}."
165
- gh pr merge "$BRANCH" --squash --auto --delete-branch
165
+ git commit -m "data: weekly crawl $WEEK [run #${GITHUB_RUN_ID}]"
166
+ git push origin "$DATA_BRANCH"
167
168
analyze:
169
needs: crawl
171
permissions:
172
actions: read
173
contents: write
173
- pull-requests: write
174
outputs:
175
week: ${{ steps.analysis-context.outputs.week }}
176
summary_file: ${{ steps.analysis-context.outputs.output_file }}
359
--current-datetime "$CURRENT_DATETIME" \
360
--source "$ANALYSIS_SOURCE"
361
362
- - name: Commit analysis via PR
362
+ - name: Commit analysis to data branch
363
env:
364
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
365
+ DATA_BRANCH: publish
366
WEEK: ${{ steps.analysis-context.outputs.week }}
367
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
368
run: |
375
fi
376
cp -r data/analyzed analyzed-data-backup
377
cp -r data/metrics metrics-data-backup
377
- git fetch origin "$DEFAULT_BRANCH"
378
- git checkout -B "$DEFAULT_BRANCH" "origin/$DEFAULT_BRANCH"
378
+ # Push to the unprotected data branch
379
+ if git fetch origin "$DATA_BRANCH" 2>/dev/null; then
380
+ git checkout -f -B "$DATA_BRANCH" "origin/$DATA_BRANCH"
381
+ else
382
+ git fetch origin "$DEFAULT_BRANCH"
383
+ git checkout -f -B "$DATA_BRANCH" "origin/$DEFAULT_BRANCH"
384
+ fi
385
mkdir -p data/analyzed data/metrics
386
cp -r analyzed-data-backup/* data/analyzed/ 2>/dev/null || true
387
cp -r metrics-data-backup/* data/metrics/ 2>/dev/null || true
388
rm -rf analyzed-data-backup metrics-data-backup
383
- BRANCH="data/analysis-${WEEK}-${GITHUB_RUN_ID}"
384
- git checkout -b "$BRANCH"
389
git add data/analyzed/ data/metrics/
390
git diff --cached --quiet && exit 0
387
- git commit -m "analysis: weekly summary $WEEK"
388
- git push origin "$BRANCH"
389
- gh pr create --base "$DEFAULT_BRANCH" --head "$BRANCH" \
390
- --title "analysis: weekly summary $WEEK" \
391
- --body "Automated analysis commit from run #${GITHUB_RUN_ID}."
392
- gh pr merge "$BRANCH" --squash --auto --delete-branch
391
+ git commit -m "analysis: weekly summary $WEEK [run #${GITHUB_RUN_ID}]"
392
+ git push origin "$DATA_BRANCH"
393
394
- name: Upload analyzed data
395
uses: actions/upload-artifact@v4
404
permissions:
405
actions: read
406
contents: write
407
- pull-requests: write
407
outputs:
408
page_path: ${{ steps.generate-content.outputs.page_path }}
409
445
- name: Generate rollups
446
run: python3 scripts/generate_rollups.py
447
449
- - name: Commit generated content via PR
448
+ - name: Commit generated content to data branch
449
env:
450
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
451
+ DATA_BRANCH: publish
452
WEEK: ${{ needs.analyze.outputs.week }}
453
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
454
run: |
462
cp -r content/weekly content-weekly-backup 2>/dev/null || true
463
cp -r content/monthly content-monthly-backup 2>/dev/null || true
464
cp -r content/yearly content-yearly-backup 2>/dev/null || true
465
- git fetch origin "$DEFAULT_BRANCH"
466
- git checkout -B "$DEFAULT_BRANCH" "origin/$DEFAULT_BRANCH"
465
+ # Push to the unprotected data branch
466
+ if git fetch origin "$DATA_BRANCH" 2>/dev/null; then
467
+ git checkout -f -B "$DATA_BRANCH" "origin/$DATA_BRANCH"
468
+ else
469
+ git fetch origin "$DEFAULT_BRANCH"
470
+ git checkout -f -B "$DATA_BRANCH" "origin/$DEFAULT_BRANCH"
471
+ fi
472
mkdir -p content/weekly content/monthly content/yearly
473
cp -r content-weekly-backup/* content/weekly/ 2>/dev/null || true
474
cp -r content-monthly-backup/* content/monthly/ 2>/dev/null || true
475
cp -r content-yearly-backup/* content/yearly/ 2>/dev/null || true
476
rm -rf content-weekly-backup content-monthly-backup content-yearly-backup
472
- BRANCH="data/content-${WEEK}-${GITHUB_RUN_ID}"
473
- git checkout -b "$BRANCH"
477
git add content/weekly/ content/monthly/ content/yearly/
478
git diff --cached --quiet && exit 0
476
- git commit -m "content: weekly page $WEEK"
477
- git push origin "$BRANCH"
478
- gh pr create --base "$DEFAULT_BRANCH" --head "$BRANCH" \
479
- --title "content: weekly page $WEEK" \
480
- --body "Automated content generation from run #${GITHUB_RUN_ID}."
481
- gh pr merge "$BRANCH" --squash --auto --delete-branch
479
+ git commit -m "content: weekly page $WEEK [run #${GITHUB_RUN_ID}]"
480
+ git push origin "$DATA_BRANCH"
481
482
- name: Upload generated content artifact
483
uses: actions/upload-artifact@v4
526
name: analyzed-data
527
path: data/analyzed/
528
530
- # The generate job already pushes weekly, monthly, and yearly content to the default branch.
531
- # Deploy builds from that branch state to avoid artifact extraction conflicts.
529
+ - name: Download generated content artifact
530
+ uses: actions/download-artifact@v4
531
+ with:
532
+ name: generated-content
533
+ path: content/
534
+ merge-multiple: true
535
+
536
+ # Deploy builds from artifacts — no dependency on PR merges to main.
537
- name: Configure GitHub Pages
538
uses: actions/configure-pages@v5
539
646
- uses: actions/checkout@v4
647
with:
648
fetch-depth: 0
644
- ref: ${{ github.event.repository.default_branch }}
649
+ ref: publish
650
+ continue-on-error: true
651
+
652
+ - name: Fallback to default branch for counter
653
+ run: |
654
+ if [ ! -f .squad/run-counter.txt ]; then
655
+ git fetch origin "${{ github.event.repository.default_branch }}" 2>/dev/null || true
656
+ git checkout "origin/${{ github.event.repository.default_branch }}" -- .squad/run-counter.txt 2>/dev/null || true
657
+ fi
658
659
- name: Check reskill trigger
660
id: check
674
runs-on: ubuntu-latest
675
permissions:
676
contents: write
664
- pull-requests: write
677
678
steps:
679
- uses: actions/checkout@v4
680
with:
681
fetch-depth: 0
670
- ref: ${{ github.event.repository.default_branch }}
682
+ ref: publish
683
+ continue-on-error: true
684
+
685
+ - name: Fallback to default branch
686
+ run: |
687
+ if [ ! -d .squad ]; then
688
+ git fetch origin "${{ github.event.repository.default_branch }}"
689
+ git checkout "origin/${{ github.event.repository.default_branch }}" -- . 2>/dev/null || true
690
+ fi
691
692
- name: Set up Node
693
uses: actions/setup-node@v4
748
749
cp -r .squad squad-state-backup
750
cp -r data/metrics reskill-metrics-backup
731
- git fetch origin "$DEFAULT_BRANCH"
732
- git checkout -B "$DEFAULT_BRANCH" "origin/$DEFAULT_BRANCH"
751
+ DATA_BRANCH="publish"
752
+ if git fetch origin "$DATA_BRANCH" 2>/dev/null; then
753
+ git checkout -f -B "$DATA_BRANCH" "origin/$DATA_BRANCH"
754
+ else
755
+ git fetch origin "$DEFAULT_BRANCH"
756
+ git checkout -f -B "$DATA_BRANCH" "origin/$DEFAULT_BRANCH"
757
+ fi
758
cp -r squad-state-backup/* .squad/ 2>/dev/null || true
759
mkdir -p data/metrics
760
cp -r reskill-metrics-backup/* data/metrics/ 2>/dev/null || true
761
rm -rf squad-state-backup reskill-metrics-backup
737
- BRANCH="data/reskill-${WEEK}-${GITHUB_RUN_ID}"
738
- git checkout -b "$BRANCH"
762
git add .squad/ data/metrics/
763
git diff --cached --quiet && exit 0
741
- git commit -m "chore: reskill state update"
742
- git push origin "$BRANCH"
743
- gh pr create --base "$DEFAULT_BRANCH" --head "$BRANCH" \
744
- --title "chore: reskill state update $WEEK" \
745
- --body "Automated reskill commit from run #${GITHUB_RUN_ID}."
746
- gh pr merge "$BRANCH" --squash --auto --delete-branch
764
+ git commit -m "chore: reskill state update [run #${GITHUB_RUN_ID}]"
765
+ git push origin "$DATA_BRANCH"