Skip to content
Open
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
37 changes: 21 additions & 16 deletions src/docs/Capabilities/release-management/design.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Design
description: How release management is built — a shared reusable workflow that reads pull-request labels, computes the SemVer bump, and cuts the release.
description: How release management is built — a shared reusable workflow that resolves a configured or label-selected SemVer bump, builds once, and publishes.
---

# Release Management — Design
Expand Down Expand Up @@ -30,6 +30,7 @@ A **release branch** is any branch configured as a release target, each with a

```yaml
# .github/release.config.yml
DefaultBump: patch
release-branches:
- branch: main
release-type: stable
Expand Down Expand Up @@ -75,18 +76,20 @@ Release automation reads only labels in its `release:` namespace:

| Label | Meaning | Valid combination |
| --- | --- | --- |
| `release:patch` | Resolve the next patch version. | Exactly one bump label. |
| `release:minor` | Resolve the next minor version. | Exactly one bump label. |
| `release:major` | Resolve the next major version. | Exactly one bump label. |
| `release:pre-release` | Publish the open pull request as a prerelease. | With exactly one bump label. |
| `release:patch` | Override `DefaultBump` and resolve the next patch version. | Alone or with `release:pre-release`. |
| `release:minor` | Override `DefaultBump` and resolve the next minor version. | Alone or with `release:pre-release`. |
| `release:major` | Override `DefaultBump` and resolve the next major version. | Alone or with `release:pre-release`. |
| `release:pre-release` | Publish the open pull request as a prerelease. | Alone or with one owned bump label. |
| `release:skip` | Run validation without resolving or publishing a version. | Alone. |

Exactly one bump label or `release:skip` is required; **no default** is applied.
`release:pre-release` is an optional mode label, not a bump. A missing decision,
multiple bump labels, `release:skip` with another release label, or
`release:pre-release` without one bump label is **rejected**, so the outcome is
always a decision someone made. Bare `major`, `minor`, and `patch` labels are
ignored.
`DefaultBump` in `.github/release.config.yml` accepts exactly `patch`, `minor`,
or `major`; omitting it resolves to `patch`. Any other value is rejected before
Resolve begins. With no owned bump label, Resolve uses `DefaultBump`. Exactly one
of `release:patch`, `release:minor`, or `release:major` overrides it.
`release:pre-release` is a mode label, not a bump, and uses that same resolved
bump. Multiple owned bump labels and `release:skip` with any other owned release
label are rejected. Bare `major`, `minor`, and `patch` labels and all unrelated
labels are ignored.

- **First release** starts from a baseline (`v0.1.0` or `v1.0.0`). Pre-`1.0.0`
breaking changes are `release:minor` per [SemVer §4](https://semver.org/#spec-item-4);
Expand Down Expand Up @@ -117,10 +120,11 @@ either: rerun the existing release with the same artifact and version under the

- **Branch-level** — a prerelease-type branch publishes on every push, using the
branch name as the identifier: `v1.3.0-dev.1`, `v1.3.0-dev.2`, …
- **PR-level** — `release:pre-release` alongside exactly one bump label on an open PR publishes
`v<base>-<identifier>.<counter>`: `base` is the next version from the PR's bump
label, `identifier` is the normalized branch name, and `counter`
auto-increments per push.
- **PR-level** — `release:pre-release` on an open PR publishes
`v<base>-<identifier>.<counter>`: `base` is the next version from one explicit
owned bump label when present, otherwise from the resolved `DefaultBump`;
`identifier` is the normalized branch name, and `counter` auto-increments per
push.
- Artifact-specific conventions replace the SemVer suffix where they exist
(`-alpha.N` for npm, `.devN` for Python). Release candidates use `-rc.N`,
auto-incrementing.
Expand Down Expand Up @@ -243,7 +247,8 @@ release, and its runs are serialised like any other.
| Surface | Where |
| --- | --- |
| Release branches + type | `.github/release.config.yml` |
| Release decision / prerelease / RC | `release:` PR label |
| Default bump | `DefaultBump` in `.github/release.config.yml` |
| Bump override / prerelease / skip | `release:` PR label |
| Optional ad hoc release | `workflow_dispatch` inputs |
| Path filter | `.github/release.config.yml` |
| Prerelease cleanup toggle | release config / workflow input |
Expand Down
12 changes: 6 additions & 6 deletions src/docs/Capabilities/release-management/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ description: How a source change becomes a versioned, immutable artifact, driven

Turning a merged change into a versioned, immutable artifact — a container
image, a GitHub Action or reusable workflow, a language package, a Terraform
module — paired with a GitHub Release and a git tag, normally driven by
pull-request labels. An implementation may add a GitHub-native ad hoc release
path when its product needs one. No release CLI, no hand-edited version file,
no tagging ritual.
module — paired with a GitHub Release and a git tag, driven by a configured
default and pull-request label overrides. An implementation may add a
GitHub-native ad hoc release path when its product needs one. No release CLI,
no hand-edited version file, no tagging ritual.

<!-- INDEX:START -->

| Page | Description |
| --- | --- |
| [Spec](spec.md) | Requirements for release management — automatic, label-driven, versioned releases driven entirely on the GitHub platform. |
| [Design](design.md) | How release management is built — a shared reusable workflow that reads pull-request labels, computes the SemVer bump, and cuts the release. |
| [Spec](spec.md) | Requirements for release management — automatic, policy-driven, versioned releases driven entirely on the GitHub platform. |
| [Design](design.md) | How release management is built — a shared reusable workflow that resolves a configured or label-selected SemVer bump, builds once, and publishes. |
| [Publishing Targets](design-publishing-targets.md) | The contract every publishing destination documents, with GitHub Releases as the reference target. |

<!-- INDEX:END -->
16 changes: 8 additions & 8 deletions src/docs/Capabilities/release-management/spec.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Spec
description: Requirements for release management — automatic, label-driven, versioned releases driven entirely on the GitHub platform.
description: Requirements for release management — automatic, policy-driven, versioned releases driven entirely on the GitHub platform.
---

# Release Management — Spec
Expand All @@ -18,7 +18,7 @@ release CLI, a hand-edited version file, or a tagging convention.
This capability rests on the [Principles](../../Ways-of-Working/Principles/index.md):

- **[Everything as Code](../../Ways-of-Working/Principles/Engineering-Practices.md#everything-as-code).** The release process and version decision are version-controlled, never a GUI action or manual tag.
- **[Decision before change](../../Ways-of-Working/Principles/AI-First-Development.md#decision-before-change).** The pull request is the decision point; its review gate approves the code *and* the release, and the bump label records the versioning decision explicitly.
- **[Decision before change](../../Ways-of-Working/Principles/AI-First-Development.md#decision-before-change).** The pull request is the decision point; its review gate approves the code *and* the release. The version-controlled `DefaultBump` records the repository's normal versioning policy, and an owned bump label records a reviewed override.
- **[Extensible by default](../../Ways-of-Working/Principles/Software-Design.md#extensible-by-default).** The rules are technology-agnostic at the core, with defined extension points per artifact type. A new artifact type supplies a convention and a publish step, not a new process.

## Scope
Expand All @@ -31,12 +31,12 @@ this capability governs the release. If no, there is nothing to release.
## Requirements

- **Semantic versioning.** Versions follow [SemVer 2.0.0](https://semver.org/) (`vMAJOR.MINOR.PATCH`), derived automatically — never written by hand.
- **Namespaced release decision, stated explicitly.** Release automation reads only the `release:` namespace. Exactly one of `release:patch`, `release:minor`, `release:major`, or `release:skip` MUST be present, and there is **no default**: an unlabeled pull request is not releasable, and the release fails closed rather than assuming the smallest bump. `release:pre-release` MAY accompany exactly one bump label on an open pull request and MUST NOT be combined with `release:skip`. Bare `patch`, `minor`, and `major` labels are not release decisions. Requiring an owned label makes versioning a reviewed decision instead of an omission. Conventional commit messages are **not** required.
- **A release per merge.** One merged PR carrying `release:patch`, `release:minor`, or `release:major` to a release branch is one release, and the PR review gate is the release gate. `release:skip` validates without publishing. This pull-request path is the required release interface.
- **Namespaced release decision with a configurable default.** Release automation reads only the `release:` namespace. `DefaultBump` MUST accept exactly `patch`, `minor`, or `major` and MUST resolve to `patch` when omitted. With no owned bump label, automation MUST use the resolved `DefaultBump`; when present, exactly one of `release:patch`, `release:minor`, or `release:major` MUST override it. `release:pre-release` MAY be used alone or with exactly one owned bump label on an open pull request and MUST use that owned bump when present, otherwise the resolved `DefaultBump`. `release:skip` MUST prevent publication and MUST NOT be combined with another owned release label. Multiple owned bump labels MUST fail. Bare `patch`, `minor`, and `major` labels and all unrelated labels MUST be ignored. Conventional commit messages are **not** required.
- **A release per merge.** One merged PR to a release branch is one release unless it carries `release:skip`, and the PR review gate is the release gate. The bump comes from one explicit owned bump label or the resolved `DefaultBump`. `release:skip` validates without publishing. This pull-request path is the required release interface.
- **Ad hoc release is optional.** An implementation MAY expose `workflow_dispatch` when its product needs an ad hoc release outside the merge flow; implementations are not required to support it. A dispatch MUST require an explicit release decision and release-note context, and MUST use the same version, build, validation, immutability, and publication controls as a merged pull request. A direct push MUST NOT be an ad hoc release interface, and an empty pull request MUST NOT be created solely to trigger a release.
- **Version before build.** The version MUST be resolved before the artifact is built, so the version is part of the artifact's identity rather than a label attached afterwards.
- **Build once.** The artifact MUST be built exactly once and MUST NOT be altered after it is built. The same bytes flow through validation and publishing. Rebuilding to publish means the tested artifact and the published artifact are different artifacts.
- **Stable and prerelease.** Every release is either **stable** (the latest version to adopt) or a **prerelease** (testable, not promoted to latest). A prerelease MUST be obtainable from an open pull request carrying `release:pre-release` and a bump label and/or from a prerelease branch.
- **Stable and prerelease.** Every release is either **stable** (the latest version to adopt) or a **prerelease** (testable, not promoted to latest). A prerelease MUST be obtainable either from an open pull request carrying `release:pre-release`, using its explicit owned bump label or the resolved `DefaultBump`, or from a prerelease branch.
- **Serialised releases.** Only one release process runs against a given version of the codebase (the same ref) at a time. A release mutates shared, version-anchored state — the tag, the version counter, the published artifact — so overlapping runs on the same ref MUST NOT race, and an in-flight release is never interrupted.
- **A single production authority.** Exactly one branch is in charge of the production (stable) version, so consumers get one unambiguous latest stable release and two branches can never publish competing production releases.
- **Notes from the contributor's own words.** The GitHub Release name is the version; its body comes from the pull request title and description, or from the required release-note context of an optional ad hoc dispatch. The PR description is therefore written for consumers.
Expand All @@ -63,9 +63,9 @@ Because versions are semantic, immutable, and published once, a consumer can ado

## Success criteria

- Merging a PR with exactly one namespaced bump label to a release branch produces a GitHub Release, a git tag, and (where one exists) a published artifact, with no manual step.
- The version bump matches the PR's `release:` label every time; a missing, conflicting, ambiguous, or bare label set is **rejected**, never guessed.
- An open pull request carrying `release:pre-release` and exactly one bump label publishes a prerelease without promoting it to latest.
- Merging a PR without `release:skip` to a release branch produces a GitHub Release, a git tag, and (where one exists) a published artifact, using one explicit owned bump label or the resolved `DefaultBump` with no manual step.
- An explicit namespaced bump label overrides `DefaultBump` every time; without one, the validated `DefaultBump` is used. An invalid default or conflicting owned label set is rejected, while bare and unrelated labels are ignored.
- An open pull request carrying `release:pre-release` publishes a prerelease without promoting it to latest, using one explicit owned bump label when present and the resolved `DefaultBump` otherwise.
- The artifact that consumers download is byte-identical to the artifact that passed validation.
- A documentation-only merge carrying `release:skip` produces no new version but still runs its CI checks.
- Two release runs for the same ref never overlap; the second waits for the first to finish rather than racing it.
Expand Down
30 changes: 18 additions & 12 deletions src/docs/Capabilities/vscode-extension-framework/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ every downstream stage reuses the exact output of the stages before it:

```mermaid
flowchart LR
find["Find version\ntags + PR label"] --> build["Build\nstamp · bundle · package VSIX"]
find["Find version\ntags + release policy"] --> build["Build\nstamp · bundle · package VSIX"]
build --> test["Test\nreal VS Code host · matrix"]
lint["Lint & type-check"] --> release
test --> release["Release\npublish the built VSIX"]
```

- **Find version** — compute the version once, from the latest `vX.Y.Z` tag or
release plus the pull request's bump label. Independent of the other stages.
release plus one explicit owned bump label or the resolved `DefaultBump`.
Independent of the other stages.
- **Lint & type-check** — static analysis and the type checker. Independent, so
it fails fast in parallel with the build.
- **Build** — stamp the computed version into the manifest, compile the
Expand All @@ -43,7 +44,7 @@ flowchart LR
The version is computed once and flows through the pipeline as artifacts, so the
thing that ships is the thing that was tested:

1. **Find version** decides `vX.Y.Z` from tags plus the PR label.
1. **Find version** decides `vX.Y.Z` from tags plus the resolved bump policy.
2. **Build** stamps it into `package.json` (and `package-lock.json`), compiles
the bundle, and runs the packaging CLI to produce a single VSIX. The stamped
manifest is uploaded alongside the VSIX so the manifest under test — including
Expand Down Expand Up @@ -98,16 +99,20 @@ pass before the release stage runs, alongside a green test result.
Versioning is [Release Management](../release-management/design.md) applied to a
VSIX artifact — this framework does not re-implement it:

- The release decision is exactly one of `release:patch`, `release:minor`,
`release:major`, or `release:skip`, with no default. Multiple bump labels and
`release:skip` with another release label are rejected.
- `DefaultBump` accepts exactly `patch`, `minor`, or `major` and resolves to
`patch` when omitted. When present, one of `release:patch`, `release:minor`, or
`release:major` overrides it. Multiple owned bump labels and `release:skip`
with any other owned release label are rejected; bare and unrelated labels are
ignored.
- `release:skip` prevents publication.
- The version is computed once and stamped into the manifest; it is never
hand-edited.
- A prerelease is requested by `release:pre-release` alongside one bump label on
an open pull request (or by a prerelease branch), producing a prerelease VSIX
that is never promoted to latest. When such a build is also published to the
VS Code Marketplace, it goes out with `@vscode/vsce publish --pre-release` and
an odd minor-version number, the Marketplace's pre-release-channel convention.
- A prerelease is requested by `release:pre-release` on an open pull request (or
by a prerelease branch), using one explicit owned bump label when present and
the resolved `DefaultBump` otherwise. It produces a prerelease VSIX that is
never promoted to latest. When such a build is also published to the VS Code
Marketplace, it goes out with `@vscode/vsce publish --pre-release` and an odd
minor-version number, the Marketplace's pre-release-channel convention.

## Publishing and distribution

Expand Down Expand Up @@ -165,7 +170,8 @@ Every external Action is pinned to a commit SHA; organization- or initiative-own
| --- | --- |
| Adoption (opt-in) | a short caller workflow that calls the reusable workflow |
| Host + OS matrix, marketplace toggle, extras | `.github/vscode-extension.yml` |
| Version bump / prerelease | pull-request label |
| Default bump | `DefaultBump` in `.github/release.config.yml` |
| Bump override / prerelease / skip | pull-request label |
| Release branches + path filter | `.github/release.config.yml` ([Release Management](../release-management/design.md)) |
| Marketplace publish tokens | a GitHub environment's secrets |
| Extension manifest (`engines.vscode`, `contributes`, activation) | `package.json` |
Expand Down
Loading
Loading