Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ extension/.test-artifacts/
extension/.test-extensions/
extension/.test-results/
extension/.test-storage/
extension/.test-workspace/
extension/.test-workspaces/
extension/node_modules/
extension/.corepack-cache/
Expand Down
19 changes: 8 additions & 11 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ Before starting a release:
| Parameter | Description | Default |
|-----------|-------------|---------|
| `SkipNuGetPublish` | Set `true` if re-running after NuGet success. | `false` |
| `SkipNpmPublish` | Set `true` if re-running after all npm packages are published. | `false` |
| `SkipNpmRidPublish` | Set `true` if npm RID packages published but the pointer package did not. | `false` |
| `SkipNpmPointerPublish` | Set `true` if the pointer package published but a later validation or promotion step failed. Registry validation still runs. | `false` |
| `SkipChannelPromotion` | Set `true` if re-running after darc success. | `false` |
Expand All @@ -99,10 +98,9 @@ Before starting a release:
| `SkipReleaseAssets` | Set `true` to skip uploading `aspire-cli-*` assets to the GitHub release. | `false` |
| `SkipHomebrewValidation` | Set `true` if re-running after a successful Homebrew cask validation against the live GitHub release. | `false` |
| `SkipVSCodeExtensionPublish` | Set `false` to publish the signed `aspire-vscode-extension` artifact to the Visual Studio Marketplace. | `true` |
| `NpmPublishOwners` | Optional comma-separated ESRP owner aliases or emails. Leave empty for the repo default; overrides must still include the required owner aliases from `eng/pipelines/common-variables.yml`. | empty |
| `NpmPublishApprovers` | Optional comma-separated ESRP approver aliases or emails. Leave empty for the repo default; overrides must still include the required approver aliases from `eng/pipelines/common-variables.yml` and must not overlap owners. | empty |
| `NpmPublishOwners` | Comma-separated ESRP owner aliases or emails. Overrides must include `joperezr` or `ankj`, matching the required owner aliases in `eng/pipelines/release-publish-nuget.yml`. | `joperezr,ankj` |
| `NpmPublishApprovers` | Single ESRP approver alias or email. The approver must be a Microsoft address and must not overlap owners. | `adamratzman` |
| `NpmRegistryPropagationDelayMinutes` | Delay between npm RID package and pointer package submissions. | `10` |
| `AllowNpmLatestDistTagMove` | Emergency override for intentionally moving npm `latest` to an older stable version. Older servicing releases should normally use `SkipNpmPublish=true`. | `false` |
| `GitHubTasksWorkflowRef` | Ref to load `release-github-tasks.yml` from when dispatching. Only affects the workflow source; the release branch and commit are passed via inputs. Override only when testing pipeline changes on a topic branch. | `main` |

4. Select the **Resources** button in the bottom right, then select the source build from the `aspire-build` dropdown.
Expand All @@ -119,7 +117,6 @@ To publish only the VS Code extension after merging an extension release PR, run
| `IsPrerelease` | `false` for stable, `true` for pre-release |
| `DryRun` | `false` |
| `SkipNuGetPublish` | `true` |
| `SkipNpmPublish` | `true` |
| `SkipNpmRidPublish` | `true` |
| `SkipNpmPointerPublish` | `true` |
| `SkipChannelPromotion` | `true` |
Expand All @@ -133,7 +130,7 @@ To publish only the VS Code extension after merging an extension release PR, run

For a full Aspire release that should also publish the extension, keep the normal NuGet/channel/GitHub task settings and set `SkipVSCodeExtensionPublish` to `false`. `IsPrerelease` also controls whether extension publishing passes `--pre-release` to `vsce`; for a pre-release extension, the selected source build must also have been queued with `Package VS Code Extension as Pre-Release=true`.

The npm release path validates Windows, Linux, and macOS install summaries, publishes the seven RID packages first, waits for ESRP completion, waits for the configured propagation delay, and then publishes the top-level `@microsoft/aspire-cli` pointer package. After the pointer package publishes, the pipeline installs it from the live npm registry and runs `aspire --version` before channel promotion. This avoids installing a pointer package whose optional RID dependencies are not visible yet and catches registry propagation issues before the release is promoted. For prereleases, set `SkipNpmPublish=true` unless the npm publishing path has gained explicit non-`latest` dist-tag support.
The npm release path validates Windows, Linux, and macOS install summaries, publishes the seven RID packages first, waits for ESRP completion, waits for the configured propagation delay, and then publishes the top-level `@microsoft/aspire-cli` pointer package. After the pointer package publishes, the pipeline installs it from the live npm registry and runs `aspire --version` before channel promotion. This avoids installing a pointer package whose optional RID dependencies are not visible yet and catches registry propagation issues before the release is promoted. For prereleases, set `SkipNpmRidPublish=true` and `SkipNpmPointerPublish=true` unless the npm publishing path has gained explicit non-`latest` dist-tag support.

`commit_sha` and `release_branch` for the GitHub workflow are derived automatically from the source build resource, so there is no need to copy them by hand.

Expand All @@ -160,7 +157,7 @@ Run this step only when releasing the VS Code extension independently of the nor

The GitHub workflow is normally dispatched by the AzDO pipeline as the `aspire-repo-bot` GitHub App, with its `authorize` job bypassed for the bot. If a GitHub-side step fails partway through and you need to re-run only the GitHub work, you can:

1. Re-run the AzDO pipeline with completed AzDO-side work skipped, such as `SkipNuGetPublish`, `SkipNpmPublish`, `SkipNpmRidPublish`, `SkipChannelPromotion`, `SkipWinGetPublish`, `SkipHomebrewValidation`, and `SkipReleaseAssets` set as appropriate, keeping `SkipGitHubTasks: false`. The `GitHubTasks` stage will dispatch the workflow again with the right inputs, and the workflow's own `skip_*` idempotency makes the completed steps no-ops.
1. Re-run the AzDO pipeline with completed AzDO-side work skipped, such as `SkipNuGetPublish`, `SkipNpmRidPublish`, `SkipNpmPointerPublish`, `SkipChannelPromotion`, `SkipWinGetPublish`, `SkipHomebrewValidation`, and `SkipReleaseAssets` set as appropriate, keeping `SkipGitHubTasks: false`. The `GitHubTasks` stage will dispatch the workflow again with the right inputs, and the workflow's own `skip_*` idempotency makes the completed steps no-ops.
2. Or, navigate to Actions → **Release GitHub Tasks**, click **Run workflow**, and fill in the parameters manually:

| Parameter | Description | Example |
Expand Down Expand Up @@ -207,7 +204,7 @@ Both automations are designed to be idempotent and safe to re-run.
| Prepare/List/Verify NuGet Packages | Check that the selected source build produced `PackageArtifacts`. |
| Prepare/List npm Packages | Check that the selected source build produced all eight `microsoft-aspire-cli*.tgz` tarballs and matching `.tgz.sig` sidecars in `BlobArtifacts`. |
| Push Packages to NuGet.org | Check NuGet.org for partial success, then re-run with already-completed steps skipped as needed. |
| MicroBuild npm Publish | Check the ESRP release result. If RID packages published but the pointer package did not, re-run with `SkipNuGetPublish: true`, `SkipNpmRidPublish: true`, and `SkipChannelPromotion: true`; do not set `SkipNpmPublish` until the pointer package is published. |
| MicroBuild npm Publish | Check the ESRP release result. If RID packages published but the pointer package did not, re-run with `SkipNuGetPublish: true`, `SkipNpmRidPublish: true`, `SkipNpmPointerPublish: false`, and `SkipChannelPromotion: true`; do not set `SkipNpmPointerPublish` until the pointer package is published. |
| Validate Published npm Package from Registry | Confirm the pointer package is visible on npm and that `npm install -g @microsoft/aspire-cli@<version>` works. If registry propagation is slow, re-run with completed publish steps skipped after the package is visible. |
| Promote Build to Channel | Re-run with completed publish steps skipped. |
| WinGet publishing / Homebrew validation | Re-run with the corresponding skip flags for completed work. |
Expand Down Expand Up @@ -286,10 +283,10 @@ If ESRP published the RID packages but failed before publishing `@microsoft/aspi

1. Verify the RID packages are visible on npm.
2. Re-run the release pipeline with completed non-npm steps skipped.
3. Set `SkipNpmRidPublish: true` and keep `SkipNpmPublish: false` so only the pointer package is submitted.
4. Set `SkipNpmPublish: true` only after the pointer package is visible.
3. Set `SkipNpmRidPublish: true` and keep `SkipNpmPointerPublish: false` so only the pointer package is submitted.
4. Set `SkipNpmPointerPublish: true` only after the pointer package is visible.

If the pointer package published but the live npm registry validation failed afterward, re-run with `SkipNpmRidPublish: true`, `SkipNpmPointerPublish: true`, and `SkipNpmPublish: false` so the pipeline retries the install smoke without resubmitting already-published packages.
If the pointer package published but the live npm registry validation failed afterward, re-run with `SkipNpmRidPublish: true` and `SkipNpmPointerPublish: true` so the pipeline retries the install smoke without resubmitting already-published packages.

### Tag already exists but points to different commit

Expand Down
6 changes: 3 additions & 3 deletions docs/specs/npm-cli-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,11 @@ The release pipeline prepares two npm artifact folders and one validation artifa

The package split is intentional. The release job submits RID packages first, waits for the ESRP submission to complete, waits an additional npm registry propagation delay, and then submits the pointer package. Publishing the pointer package last avoids optional dependency resolution races when a user installs the top-level package immediately after release.

Before publishing, the release pipeline validates that exactly one pointer tarball and exactly one tarball for each supported RID are present, that every tarball has a detached `.tgz.sig` sidecar, that all tarballs have one version, and that the `NpmValidationSummary` artifact reports `validatedByPreparePipeline: true` with every required check `passed` for Windows, Linux, and macOS install validation. Non-dry-run npm publishing resolves the default ESRP owner and approver aliases from `eng/pipelines/common-variables.yml`; explicit `NpmPublishOwners` and `NpmPublishApprovers` overrides are allowed only if they still include the required release aliases and do not overlap.
Before publishing, the release pipeline validates that exactly one pointer tarball and exactly one tarball for each supported RID are present, that every tarball has a detached `.tgz.sig` sidecar, that all tarballs have one version, and that the `NpmValidationSummary` artifact reports `validatedByPreparePipeline: true` with every required check `passed` for Windows, Linux, and macOS install validation. npm publishing reads its ESRP identities from the `NpmPublishOwners` and `NpmPublishApprovers` pipeline parameters, which default to working values in `eng/pipelines/release-publish-nuget.yml` so an unattended queue submission does not fail and can be overridden per run: owners must include at least one required release owner alias configured in the pipeline, approvers must contain exactly one Microsoft alias or `@microsoft.com` email address, and the owner and approver sets must not overlap. The pipeline forwards both parameters to the validation step as environment variables (rather than interpolating them into the inline script) so the operator-supplied values are treated as data. The validation logic lives in `eng/scripts/validate-npm-release-aliases.ps1`; the release job runs with `checkout: none`, so the same helpers are mirrored inline in the pipeline and kept in sync by a unit test.

The release pipeline checks only the package groups scheduled for publishing before invoking MicroBuild. If `SkipNpmRidPublish=false`, every staged RID tarball is checked with `npm view <name>@<version> version`; if `SkipNpmPointerPublish=false`, the pointer tarball is checked the same way. Any scheduled package version that already exists on npm fails before ESRP submission, because npm versions are immutable and a duplicate publish would otherwise fail later in MicroBuild. Re-runs after partial success should use `SkipNpmRidPublish=true` only when every RID package for the selected version is already live, `SkipNpmPointerPublish=true` only when the pointer package is already live, and `SkipNpmPublish=true` only after the entire npm publish path has completed.
The release pipeline checks only the package groups scheduled for publishing before invoking MicroBuild. If `SkipNpmRidPublish=false`, every staged RID tarball is checked with `npm view <name>@<version> version`; if `SkipNpmPointerPublish=false`, the pointer tarball is checked the same way. Any scheduled package version that already exists on npm fails before ESRP submission, because npm versions are immutable and a duplicate publish would otherwise fail later in MicroBuild. Re-runs after partial success should use `SkipNpmRidPublish=true` only when every RID package for the selected version is already live, `SkipNpmPointerPublish=true` only when the pointer package is already live, and both flags together only after the entire npm publish path has completed.

Stable Aspire npm releases publish through npm's default `latest` dist-tag because MicroBuild's npm publish template does not currently expose a dist-tag parameter. To prevent older servicing releases from moving `@microsoft/aspire-cli@latest` backward, the release pipeline compares the scheduled pointer package version with the current public `@microsoft/aspire-cli@latest` version and fails if the scheduled version is lower. Older servicing releases should set `SkipNpmPublish=true`; `AllowNpmLatestDistTagMove=true` exists only as an emergency release-owner override for an intentional latest-tag move.
Stable Aspire npm releases publish through npm's default `latest` dist-tag because MicroBuild's npm publish template does not currently expose a dist-tag parameter. To prevent older servicing releases from moving `@microsoft/aspire-cli@latest` backward, the release pipeline compares the scheduled pointer package version with the current public `@microsoft/aspire-cli@latest` version and fails if the scheduled version is lower. Older servicing releases should set both `SkipNpmRidPublish=true` and `SkipNpmPointerPublish=true`.

MicroBuild's npm publish template documentation does not currently expose an npm `dist-tag` parameter. Non-dry-run prerelease npm publishing is blocked until preview packages can be submitted under a non-`latest` tag; release managers can still use `DryRun=true` to inspect the npm publish set without submitting packages.

Expand Down
4 changes: 0 additions & 4 deletions eng/pipelines/common-variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ variables:
value: npm-validation-summary-linux-x64
- name: NPM_VALIDATION_SUMMARY_OSX_ARTIFACT
value: npm-validation-summary-osx
- name: NPM_PUBLISH_REQUIRED_OWNERS
value: joperezr,ankj
- name: NPM_PUBLISH_REQUIRED_APPROVERS
value: adamratzman
# Disable the interactive "Do you want to download yarn@x.y.z?" prompt so
# pipeline steps don't hang waiting for stdin.
- name: COREPACK_ENABLE_DOWNLOAD_PROMPT
Expand Down
Loading
Loading