diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9055332..7365451 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,21 +20,22 @@ name: release # and tsc first. So the build happens ONCE, here, and the asset is the # runnable tree: bin/, dist/, production node_modules/, package.json. on: + # ONE push key, both filters — YAML maps are last-key-wins, so a second + # sibling `push:` would silently REPLACE the first and kill a door + # (grok's round-2 catch: the tag fallback had stopped triggering). push: # Every tag, not a shape filter (box's and rig's precedent): a tag that # mismatches package.json — a habitual v0.1.0, a typo — must fail the # assert LOUDLY below, not be silently skipped by a pattern that didn't # match. tags: ["**"] - push: # The merge-is-the-release path (#111) rides pushes to MAIN, not - # pull_request events, for one load-bearing reason the first review - # round caught: a workflow run triggered by a pull_request from a - # public FORK gets a READ-ONLY GITHUB_TOKEN — `permissions:` cannot - # raise that ceiling — and every ceremony PR this org has ever merged - # is cross-repo from the bot fork. The asserts would pass and the tag - # create would 403, red on main, every release. A push to main is an - # in-repo event with the full write token, whoever authored the PR. + # pull_request events: a pull_request run from a public FORK gets a + # READ-ONLY GITHUB_TOKEN — `permissions:` cannot raise that ceiling — + # and every ceremony PR this org merges is cross-repo from the bot + # fork; the tag create would 403 after green asserts. A push to main + # is an in-repo event with the full write token, whoever authored the + # PR. The steps split on the pushed ref. branches: [main] permissions: diff --git a/test/release.test.ts b/test/release.test.ts index 8234e31..51a6305 100644 --- a/test/release.test.ts +++ b/test/release.test.ts @@ -185,12 +185,14 @@ describe("release.yml", () => { // intent — is read via the API off the merge commit's PR, and a // transition with no labeled PR behind it refuses. expect(RY).toContain("branches: [main]"); + // YAML maps are last-key-wins: a second sibling push: key silently + // replaces the first and kills a door (grok's round-2 catch — the tag + // fallback had stopped triggering). Exactly ONE push key may exist. + expect(RY.match(/^ push:$/gm)).toHaveLength(1); expect(RY).toContain("startsWith(github.ref, 'refs/tags/')"); expect(RY).toContain("github.ref == 'refs/heads/main'"); expect(RY).toContain("commits/$GITHUB_SHA/pulls"); - expect(RY).toContain( - "no merged, release-labeled PR is behind this commit", - ); + expect(RY).toContain("no merged, release-labeled PR is behind this commit"); expect(RY).not.toContain("pull_request:"); });