@oorabona/release-it-preset 0.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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +833 -0
  3. package/bin/cli.js +180 -0
  4. package/bin/run-script.js +72 -0
  5. package/config/changelog-only.js +41 -0
  6. package/config/default.js +54 -0
  7. package/config/helpers.js +52 -0
  8. package/config/hotfix.js +51 -0
  9. package/config/manual-changelog.js +64 -0
  10. package/config/no-changelog.js +40 -0
  11. package/config/republish.js +60 -0
  12. package/config/retry-publish.js +40 -0
  13. package/dist/scripts/check-config.js +285 -0
  14. package/dist/scripts/check-pr-status.js +164 -0
  15. package/dist/scripts/extract-changelog.js +66 -0
  16. package/dist/scripts/init-project.js +191 -0
  17. package/dist/scripts/lib/commit-parser.js +67 -0
  18. package/dist/scripts/lib/git-utils.js +33 -0
  19. package/dist/scripts/lib/semver-utils.js +26 -0
  20. package/dist/scripts/lib/string-utils.js +12 -0
  21. package/dist/scripts/populate-unreleased-changelog.js +236 -0
  22. package/dist/scripts/republish-changelog.js +187 -0
  23. package/dist/scripts/retry-publish.js +98 -0
  24. package/dist/scripts/validate-release.js +288 -0
  25. package/dist/types/check-config.d.ts +65 -0
  26. package/dist/types/check-pr-status.d.ts +51 -0
  27. package/dist/types/extract-changelog.d.ts +23 -0
  28. package/dist/types/init-project.d.ts +37 -0
  29. package/dist/types/lib/commit-parser.d.ts +44 -0
  30. package/dist/types/lib/git-utils.d.ts +20 -0
  31. package/dist/types/lib/semver-utils.d.ts +18 -0
  32. package/dist/types/lib/string-utils.d.ts +10 -0
  33. package/dist/types/populate-unreleased-changelog.d.ts +56 -0
  34. package/dist/types/republish-changelog.d.ts +39 -0
  35. package/dist/types/retry-publish.d.ts +33 -0
  36. package/dist/types/validate-release.d.ts +43 -0
  37. package/package.json +93 -0
package/README.md ADDED
@@ -0,0 +1,833 @@
1
+ # @oorabona/release-it-preset
2
+
3
+ Shared [release-it](https://github.com/release-it/release-it) configuration and scripts for automated versioning, changelog generation, and package publishing.
4
+
5
+ ## Features
6
+
7
+ - πŸ“¦ Multiple release configurations for different scenarios
8
+ - πŸ“ Automatic changelog generation using [Keep a Changelog](https://keepachangelog.com/) format
9
+ - πŸ€– Conventional commits parsing and categorization
10
+ - 🏷️ Git tagging with optional GitHub release automation
11
+ - πŸš€ npm publishing with provenance (opt-in, ideal for CI)
12
+ - πŸ”„ Republish and retry mechanisms for failed releases
13
+ - ⚑ Hotfix release support
14
+ - 🎯 Environment variable configuration
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pnpm add -D @oorabona/release-it-preset release-it
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### Option 1: Using the CLI (Recommended)
25
+
26
+ Add scripts to your `package.json`:
27
+
28
+ ```json
29
+ {
30
+ "scripts": {
31
+ "release": "release-it-preset default",
32
+ "release:hotfix": "release-it-preset hotfix"
33
+ }
34
+ }
35
+ ```
36
+
37
+ Then run:
38
+
39
+ ```bash
40
+ pnpm release
41
+ ```
42
+
43
+ ### Option 2: Using extends
44
+
45
+ Create `.release-it.json` in your project:
46
+
47
+ ```json
48
+ {
49
+ "extends": "@oorabona/release-it-preset/config/default"
50
+ }
51
+ ```
52
+
53
+ Add scripts to your `package.json`:
54
+
55
+ ```json
56
+ {
57
+ "scripts": {
58
+ "release": "release-it"
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Initialize CHANGELOG.md
64
+
65
+ Create a `CHANGELOG.md` file with Keep a Changelog format:
66
+
67
+ ```markdown
68
+ # Changelog
69
+
70
+ All notable changes to this project will be documented in this file.
71
+
72
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
73
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
74
+
75
+ ## [Unreleased]
76
+
77
+ ### Added
78
+ - Initial release
79
+ ```
80
+
81
+ ## GitHub Actions
82
+
83
+ - Reuse the PR validation workflow from this package:
84
+
85
+ ```yaml
86
+ name: PR Checks
87
+
88
+ on:
89
+ pull_request:
90
+ types: [opened, synchronize, reopened]
91
+
92
+ jobs:
93
+ validate:
94
+ uses: oorabona/release-it-preset/.github/workflows/reusable-verify.yml@main
95
+ with:
96
+ base-ref: origin/${{ github.base_ref }}
97
+ head-ref: ${{ github.sha }}
98
+ secrets: inherit
99
+ ```
100
+
101
+ Pair it with a follow-up job to post a summary comment using the outputs exposed by the reusable workflow (see `.github/workflows/validate-pr.yml` in this repo for a full example).
102
+
103
+ ## Available Configurations
104
+
105
+ ### `default` - Standard Release
106
+
107
+ Full-featured release with changelog, git operations, and optional GitHub/npm publishing.
108
+
109
+ **CLI:**
110
+ ```bash
111
+ pnpm release-it-preset default
112
+ ```
113
+
114
+ **Extends:**
115
+ ```json
116
+ {
117
+ "extends": "@oorabona/release-it-preset/config/default"
118
+ }
119
+ ```
120
+
121
+ Features:
122
+ - βœ… Version bumping (interactive)
123
+ - βœ… Automatic changelog population from conventional commits
124
+ - βœ… Git commit, tag, and push
125
+ - β˜‘οΈ GitHub release creation (set `GITHUB_RELEASE=true`)
126
+ - β˜‘οΈ npm publishing with provenance (set `NPM_PUBLISH=true`)
127
+
128
+ ### `hotfix` - Emergency Hotfix
129
+
130
+ For urgent patches that need quick changelog generation from git log (GitHub/npm remain opt-in).
131
+
132
+ **CLI:**
133
+ ```bash
134
+ pnpm release-it-preset hotfix
135
+ ```
136
+
137
+ **Extends:**
138
+ ```json
139
+ {
140
+ "extends": "@oorabona/release-it-preset/config/hotfix"
141
+ }
142
+ ```
143
+
144
+ Features:
145
+ - βœ… Forced patch version increment
146
+ - βœ… Automatic changelog from recent commits
147
+ - βœ… Pre-bump unreleased section population
148
+ - β˜‘οΈ GitHub release with extracted notes (set `GITHUB_RELEASE=true`)
149
+ - β˜‘οΈ npm publishing with provenance (set `NPM_PUBLISH=true`)
150
+
151
+ ### `changelog-only` - Changelog Preparation
152
+
153
+ Updates changelog without performing a release (useful in CI or pre-release).
154
+
155
+ **CLI:**
156
+ ```bash
157
+ pnpm release-it-preset changelog-only --ci
158
+ ```
159
+
160
+ **Extends:**
161
+ ```json
162
+ {
163
+ "extends": "@oorabona/release-it-preset/config/changelog-only"
164
+ }
165
+ ```
166
+
167
+ Features:
168
+ - βœ… Populates [Unreleased] section
169
+ - ❌ No version bump
170
+ - ❌ No git operations
171
+ - ❌ No publishing
172
+
173
+ ### `manual-changelog` - Manual Changelog Release
174
+
175
+ For releases where you've manually edited the [Unreleased] section in CHANGELOG.md.
176
+ Skips automatic changelog generation while keeping GitHub/npm steps opt-in.
177
+
178
+ **Workflow:**
179
+ ```bash
180
+ # 1. Generate initial changelog
181
+ pnpm release-it-preset update
182
+
183
+ # 2. Manually edit CHANGELOG.md [Unreleased] section
184
+
185
+ # 3. Release without regenerating changelog
186
+ pnpm release-it-preset manual-changelog
187
+ ```
188
+
189
+ **Extends:**
190
+ ```json
191
+ {
192
+ "extends": "@oorabona/release-it-preset/config/manual-changelog"
193
+ }
194
+ ```
195
+
196
+ Features:
197
+ - βœ… Version bumping (interactive)
198
+ - βœ… Preserves manual [Unreleased] edits
199
+ - βœ… Moves [Unreleased] to versioned section
200
+ - βœ… Git commit, tag, and push
201
+ - β˜‘οΈ GitHub release creation (set `GITHUB_RELEASE=true`)
202
+ - β˜‘οΈ npm publishing with provenance (set `NPM_PUBLISH=true`)
203
+ - ❌ Skips automatic changelog population
204
+
205
+ ### `no-changelog` - Quick Release
206
+
207
+ Standard release without changelog updates; GitHub/npm steps remain opt-in.
208
+
209
+ **CLI:**
210
+ ```bash
211
+ pnpm release-it-preset no-changelog
212
+ ```
213
+
214
+ **Extends:**
215
+ ```json
216
+ {
217
+ "extends": "@oorabona/release-it-preset/config/no-changelog"
218
+ }
219
+ ```
220
+
221
+ Features:
222
+ - βœ… Version bumping
223
+ - βœ… Git operations
224
+ - β˜‘οΈ GitHub releases (set `GITHUB_RELEASE=true`)
225
+ - β˜‘οΈ npm publishing (set `NPM_PUBLISH=true`)
226
+ - ❌ No changelog updates
227
+
228
+ ### `republish` - Version Republishing
229
+
230
+ ⚠️ **DANGER**: Republishes existing version by moving the git tag (breaks semver immutability).
231
+
232
+ Only use when you need to fix a broken release. Publishing back to npm/GitHub still requires enabling the corresponding environment flags.
233
+
234
+ **CLI:**
235
+ ```bash
236
+ pnpm release-it-preset republish
237
+ ```
238
+
239
+ **Extends:**
240
+ ```json
241
+ {
242
+ "extends": "@oorabona/release-it-preset/config/republish"
243
+ }
244
+ ```
245
+
246
+ Features:
247
+ - ⚠️ Moves existing git tag
248
+ - βœ… Updates changelog for current version
249
+ - β˜‘οΈ Republishes to npm (set `NPM_PUBLISH=true`)
250
+ - β˜‘οΈ Updates GitHub release (set `GITHUB_RELEASE=true`)
251
+
252
+ ### `retry-publish` - Retry Failed Publishing
253
+
254
+ Retries npm/GitHub publishing for an existing tag without modifying git history; opt in to each surface via `NPM_PUBLISH` and `GITHUB_RELEASE`.
255
+
256
+ **CLI:**
257
+ ```bash
258
+ # Step 1: Run pre-flight checks (optional)
259
+ node node_modules/@oorabona/release-it-preset/dist/scripts/retry-publish.js
260
+ # or during local development (TypeScript sources):
261
+ pnpm tsx scripts/retry-publish.ts
262
+
263
+ # Step 2: Retry the publish
264
+ pnpm release-it-preset retry-publish
265
+ ```
266
+
267
+ **Extends:**
268
+ ```json
269
+ {
270
+ "extends": "@oorabona/release-it-preset/config/retry-publish"
271
+ }
272
+ ```
273
+
274
+ Features:
275
+ - β˜‘οΈ Republishes to npm (set `NPM_PUBLISH=true`)
276
+ - β˜‘οΈ Updates GitHub release (set `GITHUB_RELEASE=true`)
277
+ - ❌ No version increment
278
+ - ❌ No git operations
279
+
280
+ ## CLI Usage
281
+
282
+ The package provides a `release-it-preset` CLI with two types of commands:
283
+
284
+ ### Release Commands
285
+
286
+ Run release-it with specific configurations:
287
+
288
+ ```bash
289
+ # Show help
290
+ pnpm release-it-preset --help
291
+
292
+ # Run releases
293
+ pnpm release-it-preset default --dry-run
294
+ pnpm release-it-preset hotfix --verbose
295
+ pnpm release-it-preset changelog-only --ci
296
+ pnpm release-it-preset manual-changelog
297
+ ```
298
+
299
+ All additional arguments are passed through to release-it.
300
+
301
+ ### Utility Commands
302
+
303
+ Helper commands for project setup and maintenance:
304
+
305
+ #### `init` - Initialize Project
306
+
307
+ Creates CHANGELOG.md, .release-it.json, and optionally adds scripts to package.json:
308
+
309
+ ```bash
310
+ # Interactive mode (asks for confirmation)
311
+ pnpm release-it-preset init
312
+
313
+ # Non-interactive mode (skip prompts, use defaults)
314
+ pnpm release-it-preset init --yes
315
+ ```
316
+
317
+ **What it does:**
318
+ - Creates `CHANGELOG.md` with Keep a Changelog template
319
+ - Creates `.release-it.json` with extends configuration
320
+ - Optionally adds release scripts to `package.json`
321
+ - Skips existing files in `--yes` mode
322
+
323
+ > 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.
324
+
325
+ #### `update` - Update Changelog
326
+
327
+ Updates the [Unreleased] section with commits since last tag:
328
+
329
+ ```bash
330
+ pnpm release-it-preset update
331
+ ```
332
+
333
+ **What it does:**
334
+ - Parses conventional commits since last git tag
335
+ - Groups commits by type (Added, Fixed, Changed, etc.)
336
+ - Updates [Unreleased] section in CHANGELOG.md
337
+ - Generates commit links to repository
338
+ - 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
339
+
340
+ #### `validate` - Validate Release Readiness
341
+
342
+ Checks if project is ready for release:
343
+
344
+ ```bash
345
+ # Standard validation
346
+ pnpm release-it-preset validate
347
+
348
+ # Allow uncommitted changes
349
+ pnpm release-it-preset validate --allow-dirty
350
+ ```
351
+
352
+ **What it checks:**
353
+ - βœ… CHANGELOG.md exists and is well-formatted
354
+ - βœ… [Unreleased] section has content
355
+ - βœ… Working directory is clean (unless --allow-dirty)
356
+ - βœ… npm authentication works (npm whoami)
357
+ - βœ… Current branch is allowed (if GIT_REQUIRE_BRANCH is set)
358
+
359
+ Exit code 0 if all checks pass, 1 if any fail (useful in CI/pre-commit hooks).
360
+
361
+ #### `check` - Diagnostic Information
362
+
363
+ Displays configuration and project status:
364
+
365
+ ```bash
366
+ pnpm release-it-preset check
367
+ ```
368
+
369
+ **What it shows:**
370
+ - Environment variables and their values
371
+ - Repository information (URL, branch, remote)
372
+ - Git tags and latest version
373
+ - Commits since last tag
374
+ - Configuration files status
375
+ - npm authentication status
376
+
377
+ Useful for debugging release issues.
378
+
379
+ ### pnpm Script Shortcuts
380
+
381
+ The root `package.json` defines helper scripts that wrap the CLI so you can run the most common flows with `pnpm run`:
382
+
383
+ - `pnpm release` β†’ run the default release config (`release-it-preset default`)
384
+ - `pnpm run release:default:dry-run` β†’ dry-run the default release configuration
385
+ - `pnpm run release:no-changelog` β†’ publish without touching the changelog
386
+ - `pnpm run release:changelog-only` β†’ update only the changelog
387
+ - `pnpm run release:manual-changelog` β†’ release with manually edited changelog (skip auto-generation)
388
+ - `pnpm run release:hotfix` β†’ execute the hotfix workflow
389
+ - `pnpm run release:republish` β†’ trigger the republish workflow (dangerous flow)
390
+ - `pnpm run release:retry-publish` β†’ retry npm/GitHub publishing for an existing tag
391
+ - `pnpm run release:update` β†’ populate the `[Unreleased]` section
392
+ - `pnpm run release:validate` β†’ run release validation checks
393
+ - `pnpm run release:validate:allow-dirty` β†’ validation that tolerates uncommitted changes
394
+ - `pnpm run release:check` β†’ show diagnostic information about the current repo
395
+
396
+ ## Scripts
397
+
398
+ 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.
399
+
400
+ ### `extract-changelog.ts`
401
+
402
+ Extracts the changelog entry for a specific version (used automatically by the release notes generator). If you ever need to call it manually:
403
+
404
+ ```bash
405
+ node node_modules/@oorabona/release-it-preset/dist/scripts/extract-changelog.js 1.2.3
406
+ ```
407
+
408
+ ### `populate-unreleased-changelog.ts`
409
+
410
+ Populates the [Unreleased] section with commits since the last tag using conventional commits.
411
+
412
+ ```bash
413
+ # Preferred
414
+ pnpm release-it-preset update
415
+ # or
416
+ pnpm run release:update
417
+
418
+ # Advanced (call compiled output directly)
419
+ node node_modules/@oorabona/release-it-preset/dist/scripts/populate-unreleased-changelog.js
420
+ ```
421
+
422
+ Supported commit types:
423
+ - `feat`, `feature`, `add` β†’ Added
424
+ - `fix`, `bugfix` β†’ Fixed
425
+ - `perf`, `refactor`, `style`, `docs`, `test`, `chore`, `build` β†’ Changed
426
+ - `ci`, `release`, `hotfix` β†’ Ignored
427
+
428
+ Add `[skip-changelog]` to commit message to exclude it.
429
+
430
+ ### `republish-changelog.ts`
431
+
432
+ Moves [Unreleased] content to the current version entry (for republishing).
433
+
434
+ ```bash
435
+ # Preferred
436
+ pnpm run release:republish
437
+ # or
438
+ pnpm release-it-preset republish
439
+
440
+ # Advanced
441
+ node node_modules/@oorabona/release-it-preset/dist/scripts/republish-changelog.js
442
+ ```
443
+
444
+ ### `retry-publish.ts`
445
+
446
+ Performs pre-flight checks before retrying a failed publish.
447
+
448
+ ```bash
449
+ # Preferred
450
+ pnpm run release:retry-publish
451
+ # or
452
+ pnpm release-it-preset retry-publish
453
+
454
+ # Advanced
455
+ node node_modules/@oorabona/release-it-preset/dist/scripts/retry-publish.js
456
+ ```
457
+
458
+ ## Environment Variables
459
+
460
+ Customize behavior with environment variables:
461
+
462
+ ### Changelog
463
+ - `CHANGELOG_FILE` - Changelog file path (default: `CHANGELOG.md`)
464
+
465
+ ### Git
466
+ - `GIT_COMMIT_MESSAGE` - Commit message template (default: `release: bump v${version}`)
467
+ - `GIT_TAG_NAME` - Tag name template (default: `v${version}`)
468
+ - `GIT_REQUIRE_BRANCH` - Required branch (default: `main`)
469
+ - `GIT_REQUIRE_UPSTREAM` - Require upstream tracking (default: `false`)
470
+ - `GIT_REQUIRE_CLEAN` - Require clean working directory (default: `false`)
471
+ - `GIT_REMOTE` - Git remote name (default: `origin`)
472
+
473
+ ### GitHub
474
+ - `GITHUB_RELEASE` - Enable GitHub releases (default: `false`)
475
+ - `GITHUB_REPOSITORY` - Repository in `owner/repo` format (auto-detected from git remote)
476
+
477
+ ### npm
478
+ - `NPM_PUBLISH` - Enable npm publishing (default: `false`)
479
+ - `NPM_SKIP_CHECKS` - Skip npm checks (default: `false`)
480
+ - `NPM_ACCESS` - npm access level (default: `public`)
481
+
482
+ > ℹ️ 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.
483
+
484
+ ### Example
485
+
486
+ ```bash
487
+ CHANGELOG_FILE="HISTORY.md" \
488
+ GIT_REQUIRE_BRANCH="develop" \
489
+ GIT_REQUIRE_CLEAN="true" \
490
+ pnpm release
491
+ ```
492
+
493
+ ## Configuration Override
494
+
495
+ You can override any configuration in your project's `.release-it.json`:
496
+
497
+ ```json
498
+ {
499
+ "extends": "@oorabona/release-it-preset/config/default",
500
+ "git": {
501
+ "requireBranch": "develop",
502
+ "commitMessage": "chore: release v${version}"
503
+ },
504
+ "github": {
505
+ "releaseName": "Release ${version}"
506
+ }
507
+ }
508
+ ```
509
+
510
+ ## Borrowing Scripts & Workflows
511
+
512
+ - 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).
513
+ - 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.
514
+
515
+ ## Release Workflow
516
+
517
+ ### Recommended Workflow
518
+
519
+ **Local (Developer):**
520
+ 1. Make changes and commit with conventional commits
521
+ 2. Run `pnpm run release:update` to populate the `[Unreleased]` section from commits
522
+ 3. Review `CHANGELOG.md` - you have two options here:
523
+
524
+ **Option A: Quick release with auto-generated changelog**
525
+ - Stage `CHANGELOG.md` as-is
526
+ - Run `pnpm run release:validate` to verify readiness
527
+ - Dry-run with `pnpm run release:default:dry-run`
528
+ - Execute `pnpm release` to perform the real release
529
+
530
+ **Option B: Manual changelog editing (recommended for detailed release notes)**
531
+ - Manually edit `CHANGELOG.md` [Unreleased] section (add narrative, reorganize, etc.)
532
+ - No need to stage or commit
533
+ - Run `pnpm run release:validate` (or `pnpm run release:validate:allow-dirty`)
534
+ - Dry-run with `pnpm run release:manual-changelog --dry-run`
535
+ - Execute `pnpm run release:manual-changelog` to release
536
+ - This skips changelog regeneration, preserving your edits
537
+ - Bumps version, moves [Unreleased] to versioned section
538
+ - Creates release commit + tag and pushes to origin (GitHub release happens later if `GITHUB_RELEASE=true` in CI)
539
+
540
+ **If you change your mind mid-release:** If you started with Option A but want to add manual edits when prompted `Commit (release: bump 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).
541
+
542
+ 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.
543
+
544
+ ```mermaid
545
+ flowchart TD
546
+ A[Conventional commits] --> B[pnpm run release:update]
547
+ B --> C{Want to edit<br/>changelog manually?}
548
+
549
+ C -->|No - Auto changelog| D[Stage CHANGELOG.md]
550
+ D --> E[pnpm run release:validate]
551
+ E --> F[pnpm run release:default:dry-run]
552
+ F --> G[pnpm release]
553
+
554
+ C -->|Yes - Manual editing| H[Edit CHANGELOG.md manually]
555
+ H --> I[pnpm run release:validate --allow-dirty]
556
+ I --> J[pnpm run release:manual-changelog --dry-run]
557
+ J --> K[pnpm run release:manual-changelog]
558
+
559
+ G --> L[Push commit \u0026 tag]
560
+ K --> L
561
+ L --> M[Publish workflow runs in CI]
562
+ ```
563
+
564
+ **CI (GitHub Actions):**
565
+ - When tag is pushed, CI publishes to npm with provenance
566
+
567
+ ### Why This Workflow?
568
+
569
+ - **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.
570
+ - **Local runs stay safe** - Without `GITHUB_RELEASE=true` or `NPM_PUBLISH=true`, the presets only handle changelog updates, commits, and tags.
571
+ - **Better security** - Publishing requires CI credentials (GITHUB_TOKEN + NPM_TOKEN), keeping local environments token-free by default.
572
+ - **Predictable outputs** - Release notes are regenerated from the committed changelog, avoiding drift between local runs and CI.
573
+
574
+ ### GitHub Actions Setup
575
+
576
+ Create `.github/workflows/publish.yml`:
577
+
578
+ ```yaml
579
+ name: Publish Package
580
+
581
+ on:
582
+ push:
583
+ tags:
584
+ - 'v*'
585
+
586
+ permissions:
587
+ contents: write
588
+ id-token: write # For npm provenance
589
+
590
+ jobs:
591
+ publish:
592
+ runs-on: ubuntu-latest
593
+ steps:
594
+ - uses: actions/checkout@v4
595
+
596
+ - uses: pnpm/action-setup@v4
597
+
598
+ - uses: actions/setup-node@v4
599
+ with:
600
+ node-version: 20
601
+ registry-url: 'https://registry.npmjs.org'
602
+ cache: 'pnpm'
603
+
604
+ - run: pnpm install --frozen-lockfile
605
+
606
+ - run: pnpm build
607
+
608
+ - name: Update GitHub release and publish to npm
609
+ run: pnpm release-it-preset retry-publish --ci
610
+ env:
611
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
612
+ NPM_PUBLISH: 'true'
613
+ GITHUB_RELEASE: 'true'
614
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
615
+ ```
616
+
617
+ **Required Secrets:**
618
+ - `NPM_TOKEN` - Automation token from npmjs.com (Settings β†’ Access Tokens β†’ Generate New Token β†’ Automation)
619
+ - `GITHUB_TOKEN` is provided automatically by GitHub Actions (no manual secret needed)
620
+
621
+ **Required Permissions (locally):**
622
+ - Set `GITHUB_RELEASE=true` and/or `NPM_PUBLISH=true` only when you explicitly want to perform those actions from your machine. Provide `GITHUB_TOKEN`/`NODE_AUTH_TOKEN` as needed.
623
+
624
+ ### Alternative: Full CI Release
625
+
626
+ If you prefer to run the entire release in CI:
627
+
628
+ ```yaml
629
+ on:
630
+ workflow_dispatch: # Manual trigger
631
+ inputs:
632
+ version:
633
+ description: 'Version bump type'
634
+ required: true
635
+ type: choice
636
+ options: [patch, minor, major]
637
+
638
+ permissions:
639
+ contents: write # For git operations and GitHub releases
640
+ id-token: write # For npm provenance
641
+
642
+ jobs:
643
+ release:
644
+ runs-on: ubuntu-latest
645
+ steps:
646
+ # ... setup steps ...
647
+
648
+ - run: pnpm release-it-preset default --ci --increment ${{ inputs.version }}
649
+ env:
650
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
651
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
652
+ GITHUB_RELEASE: 'true'
653
+ NPM_PUBLISH: 'true'
654
+ ```
655
+
656
+ ## GitHub Actions Workflows
657
+
658
+ This repository includes several GitHub Actions workflows for automated CI/CD and release management.
659
+
660
+ ### Available Workflows
661
+
662
+ You can copy these files into your own repository (adjusting names, branches, and secrets to match your context). They are designed to work as-is with the release-it-preset CLI defaults but feel free to trim the jobs that you don’t need.
663
+
664
+ #### 1. **CI** (`.github/workflows/ci.yml`)
665
+
666
+ **Triggers:** Push to main, Pull Requests, Manual (workflow_dispatch)
667
+
668
+ **Jobs:**
669
+ - **validate** - Validates TypeScript compilation and file structure
670
+ - **test-cli** - Tests all CLI commands (help, check, validate, init)
671
+ - **release** - Manual release creation (workflow_dispatch only)
672
+
673
+ **Manual Release:**
674
+ ```bash
675
+ # Go to Actions β†’ CI β†’ Run workflow
676
+ # Select increment type: patch, minor, or major
677
+ ```
678
+
679
+ #### 2. **Validate PR** (`.github/workflows/validate-pr.yml`)
680
+
681
+ **Trigger:** Pull Request opened/updated
682
+
683
+ **What it does:**
684
+ - Validates TypeScript compilation
685
+ - Runs release validation checks
686
+ - Checks if CHANGELOG.md was updated
687
+ - Validates conventional commits format
688
+ - Posts summary comment on PR
689
+
690
+ **Helpful for:**
691
+ - Ensuring PRs follow best practices
692
+ - Catching issues before merge
693
+ - Promoting conventional commits usage
694
+
695
+ #### 3. **Hotfix Release** (`.github/workflows/hotfix.yml`)
696
+
697
+ **Trigger:** Manual (workflow_dispatch)
698
+
699
+ **Inputs:**
700
+ - `increment` - patch or minor (required)
701
+ - `commit` - Specific commit SHA (optional)
702
+ - `dry_run` - Test without publishing (boolean)
703
+
704
+ **What it does:**
705
+ - Validates code
706
+ - Creates emergency hotfix release
707
+ - Uses `release-it-preset hotfix` config
708
+ - Auto-generates changelog from commits
709
+
710
+ **When to use:**
711
+ Critical bugs that need immediate patch release.
712
+
713
+ #### 4. **Retry Publish** (`.github/workflows/retry-publish.yml`)
714
+
715
+ **Trigger:** Manual (workflow_dispatch)
716
+
717
+ **Inputs:**
718
+ - `tag_name` - Tag to republish (defaults to latest)
719
+ - `npm_only` - Publish to npm only
720
+ - `github_only` - Create GitHub Release only
721
+
722
+ **What it does:**
723
+ - Republishes existing tag to npm and/or GitHub
724
+ - Runs pre-flight checks
725
+ - Extracts changelog for release notes
726
+
727
+ **When to use:**
728
+ When previous publish failed (network issue, auth problem, etc.)
729
+
730
+ #### 5. **Republish (EXCEPTIONAL)** (`.github/workflows/republish.yml`)
731
+
732
+ **Trigger:** Manual (workflow_dispatch)
733
+
734
+ **Inputs:**
735
+ - `version` - Version to republish (e.g., 1.2.3)
736
+ - `confirmation` - Must type "I understand the risks"
737
+
738
+ **What it does:**
739
+ ⚠️ **DANGER**: Moves existing git tag (breaks semver immutability)
740
+ - Pre-flight safety checks
741
+ - 10-second delay before execution
742
+ - Validates code
743
+ - Moves git tag to current commit
744
+ - Updates changelog
745
+ - Republishes to npm
746
+ - Updates GitHub Release
747
+ - Creates audit trail document
748
+
749
+ **When to use:**
750
+ ONLY for exceptional cases where a published version has critical issues and must be replaced.
751
+
752
+ #### 6. **Publish** (`.github/workflows/publish.yml`)
753
+
754
+ **Trigger:** Tag push (v*)
755
+
756
+ **What it does:**
757
+ - Runs `release-it-preset retry-publish --ci` to refresh the GitHub release notes and publish to npm with provenance
758
+ - Triggered automatically when release-it creates and pushes a tag
759
+
760
+ **Note:** The workflow exports `GITHUB_RELEASE=true` and `NPM_PUBLISH=true`, so both actions happen together in CI.
761
+
762
+ ## Best Practices
763
+
764
+ 1. **Use conventional commits** - Enables automatic changelog generation
765
+ 2. **Keep [Unreleased] updated** - Run `pnpm release-it-preset update` regularly or before releases
766
+ 3. **Validate before releasing** - Run `pnpm release-it-preset validate` to catch issues early
767
+ 4. **Test releases** - Use `--dry-run` flag to test without publishing
768
+ 5. **Protect main branch** - Require PR reviews before merging
769
+ 6. **Use CI for publishing** - Let GitHub Actions handle GitHub releases and npm publishing with provenance
770
+ 7. **Local runs are for prep** - Keep local runs focused on changelog, versioning, and tagging unless you explicitly opt in to publish
771
+
772
+ ## Troubleshooting
773
+
774
+ ### Changelog not updating
775
+
776
+ Run the update command:
777
+ ```bash
778
+ pnpm release-it-preset update
779
+ ```
780
+
781
+ ### GitHub releases failing
782
+
783
+ Ensure you have a `GITHUB_TOKEN` with `repo` scope and opt in to GitHub releases:
784
+ ```bash
785
+ GITHUB_RELEASE=true GITHUB_TOKEN=your_token pnpm release-it-preset default
786
+ ```
787
+
788
+ Or use GitHub CLI authentication:
789
+ ```bash
790
+ gh auth login
791
+ pnpm release-it-preset default
792
+ ```
793
+
794
+ ### npm publish failing in CI
795
+
796
+ Check that:
797
+ 1. `NPM_TOKEN` secret is set in repository settings
798
+ 2. Token is an **automation token** (not a publish token)
799
+ 3. Token has permission to publish the package
800
+ 4. Package name is available (not already taken)
801
+
802
+ 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.
803
+
804
+ Test locally:
805
+ ```bash
806
+ pnpm release-it-preset check # Check npm auth status
807
+ pnpm npm whoami # Verify authentication
808
+ ```
809
+
810
+ ### Validation failing
811
+
812
+ Run check command to see detailed status:
813
+ ```bash
814
+ pnpm release-it-preset check
815
+ ```
816
+
817
+ Common issues:
818
+ - Working directory not clean β†’ commit or stash changes, or use `--allow-dirty`
819
+ - [Unreleased] section empty β†’ run `pnpm release-it-preset update`
820
+ - Not on required branch β†’ checkout correct branch or update `GIT_REQUIRE_BRANCH`
821
+
822
+ ### `npm error Version not changed`
823
+
824
+ 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.
825
+
826
+ ## License
827
+
828
+ MIT
829
+
830
+ ## Contributing
831
+
832
+ Contributions are welcome! Please open an issue or pull request.
833
+