@varlock/bumpy 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +256 -0
- package/dist/{add-BmNL5VwL.mjs → add-yP81c9_q.mjs} +5 -5
- package/dist/{ai-sMYUf3lP.mjs → ai-STKnq09z.mjs} +1 -1
- package/dist/{apply-release-plan-0kH62jhu.mjs → apply-release-plan-CPzu6JcF.mjs} +2 -2
- package/dist/{bump-file-DVqR3k67.mjs → bump-file-Br2bTaWp.mjs} +20 -8
- package/dist/{check-BjWF6SJm.mjs → check-D_0exKi6.mjs} +32 -10
- package/dist/{ci-DY58ugIi.mjs → ci-CvaikKX1.mjs} +25 -13
- package/dist/{ci-setup-BQwktQEe.mjs → ci-setup-CARJFhcE.mjs} +1 -1
- package/dist/cli.mjs +24 -17
- package/dist/{config-B-Qg3DZH.mjs → config-D7Umr-fT.mjs} +3 -3
- package/dist/{fs-DYR2XuFE.mjs → fs-DnDogVn-.mjs} +16 -1
- package/dist/{generate-DX46X-rW.mjs → generate-BOLrTYWR.mjs} +4 -4
- package/dist/index.mjs +6 -6
- package/dist/{init-DkTPs_WQ.mjs → init-DJhMaceS.mjs} +3 -3
- package/dist/{package-manager-Clsmr-9r.mjs → package-manager-ByJ0wKYh.mjs} +1 -1
- package/dist/{publish-CGB4TIKD.mjs → publish-CPZwqyWh.mjs} +5 -5
- package/dist/{publish-pipeline-CXuqce1N.mjs → publish-pipeline-BFt96o_h.mjs} +2 -2
- package/dist/{release-plan-JNir7bSM.mjs → release-plan-CNOuSI-d.mjs} +1 -1
- package/dist/{status-EGYqULJg.mjs → status-skGX8uU7.mjs} +5 -5
- package/dist/{version-BcfidiVX.mjs → version-CnXcbqi1.mjs} +6 -6
- package/dist/{workspace-DWXlwcH4.mjs → workspace-BHsAPUmC.mjs} +3 -3
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://bumpy.varlock.dev" target="_blank" rel="noopener noreferrer">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/dmno-dev/bumpy/refs/heads/main/images/github-readme-banner.png" alt="Bumpy banner">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
<br/>
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://npmjs.com/package/@varlock/bumpy"><img src="https://img.shields.io/npm/v/@varlock/bumpy.svg" alt="npm package"></a>
|
|
9
|
+
<a href="https://github.com/dmno-dev/bumpy/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@varlock/bumpy.svg" alt="license"></a>
|
|
10
|
+
<a href="https://github.com/dmno-dev/bumpy/actions/workflows/ci.yaml"><img src="https://img.shields.io/github/actions/workflow/status/dmno-dev/bumpy/ci.yaml?style=flat&logo=github&label=CI" alt="build status"></a>
|
|
11
|
+
<a href="https://chat.dmno.dev"><img src="https://img.shields.io/badge/chat-discord-5865F2?style=flat&logo=discord" alt="discord chat"></a>
|
|
12
|
+
</p>
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
# @varlock/bumpy 🐸
|
|
16
|
+
|
|
17
|
+
A modern package versioning and changelog generation tool — built for monorepos (works great in single packages too).
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
|
|
21
|
+
Bumpy uses **bump files** (you may know them as "changesets" if coming from [that tool 🦋](https://github.com/changesets/changesets)) — small markdown files that declare an intent to release packages with a bump level (patch/minor/major), and a description that ends up in changelogs. Developers create these files as part of their PRs, and these files are then used to consolidate changes, generate changelogs, and trigger publishing. Specifically:
|
|
22
|
+
|
|
23
|
+
- Devs/agents create bump files as part of their PRs (using `bumpy add` or manually)
|
|
24
|
+
- A pre-push git hook can enforce bump files exist for changed packages
|
|
25
|
+
- In CI, a workflow checks PRs for bump files, leaves a comment on the PR detailing changed packages
|
|
26
|
+
- As PRs merge to the base branch, a "release PR" is kept up to date
|
|
27
|
+
- Shows what packages will be released and their changelogs
|
|
28
|
+
— Including packages bumped automatically due to dependency relationships
|
|
29
|
+
- When release PR is merged, publishing is triggered
|
|
30
|
+
- Oending bump files are deleted and packages are published with updated versions and changelogs
|
|
31
|
+
|
|
32
|
+
All of this is automated via two simple GitHub Actions workflows (see [CI setup](#ci--github-actions) below). You can also run everything locally with `bumpy status`, `bumpy version`, and `bumpy publish`.
|
|
33
|
+
|
|
34
|
+
### Example bump file
|
|
35
|
+
|
|
36
|
+
`.bumpy/add-user-language.md`:
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
---
|
|
40
|
+
'@myorg/core': minor
|
|
41
|
+
'@myorg/utils': patch
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
Added user language preference to the core config.
|
|
45
|
+
Fixed locale fallback logic in utils.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **All package managers** — npm, pnpm, yarn, and bun workspaces
|
|
51
|
+
- **Smart dependency propagation** — configurable rules for how version bumps cascade through your dependency graph (see [version propagation docs](https://github.com/dmno-dev/bumpy/blob/main/docs/version-propagation.md))
|
|
52
|
+
- **Pack-then-publish** — by default, publishes to npm (resolving `workspace:` and `catalog:` protocols, with OIDC/provenance support). Per-package custom publish commands let you target anything — VSCode extensions, Docker images, JSR, private registries, etc.
|
|
53
|
+
- **Flexible package management** — include/exclude any package individually via per-package config, glob patterns, or `privatePackages` setting
|
|
54
|
+
- **Non-interactive CLI** — `bumpy add` works fully non-interactively for CI/CD and AI-assisted development
|
|
55
|
+
- **Aggregated GitHub releases** — optionally create a single consolidated release instead of one per package
|
|
56
|
+
- **Auto-generate from commits** — `bumpy generate` creates bump files from branch commits — works with any commit style, with enhanced detection for conventional commits
|
|
57
|
+
- **Pluggable changelog formatters** — built-in `"default"` and `"github"` formatters, or write your own
|
|
58
|
+
- **Zero runtime dependencies** — dependencies are minimal and bundled at release time
|
|
59
|
+
|
|
60
|
+
## Getting Started
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Install
|
|
64
|
+
bun add -d @varlock/bumpy # or npm/pnpm/yarn
|
|
65
|
+
|
|
66
|
+
# Initialize (creates .bumpy/ directory and config, migrates from changesets if applicable)
|
|
67
|
+
bunx bumpy init
|
|
68
|
+
|
|
69
|
+
# Create a bump file
|
|
70
|
+
bunx bumpy add
|
|
71
|
+
|
|
72
|
+
# Preview the release plan
|
|
73
|
+
bunx bumpy status
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Then set up CI to automate versioning and publishing (see below).
|
|
77
|
+
|
|
78
|
+
## CI / GitHub Actions
|
|
79
|
+
|
|
80
|
+
No separate action to rely on — just call `bumpy ci` directly in your workflows. Two commands handle the entire release lifecycle:
|
|
81
|
+
|
|
82
|
+
- **`bumpy ci check`** — runs on every PR. Computes the release plan from pending bump files and posts/updates a comment on the PR showing what versions would be released. Warns if any changed packages are missing bump files.
|
|
83
|
+
- **`bumpy ci release`** — runs on push to main. If pending bump files exist, it opens (or updates) a "Version Packages" PR that applies all version bumps and changelog updates. If the current push _is_ the Version Packages PR being merged, it publishes the new versions, creates git tags, and creates GitHub releases.
|
|
84
|
+
|
|
85
|
+
_examples use bun, but works with Node.js_
|
|
86
|
+
|
|
87
|
+
### PR check workflow
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
# .github/workflows/bumpy-check.yml
|
|
91
|
+
name: Bumpy Check
|
|
92
|
+
on: pull_request
|
|
93
|
+
|
|
94
|
+
jobs:
|
|
95
|
+
check:
|
|
96
|
+
runs-on: ubuntu-latest
|
|
97
|
+
permissions:
|
|
98
|
+
pull-requests: write
|
|
99
|
+
steps:
|
|
100
|
+
- uses: actions/checkout@v6
|
|
101
|
+
- uses: oven-sh/setup-bun@v2
|
|
102
|
+
- run: bun install
|
|
103
|
+
- run: bunx @varlock/bumpy ci check
|
|
104
|
+
env:
|
|
105
|
+
GH_TOKEN: ${{ github.token }}
|
|
106
|
+
BUMPY_GH_TOKEN: ${{ secrets.BUMPY_GH_TOKEN }} # additional PAT (optional)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Release workflow
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
# .github/workflows/bumpy-release.yml — trusted publishing (OIDC, no secret needed)
|
|
113
|
+
name: Bumpy Release
|
|
114
|
+
on:
|
|
115
|
+
push:
|
|
116
|
+
branches: [main]
|
|
117
|
+
|
|
118
|
+
jobs:
|
|
119
|
+
release:
|
|
120
|
+
runs-on: ubuntu-latest
|
|
121
|
+
permissions:
|
|
122
|
+
contents: write
|
|
123
|
+
pull-requests: write
|
|
124
|
+
id-token: write # required for npm trusted publishing (OIDC)
|
|
125
|
+
steps:
|
|
126
|
+
- uses: actions/checkout@v6
|
|
127
|
+
with:
|
|
128
|
+
fetch-depth: 0
|
|
129
|
+
- uses: oven-sh/setup-bun@v2
|
|
130
|
+
- uses: actions/setup-node@v6
|
|
131
|
+
with:
|
|
132
|
+
node-version: lts/*
|
|
133
|
+
- run: bun install
|
|
134
|
+
- run: bunx @varlock/bumpy ci release
|
|
135
|
+
env:
|
|
136
|
+
GH_TOKEN: ${{ github.token }}
|
|
137
|
+
BUMPY_GH_TOKEN: ${{ secrets.BUMPY_GH_TOKEN }} # additonal PAT, needed to trigger CI checks on release PR
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> **Trusted publishing setup:** Configure each package on [npmjs.com](https://docs.npmjs.com/trusted-publishers/) → Package Settings → Trusted Publishers → GitHub Actions. Specify your org/user, repo, and the workflow filename (`bumpy-release.yml`). No `NPM_TOKEN` secret needed. Requires npm >= 11.5.1 — bumpy will warn if your version is too old.
|
|
141
|
+
|
|
142
|
+
<details>
|
|
143
|
+
<summary>Alternative: token-based auth (NPM_TOKEN secret)</summary>
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
# .github/workflows/bumpy-release.yml — token-based auth
|
|
147
|
+
name: Bumpy Release
|
|
148
|
+
on:
|
|
149
|
+
push:
|
|
150
|
+
branches: [main]
|
|
151
|
+
|
|
152
|
+
jobs:
|
|
153
|
+
release:
|
|
154
|
+
runs-on: ubuntu-latest
|
|
155
|
+
permissions:
|
|
156
|
+
contents: write
|
|
157
|
+
pull-requests: write
|
|
158
|
+
steps:
|
|
159
|
+
- uses: actions/checkout@v6
|
|
160
|
+
with:
|
|
161
|
+
fetch-depth: 0
|
|
162
|
+
- uses: oven-sh/setup-bun@v2
|
|
163
|
+
- run: bun install
|
|
164
|
+
- run: bunx @varlock/bumpy ci release
|
|
165
|
+
env:
|
|
166
|
+
GH_TOKEN: ${{ github.token }}
|
|
167
|
+
BUMPY_GH_TOKEN: ${{ secrets.BUMPY_GH_TOKEN }}
|
|
168
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
</details>
|
|
172
|
+
|
|
173
|
+
You can also use `bumpy ci release --auto-publish` to version + publish directly on merge without the intermediate PR.
|
|
174
|
+
|
|
175
|
+
### Token setup
|
|
176
|
+
|
|
177
|
+
The default `github.token` works for basic functionality, but GitHub's anti-recursion guard means PRs created by the default token won't trigger other workflows — so your regular CI (tests, linting, etc.) won't run automatically on the Version Packages PR. To fix this, provide a `BUMPY_GH_TOKEN` secret using either a **fine-grained PAT** or a **GitHub App token**. See the [full token setup guide](https://github.com/dmno-dev/bumpy/blob/main/docs/github-actions.md#token-setup) for details.
|
|
178
|
+
|
|
179
|
+
Run `bumpy ci setup` for interactive guidance, or set it up manually:
|
|
180
|
+
|
|
181
|
+
1. Create a [fine-grained personal access token](https://github.com/settings/personal-access-tokens) with:
|
|
182
|
+
- **Repository access:** your repo only
|
|
183
|
+
- **Permissions:** Contents (read & write), Pull requests (read & write)
|
|
184
|
+
2. Add it as a repository secret named `BUMPY_GH_TOKEN`
|
|
185
|
+
3. Add it to your release workflow:
|
|
186
|
+
```yaml
|
|
187
|
+
- run: bunx @varlock/bumpy ci release
|
|
188
|
+
env:
|
|
189
|
+
GH_TOKEN: ${{ github.token }}
|
|
190
|
+
BUMPY_GH_TOKEN: ${{ secrets.BUMPY_GH_TOKEN }}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Local versioning and publishing
|
|
194
|
+
|
|
195
|
+
If you prefer to version and publish locally instead of via CI:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
bumpy version # consume bump files, update versions and changelogs
|
|
199
|
+
bumpy publish # pack and publish, create git tags, push tags, and create GitHub releases
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## AI Integration
|
|
203
|
+
|
|
204
|
+
Bumpy ships with an AI skill that teaches LLMs how to create bump files.
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
bumpy ai setup --target claude # installs Claude Code plugin
|
|
208
|
+
bumpy ai setup --target opencode # creates OpenCode command file
|
|
209
|
+
bumpy ai setup --target cursor # creates Cursor rule file
|
|
210
|
+
bumpy ai setup --target codex # creates Codex instruction file
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The skill teaches the AI to examine git changes, identify affected packages, choose bump levels, and create bump files with `bumpy add`. It also instructs the AI to keep existing bump files up to date as work continues on a branch — updating packages, bump levels, and summaries to reflect the final state of changes.
|
|
214
|
+
|
|
215
|
+
## Documentation
|
|
216
|
+
|
|
217
|
+
- [Bump file format](https://github.com/dmno-dev/bumpy/blob/main/docs/bump-files.md) — syntax, bump levels, cascade control
|
|
218
|
+
- [Configuration reference](https://github.com/dmno-dev/bumpy/blob/main/docs/configuration.md) — all `.bumpy/_config.json` and per-package options
|
|
219
|
+
- [CLI reference](https://github.com/dmno-dev/bumpy/blob/main/docs/cli.md) — every command with flags and examples
|
|
220
|
+
- [GitHub Actions setup](https://github.com/dmno-dev/bumpy/blob/main/docs/github-actions.md) — CI workflows, token setup, trusted publishing
|
|
221
|
+
- [Version propagation](https://github.com/dmno-dev/bumpy/blob/main/docs/version-propagation.md) — how dependency bumps cascade through your graph
|
|
222
|
+
|
|
223
|
+
## Why files instead of conventional commits?
|
|
224
|
+
|
|
225
|
+
Tools like semantic-release infer version bumps from commit messages (`feat:` → minor, `fix:` → patch). This works for simple projects but breaks down in monorepos — a single PR often touches multiple packages with different bump levels, squash merges lose per-commit metadata, and commit messages are a poor place to write user-facing changelog entries. Bump files are explicit, reviewable in the PR diff, and can describe changes in language meant for consumers rather than developers. If you prefer commit-based workflows, `bumpy generate` can bridge the gap by auto-creating bump files from your branch commits — it works with any commit style, not just conventional commits.
|
|
226
|
+
|
|
227
|
+
## Why not just use changesets?
|
|
228
|
+
|
|
229
|
+
Bumpy is built as a successor to [@changesets/changesets](https://github.com/changesets/changesets). Changesets is mature and widely adopted, but has stagnated — hundreds of open issues around core design problems that are unlikely to be fixed without a rewrite. See [differences from changesets](https://github.com/dmno-dev/bumpy/blob/main/docs/differences-from-changesets.md) for a detailed comparison with links to specific issues. The biggest pain points bumpy addresses:
|
|
230
|
+
|
|
231
|
+
- **Sane dependency propagation** — changesets hardcodes aggressive behavior where a minor bump triggers a major bump on all peer dependents. Bumpy uses a [three-phase algorithm](https://github.com/dmno-dev/bumpy/blob/main/docs/version-propagation.md) with sensible defaults and full configurability.
|
|
232
|
+
- **Workspace protocol resolution** — changesets uses `npm publish` even in pnpm/yarn workspaces, so `workspace:^` and `catalog:` protocols are NOT resolved, resulting in broken published packages.
|
|
233
|
+
- **Custom publish commands** — changesets is hardcoded to `npm publish`. Bumpy supports per-package custom publish for VSCode extensions, Docker images, JSR, etc.
|
|
234
|
+
- **Flexible package management** — changesets treats all private packages the same. Bumpy lets you include/exclude any package individually.
|
|
235
|
+
- **CI without a separate action** — just `bunx @varlock/bumpy ci check` in any workflow, no bot or action to install.
|
|
236
|
+
- **Automatic migration** — `bumpy init` detects `.changeset/`, renames it to `.bumpy/`, migrates config, keeps pending files, and offers to uninstall `@changesets/cli`.
|
|
237
|
+
|
|
238
|
+
## Development
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
bun install # install deps
|
|
242
|
+
bun test # run tests
|
|
243
|
+
bun run build # build CLI
|
|
244
|
+
bunx bumpy --help # invoke built cli
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Roadmap
|
|
248
|
+
|
|
249
|
+
- Prerelease mode (for now, use [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for branch preview packages)
|
|
250
|
+
- Standalone binary for use outside of JS projects
|
|
251
|
+
- Better support for versioning non-JS packages and usage without package.json files
|
|
252
|
+
- Plugin system for different publish targets, and support multiple targets per package
|
|
253
|
+
- Tracking workspace-level / non-publishable changes
|
|
254
|
+
- More frogs 🐸
|
|
255
|
+
|
|
256
|
+
<!-- note this readme is also used for the bumpy package! -->
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { n as exists, t as ensureDir } from "./fs-
|
|
3
|
-
import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir, s as matchGlob } from "./config-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
2
|
+
import { n as exists, t as ensureDir } from "./fs-DnDogVn-.mjs";
|
|
3
|
+
import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir, s as matchGlob } from "./config-D7Umr-fT.mjs";
|
|
4
|
+
import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
6
|
-
import { i as writeBumpFile } from "./bump-file-
|
|
6
|
+
import { i as writeBumpFile } from "./bump-file-Br2bTaWp.mjs";
|
|
7
7
|
import { r as getChangedFiles } from "./git-YDedMddc.mjs";
|
|
8
8
|
import { c as ot, d as yt, i as _t, l as pt, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-C6bVkGxf.mjs";
|
|
9
9
|
import { n as slugify, t as randomName } from "./names-C-TuOPbd.mjs";
|
|
@@ -186,7 +186,7 @@ async function addCommand(rootDir, opts) {
|
|
|
186
186
|
if (opts.empty) {
|
|
187
187
|
const filename = opts.name ? slugify(opts.name) : randomName();
|
|
188
188
|
const filePath = resolve(bumpyDir, `${filename}.md`);
|
|
189
|
-
const { writeText } = await import("./fs-
|
|
189
|
+
const { writeText } = await import("./fs-DnDogVn-.mjs").then((n) => n.r);
|
|
190
190
|
await writeText(filePath, "---\n---\n");
|
|
191
191
|
log.success(`🐸 Created empty bump file: .bumpy/${filename}.md`);
|
|
192
192
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as log } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { f as writeText, n as exists, t as ensureDir } from "./fs-DnDogVn-.mjs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
5
|
import { execSync } from "node:child_process";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as log } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as readJson, c as
|
|
3
|
-
import { r as getBumpyDir } from "./config-
|
|
2
|
+
import { a as readJson, c as removeFile, f as writeText, i as listFiles, l as updateJsonFields, n as exists, s as readText, u as updateJsonNestedField } from "./fs-DnDogVn-.mjs";
|
|
3
|
+
import { r as getBumpyDir } from "./config-D7Umr-fT.mjs";
|
|
4
4
|
import { relative, resolve } from "node:path";
|
|
5
5
|
import { realpathSync } from "node:fs";
|
|
6
6
|
//#region src/core/changelog.ts
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { n as log } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { r as getBumpyDir } from "./config-
|
|
4
|
-
import { i as jsYaml } from "./package-manager-
|
|
2
|
+
import { f as writeText, i as listFiles, s as readText } from "./fs-DnDogVn-.mjs";
|
|
3
|
+
import { r as getBumpyDir } from "./config-D7Umr-fT.mjs";
|
|
4
|
+
import { i as jsYaml } from "./package-manager-ByJ0wKYh.mjs";
|
|
5
5
|
import { s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
7
8
|
//#region src/core/bump-file.ts
|
|
8
9
|
const VALID_BUMP_TYPES = new Set([
|
|
9
10
|
"major",
|
|
@@ -143,14 +144,25 @@ function extractBumpFileIdsFromChangedFiles(changedFiles) {
|
|
|
143
144
|
}
|
|
144
145
|
/**
|
|
145
146
|
* Filter bump files to only those added/modified on the current branch.
|
|
146
|
-
*
|
|
147
|
-
*
|
|
147
|
+
* Also detects empty bump files (no releases) that still exist on disk,
|
|
148
|
+
* which signal intentionally no releases needed.
|
|
148
149
|
*/
|
|
149
|
-
function filterBranchBumpFiles(allBumpFiles, changedFiles) {
|
|
150
|
+
function filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir) {
|
|
150
151
|
const branchBumpFileIds = extractBumpFileIdsFromChangedFiles(changedFiles);
|
|
152
|
+
const branchBumpFiles = allBumpFiles.filter((bf) => branchBumpFileIds.has(bf.id));
|
|
153
|
+
let hasEmptyBumpFile = false;
|
|
154
|
+
if (rootDir) {
|
|
155
|
+
const parsedIds = new Set(branchBumpFiles.map((bf) => bf.id));
|
|
156
|
+
const bumpyDir = getBumpyDir(rootDir);
|
|
157
|
+
for (const id of branchBumpFileIds) if (!parsedIds.has(id) && existsSync(resolve(bumpyDir, `${id}.md`))) {
|
|
158
|
+
hasEmptyBumpFile = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
151
162
|
return {
|
|
152
|
-
branchBumpFiles
|
|
153
|
-
branchBumpFileIds
|
|
163
|
+
branchBumpFiles,
|
|
164
|
+
branchBumpFileIds,
|
|
165
|
+
hasEmptyBumpFile
|
|
154
166
|
};
|
|
155
167
|
}
|
|
156
168
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as log, o as __toESM, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig, o as loadPackageConfig } from "./config-
|
|
3
|
-
import { n as discoverWorkspace } from "./workspace-
|
|
4
|
-
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-
|
|
2
|
+
import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir } from "./config-D7Umr-fT.mjs";
|
|
3
|
+
import { n as discoverWorkspace } from "./workspace-BHsAPUmC.mjs";
|
|
4
|
+
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-Br2bTaWp.mjs";
|
|
5
5
|
import { r as getChangedFiles } from "./git-YDedMddc.mjs";
|
|
6
6
|
import { t as require_picomatch } from "./picomatch-DMmqYjgq.mjs";
|
|
7
7
|
import { relative } from "node:path";
|
|
@@ -11,8 +11,12 @@ var import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
|
|
|
11
11
|
* Local check: detect which packages have changed on this branch
|
|
12
12
|
* and verify they have corresponding bump files.
|
|
13
13
|
* Designed for pre-push hooks — no GitHub API needed.
|
|
14
|
+
*
|
|
15
|
+
* Default: at least one bump file must exist, uncovered packages are warned.
|
|
16
|
+
* --strict: every changed package must be covered.
|
|
17
|
+
* --no-fail: warn only, never exit 1.
|
|
14
18
|
*/
|
|
15
|
-
async function checkCommand(rootDir) {
|
|
19
|
+
async function checkCommand(rootDir, opts = {}) {
|
|
16
20
|
const config = await loadConfig(rootDir);
|
|
17
21
|
const { packages } = await discoverWorkspace(rootDir, config);
|
|
18
22
|
const baseBranch = config.baseBranch;
|
|
@@ -21,8 +25,8 @@ async function checkCommand(rootDir) {
|
|
|
21
25
|
log.info("No changed files detected.");
|
|
22
26
|
return;
|
|
23
27
|
}
|
|
24
|
-
const { branchBumpFiles,
|
|
25
|
-
if (
|
|
28
|
+
const { branchBumpFiles, hasEmptyBumpFile } = filterBranchBumpFiles(await readBumpFiles(rootDir), changedFiles, rootDir);
|
|
29
|
+
if (hasEmptyBumpFile) {
|
|
26
30
|
log.success("Empty bump file found — no releases needed.");
|
|
27
31
|
return;
|
|
28
32
|
}
|
|
@@ -33,16 +37,34 @@ async function checkCommand(rootDir) {
|
|
|
33
37
|
log.info("No managed packages have changed.");
|
|
34
38
|
return;
|
|
35
39
|
}
|
|
40
|
+
const willFailNoBump = !opts.noFail;
|
|
41
|
+
if (branchBumpFiles.length === 0) {
|
|
42
|
+
(willFailNoBump ? log.error : log.warn)(`${changedPackages.length} changed package(s) missing bump files:\n`);
|
|
43
|
+
for (const name of changedPackages) console.log(` ${colorize(name, "yellow")}`);
|
|
44
|
+
console.log();
|
|
45
|
+
log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
|
|
46
|
+
log.dim("To adjust which files trigger change detection, set `changedFilePatterns` in .bumpy/_config.json.");
|
|
47
|
+
if (willFailNoBump) process.exit(1);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
36
50
|
const missing = changedPackages.filter((name) => !coveredPackages.has(name));
|
|
37
51
|
if (missing.length === 0) {
|
|
38
52
|
log.success(`🐸 All ${changedPackages.length} changed package(s) have bump files.`);
|
|
39
53
|
return;
|
|
40
54
|
}
|
|
41
|
-
|
|
55
|
+
const willFailUncovered = opts.strict && !opts.noFail;
|
|
56
|
+
(willFailUncovered ? log.error : log.warn)(`${missing.length} changed package(s) missing bump files:\n`);
|
|
42
57
|
for (const name of missing) console.log(` ${colorize(name, "yellow")}`);
|
|
58
|
+
if (branchBumpFiles.length > 0) {
|
|
59
|
+
console.log();
|
|
60
|
+
log.dim(`Existing bump files on this branch:`);
|
|
61
|
+
for (const bf of branchBumpFiles) log.dim(` ${getBumpyDir(rootDir)}/${bf.id}.md`);
|
|
62
|
+
}
|
|
43
63
|
console.log();
|
|
44
|
-
log.dim("Run `bumpy add` to create a bump file
|
|
45
|
-
|
|
64
|
+
if (opts.strict) log.dim("Run `bumpy add` to create a bump file. Use bump type `none` for packages that changed but don't need a release.");
|
|
65
|
+
else log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
|
|
66
|
+
log.dim("To adjust which files trigger change detection, set `changedFilePatterns` in .bumpy/_config.json.");
|
|
67
|
+
if (willFailUncovered) process.exit(1);
|
|
46
68
|
}
|
|
47
69
|
/** Map changed files to the packages they belong to */
|
|
48
70
|
async function findChangedPackages(changedFiles, packages, rootDir, config) {
|
|
@@ -62,4 +84,4 @@ async function findChangedPackages(changedFiles, packages, rootDir, config) {
|
|
|
62
84
|
return [...changed];
|
|
63
85
|
}
|
|
64
86
|
//#endregion
|
|
65
|
-
export { checkCommand };
|
|
87
|
+
export { checkCommand, findChangedPackages };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { t as detectPackageManager } from "./package-manager-
|
|
4
|
-
import { n as discoverWorkspace } from "./workspace-
|
|
2
|
+
import { a as loadConfig } from "./config-D7Umr-fT.mjs";
|
|
3
|
+
import { t as detectPackageManager } from "./package-manager-ByJ0wKYh.mjs";
|
|
4
|
+
import { n as discoverWorkspace } from "./workspace-BHsAPUmC.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
6
6
|
import { n as runArgs, r as runArgsAsync, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
7
|
-
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-
|
|
8
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
7
|
+
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-Br2bTaWp.mjs";
|
|
8
|
+
import { t as assembleReleasePlan } from "./release-plan-CNOuSI-d.mjs";
|
|
9
9
|
import { r as getChangedFiles } from "./git-YDedMddc.mjs";
|
|
10
10
|
import { t as randomName } from "./names-C-TuOPbd.mjs";
|
|
11
|
+
import { findChangedPackages } from "./check-D_0exKi6.mjs";
|
|
11
12
|
import { t as resolveCommitMessage } from "./commit-message-BwsowSds.mjs";
|
|
12
13
|
import { createHash } from "node:crypto";
|
|
13
14
|
//#region src/commands/ci.ts
|
|
@@ -87,16 +88,20 @@ async function ciCheckCommand(rootDir, opts) {
|
|
|
87
88
|
const shouldComment = opts.comment ?? inCI;
|
|
88
89
|
const prNumber = detectPrNumber();
|
|
89
90
|
const pm = await detectPackageManager(rootDir);
|
|
90
|
-
const
|
|
91
|
-
|
|
91
|
+
const changedFiles = getChangedFiles(rootDir, config.baseBranch);
|
|
92
|
+
const { branchBumpFiles: prBumpFiles, hasEmptyBumpFile } = filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir);
|
|
93
|
+
if (hasEmptyBumpFile) {
|
|
92
94
|
log.success("Empty bump file found — no releases needed.");
|
|
93
95
|
if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoBumpFilesComment(detectPrBranch(rootDir), pm), rootDir, opts.patComments);
|
|
94
96
|
return;
|
|
95
97
|
}
|
|
96
98
|
if (prBumpFiles.length === 0) {
|
|
97
|
-
|
|
99
|
+
const willFail = !opts.noFail;
|
|
100
|
+
const msg = "No bump files found in this PR.";
|
|
101
|
+
if (willFail) log.error(msg);
|
|
102
|
+
else log.warn(msg);
|
|
98
103
|
if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoBumpFilesComment(detectPrBranch(rootDir), pm), rootDir, opts.patComments);
|
|
99
|
-
if (
|
|
104
|
+
if (willFail) process.exit(1);
|
|
100
105
|
return;
|
|
101
106
|
}
|
|
102
107
|
const plan = assembleReleasePlan(prBumpFiles, packages, depGraph, config);
|
|
@@ -107,6 +112,13 @@ async function ciCheckCommand(rootDir, opts) {
|
|
|
107
112
|
}
|
|
108
113
|
if (plan.warnings.length > 0) for (const w of plan.warnings) log.warn(w);
|
|
109
114
|
if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatReleasePlanComment(plan, prBumpFiles, prNumber, detectPrBranch(rootDir), pm, plan.warnings), rootDir, opts.patComments);
|
|
115
|
+
const coveredPackages = new Set(plan.releases.map((r) => r.name));
|
|
116
|
+
const missing = (await findChangedPackages(changedFiles, packages, rootDir, config)).filter((name) => !coveredPackages.has(name));
|
|
117
|
+
if (missing.length > 0) {
|
|
118
|
+
const willFail = opts.strict && !opts.noFail;
|
|
119
|
+
(willFail ? log.error : log.warn)(`${missing.length} changed package(s) not covered by bump files: ${missing.join(", ")}`);
|
|
120
|
+
if (willFail) process.exit(1);
|
|
121
|
+
}
|
|
110
122
|
}
|
|
111
123
|
/**
|
|
112
124
|
* CI release: either auto-publish or create a version PR.
|
|
@@ -120,7 +132,7 @@ async function ciReleaseCommand(rootDir, opts) {
|
|
|
120
132
|
const bumpFiles = await readBumpFiles(rootDir);
|
|
121
133
|
if (bumpFiles.length === 0) {
|
|
122
134
|
log.info("No pending bump files — checking for unpublished packages...");
|
|
123
|
-
const { publishCommand } = await import("./publish-
|
|
135
|
+
const { publishCommand } = await import("./publish-CPZwqyWh.mjs");
|
|
124
136
|
await publishCommand(rootDir, { tag: opts.tag });
|
|
125
137
|
return;
|
|
126
138
|
}
|
|
@@ -134,7 +146,7 @@ async function ciReleaseCommand(rootDir, opts) {
|
|
|
134
146
|
}
|
|
135
147
|
async function autoPublish(rootDir, config, plan, tag) {
|
|
136
148
|
log.step("Running bumpy version...");
|
|
137
|
-
const { versionCommand } = await import("./version-
|
|
149
|
+
const { versionCommand } = await import("./version-CnXcbqi1.mjs");
|
|
138
150
|
await versionCommand(rootDir);
|
|
139
151
|
log.step("Committing version changes...");
|
|
140
152
|
runArgs([
|
|
@@ -163,7 +175,7 @@ async function autoPublish(rootDir, config, plan, tag) {
|
|
|
163
175
|
], { cwd: rootDir });
|
|
164
176
|
}
|
|
165
177
|
log.step("Running bumpy publish...");
|
|
166
|
-
const { publishCommand } = await import("./publish-
|
|
178
|
+
const { publishCommand } = await import("./publish-CPZwqyWh.mjs");
|
|
167
179
|
await publishCommand(rootDir, { tag });
|
|
168
180
|
}
|
|
169
181
|
/**
|
|
@@ -329,7 +341,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
|
|
|
329
341
|
branch
|
|
330
342
|
], { cwd: rootDir });
|
|
331
343
|
log.step("Running bumpy version...");
|
|
332
|
-
const { versionCommand } = await import("./version-
|
|
344
|
+
const { versionCommand } = await import("./version-CnXcbqi1.mjs");
|
|
333
345
|
await versionCommand(rootDir);
|
|
334
346
|
runArgs([
|
|
335
347
|
"git",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { t as detectPackageManager } from "./package-manager-
|
|
2
|
+
import { t as detectPackageManager } from "./package-manager-ByJ0wKYh.mjs";
|
|
3
3
|
import { s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
4
4
|
import { a as fe, c as ot, i as _t, n as O, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-C6bVkGxf.mjs";
|
|
5
5
|
//#region src/commands/ci-setup.ts
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
3
|
-
import { n as findRoot } from "./config-
|
|
3
|
+
import { n as findRoot } from "./config-D7Umr-fT.mjs";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
const args = process.argv.slice(2);
|
|
6
6
|
const command = args[0];
|
|
@@ -25,13 +25,13 @@ async function main() {
|
|
|
25
25
|
switch (command) {
|
|
26
26
|
case "init": {
|
|
27
27
|
const rootDir = await findRoot();
|
|
28
|
-
const { initCommand } = await import("./init-
|
|
28
|
+
const { initCommand } = await import("./init-DJhMaceS.mjs");
|
|
29
29
|
await initCommand(rootDir, { force: flags.force === true });
|
|
30
30
|
break;
|
|
31
31
|
}
|
|
32
32
|
case "add": {
|
|
33
33
|
const rootDir = await findRoot();
|
|
34
|
-
const { addCommand } = await import("./add-
|
|
34
|
+
const { addCommand } = await import("./add-yP81c9_q.mjs");
|
|
35
35
|
await addCommand(rootDir, {
|
|
36
36
|
packages: flags.packages,
|
|
37
37
|
message: flags.message,
|
|
@@ -42,7 +42,7 @@ async function main() {
|
|
|
42
42
|
}
|
|
43
43
|
case "status": {
|
|
44
44
|
const rootDir = await findRoot();
|
|
45
|
-
const { statusCommand } = await import("./status-
|
|
45
|
+
const { statusCommand } = await import("./status-skGX8uU7.mjs");
|
|
46
46
|
await statusCommand(rootDir, {
|
|
47
47
|
json: flags.json === true,
|
|
48
48
|
packagesOnly: flags.packages === true,
|
|
@@ -54,13 +54,13 @@ async function main() {
|
|
|
54
54
|
}
|
|
55
55
|
case "version": {
|
|
56
56
|
const rootDir = await findRoot();
|
|
57
|
-
const { versionCommand } = await import("./version-
|
|
57
|
+
const { versionCommand } = await import("./version-CnXcbqi1.mjs");
|
|
58
58
|
await versionCommand(rootDir, { commit: flags.commit === true });
|
|
59
59
|
break;
|
|
60
60
|
}
|
|
61
61
|
case "generate": {
|
|
62
62
|
const rootDir = await findRoot();
|
|
63
|
-
const { generateCommand } = await import("./generate-
|
|
63
|
+
const { generateCommand } = await import("./generate-BOLrTYWR.mjs");
|
|
64
64
|
await generateCommand(rootDir, {
|
|
65
65
|
from: flags.from,
|
|
66
66
|
dryRun: flags["dry-run"] === true,
|
|
@@ -70,8 +70,11 @@ async function main() {
|
|
|
70
70
|
}
|
|
71
71
|
case "check": {
|
|
72
72
|
const rootDir = await findRoot();
|
|
73
|
-
const { checkCommand } = await import("./check-
|
|
74
|
-
await checkCommand(rootDir
|
|
73
|
+
const { checkCommand } = await import("./check-D_0exKi6.mjs");
|
|
74
|
+
await checkCommand(rootDir, {
|
|
75
|
+
strict: flags.strict === true,
|
|
76
|
+
noFail: flags["no-fail"] === true
|
|
77
|
+
});
|
|
75
78
|
break;
|
|
76
79
|
}
|
|
77
80
|
case "ci": {
|
|
@@ -79,14 +82,15 @@ async function main() {
|
|
|
79
82
|
const subcommand = args[1];
|
|
80
83
|
const ciFlags = parseFlags(args.slice(2));
|
|
81
84
|
if (subcommand === "check") {
|
|
82
|
-
const { ciCheckCommand } = await import("./ci-
|
|
85
|
+
const { ciCheckCommand } = await import("./ci-CvaikKX1.mjs");
|
|
83
86
|
await ciCheckCommand(rootDir, {
|
|
84
87
|
comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
|
|
85
|
-
|
|
88
|
+
strict: ciFlags.strict === true,
|
|
89
|
+
noFail: ciFlags["no-fail"] === true,
|
|
86
90
|
patComments: ciFlags["pat-comments"] === true
|
|
87
91
|
});
|
|
88
92
|
} else if (subcommand === "release") {
|
|
89
|
-
const { ciReleaseCommand } = await import("./ci-
|
|
93
|
+
const { ciReleaseCommand } = await import("./ci-CvaikKX1.mjs");
|
|
90
94
|
await ciReleaseCommand(rootDir, {
|
|
91
95
|
mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
|
|
92
96
|
tag: ciFlags.tag,
|
|
@@ -94,7 +98,7 @@ async function main() {
|
|
|
94
98
|
patPr: ciFlags["pat-pr"] === true
|
|
95
99
|
});
|
|
96
100
|
} else if (subcommand === "setup") {
|
|
97
|
-
const { ciSetupCommand } = await import("./ci-setup-
|
|
101
|
+
const { ciSetupCommand } = await import("./ci-setup-CARJFhcE.mjs");
|
|
98
102
|
await ciSetupCommand(rootDir);
|
|
99
103
|
} else {
|
|
100
104
|
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
@@ -104,7 +108,7 @@ async function main() {
|
|
|
104
108
|
}
|
|
105
109
|
case "publish": {
|
|
106
110
|
const rootDir = await findRoot();
|
|
107
|
-
const { publishCommand } = await import("./publish-
|
|
111
|
+
const { publishCommand } = await import("./publish-CPZwqyWh.mjs");
|
|
108
112
|
await publishCommand(rootDir, {
|
|
109
113
|
dryRun: flags["dry-run"] === true,
|
|
110
114
|
tag: flags.tag,
|
|
@@ -118,7 +122,7 @@ async function main() {
|
|
|
118
122
|
const subcommand = args[1];
|
|
119
123
|
const aiFlags = parseFlags(args.slice(2));
|
|
120
124
|
if (subcommand === "setup") {
|
|
121
|
-
const { aiSetupCommand } = await import("./ai-
|
|
125
|
+
const { aiSetupCommand } = await import("./ai-STKnq09z.mjs");
|
|
122
126
|
await aiSetupCommand(rootDir, { target: aiFlags.target });
|
|
123
127
|
} else {
|
|
124
128
|
log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`);
|
|
@@ -128,7 +132,7 @@ async function main() {
|
|
|
128
132
|
}
|
|
129
133
|
case "--version":
|
|
130
134
|
case "-v":
|
|
131
|
-
console.log(`bumpy 1.
|
|
135
|
+
console.log(`bumpy 1.2.0`);
|
|
132
136
|
break;
|
|
133
137
|
case "help":
|
|
134
138
|
case "--help":
|
|
@@ -148,7 +152,7 @@ async function main() {
|
|
|
148
152
|
}
|
|
149
153
|
function printHelp() {
|
|
150
154
|
console.log(`
|
|
151
|
-
${colorize(`🐸 bumpy v1.
|
|
155
|
+
${colorize(`🐸 bumpy v1.2.0`, "bold")} - Modern monorepo versioning
|
|
152
156
|
|
|
153
157
|
Usage: bumpy <command> [options]
|
|
154
158
|
|
|
@@ -158,6 +162,8 @@ function printHelp() {
|
|
|
158
162
|
generate Generate bump file from branch commits
|
|
159
163
|
status Show pending releases
|
|
160
164
|
check Verify changed packages have bump files (for pre-push hooks)
|
|
165
|
+
--strict Fail if any changed package is uncovered (default: only fail if no bump files at all)
|
|
166
|
+
--no-fail Warn only, never exit 1
|
|
161
167
|
version [--commit] Apply bump files and bump versions
|
|
162
168
|
publish Publish versioned packages
|
|
163
169
|
ci check PR check — report pending releases, comment on PR
|
|
@@ -191,7 +197,8 @@ function printHelp() {
|
|
|
191
197
|
|
|
192
198
|
CI check options:
|
|
193
199
|
--comment Force PR comment on/off (auto-detected in CI)
|
|
194
|
-
--fail
|
|
200
|
+
--strict Fail if any changed package is uncovered (default: only fail if no bump files at all)
|
|
201
|
+
--no-fail Warn only, never exit 1
|
|
195
202
|
|
|
196
203
|
CI release options:
|
|
197
204
|
--auto-publish Version + publish directly (default: create version PR)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as readJson, n as exists } from "./fs-
|
|
2
|
+
import { a as readJson, n as exists, o as readJsonc } from "./fs-DnDogVn-.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
//#region src/types.ts
|
|
5
5
|
const BUMP_LEVELS = {
|
|
@@ -71,7 +71,7 @@ const DEFAULT_CONFIG = {
|
|
|
71
71
|
preamble: [
|
|
72
72
|
`<a href="https://bumpy.varlock.dev"><img src="https://raw.githubusercontent.com/dmno-dev/bumpy/main/images/frog-talking.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
|
|
73
73
|
"",
|
|
74
|
-
`This PR was created and will be kept in sync by [bumpy](https://bumpy.varlock.dev) based on your
|
|
74
|
+
`This PR was created and will be kept in sync by [bumpy](https://bumpy.varlock.dev) based on your bump files (in \`.bumpy/\`). Merge it when you are ready to release the packages listed below:`,
|
|
75
75
|
"<br clear=\"left\" />"
|
|
76
76
|
].join("\n")
|
|
77
77
|
}
|
|
@@ -109,7 +109,7 @@ async function findRoot(startDir = process.cwd()) {
|
|
|
109
109
|
async function loadConfig(rootDir) {
|
|
110
110
|
const configPath = resolve(rootDir, BUMPY_DIR, CONFIG_FILE);
|
|
111
111
|
let userConfig = {};
|
|
112
|
-
if (await exists(configPath)) userConfig = await
|
|
112
|
+
if (await exists(configPath)) userConfig = await readJsonc(configPath);
|
|
113
113
|
return mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
114
114
|
}
|
|
115
115
|
/** Load per-package bumpy config from package.json["bumpy"] or .bumpy.config.json */
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
2
|
import { access, mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
//#region src/utils/jsonc.ts
|
|
4
|
+
const stringOrCommentRe = /("(?:\\?[^])*?")|(\/\/.*)|(\/\*[^]*?\*\/)/g;
|
|
5
|
+
const stringOrTrailingCommaRe = /("(?:\\?[^])*?")|(,\s*)(?=]|})/g;
|
|
6
|
+
function parseJsonc(text) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(text);
|
|
9
|
+
} catch {
|
|
10
|
+
return JSON.parse(text.replace(stringOrCommentRe, "$1").replace(stringOrTrailingCommaRe, "$1"));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
3
14
|
//#region src/utils/fs.ts
|
|
4
15
|
var fs_exports = /* @__PURE__ */ __exportAll({
|
|
5
16
|
ensureDir: () => ensureDir,
|
|
6
17
|
exists: () => exists,
|
|
7
18
|
listFiles: () => listFiles,
|
|
8
19
|
readJson: () => readJson,
|
|
20
|
+
readJsonc: () => readJsonc,
|
|
9
21
|
readText: () => readText,
|
|
10
22
|
removeFile: () => removeFile,
|
|
11
23
|
updateJsonFields: () => updateJsonFields,
|
|
@@ -17,6 +29,9 @@ async function readJson(filePath) {
|
|
|
17
29
|
const content = await readFile(filePath, "utf-8");
|
|
18
30
|
return JSON.parse(content);
|
|
19
31
|
}
|
|
32
|
+
async function readJsonc(filePath) {
|
|
33
|
+
return parseJsonc(await readFile(filePath, "utf-8"));
|
|
34
|
+
}
|
|
20
35
|
async function writeJson(filePath, data, indent = 2) {
|
|
21
36
|
await writeFile(filePath, JSON.stringify(data, null, indent) + "\n", "utf-8");
|
|
22
37
|
}
|
|
@@ -78,4 +93,4 @@ async function ensureDir(dir) {
|
|
|
78
93
|
await mkdir(dir, { recursive: true });
|
|
79
94
|
}
|
|
80
95
|
//#endregion
|
|
81
|
-
export { readJson as a,
|
|
96
|
+
export { readJson as a, removeFile as c, writeJson as d, writeText as f, listFiles as i, updateJsonFields as l, exists as n, readJsonc as o, fs_exports as r, readText as s, ensureDir as t, updateJsonNestedField as u };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { t as ensureDir } from "./fs-
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir } from "./config-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
2
|
+
import { t as ensureDir } from "./fs-DnDogVn-.mjs";
|
|
3
|
+
import { a as loadConfig, r as getBumpyDir } from "./config-D7Umr-fT.mjs";
|
|
4
|
+
import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
|
|
5
5
|
import { s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
6
|
-
import { i as writeBumpFile } from "./bump-file-
|
|
6
|
+
import { i as writeBumpFile } from "./bump-file-Br2bTaWp.mjs";
|
|
7
7
|
import { i as getFilesChangedInCommit, n as getBranchCommits } from "./git-YDedMddc.mjs";
|
|
8
8
|
import { n as slugify, t as randomName } from "./names-C-TuOPbd.mjs";
|
|
9
9
|
import { relative } from "node:path";
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as loadConfig, c as BUMP_LEVELS, d as DEFAULT_PUBLISH_CONFIG, f as DEP_TYPES, h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, n as findRoot, p as bumpLevel, r as getBumpyDir, s as matchGlob, u as DEFAULT_CONFIG } from "./config-
|
|
2
|
-
import { t as discoverPackages } from "./workspace-
|
|
1
|
+
import { a as loadConfig, c as BUMP_LEVELS, d as DEFAULT_PUBLISH_CONFIG, f as DEP_TYPES, h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, n as findRoot, p as bumpLevel, r as getBumpyDir, s as matchGlob, u as DEFAULT_CONFIG } from "./config-D7Umr-fT.mjs";
|
|
2
|
+
import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
|
|
3
3
|
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
4
|
-
import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-
|
|
4
|
+
import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-Br2bTaWp.mjs";
|
|
5
5
|
import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-BJzWIuRz.mjs";
|
|
6
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
7
|
-
import { a as prependToChangelog, i as loadFormatter, n as defaultFormatter, r as generateChangelogEntry, t as applyReleasePlan } from "./apply-release-plan-
|
|
8
|
-
import { t as publishPackages } from "./publish-pipeline-
|
|
6
|
+
import { t as assembleReleasePlan } from "./release-plan-CNOuSI-d.mjs";
|
|
7
|
+
import { a as prependToChangelog, i as loadFormatter, n as defaultFormatter, r as generateChangelogEntry, t as applyReleasePlan } from "./apply-release-plan-CPzu6JcF.mjs";
|
|
8
|
+
import { t as publishPackages } from "./publish-pipeline-BFt96o_h.mjs";
|
|
9
9
|
export { BUMP_LEVELS, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DependencyGraph, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as readJson, d as writeText, i as listFiles, n as exists,
|
|
3
|
-
import { t as detectPackageManager } from "./package-manager-
|
|
2
|
+
import { a as readJson, d as writeJson, f as writeText, i as listFiles, n as exists, s as readText, t as ensureDir } from "./fs-DnDogVn-.mjs";
|
|
3
|
+
import { t as detectPackageManager } from "./package-manager-ByJ0wKYh.mjs";
|
|
4
4
|
import { t as run } from "./shell-CY7OD48z.mjs";
|
|
5
5
|
import { c as ot, o as gt, s as mt, t as unwrap } from "./clack-C6bVkGxf.mjs";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
7
|
import { readdir, rename, rm } from "node:fs/promises";
|
|
8
8
|
//#region ../../.bumpy/README.md
|
|
9
9
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
10
|
-
var README_default = "# 🐸 Bumpy\n\nThis directory is used by [bumpy](https://bumpy.varlock.dev) to manage versioning and changelogs.\n\nBumpy is a modern versioning tool for JavaScript/TypeScript projects (monorepos and single packages). It uses **bump files** — small markdown files in this directory — to declare pending version changes. These files are consumed during the release process to compute version bumps, update changelogs, and publish packages.\n\n## How it works\n\n1. When you make a change that should trigger a release, create a bump file (typically one per PR)\n2. Bump files accumulate on your main branch until you're ready to release\n3. At release time, bumpy merges all pending bumps into a release plan, updates versions and changelogs, and publishes packages\n\n## Creating bump files\n\n### Interactive\n\n```bash\nbunx bumpy add\n```\n\n### Non-interactive (useful for AI-assisted development)\n\n```bash\nbunx bumpy add --packages \"package-name:minor,other-package:patch\" --message \"Description of changes\" --name \"my-change\"\n```\n\n### By hand\n\nCreate a `.md` file in this directory with YAML frontmatter mapping package names to bump levels (`major`, `minor`, or `
|
|
10
|
+
var README_default = "# 🐸 Bumpy\n\nThis directory is used by [bumpy](https://bumpy.varlock.dev) to manage versioning and changelogs.\n\nBumpy is a modern versioning tool for JavaScript/TypeScript projects (monorepos and single packages). It uses **bump files** — small markdown files in this directory — to declare pending version changes. These files are consumed during the release process to compute version bumps, update changelogs, and publish packages.\n\n## How it works\n\n1. When you make a change that should trigger a release, create a bump file (typically one per PR)\n2. Bump files accumulate on your main branch until you're ready to release\n3. At release time, bumpy merges all pending bumps into a release plan, updates versions and changelogs, and publishes packages\n\n## Creating bump files\n\n### Interactive\n\n```bash\nbunx bumpy add\n```\n\n### Non-interactive (useful for AI-assisted development)\n\n```bash\nbunx bumpy add --packages \"package-name:minor,other-package:patch\" --message \"Description of changes\" --name \"my-change\"\n```\n\n### By hand\n\nCreate a `.md` file in this directory with YAML frontmatter mapping package names to bump levels (`major`, `minor`, `patch`, or `none`), and a markdown body for the changelog entry:\n\n```markdown\n---\n'package-name': minor\n---\n\nAdded a new feature.\n```\n\n### From conventional commits\n\n```bash\nbunx bumpy generate\n```\n\n### Empty bump files\n\nFor PRs that intentionally don't need a release (docs, CI, etc.):\n\n```bash\nbunx bumpy add --empty --name \"docs-update\"\n```\n\n## Keeping bump files up to date\n\nAs a PR evolves, make sure its bump file stays in sync. If the scope of changes grows (e.g., a patch becomes a new feature), update the bump level and description to match. Reviewers and AI assistants should treat the bump file as part of the PR — just like tests and docs.\n\n## Files in this directory\n\n- `_config.json` — bumpy configuration\n- `README.md` — this file\n- `*.md` (other than README.md) — pending bump files\n\n📖 Full documentation: https://bumpy.varlock.dev\n";
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/commands/init.ts
|
|
13
13
|
const PM_RUNNER = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as readJson, n as exists,
|
|
1
|
+
import { a as readJson, n as exists, s as readText } from "./fs-DnDogVn-.mjs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
//#region ../../node_modules/.bun/js-yaml@4.1.1/node_modules/js-yaml/dist/js-yaml.mjs
|
|
4
4
|
/*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { n as detectWorkspaces } from "./package-manager-
|
|
4
|
-
import { n as discoverWorkspace } from "./workspace-
|
|
2
|
+
import { a as loadConfig } from "./config-D7Umr-fT.mjs";
|
|
3
|
+
import { n as detectWorkspaces } from "./package-manager-ByJ0wKYh.mjs";
|
|
4
|
+
import { n as discoverWorkspace } from "./workspace-BHsAPUmC.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
6
6
|
import { r as runArgsAsync, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
7
7
|
import { a as hasUncommittedChanges, o as listTags, s as pushWithTags } from "./git-YDedMddc.mjs";
|
|
8
|
-
import { t as publishPackages } from "./publish-pipeline-
|
|
8
|
+
import { t as publishPackages } from "./publish-pipeline-BFt96o_h.mjs";
|
|
9
9
|
//#region src/core/github-release.ts
|
|
10
10
|
/** Get the current HEAD commit SHA */
|
|
11
11
|
function getHeadSha(rootDir) {
|
|
@@ -148,7 +148,7 @@ async function publishCommand(rootDir, opts) {
|
|
|
148
148
|
}
|
|
149
149
|
let toPublish = await findUnpublishedPackages(packages, config);
|
|
150
150
|
if (opts.filter) {
|
|
151
|
-
const { matchGlob } = await import("./config-
|
|
151
|
+
const { matchGlob } = await import("./config-D7Umr-fT.mjs").then((n) => n.t);
|
|
152
152
|
const patterns = opts.filter.split(",").map((p) => p.trim());
|
|
153
153
|
toPublish = toPublish.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
|
|
154
154
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as readJson,
|
|
3
|
-
import { r as resolveCatalogDep } from "./package-manager-
|
|
2
|
+
import { a as readJson, u as updateJsonNestedField } from "./fs-DnDogVn-.mjs";
|
|
3
|
+
import { r as resolveCatalogDep } from "./package-manager-ByJ0wKYh.mjs";
|
|
4
4
|
import { i as runAsync, o as sq, r as runArgsAsync, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
5
5
|
import { r as stripProtocol } from "./semver-BJzWIuRz.mjs";
|
|
6
6
|
import { c as tagExists, t as createTag } from "./git-YDedMddc.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, p as bumpLevel, s as matchGlob } from "./config-
|
|
1
|
+
import { h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, p as bumpLevel, s as matchGlob } from "./config-D7Umr-fT.mjs";
|
|
2
2
|
import { n as satisfies, t as bumpVersion } from "./semver-BJzWIuRz.mjs";
|
|
3
3
|
//#region src/core/release-plan.ts
|
|
4
4
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { t as discoverPackages } from "./workspace-
|
|
2
|
+
import { a as loadConfig } from "./config-D7Umr-fT.mjs";
|
|
3
|
+
import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
|
|
4
4
|
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
5
|
-
import { r as readBumpFiles } from "./bump-file-
|
|
6
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
5
|
+
import { r as readBumpFiles } from "./bump-file-Br2bTaWp.mjs";
|
|
6
|
+
import { t as assembleReleasePlan } from "./release-plan-CNOuSI-d.mjs";
|
|
7
7
|
//#region src/commands/status.ts
|
|
8
8
|
async function statusCommand(rootDir, opts) {
|
|
9
9
|
const config = await loadConfig(rootDir);
|
|
@@ -26,7 +26,7 @@ async function statusCommand(rootDir, opts) {
|
|
|
26
26
|
releases = releases.filter((r) => types.includes(r.type));
|
|
27
27
|
}
|
|
28
28
|
if (opts.filter) {
|
|
29
|
-
const { matchGlob } = await import("./config-
|
|
29
|
+
const { matchGlob } = await import("./config-D7Umr-fT.mjs").then((n) => n.t);
|
|
30
30
|
const patterns = opts.filter.split(",").map((p) => p.trim());
|
|
31
31
|
releases = releases.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
|
|
32
32
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { n as detectWorkspaces } from "./package-manager-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
2
|
+
import { a as loadConfig } from "./config-D7Umr-fT.mjs";
|
|
3
|
+
import { n as detectWorkspaces } from "./package-manager-ByJ0wKYh.mjs";
|
|
4
|
+
import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
6
6
|
import { n as runArgs, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
7
|
-
import { r as readBumpFiles } from "./bump-file-
|
|
8
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
9
|
-
import { t as applyReleasePlan } from "./apply-release-plan-
|
|
7
|
+
import { r as readBumpFiles } from "./bump-file-Br2bTaWp.mjs";
|
|
8
|
+
import { t as assembleReleasePlan } from "./release-plan-CNOuSI-d.mjs";
|
|
9
|
+
import { t as applyReleasePlan } from "./apply-release-plan-CPzu6JcF.mjs";
|
|
10
10
|
import { t as resolveCommitMessage } from "./commit-message-BwsowSds.mjs";
|
|
11
11
|
//#region src/commands/version.ts
|
|
12
12
|
async function versionCommand(rootDir, opts = {}) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as readJson, n as exists } from "./fs-
|
|
2
|
-
import { i as isPackageManaged, o as loadPackageConfig } from "./config-
|
|
3
|
-
import { n as detectWorkspaces } from "./package-manager-
|
|
1
|
+
import { a as readJson, n as exists } from "./fs-DnDogVn-.mjs";
|
|
2
|
+
import { i as isPackageManaged, o as loadPackageConfig } from "./config-D7Umr-fT.mjs";
|
|
3
|
+
import { n as detectWorkspaces } from "./package-manager-ByJ0wKYh.mjs";
|
|
4
4
|
import { relative, resolve } from "node:path";
|
|
5
5
|
import { readdir, stat } from "node:fs/promises";
|
|
6
6
|
//#region src/core/workspace.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@varlock/bumpy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Modern monorepo versioning and changelog tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bump",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsdown",
|
|
40
|
+
"prepack": "cp ../../README.md .",
|
|
40
41
|
"check": "bun run tsc --noEmit",
|
|
41
42
|
"test": "bun test"
|
|
42
43
|
},
|