UNPKG

gh-changelogen

Version:

Changelog generator for GitHub Releases

105 lines (96 loc) 3.2 kB
import { promises, constants } from 'node:fs'; import { resolve } from 'node:path'; import z from 'zod'; import { parse as parse$1 } from 'zodiarg'; import { $fetch } from 'ohmyfetch'; import 'node:child_process'; function isFunction(value) { return typeof value === "function"; } async function isExists(path) { try { await promises.access(path, constants.F_OK); return true; } catch { return false; } } function getHeaders(options) { return { accept: "application/vnd.github.v3+json", authorization: `token ${options.token}` }; } async function fetcherDefault(tag, options = {}) { if (!options.github) { throw new Error(`'github' option is required`); } const url = `https://api.github.com/repos/${options.github}/releases/tags/${tag}`; return $fetch(url, { headers: getHeaders(options), method: "GET" }); } async function fetchGithubRelease(tag, options) { const fetcher = options?.fetcher ?? fetcherDefault; if (!isFunction(fetcher)) { throw new Error("fetcher is not a function"); } return fetcher(tag, options); } function generatorDefault(release) { return Promise.resolve(`# ${release.name}${release.name !== release.tag_name ? ` ${release.tag_name}` : ""} (${release.published_at}) This changelog is generated by [GitHub Releases](${release.html_url}) ${release.body} `); } async function generateChangelog(release, generator = generatorDefault) { if (!isFunction(generator)) { throw new Error("generator is not a function"); } return generator(release); } const GITHUB_TOKEN_KEY = "GITHUB_TOKEN"; const DEFAULT_CHANGELOG_FILE = "CHANGELOG.md"; function parse(args) { return parse$1( { options: { repo: z.string().describe("GitHub repository name, format `owner/repo` (e.g. `kazupon/gh-changelogen`)"), tag: z.string().describe("GitHub release tag (e.g. `v0.0.1`)"), output: z.string().default(DEFAULT_CHANGELOG_FILE).describe( `Changelog file name to create or update. defaults to '${DEFAULT_CHANGELOG_FILE}' and resolved relative` ), token: z.string().default(GITHUB_TOKEN_KEY).describe(`GitHub token, if you won\u2019t specify, respect '${GITHUB_TOKEN_KEY}' env`) }, flags: {}, args: [], alias: {} }, args, { helpWithNoArgs: true, help: true } ); } async function writeChangelog(output, changelog) { let existChangelog = ""; if (await isExists(output)) { existChangelog = (await promises.readFile(output, "utf-8")).toString(); } await promises.writeFile(output, [changelog, "\n", existChangelog].join(""), "utf-8"); } async function main(args) { const input = parse(args); let token = input.options.token; if (token === GITHUB_TOKEN_KEY) { token = process.env.GITHUB_TOKEN || ""; if (!token) { throw new Error(`Not found ${GITHUB_TOKEN_KEY} in env`); } } const release = await fetchGithubRelease(input.options.tag, { github: input.options.repo, token }); const changelog = await generateChangelog(release); console.log(changelog); const output = resolve(process.cwd(), input.options.output); await writeChangelog(output, changelog); } export { main };