@wpelevator/wp-release 0.12.0 → 0.14.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.
- package/README.md +150 -19
- package/dist/changeset-config.d.ts +91 -5
- package/dist/changeset-config.js +108 -11
- package/dist/changeset-dependents.d.ts +19 -8
- package/dist/changeset-dependents.js +96 -34
- package/dist/changeset-files.d.ts +6 -5
- package/dist/changeset-files.js +7 -5
- package/dist/changeset-packages.d.ts +55 -8
- package/dist/changeset-packages.js +85 -14
- package/dist/changeset-prompt.d.ts +119 -0
- package/dist/changeset-prompt.js +203 -0
- package/dist/changeset-release.d.ts +43 -5
- package/dist/changeset-release.js +99 -16
- package/dist/changesets.d.ts +6 -2
- package/dist/changesets.js +18 -12
- package/dist/cli.d.ts +7 -1
- package/dist/cli.js +51 -14
- package/dist/commands/args.d.ts +0 -21
- package/dist/commands/args.js +1 -35
- package/dist/commands/changeset-add.d.ts +5 -2
- package/dist/commands/changeset-add.js +109 -9
- package/dist/commands/changeset-args.d.ts +24 -5
- package/dist/commands/changeset-args.js +57 -14
- package/dist/commands/changeset-status.d.ts +3 -1
- package/dist/commands/changeset-status.js +2 -1
- package/dist/commands/changeset-tag.d.ts +1 -1
- package/dist/commands/changeset-tag.js +6 -3
- package/dist/commands/changeset-version.d.ts +7 -1
- package/dist/commands/changeset-version.js +17 -4
- package/dist/commands/checksums.js +2 -2
- package/dist/commands/command.d.ts +5 -0
- package/dist/commands/deploy-git.d.ts +24 -4
- package/dist/commands/deploy-git.js +57 -3
- package/dist/commands/deploy-svn.d.ts +24 -4
- package/dist/commands/deploy-svn.js +57 -2
- package/dist/commands/keygen.d.ts +3 -0
- package/dist/commands/keygen.js +6 -1
- package/dist/commands/package-deploys.d.ts +86 -0
- package/dist/commands/package-deploys.js +113 -0
- package/dist/commands/sign.d.ts +19 -1
- package/dist/commands/sign.js +47 -12
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.js +43 -24
- package/dist/commands/zip.d.ts +12 -8
- package/dist/commands/zip.js +135 -78
- package/dist/ed25519.d.ts +25 -0
- package/dist/ed25519.js +44 -0
- package/dist/file-selection.d.ts +21 -0
- package/dist/file-selection.js +35 -0
- package/dist/git-deploy.d.ts +32 -0
- package/dist/git-deploy.js +57 -1
- package/dist/git.d.ts +17 -0
- package/dist/git.js +23 -0
- package/dist/index.d.ts +13 -5
- package/dist/index.js +7 -3
- package/dist/minisign.d.ts +41 -0
- package/dist/minisign.js +128 -0
- package/dist/package-deploy.d.ts +133 -0
- package/dist/package-deploy.js +323 -0
- package/dist/package-zip.d.ts +52 -0
- package/dist/package-zip.js +78 -0
- package/dist/release-repository.d.ts +18 -5
- package/dist/release-repository.js +51 -11
- package/dist/release-tags.d.ts +3 -1
- package/dist/release-tags.js +5 -2
- package/dist/signing.d.ts +64 -9
- package/dist/signing.js +113 -40
- package/dist/ssh-signature.d.ts +43 -0
- package/dist/ssh-signature.js +156 -0
- package/dist/summary.d.ts +3 -3
- package/dist/summary.js +2 -2
- package/dist/tag-format.d.ts +23 -14
- package/dist/tag-format.js +26 -40
- package/dist/version-files.d.ts +8 -8
- package/dist/version-files.js +22 -18
- package/dist/versions.d.ts +28 -3
- package/dist/versions.js +84 -9
- package/package.json +2 -2
|
@@ -2,6 +2,7 @@ import type { ChangesetConfig, DependentsConfig } from './changeset-config.ts';
|
|
|
2
2
|
import type { ChangedPackages, ConfiguredPackage } from './changeset-packages.ts';
|
|
3
3
|
import type { Changeset, ChangesetPackage, ChangesetReleasePlan, PackageRelease } from './changesets.ts';
|
|
4
4
|
import type { FileJournal } from './file-journal.ts';
|
|
5
|
+
import type { ReleaseRepository } from './release-repository.ts';
|
|
5
6
|
/**
|
|
6
7
|
* A declared dependency of a package on another configured package.
|
|
7
8
|
*/
|
|
@@ -67,16 +68,26 @@ export declare function assertDependentsSourcesReleased(plan: ChangesetReleasePl
|
|
|
67
68
|
* with its sources, which the release pull request already announces when
|
|
68
69
|
* the changesets of the diff release one of them. Exempting its package
|
|
69
70
|
* manifest pin change keeps the check from demanding an entry for what
|
|
70
|
-
* versioning rewrites anyway
|
|
71
|
-
*
|
|
71
|
+
* versioning rewrites anyway. Any other change, like documentation, code or
|
|
72
|
+
* another manifest field or dependency, still needs its own changeset.
|
|
72
73
|
*
|
|
73
|
-
* @param
|
|
74
|
-
* @param
|
|
75
|
-
* @param
|
|
76
|
-
* @param
|
|
77
|
-
* @
|
|
74
|
+
* @param input Changes of the diff and the repository.
|
|
75
|
+
* @param input.changed Changed packages and their files.
|
|
76
|
+
* @param input.changesetsInDiff Changesets added or changed by the diff.
|
|
77
|
+
* @param input.packages Discovered packages.
|
|
78
|
+
* @param input.config Repository release configuration.
|
|
79
|
+
* @param input.repository Repository to read the base manifests from.
|
|
80
|
+
* @param input.since Base ref of the diff, like origin/main.
|
|
81
|
+
* @return Names of the packages whose only changes are pins of released sources.
|
|
78
82
|
*/
|
|
79
|
-
export declare function findBundledPinChanges(
|
|
83
|
+
export declare function findBundledPinChanges(input: {
|
|
84
|
+
changed: ChangedPackages;
|
|
85
|
+
changesetsInDiff: Changeset[];
|
|
86
|
+
packages: ConfiguredPackage[];
|
|
87
|
+
config: ChangesetConfig;
|
|
88
|
+
repository: ReleaseRepository;
|
|
89
|
+
since: string;
|
|
90
|
+
}): Promise<Set<string>>;
|
|
80
91
|
/**
|
|
81
92
|
* Check whether a changeset names a package.
|
|
82
93
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
3
4
|
import semverSatisfies from 'semver/functions/satisfies.js';
|
|
4
5
|
import validRange from 'semver/ranges/valid.js';
|
|
5
6
|
import { assertKnownPackages, globRegExp } from "./changeset-packages.js";
|
|
@@ -208,57 +209,118 @@ export async function assertDependentsSourcesReleased(plan, fullPlan, packages,
|
|
|
208
209
|
* with its sources, which the release pull request already announces when
|
|
209
210
|
* the changesets of the diff release one of them. Exempting its package
|
|
210
211
|
* manifest pin change keeps the check from demanding an entry for what
|
|
211
|
-
* versioning rewrites anyway
|
|
212
|
-
*
|
|
212
|
+
* versioning rewrites anyway. Any other change, like documentation, code or
|
|
213
|
+
* another manifest field or dependency, still needs its own changeset.
|
|
213
214
|
*
|
|
214
|
-
* @param
|
|
215
|
-
* @param
|
|
216
|
-
* @param
|
|
217
|
-
* @param
|
|
218
|
-
* @
|
|
215
|
+
* @param input Changes of the diff and the repository.
|
|
216
|
+
* @param input.changed Changed packages and their files.
|
|
217
|
+
* @param input.changesetsInDiff Changesets added or changed by the diff.
|
|
218
|
+
* @param input.packages Discovered packages.
|
|
219
|
+
* @param input.config Repository release configuration.
|
|
220
|
+
* @param input.repository Repository to read the base manifests from.
|
|
221
|
+
* @param input.since Base ref of the diff, like origin/main.
|
|
222
|
+
* @return Names of the packages whose only changes are pins of released sources.
|
|
219
223
|
*/
|
|
220
|
-
export async function findBundledPinChanges(
|
|
224
|
+
export async function findBundledPinChanges(input) {
|
|
225
|
+
const { changed, changesetsInDiff, packages, config, repository, since } = input;
|
|
221
226
|
const candidates = changed.packages.filter((pkg) => undefined !== config.dependents &&
|
|
222
227
|
!hasChangeset(changesetsInDiff, pkg.name) &&
|
|
223
|
-
(changed.filesByPackage[pkg.name] ?? []).every((file) =>
|
|
228
|
+
(changed.filesByPackage[pkg.name] ?? []).every((file) => repository.relativePath(manifestFile(pkg)) === file));
|
|
224
229
|
const bundled = await Promise.all(candidates.map(async (pkg) => {
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
230
|
+
const identifiers = await collectReleasedIdentifiers(pkg, packages, config, changesetsInDiff);
|
|
231
|
+
const pinsOnly = identifiers.length > 0 &&
|
|
232
|
+
(await changesOnlyPins({
|
|
233
|
+
pkg,
|
|
234
|
+
identifiers,
|
|
235
|
+
sections: dependentsSections(config.dependents),
|
|
236
|
+
repository,
|
|
237
|
+
since,
|
|
238
|
+
}));
|
|
239
|
+
return pinsOnly ? pkg.name : undefined;
|
|
229
240
|
}));
|
|
230
241
|
return new Set(bundled.filter((name) => undefined !== name));
|
|
231
242
|
}
|
|
232
243
|
/**
|
|
233
|
-
*
|
|
244
|
+
* Collect the identifiers that a package declares for the configured sources
|
|
245
|
+
* released by the changesets, by the dependency sections of the policy,
|
|
246
|
+
* without resolving the specs against the versions. The changeset check uses
|
|
247
|
+
* this to see through a pin that the versioning will rewrite after the
|
|
248
|
+
* source releases.
|
|
234
249
|
*
|
|
235
|
-
* @param
|
|
236
|
-
* @param
|
|
237
|
-
* @
|
|
250
|
+
* @param pkg Planned package.
|
|
251
|
+
* @param packages Discovered packages.
|
|
252
|
+
* @param config Repository release configuration.
|
|
253
|
+
* @param changesets Changesets that release the sources.
|
|
254
|
+
* @return Declared identifiers of the released sources, like npm package names.
|
|
238
255
|
*/
|
|
239
|
-
|
|
240
|
-
|
|
256
|
+
async function collectReleasedIdentifiers(pkg, packages, config, changesets) {
|
|
257
|
+
const identifiers = [];
|
|
258
|
+
for (const source of packages) {
|
|
259
|
+
const specs = pkg.name !== source.name && hasChangeset(changesets, source.name)
|
|
260
|
+
? await findNpmSpecs(pkg, source, dependentsSections(config.dependents))
|
|
261
|
+
: [];
|
|
262
|
+
identifiers.push(...specs.map(({ name }) => name));
|
|
263
|
+
}
|
|
264
|
+
return identifiers;
|
|
241
265
|
}
|
|
242
266
|
/**
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* versioning will rewrite after the source releases.
|
|
267
|
+
* Check whether the package manifest differs from the base only in the specs
|
|
268
|
+
* of the given identifiers. A manifest that the diff adds has no base and
|
|
269
|
+
* always counts as a change of its own.
|
|
247
270
|
*
|
|
248
|
-
* @param
|
|
249
|
-
* @param
|
|
250
|
-
* @param
|
|
251
|
-
* @
|
|
271
|
+
* @param input Package, identifiers and the repository.
|
|
272
|
+
* @param input.pkg Changed package.
|
|
273
|
+
* @param input.identifiers Declared identifiers whose specs may differ.
|
|
274
|
+
* @param input.sections Dependency sections of the policy.
|
|
275
|
+
* @param input.repository Repository to read the base manifest from.
|
|
276
|
+
* @param input.since Base ref of the diff, like origin/main.
|
|
277
|
+
* @return Whether only the specs of the identifiers changed.
|
|
252
278
|
*/
|
|
253
|
-
async function
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
279
|
+
async function changesOnlyPins(input) {
|
|
280
|
+
const { pkg, identifiers, sections, repository, since } = input;
|
|
281
|
+
const base = await repository.readFileAtMergeBase(since, manifestFile(pkg));
|
|
282
|
+
const head = await readJsonIfExists(manifestFile(pkg));
|
|
283
|
+
return (undefined !== base &&
|
|
284
|
+
undefined !== head &&
|
|
285
|
+
isDeepStrictEqual(withoutSpecs(JSON.parse(base), sections, identifiers), withoutSpecs(head, sections, identifiers)));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Copy a manifest without the specs of the given identifiers in the
|
|
289
|
+
* dependency sections.
|
|
290
|
+
*
|
|
291
|
+
* @param manifest Parsed package manifest.
|
|
292
|
+
* @param sections Dependency sections.
|
|
293
|
+
* @param identifiers Declared identifiers to drop.
|
|
294
|
+
* @return Manifest copy without those specs.
|
|
295
|
+
*/
|
|
296
|
+
function withoutSpecs(manifest, sections, identifiers) {
|
|
297
|
+
const stripped = { ...manifest };
|
|
298
|
+
for (const section of sections) {
|
|
299
|
+
const specs = manifest[section];
|
|
300
|
+
if ('object' === typeof specs && null !== specs) {
|
|
301
|
+
stripped[section] = Object.fromEntries(Object.entries(specs).filter(([name]) => !identifiers.includes(name)));
|
|
259
302
|
}
|
|
260
303
|
}
|
|
261
|
-
return
|
|
304
|
+
return stripped;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* The npm manifest of a package.
|
|
308
|
+
*
|
|
309
|
+
* @param pkg Package.
|
|
310
|
+
* @return Absolute manifest path.
|
|
311
|
+
*/
|
|
312
|
+
function manifestFile(pkg) {
|
|
313
|
+
return path.join(pkg.directory, 'package.json');
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Check whether a changeset names a package.
|
|
317
|
+
*
|
|
318
|
+
* @param changesets Changesets.
|
|
319
|
+
* @param name Package name.
|
|
320
|
+
* @return Whether one of the changesets names the package.
|
|
321
|
+
*/
|
|
322
|
+
export function hasChangeset(changesets, name) {
|
|
323
|
+
return changesets.some((changeset) => Object.hasOwn(changeset.packages, name));
|
|
262
324
|
}
|
|
263
325
|
/**
|
|
264
326
|
* Collect the names of the configured sources that a package builds against,
|
|
@@ -11,13 +11,14 @@ export declare function readChangesets(directory: string): Promise<Changeset[]>;
|
|
|
11
11
|
/**
|
|
12
12
|
* Pick the changesets that were added or changed since a ref.
|
|
13
13
|
*
|
|
14
|
-
* @param repository
|
|
15
|
-
* @param directory
|
|
16
|
-
* @param changesets
|
|
17
|
-
* @param since
|
|
14
|
+
* @param repository Repository of the changesets.
|
|
15
|
+
* @param directory Changeset directory.
|
|
16
|
+
* @param changesets Pending changesets.
|
|
17
|
+
* @param since Base ref, like origin/main.
|
|
18
|
+
* @param uncommitted Whether to include uncommitted and untracked changesets.
|
|
18
19
|
* @return Changesets of the diff.
|
|
19
20
|
*/
|
|
20
|
-
export declare function readChangesetsSince(repository: ReleaseRepository, directory: string, changesets: Changeset[], since: string): Promise<Changeset[]>;
|
|
21
|
+
export declare function readChangesetsSince(repository: ReleaseRepository, directory: string, changesets: Changeset[], since: string, uncommitted?: boolean): Promise<Changeset[]>;
|
|
21
22
|
/**
|
|
22
23
|
* Create a Changesets-compatible Markdown file.
|
|
23
24
|
*
|
package/dist/changeset-files.js
CHANGED
|
@@ -28,17 +28,19 @@ export async function readChangesets(directory) {
|
|
|
28
28
|
/**
|
|
29
29
|
* Pick the changesets that were added or changed since a ref.
|
|
30
30
|
*
|
|
31
|
-
* @param repository
|
|
32
|
-
* @param directory
|
|
33
|
-
* @param changesets
|
|
34
|
-
* @param since
|
|
31
|
+
* @param repository Repository of the changesets.
|
|
32
|
+
* @param directory Changeset directory.
|
|
33
|
+
* @param changesets Pending changesets.
|
|
34
|
+
* @param since Base ref, like origin/main.
|
|
35
|
+
* @param uncommitted Whether to include uncommitted and untracked changesets.
|
|
35
36
|
* @return Changesets of the diff.
|
|
36
37
|
*/
|
|
37
|
-
export async function readChangesetsSince(repository, directory, changesets, since) {
|
|
38
|
+
export async function readChangesetsSince(repository, directory, changesets, since, uncommitted = false) {
|
|
38
39
|
const relativeDirectory = repository.relativePath(directory);
|
|
39
40
|
const changedFiles = new Set(await repository.getChangedFiles(since, {
|
|
40
41
|
directory,
|
|
41
42
|
diffFilter: 'ACMR',
|
|
43
|
+
uncommitted,
|
|
42
44
|
}));
|
|
43
45
|
return changesets.filter((changeset) => changedFiles.has(path.posix.join(relativeDirectory, changeset.fileName)));
|
|
44
46
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChangesetConfig, ChangesetPackageGroup } from './changeset-config.ts';
|
|
1
|
+
import type { ChangesetConfig, ChangesetPackageGroup, DeployPackage, PackageVersionConfig } from './changeset-config.ts';
|
|
2
2
|
import type { ChangesetPackage } from './changesets.ts';
|
|
3
3
|
import type { ReleaseRepository } from './release-repository.ts';
|
|
4
4
|
/**
|
|
@@ -6,7 +6,14 @@ import type { ReleaseRepository } from './release-repository.ts';
|
|
|
6
6
|
*/
|
|
7
7
|
export interface ConfiguredPackage extends ChangesetPackage {
|
|
8
8
|
group: ChangesetPackageGroup;
|
|
9
|
-
versionConfig:
|
|
9
|
+
versionConfig: PackageVersionConfig;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A discovered package with the configuration of its group, without reading
|
|
13
|
+
* its version, which may have no version or deploy configuration.
|
|
14
|
+
*/
|
|
15
|
+
export interface ConfiguredDeployPackage extends DeployPackage {
|
|
16
|
+
group: ChangesetPackageGroup;
|
|
10
17
|
}
|
|
11
18
|
export interface ChangedPackages {
|
|
12
19
|
/** Packages with changed files, in the configured order. */
|
|
@@ -16,7 +23,8 @@ export interface ChangedPackages {
|
|
|
16
23
|
}
|
|
17
24
|
/**
|
|
18
25
|
* Find the packages of the configured package groups, with their current
|
|
19
|
-
* versions.
|
|
26
|
+
* versions. Groups without a version configuration aren't released with
|
|
27
|
+
* changesets, so they're left out.
|
|
20
28
|
*
|
|
21
29
|
* @param repository Repository the packages are in.
|
|
22
30
|
* @param config Repository release configuration.
|
|
@@ -24,6 +32,26 @@ export interface ChangedPackages {
|
|
|
24
32
|
* @throws {ValidationError} For a glob without matches or a duplicate package name.
|
|
25
33
|
*/
|
|
26
34
|
export declare function discoverPackages(repository: ReleaseRepository, config: ChangesetConfig): Promise<ConfiguredPackage[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Find the packages of every package group, with or without a version or
|
|
37
|
+
* deploy configuration, without reading their versions.
|
|
38
|
+
*
|
|
39
|
+
* @param repository Repository the packages are in.
|
|
40
|
+
* @param config Repository release configuration.
|
|
41
|
+
* @return Packages in the configured order.
|
|
42
|
+
* @throws {ValidationError} For a glob without matches or a duplicate package name.
|
|
43
|
+
*/
|
|
44
|
+
export declare function discoverConfiguredPackages(repository: ReleaseRepository, config: ChangesetConfig): Promise<ConfiguredDeployPackage[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Find the packages of the package groups with deploy targets, including the
|
|
47
|
+
* groups without a version configuration, without reading their versions.
|
|
48
|
+
*
|
|
49
|
+
* @param repository Repository the packages are in.
|
|
50
|
+
* @param config Repository release configuration.
|
|
51
|
+
* @return Packages in the configured order.
|
|
52
|
+
* @throws {ValidationError} For a glob without matches or a duplicate package name.
|
|
53
|
+
*/
|
|
54
|
+
export declare function discoverDeployPackages(repository: ReleaseRepository, config: ChangesetConfig): Promise<ConfiguredDeployPackage[]>;
|
|
27
55
|
/**
|
|
28
56
|
* Fail for package names that aren't configured.
|
|
29
57
|
*
|
|
@@ -33,15 +61,34 @@ export declare function discoverPackages(repository: ReleaseRepository, config:
|
|
|
33
61
|
*/
|
|
34
62
|
export declare function assertKnownPackages(packages: ChangesetPackage[], names: string[]): void;
|
|
35
63
|
/**
|
|
36
|
-
* Find
|
|
37
|
-
*
|
|
64
|
+
* Find a package by its identifier, or by its path under the configured root,
|
|
65
|
+
* so that contributors can name a package by the directory they changed.
|
|
38
66
|
*
|
|
39
|
-
* @param repository Repository the packages are in.
|
|
40
67
|
* @param packages Discovered packages.
|
|
41
|
-
* @param
|
|
68
|
+
* @param identifier Package identifier or path, like plugins/alpha or plugins/alpha/.
|
|
69
|
+
* @return The package, or undefined when none matches.
|
|
70
|
+
*/
|
|
71
|
+
export declare function findPackage<Package extends Pick<ChangesetPackage, 'name' | 'path'>>(packages: Package[], identifier: string): Package | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve package identifiers or paths to the package identifiers.
|
|
74
|
+
*
|
|
75
|
+
* @param packages Discovered packages.
|
|
76
|
+
* @param identifiers Package identifiers or paths under the configured root.
|
|
77
|
+
* @return Package identifiers, in the given order.
|
|
78
|
+
* @throws {ValidationError} For an unknown package.
|
|
79
|
+
*/
|
|
80
|
+
export declare function resolvePackageNames(packages: ChangesetPackage[], identifiers: string[]): string[];
|
|
81
|
+
/**
|
|
82
|
+
* Find the packages with files changed between the merge base of a ref and
|
|
83
|
+
* HEAD, or the working tree.
|
|
84
|
+
*
|
|
85
|
+
* @param repository Repository the packages are in.
|
|
86
|
+
* @param packages Discovered packages.
|
|
87
|
+
* @param since Base ref, like origin/main.
|
|
88
|
+
* @param uncommitted Whether to include uncommitted and untracked files.
|
|
42
89
|
* @return Changed packages and their changed files.
|
|
43
90
|
*/
|
|
44
|
-
export declare function getChangedPackages(repository: ReleaseRepository, packages: ConfiguredPackage[], since: string): Promise<ChangedPackages>;
|
|
91
|
+
export declare function getChangedPackages(repository: ReleaseRepository, packages: ConfiguredPackage[], since: string, uncommitted?: boolean): Promise<ChangedPackages>;
|
|
45
92
|
/**
|
|
46
93
|
* Remove the release configuration from a package passed to config callbacks.
|
|
47
94
|
*
|
|
@@ -7,7 +7,8 @@ import { readVersion } from "./version-files.js";
|
|
|
7
7
|
const SKIPPED_DIRECTORIES = ['.git', 'node_modules', 'vendor', 'dist'];
|
|
8
8
|
/**
|
|
9
9
|
* Find the packages of the configured package groups, with their current
|
|
10
|
-
* versions.
|
|
10
|
+
* versions. Groups without a version configuration aren't released with
|
|
11
|
+
* changesets, so they're left out.
|
|
11
12
|
*
|
|
12
13
|
* @param repository Repository the packages are in.
|
|
13
14
|
* @param config Repository release configuration.
|
|
@@ -15,13 +16,50 @@ const SKIPPED_DIRECTORIES = ['.git', 'node_modules', 'vendor', 'dist'];
|
|
|
15
16
|
* @throws {ValidationError} For a glob without matches or a duplicate package name.
|
|
16
17
|
*/
|
|
17
18
|
export async function discoverPackages(repository, config) {
|
|
19
|
+
const found = await findGroupPackages(repository, config, config.packages.filter((group) => group.version));
|
|
20
|
+
const packages = [];
|
|
21
|
+
for (const pkg of found) {
|
|
22
|
+
const versionConfig = pkg.group.version;
|
|
23
|
+
packages.push({
|
|
24
|
+
...pkg,
|
|
25
|
+
currentVersion: await readVersion(repository, pkg.directory, versionConfig.from, pkg),
|
|
26
|
+
versionConfig,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return packages;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find the packages of every package group, with or without a version or
|
|
33
|
+
* deploy configuration, without reading their versions.
|
|
34
|
+
*
|
|
35
|
+
* @param repository Repository the packages are in.
|
|
36
|
+
* @param config Repository release configuration.
|
|
37
|
+
* @return Packages in the configured order.
|
|
38
|
+
* @throws {ValidationError} For a glob without matches or a duplicate package name.
|
|
39
|
+
*/
|
|
40
|
+
export async function discoverConfiguredPackages(repository, config) {
|
|
41
|
+
return findGroupPackages(repository, config, config.packages);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Find the packages of the package groups with deploy targets, including the
|
|
45
|
+
* groups without a version configuration, without reading their versions.
|
|
46
|
+
*
|
|
47
|
+
* @param repository Repository the packages are in.
|
|
48
|
+
* @param config Repository release configuration.
|
|
49
|
+
* @return Packages in the configured order.
|
|
50
|
+
* @throws {ValidationError} For a glob without matches or a duplicate package name.
|
|
51
|
+
*/
|
|
52
|
+
export async function discoverDeployPackages(repository, config) {
|
|
53
|
+
return findGroupPackages(repository, config, config.packages.filter((group) => group.deploy));
|
|
54
|
+
}
|
|
55
|
+
async function findGroupPackages(repository, config, groups) {
|
|
18
56
|
const root = path.resolve(repository.cwd, config.root ?? '.');
|
|
19
57
|
const packages = [];
|
|
20
|
-
const hasRecursiveGlob =
|
|
58
|
+
const hasRecursiveGlob = groups.some((item) => item.glob.split('/').includes('**'));
|
|
21
59
|
const directories = await findDirectories(root, '', hasRecursiveGlob
|
|
22
60
|
? Infinity
|
|
23
|
-
: Math.max(1, ...
|
|
24
|
-
for (const group of
|
|
61
|
+
: Math.max(1, ...groups.map((item) => item.glob.split('/').length + 2)));
|
|
62
|
+
for (const group of groups) {
|
|
25
63
|
const matcher = globRegExp(group.glob);
|
|
26
64
|
const candidates = matcher.test('.')
|
|
27
65
|
? ['.', ...directories]
|
|
@@ -36,7 +74,6 @@ export async function discoverPackages(repository, config) {
|
|
|
36
74
|
for (const relativePath of matches) {
|
|
37
75
|
const directory = path.join(root, relativePath);
|
|
38
76
|
const name = await packageName(directory, relativePath, group.idFrom ?? 'path');
|
|
39
|
-
const currentVersion = await readVersion(repository, directory, group.version.from, relativePath, group.tagType);
|
|
40
77
|
if (packages.some((pkg) => pkg.name === name)) {
|
|
41
78
|
throw new ValidationError(`Package identifier "${name}" is configured more than once.`);
|
|
42
79
|
}
|
|
@@ -45,9 +82,7 @@ export async function discoverPackages(repository, config) {
|
|
|
45
82
|
directory,
|
|
46
83
|
path: relativePath,
|
|
47
84
|
type: packageType(group),
|
|
48
|
-
currentVersion,
|
|
49
85
|
group,
|
|
50
|
-
versionConfig: group.version,
|
|
51
86
|
});
|
|
52
87
|
}
|
|
53
88
|
}
|
|
@@ -68,16 +103,52 @@ export function assertKnownPackages(packages, names) {
|
|
|
68
103
|
});
|
|
69
104
|
}
|
|
70
105
|
/**
|
|
71
|
-
* Find
|
|
72
|
-
*
|
|
106
|
+
* Find a package by its identifier, or by its path under the configured root,
|
|
107
|
+
* so that contributors can name a package by the directory they changed.
|
|
73
108
|
*
|
|
74
|
-
* @param repository Repository the packages are in.
|
|
75
109
|
* @param packages Discovered packages.
|
|
76
|
-
* @param
|
|
110
|
+
* @param identifier Package identifier or path, like plugins/alpha or plugins/alpha/.
|
|
111
|
+
* @return The package, or undefined when none matches.
|
|
112
|
+
*/
|
|
113
|
+
export function findPackage(packages, identifier) {
|
|
114
|
+
const packagePath = identifier
|
|
115
|
+
.replaceAll('\\', '/')
|
|
116
|
+
.replace(/^\.\//, '')
|
|
117
|
+
.replace(/\/+$/, '');
|
|
118
|
+
return (packages.find((pkg) => pkg.name === identifier) ??
|
|
119
|
+
packages.find((pkg) => pkg.path === packagePath));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Resolve package identifiers or paths to the package identifiers.
|
|
123
|
+
*
|
|
124
|
+
* @param packages Discovered packages.
|
|
125
|
+
* @param identifiers Package identifiers or paths under the configured root.
|
|
126
|
+
* @return Package identifiers, in the given order.
|
|
127
|
+
* @throws {ValidationError} For an unknown package.
|
|
128
|
+
*/
|
|
129
|
+
export function resolvePackageNames(packages, identifiers) {
|
|
130
|
+
return identifiers.map((identifier) => {
|
|
131
|
+
const pkg = findPackage(packages, identifier);
|
|
132
|
+
if (!pkg) {
|
|
133
|
+
throw new ValidationError(`Unknown package "${identifier}".`);
|
|
134
|
+
}
|
|
135
|
+
return pkg.name;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Find the packages with files changed between the merge base of a ref and
|
|
140
|
+
* HEAD, or the working tree.
|
|
141
|
+
*
|
|
142
|
+
* @param repository Repository the packages are in.
|
|
143
|
+
* @param packages Discovered packages.
|
|
144
|
+
* @param since Base ref, like origin/main.
|
|
145
|
+
* @param uncommitted Whether to include uncommitted and untracked files.
|
|
77
146
|
* @return Changed packages and their changed files.
|
|
78
147
|
*/
|
|
79
|
-
export async function getChangedPackages(repository, packages, since) {
|
|
80
|
-
const changedFiles = await repository.getChangedFiles(since
|
|
148
|
+
export async function getChangedPackages(repository, packages, since, uncommitted = false) {
|
|
149
|
+
const changedFiles = await repository.getChangedFiles(since, {
|
|
150
|
+
uncommitted,
|
|
151
|
+
});
|
|
81
152
|
const filesByPackage = {};
|
|
82
153
|
const changed = packages.filter((pkg) => {
|
|
83
154
|
const packageFromRepo = repository.relativePath(pkg.directory);
|
|
@@ -172,7 +243,7 @@ async function packageName(directory, relativePath, idFrom) {
|
|
|
172
243
|
return name;
|
|
173
244
|
}
|
|
174
245
|
function packageType(group) {
|
|
175
|
-
const kind = group.version
|
|
246
|
+
const kind = group.version?.from.kind;
|
|
176
247
|
if ('wordpress-plugin-header' === kind) {
|
|
177
248
|
return 'plugin';
|
|
178
249
|
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { ChangesetPackage, ChangesetPackages } from './changesets.ts';
|
|
2
|
+
import type { OutputStream } from './logger.ts';
|
|
3
|
+
/** Terminal that the prompts read answers from and write questions to. */
|
|
4
|
+
export interface PromptTerminal {
|
|
5
|
+
input: NodeJS.ReadableStream;
|
|
6
|
+
output: OutputStream;
|
|
7
|
+
}
|
|
8
|
+
/** Packages to choose from, and the changed ones that are preselected. */
|
|
9
|
+
export interface ChangesetPromptInput {
|
|
10
|
+
/** Configured packages. */
|
|
11
|
+
packages: ChangesetPackage[];
|
|
12
|
+
/** Identifiers of the changed packages without a changeset. */
|
|
13
|
+
changed: string[];
|
|
14
|
+
/** Base ref that the changed packages were compared with. */
|
|
15
|
+
since?: string;
|
|
16
|
+
/** Release note to use instead of asking for one. */
|
|
17
|
+
summary?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Answers of the prompts: no packages for an empty changeset. */
|
|
20
|
+
export interface ChangesetPromptAnswers {
|
|
21
|
+
packages: ChangesetPackages;
|
|
22
|
+
summary: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Ask for the packages, bumps and release note of a changeset, line by line,
|
|
26
|
+
* so that it works in any terminal and with piped input.
|
|
27
|
+
*/
|
|
28
|
+
export declare class ChangesetPrompt {
|
|
29
|
+
readonly terminal: PromptTerminal;
|
|
30
|
+
private lines;
|
|
31
|
+
private readline;
|
|
32
|
+
/**
|
|
33
|
+
* @param terminal Input to read answers from and output for the questions.
|
|
34
|
+
*/
|
|
35
|
+
constructor(terminal: PromptTerminal);
|
|
36
|
+
/**
|
|
37
|
+
* Ask for the changeset, preselecting the changed packages.
|
|
38
|
+
*
|
|
39
|
+
* @param input Packages, changed packages and an optional release note.
|
|
40
|
+
* @return Package bumps, empty for no release, and the release note.
|
|
41
|
+
* @throws {ValidationError} If the input ends before the changeset is complete.
|
|
42
|
+
*/
|
|
43
|
+
ask(input: ChangesetPromptInput): Promise<ChangesetPromptAnswers>;
|
|
44
|
+
/**
|
|
45
|
+
* Stop reading the input, so that the process can exit.
|
|
46
|
+
*/
|
|
47
|
+
close(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Print the numbered packages, marking the changed ones.
|
|
50
|
+
*
|
|
51
|
+
* @param input Packages and changed packages.
|
|
52
|
+
*/
|
|
53
|
+
private listPackages;
|
|
54
|
+
/**
|
|
55
|
+
* Get the package question, with the changed packages as the default.
|
|
56
|
+
*
|
|
57
|
+
* @param input Packages and changed packages.
|
|
58
|
+
* @return Question text.
|
|
59
|
+
*/
|
|
60
|
+
private getPackagesQuestion;
|
|
61
|
+
/**
|
|
62
|
+
* Parse the chosen packages.
|
|
63
|
+
*
|
|
64
|
+
* @param answer Comma or space separated numbers, identifiers or paths.
|
|
65
|
+
* @param input Packages and changed packages.
|
|
66
|
+
* @return Package identifiers, empty for no release.
|
|
67
|
+
* @throws {ValidationError} For unknown, repeated or missing packages.
|
|
68
|
+
*/
|
|
69
|
+
private parsePackages;
|
|
70
|
+
/**
|
|
71
|
+
* Parse one chosen package.
|
|
72
|
+
*
|
|
73
|
+
* @param token Package number, identifier or path.
|
|
74
|
+
* @param packages Configured packages.
|
|
75
|
+
* @return Package identifier.
|
|
76
|
+
* @throws {ValidationError} For an unknown package.
|
|
77
|
+
*/
|
|
78
|
+
private parsePackage;
|
|
79
|
+
/**
|
|
80
|
+
* Parse a bump, patch by default.
|
|
81
|
+
*
|
|
82
|
+
* @param answer Bump name.
|
|
83
|
+
* @return Bump.
|
|
84
|
+
* @throws {ValidationError} For an unknown bump.
|
|
85
|
+
*/
|
|
86
|
+
private parseBump;
|
|
87
|
+
/**
|
|
88
|
+
* Parse a release note.
|
|
89
|
+
*
|
|
90
|
+
* @param answer Release note.
|
|
91
|
+
* @return Trimmed release note.
|
|
92
|
+
* @throws {ValidationError} For an empty release note.
|
|
93
|
+
*/
|
|
94
|
+
private parseSummary;
|
|
95
|
+
/**
|
|
96
|
+
* Ask a question until the answer parses, printing why it didn't.
|
|
97
|
+
*
|
|
98
|
+
* @param question Question text.
|
|
99
|
+
* @param parse Parser that throws a ValidationError for invalid answers.
|
|
100
|
+
* @return Parsed answer.
|
|
101
|
+
*/
|
|
102
|
+
private askUntilValid;
|
|
103
|
+
/**
|
|
104
|
+
* Write a question and read the next line of the input.
|
|
105
|
+
*
|
|
106
|
+
* @param question Question text.
|
|
107
|
+
* @return Answer line.
|
|
108
|
+
* @throws {ValidationError} If the input ended.
|
|
109
|
+
*/
|
|
110
|
+
private readAnswer;
|
|
111
|
+
/**
|
|
112
|
+
* Get the lines of the input, reading it from the first question on. The
|
|
113
|
+
* interface stays in line mode, so the terminal echoes and edits the
|
|
114
|
+
* answers and Ctrl+C ends the process.
|
|
115
|
+
*
|
|
116
|
+
* @return Line iterator.
|
|
117
|
+
*/
|
|
118
|
+
private getLines;
|
|
119
|
+
}
|