Skip to content

Latest commit

 

History

History
185 lines (157 loc) · 10.4 KB

File metadata and controls

185 lines (157 loc) · 10.4 KB

Releasing AHP

This document covers the mechanics of cutting a release of any shippable artifact in this repo. For the protocol-level versioning policy (SemVer rules for the spec itself, the supported-version window, etc.) see docs/specification/versioning.md.

Release model

Every shippable artifact in this repo is versioned independently using its ecosystem's native SemVer. The protocol specification is a fifth artifact with its own release cadence. Each client release advertises which protocol versions it supports via a generated SUPPORTED_PROTOCOL_VERSIONS constant and a checked-in clients/<lang>/release-metadata.json.

Tag conventions

Artifact Tag pattern Workflow Registry / discovery
Spec spec/vX.Y.Z .github/workflows/publish-spec.yml GitHub Release with schema assets.
Rust rust/vX.Y.Z .github/workflows/publish-rust.yml crates.io (ahp-types, ahp, ahp-ws).
Kotlin kotlin/vX.Y.Z clients/kotlin/pipeline.yml (Azure DevOps) Maven Central (com.microsoft.agenthostprotocol:agent-host-protocol) via ESRP.
TypeScript typescript/vX.Y.Z clients/typescript/pipeline.yml (Azure DevOps) npm (@microsoft/agent-host-protocol) via ESRP.
Swift vX.Y.Z (bare) .github/workflows/publish-swift.yml SwiftPM resolves the tag directly.
Go clients/go/vX.Y.Z .github/workflows/publish-go.yml Go module proxy resolves the tag directly.

Why Swift gets the bare semver tag namespace: SwiftPM only resolves packages by matching plain X.Y.Z / vX.Y.Z git tags at the manifest's repo root. Path-prefixed tags like swift/v0.2.0 are invisible to it. Bare semver tags at this repo's root are therefore reserved for Swift releases.

Why Go uses the clients/go/ prefix: Go's module-version resolution for sub-module paths requires the tag prefix to match the module's directory inside the repo (see go help mod › Module versions). Without the prefix, go get github.com/microsoft/agent-host-protocol/clients/go@vX.Y.Z would fail to find a matching tag.

Why TypeScript and Kotlin publish from Azure DevOps: the npm registry publish for @microsoft/agent-host-protocol and the Maven Central publish for com.microsoft.agenthostprotocol:agent-host-protocol both go through Microsoft's ESRP-backed vscode-engineering pipeline templates (1ES-hosted agents, signed publish, retention policy) — that machinery lives in Azure DevOps. GitHub Actions cannot trigger an ADO pipeline in this repo (PATs are not permitted), so the ADO pipelines own the typescript/vX.Y.Z and kotlin/vX.Y.Z tag triggers directly and run the same validation steps (tag ↔ manifest match, CHANGELOG entry, release metadata, generated-source freshness, full client build

  • tests) before handing off to ESRP. Each pipeline can also be triggered manually from the ADO UI as a hotfix escape hatch.

Per-client release flow

Rust (rust/vX.Y.Z)

  1. Bump [workspace.package].version in clients/rust/Cargo.toml (this bumps all three crates — ahp-types, ahp, ahp-ws — together; the workspace is intentionally version-locked).
  2. Update cross-crate version = "0.X.Y" pins in [workspace.dependencies] and any per-crate dependency declarations.
  3. Run npm run generate:metadata and commit the regenerated clients/rust/release-metadata.json.
  4. Rotate clients/rust/CHANGELOG.md: move the ## [Unreleased] section to ## [X.Y.Z] — YYYY-MM-DD with an Implements AHP <version> line.
  5. Merge to main.
  6. Tag: git tag rust/v0.X.Y && git push origin rust/v0.X.Y.
  7. publish-rust.yml validates, then publishes ahp-types, ahp, and ahp-ws to crates.io in dependency order.

Kotlin (kotlin/vX.Y.Z)

  1. Bump VERSION_NAME in clients/kotlin/gradle.properties. Drop any -SNAPSHOT suffix (the publish workflow rejects snapshot tags).
  2. Run npm run generate:metadata and commit the regenerated clients/kotlin/release-metadata.json.
  3. Rotate clients/kotlin/CHANGELOG.md.
  4. Merge to main.
  5. Tag: git tag kotlin/v0.X.Y && git push origin kotlin/v0.X.Y.
  6. clients/kotlin/pipeline.yml (Azure DevOps) validates the tag, re-runs the generator + Gradle check, stages a Maven repository layout under clients/kotlin/build/maven-staging/, and hands it to ESRP (contenttype: maven). ESRP signs the artifacts and releases them to Maven Central via the Sonatype Central Portal. No manual Sonatype UI interaction is required.
  7. Bump VERSION_NAME back to the next -SNAPSHOT for ongoing development.

TypeScript (typescript/vX.Y.Z)

The TypeScript client publishes from an Azure DevOps pipeline (clients/typescript/pipeline.yml) that extends Microsoft's internal vscode-engineering npm-package template. ADO owns the tag trigger directly — there is no GitHub Actions bridge — because this repo cannot use PATs to trigger ADO from GHA.

  1. Bump version in clients/typescript/package.json.
  2. cd clients/typescript && npm install to refresh the lockfile.
  3. Run npm run generate:metadata from the repo root and commit the regenerated clients/typescript/release-metadata.json.
  4. Rotate clients/typescript/CHANGELOG.md: move ## [Unreleased] to ## [X.Y.Z] — YYYY-MM-DD with an Implements AHP <version> line.
  5. Merge to main.
  6. Tag: git tag typescript/v0.X.Y && git push origin typescript/v0.X.Y.
  7. The ADO pipeline picks up the tag, validates it against package.json, runs verify:release-metadata, verify:changelog, and the regen + build + test sequence, then publishes @microsoft/agent-host-protocol to npm with signed provenance via the vscode-engineering template.

The ADO pipeline can also be triggered manually from the ADO UI as a hotfix escape hatch — manual runs publish too. Both paths funnel through the same validation steps in the pipeline's buildSteps so a release artifact can't ship from a broken state regardless of which trigger started the run.

Swift (vX.Y.Z, bare)

  1. Update clients/swift/VERSION to the new bare semver string (no leading v, no -SNAPSHOT).
  2. Run npm run generate:metadata and commit the regenerated clients/swift/release-metadata.json.
  3. Rotate clients/swift/CHANGELOG.md.
  4. Merge to main.
  5. Tag: git tag v0.X.Y && git push origin v0.X.Y. Note the absence of any prefix — this is the one place in the repo where bare semver tags are correct.
  6. publish-swift.yml validates the tag against clients/swift/VERSION, builds and tests the Swift package on macOS, and publishes a GitHub Release. SwiftPM consumers resolve the tag directly; no registry push happens.

Go (clients/go/vX.Y.Z)

  1. Update clients/go/VERSION to the new bare semver string (no leading v, no -SNAPSHOT).
  2. Run npm run generate:metadata and commit the regenerated clients/go/release-metadata.json.
  3. Rotate clients/go/CHANGELOG.md.
  4. Merge to main.
  5. Tag: git tag clients/go/v0.X.Y && git push origin clients/go/v0.X.Y. The clients/go/ prefix is required — it is what the Go module proxy expects for sub-module tag resolution. Bare semver tags are reserved for Swift.
  6. publish-go.yml validates the tag against clients/go/VERSION, builds + vets + tests the module, warms the Go module proxy with the new version, and creates a GitHub Release with the CHANGELOG section for the tag. Go consumers resolve the tag via go get github.com/microsoft/agent-host-protocol/clients/go@vX.Y.Z; no registry push happens.

Spec (spec/vX.Y.Z)

  1. Bump PROTOCOL_VERSION in types/version/registry.ts (and, if the release is also adding the version to the supported list, SUPPORTED_PROTOCOL_VERSIONS).
  2. Update ACTION_INTRODUCED_IN / NOTIFICATION_INTRODUCED_IN for any new symbols.
  3. Run npm run generate to refresh schemas, generated client sources, and metadata.
  4. Rotate the root CHANGELOG.md.
  5. Merge to main.
  6. Tag: git tag spec/v0.X.Y && git push origin spec/v0.X.Y.
  7. publish-spec.yml validates, regenerates the JSON schemas from the tagged commit, captures a registry-snapshot.json of the introduced-in maps, and creates a GitHub Release with all of the above as assets.

What CI guards against

Drift caught by How
Version.generated.{rs,kt,swift,go}types/version/registry.ts Per-language CI job re-runs npm run generate:<lang> and fails on diff.
release-metadata.json ↔ native manifest + registry npm run verify:release-metadata (also gated on every publish workflow).
Native package version ↔ matching CHANGELOG entry npm run verify:changelog (in CI, and re-run in publish-rust.yml / publish-swift.yml / publish-go.yml / both ADO pipeline.ymls).
Tag ↔ manifest version Every tag-driven publish workflow's "Verify tag matches" step.
Tag-derived version ↔ CHANGELOG entry Every tag-driven publish workflow's grep -qE '^## \[<tag-version>\]' step (defense-in-depth alongside verify:changelog).

Required infrastructure (one-time setup)

These environments and secrets are required for the publish workflows to function. They are set per-repo by a maintainer with admin access.

Environment / secret Used by Purpose
crates-io environment, CARGO_REGISTRY_TOKEN secret publish-rust.yml Authenticates cargo publish for ahp-types / ahp / ahp-ws.
Azure DevOps Service Connection to ESRP + Maven Central provisioning clients/kotlin/pipeline.yml (vscode-engineering maven-package template) ESRP signs and uploads the staged Maven layout to Maven Central via the Sonatype Central Portal. Provisioned inside the Microsoft ADO tenant; no GitHub secret required.
Azure DevOps Service Connection to ESRP + npm publish creds clients/typescript/pipeline.yml (vscode-engineering npm-package template) Authenticates npm publish for @microsoft/agent-host-protocol. Provisioned inside the Microsoft ADO tenant; no GitHub secret required.
(none required) publish-swift.yml, publish-spec.yml, publish-go.yml All three use the default GITHUB_TOKEN to create GitHub Releases. No external registry credentials needed — SwiftPM and the Go module proxy index tags directly.