@wpelevator/wp-release 0.8.0 → 0.10.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 +49 -7
- package/dist/changeset-config.d.ts +75 -0
- package/dist/changeset-config.js +48 -0
- package/dist/changeset-release.d.ts +3 -0
- package/dist/changeset-release.js +614 -12
- package/dist/changesets.d.ts +2 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +2 -0
- package/dist/commands/args.d.ts +1 -0
- package/dist/commands/args.js +2 -0
- package/dist/commands/changeset-args.d.ts +5 -0
- package/dist/commands/changeset-args.js +2 -0
- package/dist/commands/changeset-status.d.ts +2 -0
- package/dist/commands/changeset-status.js +6 -2
- package/dist/commands/changeset-version.d.ts +3 -0
- package/dist/commands/changeset-version.js +2 -1
- package/dist/commands/checksums.js +2 -0
- package/dist/commands/deploy-git.js +1 -0
- package/dist/commands/deploy-svn.js +1 -0
- package/dist/commands/keygen.d.ts +17 -0
- package/dist/commands/keygen.js +23 -0
- package/dist/commands/zip.js +2 -0
- package/dist/deploy-options.d.ts +2 -0
- package/dist/deploy-options.js +1 -0
- package/dist/file-selection.d.ts +6 -0
- package/dist/file-selection.js +101 -5
- package/dist/git-deploy.d.ts +2 -0
- package/dist/git-deploy.js +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/signing.d.ts +9 -0
- package/dist/signing.js +18 -1
- package/package.json +3 -1
package/dist/changesets.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export interface PackageRelease {
|
|
|
31
31
|
currentVersion: string;
|
|
32
32
|
nextVersion: string;
|
|
33
33
|
changesets: Changeset[];
|
|
34
|
+
/** Names of released source packages that this dependent release bundles; absent for changeset-driven releases. */
|
|
35
|
+
sources?: string[];
|
|
34
36
|
}
|
|
35
37
|
/** A package release with its formatted changelog entries, once versioned. */
|
|
36
38
|
export interface VersionedRelease extends PackageRelease {
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ChecksumsResult } from './commands/checksums.ts';
|
|
2
2
|
import type { SignResult } from './commands/sign.ts';
|
|
3
|
+
import type { KeygenResult } from './commands/keygen.ts';
|
|
3
4
|
import type { ZipResult } from './commands/zip.ts';
|
|
4
5
|
import type { ChangesetVersionResult } from './commands/changeset-version.ts';
|
|
5
6
|
import { Logger } from './logger.ts';
|
|
@@ -44,6 +45,7 @@ export interface CommandResults {
|
|
|
44
45
|
zip: ZipResult;
|
|
45
46
|
checksums: ChecksumsResult;
|
|
46
47
|
sign: SignResult;
|
|
48
|
+
keygen: KeygenResult;
|
|
47
49
|
'changeset-add': import('./commands/changeset-add.ts').ChangesetAddResult;
|
|
48
50
|
'changeset-status': import('./commands/changeset-status.ts').ChangesetStatusResult;
|
|
49
51
|
'changeset-version': ChangesetVersionResult;
|
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,7 @@ import { parseArgs } from 'node:util';
|
|
|
3
3
|
import zip from "./commands/zip.js";
|
|
4
4
|
import checksums from "./commands/checksums.js";
|
|
5
5
|
import sign from "./commands/sign.js";
|
|
6
|
+
import keygen from "./commands/keygen.js";
|
|
6
7
|
import verify from "./commands/verify.js";
|
|
7
8
|
import versionCheck from "./commands/version-check.js";
|
|
8
9
|
import deploySvn from "./commands/deploy-svn.js";
|
|
@@ -23,6 +24,7 @@ export const commands = [
|
|
|
23
24
|
zip,
|
|
24
25
|
checksums,
|
|
25
26
|
sign,
|
|
27
|
+
keygen,
|
|
26
28
|
verify,
|
|
27
29
|
versionCheck,
|
|
28
30
|
deploySvn,
|
package/dist/commands/args.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare const fileSelectionArgs: ParseArgsOptionsConfig;
|
|
|
15
15
|
export declare function getFileSelectionInput(values: ParsedValues): {
|
|
16
16
|
distignore: string | false | undefined;
|
|
17
17
|
exclude: string[];
|
|
18
|
+
excludeGitattributes: boolean;
|
|
18
19
|
};
|
|
19
20
|
/**
|
|
20
21
|
* Check that a command got no more positional arguments than it accepts.
|
package/dist/commands/args.js
CHANGED
|
@@ -11,6 +11,7 @@ export const fileSelectionArgs = {
|
|
|
11
11
|
distignore: { type: 'string' },
|
|
12
12
|
'no-distignore': { type: 'boolean' },
|
|
13
13
|
exclude: { type: 'string', multiple: true },
|
|
14
|
+
'exclude-gitattributes': { type: 'boolean' },
|
|
14
15
|
};
|
|
15
16
|
/**
|
|
16
17
|
* Map the parsed file selection flags to resolveFileSelection() input.
|
|
@@ -24,6 +25,7 @@ export function getFileSelectionInput(values) {
|
|
|
24
25
|
? false
|
|
25
26
|
: getString(values, 'distignore'),
|
|
26
27
|
exclude: getStrings(values, 'exclude'),
|
|
28
|
+
excludeGitattributes: getBoolean(values, 'exclude-gitattributes'),
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
@@ -65,12 +65,17 @@ export declare const changesetVersionArgs: {
|
|
|
65
65
|
readonly type: "string";
|
|
66
66
|
readonly multiple: true;
|
|
67
67
|
};
|
|
68
|
+
readonly 'no-dependents': {
|
|
69
|
+
readonly type: "boolean";
|
|
70
|
+
};
|
|
68
71
|
};
|
|
69
72
|
/** Parsed input for `changeset-version`. */
|
|
70
73
|
export interface ChangesetVersionArgs {
|
|
71
74
|
dryRun: boolean;
|
|
72
75
|
date?: string;
|
|
73
76
|
packages?: string[];
|
|
77
|
+
/** Whether the selected sources release their configured dependents; defaults to true. */
|
|
78
|
+
dependents: boolean;
|
|
74
79
|
}
|
|
75
80
|
/**
|
|
76
81
|
* Validate and normalize a release date option.
|
|
@@ -75,6 +75,7 @@ export const changesetVersionArgs = {
|
|
|
75
75
|
'dry-run': { type: 'boolean' },
|
|
76
76
|
date: { type: 'string' },
|
|
77
77
|
package: { type: 'string', multiple: true },
|
|
78
|
+
'no-dependents': { type: 'boolean' },
|
|
78
79
|
};
|
|
79
80
|
/**
|
|
80
81
|
* Validate and normalize a release date option.
|
|
@@ -111,6 +112,7 @@ export function parseChangesetVersionArgs(values) {
|
|
|
111
112
|
}
|
|
112
113
|
return {
|
|
113
114
|
dryRun: getBoolean(values, 'dry-run'),
|
|
115
|
+
dependents: !getBoolean(values, 'no-dependents'),
|
|
114
116
|
...(date ? { date } : {}),
|
|
115
117
|
...(packages.length ? { packages } : {}),
|
|
116
118
|
};
|
|
@@ -13,6 +13,7 @@ export interface ChangesetStatusResult {
|
|
|
13
13
|
changedPackages: string[];
|
|
14
14
|
changedPackageFiles: Record<string, string[]>;
|
|
15
15
|
missingChangesets: string[];
|
|
16
|
+
warnings: string[];
|
|
16
17
|
}
|
|
17
18
|
declare const _default: {
|
|
18
19
|
name: string;
|
|
@@ -37,6 +38,7 @@ declare const _default: {
|
|
|
37
38
|
changedPackages: string[];
|
|
38
39
|
changedPackageFiles: Record<string, string[]>;
|
|
39
40
|
missingChangesets: string[];
|
|
41
|
+
warnings: string[];
|
|
40
42
|
};
|
|
41
43
|
}>;
|
|
42
44
|
};
|
|
@@ -20,8 +20,11 @@ An empty changeset added since the comparison base counts as an explicit no-rele
|
|
|
20
20
|
logger.summary(() => {
|
|
21
21
|
const rows = result.changedPackages.map((name) => {
|
|
22
22
|
let status = 'no release requested';
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const release = result.releases.find((item) => item.package.name === name);
|
|
24
|
+
if (release) {
|
|
25
|
+
status = release.changesets.length
|
|
26
|
+
? 'changeset found'
|
|
27
|
+
: 'releases with its sources';
|
|
25
28
|
}
|
|
26
29
|
if (result.missingChangesets.includes(name)) {
|
|
27
30
|
status = 'missing changeset';
|
|
@@ -49,6 +52,7 @@ An empty changeset added since the comparison base counts as an explicit no-rele
|
|
|
49
52
|
else if (!result.releases.length) {
|
|
50
53
|
logger.info('No pending package releases.');
|
|
51
54
|
}
|
|
55
|
+
result.warnings.forEach((warning) => logger.warning(warning));
|
|
52
56
|
return {
|
|
53
57
|
exitCode: result.missingChangesets.length ? 2 : 0,
|
|
54
58
|
result: {
|
|
@@ -26,6 +26,9 @@ declare const _default: {
|
|
|
26
26
|
readonly type: "string";
|
|
27
27
|
readonly multiple: true;
|
|
28
28
|
};
|
|
29
|
+
readonly 'no-dependents': {
|
|
30
|
+
readonly type: "boolean";
|
|
31
|
+
};
|
|
29
32
|
};
|
|
30
33
|
run({ values, cwd, configFile, logger }: import("./command.ts").CommandContext): Promise<{
|
|
31
34
|
exitCode: number;
|
|
@@ -3,12 +3,13 @@ import { getChangesetVersionSummary } from "../summary.js";
|
|
|
3
3
|
import { parseChangesetVersionArgs, changesetVersionArgs, } from "./changeset-args.js";
|
|
4
4
|
export default {
|
|
5
5
|
name: 'changeset-version',
|
|
6
|
-
usage: 'changeset-version [--dry-run] [--date <YYYY-MM-DD>] [--package <name>]',
|
|
6
|
+
usage: 'changeset-version [--dry-run] [--date <YYYY-MM-DD>] [--package <name>] [--no-dependents]',
|
|
7
7
|
summary: 'Apply pending version bumps and changelog entries.',
|
|
8
8
|
help: `Options:
|
|
9
9
|
--dry-run Print the release plan without writing files
|
|
10
10
|
--date <YYYY-MM-DD> Changelog date (default: today)
|
|
11
11
|
--package <name> Version only this package (repeatable)
|
|
12
|
+
--no-dependents Leave the configured dependents of the selected sources out
|
|
12
13
|
|
|
13
14
|
Updates configured version files, prepends changelog entries and removes the
|
|
14
15
|
applied changeset files. With --package, a changeset that also names other
|
|
@@ -28,6 +28,8 @@ Options:
|
|
|
28
28
|
--no-distignore Don't read any ignore file
|
|
29
29
|
--exclude <patterns> Extra gitignore-style patterns, comma-separated or
|
|
30
30
|
repeated, like build/,assets/*,images/**/*
|
|
31
|
+
--exclude-gitattributes Also exclude paths marked export-ignore in Git
|
|
32
|
+
attributes (requires a Git working tree)
|
|
31
33
|
--force Overwrite an existing --output file
|
|
32
34
|
|
|
33
35
|
The manifest uses the WordPress.org plugin checksums format, with paths
|
|
@@ -46,6 +46,7 @@ Options:
|
|
|
46
46
|
--distignore <file> Ignore file (default: <source-dir>/.distignore when present)
|
|
47
47
|
--no-distignore Don't read any ignore file
|
|
48
48
|
--exclude <patterns> Extra gitignore-style patterns, comma-separated or repeated
|
|
49
|
+
--exclude-gitattributes Also exclude paths marked export-ignore in Git attributes
|
|
49
50
|
--message <text> Release commit message
|
|
50
51
|
--dry-run Run everything except the push
|
|
51
52
|
|
|
@@ -60,6 +60,7 @@ Options:
|
|
|
60
60
|
--distignore <file> Ignore file (default: <source-dir>/.distignore when present)
|
|
61
61
|
--no-distignore Don't read any ignore file
|
|
62
62
|
--exclude <patterns> Extra gitignore-style patterns, comma-separated or repeated
|
|
63
|
+
--exclude-gitattributes Also exclude paths marked export-ignore in Git attributes
|
|
63
64
|
--svn-url <url> Repository URL with {slug}
|
|
64
65
|
(default: https://plugins.svn.wordpress.org/{slug}/)
|
|
65
66
|
--svn-username <name> SVN username (env: SVN_USERNAME, password: SVN_PASSWORD)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CommandOutcome } from './command.ts';
|
|
2
|
+
/** Generated Ed25519 signing keys. */
|
|
3
|
+
export interface KeygenResult {
|
|
4
|
+
/** Base64 Ed25519 seed for WP_RELEASE_SIGNING_KEY. */
|
|
5
|
+
privateKey: string;
|
|
6
|
+
/** Base64 Ed25519 public key for verification. */
|
|
7
|
+
publicKey: string;
|
|
8
|
+
}
|
|
9
|
+
declare const _default: {
|
|
10
|
+
name: string;
|
|
11
|
+
usage: string;
|
|
12
|
+
summary: string;
|
|
13
|
+
help: string;
|
|
14
|
+
options: {};
|
|
15
|
+
run({ values, logger }: import("./command.ts").CommandContext): Promise<CommandOutcome<KeygenResult>>;
|
|
16
|
+
};
|
|
17
|
+
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ValidationError } from "../errors.js";
|
|
2
|
+
import { generateSigningKeyPair } from "../signing.js";
|
|
3
|
+
import { getBoolean } from "./command.js";
|
|
4
|
+
export default {
|
|
5
|
+
name: 'keygen',
|
|
6
|
+
usage: 'keygen',
|
|
7
|
+
summary: 'Generate an Ed25519 signing key pair.',
|
|
8
|
+
help: `Generate a signing key pair for "wp-release sign" and "wp-release verify".
|
|
9
|
+
|
|
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.`,
|
|
12
|
+
options: {},
|
|
13
|
+
async run({ values, logger }) {
|
|
14
|
+
if (getBoolean(values, 'github-output')) {
|
|
15
|
+
throw new ValidationError('keygen cannot be used with --github-output, which would store the private seed in a workflow output.');
|
|
16
|
+
}
|
|
17
|
+
const result = generateSigningKeyPair();
|
|
18
|
+
logger.info(`WP_RELEASE_SIGNING_KEY=${result.privateKey}`);
|
|
19
|
+
logger.info(`Public key: ${result.publicKey}`);
|
|
20
|
+
logger.info('Store the private seed securely; it cannot be recovered from the public key.');
|
|
21
|
+
return { exitCode: 0, result };
|
|
22
|
+
},
|
|
23
|
+
};
|
package/dist/commands/zip.js
CHANGED
|
@@ -56,6 +56,8 @@ Options:
|
|
|
56
56
|
--no-distignore Don't read any ignore file
|
|
57
57
|
--exclude <patterns> Extra gitignore-style patterns, comma-separated or
|
|
58
58
|
repeated, like build/,assets/*,images/**/*
|
|
59
|
+
--exclude-gitattributes Also exclude paths marked export-ignore in Git
|
|
60
|
+
attributes (requires a Git working tree)
|
|
59
61
|
--checksums Also write the checksums manifest of the archived
|
|
60
62
|
files next to the ZIP, with .checksums.json
|
|
61
63
|
instead of .zip
|
package/dist/deploy-options.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface DeployInput {
|
|
|
27
27
|
distignore?: string | false;
|
|
28
28
|
/** Extra gitignore-style patterns. */
|
|
29
29
|
exclude?: string | string[];
|
|
30
|
+
/** Also exclude paths marked export-ignore by Git attributes. */
|
|
31
|
+
excludeGitattributes?: boolean;
|
|
30
32
|
/** Readme file name. */
|
|
31
33
|
readme?: string;
|
|
32
34
|
/** ZIP archive to deploy instead of sourceDir. */
|
package/dist/deploy-options.js
CHANGED
package/dist/file-selection.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface FileSelectionInput {
|
|
|
21
21
|
distignore?: string | false;
|
|
22
22
|
/** Extra gitignore-style patterns, comma or newline separated. */
|
|
23
23
|
exclude?: string | string[];
|
|
24
|
+
/** Also exclude paths marked export-ignore by Git attributes. */
|
|
25
|
+
excludeGitattributes?: boolean;
|
|
24
26
|
}
|
|
25
27
|
export interface FileSelection {
|
|
26
28
|
/** Ignore file path, or null when disabled. */
|
|
@@ -29,6 +31,10 @@ export interface FileSelection {
|
|
|
29
31
|
distignoreRequired: boolean;
|
|
30
32
|
/** Extra gitignore-style patterns. */
|
|
31
33
|
exclude: string[];
|
|
34
|
+
/** Source directory, needed to resolve Git attributes. */
|
|
35
|
+
sourceDir?: string;
|
|
36
|
+
/** Also exclude paths marked export-ignore by Git attributes. */
|
|
37
|
+
excludeGitattributes?: boolean;
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
34
40
|
* Parse exclude patterns from a comma or newline separated string, an array
|
package/dist/file-selection.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
-
import { join, posix, resolve } from 'node:path';
|
|
1
|
+
import { realpath, readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, join, posix, relative, resolve } from 'node:path';
|
|
3
3
|
import ignore from 'ignore';
|
|
4
4
|
import { ValidationError } from "./errors.js";
|
|
5
|
+
import { createGitRunner } from "./git.js";
|
|
5
6
|
export const DISTIGNORE_FILENAME = '.distignore';
|
|
6
7
|
/**
|
|
7
8
|
* Version control metadata that is never released, at any depth. Without
|
|
@@ -35,11 +36,13 @@ export function parseExclude(value) {
|
|
|
35
36
|
* @return Ignore file path (or null), whether it's required, and the patterns.
|
|
36
37
|
*/
|
|
37
38
|
export function resolveFileSelection(input) {
|
|
38
|
-
const { cwd, sourceDir, distignore, exclude } = input;
|
|
39
|
+
const { cwd, sourceDir, distignore, exclude, excludeGitattributes = false, } = input;
|
|
39
40
|
const selection = {
|
|
40
41
|
distignore: join(sourceDir, DISTIGNORE_FILENAME),
|
|
41
42
|
distignoreRequired: false,
|
|
42
43
|
exclude: parseExclude(exclude),
|
|
44
|
+
sourceDir,
|
|
45
|
+
excludeGitattributes,
|
|
43
46
|
};
|
|
44
47
|
if (false === distignore) {
|
|
45
48
|
selection.distignore = null;
|
|
@@ -61,8 +64,101 @@ export function resolveFileSelection(input) {
|
|
|
61
64
|
*/
|
|
62
65
|
export async function loadFileRules(selection) {
|
|
63
66
|
const { distignore = null, distignoreRequired = false, exclude = [], } = selection;
|
|
64
|
-
const rules =
|
|
65
|
-
|
|
67
|
+
const rules = ignore()
|
|
68
|
+
.add(await readIgnoreFile(distignore, distignoreRequired))
|
|
69
|
+
.add(exclude);
|
|
70
|
+
if (selection.excludeGitattributes) {
|
|
71
|
+
if (!selection.sourceDir) {
|
|
72
|
+
throw new ValidationError('--exclude-gitattributes requires a source directory.');
|
|
73
|
+
}
|
|
74
|
+
const excluded = await getExportIgnoredPaths(selection.sourceDir, rules);
|
|
75
|
+
rules.add(excluded.map((path) => `/${escapePattern(path)}`));
|
|
76
|
+
}
|
|
77
|
+
return rules.add(ALWAYS_EXCLUDED);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Read Git's export-ignore attribute for the source files selected by the
|
|
81
|
+
* other ignore rules. Git itself evaluates .gitattributes, including nested
|
|
82
|
+
* files and its pattern syntax.
|
|
83
|
+
*
|
|
84
|
+
* @param sourceDir Directory whose files are being selected.
|
|
85
|
+
* @param rules Rules already loaded from .distignore and --exclude.
|
|
86
|
+
* @return Source-relative paths marked export-ignore.
|
|
87
|
+
*/
|
|
88
|
+
async function getExportIgnoredPaths(sourceDir, rules) {
|
|
89
|
+
const runner = createGitRunner();
|
|
90
|
+
let root;
|
|
91
|
+
try {
|
|
92
|
+
({ stdout: root } = await runner({
|
|
93
|
+
args: ['rev-parse', '--show-toplevel'],
|
|
94
|
+
cwd: sourceDir,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
throw new ValidationError('--exclude-gitattributes requires the source directory to be inside a Git repository.');
|
|
99
|
+
}
|
|
100
|
+
root = await realpath(root.trim());
|
|
101
|
+
const sourceFromRoot = relative(root, await realpath(sourceDir));
|
|
102
|
+
if (isAbsolute(sourceFromRoot) ||
|
|
103
|
+
sourceFromRoot === '..' ||
|
|
104
|
+
sourceFromRoot.startsWith(`..${posix.sep}`)) {
|
|
105
|
+
throw new ValidationError('--exclude-gitattributes requires the source directory to be inside a Git repository.');
|
|
106
|
+
}
|
|
107
|
+
const candidates = await findAttributeCandidates(sourceDir, '', rules);
|
|
108
|
+
if (!candidates.length) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
const pathsFromRoot = candidates.map((path) => posix.join(sourceFromRoot.split('\\').join('/'), path));
|
|
112
|
+
const { stdout } = await runner({
|
|
113
|
+
args: ['check-attr', '-z', '--stdin', 'export-ignore'],
|
|
114
|
+
cwd: root,
|
|
115
|
+
input: pathsFromRoot.map((path) => `${path}\0`).join(''),
|
|
116
|
+
});
|
|
117
|
+
const fields = stdout.split('\0');
|
|
118
|
+
const ignored = [];
|
|
119
|
+
for (let index = 0; index + 2 < fields.length; index += 3) {
|
|
120
|
+
const candidate = candidates[index / 3];
|
|
121
|
+
if (fields[index + 2] === 'set' && candidate) {
|
|
122
|
+
ignored.push(candidate);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return ignored;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* List regular files and symbolic links not already excluded by ignore rules.
|
|
129
|
+
* Symbolic links are included here so Git can exclude them before selectFiles
|
|
130
|
+
* applies its unsupported-link validation.
|
|
131
|
+
*
|
|
132
|
+
* @param sourceDir Source directory.
|
|
133
|
+
* @param dir Relative directory being traversed.
|
|
134
|
+
* @param rules Ignore rules.
|
|
135
|
+
* @return Relative paths to candidate files.
|
|
136
|
+
*/
|
|
137
|
+
async function findAttributeCandidates(sourceDir, dir, rules) {
|
|
138
|
+
const entries = await readdir(join(sourceDir, dir), {
|
|
139
|
+
withFileTypes: true,
|
|
140
|
+
});
|
|
141
|
+
const paths = await Promise.all(entries.map(async (entry) => {
|
|
142
|
+
const path = posix.join(dir, entry.name);
|
|
143
|
+
if (entry.isDirectory() && !rules.ignores(`${path}/`)) {
|
|
144
|
+
return findAttributeCandidates(sourceDir, path, rules);
|
|
145
|
+
}
|
|
146
|
+
if ((entry.isFile() || entry.isSymbolicLink()) &&
|
|
147
|
+
!rules.ignores(path)) {
|
|
148
|
+
return [path];
|
|
149
|
+
}
|
|
150
|
+
return [];
|
|
151
|
+
}));
|
|
152
|
+
return paths.flat();
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Escape a path for an anchored gitignore pattern.
|
|
156
|
+
*
|
|
157
|
+
* @param path Relative path.
|
|
158
|
+
* @return Pattern-safe path.
|
|
159
|
+
*/
|
|
160
|
+
function escapePattern(path) {
|
|
161
|
+
return path.replace(/[\\*?[\\]!#]/g, '\\$&');
|
|
66
162
|
}
|
|
67
163
|
/**
|
|
68
164
|
* Read the ignore file, or nothing when there's no file to read.
|
package/dist/git-deploy.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface GitDeployInput {
|
|
|
24
24
|
distignore?: string | false;
|
|
25
25
|
/** Extra gitignore-style patterns. */
|
|
26
26
|
exclude?: string | string[];
|
|
27
|
+
/** Also exclude paths marked export-ignore by Git attributes. */
|
|
28
|
+
excludeGitattributes?: boolean;
|
|
27
29
|
/** Commit message of the release. */
|
|
28
30
|
message?: string;
|
|
29
31
|
/** Run everything except the push. */
|
package/dist/git-deploy.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { DISTIGNORE_FILENAME, parseExclude, resolveFileSelection, loadFileRules,
|
|
|
9
9
|
export { FILENAME_FORMAT, formatFilename } from './filename.ts';
|
|
10
10
|
export { CHECKSUMS_EXTENSION, CHECKSUM_ALGORITHMS, hashFile, hashFiles, createChecksums, writeChecksums, readChecksums, parseChecksums, compareChecksums, verifyChecksums, } from './checksums.ts';
|
|
11
11
|
export { HEADER_BYTES, PLUGIN_HEADERS, THEME_HEADERS, README_HEADERS, README_FILENAMES, parseFileHeaders, parseReadmeHeaders, readFileStart, findFileHeaderLine, findReadmeHeaderLine, findMainPluginFile, readPackageMeta, } from './package-meta.ts';
|
|
12
|
-
export { SIGNATURE_EXTENSION, SIGNING_KEY_ENV, parseSigningKey, parsePublicKey, getPublicKey, getFileDigest, signFile, writeSignature, verifyFileSignature, } from './signing.ts';
|
|
12
|
+
export { SIGNATURE_EXTENSION, SIGNING_KEY_ENV, parseSigningKey, parsePublicKey, generateSigningKeyPair, getPublicKey, getFileDigest, signFile, writeSignature, verifyFileSignature, } from './signing.ts';
|
|
13
13
|
export { ZIP_MTIME, ZIP_FILE_MODE, createZip } from './zip.ts';
|
|
14
14
|
export { isUrl, downloadFile } from './download.ts';
|
|
15
15
|
export { readZipEntries, getZipEntryErrors, extractZip } from './unzip.ts';
|
|
@@ -26,6 +26,7 @@ export { getGitDeployInputFromArgs } from './commands/deploy-git.ts';
|
|
|
26
26
|
export type { CliIo, CommandResults } from './cli.ts';
|
|
27
27
|
export type { ChecksumsResult } from './commands/checksums.ts';
|
|
28
28
|
export type { SignResult } from './commands/sign.ts';
|
|
29
|
+
export type { KeygenResult } from './commands/keygen.ts';
|
|
29
30
|
export type { ZipResult } from './commands/zip.ts';
|
|
30
31
|
export type { Command, CommandContext, CommandOutcome, ParsedValues, } from './commands/command.ts';
|
|
31
32
|
export type { DeployArgsInput } from './commands/deploy-svn.ts';
|
|
@@ -42,7 +43,7 @@ export type { ExtractZipInput, ZipEntryInfo, ZipEntryType } from './unzip.ts';
|
|
|
42
43
|
export type { FindVersionMismatchesInput, GitTagInput, VersionCheckResult, VersionMismatch, } from './version-check.ts';
|
|
43
44
|
export type { Changeset, ChangesetBump, ChangesetPackages, ChangesetConfig, ChangesetPackageType, ChangesetPackage, PackageRelease, VersionedRelease, ChangesetReleasePlan, } from './changesets.ts';
|
|
44
45
|
export type { ChangesetRepository, ChangesetVersionInput, VersionChangesetsResult, ChangesetTagInput, ChangesetTagResult, } from './changeset-release.ts';
|
|
45
|
-
export type { WpReleaseConfig, ChangesetPackageGroup, PackageVersionConfig, PackageVersionSource, PackageVersionTarget, PackageIdSource, NextVersionInput, ReleaseCommit, ReleaseNotesInput, ChangelogEntryInput, PackageJsonVersionOptions, ComposerJsonVersionOptions, WordPressVersionFileOptions, GitTagVersionOptions, PhpConstantVersionOptions, LoadChangesetConfigInput, } from './changeset-config.ts';
|
|
46
|
+
export type { WpReleaseConfig, ChangesetPackageGroup, PackageVersionConfig, PackageVersionSource, PackageVersionTarget, PackageIdSource, NextVersionInput, ReleaseCommit, ReleaseNotesInput, ChangelogEntryInput, DependentsChangelogInput, DependentsConfig, PackageJsonVersionOptions, ComposerJsonVersionOptions, WordPressVersionFileOptions, GitTagVersionOptions, PhpConstantVersionOptions, LoadChangesetConfigInput, } from './changeset-config.ts';
|
|
46
47
|
export type { SvnCheckoutInput, SvnCommandInput, SvnCommandOutput, SvnCommitInput, SvnCopyInput, SvnDepth, SvnOptions, SvnPathsInput, SvnPropsetInput, SvnRunner, SvnStatusEntry, SvnStatusType, SvnUpdateInput, } from './svn.ts';
|
|
47
48
|
export type { SyncDirectoryInput, SyncResult } from './sync.ts';
|
|
48
49
|
export type { SummaryContext } from './summary.ts';
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export { DISTIGNORE_FILENAME, parseExclude, resolveFileSelection, loadFileRules,
|
|
|
9
9
|
export { FILENAME_FORMAT, formatFilename } from "./filename.js";
|
|
10
10
|
export { CHECKSUMS_EXTENSION, CHECKSUM_ALGORITHMS, hashFile, hashFiles, createChecksums, writeChecksums, readChecksums, parseChecksums, compareChecksums, verifyChecksums, } from "./checksums.js";
|
|
11
11
|
export { HEADER_BYTES, PLUGIN_HEADERS, THEME_HEADERS, README_HEADERS, README_FILENAMES, parseFileHeaders, parseReadmeHeaders, readFileStart, findFileHeaderLine, findReadmeHeaderLine, findMainPluginFile, readPackageMeta, } from "./package-meta.js";
|
|
12
|
-
export { SIGNATURE_EXTENSION, SIGNING_KEY_ENV, parseSigningKey, parsePublicKey, getPublicKey, getFileDigest, signFile, writeSignature, verifyFileSignature, } from "./signing.js";
|
|
12
|
+
export { SIGNATURE_EXTENSION, SIGNING_KEY_ENV, parseSigningKey, parsePublicKey, generateSigningKeyPair, getPublicKey, getFileDigest, signFile, writeSignature, verifyFileSignature, } from "./signing.js";
|
|
13
13
|
export { ZIP_MTIME, ZIP_FILE_MODE, createZip } from "./zip.js";
|
|
14
14
|
export { isUrl, downloadFile } from "./download.js";
|
|
15
15
|
export { readZipEntries, getZipEntryErrors, extractZip } from "./unzip.js";
|
package/dist/signing.d.ts
CHANGED
|
@@ -4,6 +4,15 @@ export declare const SIGNATURE_EXTENSION = ".sig";
|
|
|
4
4
|
* Environment variable with the base64 Ed25519 signing key.
|
|
5
5
|
*/
|
|
6
6
|
export declare const SIGNING_KEY_ENV = "WP_RELEASE_SIGNING_KEY";
|
|
7
|
+
/**
|
|
8
|
+
* Generate an Ed25519 key pair in the base64 formats used by wp-release.
|
|
9
|
+
*
|
|
10
|
+
* @return Private seed for WP_RELEASE_SIGNING_KEY and public verification key.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateSigningKeyPair(): {
|
|
13
|
+
privateKey: string;
|
|
14
|
+
publicKey: string;
|
|
15
|
+
};
|
|
7
16
|
/**
|
|
8
17
|
* Get an Ed25519 private key from the base64 format that sodium and the
|
|
9
18
|
* update-client signing_key setting use: a 32-byte seed or a 64-byte
|
package/dist/signing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash, createPrivateKey, createPublicKey, sign, verify, } from 'node:crypto';
|
|
1
|
+
import { createHash, createPrivateKey, generateKeyPairSync, createPublicKey, sign, verify, } from 'node:crypto';
|
|
2
2
|
import { createReadStream } from 'node:fs';
|
|
3
3
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { ValidationError } from "./errors.js";
|
|
@@ -14,6 +14,23 @@ const PUBLIC_KEY_BYTES = 32;
|
|
|
14
14
|
const PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');
|
|
15
15
|
// DER prefix of a SPKI Ed25519 public key, followed by the 32-byte key.
|
|
16
16
|
const SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');
|
|
17
|
+
/**
|
|
18
|
+
* Generate an Ed25519 key pair in the base64 formats used by wp-release.
|
|
19
|
+
*
|
|
20
|
+
* @return Private seed for WP_RELEASE_SIGNING_KEY and public verification key.
|
|
21
|
+
*/
|
|
22
|
+
export function generateSigningKeyPair() {
|
|
23
|
+
const { privateKey, publicKey } = generateKeyPairSync('ed25519');
|
|
24
|
+
const privateJwk = privateKey.export({ format: 'jwk' });
|
|
25
|
+
const publicJwk = publicKey.export({ format: 'jwk' });
|
|
26
|
+
if (!privateJwk.d || !publicJwk.x) {
|
|
27
|
+
throw new ValidationError('Could not export the generated Ed25519 key pair.');
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
privateKey: Buffer.from(privateJwk.d, 'base64url').toString('base64'),
|
|
31
|
+
publicKey: Buffer.from(publicJwk.x, 'base64url').toString('base64'),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
17
34
|
/**
|
|
18
35
|
* Decode a base64 key, accepting the base64url alphabet and whitespace.
|
|
19
36
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wpelevator/wp-release",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Package, checksum, sign, verify and version-check WordPress plugins and themes, and deploy plugins to WordPress.org SVN",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,11 +41,13 @@
|
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"ignore": "^7.0.12",
|
|
44
|
+
"semver": "^7.7.1",
|
|
44
45
|
"yauzl": "^3.4.0",
|
|
45
46
|
"yazl": "^3.3.1"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@types/node": "^22.20.5",
|
|
50
|
+
"@types/semver": "^7.8.0",
|
|
49
51
|
"@types/yauzl": "^3.4.0",
|
|
50
52
|
"@types/yazl": "^3.3.1",
|
|
51
53
|
"@wordpress/scripts": "^33.0",
|