mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-23 23:39:47 +08:00
feat(projects): packages/scripts: add command changelog,release
This commit is contained in:
@ -13,12 +13,16 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@soybeanjs/changelog": "0.3.12",
|
||||
"@types/prompts": "2.4.9",
|
||||
"bumpp": "9.3.0",
|
||||
"c12": "1.6.1",
|
||||
"cac": "6.7.14",
|
||||
"consola": "3.2.3",
|
||||
"enquirer": "2.4.1",
|
||||
"execa": "8.0.1",
|
||||
"kolorist": "1.8.0",
|
||||
"npm-check-updates": "16.14.12",
|
||||
"prompts": "2.4.2",
|
||||
"rimraf": "5.0.5"
|
||||
}
|
||||
}
|
||||
|
10
packages/scripts/src/commands/changelog.ts
Normal file
10
packages/scripts/src/commands/changelog.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { generateChangelog, generateTotalChangelog } from '@soybeanjs/changelog';
|
||||
import type { ChangelogOption } from '@soybeanjs/changelog';
|
||||
|
||||
export async function genChangelog(options?: Partial<ChangelogOption>, total = false) {
|
||||
if (total) {
|
||||
await generateTotalChangelog(options);
|
||||
} else {
|
||||
await generateChangelog(options);
|
||||
}
|
||||
}
|
@ -1,37 +1,37 @@
|
||||
import path from 'node:path';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import enquirer from 'enquirer';
|
||||
import { bgRed, green, red } from 'kolorist';
|
||||
import prompts from 'prompts';
|
||||
import { bgRed, green, red, yellow } from 'kolorist';
|
||||
import { execCommand } from '../shared';
|
||||
import type { CliOption } from '../types';
|
||||
|
||||
interface PromptObject {
|
||||
types: string;
|
||||
scopes: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Git commit with Conventional Commits standard
|
||||
*
|
||||
* @param gitCommitTypes
|
||||
* @param gitCommitScopes
|
||||
*/
|
||||
export async function gitCommit(
|
||||
gitCommitTypes: CliOption['gitCommitTypes'],
|
||||
gitCommitScopes: CliOption['gitCommitScopes']
|
||||
) {
|
||||
const typesChoices = gitCommitTypes.map(([name, title]) => {
|
||||
const nameWithSuffix = `${name}:`;
|
||||
const typesChoices = gitCommitTypes.map(([value, msg]) => {
|
||||
const nameWithSuffix = `${value}:`;
|
||||
|
||||
const message = `${nameWithSuffix.padEnd(12)}${title}`;
|
||||
const title = `${nameWithSuffix.padEnd(12)}${msg}`;
|
||||
|
||||
return {
|
||||
name,
|
||||
message
|
||||
value,
|
||||
title
|
||||
};
|
||||
});
|
||||
|
||||
const scopesChoices = gitCommitScopes.map(([name, title]) => ({
|
||||
name,
|
||||
message: `${name.padEnd(30)} (${title})`
|
||||
const scopesChoices = gitCommitScopes.map(([value, msg]) => ({
|
||||
value,
|
||||
title: `${value.padEnd(30)} (${msg})`
|
||||
}));
|
||||
|
||||
const result = await enquirer.prompt<PromptObject>([
|
||||
const result = await prompts([
|
||||
{
|
||||
name: 'types',
|
||||
type: 'select',
|
||||
@ -47,15 +47,20 @@ export async function gitCommit(
|
||||
{
|
||||
name: 'description',
|
||||
type: 'text',
|
||||
message: 'Please enter a description'
|
||||
message: `Please enter a description (add prefix ${yellow('!')} to indicate breaking change)`
|
||||
}
|
||||
]);
|
||||
|
||||
const commitMsg = `${result.types}(${result.scopes}): ${result.description}`;
|
||||
const breaking = result.description.startsWith('!') ? '!' : '';
|
||||
|
||||
const description = result.description.replace(/^!/, '').trim();
|
||||
|
||||
const commitMsg = `${result.types}(${result.scopes})${breaking}: ${description}`;
|
||||
|
||||
await execCommand('git', ['commit', '-m', commitMsg], { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
/** Git commit message verify */
|
||||
export async function gitCommitVerify() {
|
||||
const gitPath = await execCommand('git', ['rev-parse', '--show-toplevel']);
|
||||
|
||||
@ -63,7 +68,7 @@ export async function gitCommitVerify() {
|
||||
|
||||
const commitMsg = readFileSync(gitMsgPath, 'utf8').trim();
|
||||
|
||||
const REG_EXP = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
||||
const REG_EXP = /(?<type>[a-z]+)(?:\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
||||
|
||||
if (!REG_EXP.test(commitMsg)) {
|
||||
throw new Error(
|
||||
|
@ -1,3 +1,5 @@
|
||||
export * from './git-commit';
|
||||
export * from './cleanup';
|
||||
export * from './update-pkg';
|
||||
export * from './changelog';
|
||||
export * from './release';
|
||||
|
12
packages/scripts/src/commands/release.ts
Normal file
12
packages/scripts/src/commands/release.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { versionBump } from 'bumpp';
|
||||
|
||||
export async function release(execute = 'pnpm sa changelog', push = true) {
|
||||
await versionBump({
|
||||
files: ['**/package.json', '!**/node_modules'],
|
||||
execute,
|
||||
all: true,
|
||||
tag: true,
|
||||
commit: 'chore(projects): release v%s',
|
||||
push
|
||||
});
|
||||
}
|
@ -2,8 +2,6 @@ import process from 'node:process';
|
||||
import { loadConfig } from 'c12';
|
||||
import type { CliOption } from '../types';
|
||||
|
||||
const eslintExt = '*.{js,jsx,mjs,cjs,ts,tsx,vue}';
|
||||
|
||||
const defaultOptions: CliOption = {
|
||||
cwd: process.cwd(),
|
||||
cleanupDirs: [
|
||||
@ -39,27 +37,7 @@ const defaultOptions: CliOption = {
|
||||
['other', 'other changes']
|
||||
],
|
||||
ncuCommandArgs: ['--deep', '-u'],
|
||||
prettierWriteGlob: [
|
||||
`!**/${eslintExt}`,
|
||||
'!*.min.*',
|
||||
'!CHANGELOG.md',
|
||||
'!dist',
|
||||
'!LICENSE*',
|
||||
'!output',
|
||||
'!coverage',
|
||||
'!public',
|
||||
'!temp',
|
||||
'!package-lock.json',
|
||||
'!pnpm-lock.yaml',
|
||||
'!yarn.lock',
|
||||
'!.github',
|
||||
'!__snapshots__',
|
||||
'!node_modules'
|
||||
],
|
||||
lintStagedConfig: {
|
||||
[eslintExt]: 'eslint --fix',
|
||||
'*': 'sa prettier-write'
|
||||
}
|
||||
changelogOptions: {}
|
||||
};
|
||||
|
||||
export async function loadCliOptions(overrides?: Partial<CliOption>, cwd = process.cwd()) {
|
||||
|
@ -1,25 +1,50 @@
|
||||
import cac from 'cac';
|
||||
import { blue, lightGreen } from 'kolorist';
|
||||
import { version } from '../package.json';
|
||||
import { cleanup, gitCommit, gitCommitVerify, updatePkg } from './commands';
|
||||
import { cleanup, genChangelog, gitCommit, gitCommitVerify, release, updatePkg } from './commands';
|
||||
import { loadCliOptions } from './config';
|
||||
|
||||
type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify';
|
||||
type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify' | 'changelog' | 'release';
|
||||
|
||||
type CommandAction<A extends object> = (args?: A) => Promise<void> | void;
|
||||
|
||||
type CommandWithAction<A extends object = object> = Record<Command, { desc: string; action: CommandAction<A> }>;
|
||||
|
||||
interface CommandArg {
|
||||
/** Execute additional command after bumping and before git commit. Defaults to 'npx soy changelog' */
|
||||
execute?: string;
|
||||
/** Indicates whether to push the git commit and tag. Defaults to true */
|
||||
push?: boolean;
|
||||
/** Generate changelog by total tags */
|
||||
total?: boolean;
|
||||
/**
|
||||
* The glob pattern of dirs to cleanup
|
||||
*
|
||||
* If not set, it will use the default value
|
||||
*
|
||||
* Multiple values use "," to separate them
|
||||
*/
|
||||
cleanupDir?: string;
|
||||
}
|
||||
|
||||
export async function setupCli() {
|
||||
const cliOptions = await loadCliOptions();
|
||||
|
||||
const cli = cac(blue('soybean'));
|
||||
const cli = cac(blue('soybean-admin'));
|
||||
|
||||
cli.version(lightGreen(version)).help();
|
||||
cli
|
||||
.version(lightGreen(version))
|
||||
.option(
|
||||
'-e, --execute [command]',
|
||||
"Execute additional command after bumping and before git commit. Defaults to 'npx soy changelog'"
|
||||
)
|
||||
.option('-p, --push', 'Indicates whether to push the git commit and tag')
|
||||
.option('-t, --total', 'Generate changelog by total tags')
|
||||
.option(
|
||||
'-c, --cleanupDir <dir>',
|
||||
'The glob pattern of dirs to cleanup, If not set, it will use the default value, Multiple values use "," to separate them'
|
||||
)
|
||||
.help();
|
||||
|
||||
const commands: CommandWithAction<CommandArg> = {
|
||||
cleanup: {
|
||||
@ -45,6 +70,18 @@ export async function setupCli() {
|
||||
action: async () => {
|
||||
await gitCommitVerify();
|
||||
}
|
||||
},
|
||||
changelog: {
|
||||
desc: 'generate changelog',
|
||||
action: async args => {
|
||||
await genChangelog(cliOptions.changelogOptions, args?.total);
|
||||
}
|
||||
},
|
||||
release: {
|
||||
desc: 'release: update version, generate changelog, commit code',
|
||||
action: async args => {
|
||||
await release(args?.execute, args?.push);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import type { ChangelogOption } from '@soybeanjs/changelog';
|
||||
|
||||
export interface CliOption {
|
||||
/** The project root directory */
|
||||
cwd: string;
|
||||
@ -23,11 +25,9 @@ export interface CliOption {
|
||||
*/
|
||||
ncuCommandArgs: string[];
|
||||
/**
|
||||
* Prettier write glob
|
||||
* Options of generate changelog
|
||||
*
|
||||
* Glob pattern syntax {@link https://github.com/micromatch/micromatch}
|
||||
* @link https://github.com/soybeanjs/changelog
|
||||
*/
|
||||
prettierWriteGlob: string[];
|
||||
/** Lint-staged config */
|
||||
lintStagedConfig: Record<string, string | string[]>;
|
||||
changelogOptions: Partial<ChangelogOption>;
|
||||
}
|
||||
|
15
packages/scripts/typings/pkg.d.ts
vendored
15
packages/scripts/typings/pkg.d.ts
vendored
@ -1,15 +0,0 @@
|
||||
declare module 'lint-staged' {
|
||||
interface LintStagedOptions {
|
||||
config?: Record<string, string | string[]>;
|
||||
allowEmpty?: boolean;
|
||||
}
|
||||
|
||||
type LintStagedFn = (options: LintStagedOptions) => Promise<boolean>;
|
||||
interface LintStaged extends LintStagedFn {
|
||||
default: LintStagedFn;
|
||||
}
|
||||
|
||||
const lintStaged: LintStaged;
|
||||
|
||||
export default lintStaged;
|
||||
}
|
Reference in New Issue
Block a user