Skip to content

Commit e02189f

Browse files
committed
feat: implement prerelease channels
Branch-based prerelease lines where prerelease versions are never committed to git β€” derived at publish time from bump files (targets), the registry (counters), and git tags/gitHead (idempotency). Core: - channels config block (+ JSON schema): branch, preid, tag, versionPr with automerge; names validated as .bumpy/ subdirectory-safe - bump file location is the only channel state: pending at .bumpy/ root (or other channels' dirs), shipped in .bumpy/<channel>/; the general pending rule gives alpha -> beta graduation for free - release plan gains a prerelease mode: range satisfaction is checked against <target>-<preid>.0, so every dependent joins the cycle at proportional bump levels (prereleases never satisfy stable ranges) - prerelease versions: registry-floor counters (max published + 1), per-package gitHead skip for re-runs/resume, exact-pinned in-cycle deps written transiently into the working tree and restored after Commands: - version: on a channel, only moves pending files into .bumpy/<channel>/ - publish: channel flow computes + rewrites + publishes to the channel dist-tag; stable flow refuses suffixed versions when channels exist - ci release: channel branches get publish-on-move-detection (push range diff) + file-move release PRs with computed versions in the title/commit message; unknown branches are refused - ci plan/check, status, check: channel-aware (status shows the cycle; check skips channel branches and gains --base) - promotion needs no special mode: main consumes channel dirs as pending, bumps stable-to-stable, writes the consolidated changelog - GitHub releases for prerelease versions are marked --prerelease Docs updated to match (banner removed, trigger/notes/check rows aligned); changesets comparison moved to Implemented.
1 parent 2ce14e0 commit e02189f

24 files changed

Lines changed: 1769 additions & 60 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@varlock/bumpy': minor
3+
---
4+
5+
Add prerelease channels β€” branch-based prerelease lines (e.g. `next` β†’ `@next` dist-tag) where prerelease versions are never committed to git. Targets derive from bump files, counters from the registry; shipped bump files are tracked by moving them into `.bumpy/<channel>/`. Includes channel-aware `version` / `publish` / `status` / `ci release` flows, exact-pinned lockstep cycle publishes, and promotion-by-merge to stable.

β€Ždocs/cli.mdβ€Ž

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,12 @@ bumpy status --verbose
5353
| `--bump <types>` | Filter by bump type, e.g. `"major"` or `"minor,patch"` |
5454
| `--filter <names>` | Filter by package name or glob |
5555
| `--verbose` | Show bump file details and summaries |
56+
| `--channel <name>` | Channel override (default: inferred from the current branch) |
5657

5758
Exits with code `0` if releases are pending, `1` if none.
5859

60+
On a [prerelease channel](prereleases.md) branch, status shows the cycle instead: shipped vs pending bump files and the derived `-<preid>.N` versions (counters come from the registry; offline they render as `.?`).
61+
5962
## `bumpy version`
6063

6164
Consume all pending bump files and apply the release plan:
@@ -72,9 +75,12 @@ bumpy version
7275
bumpy version --commit
7376
```
7477

75-
| Flag | Description |
76-
| ---------- | --------------------------------- |
77-
| `--commit` | Commit the version changes to git |
78+
| Flag | Description |
79+
| ------------------ | ------------------------------------------------------------ |
80+
| `--commit` | Commit the version changes to git |
81+
| `--channel <name>` | Channel override (default: inferred from the current branch) |
82+
83+
On a [prerelease channel](prereleases.md) branch, `bumpy version` does something much smaller: it **moves pending bump files into `.bumpy/<channel>/`** and writes no versions and no changelogs β€” prerelease versions are derived at publish time and never committed.
7884

7985
## `bumpy publish`
8086

@@ -87,12 +93,15 @@ bumpy publish --tag beta
8793
bumpy publish --filter "@myorg/*"
8894
```
8995

90-
| Flag | Description |
91-
| ------------------ | --------------------------------------------------------- |
92-
| `--dry-run` | Preview what would be published without actually doing it |
93-
| `--tag <tag>` | npm dist-tag (e.g., `next`, `beta`) |
94-
| `--no-push` | Skip pushing git tags to the remote |
95-
| `--filter <names>` | Only publish matching packages (supports globs) |
96+
| Flag | Description |
97+
| ------------------ | ------------------------------------------------------------ |
98+
| `--dry-run` | Preview what would be published without actually doing it |
99+
| `--tag <tag>` | npm dist-tag (e.g., `next`, `beta`) |
100+
| `--no-push` | Skip pushing git tags to the remote |
101+
| `--filter <names>` | Only publish matching packages (supports globs) |
102+
| `--channel <name>` | Channel override (default: inferred from the current branch) |
103+
104+
On a [prerelease channel](prereleases.md) branch, publish derives prerelease versions (targets from the cycle's bump files, counters from the registry), transiently writes them into the working tree so pack/build see them, publishes the whole cycle to the channel's dist-tag with exact-pinned inter-cycle deps, then restores the files. Nothing version-shaped is ever committed.
96105

97106
**How bumpy detects unpublished packages:**
98107

@@ -114,12 +123,15 @@ bumpy check --hook pre-commit
114123
bumpy check --hook pre-push
115124
```
116125

117-
| Flag | Description |
118-
| ------------------- | ---------------------------------------------------------- |
119-
| `--strict` | Fail if any changed package is not covered by a bump file |
120-
| `--no-fail` | Warn only, never exit non-zero (useful for advisory hooks) |
121-
| `--hook pre-commit` | Only count staged + committed bump files |
122-
| `--hook pre-push` | Only count committed bump files |
126+
| Flag | Description |
127+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
128+
| `--strict` | Fail if any changed package is not covered by a bump file |
129+
| `--no-fail` | Warn only, never exit non-zero (useful for advisory hooks) |
130+
| `--hook pre-commit` | Only count staged + committed bump files |
131+
| `--hook pre-push` | Only count committed bump files |
132+
| `--base <branch>` | Branch to compare against (default: `baseBranch`) β€” use the channel branch for feature branches targeting a [channel](prereleases.md) |
133+
134+
The check is skipped automatically on channel branches and release PR branches (they move/consume bump files by design).
123135

124136
### Hook context
125137

@@ -240,6 +252,8 @@ bumpy ci release --auto-publish --tag beta
240252

241253
Requires `GH_TOKEN`. When `BUMPY_GH_TOKEN` is set, it is automatically used to push the version branch and create/edit the PR so that PR workflows trigger (see [GitHub Actions setup](github-actions.md#token-setup)).
242254

255+
**Channel branches:** when run on a branch configured as a [prerelease channel](prereleases.md), `ci release` switches to the channel flow β€” it publishes the cycle when the triggering push moved bump files into `.bumpy/<channel>/` (a release PR merge), and creates/updates the file-move release PR when pending bump files exist. When channels are configured and the branch is neither `baseBranch` nor a channel branch, the command exits with an error instead of guessing.
256+
243257
## `bumpy ci setup`
244258

245259
Interactive guide to set up `BUMPY_GH_TOKEN` for CI. Walks through creating a fine-grained PAT or GitHub App token and storing it as a repository secret.

β€Ždocs/configuration.mdβ€Ž

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Bumpy is configured via `.bumpy/_config.json`, created by `bumpy init`. Per-pack
2525
| `versionPr` | `{ title, branch, preamble }` | see below | Customize the version PR |
2626
| `allowCustomCommands` | `boolean \| string[]` | `false` | Allow per-package custom commands from `package.json` (see below) |
2727
| `packages` | `object` | `{}` | Per-package config overrides (keyed by package name) |
28+
| `channels` | `object` | `{}` | Prerelease channels, keyed by channel name (see below) |
2829

2930
### Dependency bump rules
3031

@@ -99,6 +100,29 @@ The `versionPr` object customizes the PR that `bumpy ci release` creates:
99100
| `branch` | `string` | `"bumpy/version-packages"` | Branch name for the version PR |
100101
| `preamble` | `string` | β€” | HTML content prepended to the PR body |
101102

103+
### Prerelease channels
104+
105+
The `channels` object maps long-lived branches to prerelease lines. See [prereleases.md](prereleases.md) for the full workflow.
106+
107+
```jsonc
108+
{
109+
"channels": {
110+
"next": {
111+
"branch": "next", // required β€” branch that triggers this channel
112+
"preid": "rc", // version suffix (default: channel name)
113+
"tag": "next", // npm dist-tag (default: channel name)
114+
"versionPr": {
115+
"title": "🐸 Versioned release (next)", // default: "<base title> (<name>)"
116+
"branch": "bumpy/version-packages-next", // default: "<base branch>-<name>"
117+
"automerge": false, // enable auto-merge on the release PR
118+
},
119+
},
120+
},
121+
}
122+
```
123+
124+
Channel names become `.bumpy/<name>/` subdirectories (holding bump files that shipped on the channel), so they must be filesystem-safe and can't start with `_` or collide with reserved entries.
125+
102126
## Per-package config
103127

104128
Per-package settings can be defined in two places:

β€Ždocs/differences-from-changesets.mdβ€Ž

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,18 @@ Bumpy replaces all of this with two CLI commands you run directly in standard wo
147147
- [changesets#1242](https://github.com/changesets/changesets/issues/1242) β€” bot/action version upgrade issues
148148
- [changesets#43](https://github.com/changesets/changesets/issues/43) β€” can't customize bot messages
149149

150+
### Prerelease channels that actually work
151+
152+
Changesets' prerelease mode is described in their own docs as "very complicated" with "mistakes that can lead to repository and publish states that are very hard to fix." Key problems: global mode state poisons unrelated merges, exiting pre bumps ALL packages, counters require committed state, dist-tags can't be controlled.
153+
154+
Bumpy replaces the mode with **branch-based channels** ([docs/prereleases.md](./prereleases.md)): a long-lived branch (e.g. `next`) maps to a prerelease line. Bump file location (`.bumpy/<channel>/`) is the only state; prerelease versions are never committed β€” targets derive from bump files, counters from the registry. Promotion to stable is just a merge.
155+
156+
- [changesets#729](https://github.com/changesets/changesets/issues/729) β€” exiting pre mode bumps all versions (14 comments)
157+
- [changesets#786](https://github.com/changesets/changesets/issues/786) β€” can't control dist-tag in pre mode (13 comments)
158+
- [changesets#635](https://github.com/changesets/changesets/issues/635) β€” prerelease workflow problems
159+
- [changesets#239](https://github.com/changesets/changesets/issues/239) β€” prerelease mode design issues
160+
- [changesets#381](https://github.com/changesets/changesets/issues/381) β€” prerelease counters require committed state
161+
150162
### Local bump file verification
151163

152164
`bumpy check` verifies that changed packages on the current branch have corresponding bump files. Compares your branch to the base branch, maps changed files to packages. By default it only fails if no bump files exist at all (matching changesets behavior). Use `--strict` to require every changed package to be covered, `--no-fail` for advisory-only mode, or `--hook pre-commit`/`--hook pre-push` to control which bump files count based on their git status. No GitHub API needed.
@@ -157,15 +169,6 @@ Changesets has no built-in equivalent β€” users rely on the CI bot comment to ca
157169

158170
## Planned / Not Yet Implemented
159171

160-
### Prerelease mode that actually works
161-
162-
Changesets' prerelease mode is described in their own docs as "very complicated" with "mistakes that can lead to repository and publish states that are very hard to fix." Key problems: no target on bump files, multi-branch corruption, exiting pre bumps ALL packages, bad interactions with linked/fixed groups.
163-
164-
- [changesets#729](https://github.com/changesets/changesets/issues/729) β€” exiting pre mode bumps all versions (14 comments)
165-
- [changesets#786](https://github.com/changesets/changesets/issues/786) β€” can't control dist-tag in pre mode (13 comments)
166-
- [changesets#635](https://github.com/changesets/changesets/issues/635) β€” prerelease workflow problems
167-
- [changesets#239](https://github.com/changesets/changesets/issues/239) β€” prerelease mode design issues
168-
169172
### Root workspace / non-package changes
170173

171174
Track changes to CI, tooling, and monorepo-root-level config in changelogs β€” not just workspace packages.

0 commit comments

Comments
Β (0)