Skip to content

ci(provenance): auto-create v<version> tag after socket publish#1322

Open
John-David Dalton (jdalton) wants to merge 1 commit into
v1.xfrom
feat/tag-after-publish-v1x
Open

ci(provenance): auto-create v<version> tag after socket publish#1322
John-David Dalton (jdalton) wants to merge 1 commit into
v1.xfrom
feat/tag-after-publish-v1x

Conversation

@jdalton
Copy link
Copy Markdown
Collaborator

@jdalton John-David Dalton (jdalton) commented May 20, 2026

Summary

  • Adds a Tag release (idempotent) step at the end of the v1.x publish workflow to auto-create v<version> git tags after a successful socket npm publish.
  • Idempotent: no-op if tag already exists at the published SHA; hard-fail if it exists at a different SHA (GitHub Release Immutability means moving it is unsafe).
  • Uses gh api (not git push) so the GITHUB_TOKEN only lives in the tag step's env block — never written to .git/config where pnpm install postinstall scripts could read it.
  • Gated on steps.publish_socket.outcome == 'success': the other two publishes (@socketsecurity/cli, cli-with-sentry) use continue-on-error: true and don't represent the v<version> tag.

Mirrors the patch landed on main (8043cf7) and socket-registry/provenance.yml. Inlined here rather than reusing socket-registry/.github/workflows/provenance.yml because v1.x is intentionally decoupled from the reusable workflow's evolution.

Test plan

  • actionlint passes (verified locally — only the pre-existing options: warning on the debug input, unrelated).
  • zizmor passes (verified locally — no findings).
  • Next v1.x publish that flips inputs.socket true creates a v<cli_version> tag pointing at the published SHA.
  • Re-running the workflow against the same published version no-ops (idempotency).

Why

socket-cli 1.1.98 and 1.1.99 were published from this branch with no git tags on origin — had to be hand-created on 2026-05-20 by reading npm view socket@<v> gitHead and git tag -s vX.Y.Z <sha>. Two published versions in a row with missing tags is a fleet-wide failure mode; the publish path needs to enforce tag creation, not rely on operator memory.


Note

Medium Risk
Moderate risk because it changes CI publish permissions and adds automated tag creation; mistakes could create/lock incorrect tags or fail the release pipeline under GitHub Release immutability.

Overview
After a successful socket npm publish, the provenance workflow now creates an idempotent v<version> git tag pointing at the published commit SHA (no-op if already correct; hard-fail if the tag exists at a different SHA).

To support this, the job permission contents is raised to write, and the first publish step is given an id (publish_socket) so the tag step can be gated on its success while the other publishes remain continue-on-error.

Reviewed by Cursor Bugbot for commit 7e12956. Configure here.

Adds a Tag release step at the end of the build job, idempotently
tagging the published commit SHA with v<version> after the `socket`
npm package publishes successfully. Gated on `steps.publish_socket.outcome
== 'success'` (the other two publishes — `@socketsecurity/cli`,
`cli-with-sentry` — don't drive the v<version> tag).

Hard-fails on SHA mismatch with an existing tag rather than silently
moving it — GitHub Release Immutability freezes tags bound to a Release,
so a wrong tag requires manual recovery.

Bumps job permissions to `contents: write` and the checkout's
`persist-credentials` to `true` so the tag can be pushed.

Why: socket-cli 1.1.98 and 1.1.99 were published from this branch with
no git tags on origin (had to be hand-created on 2026-05-20 from
npm view gitHead). Mirrors the same patch landed on main, adapted to
v1.x's single-job standalone workflow.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: 404 response body breaks tag existence check
    • Split the command substitution from the fallback ($(gh api ...) || EXISTING_JSON="") so that on a 404 the variable is explicitly overwritten to empty, preventing the non-empty check from passing with the error JSON body.

Create PR

Or push these changes by commenting:

@cursor push bad849d7f8
Preview (bad849d7f8)
diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml
--- a/.github/workflows/provenance.yml
+++ b/.github/workflows/provenance.yml
@@ -258,7 +258,7 @@
           TAG="v$PUBLISHED_VERSION"
 
           # Look up any existing tag via the API. 200 → exists; 404 → absent.
-          EXISTING_JSON=$(gh api "repos/$REPO/git/ref/tags/$TAG" 2>/dev/null || echo "")
+          EXISTING_JSON=$(gh api "repos/$REPO/git/ref/tags/$TAG" 2>/dev/null) || EXISTING_JSON=""
           if [ -n "$EXISTING_JSON" ]; then
             EXISTING_SHA=$(echo "$EXISTING_JSON" | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).object.sha")
             if [ "$EXISTING_SHA" = "$PUBLISHED_SHA" ]; then

You can send follow-ups to the cloud agent here.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7e12956. Configure here.


# Look up any existing tag via the API. 200 → exists; 404 → absent.
EXISTING_JSON=$(gh api "repos/$REPO/git/ref/tags/$TAG" 2>/dev/null || echo "")
if [ -n "$EXISTING_JSON" ]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

404 response body breaks tag existence check

High Severity

gh api outputs the 404 JSON response body ({"message":"Not Found",…}) to stdout even on failure. The 2>/dev/null only suppresses stderr, and in bash $(cmd1 || cmd2), stdout from the failed cmd1 is still captured. So when a tag does not exist, EXISTING_JSON contains the error JSON (non-empty), causing [ -n "$EXISTING_JSON" ] to be true. The subsequent node -p then tries to access .object.sha on the error object, which throws a TypeError and fails the step under set -e. Tags can never be created for new versions — the primary purpose of this change.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7e12956. Configure here.

EXISTING_JSON=$(gh api "repos/$REPO/git/ref/tags/$TAG" 2>/dev/null || echo "")
if [ -n "$EXISTING_JSON" ]; then
EXISTING_SHA=$(echo "$EXISTING_JSON" | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).object.sha")
if [ "$EXISTING_SHA" = "$PUBLISHED_SHA" ]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Annotated tags cause false SHA mismatch failure

Medium Severity

For annotated (signed) tags, the GitHub git/ref/tags API returns the tag object SHA in object.sha, not the commit SHA. Comparing this against PUBLISHED_SHA (a commit SHA from git rev-parse HEAD) will always mismatch, causing a hard-fail even when the tag points to the correct commit. The PR description notes that previous tags were hand-created with git tag -s (which creates annotated tags), so a re-run against those versions would incorrectly trigger the "requires manual recovery" error path.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7e12956. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant