diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 15ced9fb5..ca7d450d6 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -7,12 +7,20 @@ name: Changeset on: pull_request: types: [opened, synchronize, reopened, labeled, unlabeled] + # "Changeset present" is a required check on main, so a merge queue entry + # needs a passing context too (see the merge_group note in ci.yml; dormant + # until the repository is organization-owned). The requirement itself is + # enforced on the pull request, which must already be green to enter the + # queue; the queue run only reports success, because a merge_group event + # carries no PR labels and its commit stacks earlier queue entries. + merge_group: + branches: [main] permissions: contents: read concurrency: - group: changeset-${{ github.event.pull_request.number }} + group: changeset-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true jobs: @@ -21,19 +29,26 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: + - name: Merge queue entry — requirement already enforced on the pull request + if: github.event_name == 'merge_group' + run: echo "::notice::merge_group run; the changeset requirement was checked on the pull request." # `changeset status --since=origin/main` diffs against the merge-base # with main, so the PR merge commit needs enough history to reach it. - uses: actions/checkout@v7 + if: github.event_name != 'merge_group' with: fetch-depth: 0 persist-credentials: false - uses: pnpm/setup@v2 + if: github.event_name != 'merge_group' with: cache: true install: false runtime: node@22.19.0 - run: pnpm install --frozen-lockfile + if: github.event_name != 'merge_group' - name: Require a changeset for publishable package changes + if: github.event_name != 'merge_group' env: SKIP_LABEL: ${{ contains(github.event.pull_request.labels.*.name, 'skip-changeset') }} # Only the machine-owned release branch of this repository is exempt; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83729f62f..bec606e2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,14 @@ on: pull_request: push: branches: [main] + # Merge queue: every job that is a required check on main must also run on + # merge_group, or a queued entry waits until the queue times it out. The + # event never fires while this repository is user-owned (GitHub offers the + # queue only to organization-owned repositories: creating a `merge_queue` + # ruleset here returns 422 "Invalid rule 'merge_queue'"), so this trigger + # is dormant until the repository moves to an organization. + merge_group: + branches: [main] # Nightly release-boundary matrix (packed-matrix job): the scaffolder # template tests beyond the per-PR minimal-template smoke. schedule: @@ -14,9 +22,10 @@ permissions: contents: read # PR pushes cancel the superseded run of the same PR (only the latest commit -# matters). Pushes to main, the nightly schedule, and manual dispatches get -# SHA-keyed groups with no cancellation, so a new main push can never kill an -# in-flight main or nightly run. Same pattern as package-preview.yml. +# matters). Pushes to main, merge-queue entries, the nightly schedule, and +# manual dispatches get SHA-keyed groups with no cancellation, so a new main +# push can never kill an in-flight main, queue, or nightly run. Same pattern +# as package-preview.yml. concurrency: group: ci-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} @@ -27,7 +36,9 @@ jobs: # Nested markdown elsewhere is code because examples and packages contain # compiled SKILL.md artifacts, and package markdown affects npm pack audits. # Classification fails open so uncertain PRs run every heavy job; pushes to - # main never skip any job based on changed paths. + # main and merge-queue entries never skip any job based on changed paths + # (this job does not run for them, and the heavy jobs treat the missing + # output as "run"). # Path rules and fail-open listing checks live in # scripts/classify-docs-only.mjs (unit-tested). This job sparse-checkouts # only that script so the vendored Effect subtree never lands on the @@ -110,12 +121,13 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 45 # Measured PR Verify cost was 3 legs × ~7 minutes, about 75% of PR - # runner-minutes. PRs run newest-LTS Node 24; every main push and manual - # dispatch still gates on the full supported matrix. + # runner-minutes. PRs and merge-queue entries run newest-LTS Node 24 (the + # "Verify (Node 24)" context is the required check on main); every main + # push and manual dispatch still gates on the full supported matrix. strategy: fail-fast: false matrix: - node-version: ${{ github.event_name == 'pull_request' && fromJSON('["24"]') || fromJSON('["22.19.0","24","26"]') }} + node-version: ${{ (github.event_name == 'pull_request' || github.event_name == 'merge_group') && fromJSON('["24"]') || fromJSON('["22.19.0","24","26"]') }} steps: - uses: actions/checkout@v7 - uses: pnpm/setup@v2 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 312b6bfb6..fcbaf9ff8 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,6 +17,12 @@ on: pull_request: push: branches: [main] + # "Docs site" is a required check on main, so it must also report on merge + # queue entries (see the merge_group note in ci.yml; dormant until the + # repository is organization-owned). Queue runs build only: the deploy + # steps stay gated on a push or dispatch of main itself. + merge_group: + branches: [main] workflow_dispatch: permissions: @@ -27,7 +33,8 @@ permissions: # build-and-deploy runs execute in order and an older, slower build can never # deploy over a newer one (GitHub keeps at most one pending run per group, so # a superseded pending build is dropped, never reordered). Dispatches on other -# refs get SHA-keyed groups. +# refs and merge-queue entries (ref gh-readonly-queue/main/...) get SHA-keyed +# groups. concurrency: group: docs-${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' && 'main' || github.event.pull_request.number || github.sha }} cancel-in-progress: ${{ github.event_name == 'pull_request' }}