diff --git a/.github/workflows/schema-update.yml b/.github/workflows/schema-update.yml index b408e100..a7f17874 100644 --- a/.github/workflows/schema-update.yml +++ b/.github/workflows/schema-update.yml @@ -10,6 +10,12 @@ on: permissions: contents: write +concurrency: + # Serialize runs that share the reused chore/schema-update branch so two + # near-simultaneous main pushes don't race on it. + group: schema-update-${{ github.ref }} + cancel-in-progress: false + jobs: generate-schema: name: Update configuration json schema @@ -17,6 +23,10 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: + # Same-repo PRs check out the PR head branch so the regenerated schema + # can be committed back to it. Fork PRs check out the merge ref so the + # schema is generated from the PR's code. Push / dispatch use main. + ref: ${{ github.event_name == 'pull_request' && (github.event.pull_request.head.repo.full_name == github.repository && github.head_ref || github.ref) || 'main' }} token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: @@ -24,9 +34,44 @@ jobs: cache: npm - run: npm ci - run: node --run website-generate-schema - - uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 + + # On same-repo pull requests, commit the regenerated schema back into the + # PR branch so the schema change rides along with the PR that caused it. + - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }} + uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 with: - commit_message: 'chore(schema): auto generate schema' + commit_message: 'chore(schema): Auto-generate schema' commit_user_name: "github-actions[bot]" commit_user_email: "github-actions[bot]@users.noreply.github.com" commit_author: "github-actions[bot] " + + # Fork pull requests use a read-only token and cannot be committed to, so + # fail if the schema is out of date to surface the drift instead of + # silently merging it. + - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} + run: | + if ! git diff --quiet; then + echo "::error::Generated schema is out of date. Run 'node --run website-generate-schema' and commit the result." + git --no-pager diff --stat + exit 1 + fi + + # On main (e.g. after a version bump), direct pushes are blocked by the + # branch ruleset (pull_request required), so deliver the regenerated + # schema as a PR instead. COMMITTER_TOKEN is used so the PR triggers CI + # and is mergeable. + - if: github.event_name != 'pull_request' + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 + with: + token: ${{ secrets.COMMITTER_TOKEN }} + base: main + commit-message: 'chore(schema): Auto-generate schema' + branch: chore/schema-update + delete-branch: true + title: 'chore(schema): Update configuration JSON schema' + body: | + Automated schema update generated by the Update Schema workflow. + + Direct pushes to `main` are blocked by the branch ruleset, so the + regenerated schema is delivered as this PR instead. + author: 'github-actions[bot] '