ci: add release.yml for npm publish on v* tags; fix author field - #44
Conversation
P1 root cause (2026-09-03): published 1.0.8 crashed on every fresh install (ReferenceError "module is not defined in ES module scope" in the sdk chunk) because package.json pinned sdk with a caret range (^2.0.11) that later resolved to a broken sdk release (2.1.2). 1.0.9 (already merged, PR #39) pins sdk to an exact 2.0.14 — but nothing published it, because this repo had no release workflow, only _checks/foundation-gate/ issue-ops-triage/public-repo-guard. A laptop npm publish was the only path to npmjs, with no build/test/smoke gate in front of it. Adds .github/workflows/release.yml: triggered on v* tags, verifies the tag matches package.json version, npm ci, build, test, npm pack, smokes the packed tarball in a throwaway project (npm i tarball && npx wave --version, compared against package.json version) — the exact check 1.0.8 shipped without — then npm publish --provenance --access public. Auth is npm trusted publishing (OIDC via id-token: write) when this repo + workflow is registered as a trusted publisher on npmjs; falls back to the NPM_TOKEN repo secret otherwise (set only if the secret is present). All actions are SHA-pinned, matching this repo and wave-foundations release-spoke-chassis.yml convention. Also fixes package.json author from "WAVE Inc. <sdk@wave.online>" to the correct legal entity "WAVE Online, LLC". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9mRh8G2ugbUt2kaXvFvF6
|
Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI. |
|
ⓘ Qodo reviews are paused because your workspace is out of credits. Ask your workspace admin to add credits to resume reviews. Manage billing |
|
Warning Review limit reachedNext included review available in 37 minutes. View limit detailsLimit details: You’ve used the included review currently available. Your 91 included PR review attempts over the past 7 days set your current allowance at 1 review per hour. Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: 📒 Files selected for processing (2)
Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_0a537e1d-59b7-4b92-b359-8b4c97dce277) |
There was a problem hiding this comment.
Sorry @yakimoto, this account has used its review budget of 2,500,000 diff characters for the last 7 days.
You can request another review in 22 hours and 38 minutes by commenting @sourcery-ai review.
Reviewer's GuideIntroduces a guarded, tag-based GitHub Actions release workflow for publishing the tested npm tarball with OIDC or token authentication, and corrects the package author metadata. Review the release gates, tag/version validation, tarball smoke test, npm authentication setup, and one-time trusted-publisher configuration; build and tests passed locally, while type-check and lint remain known pre-existing or unresolved issues outside this PR. Sequence diagram for the guarded npm release workflowsequenceDiagram
participant Maintainer
participant GitHubActions
participant NpmRegistry
participant FreshProject
Maintainer->>GitHubActions: Push v<version> tag
GitHubActions->>GitHubActions: Verify tag matches package.json version
GitHubActions->>GitHubActions: npm ci --include=dev
GitHubActions->>GitHubActions: npm run build
GitHubActions->>GitHubActions: npm test
GitHubActions->>GitHubActions: npm pack
GitHubActions->>FreshProject: npm i packed tarball
FreshProject-->>GitHubActions: npx wave --version
alt smoke version matches package.json
GitHubActions->>NpmRegistry: npm publish --provenance --access public
else tag, build, test, or smoke check fails
GitHubActions-->>Maintainer: Fail without publishing
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — The PR adds a tag-triggered workflow that publishes the CLI to public npm and introduces OIDC/NPM_TOKEN authentication, materially changing the production release path. The package author correction is metadata-only, but the deployment and credential scope warrants human review. Not approved because:
Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more. |
|
Running ultrareview automatically — This PR adds the CI/CD release pipeline that publishes the CLI to public npm with OIDC/token auth; a bug in tag/version verification, the tarball smoke test, or the publish step could ship a broken or wrong-version package, so it warrants a deeper multi-pass review.. I'll post findings when complete. |
| fi | ||
|
|
||
| - name: Publish to npm | ||
| run: npm publish --provenance --access public |
There was a problem hiding this comment.
⚠️ Bug: npm publish --provenance conflicts with publishConfig.provenance:false
package.json has "publishConfig": { "provenance": false, ... } (package.json:54), but release.yml's final step runs npm publish --provenance --access public (.github/workflows/release.yml:102). The explicit CLI flag overrides publishConfig, so provenance attestation will be generated even though the package config says it shouldn't be — the opposite of what's declared in package.json, and it may also fail if the repo/workflow isn't OIDC-eligible for provenance (e.g. when only the NPM_TOKEN fallback path is active, --provenance requires id-token: write and a Sigstore-compatible CI, which is satisfied here, but the mismatch with publishConfig is still an inconsistency worth resolving so future edits to one don't silently diverge from the other).
Align publishConfig with the workflow's intent — remove the false override so provenance is enabled consistently, or drop --provenance from the workflow if provenance is intentionally disabled.:
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}
Was this helpful? React with 👍 / 👎
| - name: Configure npm auth (NPM_TOKEN fallback only — OIDC trusted publishing needs no config here) | ||
| env: | ||
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
| run: | | ||
| if [ -n "$NPM_TOKEN" ]; then | ||
| echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> ~/.npmrc | ||
| echo "npm auth: using NPM_TOKEN secret fallback" | ||
| else | ||
| echo "npm auth: no NPM_TOKEN secret set — relying on OIDC trusted publishing" | ||
| fi |
There was a problem hiding this comment.
💡 Quality: NPM_TOKEN fallback step is dead weight once OIDC works, but harmless if left misconfigured
The 'Configure npm auth' step (.github/workflows/release.yml:90-99) only writes the token when NPM_TOKEN is non-empty, which correctly avoids the known npm CLI issue where a stray/invalid _authToken line in .npmrc blocks OIDC trusted publishing from being attempted at all. This is safe as written, but worth a one-line comment noting that the NPM_TOKEN secret should be deleted from the repo once trusted publishing is confirmed working, so the fallback path can't accidentally become the active auth method (e.g. after an unrelated token rotation) and mask a broken OIDC registration.
Was this helpful? React with 👍 / 👎
|
Note Automatic reviews are paused because your team has used its included automatic processing for this billing period (headroom scales with your seat count). You can still comment "Gitar review" to run one anytime, and automatic reviews resume on their own by October 1. Add seats for more headroom. Code Review
|
| Compact |
|
Was this helpful? React with 👍 / 👎 | Gitar
|
cubic can't run this ultrareview because your workspace has reached its monthly review limit. cubic has reviewed 100,145 of the 100,000 allowed lines of code this month. Reviews resume on 4 September 2026 (in 2 days). Enable flex capacity to cover overages automatically and resume reviews now. Learn how flex capacity works. To help optimise your usage, you can tune cubic to get the most out of your usage limits:
|
….yml Resolves the add/add conflict on .github/workflows/release.yml. `main` grew its own release.yml in PR #44 after this branch was opened, so two release workflows collided. This merge keeps EVERY gate from both sides (27 asserted, ledger in the PR body) and fixes one gate that could never have passed. Union structure: PR #17's 3-job gate chain (secret-scan -> verify -> publish), with main's contributions folded in: - main's `npm ci --include=dev`, unconditional `npm test`, and its packed- tarball smoke that actually RUNS the installed binary - main's NPM_TOKEN classic-auth fallback (kept: without it a tag pushed before the npmjs Trusted Publisher registration exists fails with no recourse; --provenance still signs on that path since the job holds id-token: write) - action pins take the newer of the two sides, never a downgrade: checkout v6.0.3 (this branch's), setup-node v7.0.0 (main's) Two real defects fixed, not papered over: 1. The ESM smoke could never pass. package.json sets "main" and "bin.wave" to the SAME file (./dist/index.js), so `import * as m from '@wave-av/cli'` does not import a library — it EXECUTES the CLI, which with no argv prints help and exits 1. Measured against a correctly built 1.0.9: exit 1. Replaced the import-and-count-exports assertion with import.meta.resolve (proves the entry resolves, without executing) plus the bin run below (proves the whole ESM graph loads — the "module is not defined in ES module scope" class of break that took 1.0.8 down). Strictly stronger than what it replaced. 2. Neither side asserted the BANNER version. @wave-av/cli@1.0.8 shipped to npm printing "v1.0.0" from a hardcoded string while package.json said 1.0.8, and the banner is a separate code path from --version (src/cli.ts printBanner(), suppressed in CI/agent mode). PR #17 only checked the bin file existed; that would have shipped the bug again. verify/e2e-smoke now asserts three-way parity: package.json == `wave --version` == the version the banner prints, clearing the CI/agent env vars so the banner actually renders. Also made lint and type-check unconditional. They were conditional because main carried no package.json when this branch was written; main declares both scripts now, and a gate that downgrades itself to a ::warning when a script goes missing is a gate that can be deleted by accident. NOTE: both currently FAIL on origin/main for pre-existing reasons unrelated to this file (missing src/types/index.ts; eslint referenced by the lint script but absent from devDependencies with no eslint config). Those are source defects for the source lane — reported in the PR body, deliberately not worked around here. Verified locally in an isolated worktree: actionlint clean, all `uses:` pinned to 40-char SHAs, id-token: write present on the publish job, `npm test` 11/11 green, full pack+install+run e2e-smoke green with banner parity, and a negative control that re-injects the 1.0.8 defect and confirms the new gate rejects it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LIVE RECEIPTS
Defect (2026-09-03, code yellow P1):
npx @wave-av/cli --versionon a fresh install crashes on node 20 and node 22 withReferenceError: module is not defined in ES module scopeinside the sdk'schunk-VYLVDBON.mjs:73. Root cause:package.jsonpinned@wave-av/sdkwith a caret range (^2.0.11), which npm resolved to sdk2.1.2— a later sdk release that ships a broken (CJS-in-ESM-context) chunk.npm view @wave-av/sdk version --@wave-av:registry=https://registry.npmjs.orgconfirms latest is2.1.2;npm view @wave-av/cli versionsconfirms the last published cli version is1.0.8.Fix already merged, never published:
1.0.9(PR #39,origin/mainat3a3db2c) pins@wave-av/sdkto an exact2.0.14(no caret) inpackage.json. It sat unpublished because this repo has no release workflow — only_checks.yml,foundation-gate.yml,issue-ops-triage.yml,public-repo-guard.yml. The only path to npmjs was a manualnpm publishfrom a laptop, with zero build/test/smoke gate in front of it. That gap is what let1.0.8ship broken in the first place.Verified locally in an isolated worktree (
/tmp/cli-release,git worktree add ... origin/main,npm ci --include=dev):npm run build→ tsup ESM build succeeds (158.82 KB).npm test→ vitest: 4 test files, 11 tests, all passed.npm pack→wave-av-cli-1.0.9.tgz(96.8 kB, 30 files).npm i ./wave-av-cli-1.0.9.tgz --@wave-av:registry=https://registry.npmjs.org && npx wave --version) → both print1.0.9, and the installednode_modules/@wave-av/sdk/package.jsonresolves to2.0.14(not the broken2.1.2).Note for the reviewer:
npm run type-checkon this same tree surfaces ~35 pre-existingtscerrors (signage/slides/stream/studio/transcribe/usb/vault/voice/zoom commands referencing SDK methods that don't exist on the current SDK types, plus 3 missingtypes/index.jsmodule errors). These are pre-existing onorigin/main— not introduced by this PR, and not blockingtsup's transpile-only build — but they meannpm run type-checkis not wired into any gate today and should probably become one in a follow-up.npm run lintfails locally witheslint: command not found(eslint isn't resolving from--include=devinstall); not investigated further since it's out of scope for this PR.WHAT CHANGED
.github/workflows/release.yml(new). Triggered onv*tags. Steps: checkout (SHA-pinned) →actions/setup-nodenode 22 (SHA-pinned) → verify the tag version matchespackage.jsonversion (fails closed on mismatch) →npm ci --include=dev→npm run build→npm test→npm pack→ smoke-test the packed tarball in a throwaway project (npm i <tarball> && npx wave --version, compared againstpackage.jsonversion) — this is the exact check1.0.8shipped without — thennpm publish --provenance --access public. Auth: npm trusted publishing (OIDC viaid-token: write) once this repo+workflow is registered as a trusted publisher on npmjs; falls back to theNPM_TOKENrepository secret otherwise (only written to the npm config if the secret is non-empty). Modeled onwave-foundation'srelease-spoke-chassis.yml(tag-triggered, verify+publish shape, SHA-pinned actions), adapted for a public npm target instead of GitHub Packages.package.json:authorcorrected from"WAVE Inc. <sdk@wave.online>"to the correct legal entity"WAVE Online, LLC".OPERATOR STEPS (to activate publishing)
wave-av/cli+.github/workflows/release.ymlas a trusted publisher for@wave-av/cliin the npmjs package settings (Publishing access → Trusted Publisher → GitHub Actions), OR set theNPM_TOKENrepository secret (Settings → Secrets and variables → Actions) as the fallback path. Either is sufficient; no workflow changes needed either way.git tag v1.0.9 3a3db2c && git push origin v1.0.9(or the currentmaintip at release time).autonomy:auto-mergelabel — review and merge manually.GATES
npm run build— OK (tsup ESM build, 158.82 KB)npm test— OK (vitest: 4 files / 11 tests passed)npm run type-check— pre-existing FAIL (~35 errors, all pre-existing onorigin/main, unrelated to this change)npm run lint— FAIL locally (eslint: command not found), not investigated, out of scope🤖 Generated with Claude Code
https://claude.ai/code/session_01K9mRh8G2ugbUt2kaXvFvF6
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Note
Cursor Bugbot is generating a summary for commit 364c726. Configure here.
Summary by Sourcery
Automate gated, version-validated npm publishing for tagged CLI releases and correct the package metadata.
New Features:
Bug Fixes:
Enhancements:
CI:
Deployment:
Tests: