@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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { sign, verify } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { PUBLIC_KEY_BYTES, digestFile, getRawPublicKey } from "./ed25519.js";
|
|
4
|
+
export const SSH_SIGNATURE_EXTENSION = '.sshsig';
|
|
5
|
+
/**
|
|
6
|
+
* Namespace of the signatures, which `ssh-keygen -Y verify -n` must match,
|
|
7
|
+
* so that a signature for files can't be used as one for something else.
|
|
8
|
+
*/
|
|
9
|
+
export const SSH_SIGNATURE_NAMESPACE = 'file';
|
|
10
|
+
const KEY_TYPE = 'ssh-ed25519';
|
|
11
|
+
const MAGIC = Buffer.from('SSHSIG');
|
|
12
|
+
const VERSION = 1;
|
|
13
|
+
const HASH_ALGORITHM = 'sha512';
|
|
14
|
+
const ARMOR_BEGIN = '-----BEGIN SSH SIGNATURE-----';
|
|
15
|
+
const ARMOR_END = '-----END SSH SIGNATURE-----';
|
|
16
|
+
const ARMOR_LINE_LENGTH = 70;
|
|
17
|
+
/**
|
|
18
|
+
* Encode a value as an SSH wire format string: its length as a 32-bit
|
|
19
|
+
* big-endian number, followed by its bytes.
|
|
20
|
+
*
|
|
21
|
+
* @param value Bytes or text.
|
|
22
|
+
* @return Encoded string.
|
|
23
|
+
*/
|
|
24
|
+
function encodeString(value) {
|
|
25
|
+
const bytes = Buffer.from(value);
|
|
26
|
+
const length = Buffer.alloc(4);
|
|
27
|
+
length.writeUInt32BE(bytes.length);
|
|
28
|
+
return Buffer.concat([length, bytes]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Read the SSH wire format strings that follow each other in a buffer.
|
|
32
|
+
*
|
|
33
|
+
* @param bytes Encoded strings.
|
|
34
|
+
* @return Decoded strings, or null when the buffer isn't a list of strings.
|
|
35
|
+
*/
|
|
36
|
+
function decodeStrings(bytes) {
|
|
37
|
+
const strings = [];
|
|
38
|
+
let offset = 0;
|
|
39
|
+
while (offset + 4 <= bytes.length) {
|
|
40
|
+
const end = offset + 4 + bytes.readUInt32BE(offset);
|
|
41
|
+
strings.push(bytes.subarray(offset + 4, end));
|
|
42
|
+
offset = end;
|
|
43
|
+
}
|
|
44
|
+
return offset === bytes.length ? strings : null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Encode an Ed25519 public key as an SSH public key blob.
|
|
48
|
+
*
|
|
49
|
+
* @param publicKey Public key bytes.
|
|
50
|
+
* @return Public key blob.
|
|
51
|
+
*/
|
|
52
|
+
function encodePublicKey(publicKey) {
|
|
53
|
+
return Buffer.concat([
|
|
54
|
+
encodeString(KEY_TYPE),
|
|
55
|
+
encodeString(publicKey),
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the data that an SSH signature signs: the namespace, the hash
|
|
60
|
+
* algorithm and the digest of the file.
|
|
61
|
+
*
|
|
62
|
+
* @param digest File digest.
|
|
63
|
+
* @param namespace Signature namespace.
|
|
64
|
+
* @param hashAlgorithm Hash algorithm of the digest.
|
|
65
|
+
* @return Signed data.
|
|
66
|
+
*/
|
|
67
|
+
function getSignedData(digest, namespace, hashAlgorithm) {
|
|
68
|
+
return Buffer.concat([
|
|
69
|
+
MAGIC,
|
|
70
|
+
encodeString(namespace),
|
|
71
|
+
encodeString(''),
|
|
72
|
+
encodeString(hashAlgorithm),
|
|
73
|
+
encodeString(digest),
|
|
74
|
+
]);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get the OpenSSH public key of a key, the line of an authorized_keys or
|
|
78
|
+
* allowed_signers file.
|
|
79
|
+
*
|
|
80
|
+
* @param key Private or public key.
|
|
81
|
+
* @return OpenSSH public key.
|
|
82
|
+
*/
|
|
83
|
+
export function getSshPublicKey(key) {
|
|
84
|
+
return `${KEY_TYPE} ${encodePublicKey(getRawPublicKey(key)).toString('base64')}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the raw public key from an OpenSSH Ed25519 public key line, with or
|
|
88
|
+
* without a comment.
|
|
89
|
+
*
|
|
90
|
+
* @param encoded OpenSSH public key.
|
|
91
|
+
* @return Public key bytes, or null when it isn't an OpenSSH Ed25519 key.
|
|
92
|
+
*/
|
|
93
|
+
export function parseSshPublicKey(encoded) {
|
|
94
|
+
const [type, blob = ''] = encoded.trim().split(/\s+/);
|
|
95
|
+
const [blobType, publicKey] = decodeStrings(Buffer.from(blob, 'base64')) ?? [];
|
|
96
|
+
const isSsh = KEY_TYPE === type &&
|
|
97
|
+
KEY_TYPE === blobType?.toString() &&
|
|
98
|
+
PUBLIC_KEY_BYTES === publicKey?.length;
|
|
99
|
+
return isSsh && publicKey ? publicKey : null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Create an SSH signature of a file, the armored format that
|
|
103
|
+
* `ssh-keygen -Y sign` writes, with the "file" namespace and a SHA-512
|
|
104
|
+
* digest.
|
|
105
|
+
*
|
|
106
|
+
* @param path File path.
|
|
107
|
+
* @param privateKey Private key.
|
|
108
|
+
* @return Contents of the signature file.
|
|
109
|
+
*/
|
|
110
|
+
export async function createSshSignature(path, privateKey) {
|
|
111
|
+
const signature = sign(null, getSignedData(await digestFile(path, HASH_ALGORITHM), SSH_SIGNATURE_NAMESPACE, HASH_ALGORITHM), privateKey);
|
|
112
|
+
const version = Buffer.alloc(4);
|
|
113
|
+
version.writeUInt32BE(VERSION);
|
|
114
|
+
const encoded = Buffer.concat([
|
|
115
|
+
MAGIC,
|
|
116
|
+
version,
|
|
117
|
+
encodeString(encodePublicKey(getRawPublicKey(privateKey))),
|
|
118
|
+
encodeString(SSH_SIGNATURE_NAMESPACE),
|
|
119
|
+
encodeString(''),
|
|
120
|
+
encodeString(HASH_ALGORITHM),
|
|
121
|
+
encodeString(Buffer.concat([
|
|
122
|
+
encodeString(KEY_TYPE),
|
|
123
|
+
encodeString(signature),
|
|
124
|
+
])),
|
|
125
|
+
]).toString('base64');
|
|
126
|
+
const lines = encoded.match(new RegExp(`.{1,${ARMOR_LINE_LENGTH}}`, 'g'));
|
|
127
|
+
return [ARMOR_BEGIN, ...(lines ?? []), ARMOR_END, ''].join('\n');
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check a file against an SSH signature file. The signature must be made by
|
|
131
|
+
* the public key, for the "file" namespace, with a SHA-512 or SHA-256 digest.
|
|
132
|
+
*
|
|
133
|
+
* @param path File path.
|
|
134
|
+
* @param signaturePath Signature file path.
|
|
135
|
+
* @param publicKey Public key.
|
|
136
|
+
* @return Whether the signature matches.
|
|
137
|
+
*/
|
|
138
|
+
export async function verifySshSignature(path, signaturePath, publicKey) {
|
|
139
|
+
const armored = (await readFile(signaturePath, 'utf8')).trim();
|
|
140
|
+
const bytes = Buffer.from(armored.slice(ARMOR_BEGIN.length, -ARMOR_END.length), 'base64');
|
|
141
|
+
const [signer, namespace, reserved, hashAlgorithm = Buffer.alloc(0), signatureBlob = Buffer.alloc(0),] = decodeStrings(bytes.subarray(MAGIC.length + 4)) ?? [];
|
|
142
|
+
const [signatureType, signature] = decodeStrings(signatureBlob) ?? [];
|
|
143
|
+
const isValidShape = armored.startsWith(ARMOR_BEGIN) &&
|
|
144
|
+
armored.endsWith(ARMOR_END) &&
|
|
145
|
+
bytes.length > MAGIC.length + 4 &&
|
|
146
|
+
MAGIC.equals(bytes.subarray(0, MAGIC.length)) &&
|
|
147
|
+
VERSION === bytes.readUInt32BE(MAGIC.length) &&
|
|
148
|
+
signer?.equals(encodePublicKey(getRawPublicKey(publicKey))) &&
|
|
149
|
+
SSH_SIGNATURE_NAMESPACE === namespace?.toString() &&
|
|
150
|
+
0 === reserved?.length &&
|
|
151
|
+
['sha512', 'sha256'].includes(hashAlgorithm.toString()) &&
|
|
152
|
+
KEY_TYPE === signatureType?.toString() &&
|
|
153
|
+
undefined !== signature;
|
|
154
|
+
return (Boolean(isValidShape) &&
|
|
155
|
+
verify(null, getSignedData(await digestFile(path, hashAlgorithm.toString()), SSH_SIGNATURE_NAMESPACE, hashAlgorithm.toString()), publicKey, signature ?? Buffer.alloc(0)));
|
|
156
|
+
}
|
package/dist/summary.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChecksumsResult } from './commands/checksums.ts';
|
|
2
2
|
import type { SignResult } from './commands/sign.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ZipPackageResult } from './package-zip.ts';
|
|
4
4
|
import type { ChangesetTagResult } from './changeset-release.ts';
|
|
5
5
|
import type { PackageRelease } from './changesets.ts';
|
|
6
6
|
import type { DeployOptions } from './deploy-options.ts';
|
|
@@ -76,7 +76,7 @@ export declare function formatFile(context: SummaryContext, file: string, line?:
|
|
|
76
76
|
* @param result ZIP and manifest paths and the number of files.
|
|
77
77
|
* @return Markdown summary.
|
|
78
78
|
*/
|
|
79
|
-
export declare function getZipSummary(context: SummaryContext, result:
|
|
79
|
+
export declare function getZipSummary(context: SummaryContext, result: ZipPackageResult): string;
|
|
80
80
|
/**
|
|
81
81
|
* Get the summary of a checksums manifest.
|
|
82
82
|
*
|
|
@@ -89,7 +89,7 @@ export declare function getChecksumsSummary(context: SummaryContext, result: Che
|
|
|
89
89
|
* Get the summary of signed files.
|
|
90
90
|
*
|
|
91
91
|
* @param context Workspace directory.
|
|
92
|
-
* @param result Signature paths and the public
|
|
92
|
+
* @param result Signature paths and the public keys of the formats.
|
|
93
93
|
* @return Markdown summary.
|
|
94
94
|
*/
|
|
95
95
|
export declare function getSignSummary(context: SummaryContext, result: SignResult): string;
|
package/dist/summary.js
CHANGED
|
@@ -138,14 +138,14 @@ export function getChecksumsSummary(context, result) {
|
|
|
138
138
|
* Get the summary of signed files.
|
|
139
139
|
*
|
|
140
140
|
* @param context Workspace directory.
|
|
141
|
-
* @param result Signature paths and the public
|
|
141
|
+
* @param result Signature paths and the public keys of the formats.
|
|
142
142
|
* @return Markdown summary.
|
|
143
143
|
*/
|
|
144
144
|
export function getSignSummary(context, result) {
|
|
145
145
|
return joinBlocks([
|
|
146
146
|
'### Signatures',
|
|
147
147
|
formatList(result.signatures.map((path) => formatFile(context, path))),
|
|
148
|
-
`Public key: ${formatCode(result.
|
|
148
|
+
...result.formats.map((format) => `Public key (${format}): ${formatCode(result.publicKeys[format])}`),
|
|
149
149
|
]);
|
|
150
150
|
}
|
|
151
151
|
/**
|
package/dist/tag-format.d.ts
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import type { ConfiguredDeployPackage } from './changeset-packages.ts';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Tag format of the package releases, like plugins/alpha/1.2.0 in a
|
|
4
|
+
* monorepo, or 1.2.0 for a package at the repository root.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_TAG_FORMAT = "{path}/{version}";
|
|
7
|
+
/**
|
|
8
|
+
* Fill in a template of a package with {name}, {path} and {version}, like a
|
|
9
|
+
* deploy template. A package at the root of the repository has an empty
|
|
10
|
+
* {path}.
|
|
4
11
|
*
|
|
5
|
-
* @param format
|
|
12
|
+
* @param format Template with {name}, {path} and {version}.
|
|
6
13
|
* @param pkg Configured package, with or without a version.
|
|
7
|
-
* @param version Released version, empty
|
|
8
|
-
* @return
|
|
14
|
+
* @param version Released version, empty when there's none.
|
|
15
|
+
* @return Formatted text.
|
|
9
16
|
*/
|
|
10
|
-
export declare function
|
|
17
|
+
export declare function formatTemplate(format: string, pkg: Pick<ConfiguredDeployPackage, 'name' | 'path'>, version: string): string;
|
|
11
18
|
/**
|
|
12
|
-
* Format the tag
|
|
13
|
-
*
|
|
19
|
+
* Format the tag of a package release, or its tag prefix without a version.
|
|
20
|
+
* Empty placeholders leave no repeated or leading slashes, so a package at
|
|
21
|
+
* the repository root gets 1.2.0 for {path}/{version}. A trailing slash is
|
|
22
|
+
* kept, since it separates the tag prefix from the version.
|
|
14
23
|
*
|
|
15
|
-
* @param
|
|
16
|
-
* @param
|
|
17
|
-
* @param
|
|
18
|
-
* @return Tag prefix.
|
|
24
|
+
* @param format Tag format with {name}, {path} and {version}.
|
|
25
|
+
* @param pkg Configured package, with or without a version.
|
|
26
|
+
* @param version Released version, empty for the tag prefix of the package.
|
|
27
|
+
* @return Tag name or prefix.
|
|
19
28
|
*/
|
|
20
|
-
export declare function
|
|
29
|
+
export declare function formatTag(format: string, pkg: Pick<ConfiguredDeployPackage, 'name' | 'path'>, version: string): string;
|
package/dist/tag-format.js
CHANGED
|
@@ -1,51 +1,37 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* Tag format of the package releases, like plugins/alpha/1.2.0 in a
|
|
3
|
+
* monorepo, or 1.2.0 for a package at the repository root.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_TAG_FORMAT = '{path}/{version}';
|
|
6
|
+
/**
|
|
7
|
+
* Fill in a template of a package with {name}, {path} and {version}, like a
|
|
8
|
+
* deploy template. A package at the root of the repository has an empty
|
|
9
|
+
* {path}.
|
|
4
10
|
*
|
|
5
|
-
* @param format
|
|
11
|
+
* @param format Template with {name}, {path} and {version}.
|
|
6
12
|
* @param pkg Configured package, with or without a version.
|
|
7
|
-
* @param version Released version, empty
|
|
8
|
-
* @return
|
|
13
|
+
* @param version Released version, empty when there's none.
|
|
14
|
+
* @return Formatted text.
|
|
9
15
|
*/
|
|
10
|
-
export function
|
|
11
|
-
const type = pkg.group.tagType ?? defaultTagType(pkg.path, pkg.type);
|
|
16
|
+
export function formatTemplate(format, pkg, version) {
|
|
12
17
|
return format
|
|
13
18
|
.replaceAll('{name}', pkg.name)
|
|
14
|
-
.replaceAll('{
|
|
15
|
-
? path.basename(pkg.directory)
|
|
16
|
-
: path.basename(pkg.path))
|
|
17
|
-
.replaceAll('{path}', pkg.path)
|
|
18
|
-
.replaceAll('{type}', type)
|
|
19
|
+
.replaceAll('{path}', '.' === pkg.path ? '' : pkg.path)
|
|
19
20
|
.replaceAll('{version}', version);
|
|
20
21
|
}
|
|
21
22
|
/**
|
|
22
|
-
* Format the tag
|
|
23
|
-
*
|
|
23
|
+
* Format the tag of a package release, or its tag prefix without a version.
|
|
24
|
+
* Empty placeholders leave no repeated or leading slashes, so a package at
|
|
25
|
+
* the repository root gets 1.2.0 for {path}/{version}. A trailing slash is
|
|
26
|
+
* kept, since it separates the tag prefix from the version.
|
|
24
27
|
*
|
|
25
|
-
* @param
|
|
26
|
-
* @param
|
|
27
|
-
* @param
|
|
28
|
-
* @return Tag prefix.
|
|
28
|
+
* @param format Tag format with {name}, {path} and {version}.
|
|
29
|
+
* @param pkg Configured package, with or without a version.
|
|
30
|
+
* @param version Released version, empty for the tag prefix of the package.
|
|
31
|
+
* @return Tag name or prefix.
|
|
29
32
|
*/
|
|
30
|
-
export function
|
|
31
|
-
return
|
|
32
|
-
.
|
|
33
|
-
.
|
|
34
|
-
.replaceAll('{name}', packagePath.split('/').at(-1) ?? packagePath)
|
|
35
|
-
.replaceAll('{slug}', packagePath.split('/').at(-1) ?? packagePath)
|
|
36
|
-
.replaceAll('{version}', '');
|
|
37
|
-
}
|
|
38
|
-
function defaultTagType(packagePath, type) {
|
|
39
|
-
if ('.' === packagePath && type) {
|
|
40
|
-
return type;
|
|
41
|
-
}
|
|
42
|
-
const first = packagePath.split('/')[0] ?? 'package';
|
|
43
|
-
const irregular = {
|
|
44
|
-
actions: 'action',
|
|
45
|
-
plugins: 'plugin',
|
|
46
|
-
themes: 'theme',
|
|
47
|
-
php: 'php',
|
|
48
|
-
js: 'js',
|
|
49
|
-
};
|
|
50
|
-
return irregular[first] ?? first.replace(/s$/, '');
|
|
33
|
+
export function formatTag(format, pkg, version) {
|
|
34
|
+
return formatTemplate(format, pkg, version)
|
|
35
|
+
.replace(/\/{2,}/g, '/')
|
|
36
|
+
.replace(/^\/+/, '');
|
|
51
37
|
}
|
package/dist/version-files.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import type { PackageVersionSource, PackageVersionTarget } from './changeset-config.ts';
|
|
2
|
-
import type { ConfiguredPackage } from './changeset-packages.ts';
|
|
2
|
+
import type { ConfiguredPackage, ConfiguredDeployPackage } from './changeset-packages.ts';
|
|
3
3
|
import type { FileJournal } from './file-journal.ts';
|
|
4
4
|
import type { ReleaseRepository } from './release-repository.ts';
|
|
5
5
|
/**
|
|
6
6
|
* Read the current version of a package from its configured source.
|
|
7
7
|
*
|
|
8
|
-
* @param repository
|
|
9
|
-
* @param directory
|
|
10
|
-
* @param descriptor
|
|
11
|
-
* @param
|
|
12
|
-
* @param tagType Configured {type} of the package tags.
|
|
8
|
+
* @param repository Repository, for versions stored as git tags.
|
|
9
|
+
* @param directory Package directory.
|
|
10
|
+
* @param descriptor Version source.
|
|
11
|
+
* @param pkg Package name and path, for the tags of a git-tag source.
|
|
13
12
|
* @return Current version.
|
|
14
13
|
* @throws {ValidationError} If the version is missing.
|
|
15
14
|
*/
|
|
16
|
-
export declare function readVersion(repository: ReleaseRepository, directory: string, descriptor: PackageVersionSource,
|
|
15
|
+
export declare function readVersion(repository: ReleaseRepository, directory: string, descriptor: PackageVersionSource, pkg: Pick<ConfiguredDeployPackage, 'name' | 'path'>): Promise<string>;
|
|
17
16
|
/**
|
|
18
17
|
* Write a version to a configured version target.
|
|
19
18
|
*
|
package/dist/version-files.js
CHANGED
|
@@ -4,21 +4,20 @@ import { ValidationError } from "./errors.js";
|
|
|
4
4
|
import { readJson } from "./json-files.js";
|
|
5
5
|
import { findMainPluginFile } from "./package-meta.js";
|
|
6
6
|
import { escapeRegExp } from "./regexp.js";
|
|
7
|
-
import {
|
|
7
|
+
import { DEFAULT_TAG_FORMAT, formatTag } from "./tag-format.js";
|
|
8
8
|
import { findConstantValues } from "./version-check.js";
|
|
9
9
|
import { compareVersions, isPrerelease } from "./versions.js";
|
|
10
10
|
/**
|
|
11
11
|
* Read the current version of a package from its configured source.
|
|
12
12
|
*
|
|
13
|
-
* @param repository
|
|
14
|
-
* @param directory
|
|
15
|
-
* @param descriptor
|
|
16
|
-
* @param
|
|
17
|
-
* @param tagType Configured {type} of the package tags.
|
|
13
|
+
* @param repository Repository, for versions stored as git tags.
|
|
14
|
+
* @param directory Package directory.
|
|
15
|
+
* @param descriptor Version source.
|
|
16
|
+
* @param pkg Package name and path, for the tags of a git-tag source.
|
|
18
17
|
* @return Current version.
|
|
19
18
|
* @throws {ValidationError} If the version is missing.
|
|
20
19
|
*/
|
|
21
|
-
export async function readVersion(repository, directory, descriptor,
|
|
20
|
+
export async function readVersion(repository, directory, descriptor, pkg) {
|
|
22
21
|
if ('package-json' === descriptor.kind ||
|
|
23
22
|
'composer-json' === descriptor.kind) {
|
|
24
23
|
const manifest = await readJson(path.join(directory, descriptor.file));
|
|
@@ -29,8 +28,8 @@ export async function readVersion(repository, directory, descriptor, relativePat
|
|
|
29
28
|
throw new ValidationError(`Missing ${descriptor.file}#${descriptor.field} in ${directory}.`);
|
|
30
29
|
}
|
|
31
30
|
if ('git-tag' === descriptor.kind) {
|
|
32
|
-
const pattern = descriptor.pattern ??
|
|
33
|
-
const tags = await repository.listTags(
|
|
31
|
+
const pattern = descriptor.pattern ?? DEFAULT_TAG_FORMAT;
|
|
32
|
+
const tags = await repository.listTags(formatTag(pattern, pkg, ''));
|
|
34
33
|
const versions = tags
|
|
35
34
|
.map((tag) => tag.match(/(?:^|\/|v)(\d+(?:\.\d+){1,3})$/)?.[1])
|
|
36
35
|
.filter((item) => Boolean(item));
|
|
@@ -38,7 +37,7 @@ export async function readVersion(repository, directory, descriptor, relativePat
|
|
|
38
37
|
if (versions[0]) {
|
|
39
38
|
return versions[0];
|
|
40
39
|
}
|
|
41
|
-
throw new ValidationError(`No git tag matches ${pattern} for ${
|
|
40
|
+
throw new ValidationError(`No git tag matches ${pattern} for ${pkg.path}.`);
|
|
42
41
|
}
|
|
43
42
|
if ('php-constant' === descriptor.kind) {
|
|
44
43
|
const file = path.join(directory, descriptor.file);
|
|
@@ -142,7 +141,7 @@ export async function verifyVersionTargets(repository, pkg, expected) {
|
|
|
142
141
|
actual = undefined;
|
|
143
142
|
}
|
|
144
143
|
else {
|
|
145
|
-
actual = await readVersion(repository, pkg.directory, target, pkg
|
|
144
|
+
actual = await readVersion(repository, pkg.directory, target, pkg);
|
|
146
145
|
}
|
|
147
146
|
if (undefined !== actual && actual !== expected) {
|
|
148
147
|
throw new ValidationError(`Version mismatch for ${pkg.name}: expected ${expected}, found ${actual}.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wpelevator/wp-release",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"build": "tsc -p tsconfig.build.json",
|
|
59
59
|
"prepack": "npm run build",
|
|
60
60
|
"lint": "npm-run-all lint:*",
|
|
61
|
-
"lint:js": "wp-scripts lint-js
|
|
61
|
+
"lint:js": "wp-scripts lint-js",
|
|
62
62
|
"lint:types": "tsc -p tsconfig.json",
|
|
63
63
|
"format": "wp-scripts format src",
|
|
64
64
|
"test": "node --test --conditions=wpelevator-source"
|