diff --git a/package.json b/package.json index f880ea2..c5681ba 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "pkg-types": "^1.0.2", "scule": "^1.0.0", "semver": "^7.5.0", + "ufo": "^1.1.1", "yaml": "^2.2.2" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65ef094..77d200d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,6 +40,9 @@ dependencies: semver: specifier: ^7.5.0 version: 7.5.0 + ufo: + specifier: ^1.1.1 + version: 1.1.1 yaml: specifier: ^2.2.2 version: 2.2.2 diff --git a/src/commands/default.ts b/src/commands/default.ts index 0645e3e..400673b 100644 --- a/src/commands/default.ts +++ b/src/commands/default.ts @@ -23,12 +23,13 @@ export default async function defaultMain(args: Argv) { to: args.to, output: args.output, newVersion: args.r, + subDir: args.subDir, }); const logger = consola.create({ stdout: process.stderr }); logger.info(`Generating changelog for ${config.from || ""}...${config.to}`); - const rawCommits = await getGitDiff(config.from, config.to); + const rawCommits = await getGitDiff(config.from, config.to, config.subDir); // Parse commits as conventional commits const commits = parseCommits(rawCommits, config).filter( @@ -86,9 +87,10 @@ export default async function defaultMain(args: Argv) { // Commit and tag changes for release mode if (args.release) { if (args.commit !== false) { - const filesToAdd = [config.output, "package.json"].filter( - (f) => f && typeof f === "string" - ) as string[]; + const filesToAdd = [ + config.output, + resolve(config.cwd, config.subDir, "package.json"), + ].filter((f) => f && typeof f === "string") as string[]; await execa("git", ["add", ...filesToAdd], { cwd }); const msg = config.templates.commitMessage.replaceAll( "{{newVersion}}", diff --git a/src/config.ts b/src/config.ts index 210ad07..dc71a0e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -20,6 +20,7 @@ export interface ChangelogConfig { tagMessage?: string; tagBody?: string; }; + subDir: string; } const getDefaultConfig = () => @@ -54,6 +55,7 @@ const getDefaultConfig = () => tagMessage: "v{{newVersion}}", tagBody: "v{{newVersion}}", }, + subDir: "/", }; export async function loadChangelogConfig( @@ -84,8 +86,11 @@ export async function loadChangelogConfig( if (!config.output) { config.output = false; } else if (config.output) { - config.output = - config.output === true ? defaults.output : resolve(cwd, config.output); + config.output = resolve( + cwd, + config.subDir, + config.output === true ? (defaults.output as string) : config.output + ); } if (!config.repo) { diff --git a/src/git.ts b/src/git.ts index 7d58114..b8fffdc 100644 --- a/src/git.ts +++ b/src/git.ts @@ -56,16 +56,21 @@ export async function getGitRemoteURL(cwd: string, remote = "origin") { export async function getGitDiff( from: string | undefined, - to = "HEAD" + to = "HEAD", + dir?: string ): Promise { - // https://git-scm.com/docs/pretty-formats - const r = await execCommand("git", [ + const args = [ "--no-pager", "log", `${from ? `${from}...` : ""}${to}`, '--pretty="----%n%s|%h|%an|%ae%n%b"', "--name-status", - ]); + ]; + if (dir) { + args.push("--", dir); + } + // https://git-scm.com/docs/pretty-formats + const r = await execCommand("git", args.filter(Boolean)); return r .split("----\n") .splice(1) diff --git a/src/github.ts b/src/github.ts index 0137d7e..05a7c6f 100644 --- a/src/github.ts +++ b/src/github.ts @@ -1,7 +1,8 @@ import { existsSync, promises as fsp } from "node:fs"; import { homedir } from "node:os"; import { $fetch, FetchOptions } from "ofetch"; -import { join } from "pathe"; +import { join, relative } from "pathe"; +import { joinURL } from "ufo"; import { ChangelogConfig } from "./config"; export interface GithubOptions { @@ -38,9 +39,11 @@ export async function getGithubReleaseByTag( } export async function getGithubChangelog(config: ChangelogConfig) { + const filePath = relative(config.cwd, config.output as string); + const urlPath = joinURL(config.repo.repo, "main", filePath); return await githubFetch( config, - `https://raw.githubusercontent.com/${config.repo.repo}/main/CHANGELOG.md` + `https://raw.githubusercontent.com/${urlPath}` ); } diff --git a/src/semver.ts b/src/semver.ts index 3db0adb..5c6fb77 100644 --- a/src/semver.ts +++ b/src/semver.ts @@ -47,7 +47,7 @@ export async function bumpVersion( let type = opts.type || determineSemverChange(commits, config) || "patch"; const originalType = type; - const pkgPath = resolve(config.cwd, "package.json"); + const pkgPath = resolve(config.cwd, config.subDir, "package.json"); const pkg = await readPackageJSON(pkgPath); const currentVersion = pkg.version || "0.0.0"; diff --git a/test/git.test.ts b/test/git.test.ts index 66ae596..1c31d7d 100644 --- a/test/git.test.ts +++ b/test/git.test.ts @@ -21,6 +21,14 @@ describe("git", () => { ); }); + test("getGitDiff with dir should work", async () => { + const COMMIT_INITIAL = "4554fc49265ac532b14c89cec15e7d21bb55d48b"; + const COMMIT_VER002 = "38d7ba15dccc3a44931bf8bf0abaa0d4d96603eb"; + expect( + (await getGitDiff(COMMIT_INITIAL, COMMIT_VER002, "./test")).length + ).toBe(1); + }); + test("parse", async () => { const COMMIT_FROM = "1cb15d5dd93302ebd5ff912079ed584efcc6703b"; const COMMIT_TO = "3828bda8c45933396ddfa869d671473231ce3c95"; diff --git a/test/github.test.ts b/test/github.test.ts new file mode 100644 index 0000000..6b8980d --- /dev/null +++ b/test/github.test.ts @@ -0,0 +1,34 @@ +import { afterEach, describe, expect, test, vi } from "vitest"; +import { $fetch } from "ofetch"; +import { getGithubChangelog } from "../src/github"; +import { ChangelogConfig } from "../src"; + +vi.mock("ofetch", () => ({ + $fetch: vi.fn(), +})); + +describe("github", () => { + afterEach(() => { + vi.mocked($fetch).mockClear(); + }); + + test("getGithubChangelog should work", async () => { + await getGithubChangelog({ + cwd: "/bar", + output: "/bar/CHANGELOG.md", + repo: { + domain: "github.com", + repo: "foo", + }, + tokens: { + github: undefined, + }, + } as ChangelogConfig); + + expect($fetch).toBeCalledTimes(1); + expect($fetch).toBeCalledWith( + `https://raw.githubusercontent.com/foo/main/CHANGELOG.md`, + expect.anything() + ); + }); +});