diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ccfab20f..a370c593 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -143,14 +143,17 @@ prerelease floors, and build metadata are rejected. The helper checks installed extension versions before activation using normal SemVer precedence, including already-active extensions. Published npm releases keep their original minimum. -Any PR editing a shared public API source or `api/runtime/**/*.ts` must bump the -npm version, update [`api/CHANGELOG.md`](./api/CHANGELOG.md), and update -[`docs/README.md`](./docs/README.md). The existing `skip api version`, -`skip api changelog`, and `skip api docs` labels apply to those file checks, but -do not bypass compatibility or publication validation. - -Release in this order: merge API changes, ship the stable extension, update the -npm minimum/version/changelog, then build and publish npm. Development can merge +Defer npm version bumps to release PRs by applying `skip api version` to API +implementation PRs. Any PR editing a shared public API source or +`api/runtime/**/*.ts` must still update [`api/CHANGELOG.md`](./api/CHANGELOG.md) +and [`docs/README.md`](./docs/README.md). The existing `skip api changelog` and +`skip api docs` labels apply to those file checks. None of these labels bypass +compatibility or publication validation. + +Release in this order: merge API changes without an npm version bump, ship the +stable extension, then merge an npm release PR updating +`minimumExtensionVersion`, the npm version, and the changelog. The stable npm +version bump starts the publication pipeline automatically. Development can merge before the extension ships: source provenance is checked at packaging, not on PRs. The npm pipeline resolves the stable release tag to an immutable commit and requires all five shared source files, including their staged copies, to match. @@ -167,6 +170,8 @@ this stable baseline: preview-only API publishing needs a separate policy. Public GitHub lookups use bounded retries and fail closed. Local runs can set `GITHUB_TOKEN` to avoid anonymous rate limits; PRs use their read-only token. +- **Releasing:** merging a stable version change in `api/package.json` into `main` automatically starts the [npm pipeline](./build/azure-pipeline.npm.yml), including its existing build, package tests, and MicroBuild approval process. Other manifest edits build and validate the package without publishing. The version check compares the merged commit with its parent, relying on the repository's squash-only merge policy; direct pushes to `main` also trigger it. Preview releases remain manual: queue the pipeline with `quality: preview` and `publishPackage: true`. Manual runs otherwise remain build-only unless `publishPackage` is explicitly enabled. + ## Internal Python agent-tool bridge The extension's existing **flat** export also provides `__pythonTools.version === 1`. diff --git a/build/azure-pipeline.npm.yml b/build/azure-pipeline.npm.yml index de35d4d8..1643fd50 100644 --- a/build/azure-pipeline.npm.yml +++ b/build/azure-pipeline.npm.yml @@ -1,6 +1,12 @@ name: $(Date:yyyyMMdd)$(Rev:.r) -trigger: none +trigger: + branches: + include: + - main + paths: + include: + - api/package.json pr: none resources: @@ -74,12 +80,29 @@ extends: targetPath: $(Build.ArtifactStagingDirectory) artifactName: npm-package steps: + - checkout: self + fetchDepth: 2 + - template: azure-pipelines/extension/templates/steps/setup.yml@templates parameters: installPython: false customNPMRegistry: $(AZURE_ARTIFACTS_FEED) nodeVersion: $(NodeVersion) + - bash: | + set -euo pipefail + previous=$(git show HEAD^:api/package.json | jq -er '.version | strings') + current=$(git show HEAD:api/package.json | jq -er '.version | strings') + changed=false + if [[ "$previous" != "$current" && "$current" != *-* ]]; then + changed=true + fi + echo "Package version: $previous -> $current" + echo "##vso[task.setvariable variable=versionChanged;isOutput=true]$changed" + name: checkVersion + displayName: Check for a stable package version change + condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + - script: npm ci workingDirectory: $(Build.SourcesDirectory)/api displayName: Install package dependencies @@ -106,7 +129,7 @@ extends: - stage: PublishNPM displayName: Publish to NPM dependsOn: Build - condition: and(succeeded(), eq('${{ parameters.publishPackage }}', 'true')) + condition: and(succeeded(), or(eq('${{ parameters.publishPackage }}', 'true'), eq(dependencies.Build.outputs['BuildPackage.checkVersion.versionChanged'], 'true'))) jobs: - job: PublishPackage displayName: Publish npm package