@oorabona/release-it-preset 0.7.0 → 0.8.1

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 (3) hide show
  1. package/README.md +110 -23
  2. package/bin/cli.js +58 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -562,56 +562,143 @@ GIT_REQUIRE_CLEAN="true" \
562
562
  pnpm release
563
563
  ```
564
564
 
565
- ## Configuration Override
565
+ ## Configuration Modes
566
566
 
567
- You can override any configuration in your project's `.release-it.json`:
567
+ The preset supports two configuration modes:
568
+
569
+ ### Mode 1: Direct Preset Usage (No Config File)
570
+
571
+ **When to use:** Simple projects, trust preset defaults, or customize only via environment variables
572
+
573
+ Don't create `.release-it.json`. Just run the CLI:
574
+
575
+ ```bash
576
+ pnpm release-it-preset default
577
+ ```
578
+
579
+ All configuration comes from the preset and environment variables.
580
+
581
+ **Pros:**
582
+ - ✅ Zero config files
583
+ - ✅ Consistent behavior across projects
584
+ - ✅ Easy to understand
585
+ - ✅ Perfect for getting started
586
+
587
+ ---
588
+
589
+ ### Mode 2: Preset + User Overrides (Recommended)
590
+
591
+ **When to use:** Customize specific options while keeping preset defaults
592
+
593
+ Create `.release-it.json` **WITH the `extends` field**:
568
594
 
569
595
  ```json
570
596
  {
571
597
  "extends": "@oorabona/release-it-preset/config/default",
572
598
  "git": {
573
- "requireBranch": "develop",
599
+ "requireBranch": "master",
574
600
  "commitMessage": "chore: release v${version}"
575
- },
576
- "github": {
577
- "releaseName": "Release ${version}"
578
601
  }
579
602
  }
580
603
  ```
581
604
 
582
- ### CLI Behavior with User Configuration
605
+ Run with CLI preset:
583
606
 
584
- **Important:** The CLI now intelligently detects and respects your `.release-it.json` file:
607
+ ```bash
608
+ pnpm release-it-preset default
609
+ ```
585
610
 
586
- - **With `.release-it.json` present:**
587
- - The CLI runs `release-it` without `--config` flag
588
- - release-it naturally merges your config with the preset via the `extends` field
589
- - **Your settings have priority** over preset defaults
590
- - Perfect for customizing tag names, commit messages, branch requirements, etc.
611
+ **How it works:**
612
+ - The `extends` field loads the preset
613
+ - release-it merges your overrides on top via c12
614
+ - **Your values take precedence** over preset defaults
615
+ - CLI validates that `extends` matches the command
591
616
 
592
- - **Without `.release-it.json`:**
593
- - The CLI runs `release-it --config <preset-path>`
594
- - Uses preset configuration directly
595
- - Works exactly as before
617
+ **Pros:**
618
+ - **Recommended for customization**
619
+ - Declarative config with explicit preset
620
+ - Industry standard pattern (like ESLint, TypeScript)
621
+ - ✅ Guaranteed config merging via release-it's c12
596
622
 
597
- **Example of customizing the default preset:**
623
+ **Example:** Using `hotfix` preset but release from `master` instead of `main`:
598
624
 
599
625
  ```json
600
626
  {
601
- "extends": "@oorabona/release-it-preset/config/default",
627
+ "extends": "@oorabona/release-it-preset/config/hotfix",
602
628
  "git": {
603
- "tagName": "release-${version}",
604
- "requireBranch": "develop"
629
+ "requireBranch": "master"
605
630
  }
606
631
  }
607
632
  ```
608
633
 
609
- Then run:
610
634
  ```bash
635
+ pnpm release-it-preset hotfix
636
+ ```
637
+
638
+ ---
639
+
640
+ ### Configuration Validation
641
+
642
+ The CLI validates your `.release-it.json` to prevent misconfigurations:
643
+
644
+ #### Error 1: Missing `extends` field
645
+
646
+ ```bash
647
+ # .release-it.json without extends:
648
+ {
649
+ "git": { "requireBranch": "master" }
650
+ }
651
+
652
+ # Running:
611
653
  pnpm release-it-preset default
654
+
655
+ # ❌ Configuration error!
656
+ # .release-it.json is missing the required "extends" field.
657
+ #
658
+ # Without "extends", your config won't merge with the preset.
659
+ # This means you'll get release-it defaults instead of preset defaults.
660
+ #
661
+ # Fix by adding this to .release-it.json:
662
+ # {
663
+ # "extends": "@oorabona/release-it-preset/config/default",
664
+ # ...your overrides
665
+ # }
612
666
  ```
613
667
 
614
- The CLI will use your customized settings instead of the preset defaults!
668
+ **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`.
669
+
670
+ #### Error 2: Preset mismatch
671
+
672
+ ```bash
673
+ # .release-it.json extends "default":
674
+ {
675
+ "extends": "@oorabona/release-it-preset/config/default"
676
+ }
677
+
678
+ # But you run:
679
+ pnpm release-it-preset hotfix
680
+
681
+ # ❌ Configuration mismatch error!
682
+ # CLI preset: hotfix
683
+ # .release-it.json extends: default
684
+ #
685
+ # Either:
686
+ # 1. Run: release-it-preset default
687
+ # 2. Update .release-it.json extends to: "@oorabona/release-it-preset/config/hotfix"
688
+ ```
689
+
690
+ ---
691
+
692
+ ### Which Mode Should I Use?
693
+
694
+ | Scenario | Recommended Mode |
695
+ |----------|------------------|
696
+ | Quick start, minimal config | **Mode 1** (No config file) |
697
+ | Customize branch/commit/hooks | **Mode 2** (Config with extends) |
698
+ | Environment-only customization | **Mode 1** (Use env vars) |
699
+ | Monorepo with per-package config | **Mode 2** (Each package has own config) |
700
+
701
+ **Use Mode 1 to get started, switch to Mode 2 when you need customization.**
615
702
 
616
703
  ## Borrowing Scripts & Workflows
617
704
 
package/bin/cli.js CHANGED
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  import { spawn } from 'node:child_process';
27
- import { existsSync } from 'node:fs';
27
+ import { existsSync, readFileSync } from 'node:fs';
28
28
  import { fileURLToPath } from 'node:url';
29
29
  import { dirname, join } from 'node:path';
30
30
  import { validateConfigName, validateUtilityCommand, sanitizeArgs } from './validators.js';
@@ -110,25 +110,71 @@ function handleReleaseCommand(configName, args) {
110
110
 
111
111
  const releaseItCommand = 'release-it';
112
112
  let fullArgs;
113
- let strategyMessage;
114
113
 
115
114
  if (hasUserConfig) {
116
- // User has .release-it.json - let release-it handle the merge naturally
117
- // The user config should have "extends": "@oorabona/release-it-preset/config/<preset>"
115
+ // Read and validate user config
116
+ try {
117
+ const userConfigContent = readFileSync(userConfigPath, 'utf8');
118
+ const userConfig = JSON.parse(userConfigContent);
119
+
120
+ const expectedExtends = `@oorabona/release-it-preset/config/${configName}`;
121
+
122
+ if (!userConfig.extends) {
123
+ // ERROR: extends is required for config merging
124
+ console.error(`\n❌ Configuration error!`);
125
+ console.error(` .release-it.json is missing the required "extends" field.`);
126
+ console.error(``);
127
+ console.error(`Without "extends", your config won't merge with the preset.`);
128
+ console.error(`This means you'll get release-it defaults instead of preset defaults.`);
129
+ console.error(``);
130
+ console.error(`Fix by adding this to .release-it.json:`);
131
+ console.error(` {`);
132
+ console.error(` "extends": "${expectedExtends}",`);
133
+ console.error(` ...your overrides`);
134
+ console.error(` }`);
135
+ console.error(``);
136
+ console.error(`Or remove .release-it.json to use the preset directly.\n`);
137
+ process.exit(1);
138
+ }
139
+
140
+ // Validate extends matches CLI preset
141
+ const extendsMatch = userConfig.extends.match(/@oorabona\/release-it-preset\/config\/(\w+)/);
142
+ const extendsPreset = extendsMatch?.[1];
143
+
144
+ if (extendsPreset && extendsPreset !== configName) {
145
+ console.error(`\n❌ Configuration mismatch error!`);
146
+ console.error(` CLI preset: ${configName}`);
147
+ console.error(` .release-it.json extends: ${extendsPreset}`);
148
+ console.error(``);
149
+ console.error(`Either:`);
150
+ console.error(` 1. Run: release-it-preset ${extendsPreset}`);
151
+ console.error(` → Use the preset specified in your config file`);
152
+ console.error(``);
153
+ console.error(` 2. Update .release-it.json extends to: "${expectedExtends}"`);
154
+ console.error(` → Match your config file to the CLI command\n`);
155
+ process.exit(1);
156
+ }
157
+
158
+ console.log(`✅ Config validated: preset "${configName}"`);
159
+ console.log(`📝 Using: ${userConfigPath}\n`);
160
+ } catch (error) {
161
+ if (error instanceof SyntaxError) {
162
+ console.error(`❌ Failed to parse .release-it.json: ${error.message}`);
163
+ } else {
164
+ console.error(`❌ Error reading .release-it.json: ${error.message}`);
165
+ }
166
+ process.exit(1);
167
+ }
168
+
169
+ // Let release-it discover .release-it.json and merge via extends
118
170
  fullArgs = [...args];
119
- strategyMessage = `📝 Using user config: ${userConfigPath}\n (should extend preset: ${configName})`;
120
- console.log(strategyMessage);
121
- console.log(`ℹ️ Ensure your .release-it.json contains: "extends": "@oorabona/release-it-preset/config/${configName}"`);
122
171
  } else {
123
172
  // No user config - use preset directly
173
+ console.log(`📝 Using preset config directly: ${configPath}`);
174
+ console.log(` Tip: Create .release-it.json with "extends" to customize\n`);
124
175
  fullArgs = ['--config', configPath, ...args];
125
- strategyMessage = `📝 Using preset config directly: ${configPath}`;
126
- console.log(strategyMessage);
127
- console.log(`ℹ️ Tip: Create .release-it.json with "extends" to customize the preset`);
128
176
  }
129
177
 
130
- console.log(`💡 Command: ${releaseItCommand} ${fullArgs.join(' ')}\n`);
131
-
132
178
  const child = spawn(releaseItCommand, fullArgs, {
133
179
  stdio: 'inherit',
134
180
  shell: false, // Security: disable shell to prevent command injection
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oorabona/release-it-preset",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Shared release-it configuration and scripts for the organisation",
5
5
  "type": "module",
6
6
  "keywords": [