@wpelevator/wp-release 0.15.0 → 0.16.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 +246 -37
- package/dist/changeset-config.d.ts +3 -0
- package/dist/changeset-release.d.ts +9 -3
- package/dist/changeset-release.js +23 -14
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2 -0
- package/dist/commands/artifact-signing.d.ts +20 -0
- package/dist/commands/artifact-signing.js +42 -0
- package/dist/commands/build.d.ts +32 -0
- package/dist/commands/build.js +91 -0
- package/dist/commands/changeset-add.d.ts +55 -6
- package/dist/commands/changeset-add.js +12 -3
- package/dist/commands/changeset-args.js +2 -2
- package/dist/commands/changeset-project-args.d.ts +63 -0
- package/dist/commands/changeset-project-args.js +114 -0
- package/dist/commands/changeset-status.d.ts +50 -1
- package/dist/commands/changeset-status.js +4 -2
- package/dist/commands/changeset-tag.d.ts +55 -6
- package/dist/commands/changeset-tag.js +7 -4
- package/dist/commands/changeset-version.d.ts +55 -6
- package/dist/commands/changeset-version.js +4 -2
- package/dist/commands/checksums.d.ts +4 -1
- package/dist/commands/checksums.js +27 -6
- package/dist/commands/package-source.d.ts +43 -0
- package/dist/commands/package-source.js +101 -0
- package/dist/commands/verify.d.ts +7 -1
- package/dist/commands/verify.js +53 -17
- package/dist/commands/zip.d.ts +20 -8
- package/dist/commands/zip.js +109 -124
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/integrity.d.ts +33 -0
- package/dist/integrity.js +115 -0
- package/dist/output-files.d.ts +7 -0
- package/dist/output-files.js +25 -0
- package/dist/package-build.d.ts +33 -0
- package/dist/package-build.js +112 -0
- package/dist/package-files.d.ts +25 -0
- package/dist/package-files.js +24 -0
- package/dist/package-zip.d.ts +14 -2
- package/dist/package-zip.js +129 -38
- package/dist/release-tags.js +6 -0
- package/dist/single-project.d.ts +32 -0
- package/dist/single-project.js +144 -0
- package/dist/summary.d.ts +9 -0
- package/dist/summary.js +25 -0
- package/dist/zip.d.ts +3 -0
- package/dist/zip.js +16 -6
- package/package.json +6 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveSingleProjectConfig } from "./single-project.js";
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { getVersionedReleases, prependChangelog } from "./changelog.js";
|
|
3
4
|
import { loadChangesetConfig } from "./changeset-config.js";
|
|
@@ -12,7 +13,7 @@ import { ReleaseRepository } from "./release-repository.js";
|
|
|
12
13
|
import { DEFAULT_TAG_FORMAT, formatTag } from "./tag-format.js";
|
|
13
14
|
import { verifyVersionTargets, writeVersion } from "./version-files.js";
|
|
14
15
|
import { getPrereleaseVersion, getSnapshotVersion, isPrerelease, } from "./versions.js";
|
|
15
|
-
const MISSING_CONFIG = 'No wp-release config found.
|
|
16
|
+
const MISSING_CONFIG = 'No wp-release config or root project found. Pass --version-* descriptors, add wp-release.config.js or pass --config <path>.';
|
|
16
17
|
/**
|
|
17
18
|
* Changeset releases of a repository: recording changesets, versioning the
|
|
18
19
|
* packages they name and tagging the releases.
|
|
@@ -24,6 +25,7 @@ const MISSING_CONFIG = 'No wp-release config found. Add wp-release.config.js or
|
|
|
24
25
|
export class ChangesetRelease {
|
|
25
26
|
cwd;
|
|
26
27
|
configFile;
|
|
28
|
+
singleProject;
|
|
27
29
|
tagFormat;
|
|
28
30
|
repository;
|
|
29
31
|
/**
|
|
@@ -32,6 +34,7 @@ export class ChangesetRelease {
|
|
|
32
34
|
constructor(options) {
|
|
33
35
|
this.cwd = options.cwd;
|
|
34
36
|
this.configFile = options.configFile;
|
|
37
|
+
this.singleProject = options.singleProject;
|
|
35
38
|
this.tagFormat = options.tagFormat;
|
|
36
39
|
this.repository = new ReleaseRepository({
|
|
37
40
|
cwd: options.cwd,
|
|
@@ -42,7 +45,7 @@ export class ChangesetRelease {
|
|
|
42
45
|
* Discover configured packages, pending changesets, and their proposed
|
|
43
46
|
* versions.
|
|
44
47
|
*
|
|
45
|
-
* @return A release plan; `undefined`
|
|
48
|
+
* @return A release plan; `undefined` without a config or a recognized root project.
|
|
46
49
|
*/
|
|
47
50
|
async getPlan() {
|
|
48
51
|
const context = await this.loadContext();
|
|
@@ -361,19 +364,14 @@ export class ChangesetRelease {
|
|
|
361
364
|
* Load the configuration, discover the packages and plan the releases of
|
|
362
365
|
* the pending changesets, including the releases of their dependents.
|
|
363
366
|
*
|
|
364
|
-
* @return Release context, undefined without a config.
|
|
367
|
+
* @return Release context, undefined without a config or a recognized root project.
|
|
365
368
|
* @throws {ValidationError} For an invalid config, plan or changeset.
|
|
366
369
|
*/
|
|
367
370
|
async loadContext() {
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
...(this.configFile ? { configFile: this.configFile } : {}),
|
|
371
|
-
...(this.tagFormat ? { tagFormat: this.tagFormat } : {}),
|
|
372
|
-
});
|
|
373
|
-
if (!loaded) {
|
|
371
|
+
const config = await this.loadConfig();
|
|
372
|
+
if (!config) {
|
|
374
373
|
return undefined;
|
|
375
374
|
}
|
|
376
|
-
const config = loaded.config;
|
|
377
375
|
const packages = await discoverPackages(this.repository, config);
|
|
378
376
|
const changesets = await readChangesets(this.getChangesetDirectory(config));
|
|
379
377
|
const releases = [];
|
|
@@ -431,15 +429,26 @@ export class ChangesetRelease {
|
|
|
431
429
|
* @throws {ValidationError} Without a config.
|
|
432
430
|
*/
|
|
433
431
|
async requireConfig() {
|
|
432
|
+
const config = await this.loadConfig();
|
|
433
|
+
if (!config) {
|
|
434
|
+
throw new ValidationError(MISSING_CONFIG);
|
|
435
|
+
}
|
|
436
|
+
return config;
|
|
437
|
+
}
|
|
438
|
+
/** Load an explicit/discovered config, otherwise resolve one root project. */
|
|
439
|
+
async loadConfig() {
|
|
434
440
|
const loaded = await loadChangesetConfig({
|
|
435
441
|
cwd: this.cwd,
|
|
436
442
|
...(this.configFile ? { configFile: this.configFile } : {}),
|
|
437
443
|
...(this.tagFormat ? { tagFormat: this.tagFormat } : {}),
|
|
438
444
|
});
|
|
439
|
-
if (
|
|
440
|
-
|
|
445
|
+
if (loaded) {
|
|
446
|
+
if (this.singleProject) {
|
|
447
|
+
throw new ValidationError('Single-project options cannot be combined with a wp-release config. Set these options in the config instead.');
|
|
448
|
+
}
|
|
449
|
+
return loaded.config;
|
|
441
450
|
}
|
|
442
|
-
return
|
|
451
|
+
return resolveSingleProjectConfig(this.cwd, this.singleProject, this.tagFormat);
|
|
443
452
|
}
|
|
444
453
|
/**
|
|
445
454
|
* Get the directory of the changeset files.
|
|
@@ -455,7 +464,7 @@ export class ChangesetRelease {
|
|
|
455
464
|
* Discover configured packages, pending changesets, and their proposed versions.
|
|
456
465
|
*
|
|
457
466
|
* @param input Repository root and optional explicit config file.
|
|
458
|
-
* @return A release plan; `undefined`
|
|
467
|
+
* @return A release plan; `undefined` without a config or a recognized root project.
|
|
459
468
|
*/
|
|
460
469
|
export async function getChangesetReleasePlan(input) {
|
|
461
470
|
return new ChangesetRelease(input).getPlan();
|
package/dist/cli.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export declare function formatGitHubOutputs(result: unknown): string;
|
|
|
59
59
|
* Results of the commands that can be run with execute(), by command name.
|
|
60
60
|
*/
|
|
61
61
|
export interface CommandResults {
|
|
62
|
+
build: import('./commands/build.ts').BuildResult;
|
|
62
63
|
'deploy-svn': import('./commands/deploy-svn.ts').DeploySvnResult;
|
|
63
64
|
zip: ZipResult;
|
|
64
65
|
checksums: ChecksumsResult;
|
package/dist/cli.js
CHANGED
|
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { appendFileSync } from 'node:fs';
|
|
3
3
|
import { parseArgs } from 'node:util';
|
|
4
4
|
import zip from "./commands/zip.js";
|
|
5
|
+
import build from "./commands/build.js";
|
|
5
6
|
import checksums from "./commands/checksums.js";
|
|
6
7
|
import sign from "./commands/sign.js";
|
|
7
8
|
import keygen from "./commands/keygen.js";
|
|
@@ -22,6 +23,7 @@ export const EXIT_SUCCESS = 0;
|
|
|
22
23
|
export const EXIT_FAILURE = 1;
|
|
23
24
|
export const EXIT_INVALID = 2;
|
|
24
25
|
export const commands = [
|
|
26
|
+
build,
|
|
25
27
|
zip,
|
|
26
28
|
checksums,
|
|
27
29
|
sign,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ParseArgsOptionsConfig } from 'node:util';
|
|
2
|
+
import type { SignFilesInput, SignatureFormat } from '../signing.ts';
|
|
3
|
+
import type { ParsedValues } from './command.ts';
|
|
4
|
+
export declare const checksumSigningArgs: ParseArgsOptionsConfig;
|
|
5
|
+
interface SigningPaths {
|
|
6
|
+
artifact?: string;
|
|
7
|
+
checksums: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolve explicit signing targets and validate them before creating artifacts.
|
|
11
|
+
*
|
|
12
|
+
* @param values Parsed CLI flags.
|
|
13
|
+
* @param paths Artifact and manifest paths that can be signed.
|
|
14
|
+
* @return Signing input, or undefined when no signing is requested.
|
|
15
|
+
* @throws {ValidationError} For formats without a signing target or invalid signing input.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getArtifactSigning(values: ParsedValues, paths: SigningPaths): (SignFilesInput & {
|
|
18
|
+
formats: SignatureFormat[];
|
|
19
|
+
}) | undefined;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ValidationError } from "../errors.js";
|
|
2
|
+
import { checkSigningInput } from "../signing.js";
|
|
3
|
+
import { parseSignatureFormats } from "./args.js";
|
|
4
|
+
import { getBoolean, getStrings } from "./command.js";
|
|
5
|
+
export const checksumSigningArgs = {
|
|
6
|
+
checksums: { type: 'boolean' },
|
|
7
|
+
'sign-checksums': { type: 'boolean' },
|
|
8
|
+
'sign-format': { type: 'string', multiple: true },
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Resolve explicit signing targets and validate them before creating artifacts.
|
|
12
|
+
*
|
|
13
|
+
* @param values Parsed CLI flags.
|
|
14
|
+
* @param paths Artifact and manifest paths that can be signed.
|
|
15
|
+
* @return Signing input, or undefined when no signing is requested.
|
|
16
|
+
* @throws {ValidationError} For formats without a signing target or invalid signing input.
|
|
17
|
+
*/
|
|
18
|
+
export function getArtifactSigning(values, paths) {
|
|
19
|
+
const names = getStrings(values, 'sign-format');
|
|
20
|
+
const targets = [
|
|
21
|
+
...(getBoolean(values, 'sign') && paths.artifact
|
|
22
|
+
? [paths.artifact]
|
|
23
|
+
: []),
|
|
24
|
+
...(getBoolean(values, 'sign-checksums')
|
|
25
|
+
? [paths.checksums]
|
|
26
|
+
: []),
|
|
27
|
+
];
|
|
28
|
+
if (names.length && !targets.length) {
|
|
29
|
+
throw new ValidationError('--sign-format requires --sign or --sign-checksums; it does not enable signing.');
|
|
30
|
+
}
|
|
31
|
+
const signing = targets.length
|
|
32
|
+
? {
|
|
33
|
+
paths: targets,
|
|
34
|
+
formats: parseSignatureFormats(names),
|
|
35
|
+
force: getBoolean(values, 'force'),
|
|
36
|
+
}
|
|
37
|
+
: undefined;
|
|
38
|
+
if (signing) {
|
|
39
|
+
checkSigningInput(signing);
|
|
40
|
+
}
|
|
41
|
+
return signing;
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BuildPackageResult } from '../package-build.ts';
|
|
2
|
+
import type { CommandOutcome } from './command.ts';
|
|
3
|
+
export interface BuildResult extends BuildPackageResult {
|
|
4
|
+
package?: string;
|
|
5
|
+
signatures?: string[];
|
|
6
|
+
publicKey?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: {
|
|
9
|
+
name: string;
|
|
10
|
+
usage: string;
|
|
11
|
+
summary: string;
|
|
12
|
+
help: string;
|
|
13
|
+
options: {
|
|
14
|
+
package: {
|
|
15
|
+
type: "string";
|
|
16
|
+
};
|
|
17
|
+
force: {
|
|
18
|
+
type: "boolean";
|
|
19
|
+
};
|
|
20
|
+
output: {
|
|
21
|
+
type: "string";
|
|
22
|
+
};
|
|
23
|
+
slug: {
|
|
24
|
+
type: "string";
|
|
25
|
+
};
|
|
26
|
+
version: {
|
|
27
|
+
type: "string";
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
run({ values, positionals, cwd, configFile, logger, }: import("./command.ts").CommandContext): Promise<CommandOutcome<BuildResult>>;
|
|
31
|
+
};
|
|
32
|
+
export default _default;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { checksumSigningArgs, getArtifactSigning } from "./artifact-signing.js";
|
|
2
|
+
import { signFiles } from "../signing.js";
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { getBuildSummary, getSignSummary } from "../summary.js";
|
|
5
|
+
import { ValidationError } from "../errors.js";
|
|
6
|
+
import { buildPackage, getBuildChecksumsPath } from "../package-build.js";
|
|
7
|
+
import { fileSelectionArgs, sourceDirArgs } from "./args.js";
|
|
8
|
+
import { getBoolean, getString } from "./command.js";
|
|
9
|
+
import { getDirectorySource, getPackageArg, getPackageSource, } from "./package-source.js";
|
|
10
|
+
export default {
|
|
11
|
+
name: 'build',
|
|
12
|
+
usage: 'build [<source-dir>] --output <dir> [options] | build --package <name> --output <dir>',
|
|
13
|
+
summary: 'Copy the selected release files into an output directory.',
|
|
14
|
+
help: `Options:
|
|
15
|
+
--output <dir> Required destination; files go directly inside it
|
|
16
|
+
--source-dir <dir> Source directory (default: .), or a positional argument
|
|
17
|
+
--package <name> Use the configured package directory and file rules
|
|
18
|
+
--distignore <file> Ignore file (default: <source-dir>/.distignore)
|
|
19
|
+
--no-distignore Don't read an ignore file
|
|
20
|
+
--exclude <patterns> Extra patterns, comma-separated or repeated
|
|
21
|
+
--exclude-gitattributes Exclude Git export-ignore paths
|
|
22
|
+
--slug <slug> Slug in the manifest (default: project directory name)
|
|
23
|
+
--version <version> Manifest version (default: Version header)
|
|
24
|
+
--checksums Write <output-dir>.checksums.json beside the directory
|
|
25
|
+
--sign-checksums Generate and sign the manifest; implies --checksums
|
|
26
|
+
--sign-format <names> Formats: wordpress,minisign,ssh; requires --sign-checksums
|
|
27
|
+
--force Replace an existing output directory, removing stale files
|
|
28
|
+
|
|
29
|
+
The output directory is excluded from the source selection. It cannot be the
|
|
30
|
+
source directory or an ancestor. --sign is unsupported for directories.
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
wp-release build --output dist/my-plugin
|
|
34
|
+
wp-release build --package plugins/alpha --output dist/alpha`,
|
|
35
|
+
options: {
|
|
36
|
+
output: { type: 'string' },
|
|
37
|
+
slug: { type: 'string' },
|
|
38
|
+
version: { type: 'string' },
|
|
39
|
+
...checksumSigningArgs,
|
|
40
|
+
...sourceDirArgs,
|
|
41
|
+
...fileSelectionArgs,
|
|
42
|
+
package: { type: 'string' },
|
|
43
|
+
force: { type: 'boolean' },
|
|
44
|
+
},
|
|
45
|
+
async run({ values, positionals, cwd, configFile, logger, }) {
|
|
46
|
+
const output = getString(values, 'output');
|
|
47
|
+
if (!output?.trim()) {
|
|
48
|
+
throw new ValidationError('build requires --output <dir>.');
|
|
49
|
+
}
|
|
50
|
+
const name = getPackageArg(values, positionals);
|
|
51
|
+
const source = name
|
|
52
|
+
? await getPackageSource(values, cwd, name, configFile)
|
|
53
|
+
: await getDirectorySource(values, positionals, cwd);
|
|
54
|
+
const outputDir = resolve(cwd, output);
|
|
55
|
+
const signing = getArtifactSigning(values, {
|
|
56
|
+
checksums: getBuildChecksumsPath(outputDir),
|
|
57
|
+
});
|
|
58
|
+
const built = await buildPackage({
|
|
59
|
+
sourceDir: source.sourceDir,
|
|
60
|
+
selection: source.selection,
|
|
61
|
+
outputDir,
|
|
62
|
+
checksums: getBoolean(values, 'checksums') ||
|
|
63
|
+
getBoolean(values, 'sign-checksums'),
|
|
64
|
+
slug: source.slug,
|
|
65
|
+
version: source.version,
|
|
66
|
+
...(source.type ? { type: source.type } : {}),
|
|
67
|
+
force: getBoolean(values, 'force'),
|
|
68
|
+
});
|
|
69
|
+
const signed = signing
|
|
70
|
+
? { ...(await signFiles(signing)), formats: signing.formats }
|
|
71
|
+
: undefined;
|
|
72
|
+
const result = {
|
|
73
|
+
...built,
|
|
74
|
+
...(signed
|
|
75
|
+
? { signatures: signed.signatures, publicKey: signed.publicKey }
|
|
76
|
+
: {}),
|
|
77
|
+
...(source.package ? { package: source.package } : {}),
|
|
78
|
+
};
|
|
79
|
+
logger.debug(`Built ${built.files} files from ${source.sourceDir}.`);
|
|
80
|
+
logger.info(built.outputDir);
|
|
81
|
+
if (built.checksumsPath) {
|
|
82
|
+
logger.info(built.checksumsPath);
|
|
83
|
+
}
|
|
84
|
+
signed?.signatures.forEach((path) => logger.info(path));
|
|
85
|
+
logger.summary((context) => getBuildSummary(context, result));
|
|
86
|
+
if (signed) {
|
|
87
|
+
logger.summary((context) => getSignSummary(context, signed));
|
|
88
|
+
}
|
|
89
|
+
return { exitCode: 0, result };
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -8,24 +8,73 @@ declare const _default: {
|
|
|
8
8
|
summary: string;
|
|
9
9
|
help: string;
|
|
10
10
|
options: {
|
|
11
|
-
|
|
11
|
+
'version-package-json': {
|
|
12
12
|
readonly type: "string";
|
|
13
13
|
readonly multiple: true;
|
|
14
14
|
};
|
|
15
|
-
|
|
15
|
+
'version-composer-json': {
|
|
16
16
|
readonly type: "string";
|
|
17
17
|
readonly multiple: true;
|
|
18
18
|
};
|
|
19
|
-
|
|
19
|
+
'version-wordpress-plugin': {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly multiple: true;
|
|
22
|
+
};
|
|
23
|
+
'version-wordpress-theme': {
|
|
24
|
+
readonly type: "string";
|
|
25
|
+
readonly multiple: true;
|
|
26
|
+
};
|
|
27
|
+
'version-wordpress-stable-tag': {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
readonly multiple: true;
|
|
30
|
+
};
|
|
31
|
+
'version-php-constant': {
|
|
32
|
+
readonly type: "string";
|
|
33
|
+
readonly multiple: true;
|
|
34
|
+
};
|
|
35
|
+
'version-git-tag': {
|
|
36
|
+
readonly type: "string";
|
|
37
|
+
readonly multiple: true;
|
|
38
|
+
};
|
|
39
|
+
'version-from': {
|
|
40
|
+
readonly type: "string";
|
|
41
|
+
};
|
|
42
|
+
'base-branch': {
|
|
43
|
+
readonly type: "string";
|
|
44
|
+
};
|
|
45
|
+
remote: {
|
|
46
|
+
readonly type: "string";
|
|
47
|
+
};
|
|
48
|
+
'changesets-dir': {
|
|
49
|
+
readonly type: "string";
|
|
50
|
+
};
|
|
51
|
+
'readme-changelog': {
|
|
52
|
+
readonly type: "boolean";
|
|
53
|
+
};
|
|
54
|
+
'no-readme-changelog': {
|
|
55
|
+
readonly type: "boolean";
|
|
56
|
+
};
|
|
57
|
+
'changelog-insert-after': {
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
};
|
|
60
|
+
package: {
|
|
61
|
+
readonly type: "string";
|
|
62
|
+
readonly multiple: true;
|
|
63
|
+
};
|
|
64
|
+
bump: {
|
|
65
|
+
readonly type: "string";
|
|
66
|
+
readonly multiple: true;
|
|
67
|
+
};
|
|
68
|
+
summary: {
|
|
20
69
|
readonly type: "string";
|
|
21
70
|
};
|
|
22
|
-
|
|
71
|
+
empty: {
|
|
23
72
|
readonly type: "boolean";
|
|
24
73
|
};
|
|
25
|
-
|
|
74
|
+
since: {
|
|
26
75
|
readonly type: "string";
|
|
27
76
|
};
|
|
28
|
-
|
|
77
|
+
name: {
|
|
29
78
|
readonly type: "string";
|
|
30
79
|
};
|
|
31
80
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { changesetProjectArgs, changesetProjectHelp, parseChangesetProjectArgs, } from "./changeset-project-args.js";
|
|
1
2
|
import { resolvePackageNames } from "../changeset-packages.js";
|
|
2
3
|
import { ChangesetPrompt } from "../changeset-prompt.js";
|
|
3
4
|
import { ChangesetRelease } from "../changeset-release.js";
|
|
@@ -13,6 +14,12 @@ import { parseChangesetAddArgs, changesetAddArgs } from "./changeset-args.js";
|
|
|
13
14
|
* @throws {ValidationError} If no changed package needs a changeset.
|
|
14
15
|
*/
|
|
15
16
|
async function getChangedPackageBumps(release, input, bump) {
|
|
17
|
+
const packages = await release.getPackages();
|
|
18
|
+
if (!input.since &&
|
|
19
|
+
1 === packages.length &&
|
|
20
|
+
'.' === packages[0]?.path) {
|
|
21
|
+
return { [packages[0].name]: bump };
|
|
22
|
+
}
|
|
16
23
|
const status = await release.getStatus({
|
|
17
24
|
...(input.since ? { since: input.since } : {}),
|
|
18
25
|
uncommitted: true,
|
|
@@ -99,15 +106,17 @@ export default {
|
|
|
99
106
|
|
|
100
107
|
Use --package and --bump pairs for package releases, or --empty for changes
|
|
101
108
|
that should pass the status check without producing a release. A single
|
|
102
|
-
--bump without --package
|
|
109
|
+
--bump without --package selects the sole root package, or releases packages
|
|
110
|
+
that changed since the base
|
|
103
111
|
ref, including uncommitted files, and have no changeset yet. Without
|
|
104
112
|
--package and --bump in a terminal, the command asks for the packages, with
|
|
105
|
-
the changed ones preselected, their bumps and the release note
|
|
106
|
-
options: changesetAddArgs,
|
|
113
|
+
the changed ones preselected, their bumps and the release note.${changesetProjectHelp}`,
|
|
114
|
+
options: { ...changesetAddArgs, ...changesetProjectArgs },
|
|
107
115
|
async run({ values, cwd, configFile, tagFormat, logger, terminal }) {
|
|
108
116
|
const input = parseChangesetAddArgs(values);
|
|
109
117
|
const release = new ChangesetRelease({
|
|
110
118
|
cwd,
|
|
119
|
+
...parseChangesetProjectArgs(values),
|
|
111
120
|
...(configFile ? { configFile } : {}),
|
|
112
121
|
...(tagFormat ? { tagFormat } : {}),
|
|
113
122
|
});
|
|
@@ -193,8 +193,8 @@ export function parseChangesetTagArgs(values) {
|
|
|
193
193
|
if ('' === args.version) {
|
|
194
194
|
throw new ValidationError('--version <version> must not be empty.');
|
|
195
195
|
}
|
|
196
|
-
if (undefined !== args.version &&
|
|
197
|
-
throw new ValidationError('--version <version>
|
|
196
|
+
if (undefined !== args.version && args.packages.length > 1) {
|
|
197
|
+
throw new ValidationError('--version <version> accepts at most one --package <name>.');
|
|
198
198
|
}
|
|
199
199
|
if (args.untagged && args.push) {
|
|
200
200
|
throw new ValidationError('--untagged cannot be combined with --push.');
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { SingleProjectOptions } from '../single-project.ts';
|
|
2
|
+
import type { ParsedValues } from './command.ts';
|
|
3
|
+
export declare const changesetProjectArgs: {
|
|
4
|
+
readonly 'version-package-json': {
|
|
5
|
+
readonly type: "string";
|
|
6
|
+
readonly multiple: true;
|
|
7
|
+
};
|
|
8
|
+
readonly 'version-composer-json': {
|
|
9
|
+
readonly type: "string";
|
|
10
|
+
readonly multiple: true;
|
|
11
|
+
};
|
|
12
|
+
readonly 'version-wordpress-plugin': {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly multiple: true;
|
|
15
|
+
};
|
|
16
|
+
readonly 'version-wordpress-theme': {
|
|
17
|
+
readonly type: "string";
|
|
18
|
+
readonly multiple: true;
|
|
19
|
+
};
|
|
20
|
+
readonly 'version-wordpress-stable-tag': {
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
readonly multiple: true;
|
|
23
|
+
};
|
|
24
|
+
readonly 'version-php-constant': {
|
|
25
|
+
readonly type: "string";
|
|
26
|
+
readonly multiple: true;
|
|
27
|
+
};
|
|
28
|
+
readonly 'version-git-tag': {
|
|
29
|
+
readonly type: "string";
|
|
30
|
+
readonly multiple: true;
|
|
31
|
+
};
|
|
32
|
+
readonly 'version-from': {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
};
|
|
35
|
+
readonly 'base-branch': {
|
|
36
|
+
readonly type: "string";
|
|
37
|
+
};
|
|
38
|
+
readonly remote: {
|
|
39
|
+
readonly type: "string";
|
|
40
|
+
};
|
|
41
|
+
readonly 'changesets-dir': {
|
|
42
|
+
readonly type: "string";
|
|
43
|
+
};
|
|
44
|
+
readonly 'readme-changelog': {
|
|
45
|
+
readonly type: "boolean";
|
|
46
|
+
};
|
|
47
|
+
readonly 'no-readme-changelog': {
|
|
48
|
+
readonly type: "boolean";
|
|
49
|
+
};
|
|
50
|
+
readonly 'changelog-insert-after': {
|
|
51
|
+
readonly type: "string";
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export declare const changesetProjectHelp = "\nSingle-project options (without a release config file):\n --version-package-json <file> npm version source/target (repeatable)\n --version-composer-json <file> Composer source/target (repeatable)\n --version-wordpress-plugin <file> Plugin header source/target (repeatable)\n --version-wordpress-theme <file> Theme header source/target (repeatable)\n --version-wordpress-stable-tag <file> Readme Stable tag source/target (repeatable)\n --version-php-constant <file>#<constant> PHP constant source/target (repeatable)\n --version-git-tag <pattern> Git tag source only; use {version}\n --version-from <kind>[:<file>] Choose the source; constants use file#constant\n --base-branch <branch> Default comparison branch on the remote\n --remote <name> Git remote (default: origin)\n --changesets-dir <dir> Changeset directory (default: .changeset)\n --readme-changelog / --no-readme-changelog\n Enable/disable readme changelog updates\n --changelog-insert-after <marker> Insert changelog entries after this marker\n\nExplicit descriptors define all version targets. Without them, detect one root\nproject. A unique non-Stable-tag descriptor is the inferred source; otherwise\npass --version-from, qualifying it with :file when its kind is repeated.\nUse the same project options for every changeset command.";
|
|
55
|
+
/**
|
|
56
|
+
* Parse shared single-project settings; operation flags stay command-specific.
|
|
57
|
+
*
|
|
58
|
+
* @param values Parsed command arguments.
|
|
59
|
+
* @return Fallback settings when explicitly supplied.
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseChangesetProjectArgs(values: ParsedValues): {
|
|
62
|
+
singleProject?: SingleProjectOptions;
|
|
63
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { packageJsonVersion, composerJsonVersion, wordpressPluginVersion, wordpressThemeVersion, wordpressStableTag, phpConstantVersion, gitTagVersion, } from "../changeset-config.js";
|
|
2
|
+
import { ValidationError } from "../errors.js";
|
|
3
|
+
import { getBoolean, getString, getStrings } from "./command.js";
|
|
4
|
+
export const changesetProjectArgs = {
|
|
5
|
+
'version-package-json': { type: 'string', multiple: true },
|
|
6
|
+
'version-composer-json': { type: 'string', multiple: true },
|
|
7
|
+
'version-wordpress-plugin': { type: 'string', multiple: true },
|
|
8
|
+
'version-wordpress-theme': { type: 'string', multiple: true },
|
|
9
|
+
'version-wordpress-stable-tag': { type: 'string', multiple: true },
|
|
10
|
+
'version-php-constant': { type: 'string', multiple: true },
|
|
11
|
+
'version-git-tag': { type: 'string', multiple: true },
|
|
12
|
+
'version-from': { type: 'string' },
|
|
13
|
+
'base-branch': { type: 'string' },
|
|
14
|
+
remote: { type: 'string' },
|
|
15
|
+
'changesets-dir': { type: 'string' },
|
|
16
|
+
'readme-changelog': { type: 'boolean' },
|
|
17
|
+
'no-readme-changelog': { type: 'boolean' },
|
|
18
|
+
'changelog-insert-after': { type: 'string' },
|
|
19
|
+
};
|
|
20
|
+
export const changesetProjectHelp = `
|
|
21
|
+
Single-project options (without a release config file):
|
|
22
|
+
--version-package-json <file> npm version source/target (repeatable)
|
|
23
|
+
--version-composer-json <file> Composer source/target (repeatable)
|
|
24
|
+
--version-wordpress-plugin <file> Plugin header source/target (repeatable)
|
|
25
|
+
--version-wordpress-theme <file> Theme header source/target (repeatable)
|
|
26
|
+
--version-wordpress-stable-tag <file> Readme Stable tag source/target (repeatable)
|
|
27
|
+
--version-php-constant <file>#<constant> PHP constant source/target (repeatable)
|
|
28
|
+
--version-git-tag <pattern> Git tag source only; use {version}
|
|
29
|
+
--version-from <kind>[:<file>] Choose the source; constants use file#constant
|
|
30
|
+
--base-branch <branch> Default comparison branch on the remote
|
|
31
|
+
--remote <name> Git remote (default: origin)
|
|
32
|
+
--changesets-dir <dir> Changeset directory (default: .changeset)
|
|
33
|
+
--readme-changelog / --no-readme-changelog
|
|
34
|
+
Enable/disable readme changelog updates
|
|
35
|
+
--changelog-insert-after <marker> Insert changelog entries after this marker
|
|
36
|
+
|
|
37
|
+
Explicit descriptors define all version targets. Without them, detect one root
|
|
38
|
+
project. A unique non-Stable-tag descriptor is the inferred source; otherwise
|
|
39
|
+
pass --version-from, qualifying it with :file when its kind is repeated.
|
|
40
|
+
Use the same project options for every changeset command.`;
|
|
41
|
+
/**
|
|
42
|
+
* Parse shared single-project settings; operation flags stay command-specific.
|
|
43
|
+
*
|
|
44
|
+
* @param values Parsed command arguments.
|
|
45
|
+
* @return Fallback settings when explicitly supplied.
|
|
46
|
+
*/
|
|
47
|
+
export function parseChangesetProjectArgs(values) {
|
|
48
|
+
const options = {};
|
|
49
|
+
const versions = [];
|
|
50
|
+
const factories = {
|
|
51
|
+
'package-json': packageJsonVersion,
|
|
52
|
+
'composer-json': composerJsonVersion,
|
|
53
|
+
'wordpress-plugin': wordpressPluginVersion,
|
|
54
|
+
'wordpress-theme': wordpressThemeVersion,
|
|
55
|
+
'wordpress-stable-tag': wordpressStableTag,
|
|
56
|
+
};
|
|
57
|
+
for (const [kind, factory] of Object.entries(factories)) {
|
|
58
|
+
for (const file of getStrings(values, `version-${kind}`)) {
|
|
59
|
+
if (!file.trim()) {
|
|
60
|
+
throw new ValidationError(`--version-${kind} <file> must not be empty.`);
|
|
61
|
+
}
|
|
62
|
+
versions.push(factory({ file }));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const value of getStrings(values, 'version-php-constant')) {
|
|
66
|
+
const separator = value.lastIndexOf('#');
|
|
67
|
+
const file = value.slice(0, separator);
|
|
68
|
+
const constant = value.slice(separator + 1);
|
|
69
|
+
if (separator < 1 ||
|
|
70
|
+
!file.trim() ||
|
|
71
|
+
!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(constant)) {
|
|
72
|
+
throw new ValidationError('--version-php-constant must be <file>#<constant>, for example plugin.php#PLUGIN_VERSION.');
|
|
73
|
+
}
|
|
74
|
+
versions.push(phpConstantVersion({ file, constant }));
|
|
75
|
+
}
|
|
76
|
+
const patterns = getStrings(values, 'version-git-tag');
|
|
77
|
+
if (patterns.length > 1) {
|
|
78
|
+
throw new ValidationError('--version-git-tag accepts one source pattern.');
|
|
79
|
+
}
|
|
80
|
+
for (const pattern of patterns) {
|
|
81
|
+
if (!pattern.trim() || !pattern.includes('{version}')) {
|
|
82
|
+
throw new ValidationError('--version-git-tag <pattern> must contain {version}.');
|
|
83
|
+
}
|
|
84
|
+
versions.push(gitTagVersion({ pattern }));
|
|
85
|
+
}
|
|
86
|
+
if (versions.length) {
|
|
87
|
+
options.versions = versions;
|
|
88
|
+
}
|
|
89
|
+
const strings = {
|
|
90
|
+
'version-from': 'versionFrom',
|
|
91
|
+
'base-branch': 'baseBranch',
|
|
92
|
+
remote: 'remote',
|
|
93
|
+
'changesets-dir': 'changesets',
|
|
94
|
+
'changelog-insert-after': 'changelogInsertAfter',
|
|
95
|
+
};
|
|
96
|
+
for (const [flag, key] of Object.entries(strings)) {
|
|
97
|
+
const value = getString(values, flag);
|
|
98
|
+
if (undefined !== value) {
|
|
99
|
+
if (!value.trim()) {
|
|
100
|
+
throw new ValidationError(`--${flag} must not be empty.`);
|
|
101
|
+
}
|
|
102
|
+
options[key] = value;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (getBoolean(values, 'readme-changelog') &&
|
|
106
|
+
getBoolean(values, 'no-readme-changelog')) {
|
|
107
|
+
throw new ValidationError('--readme-changelog cannot be combined with --no-readme-changelog.');
|
|
108
|
+
}
|
|
109
|
+
if (getBoolean(values, 'readme-changelog') ||
|
|
110
|
+
getBoolean(values, 'no-readme-changelog')) {
|
|
111
|
+
options.readmeChangelog = getBoolean(values, 'readme-changelog');
|
|
112
|
+
}
|
|
113
|
+
return Object.keys(options).length ? { singleProject: options } : {};
|
|
114
|
+
}
|