This monorepo ships three independently-versioned packages. Each has its own release workflow, tag convention, and publish destination.
| Package | Tag (stable) | Tag (preview) | Publishes to |
|---|---|---|---|
| PSDocs | psdocs-vX.Y.Z |
psdocs-vX.Y.Z-preview.N |
PowerShell Gallery (PSDocs) |
| PSDocs.Azure | psdocs-azure-vX.Y.Z |
psdocs-azure-vX.Y.Z-preview.N |
PowerShell Gallery (PSDocs.Azure) |
| VS Code Extension | vscode-vX.Y.Z |
vscode-preview-vX.Y.Z |
VS Marketplace (vicperdana.psdocs-vscode / …-preview) |
All three workflows also create a GitHub Release on this repo with notes
extracted from the relevant CHANGELOG.md and (for VS Code) the .vsix
attached.
VS Code is special. The Marketplace does not accept SemVer prerelease suffixes (
-preview.N) in the package version. Channel is encoded in the tag prefix (vscode-preview-v…) and routed via the build pipeline's-Channel previewparameter, which produces a separate extension ID (vicperdana.psdocs-vscode-preview). Both channels publish plainX.Y.Zversions.
- Sign in at https://www.powershellgallery.com with an account that is a
co-owner of
PSDocsandPSDocs.Azure. - Profile → API Keys → Create:
- Glob pattern:
PSDocs;PSDocs.Azure - Scopes:
Push new packages and package versions+Unlist packages - Expiration: 365 days (calendar a renewal reminder).
- Glob pattern:
- Copy the key.
- In this repo: Settings → Secrets and variables → Actions → New repository
secret, name
PSGALLERY_API_KEY.
- At https://dev.azure.com/{your-org} (the Azure DevOps org backing the
vicperdanaMarketplace publisher), open User settings → Personal access tokens → New Token:- Organization: All accessible organizations
- Scopes: Custom defined → Marketplace → Manage
- Expiration: 365 days max.
- Copy the token.
- In this repo: add it as a secret named
VSCE_PAT.
- Settings → Environments → New environment named
release. - Required reviewers: add yourself (and optionally a co-maintainer).
- Deployment branches and tags: select Selected branches and tags, add
three tag rules:
psdocs-v*psdocs-azure-v*vscode-v*vscode-preview-v*
- Confirm — both
PSGALLERY_API_KEYandVSCE_PATare accessible to jobs that target this environment.
Each release workflow accepts a manual trigger with two inputs:
- tag — the tag you intend to push (e.g.
psdocs-azure-v0.5.0orvscode-preview-v0.4.0). - dry_run — defaults to
true. Whentrue, the workflow does everything exceptPublish-Module/vsce publish/gh release create. Use this to:- Confirm the manifest version matches the planned tag.
- Confirm
scripts/extract-release-notes.ps1finds and renders the right CHANGELOG section. - Confirm the build artifact is produced (and, for VS Code, that the VSIX is named correctly).
To run a dry-run: Actions → Release {Package} → Run workflow → fill in tag, leave dry_run checked → Run.
Always do a dry-run before pushing the real tag for first-of-its-kind cases (first release after a manifest restructure, first time after upgrading a build dep, etc.).
The same shape applies to all three packages. The differences are: which files get bumped, which CHANGELOG you update, and which tag prefix you push.
| Package | Edit |
|---|---|
| PSDocs | packages/psdocs/src/PSDocs/PSDocs.psd1 → ModuleVersion = 'X.Y.Z' |
| PSDocs.Azure | packages/psdocs-azure/src/PSDocs.Azure/PSDocs.Azure.psd1 → ModuleVersion = 'X.Y.Z' |
| VS Code Extension | packages/vscode-extension/package.json → "version": "X.Y.Z" |
The release workflow validates the manifest version against the tag and fails fast on mismatch.
Add a new section at the top of the relevant CHANGELOG immediately after the
## Unreleased heading:
## vX.Y.Z
What's changed since vA.B.C:
- Category:
- Description. [#PR](link)| Package | CHANGELOG path |
|---|---|
| PSDocs | packages/psdocs/CHANGELOG.md |
| PSDocs.Azure | CHANGELOG.md (repo root) |
| VS Code Extension | packages/vscode-extension/CHANGELOG.md |
The release workflow uses scripts/extract-release-notes.ps1 to pull this
section verbatim into the GitHub Release notes. Keep the heading exactly as
## vX.Y.Z (a date in parentheses is also accepted, e.g. ## v0.4.0 (15 May 2026)).
git checkout -b release/psdocs-azure-v0.5.0
git add packages/psdocs-azure/src/PSDocs.Azure/PSDocs.Azure.psd1 CHANGELOG.md
git commit -m "release: PSDocs.Azure v0.5.0"
git push -u origin release/psdocs-azure-v0.5.0
gh pr create --fill --base main
# review + mergeAfter merge, on main at the merge commit:
git checkout main
git pull --ff-only
git tag -a psdocs-azure-v0.5.0 -m "PSDocs.Azure v0.5.0"
git push origin psdocs-azure-v0.5.0- Open Actions → Release {Package} — the run is paused at the
releaseenvironment gate. - Click Review deployments → Approve and deploy.
- Watch the run complete.
| Package | Verification |
|---|---|
| PSDocs | Find-Module PSDocs -Repository PSGallery shows the new version |
| PSDocs.Azure | Find-Module PSDocs.Azure -Repository PSGallery shows the new version |
| VS Code | https://marketplace.visualstudio.com/items?itemName=vicperdana.psdocs-vscode |
| All three | https://github.com/Azure/PSDocs.Azure/releases shows the new release |
For VS Code, also confirm the .vsix is attached to the GitHub Release.
The PowerShell Gallery accepts SemVer 2.0 prerelease suffixes. Tag with the suffix appended:
git tag -a psdocs-azure-v0.5.0-preview.1 -m "PSDocs.Azure v0.5.0-preview.1"
git push origin psdocs-azure-v0.5.0-preview.1The workflow strips -preview.1 from the tag, validates the base version
(0.5.0) against the manifest's ModuleVersion, then Update-ModuleManifest
sets the PSData.Prerelease field to preview1 (the pipeline removes the dot
to satisfy the gallery's prerelease character rules) before publish. The
GitHub Release is marked as a pre-release.
-preview.Nincrements: Each preview iteration must incrementN. You cannot republish the same version (e.g.…-preview.1twice) — PSGallery returns 409.
Use the dedicated tag prefix:
git tag -a vscode-preview-v0.5.0 -m "VS Code Extension v0.5.0 (preview)"
git push origin vscode-preview-v0.5.0The workflow routes this to Invoke-Build -Channel preview, which sets the
extension ID to vicperdana.psdocs-vscode-preview, sets package.preview = true, publishes with vsce publish --pre-release, and marks the GitHub
Release as a pre-release.
Preview and stable extensions are separate Marketplace listings. Users install one or the other; they do not auto-cross-upgrade.
You forgot Step 1 (bump the manifest). Either re-tag after fixing the manifest
on main, or delete the offending tag:
git tag -d psdocs-azure-v0.5.0
git push origin :refs/tags/psdocs-azure-v0.5.0
# bump manifest, commit, then re-tagThe CHANGELOG section heading exists but has no body. Add release notes
under the heading (Step 2). If you genuinely want to publish with no notes,
re-run with -AllowEmpty by editing the workflow temporarily — but this is
strongly discouraged.
You're trying to republish an existing version. PSGallery never allows this.
Bump to the next patch version (or next -preview.N) and re-tag.
The Marketplace already has this version. Bump package.json and the tag.
Ensure @types/vscode in package.json is ~ pinned to the same minor as
engines.vscode. See microsoft/vscode-vsce#787.
By design — manual approval is the safety gate. If you're the only reviewer and need to ship outside business hours, the approval link is in the workflow run page.
Never republish an already-published version. Always roll forward.
| Registry | Action |
|---|---|
| PowerShell Gallery | Sign in → package page → Manage Owners / Unlist |
| VS Marketplace | npx @vscode/vsce unpublish vicperdana.psdocs-vscode@X.Y.Z |
| GitHub Release | gh release delete vscode-vX.Y.Z then git push origin :refs/tags/vscode-vX.Y.Z |
Then ship a new version with the fix.
PSDocs tag: psdocs-vX.Y.Z (preview: psdocs-vX.Y.Z-preview.N)
PSDocs.Azure tag: psdocs-azure-vX.Y.Z (preview: psdocs-azure-vX.Y.Z-preview.N)
VS Code tag: vscode-vX.Y.Z (preview: vscode-preview-vX.Y.Z)
Secrets: PSGALLERY_API_KEY, VSCE_PAT
Env: release (with reviewers + tag-restricted)
Notes: auto-extracted via scripts/extract-release-notes.ps1