Add runtime-driven canary and unstable SDK publishing - #2544
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Critical argument-validation and moderate provenance, version-comparison, and SemVer handling issues remain unresolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Balanced
Findings: 1
New issues introduced by this change (5)
| Severity | Finding |
|---|---|
nodejs/scripts/runtime-package-acquisition.ts — Missing or misspelled required flags are silently converted to empty strings. In particular,… |
|
.github/workflows/publish.yml — runtime_run_id is only checked for numeric syntax and then copied into the release manifest;… |
|
.github/workflows/publish.yml — This substring match can select and test a different runtime version whose output merely contains… |
|
.github/workflows/sdk-canary.yml — This is a substring check, so a different runtime version can pass (for example, expected 1.0.8… |
|
.github/workflows/sdk-canary.yml — SemVer permits build metadata. If the public latest is 1.2.3+build, this leaves PATCH=3+build;… |
What changed in this PR
Adds gated canary and unstable Node SDK publishing with deterministic versioning, runtime acquisition, integrity-aware manifests, and recovery support.
Changes:
- Adds runtime acquisition, versioning, manifest, and publishing helpers.
- Reworks canary and unstable workflows with cross-platform validation.
- Adds focused release tests and operator documentation.
| File | Description | Review |
|---|---|---|
nodejs/test/unstable-version.test.ts |
Tests deterministic unstable versions. | No unresolved comments. |
nodejs/test/runtimeArtifacts.test.ts |
Tests local runtime selection. | No unresolved comments. |
nodejs/test/runtime-package-acquisition.test.ts |
Tests runtime acquisition and validation. | No unresolved comments. |
nodejs/test/release-workflows.test.ts |
Tests workflow contracts. | No unresolved comments. |
nodejs/test/release-manifest.test.ts |
Tests manifest integrity. | No unresolved comments. |
nodejs/test/npm-release.test.ts |
Tests integrity-aware publishing. | No unresolved comments. |
nodejs/scripts/unstable-version.ts |
Calculates deterministic unstable versions. | No unresolved comments. |
nodejs/scripts/set-cli-version.js |
Adds local-package mode. | No unresolved comments. |
nodejs/scripts/runtime-package-acquisition.ts |
Acquires exact runtime packages. | Critical (1 vote): Reject unknown, duplicate, missing, and incomplete arguments before filesystem operations; a missing --output currently targets the working directory. |
nodejs/scripts/releaseArtifacts.ts |
Supports pre-acquired runtime roots. | No unresolved comments. |
nodejs/scripts/release-manifest.ts |
Creates and verifies release manifests. | No unresolved comments. |
nodejs/scripts/npm-release.js |
Publishes package sets with integrity checks. | No unresolved comments. |
nodejs/README.md |
Documents runtime package inputs. | No unresolved comments. |
nodejs/package.json |
Adds release helper commands. | No unresolved comments. |
docs/developer-docs/unstable-releases.md |
Adds the operator runbook. | No unresolved comments. |
docs/developer-docs/secrets.md |
Documents token permissions. | No unresolved comments. |
.github/workflows/sdk-canary.yml |
Reworks gated canary packaging. | Moderate (1 vote each): Strip SemVer build metadata before patch arithmetic; replace substring runtime-version checks at lines 217 and 360 with exact parsed comparisons. |
.github/workflows/publish.yml |
Adds gated unstable publishing. | Moderate (1 vote each): Validate runtime_run_id provenance against the source repository and runtime metadata; replace substring runtime-version checks at lines 535 and 686 with exact parsed comparisons. |
Suppressed comments (2)
.github/workflows/publish.yml:686
- This release gate checks only that the expected text occurs somewhere in the output, so a clean install with a different version such as
1.0.83can satisfy an expected1.0.8. Parse the runtime's reported version and require exact equality before allowing public publication.
"$RUNTIME" --version | grep -F "$RUNTIME_VERSION"
.github/workflows/sdk-canary.yml:360
- The clean-install gate uses a substring match, so it can accept the wrong embedded runtime when the requested version is a prefix of the actual one (for example,
1.0.8versus1.0.83). Parse the emitted version and require exact equality so this gate proves the package contains the selected runtime.
"$RUNTIME" --version | grep -F "$RUNTIME_VERSION"
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
03bace3 to
59bc2e1
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
SDK Consistency ReviewI reviewed PR #2544 against the authoritative file list ( Scope of changes: All modifications are confined to Node.js release/publishing infrastructure and CI:
Conclusion: No public client-facing SDK API code is touched in any language (Node/TS, Python, Go, .NET, Java, Rust). This PR is entirely about how the Node.js package is versioned, packaged, and published (unstable release tooling, CI publish workflow), not about SDK feature/API surface. There is nothing here that requires mirroring in Python, Go, .NET, Java, or Rust — these languages have their own independent release/publish tooling, and this change doesn't introduce any client API, method, or behavior that other SDKs would need to match. No cross-SDK consistency issues found. ✅
|
roji
left a comment
There was a problem hiding this comment.
LGTM, it's lots of new code (~2300 net new lines) - maybe see if there's opportunity to reduce, but otherwise looks good and see comments below.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Keep unstable versions monotonically ordered, test both runtime transports, reduce workflow test brittleness, and trim redundant release artifacts and verification. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
85b7d7a to
014debf
Compare
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d


Problem
Maintainers need branch-capable unstable Node SDK releases and runtime-driven canary/unstable releases. npm trusted publishing recognizes only
.github/workflows/publish.yml, so every production npm publication must execute directly in that workflow.Changes
publish.ymlthe sole production release workflow and remove the separatesdk-canary.ymlproduction workflow.dist-tag:latest,prerelease,unstable, orcanaryversion: optional direct SDK version/basemode:publishordry-runtest-policy: runtime E2E handling withrequired,advisory, orskippedruntime: optional automation JSON with exactly{version,sha,run_id}runtimeempty and use the defaultrequiredtest policy. Direct canary is rejected because canary requires exact runtime provenance.requiredE2E failures blocking, letadvisorytolerate only the actual Ubuntu/macOS/Windows test-command failure with explicit warnings, and letskippedbypass the matrix without bypassing acquisition, packaging, manifest, or publication gates.Versioning
Canary versions use:
X.Y.(Z+1)-canary.<workflow_run_number>.g<sdk_sha7>Generated unstable versions use:
<target_core>-unstable.<workflow_run_id>.g<sdk_sha7>Explicit direct unstable overrides must use
<core>-unstableand produce:<core>-unstable.<workflow_run_id>.g<sdk_sha7>This keeps explicit and generated releases in the same numeric-first SemVer ordering. The source runtime run ID is provenance only. Re-running the same SDK workflow run preserves its release identity; a new dispatch receives a new version.
Coordinated canary cutover
This PR must not merge until github/copilot-agent-runtime#20157 is ready for the coordinated sender/receiver cutover:
runtime-canaryrepository dispatches.publish.ymlthroughworkflow_dispatch.dry-runand confirm the returned SDK workflow run completes successfully.The old schedule must remain paused throughout the interval in which the SDK repository no longer accepts
runtime-canaryrepository dispatches.