From faa6e9cede458966f82204eeb9e7c4b434819f0c Mon Sep 17 00:00:00 2001 From: Benjamin Laird <86321957+ben-laird@users.noreply.github.com> Date: Sun, 7 Jun 2026 17:44:10 -0500 Subject: [PATCH] docs: sweep deep docs to release-on-merge-first framing (#17) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The headline docs already lead with release-on-merge and present the Release PR as a variant; this sweeps the deeper docs to match, keeping "Release PR" as a named variant rather than the canonical flow. - guides/cut-a-release.md — reframe TL;DR and Step 3/4 to lead with release-on-merge; add a "Release PR variant" section and a workflow-neutral "What to review" subsection. - specs/walkthrough.md, specs/language.md (term + algebra note), specs/v1-scope.md, specs/cli.md — note the Release PR is one of two workflows (release-on-merge default). - Light reword of the "Release PR" source comments in version.ts, git/mod.ts, git/commit.ts for consistency (comments only). Docs build clean; deno task verify passes (comment-only code edits). Closes #17. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/cli/src/cli/version.ts | 6 +- apps/cli/src/subtools/git/commit.ts | 3 +- apps/cli/src/subtools/git/mod.ts | 2 +- apps/docs/content/guides/cut-a-release.md | 73 ++++++++++++++++++----- specs/cli.md | 5 +- specs/language.md | 12 ++-- specs/v1-scope.md | 7 ++- specs/walkthrough.md | 7 ++- 8 files changed, 85 insertions(+), 30 deletions(-) diff --git a/apps/cli/src/cli/version.ts b/apps/cli/src/cli/version.ts index f39daf6..6999ee0 100644 --- a/apps/cli/src/cli/version.ts +++ b/apps/cli/src/cli/version.ts @@ -53,7 +53,8 @@ import { makeStyler } from "./styler.ts"; // `dv version` per specs/cli.md § dv version. Consumes pending Records // and (per Package) applies the aggregated Bump, rewrites the manifest // Version, prepends a CHANGELOG section, deletes the consumed Records, -// and stages everything into one commit (the Release PR). +// and stages everything into one commit (the version-bump commit; the +// Release PR in a review-gated workflow). // // Plan-then-execute is the spine (specs/language.md Algebra §7): the // same buildVersionPlan call powers `dv status`, `dv version --dry-run`, @@ -147,7 +148,8 @@ export interface CascadedUpdate { * Runs `dv version`: consumes pending Records and, per Package, applies the * aggregated Bump, rewrites the manifest Version, prepends a CHANGELOG section, * cascades dependent constraints, deletes the consumed Records, and stages - * everything into one commit (the Release PR). Plan-then-execute is the spine + * everything into one commit (the version-bump commit; the Release PR in a + * review-gated workflow). Plan-then-execute is the spine * (specs/language.md Algebra §7): the same `buildVersionPlan` call powers * `dv status`, `--dry-run`, and the real run, with the dry-run path invoking * zero write-side plugin Ops and touching nothing on disk. diff --git a/apps/cli/src/subtools/git/commit.ts b/apps/cli/src/subtools/git/commit.ts index 0dc081f..50f2a4a 100644 --- a/apps/cli/src/subtools/git/commit.ts +++ b/apps/cli/src/subtools/git/commit.ts @@ -2,7 +2,8 @@ import type { GitSign } from "../../domain/config.ts"; import { DvError } from "../../domain/errors.ts"; // Creates a commit from currently-staged changes. `dv version` produces -// exactly one such commit (the Release PR) per specs/cli.md § dv version. +// exactly one such commit — the version-bump commit (the Release PR in a +// review-gated workflow) per specs/cli.md § dv version. // // Signing follows the git.sign config option (specs/config-format.md § // git.sign): `"auto"` honors git's own commit.gpgsign config (no flag diff --git a/apps/cli/src/subtools/git/mod.ts b/apps/cli/src/subtools/git/mod.ts index c9b2183..4f9d981 100644 --- a/apps/cli/src/subtools/git/mod.ts +++ b/apps/cli/src/subtools/git/mod.ts @@ -1,7 +1,7 @@ // Public surface of the git Substrate (specs/design.md § Capability // decomposition: git is a substrate, not a capability of its own). Used // by `dv version` to gate the run, stage the changes, and produce the -// Release PR commit. +// version-bump commit (the Release PR in a review-gated workflow). export { type AssertCleanTreeArgs, assertCleanTree } from "./clean-tree.ts"; export { diff --git a/apps/docs/content/guides/cut-a-release.md b/apps/docs/content/guides/cut-a-release.md index 6cbb762..0bf8d18 100644 --- a/apps/docs/content/guides/cut-a-release.md +++ b/apps/docs/content/guides/cut-a-release.md @@ -1,32 +1,43 @@ # Cut a release This guide walks through running a real release end-to-end, including -the things you'll actually do in practice — previewing first, gating -on review, handling failures. If you've never used dv, start with the +the things you'll actually do in practice — previewing first, handling +failures, and (if your team wants it) gating the bump on review. If +you've never used dv, start with the [Getting started tutorial](/getting-started) first; this assumes you already know what Records are. Skim the page top-to-bottom the first time. After that, the **TL;DR** at the top is what most days look like. +The default workflow is **release-on-merge** (plain GitHub Flow): +merging a feature PR to `main` runs both phases automatically, because +the bump is derived from the Records that PR carried. Teams that want a +human to approve the bump before it lands can route the `dv version` +commit through a **Release PR** instead — same two commands, one extra +review gate. This guide shows release-on-merge first, then the Release +PR variant. + ## TL;DR ```sh # 1. Verify the plan $ dv status -# 2. Land the Release PR +# 2. Bump versions + write CHANGELOGs $ dv version --dry-run # preview -$ dv version # for real (one commit) -# → review, merge +$ dv version # for real (one commit, straight to main + # under release-on-merge) # 3. Tag + publish $ dv release --dry-run # preview $ dv release # for real ``` -Three commands, two phases, plus the merge. The rest of this page is -the *why* and the edge cases. +Three commands, two phases. Under release-on-merge both phases run in +CI on merge to `main`; if you gate behind a Release PR, the `dv version` +commit is reviewed and merged before `dv release` runs. The rest of this +page is the *why* and the edge cases. ## Step 1: see what's pending with `dv status` @@ -100,7 +111,7 @@ The `--json` shape is documented in the [Plan schema](https://github.com/ben-lai and is stable across the three commands (`dv status`, `dv version --dry-run`, `dv release --dry-run`). -## Step 3: land the Release PR with `dv version` +## Step 3: bump versions with `dv version` ```sh $ dv version @@ -125,11 +136,16 @@ What dv did: 7. **Refreshed lockfiles** via the plugin's `finalize` op. 8. **Staged everything** into one commit. -That commit is the **Release PR**. Open it as a PR, review it, merge it. +Under **release-on-merge**, this commit lands on `main` as part of the +CI job that ran on the merge — there's no separate step. If you prefer +to gate the bump on review, that same commit becomes a **Release PR**: +open it as a PR, review it, and merge it before `dv release` runs (see +[the Release PR variant](#the-release-pr-variant) below). -### Reviewing the Release PR +### What to review (either workflow) -Things to look at: +Whether the bump commit lands automatically or you review it as a +Release PR, these are the things worth a look: - **The CHANGELOG entries** read as you'd want them to. Each Record's `notes` field became one CHANGELOG bullet. If the bullet reads @@ -191,12 +207,37 @@ right call when a package was renamed and old Records should resolve to the new name. See [Packages and plugins](/concepts/packages-and-plugins) for more on the rename ledger. -## Step 4: the merge +## Step 4: how the bump reaches `main` + +After `dv version`, the manifests and CHANGELOGs are committed; the git +tags don't exist yet. How that commit gets to `main` is your team's +call — dv works the same either way. + +- **Release-on-merge (default).** The `dv version` commit is produced by + the CI job running on merge to `main`, so it's already on `main` — the + feature PR you merged *was* the review. `dv release` runs next in the + same job. There's no second PR. See the + [CI integration guide](/guides/ci-integration) for the workflow. +- **Release PR (variant).** If you want a human to approve the bump + itself, route the `dv version` commit through a PR — see below. + +### The Release PR variant + +Some teams want the version bump and CHANGELOG reviewed before anything +is tagged. To do that, run `dv version` so its commit lands on a branch, +open that branch as a PR, and merge it before running `dv release`: + +```sh +$ dv version # one commit on a release branch +# → open as a PR, review the bump + CHANGELOG, merge to main +$ dv release # only after the Release PR merges +``` -Nothing dv-specific here. Whatever your team's PR workflow is — -review, approval, merge button — applies. After the Release PR -merges to `main`, the manifests and CHANGELOGs are committed; the -git tags don't exist yet. +The commit `dv version` produces is the **Release PR** in this workflow. +Nothing dv-specific happens at merge time — whatever your team's PR +workflow is (review, approval, merge button) applies. Once it merges to +`main`, proceed to `dv release`. (`--no-commit`, below, is handy if you +want to shape the commit yourself before opening the PR.) ## Step 5: tag + publish with `dv release` diff --git a/specs/cli.md b/specs/cli.md index 068093f..bf2dd23 100644 --- a/specs/cli.md +++ b/specs/cli.md @@ -156,8 +156,9 @@ entries (and HISTORY entries when `history.enabled: true` in config), updates dependents' constraints (constraint-only cascade), and deletes the consumed Records. Auto-commits the result by default with a templated message (CC-shaped — an emission convention only; `dv` never parses -contributor commits). **Does not push.** The commit it produces is the -Release PR. +contributor commits). **Does not push.** The commit it produces lands on +`main` under release-on-merge, or is reviewed as a Release PR when a team +gates the bump. Halts on an Unresolved Reference (a Record pointing at a Package that no longer exists with no Rename edge); `--prune` drops such Records instead. diff --git a/specs/language.md b/specs/language.md index 7c7cf5d..0bea6b7 100644 --- a/specs/language.md +++ b/specs/language.md @@ -83,8 +83,11 @@ output; distinct from the Records that feed it. computed before any mutation. The single artifact shared by `dv status` and `--dry-run`. *Not: preview, diff.* -**Release PR** — the reviewable commit `dv version` produces, merged before -`dv release` runs. *Not: version commit (in user-facing text).* +**Release PR** — the reviewable commit `dv version` produces. One of two +workflows: under **release-on-merge** (the default) it lands on `main` +automatically as part of the merge; routed through a **Release PR** it is +reviewed and merged before `dv release` runs. The term names the commit in +the latter, gated workflow. *Not: version commit (in user-facing text).* --- @@ -226,8 +229,9 @@ version : Records → ΔManifests + ΔCHANGELOGs + Commit release : Manifests × Tags → ΔTags + Publishes ``` -This is why the phases can be separated by a PR review (the Release PR) and -why each is independently runnable, dry-runnable, and resumable. +This is why the phases can run back-to-back on merge (release-on-merge) or +be separated by a PR review (the Release PR), and why each is independently +runnable, dry-runnable, and resumable. ### 7. Plan determinism diff --git a/specs/v1-scope.md b/specs/v1-scope.md index 981e993..4581fe1 100644 --- a/specs/v1-scope.md +++ b/specs/v1-scope.md @@ -109,7 +109,9 @@ Not v1, but the architecture leaves room for each: - **CC-accelerator affordances** — `dv record from-commit ` / `from-range ` to draft Records from Conventional Commits history. See `design.md` § Records over commit messages. -- **GitHub Actions companion** — bot/action that maintains a Release PR. +- **GitHub Actions companion** — release-on-merge CI that runs both phases + on merge to `main` (the default), or a bot/action that maintains a Release + PR for teams gating the bump on review. See `guides/ci-integration.md`. ## Non-goals (probably forever) @@ -158,7 +160,8 @@ A user can: 2. Write a small shell-script plugin per ecosystem (or use whatever built-ins ship by then). 3. Have contributors file records via `dv add`. -4. Get a clean Release PR via `dv version`. +4. Get a clean version-bump commit via `dv version` — landed on `main` by + release-on-merge CI, or reviewed as a Release PR first. 5. Cut tags and trigger publishes via `dv release`. With SemVer adherence enforced and per-package CHANGELOGs maintained. diff --git a/specs/walkthrough.md b/specs/walkthrough.md index ccfa132..afa5d61 100644 --- a/specs/walkthrough.md +++ b/specs/walkthrough.md @@ -145,11 +145,14 @@ $ dv version ``` The consumed Records are gone from `.dv/records/`, and the whole thing -is one commit — the **Release PR**. Open it, review it, merge it. +is one commit. Under **release-on-merge** (the default workflow) that +commit lands on `main` automatically; teams that gate the bump on review +open it as a **Release PR** and merge it first. ## 6. Release (phase two) -After the Release PR merges, cut Tags and publish. `dv release` is +Once the bump commit is on `main` (directly under release-on-merge, or +after the Release PR merges), cut Tags and publish. `dv release` is **stateless**: it compares each Package's current Version to existing Tags and acts on whatever is untagged.