versionary 0.31.0 → 1.0.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 CHANGED
@@ -1,111 +1,99 @@
1
1
  # Versionary
2
2
 
3
3
  Versionary is a software-agnostic automated release tool focused on SemVer,
4
- conventional commits, release PR workflows, and extensibility.
4
+ Conventional Commits, release-PR workflows, and extensibility.
5
5
 
6
- ## Why this exists
6
+ 📖 **Documentation: <https://versionary.dev/>**
7
7
 
8
- Versionary is designed as a practical middle ground between `semantic-release`
9
- and `release-please`.
8
+ ## Why this exists
10
9
 
11
- - Like `semantic-release`, it supports direct release execution.
12
- - Like `release-please`, it supports a release PR workflow so maintainers can
13
- preview and review changes before publication.
10
+ Versionary is a practical middle ground between
11
+ [`semantic-release`](https://github.com/semantic-release/semantic-release) and
12
+ [`release-please`](https://github.com/googleapis/release-please):
14
13
 
15
- The core idea is to keep versioning, changelog generation, tagging, and SCM
16
- release metadata in one tool, while leaving package publication (npm, crates.io,
17
- etc.) to dedicated CI workflows triggered by tags or releases.
14
+ - like `semantic-release`, it supports **direct release execution**;
15
+ - like `release-please`, it supports a **release PR workflow** so maintainers
16
+ can preview and review changes before publication.
18
17
 
19
- ## Product direction
18
+ It keeps versioning, changelog generation, tagging, and SCM release metadata in
19
+ one tool, while leaving package publication (npm, crates.io, etc.) to dedicated
20
+ CI workflows triggered by tags or releases.
20
21
 
21
- Versionary is being built to:
22
+ It is built to:
22
23
 
23
24
  - support both direct releases and release-PR-gated releases
24
- - work across repository types (Node, Rust, docs/LaTeX, etc.)
25
- - stay SCM-agnostic at the core with built-in integration adapters
26
- (GitHub first; GitLab/Codeberg later)
27
- - keep a small, stable core with explicit extension points
25
+ - work across ecosystems (Node, Rust, Python, R, Julia, LaTeX, )
26
+ - stay SCM-agnostic at the core with built-in integration (GitHub first)
27
+ - keep a small, stable core with clear extension points
28
28
  - handle trunk-based development and monorepo workflows cleanly
29
29
 
30
- ## Scope and non-goals
30
+ > **Status:** early, alpha-stage development. Breaking changes are expected
31
+ > before `1.0.0`.
31
32
 
32
- In scope:
33
+ ## Quick start
33
34
 
34
- - semantic version planning from commits
35
- - changelog generation
36
- - release PR automation
37
- - tags + SCM release metadata (e.g. GitHub Releases)
35
+ Install:
38
36
 
39
- Out of scope (intentional):
37
+ ```bash
38
+ pnpm add -D versionary # or npm install --save-dev versionary
39
+ ```
40
40
 
41
- - publishing artifacts to language registries
42
- - replacing package-specific publish tooling
43
- - external/user-provided plugin loading
41
+ Add a `versionary.jsonc` at the repo root:
44
42
 
45
- Use your CI/CD platform for registry publishing, triggered from a created
46
- release/tag.
43
+ ```jsonc
44
+ {
45
+ "$schema": "https://raw.githubusercontent.com/jolars/versionary/main/schemas/config.json",
46
+ "version": 1,
47
+ "release-type": "node"
48
+ }
49
+ ```
47
50
 
48
- ## Current status vs roadmap
51
+ Check it and preview the next release:
49
52
 
50
- Current implementation focuses on:
53
+ ```bash
54
+ npx versionary verify
55
+ npx versionary plan
56
+ ```
51
57
 
52
- - strategy-based version updates (`simple`, `node`, `rust`, `r`, `latex`,
53
- `python`, `julia`)
54
- - release planning and changelog generation
55
- - review-mode vs direct-mode release flow
56
- - a static internal SCM client (`github` provider today)
58
+ Then automate it in CI—see the
59
+ [Getting started](https://versionary.dev/guide/getting-started) and
60
+ [GitHub Actions](https://versionary.dev/guide/github-actions)
61
+ guides.
57
62
 
58
- Planned/harder areas include deeper monorepo ergonomics, broader SCM coverage,
59
- and stronger failure recovery around release steps.
63
+ ## Documentation
60
64
 
61
- ## Adding a new release strategy
65
+ The full documentation lives at <https://versionary.dev/>:
62
66
 
63
- Versionary is set up so new language strategies can be added internally without
64
- changing release orchestration. A new strategy should implement the
65
- `VersionStrategy` contract in `src/strategy/types.ts` and be wired in
66
- `src/strategy/resolve.ts`.
67
+ - [Getting started](https://versionary.dev/guide/getting-started)
68
+ - [GitHub Actions setup](https://versionary.dev/guide/github-actions)
69
+ (including tokens and permissions)
70
+ - [Release workflows](https://versionary.dev/guide/workflows)
71
+ - [Monorepos](https://versionary.dev/guide/monorepos)
72
+ - [Conventional Commits](https://versionary.dev/guide/conventional-commits)
73
+ and [Versioning](https://versionary.dev/guide/versioning)
74
+ - Reference:
75
+ [CLI](https://versionary.dev/reference/cli),
76
+ [Configuration](https://versionary.dev/reference/configuration),
77
+ [Strategies](https://versionary.dev/reference/strategies)
67
78
 
68
- Checklist for new strategies:
79
+ ## Scope and non-goals
69
80
 
70
- - define strategy `name`
71
- - define `getVersionFile(config)` defaults and config override behavior
72
- - implement `readVersion(cwd, config)` with explicit malformed-file errors
73
- - implement `writeVersion(cwd, config, version)` returning deterministic updated
74
- file paths
75
- - optionally implement `readPackageName(cwd, config)` so monorepo release tags
76
- can derive from language metadata (similar to Node/Rust/R)
77
- - optionally implement `propagateDependentPatchImpacts(cwd, packages)` if
78
- dependency updates in this ecosystem should trigger dependent package patch
79
- bumps
80
- - optionally implement `finalizeVersionWrites(cwd, writes, context)` for
81
- ecosystem post-processing after all target version files are written
82
- - add focused strategy tests for ecosystem-specific behavior and edge cases
83
- - add/extend strategy contract tests in `tests/strategy-contract.test.ts`
84
- - update schema/docs for new `release-type` behavior and defaults
81
+ In scope: semantic version planning from commits, changelog generation, release
82
+ PR automation, and tags + SCM release metadata (e.g. GitHub Releases).
85
83
 
86
- Current ecosystem policy defaults:
87
-
88
- - changelog source for publish:
89
- - root target uses root `changelog-file`
90
- - package target uses package changelog defaults:
91
- - `packages.<path>.changelog-file` when configured
92
- - otherwise `NEWS.md` for R targets or `CHANGELOG.md` for other targets at
93
- `<package-path>/<default-file>`
94
- - lockfiles:
95
- - Node strategy updates root `package-lock.json`/`npm-shrinkwrap.json` when
96
- present
97
- - Rust release PR prep refreshes all discovered `Cargo.lock` files
98
- - Python strategy refreshes any `poetry.lock`/`uv.lock`/`pdm.lock` at the
99
- package root by shelling out to the matching tool (`poetry lock
100
- --no-update`, `uv lock`, `pdm lock --update-reuse`); the corresponding
101
- binary must be on `PATH`
102
- - workspace/inheritance:
103
- - Rust supports `version.workspace = true` via `[workspace.package].version`
104
- - other strategies should document equivalent inheritance behavior explicitly
84
+ Out of scope (intentional): publishing artifacts to language registries,
85
+ replacing package-specific publish tooling, and external/user-provided plugin
86
+ loading. Use your CI/CD platform for registry publishing, triggered from a
87
+ created release/tag.
88
+
89
+ ## Contributing
90
+
91
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, commands, and
92
+ commit conventions.
105
93
 
106
94
  ## Architecture layout (canonical)
107
95
 
108
- Current runtime code uses a flat `src/` layout with clear module boundaries:
96
+ Runtime code uses a flat `src/` layout with clear module boundaries:
109
97
 
110
98
  - `src/cli/`: command router (`run`, `verify`, `plan`, `changelog`, `pr`, `release`)
111
99
  - `src/release/`: release orchestration (plan/changelog/PR/release/state/recovery)
@@ -114,369 +102,35 @@ Current runtime code uses a flat `src/` layout with clear module boundaries:
114
102
  - `src/scm/`: SCM client contracts and provider implementation(s)
115
103
  - `src/config/`: config loading and schema validation
116
104
  - `src/git/`: git commit/range and repository URL helpers
117
- - `src/verify/`: repository/config verification
118
105
  - `src/types/`: shared config/plugin-facing types
119
106
 
120
107
  Configuration is loaded from `versionary.jsonc` by default (or
121
- `versionary.json`).
122
-
123
- Schema URL for editor support:
124
-
125
- - `https://raw.githubusercontent.com/jolars/versionary/main/schemas/config.json`
126
-
127
- ## Config (manifest style)
128
-
129
- For a quick trial, use:
130
-
131
- - `version-file` (default `version.txt`) as version source
132
- - `changelog-file` (default `CHANGELOG.md`) as release notes output
133
- - `release-type: "node"` uses `package.json` as version source and updates it
134
- during release PR prep
135
- - `release-type: "r"` uses `DESCRIPTION` as version source and updates the
136
- `Version:` field
137
- - `release-type: "rust"` uses Cargo manifests (`Cargo.toml`) as version source;
138
- `version-file` must point to a `Cargo.toml` (default: `Cargo.toml`)
139
- - `release-type: "latex"` uses `build.lua` as version source and updates LaTeX
140
- `\ProvidesPackage{...}[YYYY-MM-DD vX.Y.Z ...]` metadata in `src/**/*.dtx`
141
- using the release commit date
142
- - `release-type: "python"` uses `pyproject.toml` (default) and updates
143
- `[project].version` and/or `[tool.poetry].version`; point `version-file` at a
144
- Python source file (e.g. `src/<pkg>/__init__.py`) to update a `__version__`
145
- assignment instead. Refreshes `poetry.lock`/`uv.lock`/`pdm.lock` at the
146
- package root if present
147
- - `release-type: "julia"` uses `Project.toml` (default) as version source and
148
- updates the top-level `version` field (Julia keeps `version`/`name` as root
149
- keys, not under a section)
150
- - `release-type` can also be an array of strategy names to compose them across
151
- manifests, e.g. `["python", "rust"]` for a PyO3/maturin project: the first
152
- entry is the *primary* (drives `readVersion`, `readPackageName`, and consumes
153
- any `version-file` override); each *secondary* writes its default manifest
154
- with the same target version. Common combinations:
155
- - `["python", "rust"]` — PyO3/maturin (`pyproject.toml` + `Cargo.toml` +
156
- `Cargo.lock`)
157
- - `["node", "rust"]` — napi-rs (`package.json` + `Cargo.toml` + `Cargo.lock`)
158
- - `["r", "rust"]` — R packages with embedded Rust crates (note: nested
159
- `src/rust/Cargo.toml` layouts are not supported by the array form yet —
160
- use a single strategy until per-strategy `version-file` overrides land)
161
- - simple/default strategy keeps `version.txt` as source of truth and does not
162
- update `package.json`
163
- - stable release branch (`release-branch`, default: `versionary/release`) so
164
- release PRs are updated in-place
165
- - `baseline-file` (default `.versionary-manifest.json`) tracks baseline SHA for
166
- deterministic commit ranges independent of tags
167
- - pre-1.0 policy defaults to conservative major handling: for `0.y.z`, breaking
168
- changes bump to `0.(y+1).0`; set `allow-stable-major: true` to allow explicit
169
- auto-transition to `1.0.0` on a breaking release
170
- - review mode (`review-mode`): `pr` (PR/MR style) or `direct` (no review
171
- request)
172
- - `release-draft` (default `false`) publishes GitHub releases as drafts when
173
- enabled
174
- - `release-reference-comments` controls release comments on linked issues/PRs:
175
- - `off` (default): do not post comments
176
- - `best-effort`: post comments and continue on API/permission failures
177
- - `strict`: fail release if comment posting fails
178
- - comments are authored by the account that owns the configured token; see
179
- [Comment and commit author identity](#comment-and-commit-author-identity)
180
- to post them under a bot identity
181
- - optional monorepo planning with `monorepo-mode` and `packages`:
182
- - `independent` computes package bumps per path
183
- - `fixed` computes one shared bump across configured package paths
184
- - per-package `package-name` can override release identity (labels + tag base)
185
- - per-package `changelog-file` writes package release notes to
186
- `<package-path>/<changelog-file>`
187
- - per-package `follows` declares an asymmetric version link to one or more
188
- source packages: when any source bumps, the follower releases too, with
189
- bump = `max(own bump, max(source bumps))`. The follower's changelog gets a
190
- `### Dependencies` section listing the followed sources. Use it when one
191
- package bundles another's artifact (e.g. an editor extension that ships
192
- the CLI binary). Cycles, self-references, unknown source paths, and
193
- combining `follows` with `monorepo-mode: "fixed"` are config errors.
194
- `follows` is non-transitive: A follows B does not imply A follows what B
195
- follows.
196
- - per-package `exclude-paths` drops commits that only touch the listed paths
197
- (relative to the package) from that package's bump and changelog. A
198
- top-level `exclude-paths` applies to every package; the effective excludes
199
- for a package are the union of the top-level list and the package's own
200
- list. The top-level list also applies to a single-package (non-`packages`)
201
- repository.
202
- - per-package `allow-stable-major` overrides the top-level setting for that
203
- package's own bump (including dependency-propagation and `follows`-driven
204
- bumps), so a `0.y.z` package can transition to `1.0.0` on a breaking release
205
- independently of its siblings. In `fixed` mode the single shared version is
206
- governed by the top-level `allow-stable-major` only.
207
-
208
- ```jsonc
209
- // Editor extension that bundles the root CLI artifact
210
- {
211
- "version": 1,
212
- "release-type": "rust",
213
- "monorepo-mode": "independent",
214
- "packages": {
215
- ".": { "exclude-paths": ["editors"] },
216
- "editors/code": {
217
- "release-type": "node",
218
- "package-name": "panache-code",
219
- "follows": ["."]
220
- }
221
- }
222
- }
223
- ```
224
-
225
- Rust strategy examples:
226
-
227
- ```jsonc
228
- // Single crate
229
- {
230
- "release-type": "rust",
231
- "version-file": "Cargo.toml"
232
- }
233
- ```
234
-
235
- ```jsonc
236
- // Workspace root (virtual or root crate + members)
237
- {
238
- "release-type": "rust",
239
- "version-file": "Cargo.toml"
240
- }
241
- ```
242
-
243
- Current rust auto-update behavior (phase scope):
244
-
245
- - updates crate versions in each targeted crate `[package].version`
246
- - supports targeted crates using `version.workspace = true` by updating
247
- `[workspace.package].version` in the owning workspace manifest
248
- - updates internal workspace dependency versions when the dependency name
249
- matches another targeted crate name
250
- - refreshes `Cargo.lock` via `cargo generate-lockfile` when `Cargo.lock` exists
251
- in repo root
252
- - applies dependency version rewrites in:
253
- - `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`
254
- - `[target.*.dependencies]`, `[target.*.dev-dependencies]`,
255
- `[target.*.build-dependencies]`
256
-
257
- Current rust non-goals/limits:
258
-
259
- - does not update external dependency versions
260
- - does not update `workspace.dependencies`
261
- - does not add missing `version = ...` fields to dependency inline tables
262
- - does not perform Cargo publish/release to crates.io
263
-
264
- If `Cargo.lock` exists, `cargo` must be available in PATH during PR preparation.
265
-
266
- ### Monorepo release names and tag naming
267
-
268
- For independent monorepo targets, Versionary derives release tags as:
269
-
270
- - root package (`"."`): `v<version>`
271
- - non-root package: `<release-name>-v<version>`
272
-
273
- `release-name` precedence is:
274
-
275
- 1. `packages.<path>.package-name` (explicit override)
276
- 2. strategy-native package name from version file:
277
- - Node: `package.json` `name`
278
- - Rust: `Cargo.toml` `[package].name`
279
- - R: `DESCRIPTION` `Package:`
280
- 3. package path fallback
281
-
282
- When multiple packages resolve to the same `<release-name>` and version, the run
283
- fails fast with a duplicate-tag error and suggests setting unique
284
- `package-name` values.
285
-
286
- ## Commit parsing and release analysis
287
-
288
- Release planning is based on Conventional Commit parsing semantics:
289
-
290
- - parses type/scope/description from commit headers
291
- - exposes structured parsed fields (`header`, `body`, `footer`, `type`, `scope`,
292
- `description`, `notes`, `references`, `mentions`, `revert`)
293
- - separates parser output from release policy mapping (`inferReleaseType*`)
294
- - recognizes breaking changes from `!` and `BREAKING CHANGE` / `BREAKING-CHANGE`
295
- footers
296
- - maps release impact as `feat => minor`, `fix|perf => patch`, breaking => major
297
- - treats `revert:` commits as patch-releasable by default (and major if marked
298
- breaking, e.g. `revert!:` or `BREAKING CHANGE`)
299
- - suppresses commits that are reverted within the analyzed release window so
300
- they do not affect bump/changelog output
301
- - emits parser diagnostics for malformed headers/footers/references and
302
- ambiguous revert messages
303
-
304
- Commands:
108
+ `versionary.json`). The config schema lives in `src/config/schema.ts`; the
109
+ editor-facing `schemas/config.json` is generated via `pnpm gen:schema`.
305
110
 
306
- - `pnpm verify`
307
- - `pnpm run` (default orchestration: no-op, create/update release PR, or publish
308
- release based on context)
309
- - `pnpm run -- --json` (machine-readable orchestration result)
310
- - `pnpm plan`
311
- - `pnpm changelog -- --write`
312
- - `pnpm pr`
313
- - `pnpm release`
314
-
315
- `pnpm pr` prepares release commit + branch and opens/updates a review request
316
- through the SCM client. `pnpm run` is the recommended CI entrypoint and
317
- auto-dispatches between PR/update and release publish.
318
-
319
- ### Moloch migration example (semantic-release -> versionary)
320
-
321
- For LaTeX projects like `moloch`, use `release-type: "latex"` so Versionary:
322
-
323
- - bumps `build.lua` version
324
- - updates `src/**/*.dtx` `\ProvidesPackage{...}[YYYY-MM-DD vX.Y.Z ...]` entries
325
- with the release commit date (`git show --format=%cs <sha>`)
326
-
327
- Example `versionary.jsonc` for `moloch`:
328
-
329
- ```jsonc
330
- {
331
- "version": 1,
332
- "review-mode": "pr",
333
- "release-type": "latex",
334
- "version-file": "build.lua",
335
- "changelog-file": "CHANGELOG.md",
336
- "release-branch": "versionary/release"
337
- }
338
- ```
339
-
340
- For first-run bootstrapping, set `bootstrap-sha` (similar to release-please).
341
- Subsequent runs use the baseline state file.
342
-
343
- ## Release retry and recovery behavior
344
-
345
- Release publish (`pnpm release` or the publish path in `pnpm run`) is idempotent
346
- by target tag:
347
-
348
- - if a tag already exists, Versionary reuses it rather than recreating it
349
- - if release metadata already exists for the tag (e.g., GitHub Release), it is
350
- reused
351
- - if a prior run created/pushed the tag but failed before metadata creation, a
352
- rerun creates the missing metadata and proceeds
353
-
354
- Versionary fails fast when recovery is unsafe (for example, local and remote
355
- tags with the same name point to different SHAs). In these cases, the error
356
- message includes remediation guidance so CI logs are actionable.
357
-
358
- ## SCM API model
359
-
360
- Versionary currently uses a static internal SCM client model:
361
-
362
- - `src/scm/types.ts` defines the `ScmClient` contract
363
- - `src/scm/client.ts` returns the active provider client
364
- - current provider is `github` via `src/scm/github-plugin.ts`
365
-
366
- There is no runtime discovery/loading of external SCM providers in the release
367
- flow. Adding another provider is an internal extension: implement `ScmClient`
368
- and wire provider selection in `src/scm/client.ts`.
369
-
370
- ### GitHub integration: env, permissions, and flow
371
-
372
- Required environment for the GitHub SCM provider:
373
-
374
- - `GITHUB_REPOSITORY` (format: `owner/repo`)
375
- - one token env var: `VERSIONARY_PR_TOKEN` or `GH_TOKEN` or `GITHUB_TOKEN`
376
-
377
- Token precedence is:
378
-
379
- - `VERSIONARY_PR_TOKEN` > `GH_TOKEN` > `GITHUB_TOKEN`
380
-
381
- Minimum GitHub token/repo permissions for Versionary-managed metadata:
382
-
383
- - release PR create/update flow: `contents: write`, `pull-requests: write`
384
- - release metadata flow (GitHub Release create/read): `contents: write`
385
-
386
- `review-mode` behavior:
387
-
388
- - `pr` (preferred; `review` is a backward-compatible alias): `pnpm run run`
389
- prepares/updates the release branch and creates or
390
- updates a release PR
391
- - `direct`: `pnpm run run` prepares/updates the release branch and skips review
392
- request creation
393
-
394
- Concise GitHub Actions examples:
395
-
396
- ```yaml
397
- # 1) Release PR / update flow (run on push to default branch)
398
- permissions:
399
- contents: write
400
- pull-requests: write
401
-
402
- steps:
403
- - uses: actions/checkout@v6
404
- with:
405
- fetch-depth: 0
406
- fetch-tags: true
407
- - id: versionary
408
- uses: jolars/versionary@v1
409
- with:
410
- token: ${{ secrets.RELEASE_TOKEN }}
411
- ```
412
-
413
- ```yaml
414
- # 2) Release publish flow after merge (release commit context)
415
- permissions:
416
- contents: write
417
-
418
- steps:
419
- - uses: actions/checkout@v6
420
- with:
421
- fetch-depth: 0
422
- fetch-tags: true
423
- - id: versionary
424
- uses: jolars/versionary@v1
425
- with:
426
- token: ${{ secrets.RELEASE_TOKEN }}
427
- - if: ${{ steps.versionary.outputs.release_created == 'true' }}
428
- run: echo "Released ${{ steps.versionary.outputs.tag_name }}"
429
- ```
430
-
431
- `token` is used for both GitHub API calls and git push authentication in
432
- the composite action. This means release-branch force-pushes are attributed to
433
- that token and can trigger downstream workflows when using a PAT/App token.
434
- (`github-token` remains as a deprecated alias for backward compatibility.)
435
-
436
- #### Comment and commit author identity
437
-
438
- Two distinct identities are at play; keep them apart.
439
-
440
- **Release-reference comments, the GitHub Release, and the tag/branch push** are
441
- attributed to the account that owns the token you provide. There is no GitHub
442
- API to set a custom author independent of the token, so this identity always
443
- follows the token's account:
444
-
445
- - the workflow's default `GITHUB_TOKEN` acts as `github-actions[bot]` — the
446
- common case, and what most `semantic-release` setups show
447
- - a **personal access token (PAT)** acts as your own user
448
- - a **dedicated bot user account** acts as that account (for example
449
- `semantic-release`'s own `@semantic-release-bot`): create a separate GitHub
450
- user, generate a PAT for it, and store it as the release token
451
- - a **GitHub App installation token** (e.g. minted with
452
- `actions/create-github-app-token`) acts as `<app-name>[bot]`
453
-
454
- **The release commit's committer** comes from git's `user.name`/`user.email`,
455
- not the token. When neither is configured (e.g. a bare CI runner), Versionary
456
- defaults it to `github-actions[bot]`, so no `git config` step is needed in your
457
- workflow; an existing identity (local, global, or the one the GitHub Action
458
- wrapper sets) is left untouched.
459
-
460
- The release-reference comment body itself is signed by Versionary regardless of
461
- which account posts it.
462
-
463
- Action outputs:
111
+ ## Adding a new release strategy
464
112
 
465
- - `action`: `noop`, `pr-prepared`, `release-published`, `release-skipped`
466
- - `message`: human-readable summary
467
- - `release_created`: `"true"` when at least one release was published
468
- - `tag_name`: first published tag (for single-target flows)
469
- - `tag_names`: JSON array of published tags
470
- - `review_url`: review request URL when PR flow runs
113
+ New language strategies can be added internally without changing release
114
+ orchestration. A new strategy should implement the `VersionStrategy` contract in
115
+ `src/strategy/types.ts` and be wired in `src/strategy/resolve.ts`.
471
116
 
472
- For GitHub Action consumers, publish immutable tags (for example `v1.2.3`) and
473
- maintain a moving major tag (`v1`, `v2`, ...). A small release-triggered
474
- workflow should update `v<major>` to the latest release tag so `uses:
475
- jolars/versionary@v1` stays current without breaking major compatibility.
117
+ Checklist for new strategies:
476
118
 
477
- Package publication is intentionally out of scope in the current release flow.
478
- Use separate CI workflows for publishing after Versionary has prepared/tagged
479
- the release.
119
+ - define strategy `name`
120
+ - define `getVersionFile(config)` defaults and config override behavior
121
+ - implement `readVersion(cwd, config)` with explicit malformed-file errors
122
+ - implement `writeVersion(cwd, config, version)` returning deterministic updated
123
+ file paths
124
+ - optionally implement `readPackageName(cwd, config)` so monorepo release tags
125
+ can derive from language metadata (similar to Node/Rust/R)
126
+ - optionally implement `propagateDependentPatchImpacts(cwd, packages)` if
127
+ dependency updates in this ecosystem should trigger dependent package patch
128
+ bumps
129
+ - optionally implement `finalizeVersionWrites(cwd, writes, context)` for
130
+ ecosystem post-processing after all target version files are written
131
+ - add focused strategy tests for ecosystem-specific behavior and edge cases
132
+ - add/extend strategy contract tests in `tests/strategy-contract.test.ts`
133
+ - update schema/docs for new `release-type` behavior and defaults
480
134
 
481
135
  ## Install from GitHub
482
136
 
@@ -491,4 +145,8 @@ You can install directly from a git ref:
491
145
  ```
492
146
 
493
147
  The package runs a `prepare` build during git installation so the `versionary`
494
- CLI binary is available after `pnpm install`.
148
+ CLI binary is available after install.
149
+
150
+ ## License
151
+
152
+ [MIT](LICENSE)
@@ -57,9 +57,9 @@ function setOutput(name, value) {
57
57
  appendFileSync(outputPath, `${name}<<${delimiter}\n${value}\n${delimiter}\n`, "utf8");
58
58
  }
59
59
  function main() {
60
- const token = getInput("token") || getInput("github-token");
60
+ const token = getInput("token");
61
61
  if (!token) {
62
- throw new Error("Input required and not supplied: token (or deprecated github-token).");
62
+ throw new Error("Input required and not supplied: token.");
63
63
  }
64
64
  const versionaryVersion = getInput("versionary-version") || "0.7.0";
65
65
  const cwd = getInput("working-directory") || ".";
package/dist/cli/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFileSync } from "node:child_process";
3
- import { loadConfig } from "../config/load-config.js";
4
3
  import { prependChangelog, renderReleasePlanChangelog, } from "../release/changelog.js";
5
4
  import { createReleasePlan } from "../release/plan.js";
6
- import { closeStaleReviewRequestIfExists, consumeNextReleaseFile, isReleaseCommitMessage, openOrUpdateReviewRequest, prepareReleasePr, pushReleaseBranch, resolveReleaseHighlights, } from "../release/pr.js";
5
+ import { closeStaleReviewRequestIfExists, isReleaseCommitMessage, openOrUpdateReviewRequest, prepareReleasePr, pushReleaseBranch, resolveReleaseHighlights, } from "../release/pr.js";
7
6
  import { runRelease, runReleaseDetailed } from "../release/release.js";
8
7
  import { verifyProject } from "../release/verify-project.js";
9
8
  function printVerifyResult() {
@@ -195,8 +194,7 @@ async function main() {
195
194
  console.log("No releasable commits found.");
196
195
  return 0;
197
196
  }
198
- const loaded = loadConfig();
199
- const highlightsResult = resolveReleaseHighlights(process.cwd(), loaded.config, plan.changelogFile, plan.changelogFormat, logger);
197
+ const highlightsResult = resolveReleaseHighlights(process.cwd(), plan.changelogFile, plan.changelogFormat);
200
198
  const section = renderReleasePlanChangelog(plan, {
201
199
  highlights: highlightsResult.highlights,
202
200
  });
@@ -205,9 +203,6 @@ async function main() {
205
203
  return 0;
206
204
  }
207
205
  prependChangelog(process.cwd(), plan.changelogFile, section, plan.changelogFormat);
208
- if (highlightsResult.source === "file" && highlightsResult.filePath) {
209
- consumeNextReleaseFile(process.cwd(), highlightsResult.filePath);
210
- }
211
206
  console.log(`Updated ${plan.changelogFile}`);
212
207
  return 0;
213
208
  }
@@ -5,7 +5,6 @@ export declare const configSchema: z.ZodObject<{
5
5
  "review-mode": z.ZodOptional<z.ZodEnum<{
6
6
  direct: "direct";
7
7
  pr: "pr";
8
- review: "review";
9
8
  }>>;
10
9
  "version-file": z.ZodOptional<z.ZodString>;
11
10
  "changelog-file": z.ZodOptional<z.ZodString>;
@@ -15,17 +14,16 @@ export declare const configSchema: z.ZodObject<{
15
14
  }>>;
16
15
  "release-draft": z.ZodOptional<z.ZodBoolean>;
17
16
  "release-reference-comments": z.ZodOptional<z.ZodEnum<{
18
- off: "off";
19
17
  "best-effort": "best-effort";
18
+ off: "off";
20
19
  strict: "strict";
21
20
  }>>;
22
21
  "release-branch": z.ZodOptional<z.ZodString>;
23
22
  "baseline-file": z.ZodOptional<z.ZodString>;
24
- "next-release-file": z.ZodOptional<z.ZodString>;
25
23
  "bootstrap-sha": z.ZodOptional<z.ZodString>;
26
24
  "monorepo-mode": z.ZodOptional<z.ZodEnum<{
27
- independent: "independent";
28
25
  fixed: "fixed";
26
+ independent: "independent";
29
27
  }>>;
30
28
  "bump-minor-pre-major": z.ZodOptional<z.ZodBoolean>;
31
29
  "allow-stable-major": z.ZodOptional<z.ZodBoolean>;
@@ -45,15 +43,15 @@ export declare const configSchema: z.ZodObject<{
45
43
  "extra-files": z.ZodOptional<z.ZodArray<z.ZodObject<{
46
44
  type: z.ZodEnum<{
47
45
  json: "json";
48
- toml: "toml";
49
- yaml: "yaml";
50
46
  nix: "nix";
51
47
  regex: "regex";
48
+ toml: "toml";
49
+ yaml: "yaml";
52
50
  }>;
53
51
  path: z.ZodString;
54
52
  "field-path": z.ZodOptional<z.ZodString>;
55
- jsonpath: z.ZodOptional<z.ZodString>;
56
53
  pattern: z.ZodOptional<z.ZodString>;
54
+ replacement: z.ZodOptional<z.ZodString>;
57
55
  }, z.core.$strip>>>;
58
56
  follows: z.ZodOptional<z.ZodArray<z.ZodString>>;
59
57
  }, z.core.$strict>>>;