relion 0.39.2 → 0.41.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 +31 -26
- package/dist/cli.js +4 -1
- package/dist/index.d.ts +9 -10
- package/dist/index.js +3 -3
- package/package.json +35 -45
package/README.md
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
<a href="https://
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset=".github/logo-light.png">
|
|
4
|
+
<img alt="logo" src=".github/logo-dark.png">
|
|
5
|
+
</picture>
|
|
6
|
+
<br>
|
|
7
|
+
<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=B2BFFF&labelColor=303145" alt="npm version"/></a>
|
|
8
|
+
<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=B2BFFF&labelColor=303145" alt="runtime size"/></a>
|
|
9
|
+
<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=B2BFFF&labelColor=303145" alt="license"></a>
|
|
10
|
+
<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%9B%20Bugs&style=flat-square&color=B2BFFF&labelColor=303145" alt="open bugs"></a>
|
|
8
11
|
<br><br>
|
|
9
|
-
<b>A minimal npm library for automating release workflow
|
|
12
|
+
<b>A minimal npm library for automating release workflow:<br></b> version bumping, release commit & tag creation, and AI‑assisted changelog generation
|
|
10
13
|
<br><br>
|
|
11
|
-
<p>
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
</b>
|
|
19
|
-
</p>
|
|
14
|
+
<p><b>
|
|
15
|
+
<a href="#-installation">Installation</a> •
|
|
16
|
+
<a href="#%EF%B8%8F-cli-usage">CLI</a> •
|
|
17
|
+
<a href="#-api-usage">API</a> •
|
|
18
|
+
<a href="#%EF%B8%8F-workflow-steps">Workflow Steps</a> •
|
|
19
|
+
<a href="#-changelog-generation">Changelog Generation</a>
|
|
20
|
+
</b></p>
|
|
20
21
|
<br>
|
|
21
22
|
</div>
|
|
22
23
|
|
|
@@ -39,12 +40,14 @@ Options:
|
|
|
39
40
|
-c Create a release commit
|
|
40
41
|
-t Create a release tag
|
|
41
42
|
-v <version> Set the new version explicitly
|
|
43
|
+
-m <file> Specify manifest file
|
|
42
44
|
-d Run in dry run mode
|
|
43
45
|
-h Show the help message
|
|
44
46
|
|
|
45
47
|
Examples:
|
|
46
48
|
- `pnpm relion -bct` — bump version, create release commit and tag
|
|
47
49
|
- `pnpm relion -f` — generate release context file
|
|
50
|
+
- `pnpm relion -m Cargo.toml` — use Cargo.toml as manifest
|
|
48
51
|
- `pnpm relion` — run all release steps
|
|
49
52
|
```
|
|
50
53
|
|
|
@@ -54,7 +57,7 @@ Examples:
|
|
|
54
57
|
------------------------------
|
|
55
58
|
Current version: 0.36.1
|
|
56
59
|
Current tag: v0.36.1
|
|
57
|
-
|
|
60
|
+
Parsed commits: 16
|
|
58
61
|
New version: 0.37.0
|
|
59
62
|
New tag: v0.37.0
|
|
60
63
|
Commit message: 'chore(release): v0.37.0'
|
|
@@ -83,7 +86,7 @@ import relion from 'relion';
|
|
|
83
86
|
relion({
|
|
84
87
|
flow: ['context', 'bump', 'commit', 'tag'],
|
|
85
88
|
newVersion: '1.2.3',
|
|
86
|
-
|
|
89
|
+
bump: [
|
|
87
90
|
'package.json', // uses default bumper
|
|
88
91
|
// custom bumper (equivalent to the default bumper implementation)
|
|
89
92
|
{
|
|
@@ -95,22 +98,23 @@ relion({
|
|
|
95
98
|
contextFile: 'RELEASE.md',
|
|
96
99
|
commitMessage: 'chore(release): {{tag}}',
|
|
97
100
|
tagPrefix: 'v',
|
|
98
|
-
commitFilters: [/^feat|^fix/, 'BREAKING CHANGE'],
|
|
99
101
|
dryRun: false,
|
|
100
102
|
});
|
|
101
103
|
```
|
|
102
104
|
|
|
103
105
|
### Options
|
|
104
106
|
|
|
105
|
-
- `
|
|
107
|
+
- `manifest`: manifest file (default: auto-detects `package.json` or `Cargo.toml`)
|
|
108
|
+
- `flow`: release workflow steps (`'context' | 'bump' | 'commit' | 'tag'`) (default: all steps)
|
|
106
109
|
- `newVersion`: set the new version explicitly
|
|
107
|
-
- `
|
|
110
|
+
- `bump`: files or custom bumpers for version update (default: [`'package.json', 'Cargo.toml'`])
|
|
108
111
|
- `contextFile`: path to release context output file (default: `'RELEASE.md'`)
|
|
109
112
|
- `commitMessage`: release commit message template (default: `'chore(release): {{tag}}'`)
|
|
110
113
|
- `tagPrefix`: release tag prefix (default: `'v'`)
|
|
111
|
-
- `commitFilters`: commit log filters (substring or RegExp; default: [`/^feat|^fix|^perf|^style|^docs/`, `'BREAKING CHANGE'`])
|
|
112
114
|
- `dryRun`: run in dry mode (no modifications)
|
|
113
115
|
|
|
116
|
+
> For detailed option descriptions, see [src/types.d.ts](src/types.d.ts).
|
|
117
|
+
|
|
114
118
|
### Configuration via `package.json`
|
|
115
119
|
|
|
116
120
|
Relion can also be configured via `relion` field in `package.json`:
|
|
@@ -121,7 +125,7 @@ Relion can also be configured via `relion` field in `package.json`:
|
|
|
121
125
|
"relion": {
|
|
122
126
|
"commitMessage": "release(relion): {{tag}}",
|
|
123
127
|
"tagPrefix": "",
|
|
124
|
-
"
|
|
128
|
+
"bump": ["package.json",
|
|
125
129
|
{
|
|
126
130
|
"file": "manifest.json",
|
|
127
131
|
"pattern": "/(\"version\": )\".*\"/",
|
|
@@ -178,8 +182,9 @@ Recommended workflow:
|
|
|
178
182
|
- [.github/instructions/changelog-format.instructions.md](.github/instructions/changelog-format.instructions.md)
|
|
179
183
|
- [.github/prompts/generate-changelog.prompt.md](.github/prompts/generate-changelog.prompt.md)
|
|
180
184
|
2. Run the context step to generate RELEASE.md: `pnpm relion -f`
|
|
181
|
-
3.
|
|
182
|
-
4.
|
|
185
|
+
3. Review the release context, adjust as needed
|
|
186
|
+
4. Run the prompt in VSCode Copilot chat: `/generate-changelog`
|
|
187
|
+
5. Copilot produces a polished changelog entry based on the release context
|
|
183
188
|
|
|
184
189
|
<details><summary>Generated changelog example (from the (*) release context using the instruction and prompt above; Gemini 3 Pro)</summary>
|
|
185
190
|
|
|
@@ -192,7 +197,7 @@ Recommended workflow:
|
|
|
192
197
|
###   🩹 Fixes
|
|
193
198
|
- **Correct release type calculation**: breaking changes now correctly take priority over features when determining the release type, preventing incorrect minor bumps. [🡥](https://github.com/kh4f/relion/commit/8f29acf)
|
|
194
199
|
|
|
195
|
-
#####    [
|
|
200
|
+
#####    [Full Changelog](https://github.com/kh4f/relion/compare/v0.32.1...v0.33.0)  •  Jan 10, 2026
|
|
196
201
|
```
|
|
197
202
|
</details>
|
|
198
203
|
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import e from"./index.js";const t=process.argv.slice(2).join(` `);t.includes(`-h`)&&(console.log(`Usage: relion [options]
|
|
2
3
|
|
|
3
4
|
Options:
|
|
@@ -6,11 +7,13 @@ Options:
|
|
|
6
7
|
-c Create a release commit
|
|
7
8
|
-t Create a release tag
|
|
8
9
|
-v <version> Set the new version explicitly
|
|
10
|
+
-m <file> Specify manifest file
|
|
9
11
|
-d Run in dry run mode
|
|
10
12
|
-h Show the help message
|
|
11
13
|
|
|
12
14
|
Examples:
|
|
13
15
|
- \`pnpm relion -bct\` — bump version, create release commit and tag
|
|
14
16
|
- \`pnpm relion -f\` — generate release context file
|
|
17
|
+
- \`pnpm relion -m Cargo.toml\` — use Cargo.toml as manifest
|
|
15
18
|
- \`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&&{
|
|
19
|
+
`),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=/-m (\S+)/.exec(t)?.[1],a=/-\w*d/.test(t);e({flow:n,...r&&{newVersion:r},...i&&{manifest:i},...a&&{dryRun:a}});export{};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
2
|
interface Config {
|
|
3
|
+
/** Manifest file path. Auto-detects `package.json` or `Cargo.toml` if omitted. */
|
|
4
|
+
manifest?: string;
|
|
3
5
|
/**
|
|
4
6
|
* Release workflow steps to execute (e.g. bump, context, commit, tag)
|
|
5
7
|
* @default []
|
|
@@ -13,11 +15,13 @@ interface Config {
|
|
|
13
15
|
/**
|
|
14
16
|
* Files or bumpers for version update. Each item is either:
|
|
15
17
|
* - a Bumper object specifying `file`, `pattern`, and `replacement`
|
|
16
|
-
* - a file name for which a default bumper exists (currently only 'package.json')
|
|
18
|
+
* - a file name for which a default bumper exists (currently only 'package.json', 'Cargo.toml')
|
|
17
19
|
*
|
|
18
|
-
*
|
|
20
|
+
* If a file doesn't exist, it will be skipped silently.
|
|
21
|
+
*
|
|
22
|
+
* @default ['package.json', 'Cargo.toml']
|
|
19
23
|
*/
|
|
20
|
-
|
|
24
|
+
bump?: (Bumper | string)[];
|
|
21
25
|
/**
|
|
22
26
|
* Path to the release context output file
|
|
23
27
|
* @default 'RELEASE.md'
|
|
@@ -33,11 +37,6 @@ interface Config {
|
|
|
33
37
|
* @default 'v'
|
|
34
38
|
*/
|
|
35
39
|
tagPrefix?: string;
|
|
36
|
-
/**
|
|
37
|
-
* Commit log filters (substrings or regexes)
|
|
38
|
-
* @default [/^feat|^fix|^perf|^style|^docs/, 'BREAKING CHANGE']
|
|
39
|
-
*/
|
|
40
|
-
commitFilters?: (string | RegExp)[];
|
|
41
40
|
/**
|
|
42
41
|
* Run in dry mode without making any changes
|
|
43
42
|
* @default false
|
|
@@ -55,9 +54,9 @@ interface Bumper {
|
|
|
55
54
|
}
|
|
56
55
|
//#endregion
|
|
57
56
|
//#region src/relion.d.ts
|
|
58
|
-
declare
|
|
57
|
+
declare function relion(userCfg?: Config): Promise<void>;
|
|
59
58
|
//#endregion
|
|
60
59
|
//#region src/index.d.ts
|
|
61
60
|
declare const defineConfig: (config: Config) => Config;
|
|
62
61
|
//#endregion
|
|
63
|
-
export {
|
|
62
|
+
export { relion as default, defineConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
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{createInterface as a}from"node:readline";import o from"semver";const s=e=>{let n=t(e,`utf8`),r=/name.*"(.*?)"/.exec(n)?.[1];if(!r)throw Error(`Manifest is missing 'name' field`);let i=/version.*"(.*?)"/.exec(n)?.[1];if(!i)throw Error(`Manifest is missing 'version' field`);let a=/repository.*"(.*?)"/.exec(n)?.[1];if(!a)throw Error(`Manifest is missing 'repository' field`);let o=e.endsWith(`.json`)?/relion.*({.*?})/s.exec(n)?.[1]:void 0;return{name:r,version:i,repository:a,relion:o?JSON.parse(o):void 0}},c=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()??``})),l=(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 o.inc(t,n)??(()=>{throw Error(`Failed to increment version '${t}' with release type '${n}'`)})()},u=async()=>{let e=a({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`)})})},d=e=>{let t=/^\/(.+)\/(\w*)$/.exec(e);return t?new RegExp(t[1],t[2]):new RegExp(e)},f=[`context`,`bump`,`commit`,`tag`],p={file:[`package.json`,`Cargo.toml`],pattern:/(\bversion\b.*?)\d[\w.+-]*/,replacement:`$1{{newVersion}}`},m=[`package.json`,`Cargo.toml`],h={flow:f,newVersion:``,bump:m,contextFile:`RELEASE.md`,commitMessage:`chore(release): {{tag}}`,tagPrefix:`v`,dryRun:!1},g=async(e,t,r,i,a)=>{if(console.log(`\nAbout to write context to '${e.contextFile}'`),!await u()||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=
|
|
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
|
|
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`)},_=async r=>{let i=r.bump.map(e=>typeof e==`string`?{...p,file:e}:e).filter(t=>[t.file].flat().every(t=>e(t)));console.log(`\nAbout to bump versions in files: ${i.map(e=>[e.file].flat()).flat().join(`, `)}`),await u()&&i.forEach(e=>{typeof e.pattern==`string`&&(e.pattern=d(e.pattern)),[e.file].flat().forEach(i=>{let a=t(i,`utf8`).replace(e.pattern,e.replacement.replace(`{{newVersion}}`,r.newVersion));r.dryRun||n(i,a,`utf8`)})})},v=async e=>{let t=`git commit -m "${e.commitMessage}"`;console.log(`\nAbout to commit changes: '${t}'`),await u()&&(e.dryRun||r(t,{stdio:`inherit`}))},y=async(e,t,n)=>{let i=`git tag ${n} -m "${e.commitMessage}"`,a=RegExp(`^${e.commitMessage.replace(n,t).replace(/[()]/g,`\\$&`)}$`),o=r(`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 u()&&(e.dryRun||r(i,{stdio:`inherit`}))};async function b(t){if(t?.manifest&&!e(t.manifest))throw Error(`Specified manifest file '${t.manifest}' does not exist`);let n=t?.manifest??m.find(e);if(!n)throw Error(`No manifest file found, please specify one`);console.log(`-`.repeat(30)),console.log(`Manifest file: ${n}`);let r=s(n);t={...r.relion,...t};let a={...h,...t};!t.tagPrefix&&r.name.startsWith(`@`)&&(a.tagPrefix=`${r.name}@`);let o=r.version;console.log(`Current version: ${o}`);let u=i(`git`,[`describe`,`--match`,`${a.tagPrefix}[0-9]*.[0-9]*.[0-9]*`,`--abbrev=0`],{encoding:`utf8`}).stdout.trim();console.log(`Current tag: ${u}`);let d=c(u);console.log(`Parsed commits: ${d.length}`),a.newVersion||=l(d,o),console.log(`New version: ${a.newVersion}`);let p=`${a.tagPrefix}${a.newVersion}`;console.log(`New tag: ${p}`),a.commitMessage=a.commitMessage.replace(`{{tag}}`,p),console.log(`Commit message: '${a.commitMessage}'`);let b=r.repository;console.log(`Repo URL: ${b}`),console.log(`-`.repeat(30));for(let e of f.filter(e=>a.flow.includes(e)))await{context:()=>g(a,d,u,p,b),bump:()=>_(a),commit:()=>v(a),tag:()=>y(a,u,p)}[e]()}const x=e=>e;export{b as default,x as defineConfig};
|
package/package.json
CHANGED
|
@@ -1,47 +1,37 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"typescript": "^5.9.3",
|
|
38
|
-
"typescript-eslint": "^8.56.0"
|
|
39
|
-
},
|
|
40
|
-
"scripts": {
|
|
41
|
-
"build": "tsdown",
|
|
42
|
-
"build:watch": "tsdown --watch",
|
|
43
|
-
"build:prod": "tsdown --prod",
|
|
44
|
-
"lint": "eslint",
|
|
45
|
-
"release": "tsx src/cli"
|
|
46
|
-
}
|
|
2
|
+
"name": "relion",
|
|
3
|
+
"version": "0.41.0",
|
|
4
|
+
"description": "🏷️ Modern Release Workflow Helper",
|
|
5
|
+
"author": "kh4f <kh4f.dev@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": "https://github.com/kh4f/relion",
|
|
8
|
+
"bugs": "https://github.com/kh4f/relion/issues",
|
|
9
|
+
"homepage": "https://github.com/kh4f/relion#readme",
|
|
10
|
+
"keywords": ["relion", "release", "release-automation", "release-workflow", "release-helper", "release-workflow-helper"],
|
|
11
|
+
"files": ["dist"],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"bin": "dist/cli.js",
|
|
15
|
+
"types": "dist/index.d.ts",
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsdown",
|
|
18
|
+
"build:watch": "tsdown --watch",
|
|
19
|
+
"build:prod": "tsdown --prod",
|
|
20
|
+
"lint": "eslint",
|
|
21
|
+
"release": "bun src/cli"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"semver": "^7.7.4"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@eslint/js": "^10.0.1",
|
|
28
|
+
"@stylistic/eslint-plugin": "^5.9.0",
|
|
29
|
+
"@types/node": "^25.3.3",
|
|
30
|
+
"@types/semver": "^7.7.1",
|
|
31
|
+
"eslint": "^10.0.2",
|
|
32
|
+
"jiti": "^2.6.1",
|
|
33
|
+
"tsdown": "^0.20.3",
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"typescript-eslint": "^8.56.1"
|
|
36
|
+
}
|
|
47
37
|
}
|