Skip to content

Commit dafb6fa

Browse files
committed
feat(projects): packages/scripts: add command changelog,release
1 parent 840e7f9 commit dafb6fa

File tree

10 files changed

+291
-71
lines changed

10 files changed

+291
-71
lines changed

packages/scripts/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@
1313
}
1414
},
1515
"devDependencies": {
16+
"@soybeanjs/changelog": "0.3.12",
17+
"@types/prompts": "2.4.9",
18+
"bumpp": "9.3.0",
1619
"c12": "1.6.1",
1720
"cac": "6.7.14",
1821
"consola": "3.2.3",
19-
"enquirer": "2.4.1",
2022
"execa": "8.0.1",
23+
"kolorist": "1.8.0",
2124
"npm-check-updates": "16.14.12",
25+
"prompts": "2.4.2",
2226
"rimraf": "5.0.5"
2327
}
2428
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { generateChangelog, generateTotalChangelog } from '@soybeanjs/changelog';
2+
import type { ChangelogOption } from '@soybeanjs/changelog';
3+
4+
export async function genChangelog(options?: Partial<ChangelogOption>, total = false) {
5+
if (total) {
6+
await generateTotalChangelog(options);
7+
} else {
8+
await generateChangelog(options);
9+
}
10+
}

packages/scripts/src/commands/git-commit.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
import path from 'node:path';
22
import { readFileSync } from 'node:fs';
3-
import enquirer from 'enquirer';
4-
import { bgRed, green, red } from 'kolorist';
3+
import prompts from 'prompts';
4+
import { bgRed, green, red, yellow } from 'kolorist';
55
import { execCommand } from '../shared';
66
import type { CliOption } from '../types';
77

8-
interface PromptObject {
9-
types: string;
10-
scopes: string;
11-
description: string;
12-
}
13-
8+
/**
9+
* Git commit with Conventional Commits standard
10+
*
11+
* @param gitCommitTypes
12+
* @param gitCommitScopes
13+
*/
1414
export async function gitCommit(
1515
gitCommitTypes: CliOption['gitCommitTypes'],
1616
gitCommitScopes: CliOption['gitCommitScopes']
1717
) {
18-
const typesChoices = gitCommitTypes.map(([name, title]) => {
19-
const nameWithSuffix = `${name}:`;
18+
const typesChoices = gitCommitTypes.map(([value, msg]) => {
19+
const nameWithSuffix = `${value}:`;
2020

21-
const message = `${nameWithSuffix.padEnd(12)}${title}`;
21+
const title = `${nameWithSuffix.padEnd(12)}${msg}`;
2222

2323
return {
24-
name,
25-
message
24+
value,
25+
title
2626
};
2727
});
2828

29-
const scopesChoices = gitCommitScopes.map(([name, title]) => ({
30-
name,
31-
message: `${name.padEnd(30)} (${title})`
29+
const scopesChoices = gitCommitScopes.map(([value, msg]) => ({
30+
value,
31+
title: `${value.padEnd(30)} (${msg})`
3232
}));
3333

34-
const result = await enquirer.prompt<PromptObject>([
34+
const result = await prompts([
3535
{
3636
name: 'types',
3737
type: 'select',
@@ -47,23 +47,28 @@ export async function gitCommit(
4747
{
4848
name: 'description',
4949
type: 'text',
50-
message: 'Please enter a description'
50+
message: `Please enter a description (add prefix ${yellow('!')} to indicate breaking change)`
5151
}
5252
]);
5353

54-
const commitMsg = `${result.types}(${result.scopes}): ${result.description}`;
54+
const breaking = result.description.startsWith('!') ? '!' : '';
55+
56+
const description = result.description.replace(/^!/, '').trim();
57+
58+
const commitMsg = `${result.types}(${result.scopes})${breaking}: ${description}`;
5559

5660
await execCommand('git', ['commit', '-m', commitMsg], { stdio: 'inherit' });
5761
}
5862

63+
/** Git commit message verify */
5964
export async function gitCommitVerify() {
6065
const gitPath = await execCommand('git', ['rev-parse', '--show-toplevel']);
6166

6267
const gitMsgPath = path.join(gitPath, '.git', 'COMMIT_EDITMSG');
6368

6469
const commitMsg = readFileSync(gitMsgPath, 'utf8').trim();
6570

66-
const REG_EXP = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
71+
const REG_EXP = /(?<type>[a-z]+)(?:\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
6772

6873
if (!REG_EXP.test(commitMsg)) {
6974
throw new Error(
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export * from './git-commit';
22
export * from './cleanup';
33
export * from './update-pkg';
4+
export * from './changelog';
5+
export * from './release';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { versionBump } from 'bumpp';
2+
3+
export async function release(execute = 'pnpm sa changelog', push = true) {
4+
await versionBump({
5+
files: ['**/package.json', '!**/node_modules'],
6+
execute,
7+
all: true,
8+
tag: true,
9+
commit: 'chore(projects): release v%s',
10+
push
11+
});
12+
}

packages/scripts/src/config/index.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import process from 'node:process';
22
import { loadConfig } from 'c12';
33
import type { CliOption } from '../types';
44

5-
const eslintExt = '*.{js,jsx,mjs,cjs,ts,tsx,vue}';
6-
75
const defaultOptions: CliOption = {
86
cwd: process.cwd(),
97
cleanupDirs: [
@@ -39,27 +37,7 @@ const defaultOptions: CliOption = {
3937
['other', 'other changes']
4038
],
4139
ncuCommandArgs: ['--deep', '-u'],
42-
prettierWriteGlob: [
43-
`!**/${eslintExt}`,
44-
'!*.min.*',
45-
'!CHANGELOG.md',
46-
'!dist',
47-
'!LICENSE*',
48-
'!output',
49-
'!coverage',
50-
'!public',
51-
'!temp',
52-
'!package-lock.json',
53-
'!pnpm-lock.yaml',
54-
'!yarn.lock',
55-
'!.github',
56-
'!__snapshots__',
57-
'!node_modules'
58-
],
59-
lintStagedConfig: {
60-
[eslintExt]: 'eslint --fix',
61-
'*': 'sa prettier-write'
62-
}
40+
changelogOptions: {}
6341
};
6442

6543
export async function loadCliOptions(overrides?: Partial<CliOption>, cwd = process.cwd()) {

packages/scripts/src/index.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,50 @@
11
import cac from 'cac';
22
import { blue, lightGreen } from 'kolorist';
33
import { version } from '../package.json';
4-
import { cleanup, gitCommit, gitCommitVerify, updatePkg } from './commands';
4+
import { cleanup, genChangelog, gitCommit, gitCommitVerify, release, updatePkg } from './commands';
55
import { loadCliOptions } from './config';
66

7-
type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify';
7+
type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify' | 'changelog' | 'release';
88

99
type CommandAction<A extends object> = (args?: A) => Promise<void> | void;
1010

1111
type CommandWithAction<A extends object = object> = Record<Command, { desc: string; action: CommandAction<A> }>;
1212

1313
interface CommandArg {
14+
/** Execute additional command after bumping and before git commit. Defaults to 'npx soy changelog' */
15+
execute?: string;
16+
/** Indicates whether to push the git commit and tag. Defaults to true */
17+
push?: boolean;
18+
/** Generate changelog by total tags */
1419
total?: boolean;
20+
/**
21+
* The glob pattern of dirs to cleanup
22+
*
23+
* If not set, it will use the default value
24+
*
25+
* Multiple values use "," to separate them
26+
*/
27+
cleanupDir?: string;
1528
}
1629

1730
export async function setupCli() {
1831
const cliOptions = await loadCliOptions();
1932

20-
const cli = cac(blue('soybean'));
33+
const cli = cac(blue('soybean-admin'));
2134

22-
cli.version(lightGreen(version)).help();
35+
cli
36+
.version(lightGreen(version))
37+
.option(
38+
'-e, --execute [command]',
39+
"Execute additional command after bumping and before git commit. Defaults to 'npx soy changelog'"
40+
)
41+
.option('-p, --push', 'Indicates whether to push the git commit and tag')
42+
.option('-t, --total', 'Generate changelog by total tags')
43+
.option(
44+
'-c, --cleanupDir <dir>',
45+
'The glob pattern of dirs to cleanup, If not set, it will use the default value, Multiple values use "," to separate them'
46+
)
47+
.help();
2348

2449
const commands: CommandWithAction<CommandArg> = {
2550
cleanup: {
@@ -45,6 +70,18 @@ export async function setupCli() {
4570
action: async () => {
4671
await gitCommitVerify();
4772
}
73+
},
74+
changelog: {
75+
desc: 'generate changelog',
76+
action: async args => {
77+
await genChangelog(cliOptions.changelogOptions, args?.total);
78+
}
79+
},
80+
release: {
81+
desc: 'release: update version, generate changelog, commit code',
82+
action: async args => {
83+
await release(args?.execute, args?.push);
84+
}
4885
}
4986
};
5087

packages/scripts/src/types/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { ChangelogOption } from '@soybeanjs/changelog';
2+
13
export interface CliOption {
24
/** The project root directory */
35
cwd: string;
@@ -23,11 +25,9 @@ export interface CliOption {
2325
*/
2426
ncuCommandArgs: string[];
2527
/**
26-
* Prettier write glob
28+
* Options of generate changelog
2729
*
28-
* Glob pattern syntax {@link https://github.com/micromatch/micromatch}
30+
* @link https://github.com/soybeanjs/changelog
2931
*/
30-
prettierWriteGlob: string[];
31-
/** Lint-staged config */
32-
lintStagedConfig: Record<string, string | string[]>;
32+
changelogOptions: Partial<ChangelogOption>;
3333
}

packages/scripts/typings/pkg.d.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)