@wpelevator/wp-release 0.10.0 → 0.12.0

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.
@@ -104,9 +104,6 @@ export declare const changesetTagArgs: {
104
104
  readonly untagged: {
105
105
  readonly type: "boolean";
106
106
  };
107
- readonly 'github-release': {
108
- readonly type: "boolean";
109
- };
110
107
  readonly since: {
111
108
  readonly type: "string";
112
109
  };
@@ -123,7 +120,6 @@ export interface ChangesetTagArgs {
123
120
  push: boolean;
124
121
  dryRun: boolean;
125
122
  untagged: boolean;
126
- githubRelease: boolean;
127
123
  since?: string;
128
124
  packages: string[];
129
125
  version?: string;
@@ -122,7 +122,6 @@ export const changesetTagArgs = {
122
122
  push: { type: 'boolean' },
123
123
  'dry-run': { type: 'boolean' },
124
124
  untagged: { type: 'boolean' },
125
- 'github-release': { type: 'boolean' },
126
125
  since: { type: 'string' },
127
126
  package: { type: 'string', multiple: true },
128
127
  version: { type: 'string' },
@@ -138,7 +137,6 @@ export function parseChangesetTagArgs(values) {
138
137
  push: getBoolean(values, 'push'),
139
138
  dryRun: getBoolean(values, 'dry-run'),
140
139
  untagged: getBoolean(values, 'untagged'),
141
- githubRelease: getBoolean(values, 'github-release'),
142
140
  since: getString(values, 'since'),
143
141
  packages: getStrings(values, 'package'),
144
142
  version: getString(values, 'version')?.trim(),
@@ -155,9 +153,6 @@ export function parseChangesetTagArgs(values) {
155
153
  if (undefined !== args.version && 1 !== args.packages.length) {
156
154
  throw new ValidationError('--version <version> requires exactly one --package <name>.');
157
155
  }
158
- if (args.githubRelease && !args.push) {
159
- throw new ValidationError('--github-release requires --push.');
160
- }
161
156
  if (args.untagged && args.push) {
162
157
  throw new ValidationError('--untagged cannot be combined with --push.');
163
158
  }
@@ -13,9 +13,6 @@ declare const _default: {
13
13
  readonly untagged: {
14
14
  readonly type: "boolean";
15
15
  };
16
- readonly 'github-release': {
17
- readonly type: "boolean";
18
- };
19
16
  readonly since: {
20
17
  readonly type: "string";
21
18
  };
@@ -3,7 +3,7 @@ import { parseChangesetTagArgs, changesetTagArgs } from "./changeset-args.js";
3
3
  import { getChangesetTagSummary, getTagStatus } from "../summary.js";
4
4
  export default {
5
5
  name: 'changeset-tag',
6
- usage: 'changeset-tag [--dry-run] [--untagged] [--since <ref>] [--package <name>] [--version <version>] [--push] [--github-release]',
6
+ usage: 'changeset-tag [--dry-run] [--untagged] [--since <ref>] [--package <name>] [--version <version>] [--push]',
7
7
  summary: 'Create missing release tags for configured package versions.',
8
8
  help: `Options:
9
9
  --dry-run List missing tags and their release notes without
@@ -13,16 +13,14 @@ export default {
13
13
  --package <name> Tag only this package (repeatable)
14
14
  --version <version> Fail unless the single --package is at this version;
15
15
  the version to tag for packages versioned by git tags
16
- --push Push newly created tags to origin
17
- --github-release Create a GitHub Release for each tag, marked as a
18
- pre-release for versions like 1.0.0-rc.1
16
+ --push Push newly created tags to origin, one at a time
19
17
 
20
- Tags are created only when absent, and GitHub Releases are created only when
21
- missing, so rerunning after a partial failure is safe. Before a tag is created,
22
- every configured version target must match the version. --github-release also
23
- requires --push. With --json or --github-output, --untagged lists the releases
24
- that still need a tag, for example to release each of them with a separate
25
- workflow.`,
18
+ Tags are created only when absent, so rerunning after a partial failure is
19
+ safe. Before a tag is created, every configured version target must match the
20
+ version. With --json or --github-output, each tag comes with the title, notes
21
+ and pre-release flag of its release, for a workflow step that creates the
22
+ GitHub Release. --untagged lists only the releases that still need a tag, for
23
+ example to release each of them with a separate workflow.`,
26
24
  options: changesetTagArgs,
27
25
  async run({ values, cwd, configFile, logger }) {
28
26
  const args = parseChangesetTagArgs(values);
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Original contents of the files that a versioning run changes, so that a
3
+ * failed run can put every file back the way it was.
4
+ */
5
+ export declare class FileJournal {
6
+ /** Original contents by file, undefined for files that didn't exist. */
7
+ private readonly files;
8
+ /**
9
+ * Remember the contents of a file before its first change. Later calls
10
+ * for the same file keep the original contents.
11
+ *
12
+ * @param file File about to change.
13
+ */
14
+ remember(file: string): Promise<void>;
15
+ /**
16
+ * Put the remembered files back in reverse order, removing the files that
17
+ * didn't exist. Every file is attempted, even after a failure.
18
+ *
19
+ * @return Errors of the files that couldn't be restored.
20
+ */
21
+ restore(): Promise<Error[]>;
22
+ }
@@ -0,0 +1,56 @@
1
+ import { readFile, rm, writeFile } from 'node:fs/promises';
2
+ /**
3
+ * Original contents of the files that a versioning run changes, so that a
4
+ * failed run can put every file back the way it was.
5
+ */
6
+ export class FileJournal {
7
+ /** Original contents by file, undefined for files that didn't exist. */
8
+ files = new Map();
9
+ /**
10
+ * Remember the contents of a file before its first change. Later calls
11
+ * for the same file keep the original contents.
12
+ *
13
+ * @param file File about to change.
14
+ */
15
+ async remember(file) {
16
+ if (this.files.has(file)) {
17
+ return;
18
+ }
19
+ try {
20
+ this.files.set(file, await readFile(file, 'utf8'));
21
+ }
22
+ catch (error) {
23
+ if ('ENOENT' !== error.code) {
24
+ throw error;
25
+ }
26
+ this.files.set(file, undefined);
27
+ }
28
+ }
29
+ /**
30
+ * Put the remembered files back in reverse order, removing the files that
31
+ * didn't exist. Every file is attempted, even after a failure.
32
+ *
33
+ * @return Errors of the files that couldn't be restored.
34
+ */
35
+ async restore() {
36
+ const errors = [];
37
+ for (const [file, contents] of [
38
+ ...this.files.entries(),
39
+ ].reverse()) {
40
+ try {
41
+ if (undefined === contents) {
42
+ await rm(file, { force: true });
43
+ }
44
+ else {
45
+ await writeFile(file, contents);
46
+ }
47
+ }
48
+ catch (error) {
49
+ errors.push(error instanceof Error
50
+ ? error
51
+ : new Error(String(error)));
52
+ }
53
+ }
54
+ return errors;
55
+ }
56
+ }
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export { isUrl, downloadFile } from './download.ts';
15
15
  export { readZipEntries, getZipEntryErrors, extractZip } from './unzip.ts';
16
16
  export { GIT_TAG_FORMAT, VersionMismatchError, getGitTagVersion, findConstantValues, findConstantDefinitions, findVersionMismatches, getVersionMismatchProblems, } from './version-check.ts';
17
17
  export { CHANGESET_BUMPS, parseChangeset, formatChangeset, formatChangelogEntries, formatChangelogList, getChangesetBump, getNextVersion, } from './changesets.ts';
18
- export { addChangeset, getChangesetPackages, getChangesetReleasePlan, getChangesetStatus, versionChangesets, tagChangesets, } from './changeset-release.ts';
18
+ export { ChangesetRelease, addChangeset, getChangesetPackages, getChangesetReleasePlan, getChangesetStatus, versionChangesets, tagChangesets, } from './changeset-release.ts';
19
19
  export { defineConfig, packageJsonVersion, composerJsonVersion, wordpressPluginVersion, wordpressThemeVersion, wordpressStableTag, gitTagVersion, phpConstantVersion, loadChangesetConfig, } from './changeset-config.ts';
20
20
  export { Svn, SvnError, createSvnRunner, parseStatus, toSvnPath, } from './svn.ts';
21
21
  export { syncDirectory, copyFileIfChanged } from './sync.ts';
@@ -42,13 +42,11 @@ export type { CreateZipInput } from './zip.ts';
42
42
  export type { ExtractZipInput, ZipEntryInfo, ZipEntryType } from './unzip.ts';
43
43
  export type { FindVersionMismatchesInput, GitTagInput, VersionCheckResult, VersionMismatch, } from './version-check.ts';
44
44
  export type { Changeset, ChangesetBump, ChangesetPackages, ChangesetConfig, ChangesetPackageType, ChangesetPackage, PackageRelease, VersionedRelease, ChangesetReleasePlan, } from './changesets.ts';
45
- export type { ChangesetRepository, ChangesetVersionInput, VersionChangesetsResult, ChangesetTagInput, ChangesetTagResult, } from './changeset-release.ts';
45
+ export type { ChangesetRepository, ChangesetReleaseOptions, ChangesetAddOptions, ChangesetVersionOptions, ChangesetTagOptions, ChangesetStatusOptions, ChangesetStatusResult, ChangesetVersionInput, VersionChangesetsResult, ChangesetTagInput, ChangesetTagResult, } from './changeset-release.ts';
46
46
  export type { WpReleaseConfig, ChangesetPackageGroup, PackageVersionConfig, PackageVersionSource, PackageVersionTarget, PackageIdSource, NextVersionInput, ReleaseCommit, ReleaseNotesInput, ChangelogEntryInput, DependentsChangelogInput, DependentsConfig, PackageJsonVersionOptions, ComposerJsonVersionOptions, WordPressVersionFileOptions, GitTagVersionOptions, PhpConstantVersionOptions, LoadChangesetConfigInput, } from './changeset-config.ts';
47
47
  export type { SvnCheckoutInput, SvnCommandInput, SvnCommandOutput, SvnCommitInput, SvnCopyInput, SvnDepth, SvnOptions, SvnPathsInput, SvnPropsetInput, SvnRunner, SvnStatusEntry, SvnStatusType, SvnUpdateInput, } from './svn.ts';
48
48
  export type { SyncDirectoryInput, SyncResult } from './sync.ts';
49
49
  export type { SummaryContext } from './summary.ts';
50
- export { getGitHubPullRequest } from './github.ts';
51
- export type { GitHubPullRequest, GetGitHubPullRequestInput } from './github.ts';
52
50
  export type { CheckoutPath, DeployResult } from './svn-deploy.ts';
53
51
  export type { GitCommandInput, GitCommandOutput, GitRunner } from './git.ts';
54
52
  export type { GitDeployInput, GitDeployOptions, GitDeployResult, } from './git-deploy.ts';
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ export { isUrl, downloadFile } from "./download.js";
15
15
  export { readZipEntries, getZipEntryErrors, extractZip } from "./unzip.js";
16
16
  export { GIT_TAG_FORMAT, VersionMismatchError, getGitTagVersion, findConstantValues, findConstantDefinitions, findVersionMismatches, getVersionMismatchProblems, } from "./version-check.js";
17
17
  export { CHANGESET_BUMPS, parseChangeset, formatChangeset, formatChangelogEntries, formatChangelogList, getChangesetBump, getNextVersion, } from "./changesets.js";
18
- export { addChangeset, getChangesetPackages, getChangesetReleasePlan, getChangesetStatus, versionChangesets, tagChangesets, } from "./changeset-release.js";
18
+ export { ChangesetRelease, addChangeset, getChangesetPackages, getChangesetReleasePlan, getChangesetStatus, versionChangesets, tagChangesets, } from "./changeset-release.js";
19
19
  export { defineConfig, packageJsonVersion, composerJsonVersion, wordpressPluginVersion, wordpressThemeVersion, wordpressStableTag, gitTagVersion, phpConstantVersion, loadChangesetConfig, } from "./changeset-config.js";
20
20
  export { Svn, SvnError, createSvnRunner, parseStatus, toSvnPath, } from "./svn.js";
21
21
  export { syncDirectory, copyFileIfChanged } from "./sync.js";
@@ -23,4 +23,3 @@ export { ASSET_MIME_TYPES, SvnDeploy } from "./svn-deploy.js";
23
23
  export { GitError, createGitRunner, redactUrls } from "./git.js";
24
24
  export { GitDeploy, isValidRefName, resolveGitDeployOptions, } from "./git-deploy.js";
25
25
  export { getGitDeployInputFromArgs } from "./commands/deploy-git.js";
26
- export { getGitHubPullRequest } from "./github.js";
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Read a JSON manifest that has to exist.
3
+ *
4
+ * @param file JSON file.
5
+ * @return Parsed object.
6
+ * @throws {ValidationError} If the file is missing or isn't valid JSON.
7
+ */
8
+ export declare function readJson(file: string): Promise<Record<string, unknown>>;
9
+ /**
10
+ * Read an optional JSON manifest.
11
+ *
12
+ * @param file JSON file.
13
+ * @return Parsed object, or undefined when the file doesn't exist.
14
+ */
15
+ export declare function readJsonIfExists(file: string): Promise<Record<string, unknown> | undefined>;
@@ -0,0 +1,35 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { ValidationError } from "./errors.js";
3
+ /**
4
+ * Read a JSON manifest that has to exist.
5
+ *
6
+ * @param file JSON file.
7
+ * @return Parsed object.
8
+ * @throws {ValidationError} If the file is missing or isn't valid JSON.
9
+ */
10
+ export async function readJson(file) {
11
+ try {
12
+ return JSON.parse(await readFile(file, 'utf8'));
13
+ }
14
+ catch (error) {
15
+ const message = error instanceof Error ? error.message : String(error);
16
+ throw new ValidationError(`Could not read JSON manifest ${file}: ${message}`);
17
+ }
18
+ }
19
+ /**
20
+ * Read an optional JSON manifest.
21
+ *
22
+ * @param file JSON file.
23
+ * @return Parsed object, or undefined when the file doesn't exist.
24
+ */
25
+ export async function readJsonIfExists(file) {
26
+ try {
27
+ return JSON.parse(await readFile(file, 'utf8'));
28
+ }
29
+ catch (error) {
30
+ if ('ENOENT' !== error.code) {
31
+ throw error;
32
+ }
33
+ return undefined;
34
+ }
35
+ }
@@ -1,6 +1,7 @@
1
1
  import { open, readdir, readFile } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { isErrorCode } from "./file-selection.js";
4
+ import { escapeRegExp } from "./regexp.js";
4
5
  /**
5
6
  * Number of bytes that WordPress reads from a file to parse its headers.
6
7
  */
@@ -112,9 +113,6 @@ export function findFileHeaderLine(contents, header) {
112
113
  export function getLineNumber(contents, index) {
113
114
  return contents.slice(0, index).split('\n').length;
114
115
  }
115
- function escapeRegExp(text) {
116
- return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
117
- }
118
116
  /**
119
117
  * Parse the headers of a readme.txt or readme.md, the "Key: value" lines
120
118
  * between the title and the first section. Markdown emphasis around the
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Escape text for use as a literal in a regular expression.
3
+ *
4
+ * @param text Text to match literally.
5
+ * @return Escaped pattern.
6
+ */
7
+ export declare function escapeRegExp(text: string): string;
package/dist/regexp.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Escape text for use as a literal in a regular expression.
3
+ *
4
+ * @param text Text to match literally.
5
+ * @return Escaped pattern.
6
+ */
7
+ export function escapeRegExp(text) {
8
+ return text.replaceAll(/[.*+?^${}()|[\]\\]/g, '\\$&');
9
+ }
@@ -0,0 +1,102 @@
1
+ import type { ReleaseCommit } from './changeset-config.ts';
2
+ import type { GitRunner } from './git.ts';
3
+ export interface ReleaseRepositoryOptions {
4
+ /** Repository root that relative paths resolve against. */
5
+ cwd: string;
6
+ /** Git runner, spawning git by default. */
7
+ runner?: GitRunner;
8
+ }
9
+ export interface ChangedFilesOptions {
10
+ /** Directory to limit the diff to. */
11
+ directory?: string;
12
+ /** Value of --diff-filter, like ACMR for files that still exist. */
13
+ diffFilter?: string;
14
+ }
15
+ /**
16
+ * The git queries and writes of a changeset release: tags, the commits of a
17
+ * package and the files changed since a ref.
18
+ *
19
+ * Every command runs through the runner, so that tests can replace git, and
20
+ * fails with a ValidationError that names the command.
21
+ */
22
+ export declare class ReleaseRepository {
23
+ readonly cwd: string;
24
+ readonly runner: GitRunner;
25
+ /**
26
+ * @param options Repository root and git runner.
27
+ */
28
+ constructor(options: ReleaseRepositoryOptions);
29
+ /**
30
+ * Run a git command in the repository. The repository is marked as a safe
31
+ * directory, because CI containers often check it out as another user.
32
+ *
33
+ * @param args Arguments after "git".
34
+ * @return Standard output.
35
+ * @throws {ValidationError} If the command fails.
36
+ */
37
+ run(args: string[]): Promise<string>;
38
+ /**
39
+ * Get the path of a file relative to the repository root, with forward
40
+ * slashes as git expects.
41
+ *
42
+ * @param file Absolute or relative file path.
43
+ * @return Relative path, empty for the root itself.
44
+ */
45
+ relativePath(file: string): string;
46
+ /**
47
+ * Check whether a tag exists.
48
+ *
49
+ * @param tag Tag name.
50
+ * @return Whether the tag exists.
51
+ */
52
+ tagExists(tag: string): Promise<boolean>;
53
+ /**
54
+ * List the tags that start with a prefix.
55
+ *
56
+ * @param prefix Tag prefix, like `plugins/alpha/`.
57
+ * @return Tag names.
58
+ */
59
+ listTags(prefix: string): Promise<string[]>;
60
+ /**
61
+ * Tag the current commit.
62
+ *
63
+ * @param tag Tag name.
64
+ */
65
+ createTag(tag: string): Promise<void>;
66
+ /**
67
+ * Push a tag to the origin remote.
68
+ *
69
+ * @param tag Tag name.
70
+ */
71
+ pushTag(tag: string): Promise<void>;
72
+ /**
73
+ * Find the commit that added a file.
74
+ *
75
+ * @param file File path.
76
+ * @return Commit, or undefined when the file isn't committed.
77
+ */
78
+ getAddedCommit(file: string): Promise<ReleaseCommit | undefined>;
79
+ /**
80
+ * List the commits of a revision range that changed a directory.
81
+ *
82
+ * @param revision Revision range, like `plugins/alpha/1.0.0..HEAD`.
83
+ * @param directory Directory the commits changed.
84
+ * @return Commits, newest first.
85
+ */
86
+ getDirectoryCommits(revision: string, directory: string): Promise<ReleaseCommit[]>;
87
+ /**
88
+ * List the files changed between the merge base of a ref and HEAD.
89
+ *
90
+ * @param since Base ref, like origin/main.
91
+ * @param options Directory and diff filter.
92
+ * @return Changed files relative to the repository root.
93
+ */
94
+ getChangedFiles(since: string, options?: ChangedFilesOptions): Promise<string[]>;
95
+ /**
96
+ * Run git log and parse the commits.
97
+ *
98
+ * @param args Arguments after the format option.
99
+ * @return Commits, newest first.
100
+ */
101
+ private getCommits;
102
+ }
@@ -0,0 +1,159 @@
1
+ import path from 'node:path';
2
+ import { ValidationError } from "./errors.js";
3
+ import { createGitRunner } from "./git.js";
4
+ /**
5
+ * The git queries and writes of a changeset release: tags, the commits of a
6
+ * package and the files changed since a ref.
7
+ *
8
+ * Every command runs through the runner, so that tests can replace git, and
9
+ * fails with a ValidationError that names the command.
10
+ */
11
+ export class ReleaseRepository {
12
+ cwd;
13
+ runner;
14
+ /**
15
+ * @param options Repository root and git runner.
16
+ */
17
+ constructor(options) {
18
+ this.cwd = path.resolve(options.cwd);
19
+ this.runner = options.runner ?? createGitRunner();
20
+ }
21
+ /**
22
+ * Run a git command in the repository. The repository is marked as a safe
23
+ * directory, because CI containers often check it out as another user.
24
+ *
25
+ * @param args Arguments after "git".
26
+ * @return Standard output.
27
+ * @throws {ValidationError} If the command fails.
28
+ */
29
+ async run(args) {
30
+ try {
31
+ const { stdout } = await this.runner({
32
+ args: ['-c', `safe.directory=${this.cwd}`, ...args],
33
+ cwd: this.cwd,
34
+ });
35
+ return stdout;
36
+ }
37
+ catch (error) {
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ throw new ValidationError(`Git command failed (${args.join(' ')}): ${message}`);
40
+ }
41
+ }
42
+ /**
43
+ * Get the path of a file relative to the repository root, with forward
44
+ * slashes as git expects.
45
+ *
46
+ * @param file Absolute or relative file path.
47
+ * @return Relative path, empty for the root itself.
48
+ */
49
+ relativePath(file) {
50
+ return path.relative(this.cwd, file).split(path.sep).join('/');
51
+ }
52
+ /**
53
+ * Check whether a tag exists.
54
+ *
55
+ * @param tag Tag name.
56
+ * @return Whether the tag exists.
57
+ */
58
+ async tagExists(tag) {
59
+ const output = await this.run(['tag', '--list', tag]);
60
+ return output.trim() === tag;
61
+ }
62
+ /**
63
+ * List the tags that start with a prefix.
64
+ *
65
+ * @param prefix Tag prefix, like `plugins/alpha/`.
66
+ * @return Tag names.
67
+ */
68
+ async listTags(prefix) {
69
+ const output = await this.run(['tag', '--list', `${prefix}*`]);
70
+ return output.trim().split(/\r?\n/).filter(Boolean);
71
+ }
72
+ /**
73
+ * Tag the current commit.
74
+ *
75
+ * @param tag Tag name.
76
+ */
77
+ async createTag(tag) {
78
+ await this.run(['tag', tag]);
79
+ }
80
+ /**
81
+ * Push a tag to the origin remote.
82
+ *
83
+ * @param tag Tag name.
84
+ */
85
+ async pushTag(tag) {
86
+ await this.run(['push', 'origin', tag]);
87
+ }
88
+ /**
89
+ * Find the commit that added a file.
90
+ *
91
+ * @param file File path.
92
+ * @return Commit, or undefined when the file isn't committed.
93
+ */
94
+ async getAddedCommit(file) {
95
+ const [commit] = await this.getCommits([
96
+ '--diff-filter=A',
97
+ '-1',
98
+ '--',
99
+ this.relativePath(file),
100
+ ]);
101
+ return commit;
102
+ }
103
+ /**
104
+ * List the commits of a revision range that changed a directory.
105
+ *
106
+ * @param revision Revision range, like `plugins/alpha/1.0.0..HEAD`.
107
+ * @param directory Directory the commits changed.
108
+ * @return Commits, newest first.
109
+ */
110
+ async getDirectoryCommits(revision, directory) {
111
+ return this.getCommits([
112
+ revision,
113
+ '--',
114
+ this.relativePath(directory) || '.',
115
+ ]);
116
+ }
117
+ /**
118
+ * List the files changed between the merge base of a ref and HEAD.
119
+ *
120
+ * @param since Base ref, like origin/main.
121
+ * @param options Directory and diff filter.
122
+ * @return Changed files relative to the repository root.
123
+ */
124
+ async getChangedFiles(since, options = {}) {
125
+ const output = await this.run([
126
+ 'diff',
127
+ '--name-only',
128
+ ...(options.diffFilter
129
+ ? [`--diff-filter=${options.diffFilter}`]
130
+ : []),
131
+ `${since}...HEAD`,
132
+ ...(options.directory
133
+ ? ['--', this.relativePath(options.directory)]
134
+ : []),
135
+ ]);
136
+ return output.trim().split(/\r?\n/).filter(Boolean);
137
+ }
138
+ /**
139
+ * Run git log and parse the commits.
140
+ *
141
+ * @param args Arguments after the format option.
142
+ * @return Commits, newest first.
143
+ */
144
+ async getCommits(args) {
145
+ const output = await this.run([
146
+ 'log',
147
+ '--format=%H%x1f%h%x1f%s',
148
+ ...args,
149
+ ]);
150
+ return output
151
+ .trim()
152
+ .split(/\r?\n/)
153
+ .filter(Boolean)
154
+ .map((line) => {
155
+ const [hash = '', shortHash = '', subject = ''] = line.split('\x1f');
156
+ return { hash, shortHash, subject };
157
+ });
158
+ }
159
+ }
@@ -0,0 +1,56 @@
1
+ import type { ChangesetConfig } from './changeset-config.ts';
2
+ import type { ConfiguredPackage } from './changeset-packages.ts';
3
+ import type { ReleaseRepository } from './release-repository.ts';
4
+ /**
5
+ * Version, tag and previous tag of a package release.
6
+ */
7
+ export interface ReleaseTag {
8
+ /** Released version. */
9
+ version: string;
10
+ /** Release tag. */
11
+ tag: string;
12
+ /** Tag of the previous release, if any. */
13
+ previousTag?: string;
14
+ }
15
+ /**
16
+ * Pick the packages to tag.
17
+ *
18
+ * @param packages Configured packages.
19
+ * @param names Packages passed with --package, empty for all.
20
+ * @param version Expected version passed with --version, if any.
21
+ * @return Selected packages in the configured order.
22
+ * @throws {ValidationError} For unknown packages, or an expected version without a single package.
23
+ */
24
+ export declare function selectTagPackages(packages: ConfiguredPackage[], names: string[], version?: string): ConfiguredPackage[];
25
+ /**
26
+ * Get the version to tag. Packages versioned by their git tags have no
27
+ * version file, so the expected version is the version to tag, or else the
28
+ * latest CHANGELOG.md version.
29
+ *
30
+ * @param pkg Configured package.
31
+ * @param expected Expected version from --version, if any.
32
+ * @return Version to tag.
33
+ */
34
+ export declare function getTagVersion(pkg: ConfiguredPackage, expected?: string): Promise<string>;
35
+ /**
36
+ * Find the tag of the newest release before a version.
37
+ *
38
+ * @param repository Repository with the tags.
39
+ * @param prefix Tag prefix of the package, like `plugins/alpha/`.
40
+ * @param version Version being released.
41
+ * @return Previous tag, or undefined for the first release.
42
+ */
43
+ export declare function getPreviousTag(repository: ReleaseRepository, prefix: string, version: string): Promise<string | undefined>;
44
+ /**
45
+ * Build the release notes of a tag from its CHANGELOG.md section, or from the
46
+ * commits since the previous release without one, with the configured
47
+ * formatter.
48
+ *
49
+ * @param repository Repository with the release commits.
50
+ * @param config Repository release configuration.
51
+ * @param pkg Released package.
52
+ * @param release Version, tag and previous tag of the release.
53
+ * @param end Commit of the release: the tag, or HEAD before tagging.
54
+ * @return Release notes.
55
+ */
56
+ export declare function getReleaseNotes(repository: ReleaseRepository, config: ChangesetConfig, pkg: ConfiguredPackage, release: ReleaseTag, end: string): Promise<string>;