relion 0.36.0 → 0.37.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
@@ -2,16 +2,16 @@
2
2
  <img src=".github/logo.png" alt="logo"/>
3
3
  <br><br>
4
4
  <a href="https://www.npmjs.com/package/relion"><img src="https://img.shields.io/npm/v/relion?label=npm&logo=npm&style=flat-square&color=c8c9f1&labelColor=363a4f" alt="npm version"/></a>&nbsp;
5
- <a href="https://bundlephobia.com/package/relion"><img src="https://img.shields.io/bundlephobia/minzip/relion?label=%F0%9F%93%A6%20Size&style=flat-square&color=c8c9f1&labelColor=363a4f" alt="bundle size"/></a>&nbsp;
5
+ <a href="https://www.npmjs.com/package/relion"><img src="https://img.badgesize.io/https:/unpkg.com/relion/dist/index.js?label=Size&logo=hackthebox&logoColor=c97026&style=flat-square&color=c8c9f1&labelColor=363a4f" alt="runtime size"/></a>&nbsp;
6
6
  <a href="https://github.com/kh4f/relion/blob/master/LICENSE"><img src="https://img.shields.io/github/license/kh4f/relion?style=flat-square&label=%F0%9F%9B%A1%EF%B8%8F%20License&color=c8c9f1&labelColor=363a4f" alt="license"></a>&nbsp;
7
7
  <a href="https://github.com/kh4f/relion/issues?q=is%3Aissue+is%3Aopen+label%3Abug"><img src="https://img.shields.io/github/issues/kh4f/relion/bug?label=%F0%9F%90%9E%20Bugs&style=flat-square&color=c8c9f1&labelColor=363a4f" alt="open bugs"></a>
8
- <br><br><br>
9
- <b>A minimal npm library for automating release workflow:</b><br>version bumping, release commit & tag creation, and AI‑assisted changelog generation.
8
+ <br><br>
9
+ <b>A minimal npm library for automating release workflow:</b> version bumping,<br>release commit & tag creation, and AI‑assisted changelog generation.
10
10
  <br><br>
11
11
  <p>
12
12
  <b>
13
13
  <a href="#-installation">Installation</a>&nbsp; •&nbsp;
14
- <a href="#-cli-usage">CLI</a>&nbsp; •&nbsp;
14
+ <a href="#%EF%B8%8F-cli-usage">CLI</a>&nbsp; •&nbsp;
15
15
  <a href="#-api-usage">API</a>&nbsp; •&nbsp;
16
16
  <a href="#%EF%B8%8F-workflow-steps">Workflow Steps</a>&nbsp; •&nbsp;
17
17
  <a href="#-changelog-generation">Changelog Generation</a>
@@ -26,34 +26,62 @@
26
26
  pnpm add -D relion
27
27
  ```
28
28
 
29
- ## 🚀 CLI Usage
30
- Running the CLI without arguments prints help
29
+ ## 🕹️ CLI Usage
31
30
 
32
31
  ```bash
33
- $ pnpm relion
32
+ $ pnpm relion -h
34
33
 
35
34
  Usage: relion [options]
36
35
 
37
36
  Options:
38
- -b Bump the version
39
37
  -f Prepare release context
38
+ -b Bump the version
40
39
  -c Create a release commit
41
40
  -t Create a release tag
42
41
  -v <version> Set the new version explicitly
43
42
  -d Run in dry run mode
43
+ -h Show the help message
44
44
 
45
45
  Examples:
46
46
  - `pnpm relion -bct` — bump version, create release commit and tag
47
47
  - `pnpm relion -f` — generate release context file
48
+ - `pnpm relion` — run all release steps
48
49
  ```
49
50
 
51
+ <details><summary>Example output of running <code>pnpm relion</code>:</summary>
52
+
53
+ ```txt
54
+ ------------------------------
55
+ Current version: 0.36.1
56
+ Current tag: v0.36.1
57
+ Filtered commits: 16
58
+ New version: 0.37.0
59
+ New tag: v0.37.0
60
+ Commit message: 'chore(release): v0.37.0'
61
+ Repo URL: https://github.com/kh4f/relion
62
+ ------------------------------
63
+
64
+ About to write context to 'RELEASE.md'
65
+ Press Enter to continue ('s' to skip):
66
+
67
+ About to bump versions in files: package.json
68
+ Press Enter to continue ('s' to skip):
69
+
70
+ About to commit changes: 'git commit -m "chore(release): v0.37.0"'
71
+ Press Enter to continue ('s' to skip):
72
+
73
+ About to create a tag: 'git tag v0.37.0 -m "chore(release): v0.37.0"'
74
+ Press Enter to continue ('s' to skip):
75
+ ```
76
+ </details>
77
+
50
78
  ## 🧩 API Usage
51
79
 
52
80
  ```ts
53
81
  import relion from 'relion';
54
82
 
55
83
  relion({
56
- flow: ['bump', 'context', 'commit', 'tag'],
84
+ flow: ['context', 'bump', 'commit', 'tag'],
57
85
  newVersion: '1.2.3',
58
86
  bumpFiles: [
59
87
  'package.json', // uses default bumper
@@ -74,7 +102,7 @@ relion({
74
102
 
75
103
  ### Options
76
104
 
77
- - `flow`: release workflow steps (`'bump' | 'context' | 'commit' | 'tag'`) (default: `[]`)
105
+ - `flow`: release workflow steps (`'context' | 'bump' | 'commit' | 'tag'`) (default: `[]`)
78
106
  - `newVersion`: set the new version explicitly
79
107
  - `bumpFiles`: files or custom bumpers for version update (default: [`'package.json'`])
80
108
  - `contextFile`: path to release context output file (default: `'RELEASE.md'`)
@@ -110,9 +138,9 @@ Relion can also be configured via `relion` field in `package.json`:
110
138
 
111
139
  ## ♻️ Workflow Steps
112
140
 
113
- - **Bump**: updates version in specified files
114
141
  - **Context**: generates a file with upcoming release metadata and commit log
115
- - **Commit**: creates a release commit (release context file is not committed)
142
+ - **Bump**: updates version in specified files
143
+ - **Commit**: creates a release commit
116
144
  - **Tag**: creates an annotated release tag
117
145
 
118
146
  <details><summary>Generated release context example (*):</summary>
@@ -146,14 +174,14 @@ Relion doesn’t format the changelog itself — it produces a release context t
146
174
 
147
175
  Recommended workflow:
148
176
 
149
- 1. Set up GitHub Copilot instructions and prompt:
177
+ 1. Set up GitHub Copilot instruction and prompt:
150
178
  - [.github/instructions/changelog-format.instructions.md](.github/instructions/changelog-format.instructions.md)
151
179
  - [.github/prompts/generate-changelog.prompt.md](.github/prompts/generate-changelog.prompt.md)
152
180
  2. Run the context step to generate RELEASE.md: `pnpm relion -f`
153
181
  3. Run the prompt in VSCode Copilot chat: `/generate-changelog`
154
182
  4. Copilot produces a polished changelog entry based on the release context
155
183
 
156
- <details><summary>Generated changelog example (from the (*) release context using the instructions and prompt above; Gemini 3 Pro)</summary>
184
+ <details><summary>Generated changelog example (from the (*) release context using the instruction and prompt above; Gemini 3 Pro)</summary>
157
185
 
158
186
  ```md
159
187
  ## &ensp; [` 📦 v0.33.0 `](https://github.com/kh4f/relion/compare/v0.32.1...v0.33.0)
package/dist/cli.js CHANGED
@@ -1,14 +1,16 @@
1
- import e from"./index.js";const t=process.argv.slice(2).join(` `);t||(console.log(`Usage: relion [options]
1
+ import e from"./index.js";const t=process.argv.slice(2).join(` `);t.includes(`-h`)&&(console.log(`Usage: relion [options]
2
2
 
3
3
  Options:
4
- -b Bump the version
5
4
  -f Prepare release context
5
+ -b Bump the version
6
6
  -c Create a release commit
7
7
  -t Create a release tag
8
8
  -v <version> Set the new version explicitly
9
9
  -d Run in dry run mode
10
+ -h Show the help message
10
11
 
11
12
  Examples:
12
13
  - \`pnpm relion -bct\` — bump version, create release commit and tag
13
14
  - \`pnpm relion -f\` — generate release context file
14
- `),process.exit(0));const n=/-v (\S+)/.exec(t)?.[1],r=/-\w*d/.test(t);e({flow:[/-\w*b/.test(t)&&`bump`,/-\w*f/.test(t)&&`context`,/-\w*c/.test(t)&&`commit`,/-\w*t/.test(t)&&`tag`].filter(Boolean),...n&&{newVersion:n},...r&&{dryRun:r}});export{};
15
+ - \`pnpm relion\` — run all release steps
16
+ `),process.exit(0));let n=[/-\w*f/.test(t)&&`context`,/-\w*b/.test(t)&&`bump`,/-\w*c/.test(t)&&`commit`,/-\w*t/.test(t)&&`tag`].filter(Boolean);n.length||(n=[`context`,`bump`,`commit`,`tag`]);const r=/-v (\S+)/.exec(t)?.[1],i=/-\w*d/.test(t);e({flow:n,...r&&{newVersion:r},...i&&{dryRun:i}});export{};
package/dist/index.d.ts CHANGED
@@ -64,9 +64,9 @@ interface Bumper {
64
64
  }
65
65
  //#endregion
66
66
  //#region src/relion.d.ts
67
- declare function relion(userCfg?: Config): void;
67
+ declare const _default: (userCfg?: Config) => Promise<void>;
68
68
  //#endregion
69
69
  //#region src/index.d.ts
70
70
  declare const defineConfig: (config: Config) => Config;
71
71
  //#endregion
72
- export { relion as default, defineConfig };
72
+ export { _default as default, defineConfig };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- import{existsSync as e,readFileSync as t,writeFileSync as n}from"node:fs";import{execSync as r,spawnSync as i}from"node:child_process";import a from"semver";const o=e=>r(`git log ${e?`${e}..`:``} --format="%h %B---" .`,{encoding:`utf8`}).trim().split(`---`).filter(Boolean).map(e=>/^(.+?) (.+)/s.exec(e.trim())).map(e=>({hash:e?.[1]??``,message:e?.[2].trim()??``})),s=(e,t=[])=>e.filter(e=>t.some(t=>t instanceof RegExp?t.test(e.message):l(t).test(e.message))),c=(e,t)=>{let n=e.some(e=>e.message.includes(`BREAKING CHANGE`))?t.startsWith(`0.`)?`minor`:`major`:e.some(e=>/feat(\(.*?\))?:/.test(e.message))?`minor`:`patch`;return a.inc(t,n)??(()=>{throw Error(`Failed to increment version '${t}' with release type '${n}'`)})()},l=e=>{let t=/^\/(.+)\/(\w*)$/.exec(e);return t?new RegExp(t[1],t[2]):new RegExp(e)},u={file:`package.json`,pattern:/("version": )".*"/,replacement:`$1"{{newVersion}}"`},d={flow:[],newVersion:``,bumpFiles:[`package.json`],contextFile:`RELEASE.md`,commitMessage:`chore(release): {{tag}}`,tagPrefix:`v`,commitFilters:[/^feat|^fix|^perf|^style|^docs/,`BREAKING CHANGE`],dryRun:!1},f=e=>{e.bumpFiles.forEach(r=>{let i=typeof r==`string`?u:r;typeof i.pattern==`string`&&(i.pattern=l(i.pattern)),[i.file].flat().forEach(r=>{let a=t(r,`utf8`).replace(i.pattern,i.replacement.replace(`{{newVersion}}`,e.newVersion));console.log(`Updating version in '${r}'`),!e.dryRun&&n(r,a,`utf8`)})})},p=(e,t,r,i,a)=>{if(console.log(`Outputting release context to '${e.contextFile}'`),e.dryRun)return;let o=``,s=`---\nversion: ${e.newVersion}\ntag: ${i}\ndate: ${new Date().toLocaleString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`})}\nprevTag: ${r}\nrepoURL: ${a}
1
+ import{readFileSync as e,writeFileSync as t}from"node:fs";import{execSync as n,spawnSync as r}from"node:child_process";import{createInterface as i}from"node:readline";import a from"semver";const o=e=>n(`git log ${e?`${e}..`:``} --format="%h %B---" .`,{encoding:`utf8`}).trim().split(`---`).filter(Boolean).map(e=>/^(.+?) (.+)/s.exec(e.trim())).map(e=>({hash:e?.[1]??``,message:e?.[2].trim()??``})),s=(e,t=[])=>e.filter(e=>t.some(t=>t instanceof RegExp?t.test(e.message):u(t).test(e.message))),c=(e,t)=>{let n=e.some(e=>e.message.includes(`BREAKING CHANGE`))?t.startsWith(`0.`)?`minor`:`major`:e.some(e=>/feat(\(.*?\))?:/.test(e.message))?`minor`:`patch`;return a.inc(t,n)??(()=>{throw Error(`Failed to increment version '${t}' with release type '${n}'`)})()},l=async()=>{let e=i({input:process.stdin,output:process.stdout});return await new Promise(t=>{e.question(`Press Enter to continue ('s' to skip): `,n=>{e.close(),t(n.trim()!==`s`)})})},u=e=>{let t=/^\/(.+)\/(\w*)$/.exec(e);return t?new RegExp(t[1],t[2]):new RegExp(e)},d=[`context`,`bump`,`commit`,`tag`],f={file:`package.json`,pattern:/("version": )".*"/,replacement:`$1"{{newVersion}}"`},p={flow:[],newVersion:``,bumpFiles:[`package.json`],contextFile:`RELEASE.md`,commitMessage:`chore(release): {{tag}}`,tagPrefix:`v`,commitFilters:[/^feat|^fix|^perf|^style|^docs/,`BREAKING CHANGE`],dryRun:!1},m=async(e,n,r,i,a)=>{if(console.log(`\nAbout to write context to '${e.contextFile}'`),!await l()||e.dryRun)return;let o=``,s=`---\nversion: ${e.newVersion}\ntag: ${i}\ndate: ${new Date().toLocaleString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`})}\nprevTag: ${r}\nrepoURL: ${a}
2
2
  ---
3
3
  `;o+=s+`
4
- `;let c=t.map(e=>`[${e.hash}] ${e.message}`).join(`\n${`-`.repeat(30)}\n`);o+=`## Commit Log\n\n\`\`\`\n${c}\n\`\`\``,n(e.contextFile,o,`utf8`)},m=t=>{let n=`git add -A`+(e(t.contextFile)?` && git reset ${t.contextFile}`:``)+` && git commit -m "${t.commitMessage}"`;console.log(`Committing changes: '${n}'`),!t.dryRun&&r(n,{stdio:`inherit`})},h=(e,t)=>{let n=`git tag ${t} -m "${e.commitMessage}"`;console.log(`Creating a tag: '${n}'`),!e.dryRun&&r(n,{stdio:`inherit`})};function g(e){let n=JSON.parse(t(`package.json`,`utf8`)),r={...d,...n.relion,...e};console.log(`-`.repeat(30));let a=n.version;console.log(`Current version: ${a}`);let l=i(`git`,[`describe`,`--match`,`${r.tagPrefix}[0-9]*.[0-9]*.[0-9]*`,`--abbrev=0`],{encoding:`utf8`}).stdout.trim();console.log(`Current tag: ${l}`);let u=s(o(l),r.commitFilters);console.log(`Filtered commits: ${u.length}`),r.newVersion||=c(u,a),console.log(`New version: ${r.newVersion}`);let g=`${r.tagPrefix}${r.newVersion}`;console.log(`New tag: ${g}`),r.commitMessage=r.commitMessage.replace(`{{tag}}`,g),console.log(`Commit message: '${r.commitMessage}'`);let _=n.repository;console.log(`Repo URL: ${_}`),console.log(`-`.repeat(30));for(let e of r.flow)({bump:()=>f(r),context:()=>p(r,u,l,g,_),commit:()=>m(r),tag:()=>h(r,g)})[e]()}const _=e=>e;export{g as default,_ as defineConfig};
4
+ `;let c=n.map(e=>`[${e.hash}] ${e.message}`).join(`\n${`-`.repeat(30)}\n`);o+=`## Commit Log\n\n\`\`\`\n${c}\n\`\`\``,t(e.contextFile,o,`utf8`)},h=async n=>{let r=n.bumpFiles.map(e=>typeof e==`string`?{...f,file:e}:e);console.log(`\nAbout to bump versions in files: ${r.map(e=>[e.file].flat()).flat().join(`, `)}`),await l()&&r.forEach(r=>{typeof r.pattern==`string`&&(r.pattern=u(r.pattern)),[r.file].flat().forEach(i=>{let a=e(i,`utf8`).replace(r.pattern,r.replacement.replace(`{{newVersion}}`,n.newVersion));n.dryRun||t(i,a,`utf8`)})})},g=async e=>{let t=`git commit -m "${e.commitMessage}"`;console.log(`\nAbout to commit changes: '${t}'`),await l()&&(e.dryRun||n(t,{stdio:`inherit`}))},_=async(e,t,r)=>{let i=`git tag ${r} -m "${e.commitMessage}"`,a=RegExp(`^${e.commitMessage.replace(r,t).replace(/[()]/g,`\\$&`)}$`),o=n(`git log -1 --format=%s`,{encoding:`utf8`}).trim(),s=``;a.test(o)&&(s+=`
5
+ Latest commit is a release commit. Reusing the latest tag.`,i=`git tag ${t} -m "${o}" -f`),s+=`\nAbout to create a tag: '${i}'`,console.log(s),await l()&&(e.dryRun||n(i,{stdio:`inherit`}))};var v=async t=>{let n=JSON.parse(e(`package.json`,`utf8`)),i={...p,...n.relion,...t};console.log(`-`.repeat(30));let a=n.version;console.log(`Current version: ${a}`);let l=r(`git`,[`describe`,`--match`,`${i.tagPrefix}[0-9]*.[0-9]*.[0-9]*`,`--abbrev=0`],{encoding:`utf8`}).stdout.trim();console.log(`Current tag: ${l}`);let u=s(o(l),i.commitFilters);console.log(`Filtered commits: ${u.length}`),i.newVersion||=c(u,a),console.log(`New version: ${i.newVersion}`);let f=`${i.tagPrefix}${i.newVersion}`;console.log(`New tag: ${f}`),i.commitMessage=i.commitMessage.replace(`{{tag}}`,f),console.log(`Commit message: '${i.commitMessage}'`);let v=n.repository;console.log(`Repo URL: ${v}`),console.log(`-`.repeat(30));for(let e of d.filter(e=>i.flow.includes(e)))await{context:()=>m(i,u,l,f,v),bump:()=>h(i),commit:()=>g(i),tag:()=>_(i,l,f)}[e]()};const y=e=>e;export{v as default,y as defineConfig};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relion",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "description": "🔖 Modern Release Workflow Helper",
5
5
  "author": "kh4f <kh4f.dev@gmail.com>",
6
6
  "license": "MIT",
@@ -28,23 +28,20 @@
28
28
  "devDependencies": {
29
29
  "@eslint/js": "^9.39.2",
30
30
  "@stylistic/eslint-plugin": "^5.7.0",
31
- "@types/node": "^25.0.6",
31
+ "@types/node": "^25.0.9",
32
32
  "@types/semver": "^7.7.1",
33
33
  "eslint": "^9.39.2",
34
- "globals": "^17.0.0",
35
34
  "jiti": "^2.6.1",
36
35
  "tsdown": "^0.19.0",
37
36
  "tsx": "^4.21.0",
38
37
  "typescript": "^5.9.3",
39
- "typescript-eslint": "^8.52.0"
38
+ "typescript-eslint": "^8.53.1"
40
39
  },
41
40
  "scripts": {
42
41
  "build": "tsdown",
43
42
  "build:watch": "tsdown --watch",
44
43
  "build:prod": "tsdown --prod",
45
44
  "lint": "eslint",
46
- "release:context": "pnpm relion -f",
47
- "release": "pnpm relion -bct",
48
- "relion": "tsx src/cli"
45
+ "release": "tsx src/cli"
49
46
  }
50
47
  }