Skip to content

Add runtime-driven canary and unstable SDK publishing - #2544

Merged
MackinnonBuck merged 33 commits into
mainfrom
mackinnonbuck-sdk-unstable-publishing
Sep 16, 2026
Merged

MackinnonBuck merged 33 commits into
mainfrom
mackinnonbuck-sdk-unstable-publishing

Conversation

@MackinnonBuck

@MackinnonBuck MackinnonBuck commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

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

  • Make publish.yml the sole production release workflow and remove the separate sdk-canary.yml production workflow.
  • Preserve existing stable/prerelease behavior across Node, .NET, Rust, Python, Java, Go, and GitHub Releases.
  • Use one dispatch surface:
    • dist-tag: latest, prerelease, unstable, or canary
    • version: optional direct SDK version/base
    • mode: publish or dry-run
    • test-policy: runtime E2E handling with required, advisory, or skipped
    • runtime: optional automation JSON with exactly {version,sha,run_id}
  • Keep normal SDK publishing simple: direct latest/prerelease/unstable releases leave runtime empty and use the default required test policy. Direct canary is rejected because canary requires exact runtime provenance.
  • Keep latest/prerelease publish-only. Canary and unstable support dry-run; dry-run performs acquisition, testing when selected, packaging, and verification without registry, tag, or release mutations.
  • Parse and validate runtime JSON and test policy once, then pass validated values through job outputs.
  • Keep required E2E failures blocking, let advisory tolerate only the actual Ubuntu/macOS/Windows test-command failure with explicit warnings, and let skipped bypass the matrix without bypassing acquisition, packaging, manifest, or publication gates.
  • Test runtime-backed releases with both the default and in-process transports on Ubuntu, macOS, and Windows.
  • Record the selected test policy in the retained release manifest.
  • Keep exact runtime acquisition, nine-package verification, retries, idempotent publication, and dry-run mutation suppression.
  • Keep direct unstable public npm → Azure ordering and runtime unstable Azure verification → public npm ordering. Canary remains Azure-only.

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>-unstable and 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:

  1. Pause the runtime repository's scheduled canary automation and drain any in-flight runtime-canary repository dispatches.
  2. Merge this SDK receiver change, then immediately merge the runtime sender change that dispatches publish.yml through workflow_dispatch.
  3. Run one runtime-backed canary dry-run and confirm the returned SDK workflow run completes successfully.
  4. Resume scheduled runtime canary publication.

The old schedule must remain paused throughout the interval in which the SDK repository no longer accepts runtime-canary repository dispatches.

@MackinnonBuck
MackinnonBuck requested a review from a team as a code owner September 4, 2026 21:09
Copilot AI balanced review requested due to automatic review settings September 4, 2026 21:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 High severity · 4 Medium severity

New issues introduced by this change (5)
Severity Finding
High severity nodejs/​scripts/​runtime-package-acquisition.ts — Missing or misspelled required flags are silently converted to empty strings. In particular,…
Medium severity .github/​workflows/​publish.ymlruntime_run_id is only checked for numeric syntax and then copied into the release manifest;…
Medium severity .github/​workflows/​publish.yml — This substring match can select and test a different runtime version whose output merely contains…
Medium severity .github/​workflows/​sdk-canary.yml — This is a substring check, so a different runtime version can pass (for example, expected 1.0.8
Medium severity .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.83 can satisfy an expected 1.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.8 versus 1.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.

Comment thread nodejs/scripts/runtime-package-acquisition.ts Outdated
Comment thread .github/workflows/publish.yml Outdated
Comment thread .github/workflows/publish.yml Outdated
Comment thread .github/workflows/sdk-canary.yml Outdated
Comment thread .github/workflows/sdk-canary.yml Outdated
@MackinnonBuck MackinnonBuck changed the title Add gated unstable SDK publishing Add runtime-driven canary and unstable SDK publishing Sep 4, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Comment thread nodejs/scripts/runtime-dispatch-ledger.ts Fixed
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

SDK Consistency Review

I reviewed PR #2544 against the authoritative file list (pull_request_read get_files/get_diff).

Scope of changes: All modifications are confined to Node.js release/publishing infrastructure and CI:

  • .github/workflows/publish.yml, .github/workflows/sdk-canary.yml (removed)
  • docs/developer-docs/secrets.md, docs/developer-docs/unstable-releases.md
  • nodejs/README.md, nodejs/package.json
  • nodejs/scripts/* (npm-release.js, package-set-manifest.js, release-manifest.ts, releaseArtifacts.ts, runtime-package-acquisition.ts, runtime-release-identity.ts, set-cli-version.js, unstable-version.ts)
  • nodejs/test/* (corresponding test files)

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. ✅

Generated by SDK Consistency Review Agent for #2544 · copilot · sonnet50 · 15.3 AIC · ⌖ 12.2 AIC · ⊞ 8.3K ·

Comment thread .github/workflows/publish.yml

@roji roji left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.

Comment thread nodejs/scripts/unstable-version.ts Outdated
Comment thread .github/workflows/publish.yml
Comment thread nodejs/test/release-workflows.test.ts Outdated
Comment thread .github/workflows/publish.yml Outdated
Comment thread .github/workflows/publish.yml Outdated
Comment thread .github/workflows/sdk-canary.yml
Mackinnon Buck and others added 5 commits September 15, 2026 09:37
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
Mackinnon Buck and others added 10 commits September 15, 2026 09:38
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
@MackinnonBuck
MackinnonBuck force-pushed the mackinnonbuck-sdk-unstable-publishing branch from 85b7d7a to 014debf Compare September 15, 2026 16:49
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d81fc7cf-d30a-470e-b7bf-42a02f62841d
@MackinnonBuck
MackinnonBuck added this pull request to the merge queue Sep 15, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 16, 2026
@MackinnonBuck
MackinnonBuck added this pull request to the merge queue Sep 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 16, 2026
@MackinnonBuck
MackinnonBuck added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit b47310c Sep 16, 2026
211 of 215 checks passed
@MackinnonBuck
MackinnonBuck deleted the mackinnonbuck-sdk-unstable-publishing branch September 16, 2026 01:48
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.

6 participants