@wpelevator/wp-release 0.13.0 → 0.15.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 +83 -25
- package/dist/changeset-config.d.ts +8 -6
- package/dist/changeset-config.js +7 -5
- package/dist/changeset-packages.d.ts +12 -2
- package/dist/changeset-packages.js +13 -1
- package/dist/changeset-release.d.ts +5 -2
- package/dist/changeset-release.js +12 -6
- package/dist/cli.d.ts +16 -7
- package/dist/cli.js +58 -11
- package/dist/commands/args.d.ts +11 -21
- package/dist/commands/args.js +24 -35
- package/dist/commands/changeset-add.d.ts +1 -1
- package/dist/commands/changeset-add.js +3 -2
- package/dist/commands/changeset-status.d.ts +1 -1
- package/dist/commands/changeset-status.js +2 -1
- package/dist/commands/changeset-tag.d.ts +1 -1
- package/dist/commands/changeset-tag.js +4 -2
- package/dist/commands/changeset-version.d.ts +1 -1
- package/dist/commands/changeset-version.js +2 -1
- package/dist/commands/checksums.js +2 -2
- package/dist/commands/command.d.ts +5 -0
- package/dist/commands/deploy-git.d.ts +1 -1
- package/dist/commands/deploy-git.js +2 -1
- package/dist/commands/deploy-svn.d.ts +11 -15
- package/dist/commands/deploy-svn.js +26 -5
- package/dist/commands/keygen.d.ts +3 -0
- package/dist/commands/keygen.js +6 -1
- package/dist/commands/package-deploys.d.ts +8 -0
- package/dist/commands/package-deploys.js +5 -0
- package/dist/commands/sign.d.ts +10 -1
- package/dist/commands/sign.js +29 -31
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.js +43 -24
- package/dist/commands/zip.d.ts +23 -8
- package/dist/commands/zip.js +171 -73
- 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.d.ts +17 -0
- package/dist/git.js +23 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.js +6 -3
- package/dist/minisign.d.ts +41 -0
- package/dist/minisign.js +128 -0
- package/dist/package-deploy.d.ts +28 -0
- package/dist/package-deploy.js +41 -6
- package/dist/package-zip.d.ts +52 -0
- package/dist/package-zip.js +78 -0
- package/dist/release-repository.d.ts +4 -3
- package/dist/release-repository.js +5 -4
- package/dist/signing.d.ts +100 -9
- package/dist/signing.js +165 -41
- 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 +21 -12
- package/dist/tag-format.js +25 -39
- package/dist/version-files.d.ts +6 -7
- package/dist/version-files.js +10 -11
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import { appendFileSync } from 'node:fs';
|
|
2
3
|
import { parseArgs } from 'node:util';
|
|
3
4
|
import zip from "./commands/zip.js";
|
|
@@ -43,6 +44,7 @@ const globalArgs = {
|
|
|
43
44
|
json: { type: 'boolean' },
|
|
44
45
|
'github-output': { type: 'boolean' },
|
|
45
46
|
config: { type: 'string' },
|
|
47
|
+
'tag-format': { type: 'string' },
|
|
46
48
|
};
|
|
47
49
|
const globalOptions = `Global options:
|
|
48
50
|
-h, --help Show help for the command
|
|
@@ -55,7 +57,32 @@ const globalOptions = `Global options:
|
|
|
55
57
|
--json Print the result as JSON
|
|
56
58
|
--github-output Set the result as JSON to the "result" output of
|
|
57
59
|
the GitHub Actions step
|
|
58
|
-
--config <path> Path to a JavaScript release config file
|
|
60
|
+
--config <path> Path to a JavaScript release config file
|
|
61
|
+
--tag-format <format>
|
|
62
|
+
Tag format with {name}, {path} and {version} that
|
|
63
|
+
replaces the tagFormat of the config, like
|
|
64
|
+
{path}/{version}`;
|
|
65
|
+
/**
|
|
66
|
+
* Get the config file and the tag format from the global options.
|
|
67
|
+
*
|
|
68
|
+
* @param values Parsed CLI values.
|
|
69
|
+
* @return The --config and --tag-format values.
|
|
70
|
+
* @throws {ValidationError} For an empty --config or --tag-format.
|
|
71
|
+
*/
|
|
72
|
+
function getConfigArgs(values) {
|
|
73
|
+
const configFile = getString(values, 'config');
|
|
74
|
+
const tagFormat = getString(values, 'tag-format');
|
|
75
|
+
if ('' === configFile?.trim()) {
|
|
76
|
+
throw new ValidationError('--config <path> must not be empty.');
|
|
77
|
+
}
|
|
78
|
+
if ('' === tagFormat?.trim()) {
|
|
79
|
+
throw new ValidationError('--tag-format <format> must not be empty.');
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
...(configFile ? { configFile } : {}),
|
|
83
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
59
86
|
/**
|
|
60
87
|
* Get the top-level help text listing all commands.
|
|
61
88
|
*
|
|
@@ -151,6 +178,28 @@ function createLogWriter(values, streams) {
|
|
|
151
178
|
}
|
|
152
179
|
return create(streams);
|
|
153
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Format the result of a command as GitHub Actions step outputs: the whole
|
|
183
|
+
* result as JSON in "result", and each top-level string, number or boolean
|
|
184
|
+
* as its own output, like "zipPath", so that a workflow reads it without
|
|
185
|
+
* fromJSON(). Lists and objects are only in "result". Every value but the
|
|
186
|
+
* compact JSON, which has no line breaks, uses a random delimiter, so that a
|
|
187
|
+
* value with line breaks can't set other outputs.
|
|
188
|
+
*
|
|
189
|
+
* @param result Command result.
|
|
190
|
+
* @return Lines for the GITHUB_OUTPUT file.
|
|
191
|
+
*/
|
|
192
|
+
export function formatGitHubOutputs(result) {
|
|
193
|
+
const values = 'object' === typeof result && null !== result
|
|
194
|
+
? Object.entries(result).filter(([name, value]) => 'result' !== name &&
|
|
195
|
+
['string', 'number', 'boolean'].includes(typeof value))
|
|
196
|
+
: [];
|
|
197
|
+
const delimiter = `ghadelimiter_${randomUUID()}`;
|
|
198
|
+
return [
|
|
199
|
+
`result=${JSON.stringify(result)}\n`,
|
|
200
|
+
...values.map(([name, value]) => `${name}<<${delimiter}\n${String(value)}\n${delimiter}\n`),
|
|
201
|
+
].join('');
|
|
202
|
+
}
|
|
154
203
|
/**
|
|
155
204
|
* Get the GitHub Actions step output file for --github-output, checked before
|
|
156
205
|
* the command runs.
|
|
@@ -188,10 +237,7 @@ async function runCommand(command, args, io) {
|
|
|
188
237
|
options: { ...globalArgs, ...command.options },
|
|
189
238
|
allowPositionals: true,
|
|
190
239
|
});
|
|
191
|
-
const configFile =
|
|
192
|
-
if ('' === configFile?.trim()) {
|
|
193
|
-
throw new ValidationError('--config <path> must not be empty.');
|
|
194
|
-
}
|
|
240
|
+
const { configFile, tagFormat } = getConfigArgs(values);
|
|
195
241
|
const githubOutputFile = getGitHubOutputFile(values);
|
|
196
242
|
logger = new Logger({
|
|
197
243
|
writer: createLogWriter(values, { stdout, stderr }),
|
|
@@ -208,6 +254,7 @@ async function runCommand(command, args, io) {
|
|
|
208
254
|
positionals,
|
|
209
255
|
cwd,
|
|
210
256
|
...(configFile ? { configFile } : {}),
|
|
257
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
211
258
|
logger,
|
|
212
259
|
...(interactive
|
|
213
260
|
? { terminal: { input: stdin, output: stdout } }
|
|
@@ -217,8 +264,7 @@ async function runCommand(command, args, io) {
|
|
|
217
264
|
stdout.write(JSON.stringify(result, null, '\t') + '\n');
|
|
218
265
|
}
|
|
219
266
|
if (githubOutputFile) {
|
|
220
|
-
|
|
221
|
-
appendFileSync(githubOutputFile, `result=${JSON.stringify(result)}\n`);
|
|
267
|
+
appendFileSync(githubOutputFile, formatGitHubOutputs(result));
|
|
222
268
|
}
|
|
223
269
|
return exitCode;
|
|
224
270
|
}
|
|
@@ -238,6 +284,7 @@ async function runCommand(command, args, io) {
|
|
|
238
284
|
* @param context.cwd Working directory that relative paths resolve against.
|
|
239
285
|
* @param context.configFile Explicit config file path, when supplied by a wrapper.
|
|
240
286
|
* @param context.logger Logger for the command output.
|
|
287
|
+
* @param context.svnRunner Optional SVN command runner supplied by a wrapper.
|
|
241
288
|
* @return Exit code and result of the command.
|
|
242
289
|
* @throws {Error} If the command is unknown, the arguments are invalid or the command fails.
|
|
243
290
|
*/
|
|
@@ -251,16 +298,16 @@ export async function execute(name, args, context) {
|
|
|
251
298
|
options: { ...globalArgs, ...command.options },
|
|
252
299
|
allowPositionals: true,
|
|
253
300
|
});
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
301
|
+
const configArgs = getConfigArgs(values);
|
|
302
|
+
const configFile = configArgs.configFile ?? context.configFile;
|
|
303
|
+
const { tagFormat } = configArgs;
|
|
258
304
|
// The command table is keyed by name, so the result matches CommandResults.
|
|
259
305
|
return command.run({
|
|
260
306
|
values,
|
|
261
307
|
positionals,
|
|
262
308
|
...context,
|
|
263
309
|
...(configFile ? { configFile } : {}),
|
|
310
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
264
311
|
});
|
|
265
312
|
}
|
|
266
313
|
/**
|
package/dist/commands/args.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ParseArgsOptionsConfig } from 'node:util';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SignatureFormat } from '../signing.ts';
|
|
3
3
|
import type { ParsedValues } from './command.ts';
|
|
4
4
|
/**
|
|
5
5
|
* Options shared by the commands that select files with .distignore and
|
|
@@ -40,26 +40,6 @@ export declare function checkDirectory(path: string): Promise<void>;
|
|
|
40
40
|
* @return Whether the path is a directory.
|
|
41
41
|
*/
|
|
42
42
|
export declare function isDirectory(path: string): Promise<boolean>;
|
|
43
|
-
/**
|
|
44
|
-
* Ignore a file that the command writes or reads, such as the checksums
|
|
45
|
-
* manifest, when it's inside the selected directory.
|
|
46
|
-
*
|
|
47
|
-
* @param rules Matcher from loadFileRules().
|
|
48
|
-
* @param sourceDir Selected directory.
|
|
49
|
-
* @param path Absolute file path.
|
|
50
|
-
* @return The same matcher.
|
|
51
|
-
*/
|
|
52
|
-
export declare function ignoreOwnFile(rules: FileRules, sourceDir: string, path: string): FileRules;
|
|
53
|
-
/**
|
|
54
|
-
* Ignore the signature file that "wp-release sign" writes next to a file the
|
|
55
|
-
* command writes, when it's inside the selected directory.
|
|
56
|
-
*
|
|
57
|
-
* @param rules Matcher from loadFileRules().
|
|
58
|
-
* @param sourceDir Selected directory.
|
|
59
|
-
* @param path Absolute path of the signed file.
|
|
60
|
-
* @return The same matcher.
|
|
61
|
-
*/
|
|
62
|
-
export declare function ignoreOwnSignature(rules: FileRules, sourceDir: string, path: string): FileRules;
|
|
63
43
|
/**
|
|
64
44
|
* Option for the source directory, which can also be the first positional
|
|
65
45
|
* argument.
|
|
@@ -90,3 +70,13 @@ export interface ResolveOutputInput {
|
|
|
90
70
|
* @return Absolute file path.
|
|
91
71
|
*/
|
|
92
72
|
export declare function resolveOutput(input: ResolveOutputInput): string;
|
|
73
|
+
/**
|
|
74
|
+
* Get the signature formats from the --format values of sign or the
|
|
75
|
+
* --sign-format values of zip, which can be repeated
|
|
76
|
+
* or comma-separated.
|
|
77
|
+
*
|
|
78
|
+
* @param values Option values.
|
|
79
|
+
* @return Unique formats, the default when none are given.
|
|
80
|
+
* @throws {ValidationError} If a format is unknown.
|
|
81
|
+
*/
|
|
82
|
+
export declare function parseSignatureFormats(values: string[]): SignatureFormat[];
|
package/dist/commands/args.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { stat } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
3
|
import { ValidationError } from "../errors.js";
|
|
4
|
-
import {
|
|
4
|
+
import { DEFAULT_SIGNATURE_FORMAT, SIGNATURE_FORMATS, isSignatureFormat, } from "../signing.js";
|
|
5
5
|
import { getBoolean, getString, getStrings } from "./command.js";
|
|
6
6
|
/**
|
|
7
7
|
* Options shared by the commands that select files with .distignore and
|
|
@@ -63,39 +63,6 @@ export async function isDirectory(path) {
|
|
|
63
63
|
const stats = await stat(path).catch(() => null);
|
|
64
64
|
return Boolean(stats?.isDirectory());
|
|
65
65
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Ignore a file that the command writes or reads, such as the checksums
|
|
68
|
-
* manifest, when it's inside the selected directory.
|
|
69
|
-
*
|
|
70
|
-
* @param rules Matcher from loadFileRules().
|
|
71
|
-
* @param sourceDir Selected directory.
|
|
72
|
-
* @param path Absolute file path.
|
|
73
|
-
* @return The same matcher.
|
|
74
|
-
*/
|
|
75
|
-
export function ignoreOwnFile(rules, sourceDir, path) {
|
|
76
|
-
const relativePath = relative(sourceDir, path).split('\\').join('/');
|
|
77
|
-
const isInside = relativePath &&
|
|
78
|
-
'..' !== relativePath &&
|
|
79
|
-
!relativePath.startsWith('../') &&
|
|
80
|
-
!isAbsolute(relativePath);
|
|
81
|
-
if (isInside) {
|
|
82
|
-
// Escape the gitignore wildcards so that the pattern matches only this file.
|
|
83
|
-
rules.add(`/${relativePath.replace(/[\\*?[\]!#]/g, '\\$&')}`);
|
|
84
|
-
}
|
|
85
|
-
return rules;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Ignore the signature file that "wp-release sign" writes next to a file the
|
|
89
|
-
* command writes, when it's inside the selected directory.
|
|
90
|
-
*
|
|
91
|
-
* @param rules Matcher from loadFileRules().
|
|
92
|
-
* @param sourceDir Selected directory.
|
|
93
|
-
* @param path Absolute path of the signed file.
|
|
94
|
-
* @return The same matcher.
|
|
95
|
-
*/
|
|
96
|
-
export function ignoreOwnSignature(rules, sourceDir, path) {
|
|
97
|
-
return ignoreOwnFile(rules, sourceDir, path + SIGNATURE_EXTENSION);
|
|
98
|
-
}
|
|
99
66
|
/**
|
|
100
67
|
* Option for the source directory, which can also be the first positional
|
|
101
68
|
* argument.
|
|
@@ -129,3 +96,25 @@ export function getSourceDirArg(values, positionals) {
|
|
|
129
96
|
export function resolveOutput(input) {
|
|
130
97
|
return resolve(input.cwd, input.output ?? input.filename);
|
|
131
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Get the signature formats from the --format values of sign or the
|
|
101
|
+
* --sign-format values of zip, which can be repeated
|
|
102
|
+
* or comma-separated.
|
|
103
|
+
*
|
|
104
|
+
* @param values Option values.
|
|
105
|
+
* @return Unique formats, the default when none are given.
|
|
106
|
+
* @throws {ValidationError} If a format is unknown.
|
|
107
|
+
*/
|
|
108
|
+
export function parseSignatureFormats(values) {
|
|
109
|
+
const names = values
|
|
110
|
+
.flatMap((value) => value.split(','))
|
|
111
|
+
.map((name) => name.trim())
|
|
112
|
+
.filter(Boolean);
|
|
113
|
+
const unknown = names.filter((name) => !isSignatureFormat(name));
|
|
114
|
+
if (unknown.length) {
|
|
115
|
+
throw new ValidationError(`Unknown signature format ${unknown.join(', ')}, use ${Object.keys(SIGNATURE_FORMATS).join(', ')}.`);
|
|
116
|
+
}
|
|
117
|
+
return names.length
|
|
118
|
+
? [...new Set(names.filter(isSignatureFormat))]
|
|
119
|
+
: [DEFAULT_SIGNATURE_FORMAT];
|
|
120
|
+
}
|
|
@@ -29,7 +29,7 @@ declare const _default: {
|
|
|
29
29
|
readonly type: "string";
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
|
-
run({ values, cwd, configFile, logger, terminal }: import("./command.ts").CommandContext): Promise<{
|
|
32
|
+
run({ values, cwd, configFile, tagFormat, logger, terminal }: import("./command.ts").CommandContext): Promise<{
|
|
33
33
|
exitCode: number;
|
|
34
34
|
result: {
|
|
35
35
|
file: string;
|
|
@@ -94,7 +94,7 @@ export default {
|
|
|
94
94
|
--summary <text> Customer-facing release note
|
|
95
95
|
--empty Record that this change does not need a release
|
|
96
96
|
--since <ref> Compare changed files with this git ref (default:
|
|
97
|
-
|
|
97
|
+
<remote>/<baseBranch>)
|
|
98
98
|
--name <name> Changeset filename (default: random identifier)
|
|
99
99
|
|
|
100
100
|
Use --package and --bump pairs for package releases, or --empty for changes
|
|
@@ -104,11 +104,12 @@ ref, including uncommitted files, and have no changeset yet. Without
|
|
|
104
104
|
--package and --bump in a terminal, the command asks for the packages, with
|
|
105
105
|
the changed ones preselected, their bumps and the release note.`,
|
|
106
106
|
options: changesetAddArgs,
|
|
107
|
-
async run({ values, cwd, configFile, logger, terminal }) {
|
|
107
|
+
async run({ values, cwd, configFile, tagFormat, logger, terminal }) {
|
|
108
108
|
const input = parseChangesetAddArgs(values);
|
|
109
109
|
const release = new ChangesetRelease({
|
|
110
110
|
cwd,
|
|
111
111
|
...(configFile ? { configFile } : {}),
|
|
112
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
112
113
|
});
|
|
113
114
|
const changeset = await getChangeset(release, input, terminal);
|
|
114
115
|
// Adding resolves the package paths and rejects a package passed twice.
|
|
@@ -26,7 +26,7 @@ declare const _default: {
|
|
|
26
26
|
readonly type: "string";
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
-
run({ values, cwd, configFile, logger }: import("./command.ts").CommandContext): Promise<{
|
|
29
|
+
run({ values, cwd, configFile, tagFormat, logger }: import("./command.ts").CommandContext): Promise<{
|
|
30
30
|
exitCode: number;
|
|
31
31
|
result: {
|
|
32
32
|
releases: {
|
|
@@ -10,11 +10,12 @@ export default {
|
|
|
10
10
|
Exit status is 2 when a changed package has no changeset added since the comparison base.
|
|
11
11
|
An empty changeset added since the comparison base counts as an explicit no-release decision.`,
|
|
12
12
|
options: changesetStatusArgs,
|
|
13
|
-
async run({ values, cwd, configFile, logger }) {
|
|
13
|
+
async run({ values, cwd, configFile, tagFormat, logger }) {
|
|
14
14
|
const { since } = parseChangesetStatusArgs(values);
|
|
15
15
|
const result = await getChangesetStatus({
|
|
16
16
|
cwd,
|
|
17
17
|
...(configFile ? { configFile } : {}),
|
|
18
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
18
19
|
...(since ? { since } : {}),
|
|
19
20
|
});
|
|
20
21
|
logger.summary(() => {
|
|
@@ -24,7 +24,7 @@ declare const _default: {
|
|
|
24
24
|
readonly type: "string";
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
|
-
run({ values, cwd, configFile, logger }: import("./command.ts").CommandContext): Promise<{
|
|
27
|
+
run({ values, cwd, configFile, tagFormat, logger }: import("./command.ts").CommandContext): Promise<{
|
|
28
28
|
exitCode: number;
|
|
29
29
|
result: import("../changeset-release.ts").ChangesetTagResult;
|
|
30
30
|
}>;
|
|
@@ -14,7 +14,8 @@ export default {
|
|
|
14
14
|
the configured root (repeatable)
|
|
15
15
|
--version <version> Fail unless the single --package is at this version;
|
|
16
16
|
the version to tag for packages versioned by git tags
|
|
17
|
-
--push Push newly created tags to
|
|
17
|
+
--push Push newly created tags to the configured remote
|
|
18
|
+
(default: origin), one at a time
|
|
18
19
|
|
|
19
20
|
Tags are created only when absent, so rerunning after a partial failure is
|
|
20
21
|
safe. Before a tag is created, every configured version target must match the
|
|
@@ -23,11 +24,12 @@ and pre-release flag of its release, for a workflow step that creates the
|
|
|
23
24
|
GitHub Release. --untagged lists only the releases that still need a tag, for
|
|
24
25
|
example to release each of them with a separate workflow.`,
|
|
25
26
|
options: changesetTagArgs,
|
|
26
|
-
async run({ values, cwd, configFile, logger }) {
|
|
27
|
+
async run({ values, cwd, configFile, tagFormat, logger }) {
|
|
27
28
|
const args = parseChangesetTagArgs(values);
|
|
28
29
|
const result = await tagChangesets({
|
|
29
30
|
cwd,
|
|
30
31
|
...(configFile ? { configFile } : {}),
|
|
32
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
31
33
|
...args,
|
|
32
34
|
});
|
|
33
35
|
result.tags.forEach((item) => {
|
|
@@ -36,7 +36,7 @@ declare const _default: {
|
|
|
36
36
|
readonly type: "string";
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
|
-
run({ values, cwd, configFile, logger }: import("./command.ts").CommandContext): Promise<{
|
|
39
|
+
run({ values, cwd, configFile, tagFormat, logger }: import("./command.ts").CommandContext): Promise<{
|
|
40
40
|
exitCode: number;
|
|
41
41
|
result: {
|
|
42
42
|
date: string;
|
|
@@ -28,11 +28,12 @@ The readme Stable tag keeps the last stable version.
|
|
|
28
28
|
With --snapshot, build and publish the versioned files without committing
|
|
29
29
|
them, for example to test a pull request.`,
|
|
30
30
|
options: changesetVersionArgs,
|
|
31
|
-
async run({ values, cwd, configFile, logger }) {
|
|
31
|
+
async run({ values, cwd, configFile, tagFormat, logger }) {
|
|
32
32
|
const args = parseChangesetVersionArgs(values);
|
|
33
33
|
const result = await versionChangesets({
|
|
34
34
|
cwd,
|
|
35
35
|
...(configFile ? { configFile } : {}),
|
|
36
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
36
37
|
...args,
|
|
37
38
|
});
|
|
38
39
|
result.releases.forEach((release) => logger.info(`${release.package.name}: ${release.currentVersion} → ${release.nextVersion} (${release.bump})`));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { basename, resolve } from 'node:path';
|
|
2
2
|
import { CHECKSUMS_EXTENSION, createChecksums, writeChecksums, } from "../checksums.js";
|
|
3
|
-
import { loadFileRules, resolveFileSelection } from "../file-selection.js";
|
|
3
|
+
import { ignoreOwnFile, ignoreOwnSignature, loadFileRules, resolveFileSelection, } from "../file-selection.js";
|
|
4
4
|
import { FILENAME_FORMAT, formatFilename } from "../filename.js";
|
|
5
5
|
import { readPackageMeta } from "../package-meta.js";
|
|
6
6
|
import { getChecksumsSummary } from "../summary.js";
|
|
7
|
-
import { checkDirectory, fileSelectionArgs, getFileSelectionInput, getSourceDirArg,
|
|
7
|
+
import { checkDirectory, fileSelectionArgs, getFileSelectionInput, getSourceDirArg, resolveOutput, sourceDirArgs, } from "./args.js";
|
|
8
8
|
import { getBoolean, getString } from "./command.js";
|
|
9
9
|
export default {
|
|
10
10
|
name: 'checksums',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ParseArgsOptionsConfig } from 'node:util';
|
|
2
2
|
import type { PromptTerminal } from '../changeset-prompt.ts';
|
|
3
3
|
import type { Logger } from '../logger.ts';
|
|
4
|
+
import type { SvnRunner } from '../svn.ts';
|
|
4
5
|
/**
|
|
5
6
|
* Parsed option values from node:util parseArgs().
|
|
6
7
|
*/
|
|
@@ -14,8 +15,12 @@ export interface CommandContext {
|
|
|
14
15
|
cwd: string;
|
|
15
16
|
/** Explicit JavaScript release config path from --config, if supplied. */
|
|
16
17
|
configFile?: string;
|
|
18
|
+
/** Tag format from --tag-format, which replaces the tagFormat of the config. */
|
|
19
|
+
tagFormat?: string;
|
|
17
20
|
/** Logger for the command output. */
|
|
18
21
|
logger: Logger;
|
|
22
|
+
/** SVN command runner supplied by a wrapper, instead of spawning svn directly. */
|
|
23
|
+
svnRunner?: SvnRunner;
|
|
19
24
|
/** Terminal for interactive prompts, only when the CLI runs in one and prints no JSON. */
|
|
20
25
|
terminal?: PromptTerminal;
|
|
21
26
|
}
|
|
@@ -47,7 +47,7 @@ declare const _default: {
|
|
|
47
47
|
type: "string";
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
|
-
run({ values, positionals, cwd, configFile, logger }: import("./command.ts").CommandContext): Promise<{
|
|
50
|
+
run({ values, positionals, cwd, configFile, tagFormat, logger }: import("./command.ts").CommandContext): Promise<{
|
|
51
51
|
exitCode: number;
|
|
52
52
|
result: {
|
|
53
53
|
packages: import("../package-deploy.ts").PackageDeployPlanItem[];
|
|
@@ -114,7 +114,7 @@ Examples:
|
|
|
114
114
|
...packageDeployArgs,
|
|
115
115
|
'dry-run': { type: 'boolean' },
|
|
116
116
|
},
|
|
117
|
-
async run({ values, positionals, cwd, configFile, logger }) {
|
|
117
|
+
async run({ values, positionals, cwd, configFile, tagFormat, logger }) {
|
|
118
118
|
const { ref, packages, list } = getPackageDeployArgs(values, positionals, TARGET_FLAGS);
|
|
119
119
|
if (ref) {
|
|
120
120
|
const deploys = await getGitDeploys({
|
|
@@ -123,6 +123,7 @@ Examples:
|
|
|
123
123
|
packages,
|
|
124
124
|
dryRun: getBoolean(values, 'dry-run'),
|
|
125
125
|
...(configFile ? { configFile } : {}),
|
|
126
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
126
127
|
});
|
|
127
128
|
return list
|
|
128
129
|
? listPackageDeploys(deploys, logger, ref)
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { DeployInput } from '../deploy-options.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DeployResult } from '../svn-deploy.ts';
|
|
3
|
+
import type { PackageDeployPlanItem } from '../package-deploy.ts';
|
|
4
|
+
import type { CommandOutcome, ParsedValues } from './command.ts';
|
|
5
|
+
import type { PackageDeployOutcome } from './package-deploys.ts';
|
|
6
|
+
/** Results of a single deploy, a configured plan or configured deploys. */
|
|
7
|
+
export type DeploySvnResult = DeployResult | {
|
|
8
|
+
packages: PackageDeployPlanItem[];
|
|
9
|
+
} | {
|
|
10
|
+
deploys: PackageDeployOutcome<DeployResult>[];
|
|
11
|
+
};
|
|
3
12
|
export interface DeployArgsInput {
|
|
4
13
|
/** Parsed CLI values. */
|
|
5
14
|
values: ParsedValues;
|
|
@@ -76,19 +85,6 @@ declare const _default: {
|
|
|
76
85
|
type: "string";
|
|
77
86
|
};
|
|
78
87
|
};
|
|
79
|
-
run({ values, positionals, cwd, configFile, logger }: import("./command.ts").CommandContext): Promise<
|
|
80
|
-
exitCode: number;
|
|
81
|
-
result: {
|
|
82
|
-
packages: import("../package-deploy.ts").PackageDeployPlanItem[];
|
|
83
|
-
};
|
|
84
|
-
} | {
|
|
85
|
-
exitCode: number;
|
|
86
|
-
result: {
|
|
87
|
-
deploys: import("./package-deploys.ts").PackageDeployOutcome<import("../svn-deploy.ts").DeployResult>[];
|
|
88
|
-
};
|
|
89
|
-
} | {
|
|
90
|
-
exitCode: number;
|
|
91
|
-
result: import("../svn-deploy.ts").DeployResult;
|
|
92
|
-
}>;
|
|
88
|
+
run({ values, positionals, cwd, configFile, tagFormat, logger, svnRunner, }: import("./command.ts").CommandContext): Promise<CommandOutcome<DeploySvnResult>>;
|
|
93
89
|
};
|
|
94
90
|
export default _default;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveDeployOptions } from "../deploy-options.js";
|
|
2
2
|
import { getSvnDeploys } from "../package-deploy.js";
|
|
3
3
|
import { SvnDeploy } from "../svn-deploy.js";
|
|
4
|
+
import { Svn } from "../svn.js";
|
|
4
5
|
import { fileSelectionArgs, getFileSelectionInput, getSourceDirArg, sourceDirArgs, } from "./args.js";
|
|
5
6
|
import { getBoolean, getString } from "./command.js";
|
|
6
7
|
import { getPackageDeployArgs, listPackageDeploys, packageDeployArgs, runPackageDeploys, } from "./package-deploys.js";
|
|
@@ -23,6 +24,26 @@ const TARGET_FLAGS = [
|
|
|
23
24
|
'svn-url',
|
|
24
25
|
'message',
|
|
25
26
|
];
|
|
27
|
+
/**
|
|
28
|
+
* Run an SVN deploy with the optional command runner supplied by a wrapper.
|
|
29
|
+
*
|
|
30
|
+
* @param input Deploy input.
|
|
31
|
+
* @param logger Logger for the deploy.
|
|
32
|
+
* @param runner Optional SVN command runner.
|
|
33
|
+
* @return Deploy result.
|
|
34
|
+
*/
|
|
35
|
+
async function runDeploy(input, logger, runner) {
|
|
36
|
+
const options = resolveDeployOptions(input);
|
|
37
|
+
const svn = runner
|
|
38
|
+
? new Svn({
|
|
39
|
+
runner,
|
|
40
|
+
username: options.svnUsername,
|
|
41
|
+
password: options.svnPassword,
|
|
42
|
+
logger,
|
|
43
|
+
})
|
|
44
|
+
: undefined;
|
|
45
|
+
return new SvnDeploy(options, logger, svn).run();
|
|
46
|
+
}
|
|
26
47
|
/**
|
|
27
48
|
* Map the parsed "deploy-svn" arguments to resolveDeployOptions() input.
|
|
28
49
|
* Flags that aren't passed stay undefined, so that the same defaults apply
|
|
@@ -135,7 +156,7 @@ Examples:
|
|
|
135
156
|
...packageDeployArgs,
|
|
136
157
|
'dry-run': { type: 'boolean' },
|
|
137
158
|
},
|
|
138
|
-
async run({ values, positionals, cwd, configFile, logger }) {
|
|
159
|
+
async run({ values, positionals, cwd, configFile, tagFormat, logger, svnRunner, }) {
|
|
139
160
|
const { ref, packages, list } = getPackageDeployArgs(values, positionals, TARGET_FLAGS);
|
|
140
161
|
if (ref) {
|
|
141
162
|
const deploys = await getSvnDeploys({
|
|
@@ -144,17 +165,17 @@ Examples:
|
|
|
144
165
|
packages,
|
|
145
166
|
dryRun: getBoolean(values, 'dry-run'),
|
|
146
167
|
...(configFile ? { configFile } : {}),
|
|
168
|
+
...(tagFormat ? { tagFormat } : {}),
|
|
147
169
|
});
|
|
148
170
|
return list
|
|
149
171
|
? listPackageDeploys(deploys, logger, ref)
|
|
150
|
-
: runPackageDeploys(deploys, (input) =>
|
|
172
|
+
: runPackageDeploys(deploys, (input) => runDeploy({
|
|
151
173
|
...input,
|
|
152
174
|
svnUsername: getString(values, 'svn-username'),
|
|
153
175
|
force: getBoolean(values, 'force'),
|
|
154
|
-
}
|
|
176
|
+
}, logger, svnRunner), logger, ref);
|
|
155
177
|
}
|
|
156
|
-
const
|
|
157
|
-
const result = await new SvnDeploy(options, logger).run();
|
|
178
|
+
const result = await runDeploy(getDeployInputFromArgs({ values, positionals, cwd }), logger, svnRunner);
|
|
158
179
|
return { exitCode: 0, result };
|
|
159
180
|
},
|
|
160
181
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SignatureFormat } from '../signing.ts';
|
|
1
2
|
import type { CommandOutcome } from './command.ts';
|
|
2
3
|
/** Generated Ed25519 signing keys. */
|
|
3
4
|
export interface KeygenResult {
|
|
@@ -5,6 +6,8 @@ export interface KeygenResult {
|
|
|
5
6
|
privateKey: string;
|
|
6
7
|
/** Base64 Ed25519 public key for verification. */
|
|
7
8
|
publicKey: string;
|
|
9
|
+
/** Public key in the form of each signature format. */
|
|
10
|
+
publicKeys: Record<SignatureFormat, string>;
|
|
8
11
|
}
|
|
9
12
|
declare const _default: {
|
|
10
13
|
name: string;
|
package/dist/commands/keygen.js
CHANGED
|
@@ -8,7 +8,10 @@ export default {
|
|
|
8
8
|
help: `Generate a signing key pair for "wp-release sign" and "wp-release verify".
|
|
9
9
|
|
|
10
10
|
The private seed is printed once as WP_RELEASE_SIGNING_KEY. Store it securely
|
|
11
|
-
and never commit it or share it. The public key can be distributed to verifiers
|
|
11
|
+
and never commit it or share it. The public key can be distributed to verifiers.
|
|
12
|
+
It's also printed as a minisign public key for "minisign -V -P" and as an
|
|
13
|
+
ssh-ed25519 public key for the allowed_signers file of "ssh-keygen -Y verify",
|
|
14
|
+
since the same key signs every format of "wp-release sign".`,
|
|
12
15
|
options: {},
|
|
13
16
|
async run({ values, logger }) {
|
|
14
17
|
if (getBoolean(values, 'github-output')) {
|
|
@@ -17,6 +20,8 @@ and never commit it or share it. The public key can be distributed to verifiers.
|
|
|
17
20
|
const result = generateSigningKeyPair();
|
|
18
21
|
logger.info(`WP_RELEASE_SIGNING_KEY=${result.privateKey}`);
|
|
19
22
|
logger.info(`Public key: ${result.publicKey}`);
|
|
23
|
+
logger.info(`Minisign public key: ${result.publicKeys.minisign}`);
|
|
24
|
+
logger.info(`SSH public key: ${result.publicKeys.ssh}`);
|
|
20
25
|
logger.info('Store the private seed securely; it cannot be recovered from the public key.');
|
|
21
26
|
return { exitCode: 0, result };
|
|
22
27
|
},
|
|
@@ -22,6 +22,14 @@ export interface PackageDeployOutcome<Result> {
|
|
|
22
22
|
package: string;
|
|
23
23
|
/** Package, target and ref, with credentials redacted. */
|
|
24
24
|
label: string;
|
|
25
|
+
/** Repository or WordPress.org plugin of the target, with credentials redacted. */
|
|
26
|
+
target: string;
|
|
27
|
+
/** Tag or branch that the deploy writes in the target. */
|
|
28
|
+
targetRef: string;
|
|
29
|
+
/** Host of a remote target repository, like github.com. */
|
|
30
|
+
targetHost?: string;
|
|
31
|
+
/** Path of a remote target repository on its host, like owner/repo. */
|
|
32
|
+
targetPath?: string;
|
|
25
33
|
version?: string;
|
|
26
34
|
branch?: string;
|
|
27
35
|
/** Deploy result, unless it failed. */
|
|
@@ -78,6 +78,11 @@ async function runDeploy(item, deploy, logger) {
|
|
|
78
78
|
const outcome = {
|
|
79
79
|
package: item.package.name,
|
|
80
80
|
label: item.label,
|
|
81
|
+
target: item.target,
|
|
82
|
+
targetRef: item.targetRef,
|
|
83
|
+
...(item.targetHost
|
|
84
|
+
? { targetHost: item.targetHost, targetPath: item.targetPath }
|
|
85
|
+
: {}),
|
|
81
86
|
...item.release,
|
|
82
87
|
};
|
|
83
88
|
try {
|
package/dist/commands/sign.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import type { SignatureFormat } from '../signing.ts';
|
|
1
2
|
import type { CommandOutcome } from './command.ts';
|
|
2
3
|
/** Result of the sign command. */
|
|
3
4
|
export interface SignResult {
|
|
4
|
-
/** Absolute paths of the written
|
|
5
|
+
/** Absolute paths of the written signature files. */
|
|
5
6
|
signatures: string[];
|
|
7
|
+
/** Signature formats that were written. */
|
|
8
|
+
formats: SignatureFormat[];
|
|
6
9
|
/** Base64 public key of the signing key. */
|
|
7
10
|
publicKey: string;
|
|
11
|
+
/** Public key of the signing key in the form of each signature format. */
|
|
12
|
+
publicKeys: Record<SignatureFormat, string>;
|
|
8
13
|
}
|
|
9
14
|
declare const _default: {
|
|
10
15
|
name: string;
|
|
@@ -12,6 +17,10 @@ declare const _default: {
|
|
|
12
17
|
summary: string;
|
|
13
18
|
help: string;
|
|
14
19
|
options: {
|
|
20
|
+
format: {
|
|
21
|
+
type: "string";
|
|
22
|
+
multiple: true;
|
|
23
|
+
};
|
|
15
24
|
force: {
|
|
16
25
|
type: "boolean";
|
|
17
26
|
};
|