sync #82
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: sync | |
| # Daily registry sync. Re-runs every producer entry, regenerates the | |
| # README, stats, badges, and .well-known files, then opens a PR with the | |
| # diff for auto-merge once required checks pass. The PR path lets us | |
| # enforce branch protection (required status checks + codeowner review) | |
| # while still automating ingestion. | |
| # | |
| # Escape hatch: `workflow_dispatch` with `direct_push=true` skips the PR | |
| # and pushes straight to main. Use only when branch protection is | |
| # bypassed (admin) — auto-merge handles normal operation. | |
| on: | |
| schedule: | |
| - cron: '0 3 * * *' | |
| repository_dispatch: | |
| types: [sync-entry] | |
| workflow_dispatch: | |
| inputs: | |
| id: | |
| description: 'Single entry id (owner/repo) to sync' | |
| required: false | |
| type: string | |
| revalidate: | |
| description: 'Resync all entries even if unchanged' | |
| required: false | |
| type: boolean | |
| default: false | |
| direct_push: | |
| description: 'Bypass PR; push directly to main (admin only)' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: sync-${{ github.event.client_payload.id || github.event.inputs.id || 'all' }} | |
| cancel-in-progress: false | |
| jobs: | |
| sync: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: write | |
| steps: | |
| # pin: v6.0.0 -- actions/checkout | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 | |
| # pin: v6.0.0 -- actions/setup-node | |
| - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: 'npm' | |
| - run: npm ci | |
| - name: Resolve target id | |
| id: target | |
| env: | |
| DISPATCH_ID: ${{ github.event.client_payload.id }} | |
| INPUT_ID: ${{ github.event.inputs.id }} | |
| run: | | |
| ID="${DISPATCH_ID:-$INPUT_ID}" | |
| if [[ -n "$ID" && ! "$ID" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then | |
| echo "rejecting malformed id: $ID" >&2 | |
| exit 1 | |
| fi | |
| echo "id=$ID" >> "$GITHUB_OUTPUT" | |
| - name: Smoke (dry-run; cron only) | |
| if: github.event_name == 'schedule' | |
| run: npm run smoke | |
| - name: Sync | |
| env: | |
| TARGET_ID: ${{ steps.target.outputs.id }} | |
| run: | | |
| if [ -n "$TARGET_ID" ]; then | |
| node scripts/sync.mjs --only "$TARGET_ID" | |
| else | |
| node scripts/sync.mjs | |
| fi | |
| - name: Render README inline | |
| run: npm run render | |
| - name: Aggregate cross-graph stats | |
| run: node scripts/aggregate.mjs --registry registry.json --out site/stats.json | |
| - name: Render badges | |
| run: node scripts/render-badges.mjs --registry registry.json --out site/badges | |
| - name: Render well-known | |
| run: node scripts/well-known.mjs --registry registry.json --out site/.well-known | |
| - name: Check for diff | |
| id: diff | |
| run: | | |
| if git diff --quiet registry.json README.md site/stats.json site/badges site/.well-known; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| echo "no changes to commit" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| # Direct push path (admin escape hatch). Used when | |
| # workflow_dispatch.inputs.direct_push=true; bypasses the PR. | |
| - name: Configure git (direct push only) | |
| if: steps.diff.outputs.changed == 'true' && github.event.inputs.direct_push == 'true' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Commit and push (direct push only) | |
| if: steps.diff.outputs.changed == 'true' && github.event.inputs.direct_push == 'true' | |
| run: | | |
| git add registry.json README.md site/stats.json site/badges site/.well-known | |
| git commit -m "chore(sync): update registry and README" | |
| git push | |
| # PR path (default). create-pull-request stages the diff, opens | |
| # or updates the bot/sync branch, and the next step enables | |
| # auto-merge so it lands once branch protection's required checks | |
| # go green. | |
| # pin: v8.1.1 -- peter-evans/create-pull-request | |
| - name: Open or update sync PR | |
| if: steps.diff.outputs.changed == 'true' && github.event.inputs.direct_push != 'true' | |
| id: cpr | |
| uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| branch: bot/sync | |
| delete-branch: true | |
| commit-message: 'chore(sync): update registry and README' | |
| title: 'chore(sync): update registry and README' | |
| body: | | |
| Automated registry resync from `scripts/sync.mjs`. | |
| Touches: | |
| - `registry.json` — entry-level `head_sha`, `last_validated_at`, | |
| and any newly drifted entries. | |
| - `README.md` — rendered entry table. | |
| - `site/stats.json`, `site/badges/`, `site/.well-known/` — | |
| regenerated derivatives. | |
| Auto-merges once required status checks pass. | |
| labels: | | |
| bot-sync | |
| automerge | |
| chore | |
| add-paths: | | |
| registry.json | |
| README.md | |
| site/stats.json | |
| site/badges | |
| site/.well-known | |
| # Auto-merge intentionally NOT enabled here. GitHub's | |
| # branch-protection bypass allowlist does not accept the built-in | |
| # `github-actions` app slug, so the bot's PR cannot satisfy | |
| # `require_code_owner_reviews`. The PR sits open until a | |
| # codeowner (amacsmith) reviews and merges manually, OR until we | |
| # wire a custom GitHub App or fine-grained PAT through | |
| # `secrets.BOT_PAT` and re-enable the enable-pull-request-automerge | |
| # step using that token. | |
| - name: Trigger pages redeploy (best-effort) | |
| if: steps.diff.outputs.changed == 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: gh workflow run pages.yml --repo "$GITHUB_REPOSITORY" --ref main |