@wpelevator/wp-release 0.11.0 → 0.13.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.
Files changed (51) hide show
  1. package/README.md +95 -13
  2. package/dist/changeset-config.d.ts +86 -2
  3. package/dist/changeset-config.js +101 -6
  4. package/dist/changeset-dependents.d.ts +19 -8
  5. package/dist/changeset-dependents.js +96 -34
  6. package/dist/changeset-files.d.ts +6 -5
  7. package/dist/changeset-files.js +7 -5
  8. package/dist/changeset-packages.d.ts +45 -8
  9. package/dist/changeset-packages.js +73 -14
  10. package/dist/changeset-prompt.d.ts +119 -0
  11. package/dist/changeset-prompt.js +203 -0
  12. package/dist/changeset-release.d.ts +38 -3
  13. package/dist/changeset-release.js +88 -11
  14. package/dist/changesets.d.ts +6 -2
  15. package/dist/changesets.js +18 -12
  16. package/dist/cli.d.ts +7 -1
  17. package/dist/cli.js +18 -5
  18. package/dist/commands/changeset-add.d.ts +5 -2
  19. package/dist/commands/changeset-add.js +108 -9
  20. package/dist/commands/changeset-args.d.ts +24 -5
  21. package/dist/commands/changeset-args.js +57 -14
  22. package/dist/commands/changeset-status.d.ts +2 -0
  23. package/dist/commands/changeset-tag.js +2 -1
  24. package/dist/commands/changeset-version.d.ts +6 -0
  25. package/dist/commands/changeset-version.js +15 -3
  26. package/dist/commands/command.d.ts +3 -0
  27. package/dist/commands/deploy-git.d.ts +24 -4
  28. package/dist/commands/deploy-git.js +56 -3
  29. package/dist/commands/deploy-svn.d.ts +24 -4
  30. package/dist/commands/deploy-svn.js +56 -2
  31. package/dist/commands/package-deploys.d.ts +78 -0
  32. package/dist/commands/package-deploys.js +108 -0
  33. package/dist/git-deploy.d.ts +32 -0
  34. package/dist/git-deploy.js +57 -1
  35. package/dist/index.d.ts +5 -4
  36. package/dist/index.js +2 -2
  37. package/dist/package-deploy.d.ts +105 -0
  38. package/dist/package-deploy.js +288 -0
  39. package/dist/release-repository.d.ts +14 -2
  40. package/dist/release-repository.js +46 -7
  41. package/dist/release-tags.d.ts +3 -1
  42. package/dist/release-tags.js +5 -2
  43. package/dist/tag-format.d.ts +3 -3
  44. package/dist/tag-format.js +1 -1
  45. package/dist/version-files.d.ts +2 -1
  46. package/dist/version-files.js +12 -7
  47. package/dist/versions.d.ts +28 -3
  48. package/dist/versions.js +84 -9
  49. package/package.json +1 -1
  50. package/dist/github.d.ts +0 -24
  51. package/dist/github.js +0 -30
@@ -11,6 +11,8 @@ export interface ChangedFilesOptions {
11
11
  directory?: string;
12
12
  /** Value of --diff-filter, like ACMR for files that still exist. */
13
13
  diffFilter?: string;
14
+ /** Whether to include the uncommitted and untracked files of the working tree. */
15
+ uncommitted?: boolean;
14
16
  }
15
17
  /**
16
18
  * The git queries and writes of a changeset release: tags, the commits of a
@@ -85,13 +87,23 @@ export declare class ReleaseRepository {
85
87
  */
86
88
  getDirectoryCommits(revision: string, directory: string): Promise<ReleaseCommit[]>;
87
89
  /**
88
- * List the files changed between the merge base of a ref and HEAD.
90
+ * List the files changed between the merge base of a ref and HEAD, or the
91
+ * working tree with the uncommitted option, which adds untracked files.
89
92
  *
90
93
  * @param since Base ref, like origin/main.
91
- * @param options Directory and diff filter.
94
+ * @param options Directory, diff filter and uncommitted files.
92
95
  * @return Changed files relative to the repository root.
93
96
  */
94
97
  getChangedFiles(since: string, options?: ChangedFilesOptions): Promise<string[]>;
98
+ /**
99
+ * Read a file as of the merge base of a ref and HEAD, the side that
100
+ * getChangedFiles() diffs against.
101
+ *
102
+ * @param since Base ref, like origin/main.
103
+ * @param file Absolute or relative file path.
104
+ * @return File contents, or undefined when the file doesn't exist there.
105
+ */
106
+ readFileAtMergeBase(since: string, file: string): Promise<string | undefined>;
95
107
  /**
96
108
  * Run git log and parse the commits.
97
109
  *
@@ -115,25 +115,64 @@ export class ReleaseRepository {
115
115
  ]);
116
116
  }
117
117
  /**
118
- * List the files changed between the merge base of a ref and HEAD.
118
+ * List the files changed between the merge base of a ref and HEAD, or the
119
+ * working tree with the uncommitted option, which adds untracked files.
119
120
  *
120
121
  * @param since Base ref, like origin/main.
121
- * @param options Directory and diff filter.
122
+ * @param options Directory, diff filter and uncommitted files.
122
123
  * @return Changed files relative to the repository root.
123
124
  */
124
125
  async getChangedFiles(since, options = {}) {
126
+ const pathspec = options.directory
127
+ ? ['--', this.relativePath(options.directory)]
128
+ : [];
129
+ const range = options.uncommitted
130
+ ? (await this.run(['merge-base', since, 'HEAD'])).trim()
131
+ : `${since}...HEAD`;
125
132
  const output = await this.run([
126
133
  'diff',
127
134
  '--name-only',
128
135
  ...(options.diffFilter
129
136
  ? [`--diff-filter=${options.diffFilter}`]
130
137
  : []),
131
- `${since}...HEAD`,
132
- ...(options.directory
133
- ? ['--', this.relativePath(options.directory)]
134
- : []),
138
+ range,
139
+ ...pathspec,
135
140
  ]);
136
- return output.trim().split(/\r?\n/).filter(Boolean);
141
+ const untracked = options.uncommitted
142
+ ? await this.run([
143
+ 'ls-files',
144
+ '--others',
145
+ '--exclude-standard',
146
+ '--full-name',
147
+ ...pathspec,
148
+ ])
149
+ : '';
150
+ const files = `${output}\n${untracked}`
151
+ .split(/\r?\n/)
152
+ .filter(Boolean);
153
+ return [...new Set(files)];
154
+ }
155
+ /**
156
+ * Read a file as of the merge base of a ref and HEAD, the side that
157
+ * getChangedFiles() diffs against.
158
+ *
159
+ * @param since Base ref, like origin/main.
160
+ * @param file Absolute or relative file path.
161
+ * @return File contents, or undefined when the file doesn't exist there.
162
+ */
163
+ async readFileAtMergeBase(since, file) {
164
+ const base = (await this.run(['merge-base', since, 'HEAD'])).trim();
165
+ const relative = this.relativePath(file);
166
+ const listed = await this.run([
167
+ 'ls-tree',
168
+ '--name-only',
169
+ base,
170
+ '--',
171
+ relative,
172
+ ]);
173
+ return '' === listed.trim()
174
+ ? undefined
175
+ : this.run(['show', `${base}:${relative}`]);
137
176
  }
138
177
  /**
139
178
  * Run git log and parse the commits.
@@ -33,7 +33,9 @@ export declare function selectTagPackages(packages: ConfiguredPackage[], names:
33
33
  */
34
34
  export declare function getTagVersion(pkg: ConfiguredPackage, expected?: string): Promise<string>;
35
35
  /**
36
- * Find the tag of the newest release before a version.
36
+ * Find the tag of the newest release before a version. A stable release
37
+ * skips the pre-releases before it, so that it compares with the previous
38
+ * stable release.
37
39
  *
38
40
  * @param repository Repository with the tags.
39
41
  * @param prefix Tag prefix of the package, like `plugins/alpha/`.
@@ -1,7 +1,7 @@
1
1
  import { readChangelogSection, getLatestChangelogVersion, } from "./changelog.js";
2
2
  import { assertKnownPackages, toChangesetPackage, } from "./changeset-packages.js";
3
3
  import { ValidationError } from "./errors.js";
4
- import { compareVersions, isVersion } from "./versions.js";
4
+ import { compareVersions, isPrerelease, isVersion } from "./versions.js";
5
5
  /**
6
6
  * Pick the packages to tag.
7
7
  *
@@ -37,7 +37,9 @@ export async function getTagVersion(pkg, expected) {
37
37
  (await getLatestChangelogVersion(pkg.directory, pkg.currentVersion)));
38
38
  }
39
39
  /**
40
- * Find the tag of the newest release before a version.
40
+ * Find the tag of the newest release before a version. A stable release
41
+ * skips the pre-releases before it, so that it compares with the previous
42
+ * stable release.
41
43
  *
42
44
  * @param repository Repository with the tags.
43
45
  * @param prefix Tag prefix of the package, like `plugins/alpha/`.
@@ -50,6 +52,7 @@ export async function getPreviousTag(repository, prefix, version) {
50
52
  .filter((tag) => tag.startsWith(prefix))
51
53
  .map((tag) => ({ tag, version: tag.slice(prefix.length) }))
52
54
  .filter((item) => isVersion(item.version) &&
55
+ (isPrerelease(version) || !isPrerelease(item.version)) &&
53
56
  compareVersions(item.version, version) < 0)
54
57
  .sort((a, b) => compareVersions(b.version, a.version))[0]?.tag;
55
58
  }
@@ -1,13 +1,13 @@
1
- import type { ConfiguredPackage } from './changeset-packages.ts';
1
+ import type { ConfiguredDeployPackage } from './changeset-packages.ts';
2
2
  /**
3
3
  * Format the tag of a package release.
4
4
  *
5
5
  * @param format Tag format with {name}, {slug}, {path}, {type} and {version}.
6
- * @param pkg Configured package.
6
+ * @param pkg Configured package, with or without a version.
7
7
  * @param version Released version, empty for the tag prefix of the package.
8
8
  * @return Tag name.
9
9
  */
10
- export declare function formatTag(format: string, pkg: ConfiguredPackage, version: string): string;
10
+ export declare function formatTag(format: string, pkg: ConfiguredDeployPackage, version: string): string;
11
11
  /**
12
12
  * Format the tag prefix of a package before its name is known, for packages
13
13
  * versioned by their git tags.
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  * Format the tag of a package release.
4
4
  *
5
5
  * @param format Tag format with {name}, {slug}, {path}, {type} and {version}.
6
- * @param pkg Configured package.
6
+ * @param pkg Configured package, with or without a version.
7
7
  * @param version Released version, empty for the tag prefix of the package.
8
8
  * @return Tag name.
9
9
  */
@@ -26,7 +26,8 @@ export declare function readVersion(repository: ReleaseRepository, directory: st
26
26
  export declare function writeVersion(directory: string, descriptor: PackageVersionTarget, version: string, journal: FileJournal): Promise<void>;
27
27
  /**
28
28
  * Check that every version target of a package has the expected version.
29
- * Optional targets that are absent are skipped.
29
+ * Optional targets that are absent are skipped, and so is the readme Stable
30
+ * tag of a pre-release.
30
31
  *
31
32
  * @param repository Repository, for versions stored as git tags.
32
33
  * @param pkg Configured package.
@@ -6,7 +6,7 @@ import { findMainPluginFile } from "./package-meta.js";
6
6
  import { escapeRegExp } from "./regexp.js";
7
7
  import { formatTemplatePrefix } from "./tag-format.js";
8
8
  import { findConstantValues } from "./version-check.js";
9
- import { compareVersions } from "./versions.js";
9
+ import { compareVersions, isPrerelease } from "./versions.js";
10
10
  /**
11
11
  * Read the current version of a package from its configured source.
12
12
  *
@@ -32,7 +32,7 @@ export async function readVersion(repository, directory, descriptor, relativePat
32
32
  const pattern = descriptor.pattern ?? '{path}/{version}';
33
33
  const tags = await repository.listTags(formatTemplatePrefix(pattern, relativePath, tagType));
34
34
  const versions = tags
35
- .map((tag) => tag.match(/(?:^|\/|v)(\d+\.\d+\.\d+)$/)?.[1])
35
+ .map((tag) => tag.match(/(?:^|\/|v)(\d+(?:\.\d+){1,3})$/)?.[1])
36
36
  .filter((item) => Boolean(item));
37
37
  versions.sort((a, b) => compareVersions(b, a));
38
38
  if (versions[0]) {
@@ -99,9 +99,12 @@ export async function writeVersion(directory, descriptor, version, journal) {
99
99
  await writeFile(file, updated);
100
100
  return;
101
101
  }
102
+ // The readme Stable tag keeps the last stable version for a pre-release,
103
+ // since WordPress.org offers the stable tag to every site.
102
104
  if ('wordpress-stable-tag' === descriptor.kind &&
103
- descriptor.ifPresent &&
104
- !(await versionFileExists(directory, descriptor.kind, descriptor.file))) {
105
+ (isPrerelease(version) ||
106
+ (descriptor.ifPresent &&
107
+ !(await versionFileExists(directory, descriptor.kind, descriptor.file))))) {
105
108
  return;
106
109
  }
107
110
  const file = path.join(directory, await getVersionFile(directory, descriptor.kind, descriptor.file));
@@ -116,7 +119,8 @@ export async function writeVersion(directory, descriptor, version, journal) {
116
119
  }
117
120
  /**
118
121
  * Check that every version target of a package has the expected version.
119
- * Optional targets that are absent are skipped.
122
+ * Optional targets that are absent are skipped, and so is the readme Stable
123
+ * tag of a pre-release.
120
124
  *
121
125
  * @param repository Repository, for versions stored as git tags.
122
126
  * @param pkg Configured package.
@@ -132,8 +136,9 @@ export async function verifyVersionTargets(repository, pkg, expected) {
132
136
  actual = undefined;
133
137
  }
134
138
  else if ('wordpress-stable-tag' === target.kind &&
135
- target.ifPresent &&
136
- !(await versionFileExists(pkg.directory, target.kind, target.file))) {
139
+ (isPrerelease(expected) ||
140
+ (target.ifPresent &&
141
+ !(await versionFileExists(pkg.directory, target.kind, target.file))))) {
137
142
  actual = undefined;
138
143
  }
139
144
  else {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Check whether a string is a SemVer version, like 1.2.0 or 1.2.0-rc.1.
2
+ * Check whether a string is a version, like 1.2.0, 1.2.0-rc.1, 2.1 or 1.2.3.4.
3
3
  *
4
4
  * @param version Version.
5
5
  * @return Whether the version is valid.
@@ -15,11 +15,36 @@ export declare function isPrerelease(version: string): boolean;
15
15
  /**
16
16
  * Compare two versions with SemVer precedence, where a pre-release like
17
17
  * 1.0.0-rc.1 comes before 1.0.0. Unlike the semver package, it doesn't throw
18
- * for versions outside SemVer, like the 1.2 of a custom nextVersion
19
- * strategy: missing parts count as 0.
18
+ * for versions outside SemVer, like 1.2 or 1.2.3.4: every part is compared,
19
+ * and missing parts count as 0.
20
20
  *
21
21
  * @param left Version.
22
22
  * @param right Version to compare with.
23
23
  * @return Negative when left is lower, positive when higher, otherwise 0.
24
24
  */
25
25
  export declare function compareVersions(left: string, right: string): number;
26
+ /**
27
+ * Get the pre-release version of a stable release version, like 1.3.0-rc.1
28
+ * for 1.3.0. A pre-release with a number, like rc.2, is used as is. Without a
29
+ * number, like rc, the number is one above the highest existing pre-release
30
+ * of that identifier and stable version, so the first one is rc.1.
31
+ *
32
+ * @param stable Stable version of the release, like 1.3.0.
33
+ * @param prerelease Pre-release identifier with an optional number, like rc or rc.2.
34
+ * @param existing Existing versions of the package, like those of its tags.
35
+ * @return Pre-release version.
36
+ * @throws {ValidationError} For an invalid input, or a version that exists.
37
+ */
38
+ export declare function getPrereleaseVersion(stable: string, prerelease: string, existing: string[]): string;
39
+ /**
40
+ * Get the snapshot version of a stable release version, like
41
+ * 1.3.0-pr-251.20261012183000 for 1.3.0: the identifier and the UTC time,
42
+ * which keeps every snapshot unique and sorts them by time.
43
+ *
44
+ * @param stable Stable version of the release, like 1.3.0.
45
+ * @param id Snapshot identifier, like pr-251.
46
+ * @param time Time of the snapshot.
47
+ * @return Snapshot version.
48
+ * @throws {ValidationError} For an invalid identifier or a version that isn't stable.
49
+ */
50
+ export declare function getSnapshotVersion(stable: string, id: string, time: Date): string;
package/dist/versions.js CHANGED
@@ -1,9 +1,20 @@
1
+ import { ValidationError } from "./errors.js";
1
2
  /**
2
- * Stable or pre-release SemVer version without build metadata.
3
+ * Stable or pre-release version without build metadata: SemVer x.y.z, or the
4
+ * x.y and x.y.z.w versions common in WordPress plugins.
3
5
  */
4
- const VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?$/;
6
+ const VERSION_PATTERN = /^(?:0|[1-9]\d*)(?:\.(?:0|[1-9]\d*)){1,3}(?:-([0-9A-Za-z.-]+))?$/;
5
7
  /**
6
- * Check whether a string is a SemVer version, like 1.2.0 or 1.2.0-rc.1.
8
+ * Pre-release input: an identifier with an optional number, like rc or rc.1.
9
+ */
10
+ const PRERELEASE_INPUT_PATTERN = /^([A-Za-z][0-9A-Za-z-]*)(?:\.(0|[1-9]\d*))?$/;
11
+ /**
12
+ * Snapshot identifier: dot-separated SemVer pre-release identifiers that start
13
+ * with a letter, like pr-251 or pr-251.g1a2b3c4.
14
+ */
15
+ const SNAPSHOT_ID_PATTERN = /^[A-Za-z][0-9A-Za-z-]*(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*$/;
16
+ /**
17
+ * Check whether a string is a version, like 1.2.0, 1.2.0-rc.1, 2.1 or 1.2.3.4.
7
18
  *
8
19
  * @param version Version.
9
20
  * @return Whether the version is valid.
@@ -18,13 +29,13 @@ export function isVersion(version) {
18
29
  * @return Whether the version is a valid pre-release.
19
30
  */
20
31
  export function isPrerelease(version) {
21
- return Boolean(VERSION_PATTERN.exec(version)?.[4]);
32
+ return Boolean(VERSION_PATTERN.exec(version)?.[1]);
22
33
  }
23
34
  /**
24
35
  * Compare two versions with SemVer precedence, where a pre-release like
25
36
  * 1.0.0-rc.1 comes before 1.0.0. Unlike the semver package, it doesn't throw
26
- * for versions outside SemVer, like the 1.2 of a custom nextVersion
27
- * strategy: missing parts count as 0.
37
+ * for versions outside SemVer, like 1.2 or 1.2.3.4: every part is compared,
38
+ * and missing parts count as 0.
28
39
  *
29
40
  * @param left Version.
30
41
  * @param right Version to compare with.
@@ -35,9 +46,7 @@ export function compareVersions(left, right) {
35
46
  const [rightCore = '', rightPre] = splitPrerelease(right);
36
47
  const a = leftCore.split('.').map(Number);
37
48
  const b = rightCore.split('.').map(Number);
38
- const core = (a[0] ?? 0) - (b[0] ?? 0) ||
39
- (a[1] ?? 0) - (b[1] ?? 0) ||
40
- (a[2] ?? 0) - (b[2] ?? 0);
49
+ const core = compareParts(a, b);
41
50
  if (core || leftPre === rightPre) {
42
51
  return core;
43
52
  }
@@ -46,6 +55,14 @@ export function compareVersions(left, right) {
46
55
  }
47
56
  return comparePrerelease(leftPre.split('.'), rightPre.split('.'));
48
57
  }
58
+ function compareParts(left, right) {
59
+ const [a, ...leftRest] = left;
60
+ const [b, ...rightRest] = right;
61
+ if (undefined === a && undefined === b) {
62
+ return 0;
63
+ }
64
+ return (a ?? 0) - (b ?? 0) || compareParts(leftRest, rightRest);
65
+ }
49
66
  function splitPrerelease(version) {
50
67
  const index = version.indexOf('-');
51
68
  return -1 === index
@@ -72,3 +89,61 @@ function compareIdentifier(a, b) {
72
89
  }
73
90
  return Number(a > b) - Number(a < b);
74
91
  }
92
+ /**
93
+ * Get the pre-release version of a stable release version, like 1.3.0-rc.1
94
+ * for 1.3.0. A pre-release with a number, like rc.2, is used as is. Without a
95
+ * number, like rc, the number is one above the highest existing pre-release
96
+ * of that identifier and stable version, so the first one is rc.1.
97
+ *
98
+ * @param stable Stable version of the release, like 1.3.0.
99
+ * @param prerelease Pre-release identifier with an optional number, like rc or rc.2.
100
+ * @param existing Existing versions of the package, like those of its tags.
101
+ * @return Pre-release version.
102
+ * @throws {ValidationError} For an invalid input, or a version that exists.
103
+ */
104
+ export function getPrereleaseVersion(stable, prerelease, existing) {
105
+ const match = PRERELEASE_INPUT_PATTERN.exec(prerelease);
106
+ if (!match) {
107
+ throw new ValidationError(`Invalid pre-release "${prerelease}"; expected an identifier with an optional number, like rc or rc.1.`);
108
+ }
109
+ if (!isVersion(stable) || isPrerelease(stable)) {
110
+ throw new ValidationError(`Cannot release "${stable}" as a pre-release: expected a stable version.`);
111
+ }
112
+ const identifier = match[1] ?? '';
113
+ const version = match[2]
114
+ ? `${stable}-${prerelease}`
115
+ : `${stable}-${identifier}.${getNextPrereleaseNumber(`${stable}-${identifier}.`, existing)}`;
116
+ if (existing.includes(version)) {
117
+ throw new ValidationError(`Version ${version} already exists; pass a pre-release without a number to release the next one.`);
118
+ }
119
+ return version;
120
+ }
121
+ function getNextPrereleaseNumber(prefix, existing) {
122
+ const numbers = existing
123
+ .filter((version) => version.startsWith(prefix))
124
+ .map((version) => version.slice(prefix.length))
125
+ .filter((number) => /^\d+$/.test(number))
126
+ .map(Number);
127
+ return Math.max(0, ...numbers) + 1;
128
+ }
129
+ /**
130
+ * Get the snapshot version of a stable release version, like
131
+ * 1.3.0-pr-251.20261012183000 for 1.3.0: the identifier and the UTC time,
132
+ * which keeps every snapshot unique and sorts them by time.
133
+ *
134
+ * @param stable Stable version of the release, like 1.3.0.
135
+ * @param id Snapshot identifier, like pr-251.
136
+ * @param time Time of the snapshot.
137
+ * @return Snapshot version.
138
+ * @throws {ValidationError} For an invalid identifier or a version that isn't stable.
139
+ */
140
+ export function getSnapshotVersion(stable, id, time) {
141
+ if (!SNAPSHOT_ID_PATTERN.test(id)) {
142
+ throw new ValidationError(`Invalid snapshot "${id}"; expected SemVer pre-release identifiers that start with a letter, like pr-251.`);
143
+ }
144
+ if (!isVersion(stable) || isPrerelease(stable)) {
145
+ throw new ValidationError(`Cannot release "${stable}" as a snapshot: expected a stable version.`);
146
+ }
147
+ const timestamp = time.toISOString().replace(/\D/g, '').slice(0, 14);
148
+ return `${stable}-${id}.${timestamp}`;
149
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wpelevator/wp-release",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Package, checksum, sign, verify and version-check WordPress plugins and themes, and deploy plugins to WordPress.org SVN",
5
5
  "license": "MIT",
6
6
  "repository": {
package/dist/github.d.ts DELETED
@@ -1,24 +0,0 @@
1
- /**
2
- * A GitHub pull request of a commit.
3
- */
4
- export interface GitHubPullRequest {
5
- number: number;
6
- url: string;
7
- /** GitHub handle of the pull request author, without the @. */
8
- author: string;
9
- }
10
- export interface GetGitHubPullRequestInput {
11
- /** Directory of the repository, whose GitHub remote `gh` uses. */
12
- cwd: string;
13
- /** Commit hash. */
14
- commit: string;
15
- }
16
- /**
17
- * Find the pull request that merged a commit, with the authenticated `gh`
18
- * command line client.
19
- *
20
- * @param input Repository directory and commit.
21
- * @return The first pull request of the commit, or undefined without one.
22
- * @throws {ValidationError} If `gh` fails, like without authentication.
23
- */
24
- export declare function getGitHubPullRequest(input: GetGitHubPullRequestInput): Promise<GitHubPullRequest | undefined>;
package/dist/github.js DELETED
@@ -1,30 +0,0 @@
1
- import { execFile } from 'node:child_process';
2
- import { promisify } from 'node:util';
3
- import { ValidationError } from "./errors.js";
4
- const execFileAsync = promisify(execFile);
5
- /**
6
- * Find the pull request that merged a commit, with the authenticated `gh`
7
- * command line client.
8
- *
9
- * @param input Repository directory and commit.
10
- * @return The first pull request of the commit, or undefined without one.
11
- * @throws {ValidationError} If `gh` fails, like without authentication.
12
- */
13
- export async function getGitHubPullRequest(input) {
14
- let stdout;
15
- try {
16
- ({ stdout } = await execFileAsync('gh', ['api', `repos/{owner}/{repo}/commits/${input.commit}/pulls`], { cwd: input.cwd }));
17
- }
18
- catch (error) {
19
- const message = error instanceof Error ? error.message : String(error);
20
- throw new ValidationError(`Could not find the pull request of commit ${input.commit}: ${message}`);
21
- }
22
- const [pullRequest] = JSON.parse(stdout);
23
- return pullRequest
24
- ? {
25
- number: pullRequest.number,
26
- url: pullRequest.html_url,
27
- author: pullRequest.user?.login ?? '',
28
- }
29
- : undefined;
30
- }