keepchanges 1.0.0-beta.1 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -150,7 +150,8 @@ different commits.
150
150
 
151
151
  Stable releases compare with the previous stable tag. Prereleases compare with
152
152
  the nearest previous tag. With `--release`, `--dry` takes precedence and
153
- prevents all file writes and remote mutations.
153
+ prevents all file writes and remote mutations. Its manual URL opens a new
154
+ Release for a new tag and the edit page for an existing tag.
154
155
 
155
156
  > [!NOTE]
156
157
  > A regular `--release` without a token still writes files, commits, tags, and
package/README.zh-CN.md CHANGED
@@ -143,7 +143,8 @@ GitHub 和 Gitea 均支持作者解析和 Release 发布;Gitea 使用 `GITEA_T
143
143
  时会停止,不会强制覆盖。
144
144
 
145
145
  稳定版本会与前一个稳定 tag 对比,预发布版本会与最近的前一个 tag 对比。与
146
- `--release` 搭配的 `--dry` 优先级最高,不会执行任何写入或远程修改。
146
+ `--release` 搭配的 `--dry` 优先级最高,不会执行任何写入或远程修改。手动链接
147
+ 会为新 tag 打开创建 Release 页面,为已有 tag 打开编辑页面。
147
148
 
148
149
  > [!NOTE]
149
150
  > 没有 token 的普通 `--release` 仍会执行本地写入、commit、tag 和 push,
package/dist/cli.mjs CHANGED
@@ -8,7 +8,7 @@ import { resolve } from "node:path";
8
8
  import ansis from "ansis";
9
9
  import { x } from "tinyexec";
10
10
  //#region package.json
11
- var version = "1.0.0-beta.1";
11
+ var version = "1.0.0-beta.2";
12
12
  //#endregion
13
13
  //#region src/git.ts
14
14
  async function git(cwd, ...args) {
@@ -58,6 +58,7 @@ async function readGitCommits(cwd, from, to) {
58
58
  //#region src/repositories/gitea.ts
59
59
  const giteaRepository = {
60
60
  name: "Gitea",
61
+ tokenEnv: "GITEA_TOKEN",
61
62
  parse(source) {
62
63
  try {
63
64
  const url = new URL(source.replace(/^git\+/, ""));
@@ -83,7 +84,8 @@ const giteaRepository = {
83
84
  compareUrl(repository, from, to) {
84
85
  return `${repository.webUrl}/compare/${from}...${to}`;
85
86
  },
86
- manualReleaseUrl(repository, release) {
87
+ manualReleaseUrl(repository, release, action) {
88
+ if (action === "edit") return `${repository.webUrl}/releases/edit/${encodeURIComponent(release.tag)}`;
87
89
  const url = new URL(`${repository.webUrl}/releases/new`);
88
90
  url.search = new URLSearchParams({ tag: release.tag }).toString();
89
91
  return url.toString();
@@ -143,6 +145,7 @@ const giteaRepository = {
143
145
  //#region src/repositories/github.ts
144
146
  const githubRepository = {
145
147
  name: "GitHub",
148
+ tokenEnv: "GITHUB_TOKEN",
146
149
  parse(source) {
147
150
  const match = /github\.com[:/]([^/]+\/[^/]+?)(?:\.git)?$/.exec(source);
148
151
  if (!match) return;
@@ -164,7 +167,8 @@ const githubRepository = {
164
167
  compareUrl(repository, from, to) {
165
168
  return `${repository.webUrl}/compare/${from}...${to}`;
166
169
  },
167
- manualReleaseUrl(repository, release) {
170
+ manualReleaseUrl(repository, release, action) {
171
+ if (action === "edit") return `${repository.webUrl}/releases/edit/${encodeURIComponent(release.tag)}`;
168
172
  const url = new URL(`${repository.webUrl}/releases/new`);
169
173
  url.search = new URLSearchParams({
170
174
  title: release.name,
@@ -288,9 +292,9 @@ function printChangesPreview(preview, stdout, colors) {
288
292
  ""
289
293
  ].join("\n"));
290
294
  }
291
- function printManualReleaseUrl(repository, release, stdout, colors) {
292
- const url = repository.provider.manualReleaseUrl?.(repository, release);
293
- if (url) stdout(`${colors.yellow("Using the following link to create it manually:")}\n${colors.yellow(url)}\n`);
295
+ function printManualReleaseUrl(repository, release, stdout, colors, action = "create") {
296
+ const url = repository.provider.manualReleaseUrl?.(repository, release, action);
297
+ if (url) stdout(`${colors.yellow(`Using the following link to ${action} it manually:`)}\n${colors.yellow(url)}\n`);
294
298
  }
295
299
  function printPublishedRelease(provider, result, stdout, colors) {
296
300
  const action = result.action.charAt(0).toUpperCase() + result.action.slice(1);
@@ -326,7 +330,7 @@ async function createChanges(options, environment) {
326
330
  const to = releaseRef || options.to;
327
331
  const comparisonFrom = from || (repository ? await git(environment.cwd, "rev-list", "--max-parents=0", to).then((value) => value.trim()) : "");
328
332
  const commits = parseCommits(await readGitCommits(environment.cwd, from, to));
329
- if (token && repository && !(options.release && options.dry)) await repository.provider.resolveAuthors?.(commits, repository, token, environment.fetch ?? globalThis.fetch);
333
+ if (token && repository) await repository.provider.resolveAuthors?.(commits, repository, token, environment.fetch ?? globalThis.fetch);
330
334
  const style = {
331
335
  emoji: options.emoji,
332
336
  capitalize: options.capitalize,
@@ -355,13 +359,13 @@ async function createChanges(options, environment) {
355
359
  printChangesPreview(preview, stdout, colors);
356
360
  if (options.release) {
357
361
  stdout(`${colors.yellow("Dry run. Release skipped.")}\n\n`);
358
- printManualReleaseUrl(repository, repositoryRelease, stdout, colors);
362
+ printManualReleaseUrl(repository, repositoryRelease, stdout, colors, taggedCommit ? "edit" : "create");
359
363
  }
360
364
  return;
361
365
  }
362
366
  if (options.release && taggedCommit) {
363
367
  if (!remoteTaggedCommit) await git(environment.cwd, "push", "origin", `refs/tags/${tag}`);
364
- await publishRelease(repository, repositoryRelease, token, preview, environment);
368
+ await publishRelease(repository, repositoryRelease, token, preview, environment, "edit");
365
369
  return;
366
370
  }
367
371
  const outputPath = resolve(environment.cwd, options.output);
@@ -390,14 +394,14 @@ async function commitReleaseFiles(options, cwd, outputPath, versionPath, release
390
394
  const commitMessage = versionPath && !versionChanges.trim() ? `docs(changelog): ${releaseExists ? "update" : "add"} v${options.version} release notes` : `chore(release): v${options.version}`;
391
395
  await git(cwd, ...resolveGitIdentity(options.author), "commit", "-m", commitMessage, ...options.author ? ["--author", options.author] : [], "--only", "--", ...releasePaths);
392
396
  }
393
- async function publishRelease(repository, release, token, preview, environment) {
397
+ async function publishRelease(repository, release, token, preview, environment, manualAction = "create") {
394
398
  const stdout = environment.stdout ?? ((value) => process.stdout.write(value));
395
399
  const colors = environment.colors ?? ansis;
396
400
  printChangesPreview(preview, stdout, colors);
397
401
  if (!token || !repository.provider.publishRelease) {
398
402
  if (!repository.provider.manualReleaseUrl) throw new Error("A repository token is required to release");
399
- stdout(`${colors.red(`No ${repository.provider.name} token found, specify it via --token or environment variable. Release skipped.`)}\n\n`);
400
- printManualReleaseUrl(repository, release, stdout, colors);
403
+ stdout(`${colors.red(`No ${repository.provider.name} token found, specify it via --token or ${repository.provider.tokenEnv} env. Release skipped.`)}\n\n`);
404
+ printManualReleaseUrl(repository, release, stdout, colors, manualAction);
401
405
  return;
402
406
  }
403
407
  const result = await repository.provider.publishRelease(repository, release, token, environment.fetch ?? globalThis.fetch);
package/dist/index.d.mts CHANGED
@@ -24,8 +24,10 @@ interface RepositoryReleaseResult {
24
24
  url: string;
25
25
  action: 'created' | 'updated';
26
26
  }
27
+ type ManualReleaseAction = 'create' | 'edit';
27
28
  interface RepositoryProvider {
28
29
  name: string;
30
+ tokenEnv: string;
29
31
  parse: (source: string) => Repository | undefined;
30
32
  token: (explicit: string | undefined, env: NodeJS.ProcessEnv) => string | undefined;
31
33
  commitUrl: (repository: Repository, hash: string) => string;
@@ -33,7 +35,7 @@ interface RepositoryProvider {
33
35
  compareUrl: (repository: Repository, from: string, to: string) => string;
34
36
  resolveAuthors?: (commits: RepositoryCommit[], repository: Repository, token: string, fetch: typeof globalThis.fetch) => Promise<void>;
35
37
  publishRelease?: (repository: Repository, release: RepositoryRelease, token: string, fetch: typeof globalThis.fetch) => Promise<RepositoryReleaseResult>;
36
- manualReleaseUrl?: (repository: Repository, release: RepositoryRelease) => string;
38
+ manualReleaseUrl?: (repository: Repository, release: RepositoryRelease, action?: ManualReleaseAction) => string;
37
39
  }
38
40
  //#endregion
39
41
  //#region src/git.d.ts
@@ -149,4 +151,4 @@ declare function writeChangelog(path: string, changelog: string): Promise<void>;
149
151
  declare function hasRelease(changelog: string, version: string): boolean;
150
152
  declare function insertRelease(changelog: string, release: string): string;
151
153
  //#endregion
152
- export { type ChangelogConfig, type ChangelogConfigOverrides, type ChangelogMessages, type ChangelogSectionConfig, type Commit, type GenerateChangelogOptions, type GeneratedChangelog, type KeepChangesConfig, type RawCommit, type Repository, type RepositoryAuthor, type RepositoryCommit, type RepositoryProvider, type RepositoryRelease, type RepositoryReleaseResult, defaultConfig, generateChangelog, hasRelease, insertRelease, parseCommit, parseCommits, readChangelog, resolveChangelogConfig, writeChangelog };
154
+ export { type ChangelogConfig, type ChangelogConfigOverrides, type ChangelogMessages, type ChangelogSectionConfig, type Commit, type GenerateChangelogOptions, type GeneratedChangelog, type KeepChangesConfig, type ManualReleaseAction, type RawCommit, type Repository, type RepositoryAuthor, type RepositoryCommit, type RepositoryProvider, type RepositoryRelease, type RepositoryReleaseResult, defaultConfig, generateChangelog, hasRelease, insertRelease, parseCommit, parseCommits, readChangelog, resolveChangelogConfig, writeChangelog };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "keepchanges",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.1",
4
+ "version": "1.0.0-beta.2",
5
5
  "description": "Generate and maintain CHANGELOG.md from Conventional Commits.",
6
6
  "author": "edram",
7
7
  "license": "MIT",
@@ -41,19 +41,19 @@
41
41
  "devDependencies": {
42
42
  "@antfu/eslint-config": "^9.2.0",
43
43
  "@types/node": "^26.1.1",
44
- "bumpp": "^11.1.0",
45
44
  "eslint": "^10.7.0",
46
45
  "tsdown": "^0.22.5",
46
+ "tsx": "^4.23.8",
47
47
  "typescript": "^6.0.3",
48
48
  "vitest": "^4.1.10"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "tsdown",
52
52
  "dev": "tsdown --watch",
53
+ "start": "tsx ./src/cli.ts",
53
54
  "lint": "eslint",
54
55
  "lint:fix": "eslint --fix",
55
56
  "test": "pnpm run build && vitest run",
56
- "typecheck": "tsc --noEmit",
57
- "release": "bumpp"
57
+ "typecheck": "tsc --noEmit"
58
58
  }
59
59
  }