@oorabona/release-it-preset 1.1.0 → 1.3.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,6 +1,6 @@
1
1
  # @oorabona/release-it-preset
2
2
 
3
- Shared [release-it](https://github.com/release-it/release-it) configuration and scripts for automated versioning, changelog generation, and package publishing.
3
+ Shareable [release-it](https://github.com/release-it/release-it) configuration and scripts for automated versioning, changelog generation, and package publishing — for solo and small-team JavaScript maintainers who want Keep a Changelog discipline without the ceremony of changesets or the hands-off philosophy of semantic-release.
4
4
 
5
5
  [![NPM Version](https://img.shields.io/npm/v/@oorabona/release-it-preset.svg)](https://npmjs.org/package/@oorabona/release-it-preset)
6
6
  [![NPM Downloads](https://img.shields.io/npm/dm/@oorabona/release-it-preset.svg)](https://npmjs.org/package/@oorabona/release-it-preset)
@@ -10,7 +10,32 @@ Shared [release-it](https://github.com/release-it/release-it) configuration and
10
10
  [![CI](https://github.com/oorabona/release-it-preset/actions/workflows/ci.yml/badge.svg)](https://github.com/oorabona/release-it-preset/actions/workflows/ci.yml)
11
11
  [![Audit](https://github.com/oorabona/release-it-preset/actions/workflows/audit.yml/badge.svg)](https://github.com/oorabona/release-it-preset/actions/workflows/audit.yml)
12
12
  [![codecov](https://codecov.io/github/oorabona/release-it-preset/graph/badge.svg?token=6RMN34Z7TX)](https://codecov.io/github/oorabona/release-it-preset)
13
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.3+-blue.svg)](https://www.typescriptlang.org/)
13
+ [![TypeScript](https://img.shields.io/badge/TypeScript-supported-blue.svg)](https://www.typescriptlang.org/)
14
+
15
+ ## Quick Start (30 seconds)
16
+
17
+ ```bash
18
+ pnpm add -D release-it @oorabona/release-it-preset
19
+ pnpm release-it-preset init --with-workflows
20
+ ```
21
+
22
+ That's it. You now have:
23
+ - `.release-it.json` extending the `default` preset (auto-generated changelog from commits)
24
+ - A `CHANGELOG.md` with Keep a Changelog skeleton
25
+ - Release scripts in your `package.json` (`pnpm release:patch`, `release:minor`, `release:major`)
26
+ - A `.github/workflows/release.yml` that publishes via npm OIDC trusted publishing on tag push
27
+
28
+ Run a release:
29
+ ```bash
30
+ pnpm release-it-preset validate # pre-flight checks
31
+ pnpm release:minor # bump + commit + tag + push (CI publishes)
32
+ ```
33
+
34
+ **For monorepos:** `init` auto-detects `pnpm-workspace.yaml` / `package.json#workspaces` and scaffolds per-package `.release-it.json`.
35
+
36
+ **One-off (no install):** `pnpm dlx @oorabona/release-it-preset init --with-workflows`
37
+
38
+ → Full reference: [docs/USAGE.md](docs/USAGE.md) · [Migration v0→v1](docs/MIGRATION.md) · [Public API](docs/PUBLIC_API.md)
14
39
 
15
40
  ## Why this preset?
16
41
 
@@ -18,7 +43,7 @@ Most release workflows fall into one of three traps: too much manual work (plain
18
43
 
19
44
  `@oorabona/release-it-preset` occupies the productive middle ground for solo and small-team JavaScript package maintainers who want:
20
45
 
21
- - **Human-readable changelogs.** Keep a Changelog format (Added/Changed/Deprecated/Removed/Fixed/Security) generated automatically from conventional commits — no manual entry writing, no machine-format diffs. `[YANKED]` markers in version headings are preserved transparently; apply them manually post-release per the [Keep a Changelog spec](https://keepachangelog.com/en/1.1.0/).
46
+ - **Human-readable changelogs.** Keep a Changelog format (Added/Changed/Deprecated/Removed/Fixed/Security) generated automatically from conventional commits — no manual entry writing, no machine-format diffs. `[YANKED]` markers in version headings are preserved transparently.
22
47
  - **OIDC publishing without CI plumbing.** Import the reusable `publish.yml` workflow in three lines. OIDC trusted publishing with npm provenance ships on day one, no `NPM_TOKEN` secret required.
23
48
  - **Diagnostic confidence before release.** Run `release-it-preset doctor` to surface every misconfiguration — git auth, npm auth, changelog hygiene, branch requirements — before anything breaks in CI.
24
49
  - **Recovery presets for the real world.** Dedicated `republish` and `retry-publish` configs handle the scenarios other tools pretend don't happen.
@@ -36,1615 +61,52 @@ Most release workflows fall into one of three traps: too much manual work (plain
36
61
  | [changesets](https://github.com/changesets/changesets) | PR-driven versioning, fixed/linked package versions | 5+ maintainer monorepo, every change deserves explicit intent |
37
62
  | [semantic-release](https://github.com/semantic-release/semantic-release) | Fully-automated, zero human intervention | Branch-driven release pipelines, no human review of changelogs |
38
63
  | [release-please](https://github.com/googleapis/release-please) | GitHub Release PR pattern, 20+ language strategies | Polyglot repos, GitHub-native PR-driven workflow |
39
- | [`@release-it-plugins/workspaces`](https://github.com/release-it-plugins/workspaces) | Multi-package iteration + cross-pkg dep sync | Monorepo with bulk publish — composes with this preset (see [Composing with `@release-it-plugins/workspaces`](#composing-with-release-it-pluginsworkspaces)) |
40
-
41
- ## Table of Contents
42
-
43
- - [Why this preset?](#why-this-preset)
44
- - [Ecosystem positioning](#ecosystem-positioning)
45
- - [Features](#features)
46
- - [Installation](#installation)
47
- - [Install patterns](#install-patterns)
48
- - [Quick Start](#quick-start)
49
- - [Available Configurations](#available-configurations)
50
- - [CLI Usage](#cli-usage)
51
- - [Zero-Config Mode (Auto-Detection)](#zero-config-mode-auto-detection)
52
- - [Preset Selection Mode](#preset-selection-mode)
53
- - [Passthrough Mode (Custom Config Override)](#passthrough-mode-custom-config-override)
54
- - [Monorepo Support](#monorepo-support)
55
- - [Composing with `@release-it-plugins/workspaces`](#composing-with-release-it-pluginsworkspaces)
56
- - [Utility Commands](#utility-commands)
57
- - [Scripts](#scripts)
58
- - [Environment Variables](#environment-variables)
59
- - [Configuration Modes](#configuration-modes)
60
- - [Borrowing Scripts & Workflows](#borrowing-scripts--workflows)
61
- - [Release Workflow](#release-workflow)
62
- - [GitHub Actions Workflows](#github-actions-workflows)
63
- - [Reusable Workflows](#reusable-workflows)
64
- - [Workflow Reference](#workflow-reference)
65
- - [Exit codes](#exit-codes)
66
- - [Best Practices](#best-practices)
67
- - [Troubleshooting](#troubleshooting)
68
- - [Public API](#public-api)
69
- - [Contributing](#contributing)
64
+ | [`@release-it-plugins/workspaces`](https://github.com/release-it-plugins/workspaces) | Multi-package iteration + cross-pkg dep sync | Monorepo with bulk publish — composes with this preset |
70
65
 
71
66
  ## Features
72
67
 
73
- - 📦 Multiple release configurations for different scenarios
74
- - 📝 Automatic changelog generation using [Keep a Changelog](https://keepachangelog.com/) format
75
- - 🤖 Conventional commits parsing and categorization
76
- - 🏷️ Git tagging with optional GitHub release automation
77
- - 🚀 npm publishing with provenance (opt-in, ideal for CI)
78
- - 🔄 Republish and retry mechanisms for failed releases
79
- - Hotfix release support
80
- - 🎯 Environment variable configuration
81
- - 🔍 Zero-config auto-detection mode
82
- - 🏢 Monorepo support with parent directory config references
83
- - ⚙️ Passthrough mode for custom config files
84
-
85
- ## Installation
86
-
87
- ```bash
88
- pnpm add -D @oorabona/release-it-preset release-it
89
- ```
90
-
91
- ### Install patterns
92
-
93
- | Use case | Command | Notes |
94
- |---|---|---|
95
- | **Try without installing** | `pnpm dlx @oorabona/release-it-preset doctor` | Fetch + run, no install. Use for evaluating the preset on an existing repo. |
96
- | **One-shot npx** | `npx -y @oorabona/release-it-preset doctor` | Same idea, npm-flavored |
97
- | **Adopt as devDep** (recommended) | `pnpm add -D @oorabona/release-it-preset release-it` | Pins via lockfile, idiomatic for projects |
98
- | **CI usage** | `pnpm install --frozen-lockfile && pnpm exec release-it-preset retry-publish --ci` | Lockfile-deterministic, no prompts |
99
- | **Diagnostic on any repo** | `pnpm dlx @oorabona/release-it-preset doctor` | Works against the cwd's git/package.json/CHANGELOG; great for quick health checks |
100
-
101
- **Global install is not recommended** — pin per-project for reproducibility. The preset is small (<20KB unpacked); CI overhead is negligible.
102
-
103
- The peer requirement is `release-it ^19.0.0 || ^20.0.0`. CI runs against the upper bound (v20.x) on every commit; v19 was smoke-tested manually before the constraint was widened. v20 is recommended for the OIDC trusted publishing handshake (npm ≥ 11.5.1, Node ≥ 24); v19 is supported for composing with [`@release-it-plugins/workspaces`](#composing-with-release-it-pluginsworkspaces) (its peer maxes at v19 today).
104
-
105
- ## Quick Start
106
-
107
- ### Option 1: Using the CLI (Recommended)
108
-
109
- Add scripts to your `package.json`:
110
-
111
- ```json
112
- {
113
- "scripts": {
114
- "release": "release-it-preset default",
115
- "release:hotfix": "release-it-preset hotfix"
116
- }
117
- }
118
- ```
119
-
120
- Then run:
121
-
122
- ```bash
123
- pnpm release
124
- ```
125
-
126
- ### Option 2: Using extends
127
-
128
- Create `.release-it.json` in your project:
129
-
130
- ```json
131
- {
132
- "extends": "@oorabona/release-it-preset/config/default"
133
- }
134
- ```
135
-
136
- Add scripts to your `package.json`:
137
-
138
- ```json
139
- {
140
- "scripts": {
141
- "release": "release-it"
142
- }
143
- }
144
- ```
145
-
146
- ### Initialize CHANGELOG.md
147
-
148
- Create a `CHANGELOG.md` file with Keep a Changelog format:
149
-
150
- ```markdown
151
- # Changelog
152
-
153
- All notable changes to this project will be documented in this file.
154
-
155
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
156
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
157
-
158
- ## [Unreleased]
159
-
160
- ### Added
161
- - Initial release
162
- ```
163
-
164
- ## GitHub Actions
165
-
166
- ### Quick Start: Reusable Workflows
167
-
168
- Import pre-configured workflows into your repository:
169
-
170
- **PR Validation:**
171
- ```yaml
172
- name: PR Checks
173
-
174
- on:
175
- pull_request:
176
- types: [opened, synchronize, reopened]
177
-
178
- permissions:
179
- contents: read
180
- pull-requests: write
181
-
182
- jobs:
183
- validate:
184
- uses: oorabona/release-it-preset/.github/workflows/reusable-verify.yml@main
185
- with:
186
- base-ref: origin/${{ github.base_ref }}
187
- head-ref: ${{ github.sha }}
188
- run-tests: true
189
- secrets: inherit
190
- ```
191
-
192
- **Publish on Tag:**
193
- ```yaml
194
- name: Publish
195
-
196
- on:
197
- push:
198
- tags: ['v*']
199
-
200
- permissions:
201
- contents: write
202
- id-token: write
203
-
204
- jobs:
205
- publish:
206
- uses: oorabona/release-it-preset/.github/workflows/publish.yml@main
207
- secrets:
208
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
209
- ```
210
-
211
- 📖 **[Full Reusable Workflows Documentation](examples/reusable-workflows.md)** | 📚 **[CI/CD Integration Examples](examples/ci-integration.md)**
212
-
213
- ## Available Configurations
214
-
215
- ### `default` - Standard Release
216
-
217
- Full-featured release with changelog, git operations, and optional GitHub/npm publishing.
218
-
219
- **CLI:**
220
- ```bash
221
- pnpm release-it-preset default
222
- ```
223
-
224
- **Extends:**
225
- ```json
226
- {
227
- "extends": "@oorabona/release-it-preset/config/default"
228
- }
229
- ```
230
-
231
- Features:
232
- - ✅ Version bumping (interactive)
233
- - ✅ Automatic changelog population from conventional commits
234
- - ✅ Git commit, tag, and push
235
- - ☑️ GitHub release creation (set `GITHUB_RELEASE=true`)
236
- - ☑️ npm publishing with provenance (set `NPM_PUBLISH=true`)
237
-
238
- ### `hotfix` - Emergency Hotfix
239
-
240
- For urgent patches that need quick changelog generation from git log (GitHub/npm remain opt-in).
241
-
242
- **CLI:**
243
- ```bash
244
- pnpm release-it-preset hotfix
245
- ```
246
-
247
- **Extends:**
248
- ```json
249
- {
250
- "extends": "@oorabona/release-it-preset/config/hotfix"
251
- }
252
- ```
253
-
254
- Features:
255
- - ✅ Forced patch version increment
256
- - ✅ Automatic changelog from recent commits
257
- - ✅ Pre-bump unreleased section population
258
- - ☑️ GitHub release with extracted notes (set `GITHUB_RELEASE=true`)
259
- - ☑️ npm publishing with provenance (set `NPM_PUBLISH=true`)
260
-
261
- ### `changelog-only` - Changelog Preparation
262
-
263
- Updates changelog without performing a release (useful in CI or pre-release).
264
-
265
- **CLI:**
266
- ```bash
267
- pnpm release-it-preset changelog-only --ci
268
- ```
269
-
270
- **Extends:**
271
- ```json
272
- {
273
- "extends": "@oorabona/release-it-preset/config/changelog-only"
274
- }
275
- ```
276
-
277
- Features:
278
- - ✅ Populates [Unreleased] section
279
- - ❌ No version bump
280
- - ❌ No git operations
281
- - ❌ No publishing
282
-
283
- ### `manual-changelog` - Manual Changelog Release
284
-
285
- For releases where you've manually edited the [Unreleased] section in CHANGELOG.md.
286
- Skips automatic changelog generation while keeping GitHub/npm steps opt-in.
287
-
288
- **Workflow:**
289
- ```bash
290
- # 1. Generate initial changelog
291
- pnpm release-it-preset update
292
-
293
- # 2. Manually edit CHANGELOG.md [Unreleased] section
294
-
295
- # 3. Release without regenerating changelog
296
- pnpm release-it-preset manual-changelog
297
- ```
298
-
299
- **Extends:**
300
- ```json
301
- {
302
- "extends": "@oorabona/release-it-preset/config/manual-changelog"
303
- }
304
- ```
305
-
306
- Features:
307
- - ✅ Version bumping (interactive)
308
- - ✅ Preserves manual [Unreleased] edits
309
- - ✅ Moves [Unreleased] to versioned section
310
- - ✅ Git commit, tag, and push
311
- - ☑️ GitHub release creation (set `GITHUB_RELEASE=true`)
312
- - ☑️ npm publishing with provenance (set `NPM_PUBLISH=true`)
313
- - ❌ Skips automatic changelog population
314
-
315
- ### `no-changelog` - Quick Release
316
-
317
- Standard release without changelog updates; GitHub/npm steps remain opt-in.
318
-
319
- **CLI:**
320
- ```bash
321
- pnpm release-it-preset no-changelog
322
- ```
323
-
324
- **Extends:**
325
- ```json
326
- {
327
- "extends": "@oorabona/release-it-preset/config/no-changelog"
328
- }
329
- ```
330
-
331
- Features:
332
- - ✅ Version bumping
333
- - ✅ Git operations
334
- - ☑️ GitHub releases (set `GITHUB_RELEASE=true`)
335
- - ☑️ npm publishing (set `NPM_PUBLISH=true`)
336
- - ❌ No changelog updates
337
-
338
- ### `republish` - Git Tag Move + GitHub Release Update
339
-
340
- ⚠️ **DANGER**: Moves an existing git tag to HEAD and updates the GitHub release notes (breaks semver immutability for that tag).
341
-
342
- Only use when you need to fix a broken release that requires moving the git tag. This preset **does not publish to npm** — npm immutability (since 2016) makes republishing an existing version impossible under any dist-tag. See [ADR 0005](docs/adr/0005-republish-scope-narrowing.md).
343
-
344
- Alternatives:
345
- - **dist-tag change** (e.g. move `latest` to a different version): `npm dist-tag add @oorabona/release-it-preset@<version> latest`
346
- - **Retry a failed npm/GitHub publish**: use the `retry-publish` preset instead
347
-
348
- **CLI:**
349
- ```bash
350
- pnpm release-it-preset republish
351
- ```
352
-
353
- **Extends:**
354
- ```json
355
- {
356
- "extends": "@oorabona/release-it-preset/config/republish"
357
- }
358
- ```
359
-
360
- Features:
361
- - ⚠️ Moves existing git tag
362
- - ✅ Updates changelog for current version
363
- - ☑️ Updates GitHub release (set `GITHUB_RELEASE=true`)
364
- - ❌ Does not publish to npm (npm immutability — use `npm dist-tag add` or `retry-publish`)
365
-
366
- ### `retry-publish` - Retry Failed Publishing
367
-
368
- Retries npm/GitHub publishing for an existing tag without modifying git history; opt in to each surface via `NPM_PUBLISH` and `GITHUB_RELEASE`.
369
-
370
- **CLI:**
371
- ```bash
372
- # Step 1: Run pre-flight checks (optional)
373
- pnpm release-it-preset retry-publish-preflight
374
- # Advanced (direct compiled call)
375
- # node node_modules/@oorabona/release-it-preset/dist/scripts/retry-publish.js
376
-
377
- # Step 2: Retry the publish
378
- pnpm release-it-preset retry-publish
379
- ```
380
-
381
- **Extends:**
382
- ```json
383
- {
384
- "extends": "@oorabona/release-it-preset/config/retry-publish"
385
- }
386
- ```
387
-
388
- Features:
389
- - ☑️ Republishes to npm (set `NPM_PUBLISH=true`)
390
- - ☑️ Updates GitHub release (set `GITHUB_RELEASE=true`)
391
- - ❌ No version increment
392
- - ❌ No git operations
393
-
394
- ## CLI Usage
395
-
396
- The package provides a `release-it-preset` CLI with four operating modes:
397
-
398
- 1. **Zero-Config Mode** (auto-detection) - No arguments needed
399
- 2. **Preset Selection Mode** - Specify which preset to use
400
- 3. **Passthrough Mode** - Direct config file override
401
- 4. **Utility Mode** - Helper commands
402
-
403
- ### Zero-Config Mode (Auto-Detection)
404
-
405
- The CLI can automatically detect which preset to use from your `.release-it.json`:
406
-
407
- ```bash
408
- # Just run release-it-preset with no arguments
409
- pnpm release-it-preset
410
-
411
- # 🔍 Auto-detected preset: default
412
- # ✅ Config validated: preset "default"
413
- # 📝 Using: /path/to/.release-it.json
414
- ```
415
-
416
- **How it works:**
417
- 1. CLI reads your `.release-it.json`
418
- 2. Extracts the preset name from the `extends` field
419
- 3. Runs that preset automatically
420
-
421
- **Requirements:**
422
- - `.release-it.json` must exist
423
- - Must have `extends` field like `"@oorabona/release-it-preset/config/default"`
424
-
425
- **Benefits:**
426
- - ✅ Shortest command possible
427
- - ✅ Config file is source of truth
428
- - ✅ No need to remember preset names
429
- - ✅ Follows industry standards (ESLint, TypeScript, Prettier)
430
-
431
- ### Preset Selection Mode
432
-
433
- Run release-it with specific configurations:
434
-
435
- ```bash
436
- # Show help
437
- pnpm release-it-preset --help
438
-
439
- # Run releases
440
- pnpm release-it-preset default --dry-run
441
- pnpm release-it-preset hotfix --verbose
442
- pnpm release-it-preset changelog-only --ci
443
- pnpm release-it-preset manual-changelog
444
- ```
445
-
446
- All additional arguments are passed through to release-it.
447
-
448
- ### Passthrough Mode (Custom Config Override)
449
-
450
- Use a custom config file and bypass preset validation:
451
-
452
- ```bash
453
- # Use custom config file
454
- pnpm release-it-preset --config .release-it-manual.json
455
-
456
- # 🔀 Passthrough mode: using config .release-it-manual.json
457
- # Bypassing preset validation - direct release-it invocation
458
- ```
459
-
460
- **Use cases:**
461
- - **Switching presets occasionally** - Have multiple config files for different scenarios
462
- - **Monorepo workflows** - Reference shared configs from parent directories
463
- - **Advanced customization** - Full control over release-it configuration
464
-
465
- **Example workflow:**
466
-
467
- ```json
468
- // .release-it.json (default - 95% of time)
469
- {
470
- "extends": "@oorabona/release-it-preset/config/default",
471
- "git": { "requireBranch": "develop" }
472
- }
473
-
474
- // .release-it-manual.json (rare - 5% of time)
475
- {
476
- "extends": "@oorabona/release-it-preset/config/manual-changelog",
477
- "git": { "requireBranch": "develop" }
478
- }
479
- ```
480
-
481
- ```bash
482
- # Normal release
483
- pnpm release-it-preset # Auto-detects default
484
-
485
- # Manual changelog release (rare)
486
- pnpm release-it-preset --config .release-it-manual.json
487
- ```
488
-
489
- **Benefits:**
490
- - ✅ No need to edit `.release-it.json` to switch presets
491
- - ✅ Config files are explicit and version-controlled
492
- - ✅ Works with monorepo parent directory references
493
-
494
- ### Monorepo Support
495
-
496
- Parent directory config references are now supported:
497
-
498
- ```bash
499
- # Monorepo structure
500
- /my-monorepo/
501
- ├── .release-it-base.json # Shared configuration
502
- ├── packages/
503
- │ ├── core/
504
- │ │ └── .release-it.json # extends: ../../.release-it-base.json
505
- │ └── utils/
506
- │ └── .release-it.json # extends: ../../.release-it-base.json
507
- ```
508
-
509
- ```json
510
- // packages/core/.release-it.json
511
- {
512
- "extends": [
513
- "../../.release-it-base.json", // ✅ Parent reference allowed!
514
- "@oorabona/release-it-preset/config/default"
515
- ]
516
- }
517
- ```
518
-
519
- **Security validation:**
520
- - ✅ Parent directory references (`../`) supported (up to 5 levels)
521
- - ✅ Config file extension whitelist (`.json`, `.js`, `.cjs`, `.mjs`, `.yaml`, `.yml`, `.toml`)
522
- - ✅ File existence validation
523
- - ❌ Absolute paths blocked (use relative paths)
524
- - ❌ Excessive traversal blocked (max `../../../../../../`)
525
-
526
- **Why this is safe:**
527
- - Config files are trusted code (developer controls the repository)
528
- - Industry standard pattern (TypeScript, ESLint, Prettier all allow `../`)
529
- - Multiple validation layers prevent abuse
530
- - No privilege escalation in CLI tool context
531
-
532
- See [examples/monorepo-workflow.md](examples/monorepo-workflow.md) for complete monorepo guide and [examples/monorepo/](examples/monorepo/) for a runnable workspace demo.
533
-
534
- ### Composing with `@release-it-plugins/workspaces`
535
-
536
- This preset focuses on a single package per release-it run. If your monorepo needs **bulk publish** (iterate over every workspace package + sync cross-package dependency versions), compose this preset with [`@release-it-plugins/workspaces`](https://github.com/release-it-plugins/workspaces) — the canonical release-it plugin for that workflow.
537
-
538
- ```bash
539
- # Install both
540
- pnpm add -D @oorabona/release-it-preset @release-it-plugins/workspaces release-it@^19
541
- ```
542
-
543
- ```jsonc
544
- // .release-it.json — extends our preset AND loads the workspaces plugin
545
- {
546
- "extends": "@oorabona/release-it-preset/config/default",
547
- "plugins": {
548
- "@release-it-plugins/workspaces": true
549
- }
550
- }
551
- ```
552
-
553
- **Peer compatibility note:** `@release-it-plugins/workspaces` v5.0.3 declares peer `release-it ^17 || ^18 || ^19`. Our preset declares peer `^19 || ^20`. The intersection is `^19`, so when composing with the workspaces plugin you must pin release-it to v19. v20 standalone (without the workspaces plugin) is fully supported and recommended for new projects.
554
-
555
- `release-it-preset doctor` does **not** check whether the workspaces plugin is loaded — it's an opt-in composition. Run it manually after install if you want to verify the plugin's own preflight checks.
556
-
557
- When this composition is right for you:
558
- - You release multiple packages from one repo with **synchronized versions** (all bumped together).
559
- - You want **cross-package dependency sync** (when `pkg-a` bumps to 2.0, `pkg-b`'s reference auto-updates).
560
-
561
- When our preset alone is enough:
562
- - **Independent versioning** per package (each package releases when ready). Use `GIT_CHANGELOG_PATH=packages/<pkg>` to scope the CHANGELOG. See [examples/monorepo/](examples/monorepo/) for the runnable demo.
563
-
564
- ### Utility Commands
565
-
566
- Helper commands for project setup and maintenance:
567
-
568
- #### `init` - Initialize Project
569
-
570
- Creates CHANGELOG.md, .release-it.json, and optionally adds scripts to package.json:
571
-
572
- ```bash
573
- # Interactive mode (asks for confirmation)
574
- pnpm release-it-preset init
575
-
576
- # Non-interactive mode (skip prompts, use defaults)
577
- pnpm release-it-preset init --yes
578
- ```
579
-
580
- **What it does:**
581
- - Creates `CHANGELOG.md` with Keep a Changelog template
582
- - Creates `.release-it.json` with extends configuration
583
- - Optionally adds release scripts to `package.json`
584
- - Skips existing files in `--yes` mode
585
-
586
- > One-off usage: `pnpm dlx @oorabona/release-it-preset init` (or `npx @oorabona/release-it-preset init`) runs the CLI without installing it as a dependency.
587
-
588
- #### `update` - Update Changelog
589
-
590
- Updates the [Unreleased] section with commits since last tag:
591
-
592
- ```bash
593
- pnpm release-it-preset update
594
- ```
595
-
596
- **What it does:**
597
- - Parses conventional commits since last git tag
598
- - Groups commits by type (Added, Fixed, Changed, etc.)
599
- - Updates [Unreleased] section in CHANGELOG.md
600
- - Generates commit links to repository
601
- - Uses only the conventional commit subject; feel free to edit `CHANGELOG.md` afterwards if you want to add the detailed bullet points that lived in the commit body
602
-
603
- #### `validate` - Validate Release Readiness
604
-
605
- Checks if project is ready for release:
606
-
607
- ```bash
608
- # Standard validation
609
- pnpm release-it-preset validate
610
-
611
- # Allow uncommitted changes
612
- pnpm release-it-preset validate --allow-dirty
613
- ```
614
-
615
- **What it checks:**
616
- - ✅ CHANGELOG.md exists and is well-formatted
617
- - ✅ [Unreleased] section has content
618
- - ✅ Working directory is clean (unless --allow-dirty)
619
- - ✅ npm authentication works (npm whoami)
620
- - ✅ Current branch is allowed (if GIT_REQUIRE_BRANCH is set)
621
-
622
- Exit code 0 if all checks pass, 1 if any fail (useful in CI/pre-commit hooks).
623
-
624
- #### `check` - Diagnostic Information
625
-
626
- Displays configuration and project status:
627
-
628
- ```bash
629
- pnpm release-it-preset check
630
- ```
631
-
632
- **What it shows:**
633
- - Environment variables and their values
634
- - Repository information (URL, branch, remote)
635
- - Git tags and latest version
636
- - Commits since last tag
637
- - Configuration files status
638
- - npm authentication status
639
-
640
- Useful for debugging release issues.
641
-
642
- #### `doctor` - Release Readiness Diagnostic
643
-
644
- Runs a structured checklist across four categories and outputs a readiness score:
645
-
646
- ```bash
647
- pnpm release-it-preset doctor
648
- pnpm release-it-preset doctor --json
649
- ```
650
-
651
- **What it checks:**
652
-
653
- | Category | Checks |
654
- |----------|--------|
655
- | Environment | Known env vars, source (env / default / unset), publish-mode consistency |
656
- | Repository | Git repo presence, branch vs `GIT_REQUIRE_BRANCH`, latest tag, commit count, dirty WD, upstream tracking, remote URL |
657
- | Configuration | `CHANGELOG.md` exists + Keep a Changelog format + `[Unreleased]` content, `.release-it.json` parseable + `extends` field, `package.json` valid semver version, `release-it` peer range satisfied, `release-it` major version advisor |
658
- | Readiness Summary | `PASS`/`WARN`/`FAIL` counts, score `N/M checks passing`, status (`READY`/`WARNINGS`/`BLOCKED`), actionable recommendations |
659
-
660
- **Exit codes:**
661
- - `0` — status is `READY` or `WARNINGS`
662
- - `1` — status is `BLOCKED` (at least one `FAIL`)
663
-
664
- **`--json` output shape:**
665
- ```json
666
- {
667
- "environment": { "checks": [...], "vars": [...], "status": "PASS" },
668
- "repository": { "checks": [...], "status": "WARN" },
669
- "configuration": { "checks": [...], "status": "PASS" },
670
- "summary": {
671
- "pass": 10, "warn": 2, "fail": 0, "total": 12,
672
- "score": "10/12 checks passing",
673
- "status": "WARNINGS",
674
- "recommendations": ["Review 2 warning(s) before releasing"]
675
- }
676
- }
677
- ```
678
-
679
- Use `doctor` as a pre-release sanity check, and `check` for the full verbose configuration dump.
680
-
681
- #### `check-pr` - Pull Request Hygiene
682
-
683
- Evaluates PR readiness by analysing commits and changelog changes. Designed for CI usage but safe locally when the required environment variables are set (`PR_BASE_REF`, `PR_HEAD_REF`).
684
-
685
- ```bash
686
- PR_BASE_REF=origin/main PR_HEAD_REF=HEAD pnpm release-it-preset check-pr
687
- ```
688
-
689
- Outputs JSON summaries for workflows (base64 encoded) and prints a human-readable report.
690
-
691
- #### `retry-publish-preflight` - Retry Safety Checks
692
-
693
- Runs the retry publish pre-flight script with the same CLI convenience wrapper as other utilities. Verifies that the latest tag exists, matches `package.json`, and that there are no unexpected workspace changes before attempting a retry.
694
-
695
- ```bash
696
- pnpm release-it-preset retry-publish-preflight
697
- ```
698
-
699
- Use this before calling `pnpm release-it-preset retry-publish` when recovering from a failed publish.
700
-
701
- ### pnpm Script Shortcuts
702
-
703
- The root `package.json` defines helper scripts that wrap the CLI so you can run the most common flows with `pnpm run`:
704
-
705
- - `pnpm release` → run the default release config (`release-it-preset default`)
706
- - `pnpm run release:default:dry-run` → dry-run the default release configuration
707
- - `pnpm run release:no-changelog` → publish without touching the changelog
708
- - `pnpm run release:changelog-only` → update only the changelog
709
- - `pnpm run release:manual-changelog` → release with manually edited changelog (skip auto-generation)
710
- - `pnpm run release:hotfix` → execute the hotfix workflow
711
- - `pnpm run release:republish` → trigger the republish workflow (dangerous flow)
712
- - `pnpm run release:retry-preflight` → run retry publish safety checks
713
- - `pnpm run release:retry-publish` → retry npm/GitHub publishing for an existing tag
714
- - `pnpm run release:update` → populate the `[Unreleased]` section
715
- - `pnpm run release:validate` → run release validation checks
716
- - `pnpm run release:validate:allow-dirty` → validation that tolerates uncommitted changes
717
- - `pnpm run release:check` → show diagnostic information about the current repo
718
-
719
- ## Scripts
720
-
721
- Scripts are authored in TypeScript but distributed as compiled ESM JavaScript in `dist/scripts`. Under normal circumstances you should invoke them via the `release-it-preset` CLI or the pnpm aliases listed above; the CLI automatically prefers the compiled build and falls back to `tsx` only for local development. The direct `node` examples below are provided for automation scenarios where you deliberately want to call the compiled output.
722
-
723
- ### `extract-changelog.ts`
724
-
725
- Extracts the changelog entry for a specific version (used automatically by the release notes generator). If you ever need to call it manually:
726
-
727
- ```bash
728
- node node_modules/@oorabona/release-it-preset/dist/scripts/extract-changelog.js 1.2.3
729
- ```
730
-
731
- ### `populate-unreleased-changelog.ts`
732
-
733
- Populates the [Unreleased] section with commits since the last tag using conventional commits.
734
-
735
- ```bash
736
- # Preferred
737
- pnpm release-it-preset update
738
- # or
739
- pnpm run release:update
740
-
741
- # Advanced (call compiled output directly)
742
- node node_modules/@oorabona/release-it-preset/dist/scripts/populate-unreleased-changelog.js
743
- ```
744
-
745
- Supported commit types:
746
- - `feat`, `feature`, `add` → Added
747
- - `fix`, `bugfix` → Fixed
748
- - `deprecate`, `deprecated`, `deprecation` → Deprecated
749
- - `perf`, `refactor`, `style`, `docs`, `test`, `chore`, `build` → Changed
750
- - `remove`, `removed`, `delete`, `deleted` → Removed
751
- - `security` → Security
752
- - `ci`, `release`, `hotfix` → Ignored
753
-
754
- Add `[skip-changelog]` to commit message to exclude it.
755
-
756
- ### `republish-changelog.ts`
68
+ - **One-command init** — `init --with-workflows` scaffolds `.release-it.json`, `CHANGELOG.md`, `package.json` scripts, and a GitHub Actions publish workflow.
69
+ - **Seven release configs** — `default`, `hotfix`, `manual-changelog`, `no-changelog`, `changelog-only`, `republish`, `retry-publish` — each tuned for a specific scenario. → [docs/USAGE.md#configurations](docs/USAGE.md#available-configurations)
70
+ - **Doctor command** pre-release diagnostics: branch state, publish workflow freshness, npm provenance readiness, peer-dep range, CHANGELOG validity, readiness score. → [docs/USAGE.md#doctor](docs/USAGE.md#doctor---release-readiness-diagnostic)
71
+ - **OIDC trusted publishing** zero-config npm provenance via GitHub Actions OIDC; no `NPM_TOKEN` secret needed when using the reusable `publish.yml` workflow.
72
+ - **Monorepo support** `init` auto-detects workspace manifests; `GIT_CHANGELOG_PATH` scopes changelog generation per package.
73
+ - **Recovery flows** `republish` / `retry-publish` for the inevitable "first publish failed at npm step" moment.
74
+ - **Smart dist-tag selection** — pre-releases (`-rc`, `-beta`) auto-publish under non-`latest` tags.
75
+ - **Conventional Commits aware** — auto-generated `[Unreleased]` from commit history, with curatable manual edits preserved.
76
+ - **Reusable GitHub workflows** — `publish.yml`, `hotfix.yml`, `republish.yml` shipped as composable callables.
77
+ - **TypeScript-first** DI pattern in scripts, fully testable (213 unit tests).
757
78
 
758
- Moves [Unreleased] content to the current version entry (for republishing).
79
+ ## Installation & requirements
759
80
 
760
- ```bash
761
- # Preferred
762
- pnpm run release:republish
763
- # or
764
- pnpm release-it-preset republish
765
-
766
- # Advanced
767
- node node_modules/@oorabona/release-it-preset/dist/scripts/republish-changelog.js
768
- ```
769
-
770
- ### `retry-publish.ts`
771
-
772
- Performs pre-flight checks before retrying a failed publish.
773
-
774
- ```bash
775
- # Preferred (CLI)
776
- pnpm release-it-preset retry-publish-preflight
777
-
778
- # Advanced (call compiled output directly)
779
- node node_modules/@oorabona/release-it-preset/dist/scripts/retry-publish.js
780
- ```
781
-
782
- ## Environment Variables
783
-
784
- Customize behavior with environment variables:
785
-
786
- ### Changelog
787
- - `CHANGELOG_FILE` - Changelog file path (default: `CHANGELOG.md`)
788
- - `GIT_CHANGELOG_PATH` - Optional. When set to a repository-relative path (e.g. `packages/tar-xz`), restrict changelog generation to commits touching that path. Useful for monorepo per-package CHANGELOG files. Empty / unset = repository-wide (default).
789
- - `GIT_CHANGELOG_SINCE` - Optional. Override the `since` baseline for changelog generation (any git ref: SHA, tag, branch). When set, bypasses both the per-package release-commit detection and the `git describe --tags` fallback. Useful for monorepo workspaces with non-standard release commit patterns. Empty / unset = use auto-detection.
790
- - `CHANGELOG_TYPE_MAP` - Optional. JSON string mapping commit types to CHANGELOG section headings. Merged on top of `.changelog-types.json` (if present) and the built-in defaults. Use `false` as a value to suppress a type entirely. Example: `CHANGELOG_TYPE_MAP='{"ops":"### Operations","deps":"### Dependencies"}'`.
791
-
792
- ### Custom type map (`.changelog-types.json`)
793
-
794
- Create a `.changelog-types.json` file in your project root to override or extend the built-in commit-type → section mapping at the project level. The file is merged on top of the built-in defaults; individual keys can be overridden without touching the rest.
795
-
796
- **Resolution order** (highest priority wins):
797
- 1. `CHANGELOG_TYPE_MAP` env var (runtime override, e.g. in CI)
798
- 2. `.changelog-types.json` project file
799
- 3. Built-in defaults
800
-
801
- **Example `.changelog-types.json`:**
802
- ```json
803
- {
804
- "deps": "### Dependencies",
805
- "ops": "### Operations",
806
- "ci": false
807
- }
808
- ```
809
- - String values must be a valid `### Section Heading`.
810
- - `false` suppresses the type (no CHANGELOG entry emitted).
811
- - Malformed JSON or invalid values → warning logged, layer ignored, lower-priority map used.
812
-
813
- **BREAKING CHANGE: footer parsing** (Conventional Commits 1.0.0 §6): `BREAKING CHANGE:` is recognised as a footer only when it appears after a blank-line separator from the preceding paragraph. Mid-body occurrences without the blank line do not promote the commit to breaking. Multiple `BREAKING CHANGE:` lines in the same footer paragraph each emit a separate entry under `### ⚠️ BREAKING CHANGES`.
814
-
815
- ### Git
816
- - `GIT_COMMIT_MESSAGE` - Commit message template. Defaults vary per preset: `chore(release): v${version}` (`default`), `chore(hotfix): v${version}` (`hotfix`), `chore: republish v${version}` (`republish`). Set this env var to override across all presets.
817
- - `GIT_TAG_NAME` - Tag name template (default: `v${version}`)
818
- - `GIT_REQUIRE_BRANCH` - Required branch (default: `main`)
819
- - `GIT_REQUIRE_UPSTREAM` - Require upstream tracking (default: `false`)
820
- - `GIT_REQUIRE_CLEAN` - Require clean working directory (default: `false`)
821
- - `GIT_REMOTE` - Git remote name (default: `origin`)
822
- - `GIT_CHANGELOG_COMMAND` - Override the git log command used for previews (default filters out release/hotfix/ci commits)
823
- - `GIT_CHANGELOG_DESCRIBE_COMMAND` - Override the latest-tag detection command (default: `git describe --tags --abbrev=0`)
824
-
825
- ### GitHub
826
- - `GITHUB_RELEASE` - Enable GitHub releases (default: `false`)
827
- - `GITHUB_REPOSITORY` - Repository in `owner/repo` format (auto-detected from git remote)
828
-
829
- ### npm
830
- - `NPM_PUBLISH` - Enable npm publishing (default: `false`)
831
- - `NPM_SKIP_CHECKS` - Skip npm checks (default: `false`)
832
- - `NPM_ACCESS` - npm access level (default: `public`)
833
- - `NPM_TAG` - Optional. When set, the npm publish step appends `--tag <value>` (e.g. `legacy-v0.10.0`). Used to assign version-named dist-tags when republishing older versions so `latest` is not overwritten. Empty / unset = npm uses `latest`.
834
-
835
- ### Hotfix
836
- - `HOTFIX_INCREMENT` - Increment kind passed to release-it for the `hotfix` preset (default: `patch`). Accepts any release-it increment value (`patch`, `minor`, `major`, or an explicit version).
837
-
838
- > ℹ️ By default, the presets skip GitHub releases and npm publishing. Set `GITHUB_RELEASE=true` and/or `NPM_PUBLISH=true` in the environment (typically in CI) when you are ready to perform those steps.
839
-
840
- ### Example
841
-
842
- ```bash
843
- CHANGELOG_FILE="HISTORY.md" \
844
- GIT_REQUIRE_BRANCH="develop" \
845
- GIT_REQUIRE_CLEAN="true" \
846
- pnpm release
847
- ```
848
-
849
- ## Configuration Modes
850
-
851
- The preset supports two configuration modes:
852
-
853
- ### Mode 1: Direct Preset Usage (No Config File)
854
-
855
- **When to use:** Simple projects, trust preset defaults, or customize only via environment variables
856
-
857
- Don't create `.release-it.json`. Just run the CLI:
81
+ - **Node.js** >= 20.19.0
82
+ - **Package manager:** pnpm, npm, or yarn
83
+ - **Peer dependency:** `release-it ^19.0.0 || ^20.0.0` (v20 recommended for OIDC publishing)
84
+ - **TypeScript:** built with TypeScript 6; TypeScript 5+ projects are supported via the compiled ESM distribution
858
85
 
859
86
  ```bash
860
- pnpm release-it-preset default
87
+ pnpm add -D release-it @oorabona/release-it-preset
861
88
  ```
862
89
 
863
- All configuration comes from the preset and environment variables.
864
-
865
- **Pros:**
866
- - ✅ Zero config files
867
- - ✅ Consistent behavior across projects
868
- - ✅ Easy to understand
869
- - ✅ Perfect for getting started
870
-
871
- ---
872
-
873
- ### Mode 2: Preset + User Overrides (Recommended)
874
-
875
- **When to use:** Customize specific options while keeping preset defaults
876
-
877
- Create `.release-it.json` **WITH the `extends` field**:
878
-
879
- ```json
880
- {
881
- "extends": "@oorabona/release-it-preset/config/default",
882
- "git": {
883
- "requireBranch": "master",
884
- "commitMessage": "chore: release v${version}"
885
- }
886
- }
887
- ```
888
-
889
- Run with CLI preset:
890
-
891
- ```bash
892
- pnpm release-it-preset default
893
- ```
894
-
895
- **How it works:**
896
- - The `extends` field loads the preset
897
- - release-it merges your overrides on top via c12
898
- - **Your values take precedence** over preset defaults
899
- - CLI validates that `extends` matches the command
900
-
901
- **Pros:**
902
- - ✅ **Recommended for customization**
903
- - ✅ Declarative config with explicit preset
904
- - ✅ Industry standard pattern (like ESLint, TypeScript)
905
- - ✅ Guaranteed config merging via release-it's c12
906
-
907
- **Example:** Using `hotfix` preset but release from `master` instead of `main`:
908
-
909
- ```json
910
- {
911
- "extends": "@oorabona/release-it-preset/config/hotfix",
912
- "git": {
913
- "requireBranch": "master"
914
- }
915
- }
916
- ```
917
-
918
- ```bash
919
- pnpm release-it-preset hotfix
920
- ```
921
-
922
- ---
923
-
924
- ### Configuration Validation
925
-
926
- The CLI validates your `.release-it.json` to prevent misconfigurations:
927
-
928
- #### Error 1: Missing `extends` field
929
-
930
- ```bash
931
- # .release-it.json without extends:
932
- {
933
- "git": { "requireBranch": "master" }
934
- }
935
-
936
- # Running:
937
- pnpm release-it-preset default
938
-
939
- # ❌ Configuration error!
940
- # .release-it.json is missing the required "extends" field.
941
- #
942
- # Without "extends", your config won't merge with the preset.
943
- # This means you'll get release-it defaults instead of preset defaults.
944
- #
945
- # Fix by adding this to .release-it.json:
946
- # {
947
- # "extends": "@oorabona/release-it-preset/config/default",
948
- # ...your overrides
949
- # }
950
- ```
951
-
952
- **Why `extends` is required:** Without it, release-it only loads your config file and uses release-it's own defaults. The preset is never loaded, so you lose important defaults like `npm.publish: false`.
953
-
954
- #### Error 2: Preset mismatch
955
-
90
+ **Try without installing:**
956
91
  ```bash
957
- # .release-it.json extends "default":
958
- {
959
- "extends": "@oorabona/release-it-preset/config/default"
960
- }
961
-
962
- # But you run:
963
- pnpm release-it-preset hotfix
964
-
965
- # ❌ Configuration mismatch error!
966
- # CLI preset: hotfix
967
- # .release-it.json extends: default
968
- #
969
- # Either:
970
- # 1. Run: release-it-preset default
971
- # 2. Update .release-it.json extends to: "@oorabona/release-it-preset/config/hotfix"
972
- ```
973
-
974
- ---
975
-
976
- ### Which Mode Should I Use?
977
-
978
- | Scenario | Recommended Mode |
979
- |----------|------------------|
980
- | Quick start, minimal config | **Mode 1** (No config file) |
981
- | Customize branch/commit/hooks | **Mode 2** (Config with extends) |
982
- | Environment-only customization | **Mode 1** (Use env vars) |
983
- | Monorepo with per-package config | **Mode 2** (Each package has own config) |
984
-
985
- **Use Mode 1 to get started, switch to Mode 2 when you need customization.**
986
-
987
- ## Borrowing Scripts & Workflows
988
-
989
- - The root `package.json` of this repository shows how to expose convenient `pnpm run release:*` shortcuts. Feel free to copy that block into your own project (adjust the commands if you only need a subset).
990
- - The GitHub Actions workflows under `.github/workflows/*.yml` illustrate how to wire the CLI into CI. They are safe to reuse, provided you review the permissions/secrets section and adapt branch names or triggers to your process.
991
-
992
- ## Release Workflow
993
-
994
- ### Recommended Workflow
995
-
996
- **Local (Developer):**
997
- 1. Make changes and commit with conventional commits
998
- 2. Run `pnpm run release:update` to populate the `[Unreleased]` section from commits
999
- 3. Review `CHANGELOG.md` - you have two options here:
1000
-
1001
- **Option A: Quick release with auto-generated changelog**
1002
- - Stage `CHANGELOG.md` as-is
1003
- - Run `pnpm run release:validate` to verify readiness
1004
- - Dry-run with `pnpm run release:default:dry-run`
1005
- - Execute `pnpm release` to perform the real release
1006
-
1007
- **Option B: Manual changelog editing (recommended for detailed release notes)**
1008
- - Manually edit `CHANGELOG.md` [Unreleased] section (add narrative, reorganize, etc.)
1009
- - No need to stage or commit
1010
- - Run `pnpm run release:validate` (or `pnpm run release:validate:allow-dirty`)
1011
- - Dry-run with `pnpm run release:manual-changelog --dry-run`
1012
- - Execute `pnpm run release:manual-changelog` to release
1013
- - This skips changelog regeneration, preserving your edits
1014
- - Bumps version, moves [Unreleased] to versioned section
1015
- - Creates release commit + tag and pushes to origin (GitHub release happens later if `GITHUB_RELEASE=true` in CI)
1016
-
1017
- **If you change your mind mid-release:** If you started with Option A but want to add manual edits when prompted `Commit (chore(release): vX.Y.Z)?`, answer **No**, then press Ctrl+C to abort. Edit your `CHANGELOG.md`, then run `pnpm run release:manual-changelog` instead. Alternatively, re-run `pnpm release` and select the same version again (the preset's `--allow-same-version` makes this safe).
1018
-
1019
- 4. **Note:** GitHub releases and npm publish are skipped locally by default. Enable them with environment variables or let the `publish.yml` workflow handle both steps after the tag push.
1020
-
1021
- ```mermaid
1022
- flowchart TD
1023
- A[Conventional commits] --> B[pnpm run release:update]
1024
- B --> C{Want to edit<br/>changelog manually?}
1025
-
1026
- C -->|No - Auto changelog| D[Stage CHANGELOG.md]
1027
- D --> E[pnpm run release:validate]
1028
- E --> F[pnpm run release:default:dry-run]
1029
- F --> G[pnpm release]
1030
-
1031
- C -->|Yes - Manual editing| H[Edit CHANGELOG.md manually]
1032
- H --> I[pnpm run release:validate --allow-dirty]
1033
- I --> J[pnpm run release:manual-changelog --dry-run]
1034
- J --> K[pnpm run release:manual-changelog]
1035
-
1036
- G --> L[Push commit \u0026 tag]
1037
- K --> L
1038
- L --> M[Publish workflow runs in CI]
1039
- ```
1040
-
1041
- **CI (GitHub Actions):**
1042
- - When tag is pushed, CI publishes to npm with provenance
1043
-
1044
- ### Why This Workflow?
1045
-
1046
- - **Single CI entry point** - Tag pushes run the `retry-publish` preset, which updates the GitHub release and publishes to npm with provenance in one command.
1047
- - **Local runs stay safe** - Without `GITHUB_RELEASE=true` or `NPM_PUBLISH=true`, the presets only handle changelog updates, commits, and tags.
1048
- - **Better security** - Publishing requires CI credentials (GITHUB_TOKEN + NPM_TOKEN), keeping local environments token-free by default.
1049
- - **Predictable outputs** - Release notes are regenerated from the committed changelog, avoiding drift between local runs and CI.
1050
-
1051
- ### GitHub Actions Setup
1052
-
1053
- Create `.github/workflows/publish.yml`:
1054
-
1055
- ```yaml
1056
- name: Publish Package
1057
-
1058
- on:
1059
- push:
1060
- tags:
1061
- - 'v*'
1062
-
1063
- permissions:
1064
- contents: write
1065
- id-token: write # For npm provenance
1066
-
1067
- jobs:
1068
- publish:
1069
- runs-on: ubuntu-latest
1070
- steps:
1071
- - uses: actions/checkout@v4
1072
-
1073
- - uses: pnpm/action-setup@v4
1074
-
1075
- - uses: actions/setup-node@v4
1076
- with:
1077
- node-version: 20
1078
- registry-url: 'https://registry.npmjs.org'
1079
- cache: 'pnpm'
1080
-
1081
- - run: pnpm install --frozen-lockfile
1082
-
1083
- - run: pnpm build
1084
-
1085
- - name: Update GitHub release and publish to npm
1086
- run: pnpm release-it-preset retry-publish --ci
1087
- env:
1088
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
1089
- NPM_PUBLISH: 'true'
1090
- GITHUB_RELEASE: 'true'
1091
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1092
- ```
1093
-
1094
- **Required Secrets:**
1095
- - `NPM_TOKEN` - Automation token from npmjs.com (Settings → Access Tokens → Generate New Token → Automation)
1096
- - `GITHUB_TOKEN` is provided automatically by GitHub Actions (no manual secret needed)
1097
-
1098
- **Required Permissions (locally):**
1099
- - Set `GITHUB_RELEASE=true` and/or `NPM_PUBLISH=true` only when you explicitly want to perform those actions from your machine. Provide `GITHUB_TOKEN`/`NPM_TOKEN` as needed.
1100
-
1101
- ### Alternative: Full CI Release
1102
-
1103
- If you prefer to run the entire release in CI:
1104
-
1105
- ```yaml
1106
- on:
1107
- workflow_dispatch: # Manual trigger
1108
- inputs:
1109
- version:
1110
- description: 'Version bump type'
1111
- required: true
1112
- type: choice
1113
- options: [patch, minor, major]
1114
-
1115
- permissions:
1116
- contents: write # For git operations and GitHub releases
1117
- id-token: write # For npm provenance
1118
-
1119
- jobs:
1120
- release:
1121
- runs-on: ubuntu-latest
1122
- steps:
1123
- # ... setup steps ...
1124
-
1125
- - run: pnpm release-it-preset default --ci --increment ${{ inputs.version }}
1126
- env:
1127
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1128
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
1129
- GITHUB_RELEASE: 'true'
1130
- NPM_PUBLISH: 'true'
1131
- ```
1132
-
1133
- ## GitHub Actions Workflows
1134
-
1135
- This repository includes several GitHub Actions workflows for automated CI/CD and release management.
1136
-
1137
- ### Reusable Workflows
1138
-
1139
- Two workflows are designed for reuse in your own projects:
1140
-
1141
- #### 🔄 `reusable-verify.yml` - PR Validation & Hygiene Checks
1142
-
1143
- Validates TypeScript compilation, runs tests, checks release readiness, and evaluates PR hygiene (changelog updates, conventional commits).
1144
-
1145
- **When to use:** Import this workflow in your PR validation to ensure code quality and release readiness.
1146
-
1147
- **Inputs:**
1148
-
1149
- | Input | Type | Default | Description |
1150
- |-------|------|---------|-------------|
1151
- | `node-version` | string | `'20'` | Node.js version to use |
1152
- | `run-tests` | boolean | `false` | Run `pnpm test` after compilation |
1153
- | `base-ref` | string | `''` | Base ref for diff comparisons (e.g., `origin/main`) |
1154
- | `head-ref` | string | `'HEAD'` | Head ref for comparisons |
1155
- | `install-args` | string | `'--frozen-lockfile'` | Additional pnpm install arguments |
1156
- | `fetch-depth` | number | `0` | Git fetch depth for checkout |
1157
-
1158
- **Outputs:**
1159
-
1160
- | Output | Description |
1161
- |--------|-------------|
1162
- | `release_validation` | `'true'` when release validation passes |
1163
- | `changelog_status` | Changelog status: `updated`, `skipped`, or `missing` |
1164
- | `skip_changelog` | `'true'` when `[skip-changelog]` detected in commits |
1165
- | `conventional_commits` | `'true'` when conventional commits detected |
1166
- | `commit_messages` | Base64 encoded JSON array of analyzed commit messages |
1167
- | `changed_files` | Base64 encoded JSON array of changed files |
1168
-
1169
- **Example usage in your project:**
1170
-
1171
- ```yaml
1172
- # .github/workflows/validate-pr.yml
1173
- name: PR Validation
1174
-
1175
- on:
1176
- pull_request:
1177
- types: [opened, synchronize, reopened]
1178
-
1179
- jobs:
1180
- validate:
1181
- uses: oorabona/release-it-preset/.github/workflows/reusable-verify.yml@main
1182
- with:
1183
- node-version: '20'
1184
- base-ref: origin/${{ github.base_ref }}
1185
- head-ref: ${{ github.sha }}
1186
- run-tests: true
1187
- secrets: inherit
1188
-
1189
- comment:
1190
- needs: validate
1191
- runs-on: ubuntu-latest
1192
- if: always()
1193
- permissions:
1194
- pull-requests: write
1195
- steps:
1196
- - uses: actions/github-script@v7
1197
- with:
1198
- script: |
1199
- const summary = `## 📋 PR Validation
1200
-
1201
- ${needs.validate.outputs.release_validation === 'true' ? '✅' : '⚠️'} Release validation
1202
- ${needs.validate.outputs.changelog_status === 'updated' ? '✅' : 'ℹ️'} Changelog: ${needs.validate.outputs.changelog_status}
1203
- ${needs.validate.outputs.conventional_commits === 'true' ? '✅' : 'ℹ️'} Conventional commits
1204
- `;
1205
-
1206
- github.rest.issues.createComment({
1207
- owner: context.repo.owner,
1208
- repo: context.repo.repo,
1209
- issue_number: context.issue.number,
1210
- body: summary
1211
- });
92
+ pnpm dlx @oorabona/release-it-preset doctor # health check on any repo
93
+ pnpm dlx @oorabona/release-it-preset init # scaffold a new project
1212
94
  ```
1213
95
 
1214
- #### 🔄 `build-dist.yml` - Build Compiled Distribution
96
+ ## CHANGELOG
1215
97
 
1216
- Builds TypeScript sources to `dist/` and uploads as artifact for reuse in other jobs.
98
+ See [CHANGELOG.md](CHANGELOG.md) for all version history, or browse [GitHub Releases](https://github.com/oorabona/release-it-preset/releases).
1217
99
 
1218
- **When to use:** When you need compiled outputs across multiple jobs without rebuilding.
100
+ ## Contributing & support
1219
101
 
1220
- **Inputs:**
102
+ - [CONTRIBUTING.md](CONTRIBUTING.md) — Conventional Commits, branch prefixes, pre-PR checklist, testing conventions
103
+ - [SUPPORT.md](SUPPORT.md) — where to ask questions, file bugs, and report security issues
104
+ - [Discussions](https://github.com/oorabona/release-it-preset/discussions) — Q&A, usage tips, ideas
105
+ - [Issues](https://github.com/oorabona/release-it-preset/issues) — bugs + feature requests (use templates)
106
+ - [SECURITY.md](SECURITY.md) — vulnerability reporting (do NOT use public issues)
1221
107
 
1222
- | Input | Type | Default | Description |
1223
- |-------|------|---------|-------------|
1224
- | `artifact_name` | string | `'dist-build'` | Name for the uploaded dist artifact |
1225
- | `ref` | string | (current) | Optional git ref to checkout before building |
1226
-
1227
- **Outputs:**
1228
-
1229
- | Output | Description |
1230
- |--------|-------------|
1231
- | `artifact_name` | Name of the uploaded dist artifact |
1232
-
1233
- **Example usage in your project:**
1234
-
1235
- ```yaml
1236
- # .github/workflows/ci.yml
1237
- jobs:
1238
- build:
1239
- uses: oorabona/release-it-preset/.github/workflows/build-dist.yml@main
1240
- with:
1241
- artifact_name: my-dist
1242
- ref: ${{ github.sha }}
1243
-
1244
- test:
1245
- needs: build
1246
- runs-on: ubuntu-latest
1247
- steps:
1248
- - uses: actions/checkout@v4
1249
- - uses: actions/download-artifact@v4
1250
- with:
1251
- name: ${{ needs.build.outputs.artifact_name }}
1252
- path: dist
1253
- - run: pnpm test
1254
- ```
1255
-
1256
- ### Workflow Reference
1257
-
1258
- #### Overview Table
1259
-
1260
- | Workflow | Type | Trigger | Purpose |
1261
- |----------|------|---------|---------|
1262
- | 🔄 [reusable-verify.yml](#-reusable-verifyyml---pr-validation--hygiene-checks) | Reusable | `workflow_call` | PR validation & hygiene checks |
1263
- | 🔄 [build-dist.yml](#-build-distyml---build-compiled-distribution) | Reusable | `workflow_call` | Build TypeScript distribution |
1264
- | ⚙️ [ci.yml](#1-️-ci-github-workflowsciyml) | Standalone | Push, PR, Manual | Continuous Integration |
1265
- | ✅ [validate-pr.yml](#2--validate-pr-github-workflowsvalidate-pryml) | Standalone | PR | Pull request validation |
1266
- | 🚨 [hotfix.yml](#3--hotfix-release-github-workflowshotfixyml) | Manual | `workflow_dispatch` | Emergency hotfix releases |
1267
- | 🔄 [retry-publish.yml](#4--retry-publish-github-workflowsretry-publishyml) | Manual | `workflow_dispatch` | Retry failed publishing |
1268
- | ⚠️ [republish.yml](#5-️-republish-exceptional-github-workflowsrepublishyml) | Manual | `workflow_dispatch` | Republish existing version |
1269
- | 📦 [publish.yml](#6--publish-github-workflowspublishyml) | Reusable | Tag push, `workflow_call` | Automated publishing |
1270
-
1271
- You can copy these workflows into your own repository (adjusting names, branches, and secrets to match your context). They work with the release-it-preset CLI defaults.
1272
-
1273
- #### 1. ⚙️ **CI** (`.github/workflows/ci.yml`)
1274
-
1275
- **Triggers:**
1276
- - Push to `main`
1277
- - Pull Requests to `main`
1278
- - Manual (`workflow_dispatch`)
1279
-
1280
- **Jobs:**
1281
- - `build-dist` - Builds compiled distribution using reusable workflow
1282
- - `tests` - Runs unit tests with coverage
1283
- - `test-cli` - Tests all CLI commands (help, check, validate, init)
1284
- - `release` - Manual release creation (workflow_dispatch only)
1285
-
1286
- **Manual Release:**
1287
- ```bash
1288
- # Go to Actions → CI → Run workflow
1289
- # Select increment type: patch, minor, or major
1290
- ```
1291
-
1292
- **Secrets required:**
1293
- - `NPM_TOKEN` - npm automation token (for release job)
1294
- - `CODECOV_TOKEN` - Codecov upload token (optional)
1295
-
1296
- #### 2. ✅ **Validate PR** (`.github/workflows/validate-pr.yml`)
1297
-
1298
- **Triggers:**
1299
- - Pull Request `opened`, `synchronize`, `reopened`
1300
- - Can be called as reusable workflow (`workflow_call`)
1301
-
1302
- **Jobs:**
1303
- - `validate` - Uses `reusable-verify.yml` for hygiene checks
1304
- - `summarize` - Posts validation summary comment on PR
1305
-
1306
- **What it checks:**
1307
- - ✅ TypeScript compilation
1308
- - ✅ Release validation (with `--allow-dirty`)
1309
- - ✅ CHANGELOG.md updates (or `[skip-changelog]` marker)
1310
- - ✅ Conventional commits format
1311
- - ✅ Commit messages analysis
1312
-
1313
- **Permissions required:**
1314
- ```yaml
1315
- permissions:
1316
- contents: read
1317
- pull-requests: write # For posting comments
1318
- ```
1319
-
1320
- **No secrets required** (uses `GITHUB_TOKEN` automatically)
1321
-
1322
- #### 3. 🚨 **Hotfix Release** (`.github/workflows/hotfix.yml`)
1323
-
1324
- **Trigger:** Manual (`workflow_dispatch`)
1325
-
1326
- **Inputs:**
1327
-
1328
- | Input | Type | Required | Default | Description |
1329
- |-------|------|----------|---------|-------------|
1330
- | `increment` | choice | ✅ | `patch` | Version bump: `patch` or `minor` |
1331
- | `commit` | string | ❌ | latest | Specific commit SHA to release |
1332
- | `dry_run` | boolean | ❌ | `false` | Test without actual publishing |
1333
-
1334
- **Jobs:**
1335
- - `validate` - Validates TypeScript compilation and builds
1336
- - `hotfix` - Creates emergency hotfix release and publishes
1337
-
1338
- **What it does:**
1339
- 1. Validates code at specified commit
1340
- 2. Auto-generates changelog from recent commits
1341
- 3. Creates hotfix release (patch/minor bump)
1342
- 4. Pushes git tag
1343
- 5. **Publishes to npm with provenance**
1344
- 6. **Creates GitHub Release**
1345
-
1346
- **When to use:** Critical bugs needing immediate patch release
1347
-
1348
- **Permissions required:**
1349
- ```yaml
1350
- permissions:
1351
- contents: write # For git operations
1352
- id-token: write # For npm provenance
1353
- ```
1354
-
1355
- **Secrets required:**
1356
- - `NPM_TOKEN` - npm automation token
1357
- - `GITHUB_TOKEN` - Provided automatically
1358
-
1359
- #### 4. 🔄 **Retry Publish** (`.github/workflows/retry-publish.yml`)
1360
-
1361
- **Trigger:** Manual (`workflow_dispatch`)
1362
-
1363
- **Inputs:**
1364
-
1365
- | Input | Type | Required | Default | Description |
1366
- |-------|------|----------|---------|-------------|
1367
- | `tag_name` | string | ❌ | latest tag | Git tag to republish |
1368
- | `npm_only` | boolean | ❌ | `false` | Publish to npm only (skip GitHub Release) |
1369
- | `github_only` | boolean | ❌ | `false` | Create GitHub Release only (skip npm) |
1370
-
1371
- **Jobs:**
1372
- - `determine-tag` - Validates and determines which tag to publish
1373
- - `build-dist` - Builds distribution using reusable workflow
1374
- - `retry-publish` - Republishes to npm and/or GitHub
1375
-
1376
- **What it does:**
1377
- 1. Verifies git tag exists
1378
- 2. Runs pre-flight checks (`retry-publish.js` script)
1379
- 3. Republishes to selected destination(s)
1380
- 4. Uses existing changelog for release notes
1381
-
1382
- **When to use:** Previous publish failed (network issue, auth problem, etc.)
1383
-
1384
- **Permissions required:**
1385
- ```yaml
1386
- permissions:
1387
- contents: write # For GitHub releases
1388
- id-token: write # For npm provenance
1389
- ```
1390
-
1391
- **Secrets required:**
1392
- - `NPM_TOKEN` - npm automation token (if npm publish enabled)
1393
- - `GITHUB_TOKEN` - Provided automatically
1394
-
1395
- #### 5. ⚠️ **Republish (EXCEPTIONAL)** (`.github/workflows/republish.yml`)
1396
-
1397
- **Trigger:** Manual (`workflow_dispatch`)
1398
-
1399
- **⚠️ DANGER:** Moves existing git tag (breaks semver immutability)
1400
-
1401
- **Inputs:**
1402
-
1403
- | Input | Type | Required | Description |
1404
- |-------|------|----------|-------------|
1405
- | `version` | string | ✅ | Version to republish (e.g., `1.2.3`) |
1406
- | `confirmation` | string | ✅ | Must type exactly `"I understand the risks"` |
1407
-
1408
- **Jobs:**
1409
- - `pre-flight-checks` - Validates confirmation, version format, and tag existence
1410
- - `build-dist` - Builds distribution using reusable workflow
1411
- - `validate` - Validates TypeScript compilation
1412
- - `republish` - Moves git tag and updates GitHub release
1413
-
1414
- **What it does:**
1415
- 1. **Pre-flight safety checks:**
1416
- - Validates confirmation phrase
1417
- - Checks version format
1418
- - Verifies tag exists
1419
- - Displays warning message
1420
- - **10-second safety delay** ⏰
1421
- 2. Validates code compilation
1422
- 3. **Moves git tag to current commit** (⚠️ breaks immutability)
1423
- 4. Updates changelog for current version
1424
- 5. Updates GitHub Release
1425
-
1426
- > **Note:** npm is not republished — npm immutability (since 2016) prevents republishing an existing version. To redirect a dist-tag, use `npm dist-tag add`. To retry a failed publish, use the `retry-publish` preset.
1427
-
1428
- **When to use:** ONLY for exceptional emergencies where a published version must be moved to a different commit (e.g. a broken tag pointing to the wrong SHA)
1429
-
1430
- **Permissions required:**
1431
- ```yaml
1432
- permissions:
1433
- contents: write # For git tag operations
1434
- ```
1435
-
1436
- **Secrets required:**
1437
- - `GITHUB_TOKEN` - Provided automatically
1438
-
1439
- **Concurrency:** Prevents parallel republish operations for same version
1440
-
1441
- #### 6. 📦 **Publish** (`.github/workflows/publish.yml`)
1442
-
1443
- **Triggers:**
1444
- - Tag push matching `v*` pattern
1445
- - Can be called as reusable workflow (`workflow_call`)
1446
-
1447
- **Inputs (for `workflow_call`):**
1448
-
1449
- | Input | Type | Required | Description |
1450
- |-------|------|----------|-------------|
1451
- | `tag` | string | ❌ | Override tag (auto-detected from `github.ref_name`) |
1452
-
1453
- **Jobs:**
1454
- - `build-dist` - Builds distribution using reusable workflow
1455
- - `publish` - Updates GitHub release and publishes to npm
1456
-
1457
- **What it does:**
1458
- 1. Builds compiled distribution
1459
- 2. Runs `release-it-preset retry-publish --ci`
1460
- 3. Creates/updates GitHub Release with changelog
1461
- 4. Publishes to npm with provenance attestation
1462
-
1463
- **When it runs:** Automatically triggered when a tag is pushed (e.g., by `default` or `hotfix` workflows)
1464
-
1465
- **Permissions required:**
1466
- ```yaml
1467
- permissions:
1468
- contents: write # For GitHub releases
1469
- id-token: write # For npm provenance attestation
1470
- ```
1471
-
1472
- **Secrets required (for `workflow_call`):**
1473
- - `NPM_TOKEN` - npm automation token (must be passed explicitly)
1474
-
1475
- **Secrets required (for tag push):**
1476
- - `NPM_TOKEN` - npm automation token (repository secret)
1477
- - `GITHUB_TOKEN` - Provided automatically
1478
-
1479
- **Environment variables set:**
1480
- - `GITHUB_RELEASE=true` - Enables GitHub release creation
1481
- - `NPM_PUBLISH=true` - Enables npm publishing
1482
-
1483
- ---
1484
-
1485
- ### Workflows Summary Diagram
1486
-
1487
- ```mermaid
1488
- graph TB
1489
- subgraph "Reusable Workflows"
1490
- RV[🔄 reusable-verify.yml<br/>PR validation & hygiene]
1491
- BD[🔄 build-dist.yml<br/>Build TypeScript dist]
1492
- end
1493
-
1494
- subgraph "Development Flow"
1495
- PR[Pull Request] --> VPR[✅ validate-pr.yml]
1496
- VPR --> RV
1497
- VPR --> Comment[Post PR comment]
1498
- end
1499
-
1500
- subgraph "Release Flow"
1501
- Manual[Manual Trigger] --> CI[⚙️ ci.yml]
1502
- CI --> BD
1503
- CI --> Tag[Create Tag]
1504
- Tag --> PUB[📦 publish.yml]
1505
- PUB --> BD
1506
- PUB --> NPM[npm publish]
1507
- PUB --> GH[GitHub Release]
1508
- end
1509
-
1510
- subgraph "Emergency Flow"
1511
- Critical[Critical Bug] --> HF[🚨 hotfix.yml]
1512
- HF --> BD
1513
- HF --> Tag
1514
- end
1515
-
1516
- subgraph "Recovery Flow"
1517
- Failed[Failed Publish] --> RP[🔄 retry-publish.yml]
1518
- RP --> BD
1519
- RP --> Decision{Retry What?}
1520
- Decision -->|npm only| NPM
1521
- Decision -->|GitHub only| GH
1522
- Decision -->|Both| Both[npm + GitHub]
1523
- end
1524
-
1525
- style RV fill:#e1f5fe
1526
- style BD fill:#e1f5fe
1527
- style VPR fill:#c8e6c9
1528
- style CI fill:#fff9c4
1529
- style HF fill:#ffccbc
1530
- style RP fill:#b2ebf2
1531
- style PUB fill:#d1c4e9
1532
- ```
1533
-
1534
- ## Best Practices
1535
-
1536
- 1. **Use conventional commits** - Enables automatic changelog generation
1537
- 2. **Keep [Unreleased] updated** - Run `pnpm release-it-preset update` regularly or before releases
1538
- 3. **Validate before releasing** - Run `pnpm release-it-preset validate` to catch issues early
1539
- 4. **Test releases** - Use `--dry-run` flag to test without publishing
1540
- 5. **Protect main branch** - Require PR reviews before merging
1541
- 6. **Use CI for publishing** - Let GitHub Actions handle GitHub releases and npm publishing with provenance
1542
- 7. **Local runs are for prep** - Keep local runs focused on changelog, versioning, and tagging unless you explicitly opt in to publish
1543
-
1544
- ## Security
1545
-
1546
- This preset implements OWASP security best practices:
1547
-
1548
- ### Input Validation
1549
-
1550
- All CLI inputs are validated before execution:
1551
- - **Whitelist validation**: Config names and commands are validated against allowed lists
1552
- - **Argument sanitization**: All arguments are checked for dangerous characters (`;`, `&`, `|`, `` ` ``, `$()`, etc.)
1553
- - **Path traversal protection**: File paths are validated to prevent directory traversal attacks
1554
-
1555
- ### Command Injection Prevention
1556
-
1557
- - All `spawn()` calls use `shell: false` to prevent command injection
1558
- - Arguments are passed as arrays, not concatenated strings
1559
- - No user input is ever executed in a shell context
1560
-
1561
- ### Architecture
1562
-
1563
- The preset follows SOLID principles:
1564
- - **Single Responsibility**: Each module has one clear purpose
1565
- - **DRY**: Shared configuration builders eliminate code duplication
1566
- - **Dependency Inversion**: User configs have priority over preset defaults
1567
-
1568
- All 213 unit tests verify functionality and security boundaries.
1569
-
1570
- ## Troubleshooting
1571
-
1572
- ### Changelog not updating
1573
-
1574
- Run the update command:
1575
- ```bash
1576
- pnpm release-it-preset update
1577
- ```
1578
-
1579
- ### GitHub releases failing
1580
-
1581
- Ensure you have a `GITHUB_TOKEN` with `repo` scope and opt in to GitHub releases:
1582
- ```bash
1583
- GITHUB_RELEASE=true GITHUB_TOKEN=your_token pnpm release-it-preset default
1584
- ```
1585
-
1586
- Or use GitHub CLI authentication:
1587
- ```bash
1588
- gh auth login
1589
- pnpm release-it-preset default
1590
- ```
1591
-
1592
- ### npm publish failing in CI
1593
-
1594
- Check that:
1595
- 1. `NPM_TOKEN` secret is set in repository settings
1596
- 2. Token is an **automation token** (not a publish token)
1597
- 3. Token has permission to publish the package
1598
- 4. Package name is available (not already taken)
1599
-
1600
- Remember to export `NPM_PUBLISH=true` (and `GITHUB_RELEASE=true` if you expect a GitHub release) in the workflow or shell where you invoke release-it.
1601
-
1602
- Test locally:
1603
- ```bash
1604
- pnpm release-it-preset check # Check npm auth status
1605
- pnpm npm whoami # Verify authentication
1606
- ```
1607
-
1608
- ### Validation failing
1609
-
1610
- Run check command to see detailed status:
1611
- ```bash
1612
- pnpm release-it-preset check
1613
- ```
1614
-
1615
- Common issues:
1616
- - Working directory not clean → commit or stash changes, or use `--allow-dirty`
1617
- - [Unreleased] section empty → run `pnpm release-it-preset update`
1618
- - Not on required branch → checkout correct branch or update `GIT_REQUIRE_BRANCH`
1619
-
1620
- ### `npm error Version not changed`
1621
-
1622
- This can appear if you interrupt a release, tweak `CHANGELOG.md`, then retry with the same version. The preset automatically passes `--allow-same-version` to `npm version`, so simply re-run `pnpm release` (or `pnpm release-it-preset default --retry`) and select the same version—`npm` will no longer abort.
1623
-
1624
- ## Exit codes
1625
-
1626
- The CLI follows this convention (stable from v1.0.0 onward):
1627
-
1628
- | Code | Meaning | Examples |
1629
- |---|---|---|
1630
- | `0` | Success | Command completed; for `doctor`, `READY` or `WARNINGS` status |
1631
- | `1` | General failure | Unhandled error, validation failure, `doctor` `BLOCKED` status |
1632
- | `2` | Precondition failure (CI-friendly) | `validate` reports CHANGELOG missing or `[Unreleased]` empty |
1633
- | `3..9` | **Reserved** | Not currently emitted; reserved for future contract additions |
1634
-
1635
- In CI scripts, distinguish `exit 1` (try-again-friendly) from `exit 2` (precondition not met — require operator action) when chaining commands.
1636
-
1637
- ## Public API
1638
-
1639
- The full **stable surface** (CLI commands, environment variables, config exports, GHA workflow inputs, exit codes) is documented in [`docs/PUBLIC_API.md`](docs/PUBLIC_API.md). Items not listed there are internal and may change in any version.
108
+ By participating you agree to abide by the [Code of Conduct](CODE_OF_CONDUCT.md) (Contributor Covenant 2.1).
1640
109
 
1641
110
  ## License
1642
111
 
1643
- MIT — see [`LICENSE`](LICENSE).
1644
-
1645
- ## Contributing
1646
-
1647
- PRs and issues welcome. Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) before opening a pull request — it covers the Conventional Commits requirement, branch prefixes, the pre-PR checklist, and the testing conventions. By participating you agree to abide by the [Code of Conduct](CODE_OF_CONDUCT.md) (Contributor Covenant 2.1).
1648
-
1649
- For security concerns, please email `olivier.orabona@gmail.com` directly rather than opening a public issue. See [`SECURITY.md`](SECURITY.md) for the disclosure policy.
1650
-
112
+ MIT — see [LICENSE](LICENSE).