relizy 0.1.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 ADDED
@@ -0,0 +1,1230 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/LouisMazel/relizy/refs/heads/main/resources/logo.svg" alt="Relizy Logo" width="100">
3
+
4
+ <h1>Relizy</h1>
5
+ <p>
6
+ <strong>
7
+ A tool to manage releases for monorepos and single packages.
8
+ </strong>
9
+ </p>
10
+ </div>
11
+
12
+ Seamless and automated release management with elegant changelog generation based on Conventional Commits, supporting both monorepos and single packages. Handles version bumping, changelog generation, Git tagging, and publishing to npm, GitHub & GitLab effortlessly.
13
+
14
+ ## 🎯 Why use this tool?
15
+
16
+ Imagine you have multiple packages in your project (like a box with several toys). With **one command**, this tool helps you to:
17
+
18
+ 1. **Update version numbers** of your packages automatically
19
+ 2. **Create changelogs** to explain what changed
20
+ 3. **Publish your packages** to npm so others can use them
21
+ 4. **Create releases** on GitHub or GitLab
22
+
23
+ ## ✨ Features
24
+
25
+ - 🚀 Built on top of [changelogen](https://github.com/unjs/changelogen)
26
+ - 📦 Monorepo support with glob pattern matching
27
+ - 🔄 Three versioning modes: unified, selective, independent
28
+ - 📝 Generate changelogs per package + root aggregate
29
+ - 🏷️ Pre-release support (alpha, beta, rc)
30
+ - 📢 NPM publish with smart tag detection
31
+ - 🔗 Automatic dependency bumping for workspace dependencies
32
+ - 🐙 GitHub & GitLab release automation
33
+ - 🔐 2FA/OTP support for npm publishing
34
+ - 🎛️ Custom registry support (private registries, GitHub Packages, etc.)
35
+ - ⚙️ Multiple configuration files support for different release workflows
36
+ - 🔧 Support for npm, yarn, pnpm, and bun (auto-detected)
37
+
38
+ ## 📦 Installation
39
+
40
+ ```bash
41
+ pnpm add -D relizy
42
+ ```
43
+
44
+ ## 📦 Package Manager Support
45
+
46
+ This tool automatically detects your package manager and uses the appropriate commands:
47
+
48
+ - **npm** - Standard npm registry commands
49
+ - **yarn** - Supports both Yarn Classic and Yarn Berry
50
+ - **pnpm** - Optimized for pnpm workspaces
51
+ - **bun** - Full support for bun package manager
52
+
53
+ Detection is automatic based on:
54
+
55
+ 1. `packageManager` field in package.json
56
+ 2. Lock file presence (pnpm-lock.yaml, yarn.lock, package-lock.json, bun.lockb)
57
+ 3. npm_config_user_agent environment variable
58
+
59
+ ## ⚙️ Minimal configuration
60
+
61
+ Create a configuration file in the root of your project. The config file is loaded using [c12](https://github.com/unjs/c12), which supports multiple formats.
62
+
63
+ ### Supported Configuration Formats
64
+
65
+ You can use any of these formats for your configuration file:
66
+
67
+ - **JavaScript/TypeScript:** `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, `.cts`
68
+ - **JSON:** `.json`, `.jsonc`, `.json5`
69
+ - **YAML:** `.yaml`, `.yml`
70
+ - **TOML:** `.toml`
71
+
72
+ **Examples:**
73
+
74
+ - `changelog.config.ts` (TypeScript - recommended)
75
+ - `changelog.config.js` (JavaScript)
76
+ - `changelog.config.json` (JSON)
77
+ - `changelog.config.yaml` (YAML)
78
+
79
+ ### Minimal Configuration Example
80
+
81
+ **TypeScript/JavaScript** (recommended):
82
+
83
+ ```typescript
84
+ // changelog.config.ts
85
+ import { defineConfig } from 'relizy'
86
+
87
+ export default defineConfig({
88
+ monorepo: {
89
+ versionMode: 'selective', // 'unified', 'selective', 'independent'
90
+ packages: ['packages/*'], // glob pattern matching
91
+ },
92
+ })
93
+ ```
94
+
95
+ **JSON:**
96
+
97
+ ```json
98
+ {
99
+ "monorepo": {
100
+ "versionMode": "selective",
101
+ "packages": ["packages/*"]
102
+ }
103
+ }
104
+ ```
105
+
106
+ **YAML:**
107
+
108
+ ```yaml
109
+ monorepo:
110
+ versionMode: selective
111
+ packages:
112
+ - packages/*
113
+ ```
114
+
115
+ Check all options in the [configuration section](#configuration-options).
116
+
117
+ ## 🚀 Usage
118
+
119
+ ### Available commands
120
+
121
+ The CLI uses the `relizy` command:
122
+
123
+ ```bash
124
+ relizy <command> [options]
125
+ ```
126
+
127
+ #### 1. `release` - Complete release workflow
128
+
129
+ Executes the entire release workflow in one command:
130
+
131
+ 1. Bump versions
132
+ 2. Generate changelogs
133
+ 3. Commit changes
134
+ 4. Create git tag
135
+ 5. Push to remote
136
+ 6. Publish to npm
137
+ 7. Create GitHub/GitLab release
138
+
139
+ ```bash
140
+ # Complete release
141
+ relizy release --patch
142
+
143
+ # Release with pre-release
144
+ relizy release --prerelease --preid beta --tag beta
145
+
146
+ # Release with custom suffix (see bump --suffix)
147
+ relizy release --prerelease --preid beta --suffix abc123
148
+
149
+ # Without push to remote
150
+ relizy release --patch --no-push
151
+
152
+ # Without GitHub/GitLab release creation
153
+ relizy release --patch --no-release
154
+
155
+ # Without npm publish
156
+ relizy release --patch --no-publish
157
+
158
+ # Without git verification (skip hooks)
159
+ relizy release --patch --no-verify
160
+
161
+ # With npm options
162
+ relizy release --patch --registry https://npm.pkg.github.com --access public --otp 123456
163
+
164
+ # Force even without commits
165
+ relizy release --patch --force
166
+ ```
167
+
168
+ **Available options:**
169
+
170
+ All options from `bump`, `changelog`, `publish` and `provider-release` are available, and:
171
+
172
+ - `--no-push` - Don't push changes and tags to remote
173
+ - `--no-release` - Don't create GitHub/GitLab release
174
+ - `--no-publish` - Don't publish to npm
175
+ - `--no-verify` - Skip git hooks during commit
176
+ - `--no-commit` - Skip commit and tag creation
177
+ - `--no-changelog` - Skip changelog generation
178
+ - `--no-clean` - Skip working directory clean check
179
+ - `--token <token>` - Git token (GitHub or GitLab)
180
+ - `--force` - Force bump even without commits
181
+ - `--yes` - Skip confirmation prompt
182
+ - `--build-cmd <cmd>` - Command to build packages before publish
183
+ - `--suffix <suffix>` - Custom suffix for prerelease versions (see [bump --suffix](#suffix))
184
+
185
+ #### 2. `bump` - Update versions
186
+
187
+ Updates package version numbers.
188
+
189
+ ```bash
190
+ # Auto-detect bump type from commits
191
+ relizy bump
192
+
193
+ # Specify bump type
194
+ relizy bump --patch # 1.0.0 → 1.0.1
195
+ relizy bump --minor # 1.0.0 → 1.1.0
196
+ relizy bump --major # 1.0.0 → 2.0.0
197
+
198
+ # Pre-releases
199
+ relizy bump --prerelease --preid beta # 1.0.0 → 1.0.1-beta.0
200
+ relizy bump --premajor --preid alpha # 1.0.0 → 2.0.0-alpha.0
201
+ relizy bump --preminor --preid rc # 1.0.0 → 1.1.0-rc.0
202
+ relizy bump --prepatch --preid beta # 1.0.0 → 1.0.1-beta.0
203
+
204
+ # Pre-releases with custom suffix
205
+ relizy bump --prepatch --preid beta --suffix abc123 # 1.0.0 → 1.0.1-beta.abc123
206
+ relizy bump --prerelease --preid alpha --suffix 20241106 # 1.0.0-alpha.0 → 1.0.0-alpha.20241106
207
+
208
+ # Options
209
+ relizy bump --force # Force bump even without commits
210
+ relizy bump --yes # Skip confirmation prompt
211
+ relizy bump --no-clean # Skip working directory clean check
212
+ ```
213
+
214
+ **Available options:**
215
+
216
+ - `--major` - Bump major version
217
+ - `--minor` - Bump minor version
218
+ - `--patch` - Bump patch version
219
+ - `--prerelease` - Bump prerelease version
220
+ - `--premajor` - Bump premajor version
221
+ - `--preminor` - Bump preminor version
222
+ - `--prepatch` - Bump prepatch version
223
+ - `--preid <id>` - Prerelease identifier (alpha, beta, rc, etc.)
224
+ - `--suffix <suffix>` - Custom suffix for prerelease versions
225
+ - `--force` - Force bump even without commits
226
+ - `--yes` - Skip confirmation prompt
227
+ - `--no-clean` - Skip working directory clean check
228
+
229
+ ##### `--suffix`
230
+
231
+ The `--suffix` option allows you to customize the prerelease version number with a custom identifier instead of an auto-incremented number. This is particularly useful for CI/CD pipelines where you want to include build metadata in your version.
232
+
233
+ **How it works:**
234
+
235
+ When you use a prerelease bump type (`prepatch`, `preminor`, `premajor`, or `prerelease`) with the `--suffix` option, the version number's prerelease suffix will be replaced with your custom value instead of an auto-incremented number.
236
+
237
+ **Examples:**
238
+
239
+ ```bash
240
+ # Without suffix (default behavior)
241
+ relizy bump --prepatch --preid beta
242
+ # 1.0.0 → 1.0.1-beta.0
243
+
244
+ # With custom suffix
245
+ relizy bump --prepatch --preid beta --suffix abc123
246
+ # 1.0.0 → 1.0.1-beta.abc123
247
+
248
+ # Incrementing an existing prerelease with suffix
249
+ relizy bump --prerelease --preid beta --suffix xyz789
250
+ # 1.0.1-beta.0 → 1.0.1-beta.xyz789
251
+
252
+ # Common CI/CD use case: Git commit SHA
253
+ relizy bump --prerelease --preid alpha --suffix $(git rev-parse --short HEAD)
254
+ # 1.0.0-alpha.5 → 1.0.0-alpha.a1b2c3d
255
+
256
+ # Common CI/CD use case: Build number
257
+ relizy bump --prepatch --preid rc --suffix ${CI_PIPELINE_ID}
258
+ # 2.5.0 → 2.5.1-rc.12345
259
+
260
+ # Common CI/CD use case: Timestamp
261
+ relizy bump --preminor --preid beta --suffix $(date +%Y%m%d%H%M%S)
262
+ # 1.0.0 → 1.1.0-beta.20241106153045
263
+ ```
264
+
265
+ **Important notes:**
266
+
267
+ - The `--suffix` option **only works with prerelease bump types** (`prepatch`, `preminor`, `premajor`, `prerelease`)
268
+ - It has **no effect on stable release types** (`patch`, `minor`, `major`)
269
+ - The suffix can contain letters, numbers, or hyphens
270
+ - Suffix values follow semantic versioning rules for prerelease identifiers
271
+
272
+ **Use cases:**
273
+
274
+ 1. **CI/CD Pipelines**: Include build numbers, commit SHAs, or timestamps in your prerelease versions
275
+ 2. **Feature Branches**: Create unique prerelease versions for different branches
276
+ 3. **Testing**: Generate identifiable test releases
277
+ 4. **Reproducible Builds**: Track exact build metadata in version numbers
278
+
279
+ **Example in CI/CD (GitHub Actions):**
280
+
281
+ ```yaml
282
+ - name: Bump prerelease version
283
+ run: |
284
+ pnpm relizy bump --prerelease --preid beta --suffix ${{ github.sha }}
285
+ ```
286
+
287
+ **Example in CI/CD (GitLab CI):**
288
+
289
+ ```yaml
290
+ bump:
291
+ script:
292
+ - pnpm relizy bump --prepatch --preid rc --suffix $CI_COMMIT_SHORT_SHA
293
+ ```
294
+
295
+ #### 3. `changelog` - Generate changelogs
296
+
297
+ Generates CHANGELOG.md files for each package and at the root.
298
+
299
+ ```bash
300
+ # Generate all changelogs
301
+ relizy changelog
302
+
303
+ # Specify commit range
304
+ relizy changelog --from v1.0.0
305
+ relizy changelog --from v1.0.0 --to v1.1.0
306
+
307
+ # Format after generation
308
+ relizy changelog --format-cmd "pnpm lint:fix"
309
+
310
+ # Without root changelog
311
+ relizy changelog --no-root-changelog
312
+ ```
313
+
314
+ **Available options:**
315
+
316
+ - `--from <ref>` - Start commit reference
317
+ - `--to <ref>` - End commit reference
318
+ - `--format-cmd <cmd>` - Command to format CHANGELOGs after generation
319
+ - `--no-root-changelog` - Skip root changelog generation
320
+
321
+ #### 4. `publish` - Publish to npm
322
+
323
+ Publishes packages to npm registry (or other registry).
324
+
325
+ ```bash
326
+ # Simple publish
327
+ relizy publish
328
+
329
+ # With custom registry
330
+ relizy publish --registry https://npm.pkg.github.com
331
+
332
+ # With custom tag
333
+ relizy publish --tag next
334
+
335
+ # For scoped packages (public access)
336
+ relizy publish --access public
337
+
338
+ # With 2FA
339
+ relizy publish --otp 123456
340
+
341
+ # Build before publish
342
+ relizy publish --build-cmd "pnpm build"
343
+ ```
344
+
345
+ **Available options:**
346
+
347
+ - `--registry <url>` - Custom npm registry URL
348
+ - `--tag <tag>` - Publish tag (default: `latest` for stable, `next` for prerelease)
349
+ - `--access <type>` - Access level (`public` or `restricted`)
350
+ - `--otp <code>` - OTP code for 2FA
351
+ - `--build-cmd <cmd>` - Command to build packages before publish
352
+
353
+ **Automatic tag detection:**
354
+
355
+ - Stable version (e.g., `1.2.3`) → tag `latest`
356
+ - Prerelease version (e.g., `1.2.3-beta.0`) → tag `next`
357
+
358
+ #### 5. `provider-release` - Publish a release to git provider (github or gitlab)
359
+
360
+ Publishes a release for the latest tag.
361
+
362
+ ```bash
363
+ # Publish release
364
+ relizy provider-release
365
+
366
+ # With custom token
367
+ relizy provider-release --token YOUR_GITHUB_TOKEN
368
+
369
+ # Force git provider
370
+ relizy provider-release --provider github
371
+
372
+ # Specify range
373
+ relizy provider-release --from v1.0.0 --to v1.1.0
374
+ ```
375
+
376
+ **Available options:**
377
+
378
+ - `--from <ref>` - Start commit reference
379
+ - `--to <ref>` - End commit reference
380
+ - `--token <token>` - Git provider token
381
+ - `--provider <provider>` - Git provider (github or gitlab)
382
+
383
+ **Token:**
384
+
385
+ Multiple ways to provide the token:
386
+
387
+ - Command line option (`--token`)
388
+ - Configuration file (see [tokens](#tokens) section)
389
+ - Environment variables (checked in order):
390
+ - **GitHub:** `RELIZY_TOKENS_GITHUB`, `GITHUB_TOKEN`, `GH_TOKEN`
391
+ - **GitLab:** `RELIZY_TOKENS_GITLAB`, `GITLAB_TOKEN`, `GITLAB_API_TOKEN`, `CI_JOB_TOKEN`
392
+
393
+ ### Global options
394
+
395
+ All commands support these global options:
396
+
397
+ #### Config File
398
+
399
+ Use `--config` to specify a custom configuration file name (without the file extension):
400
+
401
+ ```bash
402
+ # Use default config (changelog.config.{ts,js,json,yaml,...})
403
+ relizy bump --patch
404
+
405
+ # Use custom config (changelog.standalone.config.{ts,js,json,yaml,...})
406
+ relizy bump --config changelog.standalone --patch
407
+
408
+ # Use another config (changelog.experimental.config.{ts,js,json,yaml,...})
409
+ relizy release --config changelog.experimental --minor
410
+ ```
411
+
412
+ **Important:**
413
+
414
+ - The config file name must follow the pattern: `<name>.config.<ext>` (e.g., `myconfig.config.ts`, `myconfig.config.json`)
415
+ - In the `--config` option, you only specify the `<name>` part (without `.config.<ext>`)
416
+ - Supported extensions: `.ts`, `.js`, `.mjs`, `.cjs`, `.mts`, `.cts`, `.json`, `.jsonc`, `.json5`, `.yaml`, `.yml`, `.toml`
417
+
418
+ #### Dry Run
419
+
420
+ Use `--dry-run` to preview changes without writing files, creating tags, commits, or publishing:
421
+
422
+ ```bash
423
+ # Preview bump
424
+ relizy bump --patch --dry-run
425
+
426
+ # Preview entire release workflow
427
+ relizy release --minor --dry-run
428
+
429
+ # Preview publish
430
+ relizy publish --dry-run
431
+ ```
432
+
433
+ #### Log Level
434
+
435
+ Use `--log-level` to control verbosity:
436
+
437
+ ```bash
438
+ # Default level (essential information)
439
+ relizy bump
440
+
441
+ # Debug level (detailed information)
442
+ relizy release --patch --log-level debug
443
+
444
+ # Silent level (errors only)
445
+ relizy publish --log-level silent
446
+ ```
447
+
448
+ **Available levels:**
449
+
450
+ - `silent` - Errors only
451
+ - `error` - Errors and critical warnings
452
+ - `warning` - Warnings and above
453
+ - `normal` - Normal information
454
+ - `default` - Essential information (default)
455
+ - `debug` - Detailed debugging information
456
+ - `trace` - Very detailed trace information
457
+ - `verbose` - Show everything
458
+
459
+ **Examples:**
460
+
461
+ ```bash
462
+ # Clean output with essential info
463
+ $ relizy bump --patch
464
+ ℹ 4.2.0 → 4.2.1 (unified mode)
465
+ ✔ All 3 package(s) bumped to 4.2.1
466
+
467
+ # Detailed output for debugging
468
+ $ relizy bump --patch --log-level debug
469
+ ● Loading monorepo configuration
470
+ ● Version mode: unified
471
+ ● From: v4.2.0, To: HEAD
472
+ ● Package patterns: packages/*
473
+ ● Found 3 package(s)
474
+ ● Starting bump in unified mode
475
+ ● Fetching commits from v4.2.0 to HEAD
476
+ ● Found 5 commits since v4.2.0
477
+ ● Detected release type from commits: patch
478
+ ℹ 4.2.0 → 4.2.1 (unified mode)
479
+ ● Writing version to 3 package(s)
480
+ ● Updating lerna.json version
481
+ ✔ All 3 package(s) bumped to 4.2.1
482
+ ```
483
+
484
+ ## ⚙️ Configuration
485
+
486
+ This tool extends [changelogen](https://github.com/unjs/changelogen) configuration with additional monorepo-specific options. Some options from changelogen are overridden to provide better monorepo support.
487
+
488
+ Create a `changelog.config.ts` file at the root of your project:
489
+
490
+ ```typescript
491
+ import { defineConfig } from 'relizy'
492
+
493
+ export default defineConfig({
494
+ // Standard changelogen configuration
495
+ types: {
496
+ feat: { title: '🚀 Features', semver: 'minor' },
497
+ fix: { title: '🩹 Fixes', semver: 'patch' },
498
+ },
499
+
500
+ // Monorepo configuration
501
+ monorepo: {
502
+ versionMode: 'selective',
503
+ packages: ['packages/*'],
504
+ ignorePackageNames: [],
505
+ },
506
+
507
+ // Optional configuration
508
+ changelog: {
509
+ formatCmd: 'pnpm lint:fix',
510
+ rootChangelog: true,
511
+ },
512
+
513
+ bump: {
514
+ type: 'release',
515
+ preid: undefined,
516
+ },
517
+
518
+ publish: {
519
+ private: false,
520
+ tag: 'latest',
521
+ args: [],
522
+ },
523
+
524
+ release: {
525
+ push: true,
526
+ release: true,
527
+ publish: true,
528
+ noVerify: false,
529
+ },
530
+ })
531
+ ```
532
+
533
+ ### Configuration options
534
+
535
+ The configuration extends [ChangelogConfig](https://github.com/unjs/changelogen#configuration) from changelogen with additional monorepo-specific options.
536
+
537
+ #### `types`
538
+
539
+ **Type:** `Record<string, { title: string, semver?: 'major' | 'minor' | 'patch' } | false>`
540
+
541
+ **Description:** Defines commit types and their impact on versioning.
542
+
543
+ - With `semver`: Triggers a version bump
544
+ - `'major'`: Breaking changes → 1.0.0 → 2.0.0
545
+ - `'minor'`: New features → 1.0.0 → 1.1.0
546
+ - `'patch'`: Bug fixes → 1.0.0 → 1.0.1
547
+ - Without `semver`: Appears in changelog but doesn't trigger a bump
548
+ - `false`: Completely ignored (no changelog, no bump)
549
+
550
+ **Example:**
551
+
552
+ ```typescript
553
+ export default defineConfig({
554
+ types: {
555
+ // Trigger a bump
556
+ feat: { title: '🚀 Features', semver: 'minor' },
557
+ fix: { title: '🩹 Fixes', semver: 'patch' },
558
+ perf: { title: '🔥 Performance', semver: 'patch' },
559
+
560
+ // Appear in changelog but no bump
561
+ docs: { title: '📖 Documentation' },
562
+ chore: { title: '🏡 Chore' },
563
+
564
+ // Completely ignored
565
+ ci: false,
566
+ test: false,
567
+ },
568
+ })
569
+ ```
570
+
571
+ #### `monorepo`
572
+
573
+ Monorepo-specific configuration (required).
574
+
575
+ | Property | Type | Default | Description |
576
+ | -------------------- | ----------------------------------------------- | ---------------- | ---------------------------------------- |
577
+ | `versionMode` | `'unified'` \| `'selective'` \| `'independent'` | `'selective'` | How versions are managed across packages |
578
+ | `packages` | `string[]` | `['packages/*']` | Glob patterns to locate packages |
579
+ | `ignorePackageNames` | `string[]` | `[]` | Package names to ignore |
580
+
581
+ **Version modes:**
582
+
583
+ | Mode | Version | Scope | Root & Lerna | Best for |
584
+ | ------------------ | ----------- | -------------------------- | ------------ | ------------------------------ |
585
+ | **`selective`** ⭐ | Unified | Only packages with commits | ✅ Updated | Most monorepos |
586
+ | **`unified`** | Unified | ALL packages | ✅ Updated | Keep all packages synchronized |
587
+ | **`independent`** | Independent | Only packages with commits | ❌ Unchanged | Collections of unrelated tools |
588
+
589
+ **Examples:**
590
+
591
+ ```typescript
592
+ export default defineConfig({
593
+ // Selective mode (recommended) - Only bump packages with commits
594
+ monorepo: {
595
+ versionMode: 'selective',
596
+ packages: ['packages/*'],
597
+ },
598
+
599
+ // Unified mode - Bump ALL packages together
600
+ // monorepo: {
601
+ // versionMode: 'unified',
602
+ // packages: ['packages/*', 'tools/*'],
603
+ // },
604
+
605
+ // Independent mode - Each package has its own version
606
+ // monorepo: {
607
+ // versionMode: 'independent',
608
+ // packages: ['packages/*'],
609
+ // ignorePackageNames: ['@myorg/internal-utils'],
610
+ // },
611
+ })
612
+ ```
613
+
614
+ #### `changelog`
615
+
616
+ Changelog generation configuration.
617
+
618
+ | Property | Type | Default | Description |
619
+ | ------------------- | --------- | ----------- | -------------------------------------------------- |
620
+ | `formatCmd` | `string` | `undefined` | Command to format changelogs after generation |
621
+ | `rootChangelog` | `boolean` | `true` | Generate root CHANGELOG.md with aggregated changes |
622
+ | `includeCommitBody` | `boolean` | `false` | Include full commit bodies in changelog entries |
623
+
624
+ **Example:**
625
+
626
+ ```typescript
627
+ export default defineConfig({
628
+ changelog: {
629
+ formatCmd: 'pnpm lint:fix',
630
+ rootChangelog: true,
631
+ includeCommitBody: true,
632
+ },
633
+ })
634
+ ```
635
+
636
+ #### `bump`
637
+
638
+ Version bump configuration.
639
+
640
+ | Property | Type | Default | Description |
641
+ | ----------------- | --------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------- |
642
+ | `type` | `'release'` \| `'major'` \| `'minor'` \| `'patch'` \| `'prerelease'` \| ... | `'release'` | Default bump type ('release' auto-detects from commits) |
643
+ | `preid` | `string` | `undefined` | Pre-release identifier (alpha, beta, rc, etc.) |
644
+ | `clean` | `boolean` | `true` | Check if working directory is clean before bumping |
645
+ | `dependencyTypes` | `Array<'dependencies' \| 'devDependencies' \| 'peerDependencies'>` | `['dependencies']` | Which dependency types trigger a version bump |
646
+ | `yes` | `boolean` | `true` | Skip confirmation prompt |
647
+
648
+ **Dependency types:** When a package is updated, this decides which dependent packages should also be bumped:
649
+
650
+ - `dependencies` - Packages that need it to work
651
+ - `devDependencies` - Packages that need it for building/testing
652
+ - `peerDependencies` - Packages that work alongside it
653
+
654
+ **Example:**
655
+
656
+ ```typescript
657
+ export default defineConfig({
658
+ bump: {
659
+ type: 'release',
660
+ dependencyTypes: ['dependencies', 'devDependencies'],
661
+ clean: true,
662
+ yes: true,
663
+ },
664
+ })
665
+ ```
666
+
667
+ #### `publish`
668
+
669
+ npm publishing configuration.
670
+
671
+ | Property | Type | Default | Description |
672
+ | ---------- | ---------------------------- | ----------- | --------------------------------------------------- |
673
+ | `private` | `boolean` | `false` | Don't publish packages |
674
+ | `tag` | `string` | `'latest'` | npm tag (auto: 'latest' for stable, 'next' for pre) |
675
+ | `registry` | `string` | `undefined` | Custom registry URL |
676
+ | `access` | `'public'` \| `'restricted'` | `undefined` | Package access level |
677
+ | `otp` | `string` | `undefined` | One-time password for 2FA |
678
+ | `buildCmd` | `string` | `undefined` | Command to build packages before publish |
679
+ | `args` | `string[]` | `[]` | Additional arguments for publish command |
680
+
681
+ **Example:**
682
+
683
+ ```typescript
684
+ export default defineConfig({
685
+ publish: {
686
+ private: false,
687
+ tag: 'latest',
688
+ registry: 'https://registry.npmjs.org',
689
+ access: 'public',
690
+ buildCmd: 'pnpm build',
691
+ },
692
+ })
693
+ ```
694
+
695
+ #### `release`
696
+
697
+ Release workflow configuration.
698
+
699
+ | Property | Type | Default | Description |
700
+ | ----------- | --------- | ------- | ----------------------------------- |
701
+ | `commit` | `boolean` | `true` | Commit changes and create tag |
702
+ | `push` | `boolean` | `true` | Push changes and tags to remote |
703
+ | `changelog` | `boolean` | `true` | Generate changelog files |
704
+ | `release` | `boolean` | `true` | Create release on GitHub/GitLab |
705
+ | `publish` | `boolean` | `true` | Publish to npm |
706
+ | `clean` | `boolean` | `true` | Check if working directory is clean |
707
+ | `noVerify` | `boolean` | `false` | Skip git hooks during commit |
708
+ | `force` | `boolean` | `false` | Force bump even without commits |
709
+
710
+ **Example:**
711
+
712
+ ```typescript
713
+ export default defineConfig({
714
+ release: {
715
+ commit: true,
716
+ push: true,
717
+ changelog: true,
718
+ release: true,
719
+ publish: true,
720
+ noVerify: false,
721
+ },
722
+ })
723
+ ```
724
+
725
+ #### `repo`
726
+
727
+ Git repository configuration (auto-detected by default).
728
+
729
+ | Property | Type | Default | Description |
730
+ | ---------- | ------------------------ | ------------- | -------------------------------------- |
731
+ | `provider` | `'github'` \| `'gitlab'` | Auto-detected | Git provider (auto from remote URL) |
732
+ | `domain` | `string` | `undefined` | Custom domain for self-hosted instance |
733
+ | `repo` | `string` | Auto-detected | Repository in 'owner/repo' format |
734
+ | `token` | `string` | From env vars | Authentication token |
735
+
736
+ **Auto-detection:**
737
+
738
+ - Provider: Detected from git remote URL (github.com → GitHub, gitlab.com → GitLab)
739
+ - Repository: Parsed from git remote URL
740
+ - Token: Read from environment variables (see [tokens](#tokens) section)
741
+
742
+ **Example:**
743
+
744
+ ```typescript
745
+ export default defineConfig({
746
+ // For self-hosted GitLab
747
+ repo: {
748
+ provider: 'gitlab',
749
+ domain: 'gitlab.mycompany.com',
750
+ },
751
+ })
752
+ ```
753
+
754
+ #### `tokens`
755
+
756
+ Authentication tokens for git providers (read from environment variables by default).
757
+
758
+ | Property | Type | Default | Description |
759
+ | -------- | -------- | ------------- | --------------------------- |
760
+ | `github` | `string` | From env vars | GitHub authentication token |
761
+ | `gitlab` | `string` | From env vars | GitLab authentication token |
762
+
763
+ **Environment variables checked (in order):**
764
+
765
+ - GitHub: `RELIZY_TOKENS_GITHUB`, `GITHUB_TOKEN`, `GH_TOKEN`
766
+ - GitLab: `RELIZY_TOKENS_GITLAB`, `GITLAB_TOKEN`, `GITLAB_API_TOKEN`, `CI_JOB_TOKEN`
767
+
768
+ **Example:**
769
+
770
+ ```typescript
771
+ export default defineConfig({
772
+ tokens: {
773
+ github: process.env.GITHUB_TOKEN,
774
+ gitlab: process.env.GITLAB_TOKEN,
775
+ },
776
+ })
777
+ ```
778
+
779
+ #### `templates`
780
+
781
+ Templates for commit and tag messages.
782
+
783
+ | Property | Type | Default | Description |
784
+ | ----------------------- | -------- | -------------------------------------------------- | ------------------------------------------- |
785
+ | `commitMessage` | `string` | `'chore(release): bump version to {{newVersion}}'` | Commit message template |
786
+ | `tagMessage` | `string` | `'Bump version to v{{newVersion}}'` | Git tag message template |
787
+ | `tagBody` | `string` | `'v{{newVersion}}'` | Git tag body (not used in independent mode) |
788
+ | `emptyChangelogContent` | `string` | `'No relevant changes for this release'` | Changelog content when no changes |
789
+
790
+ **Available variables:** `{{newVersion}}`, `{{oldVersion}}`, `{{packageName}}`
791
+
792
+ **Example:**
793
+
794
+ ```typescript
795
+ export default defineConfig({
796
+ templates: {
797
+ commitMessage: 'chore(release): v{{newVersion}} [skip ci]',
798
+ tagMessage: 'Release {{newVersion}}',
799
+ tagBody: 'Version {{newVersion}}',
800
+ },
801
+ })
802
+ ```
803
+
804
+ #### `logLevel`
805
+
806
+ Control verbosity of command output.
807
+
808
+ **Type:** `'silent' | 'error' | 'warning' | 'normal' | 'default' | 'debug' | 'trace' | 'verbose'`
809
+
810
+ **Default:** `'default'`
811
+
812
+ See [Log Level](#log-level) section for details.
813
+
814
+ #### Inherited from Changelogen
815
+
816
+ The following options are inherited from [changelogen configuration](https://github.com/unjs/changelogen#configuration):
817
+
818
+ | Property | Type | Default | Description |
819
+ | ---------------- | ------------------------ | --------------- | ----------------------------------------- |
820
+ | `cwd` | `string` | `process.cwd()` | Working directory |
821
+ | `from` | `string` | Last git tag | Start reference for changelog |
822
+ | `to` | `string` | `HEAD` | End reference for changelog |
823
+ | `excludeAuthors` | `string[]` | `[]` | List of authors to exclude from changelog |
824
+ | `noAuthors` | `boolean` | `false` | Don't include authors in changelog |
825
+ | `scopeMap` | `Record<string, string>` | `{}` | Map scopes to custom names |
826
+
827
+ **Example:**
828
+
829
+ ```typescript
830
+ export default defineConfig({
831
+ cwd: process.cwd(),
832
+ from: 'v1.0.0',
833
+ to: 'HEAD',
834
+ excludeAuthors: ['bot[bot]', 'dependabot'],
835
+ noAuthors: false,
836
+ scopeMap: {
837
+ ui: 'User Interface',
838
+ api: 'API',
839
+ },
840
+ })
841
+ ```
842
+
843
+ ### Configuration Examples
844
+
845
+ #### Simple configuration (selective mode)
846
+
847
+ ```typescript
848
+ import { defineConfig } from 'relizy'
849
+
850
+ export default defineConfig({
851
+ types: {
852
+ feat: { title: '🚀 Features', semver: 'minor' },
853
+ fix: { title: '🩹 Fixes', semver: 'patch' },
854
+ },
855
+ monorepo: {
856
+ versionMode: 'selective',
857
+ packages: ['packages/*'],
858
+ },
859
+ })
860
+ ```
861
+
862
+ #### Advanced configuration
863
+
864
+ ```typescript
865
+ import { defineConfig } from 'relizy'
866
+
867
+ export default defineConfig({
868
+ types: {
869
+ feat: { title: '🚀 Features', semver: 'minor' },
870
+ fix: { title: '🩹 Fixes', semver: 'patch' },
871
+ perf: { title: '🔥 Performance', semver: 'patch' },
872
+ docs: { title: '📖 Documentation' },
873
+ chore: { title: '🏡 Chore' },
874
+ ci: false,
875
+ test: false,
876
+ },
877
+
878
+ monorepo: {
879
+ versionMode: 'selective',
880
+ packages: ['packages/*', 'tools/*'],
881
+ ignorePackageNames: ['@myorg/eslint-config'],
882
+ },
883
+
884
+ changelog: {
885
+ formatCmd: 'pnpm lint:fix',
886
+ rootChangelog: true,
887
+ },
888
+
889
+ bump: {
890
+ type: 'release',
891
+ },
892
+
893
+ publish: {
894
+ private: false,
895
+ tag: 'latest',
896
+ },
897
+
898
+ release: {
899
+ push: true,
900
+ release: true,
901
+ publish: true,
902
+ noVerify: false,
903
+ },
904
+
905
+ templates: {
906
+ commitMessage: 'chore(release): v{{newVersion}}',
907
+ },
908
+ })
909
+ ```
910
+
911
+ #### Configuration for self-hosted GitLab
912
+
913
+ ```typescript
914
+ import { defineConfig } from 'relizy'
915
+
916
+ export default defineConfig({
917
+ repo: {
918
+ domain: 'gitlab.mycompany.com',
919
+ provider: 'gitlab',
920
+ },
921
+ monorepo: {
922
+ versionMode: 'selective',
923
+ packages: ['packages/*'],
924
+ },
925
+ })
926
+ ```
927
+
928
+ ## 📁 Multiple Configuration Files
929
+
930
+ You can create multiple configuration files to manage different release workflows in your monorepo. This is useful when you have packages with different versioning strategies or release cadences.
931
+
932
+ ### Use Cases
933
+
934
+ **Common scenarios for multiple configs:**
935
+
936
+ 1. **Separate core packages from standalone utilities** - Core UI packages use `selective` mode together, while standalone utilities use `independent` mode
937
+ 2. **Different release cadences** - Stable packages vs experimental packages
938
+ 3. **Different registries** - Public npm vs private registry
939
+ 4. **Different package groups** - Apps vs libraries vs tools
940
+
941
+ ### How to Create Multiple Configs
942
+
943
+ Create multiple configuration files following this naming pattern: `<name>.config.<ext>`
944
+
945
+ **Example file structure:**
946
+
947
+ ```
948
+ /
949
+ ├── changelog.config.ts # Main config (core packages)
950
+ ├── changelog.standalone.config.ts # Standalone utilities config
951
+ └── changelog.experimental.config.json # Experimental packages config
952
+ ```
953
+
954
+ You can use any supported format (`.ts`, `.js`, `.json`, `.yaml`, etc.) for each config file.
955
+
956
+ ### Example: Core UI Packages vs Standalone Utilities
957
+
958
+ This is a real-world example where you want to separate UI components (which should be released together) from standalone utilities (which can evolve independently).
959
+
960
+ **`changelog.config.ts`** - Core UI packages (selective mode):
961
+
962
+ ```typescript
963
+ import { defineConfig } from 'relizy'
964
+
965
+ export default defineConfig({
966
+ types: {
967
+ feat: { title: '🚀 Features', semver: 'minor' },
968
+ fix: { title: '🩹 Fixes', semver: 'patch' },
969
+ },
970
+ monorepo: {
971
+ versionMode: 'selective',
972
+ packages: [
973
+ 'packages/lib',
974
+ 'packages/icons',
975
+ 'packages/themes',
976
+ 'packages/nuxt',
977
+ 'packages/translations',
978
+ ],
979
+ },
980
+ templates: {
981
+ commitMessage: 'chore(release): v{{newVersion}}',
982
+ },
983
+ })
984
+ ```
985
+
986
+ **`changelog.standalone.config.ts`** - Standalone utilities (independent mode):
987
+
988
+ ```typescript
989
+ import { defineConfig } from 'relizy'
990
+
991
+ export default defineConfig({
992
+ types: {
993
+ feat: { title: '🚀 Features', semver: 'minor' },
994
+ fix: { title: '🩹 Fixes', semver: 'patch' },
995
+ },
996
+ monorepo: {
997
+ versionMode: 'independent',
998
+ packages: [
999
+ 'packages/utils',
1000
+ 'packages/node',
1001
+ 'packages/changelogen-monorepo',
1002
+ 'packages/eslint-config',
1003
+ ],
1004
+ },
1005
+ templates: {
1006
+ commitMessage: 'chore(release): {{packageName}}@{{newVersion}}',
1007
+ },
1008
+ changelog: {
1009
+ rootChangelog: false, // No root changelog for independent packages
1010
+ },
1011
+ })
1012
+ ```
1013
+
1014
+ ### Usage with Multiple Configs
1015
+
1016
+ ```bash
1017
+ # Release core UI packages together (selective mode)
1018
+ pnpm relizy release --patch
1019
+ # or explicitly
1020
+ pnpm relizy release --config changelog --patch
1021
+
1022
+ # Release standalone utilities independently
1023
+ pnpm relizy release --config changelog.standalone --patch
1024
+
1025
+ # You can also use different configs for different commands
1026
+ pnpm relizy bump --config changelog.standalone --minor
1027
+ pnpm relizy changelog --config changelog.standalone
1028
+ pnpm relizy publish --config changelog.standalone
1029
+ ```
1030
+
1031
+ ### Example: Different Registries
1032
+
1033
+ **`changelog.config.ts`** - Public packages (npm registry):
1034
+
1035
+ ```typescript
1036
+ import { defineConfig } from 'relizy'
1037
+
1038
+ export default defineConfig({
1039
+ monorepo: {
1040
+ versionMode: 'selective',
1041
+ packages: ['packages/public/*'],
1042
+ },
1043
+ publish: {
1044
+ registry: 'https://registry.npmjs.org',
1045
+ access: 'public',
1046
+ },
1047
+ })
1048
+ ```
1049
+
1050
+ **`changelog.private.config.ts`** - Private packages (GitHub Packages):
1051
+
1052
+ ```typescript
1053
+ import { defineConfig } from 'relizy'
1054
+
1055
+ export default defineConfig({
1056
+ monorepo: {
1057
+ versionMode: 'independent',
1058
+ packages: ['packages/private/*'],
1059
+ },
1060
+ publish: {
1061
+ registry: 'https://npm.pkg.github.com',
1062
+ access: 'restricted',
1063
+ },
1064
+ })
1065
+ ```
1066
+
1067
+ ```bash
1068
+ # Publish public packages to npm
1069
+ pnpm relizy publish
1070
+
1071
+ # Publish private packages to GitHub Packages
1072
+ pnpm relizy publish --config changelog.private
1073
+ ```
1074
+
1075
+ ### Best Practices
1076
+
1077
+ 1. **Use descriptive config names** - `changelog.standalone.config.ts` is better than `changelog.alt.config.ts`
1078
+ 2. **Document your workflow** - Add comments in your config files explaining the purpose
1079
+ 3. **Keep it simple** - Don't create too many configs unless necessary
1080
+ 4. **Version control** - Commit all config files to your repository
1081
+ 5. **CI/CD integration** - Use different configs in different CI jobs if needed
1082
+
1083
+ ### Tips
1084
+
1085
+ - The default config is `changelog.config.<ext>` where c12 will auto-detect the extension (you don't need `--config` flag)
1086
+ - Config files must follow the pattern `<name>.config.<ext>` (c12 requirement)
1087
+ - Supported formats: `.ts`, `.js`, `.mjs`, `.cjs`, `.mts`, `.cts`, `.json`, `.jsonc`, `.json5`, `.yaml`, `.yml`, `.toml`
1088
+ - All commands support the `--config` option
1089
+ - You can combine `--config` with `--dry-run` to preview different workflows
1090
+
1091
+ ## 🔗 Dependency Management
1092
+
1093
+ The tool automatically detects and bumps packages that depend on other packages in the monorepo.
1094
+
1095
+ ### How it works
1096
+
1097
+ **Automatic detection:**
1098
+
1099
+ - When package B is updated, all packages that depend on B are automatically identified
1100
+ - By default only `dependencies` are considered (not `devDependencies` or `peerDependencies`). You can change this behavior using the [dependencyTypes](#bump) option.
1101
+ - Transitive dependencies are handled: if A→B→C and C is updated, both B and A are bumped
1102
+
1103
+ **Bump types by mode:**
1104
+
1105
+ - **Selective/unified mode:** Dependent packages get the same unified version as the root
1106
+ - **Independent mode:** Dependent packages get a minimum `patch` bump (can be higher if they also have commits)
1107
+
1108
+ **Example:**
1109
+
1110
+ ```bash
1111
+ Packages:
1112
+ - @maz-ui/utils@1.0.0
1113
+ - @maz-ui/components@2.0.0 (depends on @maz-ui/utils)
1114
+ - @maz-ui/forms@1.5.0 (depends on @maz-ui/components)
1115
+
1116
+ Commit: feat(utils): add new utility
1117
+
1118
+ Result in Independent mode:
1119
+ - @maz-ui/utils: 1.0.0 → 1.1.0 (minor - from commit)
1120
+ - @maz-ui/components: 2.0.0 → 2.0.1 (patch - dependency updated)
1121
+ - @maz-ui/forms: 1.5.0 → 1.5.1 (patch - transitive dependency)
1122
+
1123
+ Result in Selective mode:
1124
+ - All 3 packages: bumped to unified version 2.1.0
1125
+ - Root version: 2.0.0 → 2.1.0
1126
+ ```
1127
+
1128
+ ## 🔄 Lerna Integration
1129
+
1130
+ ### Automatic `lerna.json` updates
1131
+
1132
+ If a `lerna.json` file exists at the root, the tool automatically updates its `version` field during bump (in unified and selective modes only).
1133
+
1134
+ **No `lerna.json`?** No problem! The tool works perfectly without it.
1135
+
1136
+ ### Replacing Lerna commands
1137
+
1138
+ | Lerna command | relizy equivalent |
1139
+ | --------------------------------------- | ------------------------------------------ |
1140
+ | `lerna version patch` | `relizy release --patch` |
1141
+ | `lerna version minor` | `relizy release --minor` |
1142
+ | `lerna version major` | `relizy release --major` |
1143
+ | `lerna version prerelease --preid beta` | `relizy release --prerelease --preid beta` |
1144
+ | `lerna publish from-package` | Not needed (use `pnpm publish -r`) |
1145
+
1146
+ ### Migration from Lerna
1147
+
1148
+ 1. Keep your existing `lerna.json` (optional)
1149
+ 2. Create a `changelog.config.ts` with your versioning strategy
1150
+ 3. Replace `lerna version` with `relizy release`
1151
+ 4. Use your package manager to publish (e.g., `pnpm publish -r`)
1152
+
1153
+ ## 🦊 GitLab CI/CD Configuration
1154
+
1155
+ ### Personal Access Token
1156
+
1157
+ 1. Go to GitLab → Settings → Access Tokens
1158
+ 2. Create a token with `api` scope
1159
+ 3. Set the environment variable:
1160
+
1161
+ ```bash
1162
+ GITLAB_TOKEN="your-token-here"
1163
+ ```
1164
+
1165
+ ### CI/CD Pipeline
1166
+
1167
+ GitLab CI automatically provides `CI_JOB_TOKEN` which can be used for releases:
1168
+
1169
+ ```yaml
1170
+ release:
1171
+ stage: deploy
1172
+ script:
1173
+ - pnpm install
1174
+ - pnpm relizy release --yes
1175
+ only:
1176
+ - main
1177
+ ```
1178
+
1179
+ ## Programmatic Usage (API)
1180
+
1181
+ You can also use the tool programmatically:
1182
+
1183
+ ```typescript
1184
+ import {
1185
+ bump,
1186
+ changelog,
1187
+ providerRelease,
1188
+ publish,
1189
+ release,
1190
+ } from 'relizy'
1191
+
1192
+ // Bump versions
1193
+ await bump({
1194
+ type: 'prerelease',
1195
+ preid: 'beta',
1196
+ })
1197
+
1198
+ // Generate changelogs
1199
+ await changelog({
1200
+ from: 'v1.0.0',
1201
+ to: 'v1.1.0',
1202
+ })
1203
+
1204
+ // Publish to npm
1205
+ await publish({
1206
+ registry: 'https://registry.npmjs.org',
1207
+ tag: 'beta',
1208
+ })
1209
+
1210
+ // GitHub release
1211
+ // Git provider is detected automatically but you can also specify it explicitly
1212
+ await providerRelease({
1213
+ provider: 'github',
1214
+ })
1215
+
1216
+ // Complete workflow
1217
+ await release({
1218
+ type: 'prerelease',
1219
+ preid: 'beta',
1220
+ tag: 'beta',
1221
+ registry: 'https://registry.npmjs.org',
1222
+ push: true,
1223
+ release: true,
1224
+ publish: true,
1225
+ })
1226
+ ```
1227
+
1228
+ ## License
1229
+
1230
+ MIT