Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,33 @@ jobs:
publish:
name: Publish to npm (gated, idempotent)
needs: [resolve-ref, secret-scan, verify]
# Ref floor for the one job that mints a publishing credential.
# `resolve-ref` proves the TAG is sdk-v<semver>, exists, and is an ancestor
# of origin/main -- so the CODE published is always merged code. It says
# nothing about the RUN's own ref, which is what lands in the OIDC token's
# `ref` claim and scopes this run's Actions cache: a dispatch from an
# arbitrary branch would still reach npm under that branch's identity.
# So: an sdk-v* tag push, a published release, or a dispatch from the
# default branch (the documented backfill path, already ancestry-anchored)
# -- and nothing else. A missing `default_branch` makes `format(...)` yield
# `refs/heads/`, matching no real ref, so the guard fails CLOSED.
if: >-
startsWith(github.ref, 'refs/tags/sdk-v')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A manual dispatch whose selected ref is an sdk-v* tag also passes this clause, even though the guard promises to allow only a tag push. Require github.event_name == 'push' alongside startsWith(...) so dispatches cannot bypass the default-branch backfill boundary.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 310:

<comment>A manual dispatch whose selected ref is an `sdk-v*` tag also passes this clause, even though the guard promises to allow only a tag push. Require `github.event_name == 'push'` alongside `startsWith(...)` so dispatches cannot bypass the default-branch backfill boundary.</comment>

<file context>
@@ -296,8 +296,33 @@ jobs:
+    # -- and nothing else. A missing `default_branch` makes `format(...)` yield
+    # `refs/heads/`, matching no real ref, so the guard fails CLOSED.
+    if: >-
+      startsWith(github.ref, 'refs/tags/sdk-v')
+      || github.event_name == 'release'
+      || github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
</file context>
Suggested change
startsWith(github.ref, 'refs/tags/sdk-v')
github.event_name == 'push' && startsWith(github.ref, 'refs/tags/sdk-v')

|| github.event_name == 'release'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The github.event_name == 'release' clause is dead code: release.yml's on: block only declares push: tags ['sdk-v*'] and workflow_dispatch (lines 47-62), and this file is not a reusable workflow (no workflow_call), so no run of this workflow can ever have event_name == 'release'. The guard comment and the PR description advertise 'a published release' as a supported path that cannot actually occur. This doesn't widen access (release events never start the workflow), but it misrepresents the fail-closed guarantee in the one job that mints a publishing credential. Drop the clause or add the missing release trigger to on: if that path is genuinely intended.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 311:

<comment>The `github.event_name == 'release'` clause is dead code: release.yml's `on:` block only declares `push: tags ['sdk-v*']` and `workflow_dispatch` (lines 47-62), and this file is not a reusable workflow (no `workflow_call`), so no run of this workflow can ever have `event_name == 'release'`. The guard comment and the PR description advertise 'a published release' as a supported path that cannot actually occur. This doesn't widen access (release events never start the workflow), but it misrepresents the fail-closed guarantee in the one job that mints a publishing credential. Drop the clause or add the missing `release` trigger to `on:` if that path is genuinely intended.</comment>

<file context>
@@ -296,8 +296,33 @@ jobs:
+    # `refs/heads/`, matching no real ref, so the guard fails CLOSED.
+    if: >-
+      startsWith(github.ref, 'refs/tags/sdk-v')
+      || github.event_name == 'release'
+      || github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
     runs-on: ubuntu-latest
</file context>

|| github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
runs-on: ubuntu-latest
timeout-minutes: 15
# Named environment on the publish job ONLY. It anchors two things this
# workflow cannot grant itself: the `environment:npm` claim the
# registry-side trusted publisher is pinned to, and an environment
# protection rule (required reviewer + tag-only deployment policy) gating
# the mint. Configuring that environment is an operator act, not this file.
environment:
name: npm

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: With the documented tag-only npm environment policy, a default-branch backfill never reaches this job because its deployment ref is the branch, not the sdk-v... input. Allow the default branch in that environment policy or use a tag-ref backfill path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 321:

<comment>With the documented tag-only `npm` environment policy, a default-branch backfill never reaches this job because its deployment ref is the branch, not the `sdk-v...` input. Allow the default branch in that environment policy or use a tag-ref backfill path.</comment>

<file context>
@@ -296,8 +296,33 @@ jobs:
+    # protection rule (required reviewer + tag-only deployment policy) gating
+    # the mint. Configuring that environment is an operator act, not this file.
+    environment:
+      name: npm
+      url: https://www.npmjs.com/package/@wave-av/sdk
+    # `id-token: write` lives here and NOWHERE else; the workflow-level default
</file context>

url: https://www.npmjs.com/package/@wave-av/sdk
# `id-token: write` lives here and NOWHERE else; the workflow-level default
# stays `contents: read`. Do not hoist this to the workflow level -- the
# sbom job deliberately holds `contents: write` and never the mint.
permissions:
id-token: write # mint the OIDC token npm exchanges for a publish credential
contents: read
Expand Down
Loading