From 8089d0455ecd79df9965ce164cb0c06872e21e4e Mon Sep 17 00:00:00 2001 From: chengpeiquan Date: Fri, 16 Feb 2024 00:19:04 +0800 Subject: [PATCH] feat(release): initial release CLI --- packages/release/.build/config.json | 3 + packages/release/README.md | 114 ++++++++++++++++++++++++++++ packages/release/package.json | 40 ++++++++++ packages/release/src/index.ts | 49 ++++++++++++ packages/release/src/utils.ts | 52 +++++++++++++ pnpm-lock.yaml | 12 +++ 6 files changed, 270 insertions(+) create mode 100644 packages/release/.build/config.json create mode 100644 packages/release/README.md create mode 100644 packages/release/package.json create mode 100644 packages/release/src/index.ts create mode 100644 packages/release/src/utils.ts diff --git a/packages/release/.build/config.json b/packages/release/.build/config.json new file mode 100644 index 0000000..8332a0e --- /dev/null +++ b/packages/release/.build/config.json @@ -0,0 +1,3 @@ +{ + "bin": true +} \ No newline at end of file diff --git a/packages/release/README.md b/packages/release/README.md new file mode 100644 index 0000000..fc9ddf5 --- /dev/null +++ b/packages/release/README.md @@ -0,0 +1,114 @@ +# @bassist/release + +

+ + + + + + + + + + + GitHub stars + +

+ +Simple GitHub release generator by [@chengpeiquan](https://github.com/chengpeiquan) , based on [GitHub CLI](https://cli.github.com/). + +If you're tired of having to release every time on GitHub web, you can use this package to make it easier and just run a single command. + +## Prerequisite + +For the security of your account and to avoid Token leakage, you must first install GitHub CLI and complete the login on it. + +See: [GitHub CLI](https://cli.github.com/) + +And make sure you have Release permissions on the project's GitHub repository. + +There is another requirement, please configure the repository information of `package.json` according to the specifications of npm docs. + +See: [repository](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#repository) + +e.g. + +For single-package repo: + +```json +{ + "repository": { + "type": "git", + "url": "https://github.com/chengpeiquan/bassist" + } +} +``` + +For monorepo, you can specify the `directory` in which it lives: + +```json +{ + "repository": { + "type": "git", + "url": "https://github.com/chengpeiquan/bassist", + "directory": "packages/utils" + } +} +``` + +Currently supported URL formats are: + +- `https://github.com/chengpeiquan/bassist` +- `https://github.com/chengpeiquan/bassist.git` +- `github:chengpeiquan/bassist` + +## Usage + +This is a CLI tool, you can install it locally and run it through commands such as pnpm exec. + +Install it: + +```bash +pnpm add -D @bassist/release +``` + +In your `package.json` : + +```json +{ + "scripts": { + "gen:release": "pnpm exec release" + } +} +``` + +Run on command line: + +```bash +pnpm gen:release +``` + +You can view the latest release information on the releases page of your GitHub repository. + +## Options + +For most projects, the default settings are sufficient. If adjustments are sometimes needed, some options are provided to pass on. + +On the command line, options can be passed to the program, e.g. `--preset angular` by option, or `-p angular` by short flag. + +| Option | Short Flag | Default Value | Description | +| :-------: | :--------: | :------------: | :--------------------------------------------- | +| branch | b | `main` | The branch where the CHANGELOG file is located | +| changelog | c | `CHANGELOG.md` | The file name of the change log | + +Btw: The paths are all based on `process.cwd()` , which is usually run from the root directory of the package (the directory where `package.json` is located). + +If there are any running problems, please provide a reproducible example in the [issue](https://github.com/chengpeiquan/bassist/issues) . + +## Release Notes + +Please refer to [CHANGELOG](https://github.com/chengpeiquan/bassist/blob/main/packages/release/CHANGELOG.md) for details. + +## License + +MIT License © 2023-PRESENT [chengpeiquan](https://github.com/chengpeiquan) diff --git a/packages/release/package.json b/packages/release/package.json new file mode 100644 index 0000000..38a25f3 --- /dev/null +++ b/packages/release/package.json @@ -0,0 +1,40 @@ +{ + "name": "@bassist/release", + "version": "0.1.0", + "description": "Simple GitHub release generator by @chengpeiquan , based on GitHub CLI.", + "author": "chengpeiquan ", + "license": "MIT", + "homepage": "https://github.com/chengpeiquan/bassist/tree/main/packages/release", + "files": [ + "dist" + ], + "bin": { + "@bassist/release": "./dist/index.mjs", + "release": "./dist/index.mjs" + }, + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + } + }, + "repository": { + "type": "git", + "url": "https://github.com/chengpeiquan/bassist" + }, + "keywords": [ + "release", + "release generator", + "generate release", + "github release" + ], + "dependencies": { + "@bassist/utils": "workspace:^", + "@withtypes/fs-extra": "^0.1.1", + "@withtypes/minimist": "^0.1.1" + } +} \ No newline at end of file diff --git a/packages/release/src/index.ts b/packages/release/src/index.ts new file mode 100644 index 0000000..a046e5e --- /dev/null +++ b/packages/release/src/index.ts @@ -0,0 +1,49 @@ +import { resolve } from 'node:path' +import { execSync } from 'node:child_process' +import { readJsonSync } from '@withtypes/fs-extra' +import { getNotes } from './utils' +import minimist from '@withtypes/minimist' +import pkg from '../package.json' + +async function run() { + const argv = minimist(process.argv.slice(2), { + string: ['_', 'branch', 'changelog'], + alias: { + branch: 'b', + changelog: 'c', + }, + }) + + const { branch = 'main', changelog = 'CHANGELOG.md' } = argv + + const cwd = process.cwd() + const pkgPath = resolve(cwd, './package.json') + const json = readJsonSync(pkgPath) || {} + + const { version, repository } = json + if (!version) { + throw new Error(`[${pkg.name}] Missing package version`) + } + if (!repository) { + throw new Error(`[${pkg.name}] Missing package repository`) + } + + const notes = getNotes({ + repository, + branch, + changelog, + }) + + const releaseArgs = [ + 'gh --version', + `git tag -a v${version} -m "v${version}"`, + `git push origin v${version}`, + `gh release create v${version} --title "v${version}" --notes "${notes}"`, + ] + + const cmd = releaseArgs.join(' && ') + execSync(cmd) +} +run().catch((e) => { + console.log(e) +}) diff --git a/packages/release/src/utils.ts b/packages/release/src/utils.ts new file mode 100644 index 0000000..b208d1d --- /dev/null +++ b/packages/release/src/utils.ts @@ -0,0 +1,52 @@ +import { isObject } from '@bassist/utils' + +const GITHUB_URL = 'https://github.com/' +const DETAILS_LABEL = 'CHANGELOG' + +// https://docs.npmjs.com/cli/v10/configuring-npm/package-json#repository +interface Repository { + type: string + url: string + directory: string +} + +function getRepo(repository?: Repository) { + if (!repository || !isObject(repository)) return undefined + const { url = '', directory = '' } = repository + if (!url) return undefined + + if (url.startsWith('http')) { + const repo = url.endsWith('.git') ? url.replace('.git', '') : url + return { repo, directory } + } + + if (url.startsWith('github:')) { + const user = url.replace('github:', '') + const repo = `${GITHUB_URL}${user}` + return { repo, directory } + } + + return undefined +} + +function getTips(label = DETAILS_LABEL) { + return ['Please refer to', label, 'for details.'].join(' ') +} + +interface GetNotesOptions { + repository?: Repository + branch: string + changelog: string +} + +export function getNotes({ repository, branch, changelog }: GetNotesOptions) { + const repoInfo = getRepo(repository) + if (!repoInfo) return getTips() + + const url = [repoInfo.repo, 'blob', branch, repoInfo.directory, changelog] + .filter((i) => !!i) + .join('/') + + const label = `[${DETAILS_LABEL}](${url})` + return getTips(label) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecb3fe6..adba1ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -228,6 +228,18 @@ importers: specifier: ^0.2.0 version: 0.2.0 + packages/release: + dependencies: + '@bassist/utils': + specifier: workspace:^ + version: link:../utils + '@withtypes/fs-extra': + specifier: ^0.1.1 + version: 0.1.1 + '@withtypes/minimist': + specifier: ^0.1.1 + version: 0.1.1 + packages/tsconfig: {} packages/uno: