Skip to content

ci(publish): bypass main ruleset via deploy key for version-bump push - #85

Merged
bergetbjork merged 1 commit into
mainfrom
fix/publish-deploy-key
Sep 7, 2026
Merged

bergetbjork merged 1 commit into
mainfrom
fix/publish-deploy-key

Conversation

@bergetbjork

Copy link
Copy Markdown
Contributor

Publish workflow failed with GH013 (ruleset requires PRs for GITHUB_TOKEN pushes to main) — the bot could never push the npm version bump, so npm publish never ran and npm stayed at 2.2.21.

Copies the proven pattern from api/console/chat release.yml: checkout with the repo Deploy Key (DEPLOY_KEY SSH secret, added to this repo along with its read-write deploy key) so the version-bump push bypasses the ruleset.

The publish workflow died at 'git push --follow-tags' with GH013: the
repo ruleset requires PRs for GITHUB_TOKEN pushes to main, so the bot
could never push the npm version bump and 'npm publish' never ran
(npm frozen at 2.2.21 despite green releases).

Same fix as api/console/chat release.yml: check out with the repo
Deploy Key (SSH secret DEPLOY_KEY), which bypasses the ruleset for the
version-bump push. Key added as read-write deploy key + DEPLOY_KEY
secret on this repo.
@bergetbjork
bergetbjork merged commit 6a39939 into main Sep 7, 2026
2 checks passed
@bergetbjork
bergetbjork deleted the fix/publish-deploy-key branch September 7, 2026 14:58
with:
fetch-depth: 0
ref: main
ssh-key: ${{ secrets.DEPLOY_KEY }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 warning — Deliberate ruleset bypass via a write deploy key makes DEPLOY_KEY a standing direct-push credential for anyone who can dispatch this workflow; keep it repo-scoped/rotated or use a GitHub App as an explicit bypass actor.

needs: test
runs-on: ubuntu-latest
permissions:
contents: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 nit — contents: write is unneeded — the push uses the SSH deploy key and npm publish uses NPM_TOKEN; contents: read suffices.

uses: actions/checkout@v4
with:
fetch-depth: 0
ref: main

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 nit — publish always checks out main while test runs on the dispatch ref, so dispatching from a branch publishes main code that was never tested.

test:
runs-on: ubuntu-latest
permissions:
contents: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

good — Scoped permissions on the test job follow least privilege.

@berget-ai

berget-ai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Review

Summary

This PR makes the publish workflow able to actually push its version-bump commit to main under the repo ruleset by checking out with the DEPLOY_KEY SSH secret (deploy-key pushes bypass the PR-required ruleset), and adds explicit least-privilege permissions blocks to both jobs.

Risk

MEDIUM — the change intentionally introduces a standing write credential (a write-capable SSH deploy key) that bypasses the main-branch ruleset for anyone who can dispatch this workflow, and publishes to NPM from it.

Issues

  • warning .github/workflows/publish.yml:53 — Checking out with a repo deploy key to bypass the ruleset is deliberate (matches the org pattern in the comment), but secrets.DEPLOY_KEY is now a permanent direct-push-to-main credential exposed to every job in this workflow; confirm it is a dedicated repo-scoped deploy key (not an org-wide/account key) and consider rotating it on a schedule, or register a dedicated GitHub App as an explicit ruleset bypass actor so bypass pushes remain auditable.
  • warning .github/workflows/publish.yml:72npm version ${{ inputs.bump }} interpolates user input straight into the shell; choice options are only enforced in the UI, not when the workflow is dispatched via the REST API, so arbitrary strings reach the runner (which holds the deploy key and NPM_TOKEN). Pass it through an env var and whitelist:
    - name: Bump version
      env:
        BUMP: ${{ inputs.bump }}
      run: |
        case "$BUMP" in
          patch|minor|major) npm version "$BUMP" -m "release: %s" && git push --follow-tags ;;
          *) echo "invalid bump type: $BUMP"; exit 1 ;;
        esac
  • nit .github/workflows/publish.yml:43contents: write is now unnecessary: the push goes over the SSH remote (deploy key) and npm publish uses NPM_TOKEN; contents: read for the publish job is sufficient and shrinks blast radius if the runner is compromised.
  • nit .github/workflows/publish.yml:3 — No concurrency group: two simultaneous dispatches both branch from the same main HEAD and race the push (one gets a non-fast-forward rejection / npm publish 409 for a duplicate version). Add concurrency: { group: publish-${{ github.workflow }}, cancel-in-progress: false }.
  • nit .github/workflows/publish.yml:52publish always checks out ref: main while test checks out the dispatch ref; dispatching from a non-main branch publishes main code that was never exercised by the test job.
  • .github/workflows/publish.yml:19 — Scoped permissions: contents: read on the test job follows least privilege.

Suggestions

  • .github/workflows/publish.yml — After this lands, document the release admission path (who may dispatch, deploy-key ownership/rotation) in CONTRIBUTING.md, since it now bypasses branch review.
  • Verified OK: package.json is unscoped/public with publishConfig.access: public, and test:run/build scripts referenced by the workflow all exist; --follow-tags works because npm version creates annotated tags.

Architecture

No structural change — this is a CI-release plumbing fix aligning this repo's publish workflow with the deploy-key pattern used by the api/console/chat release workflows.

Code quality: 8/10 — small, well-commented change consistent with established org patterns; deducted for direct input interpolation and unnecessary write scope.

Inline findings


Berget AI (berget/zai-org/GLM-5.3-Flash) | PR #85

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