This package (copilotkit-vscode-extension) ships to two registries:
- VS Code Marketplace — primary, used by VS Code, Cursor, etc.
- Open VSX — used by VSCodium, Gitpod, OpenVSCode Server, Theia-based IDEs.
The flow mirrors the CopilotKit/aimock release model for publish: a chore: release vX.Y.Z commit on main triggers CI, which self-gates on whether the version is already live and publishes if not. Unlike aimock, contributors don't hand-edit package.json — the VS Code Extension — Metadata Sync workflow (.github/workflows/vscode-extension-changelog-sync.yml) auto-syncs package.json.version (and optionally package.json.description) from the CHANGELOG entry (and optionally the README.md first paragraph) when the PR is opened, and commits chore: release vX.Y.Z on the PR branch for you. No tag is created by hand. No vsce publish is run by hand.
Cutting a release is one file edit, one commit, one PR.
-
Prepend an entry to
CHANGELOG.md:## 0.1.1 — 2026-04-22 ### Fixed - Hook Explorer crash on empty workspaces ### Added - New "Copy AG-UI run URL" command
Use Keep-a-Changelog subsections:
Added,Changed,Fixed,Removed,Deprecated,Security. The date is whatever date you commit.If you also want to change how the extension is described on the Marketplace / Open VSX listing page, edit the first paragraph under the
# CopilotKit for VS Codetitle inREADME.mdin the same PR. The metadata-sync workflow extracts that paragraph, strips inline markdown, and writes it topackage.json.description(the field both registries render as the one-liner). First paragraph must stay ≤200 chars — the workflow fails fast otherwise so you don't silently ship a truncated listing. -
Commit with any message (e.g.
docs: changelog for 0.1.1) and push. -
Open a PR.
-
Automation: the VS Code Extension — Metadata Sync workflow runs on your PR, reads the top version from CHANGELOG and the first paragraph of README.md, and bumps
package.json(.versionand/or.description) to match. If a version bump is needed it commitschore: release vX.Y.Z; otherwise, if only the description drifted it commitschore(vscode-extension): sync description from README. No action needed from you — just pull the updated branch if you keep working locally. -
Review, merge with a merge commit (NOT squash — the
chore: releasecommit needs to land onmainso the publish workflow's path filter fires).
On merge, CI auto-publishes to the VS Code Marketplace and Open VSX, tags vscode-extension-vX.Y.Z, cuts a GitHub Release, and posts to #oss-alerts.
If the sync workflow is down or you can't wait, bump package.json yourself in the same PR and use chore: release vX.Y.Z as your own commit subject. Everything downstream works the same.
On every push to main, .github/workflows/publish-vscode-extension.yml runs:
- Reads
versionfrompackage.json. - Calls
vsce show <publisher>.<name>and checks whether that exact version is already listed on the Marketplace. - If already published → no-op (green, zero side effects). This makes every non-release push to main safe.
- Otherwise: install, build,
vsce package→ singleextension.vsix, upload artifact. - Marketplace auth is GitHub OIDC → Entra federated Service Principal →
vsce publish --azure-credential. No user PAT. The SP iscopilotkit-vscode-publishin the copilotkit.ai tenant with Contributor role on the Marketplacecopilotkitpublisher.azure/login@v2sourcesAZURE_CLIENT_ID/AZURE_TENANT_ID/AZURE_SUBSCRIPTION_IDfrom theproductionenvironment variables (not secrets) and populates theAzureCliCredentialchain thatvscereads by default. Averify-pat --azure-credentialpre-flight step catches auth issues before we publish. - Publish the same
.vsixto Open VSX with$OVSX_PAT(bot-owned PAT, quarterly rotation — OIDC is not yet supported on Open VSX). - Create tag
vscode-extension-v<version>and push it. - Cut a GitHub Release using the CHANGELOG section for that version (or auto-generated notes if absent).
- Post a Slack message to
SLACK_WEBHOOKif configured.
The federated credential on the Entra SP is pinned to subject repo:CopilotKit/vscode-extension:environment:production, which means the workflow's environment: production must match exactly (case-sensitive) for the OIDC token exchange to succeed.
Both publishes use continue-on-error so a partial failure is visible. The final "Report publish results" step fails the job if either registry ultimately failed — you never land in "Marketplace succeeded, Open VSX silently skipped."
Both registries occasionally return transient 5xx errors during publish. In particular, Open VSX's /publish endpoint returns intermittent 502 Bad Gateway errors — a known Eclipse Foundation infra issue. VS Code Marketplace is more reliable but can also flake on 502/503/504.
The CI workflow handles this automatically:
- Each publish step retries up to 5 times with backoff (10s, 20s, 40s, 60s, 90s).
- Only transient conditions are retried:
5xx, timeouts, connection resets, DNS (EAI_AGAIN). Auth (401/403,TF400813, "Invalid access token") and validation (400/422, manifest errors) fail fast with no retry. - A
"version already exists"response is treated as idempotent success — this handles the case where attempt N-1 actually landed on the registry but its response never reached us (e.g.502after commit), and attempt N sees the version already there. - Each attempt is wrapped in
::group::/::endgroup::so the per-attempt logs are collapsible in the GH Actions UI.
If the workflow fails after all retries:
- Rerun the job from the GH Actions UI (Actions → failed run → Re-run failed jobs).
- Do NOT bump the version. The same tag + version is safe to re-publish because both registries treat "version already exists" as idempotent in our retry logic — whichever one previously succeeded will short-circuit, and the one that failed will get a fresh attempt.
For manual publishes (emergencies only — prefer CI):
- If
npx ovsx publish ...fails with a502, just retry the same command 2–3 times. - If
vsce publishfails with a5xx, same — retry. Auth errors (TF400813) mean the PAT is bad; don't retry, fix the token.
After CI goes green:
-
Marketplace: https://marketplace.visualstudio.com/items?itemName=copilotkit.copilotkit-vscode-extension
-
Open VSX: https://open-vsx.org/extension/copilotkit/copilotkit-vscode-extension
-
Smoke test install:
code --install-extension copilotkit.copilotkit-vscode-extension --force
(for VSCodium / Cursor, use their respective CLIs with the same extension ID.)
Both registries treat published versions as immutable. You cannot unpublish or replace a bad version — you can only publish a patch that supersedes it.
If a bad version ships:
- Fix the regression on a branch, open a PR, land it on
main. - Prepend a new
## X.Y.Z — <date>entry with a### Fixedsubsection toCHANGELOG.md(patch-bumping the version), open a PR, and merge. The metadata-sync workflow auto-commits the correspondingpackage.jsonbump aschore: release vX.Y.Zon the PR branch — same flow as a normal release. - If the regression is severe enough to warrant pulling the listing, the Marketplace / Open VSX admin UIs each offer a per-version unlist (different from unpublish) — use that as a last resort; prefer shipping forward.
If the Login to Azure or Verify Marketplace credential step fails on the first OIDC publish, check these in order:
- SP not added as Contributor on the Marketplace publisher.
copilotkit-vscode-publishmust be a member of thecopilotkitpublisher at https://marketplace.visualstudio.com/manage/publishers/copilotkit with the Contributor (or higher) role. - Federated credential subject mismatch. The credential on the Entra app must have subject exactly
repo:CopilotKit/vscode-extension:environment:production(case-sensitive, no trailing slash). The workflow'senvironment: productionmust match that subject byte-for-byte. - Tenant conditional access policy blocking workload identities. The copilotkit.ai tenant may have CA policies that block service principals from non-corporate IPs. Check Entra → Security → Conditional Access and exclude the
copilotkit-vscode-publishSP from any policy that filters on location. - Missing
permissions: id-token: writeon thepublishjob. Without this, GitHub will not mint an OIDC token andazure/login@v2will fail with "Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable".
VSCE_PAT is retained in the production environment secrets specifically as a rollback lever for this cutover window. To revert:
- Check out
.github/workflows/publish-vscode-extension.yml, replace--azure-credentialwith--pat "$VSCE_PAT", and re-add theenv: { VSCE_PAT: ${{ secrets.VSCE_PAT }} }block on thePublish to VS Code Marketplacestep. - Push. Ship the release. Debug OIDC out of band.
Once OIDC publishing has been confirmed green in CI at least once, delete VSCE_PAT from the production environment. That commit — the one that removes the last Marketplace PAT from the pipeline — is the actual completion of this migration. Until then the PAT is still a live credential and still needs to be treated as one for rotation / incident response purposes.
- ADO PAT retirement (2026-12-01): Azure DevOps is sunsetting long-lived Marketplace PATs. This workflow has been migrated to OIDC / federated credentials ahead of that date;
VSCE_PATis retained only as a short-lived rollback lever (see above). - If a release needs to pin to a specific
@copilotkit/*version, bump the dependency inpackage.jsonas part of the same PR that updates the CHANGELOG.
The following setup was completed during pipeline bootstrap (2026-04-21) and should not need to be redone. Documented here for disaster recovery / re-bootstrapping.
Configuration lives in the production GitHub environment (repo → Settings → Environments → production), split between non-secret variables and secrets:
Environment variables (non-secret, consumed by azure/login@v2):
AZURE_CLIENT_ID— client ID of thecopilotkit-vscode-publishEntra Service Principal.AZURE_TENANT_ID— tenant ID for copilotkit.ai.AZURE_SUBSCRIPTION_ID— subscription the SP is scoped into.
Environment secrets:
OVSX_PAT— Open VSX Personal Access Token (bot-owned, quarterly rotation). OIDC is not yet supported on Open VSX, so a PAT is still required here.VSCE_PAT— retained as explicit rollback only. No longer referenced by the workflow; Marketplace auth is OIDC. Delete this secret once OIDC publishing has been confirmed green at least once in production (see Rollback guidance).SLACK_WEBHOOK(optional) — webhook for the #oss-alerts release ping. Publish succeeds without it.
Open VSX requires claiming the namespace before the first publish:
-
Maintainer signs up at https://open-vsx.org with their GitHub identity.
-
Creates a personal access token at https://open-vsx.org/user-settings/tokens.
-
Claims the publisher namespace (one-time, from any machine):
npx --yes ovsx create-namespace copilotkit -p <token>
-
Stores the token as
OVSX_PATin theproductionGH environment.
Once the namespace is claimed, subsequent CI publishes run unattended.