@git.zone/cli 6.10.0 → 6.12.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/helpers.changelog.d.ts +4 -0
- package/dist_ts/helpers.changelog.js +73 -24
- package/dist_ts/helpers.climode.js +40 -3
- package/dist_ts/helpers.workflow.d.ts +2 -2
- package/dist_ts/helpers.workflow.js +42 -6
- package/dist_ts/mod_commit/helpers.manual.d.ts +10 -0
- package/dist_ts/mod_commit/helpers.manual.js +97 -0
- package/dist_ts/mod_commit/index.js +156 -35
- package/dist_ts/mod_commit/mod.plugins.d.ts +7 -7
- package/dist_ts/mod_commit/mod.plugins.js +9 -8
- package/dist_ts/mod_release/helpers.npmartifact.d.ts +1 -3
- package/dist_ts/mod_release/helpers.npmartifact.js +88 -66
- package/dist_ts/mod_standard/index.js +2 -2
- package/dist_ts/mod_tools/classes.packagemanager.d.ts +2 -0
- package/dist_ts/mod_tools/classes.packagemanager.js +3 -3
- package/package.json +2 -2
- package/readme.md +45 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/helpers.changelog.ts +108 -32
- package/ts/helpers.climode.ts +45 -2
- package/ts/helpers.workflow.ts +46 -5
- package/ts/mod_commit/helpers.manual.ts +156 -0
- package/ts/mod_commit/index.ts +272 -53
- package/ts/mod_commit/mod.plugins.ts +8 -7
- package/ts/mod_release/helpers.npmartifact.ts +156 -77
- package/ts/mod_standard/index.ts +1 -1
- package/ts/mod_tools/classes.packagemanager.ts +2 -2
|
@@ -4,16 +4,15 @@ import {
|
|
|
4
4
|
type IReleaseArtifact,
|
|
5
5
|
} from "./classes.releasejournal.js";
|
|
6
6
|
import { assertCredentialFreeGitPushDestination } from "./helpers.releasebranch.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"11.25.0": {
|
|
7
|
+
import {
|
|
8
|
+
getDefaultMinimumReleaseAgeMinutes,
|
|
9
|
+
packageSelectorMatches,
|
|
10
|
+
} from "../mod_tools/classes.packagemanager.js";
|
|
11
|
+
|
|
12
|
+
const stablePnpmVersion = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
13
|
+
// Qualify the command contract, independently of the executable's version.
|
|
14
|
+
const pnpmHelpRequirements = [
|
|
15
|
+
{
|
|
17
16
|
pack: ["--out <path>", "--json"],
|
|
18
17
|
publish: [
|
|
19
18
|
"publish [<tarball>|<dir>]",
|
|
@@ -24,33 +23,7 @@ const pnpmHelpRequirements = {
|
|
|
24
23
|
"--access <public|restricted>",
|
|
25
24
|
],
|
|
26
25
|
},
|
|
27
|
-
|
|
28
|
-
pack: ["Usage: pnpm pack [OPTIONS]", "--out <OUT>", "--json"],
|
|
29
|
-
publish: [
|
|
30
|
-
"Usage: pnpm publish [OPTIONS] [PACKAGE]",
|
|
31
|
-
"Tarball or directory to publish",
|
|
32
|
-
"--no-git-checks",
|
|
33
|
-
"--ignore-scripts",
|
|
34
|
-
"--json",
|
|
35
|
-
"--tag <TAG>",
|
|
36
|
-
"--access <ACCESS>",
|
|
37
|
-
"[possible values: public, restricted]",
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
"12.2.1": {
|
|
41
|
-
pack: ["Usage: pnpm pack [OPTIONS]", "--out <OUT>", "--json"],
|
|
42
|
-
publish: [
|
|
43
|
-
"Usage: pnpm publish [OPTIONS] [PACKAGE]",
|
|
44
|
-
"Tarball or directory to publish",
|
|
45
|
-
"--no-git-checks",
|
|
46
|
-
"--ignore-scripts",
|
|
47
|
-
"--json",
|
|
48
|
-
"--tag <TAG>",
|
|
49
|
-
"--access <ACCESS>",
|
|
50
|
-
"[possible values: public, restricted]",
|
|
51
|
-
],
|
|
52
|
-
},
|
|
53
|
-
"12.3.0": {
|
|
26
|
+
{
|
|
54
27
|
pack: ["Usage: pnpm pack [OPTIONS]", "--out <OUT>", "--json"],
|
|
55
28
|
publish: [
|
|
56
29
|
"Usage: pnpm publish [OPTIONS] [PACKAGE]",
|
|
@@ -63,20 +36,7 @@ const pnpmHelpRequirements = {
|
|
|
63
36
|
"[possible values: public, restricted]",
|
|
64
37
|
],
|
|
65
38
|
},
|
|
66
|
-
|
|
67
|
-
pack: ["Usage: pnpm pack [OPTIONS]", "--out <OUT>", "--json"],
|
|
68
|
-
publish: [
|
|
69
|
-
"Usage: pnpm publish [OPTIONS] [PACKAGE]",
|
|
70
|
-
"Tarball or directory to publish",
|
|
71
|
-
"--no-git-checks",
|
|
72
|
-
"--ignore-scripts",
|
|
73
|
-
"--json",
|
|
74
|
-
"--tag <TAG>",
|
|
75
|
-
"--access <ACCESS>",
|
|
76
|
-
"[possible values: public, restricted]",
|
|
77
|
-
],
|
|
78
|
-
},
|
|
79
|
-
} as const;
|
|
39
|
+
] as const;
|
|
80
40
|
const maximumMetadataResponseBytes = 8 * 1024 * 1024;
|
|
81
41
|
const capabilityCommandTimeoutMs = 30_000;
|
|
82
42
|
const packCommandTimeoutMs = 10 * 60_000;
|
|
@@ -91,17 +51,14 @@ export function assertNpmPackageName(value: unknown): asserts value is string {
|
|
|
91
51
|
}
|
|
92
52
|
|
|
93
53
|
export interface IPnpmReleaseCapability {
|
|
94
|
-
readonly version:
|
|
54
|
+
readonly version: string;
|
|
95
55
|
}
|
|
96
56
|
|
|
97
57
|
export const buildQualifiedPnpmArgs = (
|
|
98
58
|
capabilityArg: IPnpmReleaseCapability | undefined,
|
|
99
59
|
argsArg: readonly string[],
|
|
100
60
|
): string[] => {
|
|
101
|
-
if (
|
|
102
|
-
!capabilityArg ||
|
|
103
|
-
!supportedPnpmVersions.includes(capabilityArg.version)
|
|
104
|
-
) {
|
|
61
|
+
if (!capabilityArg || !stablePnpmVersion.test(capabilityArg.version)) {
|
|
105
62
|
throw new Error(
|
|
106
63
|
"npm release commands require a qualified pnpm invocation.",
|
|
107
64
|
);
|
|
@@ -165,15 +122,140 @@ const readPackageIdentity = async (
|
|
|
165
122
|
|
|
166
123
|
const requireHelpFragments = (
|
|
167
124
|
outputArg: string,
|
|
168
|
-
|
|
169
|
-
commandArg: string,
|
|
125
|
+
commandArg: "pack" | "publish",
|
|
170
126
|
): void => {
|
|
171
|
-
const missing =
|
|
172
|
-
|
|
127
|
+
const missing = pnpmHelpRequirements.map((requirements) =>
|
|
128
|
+
requirements[commandArg].filter(
|
|
129
|
+
(fragment) => !outputArg.includes(fragment),
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
if (missing.every((fragments) => fragments.length > 0)) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`pnpm ${commandArg} is missing required exact-release capabilities: ${missing.map((fragments) => fragments.join(", ")).join("; or ")}.`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const readPnpmJson = async (
|
|
140
|
+
shellArg: plugins.smartshell.Smartshell,
|
|
141
|
+
cwdArg: string,
|
|
142
|
+
capabilityArg: IPnpmReleaseCapability,
|
|
143
|
+
argsArg: string[],
|
|
144
|
+
labelArg: string,
|
|
145
|
+
): Promise<unknown> => {
|
|
146
|
+
const result = await shellArg.execSpawn(
|
|
147
|
+
"pnpm",
|
|
148
|
+
buildQualifiedPnpmArgs(capabilityArg, [...argsArg, "--json"]),
|
|
149
|
+
{
|
|
150
|
+
cwd: cwdArg,
|
|
151
|
+
silent: true,
|
|
152
|
+
timeout: capabilityCommandTimeoutMs,
|
|
153
|
+
timeoutKillGraceMs: 5_000,
|
|
154
|
+
maxBuffer: maximumMetadataResponseBytes,
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
if (result.exitCode !== 0 || result.timedOut) {
|
|
158
|
+
throw new Error(`Unable to inspect pnpm ${labelArg}.`);
|
|
159
|
+
}
|
|
160
|
+
if (result.stdout.trim() === "undefined") return undefined;
|
|
161
|
+
try {
|
|
162
|
+
return JSON.parse(result.stdout);
|
|
163
|
+
} catch {
|
|
164
|
+
throw new Error(`Invalid pnpm ${labelArg} response.`);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const assertPnpmReleaseAge = async (
|
|
169
|
+
shellArg: plugins.smartshell.Smartshell,
|
|
170
|
+
cwdArg: string,
|
|
171
|
+
capabilityArg: IPnpmReleaseCapability,
|
|
172
|
+
): Promise<void> => {
|
|
173
|
+
const configuredAge = await readPnpmJson(
|
|
174
|
+
shellArg,
|
|
175
|
+
cwdArg,
|
|
176
|
+
capabilityArg,
|
|
177
|
+
["config", "get", "minimum-release-age"],
|
|
178
|
+
"minimum release age",
|
|
179
|
+
);
|
|
180
|
+
const age =
|
|
181
|
+
configuredAge === undefined || configuredAge === null
|
|
182
|
+
? getDefaultMinimumReleaseAgeMinutes(capabilityArg.version)
|
|
183
|
+
: configuredAge;
|
|
184
|
+
if (
|
|
185
|
+
typeof age !== "number" ||
|
|
186
|
+
!Number.isSafeInteger(age) ||
|
|
187
|
+
age < 0 ||
|
|
188
|
+
age > Number.MAX_SAFE_INTEGER / 60_000
|
|
189
|
+
) {
|
|
190
|
+
throw new Error(
|
|
191
|
+
"pnpm minimum-release-age must be a nonnegative integer number of minutes.",
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
if (age === 0) return;
|
|
195
|
+
const configuredExclusions = await readPnpmJson(
|
|
196
|
+
shellArg,
|
|
197
|
+
cwdArg,
|
|
198
|
+
capabilityArg,
|
|
199
|
+
["config", "get", "minimum-release-age-exclude"],
|
|
200
|
+
"release-age exclusions",
|
|
173
201
|
);
|
|
174
|
-
|
|
202
|
+
const exclusions =
|
|
203
|
+
configuredExclusions === undefined || configuredExclusions === null
|
|
204
|
+
? []
|
|
205
|
+
: configuredExclusions;
|
|
206
|
+
if (
|
|
207
|
+
!Array.isArray(exclusions) ||
|
|
208
|
+
exclusions.some((value) => typeof value !== "string" || !value.trim())
|
|
209
|
+
) {
|
|
175
210
|
throw new Error(
|
|
176
|
-
|
|
211
|
+
"pnpm minimum-release-age-exclude must be an array of package selectors.",
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
if (
|
|
215
|
+
exclusions.some((selector) =>
|
|
216
|
+
packageSelectorMatches("pnpm", capabilityArg.version, selector),
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
return;
|
|
220
|
+
|
|
221
|
+
const times = await readPnpmJson(
|
|
222
|
+
shellArg,
|
|
223
|
+
cwdArg,
|
|
224
|
+
capabilityArg,
|
|
225
|
+
["view", `pnpm@${capabilityArg.version}`, "time"],
|
|
226
|
+
"publication times",
|
|
227
|
+
);
|
|
228
|
+
if (!times || typeof times !== "object" || Array.isArray(times)) {
|
|
229
|
+
throw new Error("pnpm publication times must be an object.");
|
|
230
|
+
}
|
|
231
|
+
const publishedAt = Object.hasOwn(times, capabilityArg.version)
|
|
232
|
+
? (times as Record<string, unknown>)[capabilityArg.version]
|
|
233
|
+
: undefined;
|
|
234
|
+
if (publishedAt === undefined) {
|
|
235
|
+
const ignoreMissingTime = await readPnpmJson(
|
|
236
|
+
shellArg,
|
|
237
|
+
cwdArg,
|
|
238
|
+
capabilityArg,
|
|
239
|
+
["config", "get", "minimum-release-age-ignore-missing-time"],
|
|
240
|
+
"missing publication time policy",
|
|
241
|
+
);
|
|
242
|
+
if (
|
|
243
|
+
ignoreMissingTime === true ||
|
|
244
|
+
ignoreMissingTime === undefined ||
|
|
245
|
+
ignoreMissingTime === null
|
|
246
|
+
)
|
|
247
|
+
return;
|
|
248
|
+
throw new Error(
|
|
249
|
+
`The registry has no publication time for pnpm ${capabilityArg.version}; its minimum release age cannot be verified.`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
const timestamp =
|
|
253
|
+
typeof publishedAt === "string" ? Date.parse(publishedAt) : NaN;
|
|
254
|
+
if (!Number.isFinite(timestamp))
|
|
255
|
+
throw new Error("Invalid pnpm publication timestamp.");
|
|
256
|
+
if (timestamp > Date.now() - age * 60_000) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
`pnpm ${capabilityArg.version} does not yet satisfy minimum-release-age (${age} minutes).`,
|
|
177
259
|
);
|
|
178
260
|
}
|
|
179
261
|
};
|
|
@@ -189,16 +271,17 @@ export const assertPnpmReleaseCapability = async (
|
|
|
189
271
|
timeoutKillGraceMs: 5_000,
|
|
190
272
|
});
|
|
191
273
|
const version = versionResult.stdout.trim();
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
274
|
+
if (
|
|
275
|
+
versionResult.exitCode !== 0 ||
|
|
276
|
+
versionResult.timedOut ||
|
|
277
|
+
!stablePnpmVersion.test(version)
|
|
278
|
+
) {
|
|
196
279
|
throw new Error(
|
|
197
|
-
|
|
280
|
+
"Exact release packaging requires a canonical stable pnpm version.",
|
|
198
281
|
);
|
|
199
282
|
}
|
|
200
|
-
const
|
|
201
|
-
|
|
283
|
+
const capability = Object.freeze({ version });
|
|
284
|
+
await assertPnpmReleaseAge(smartshellArg, cwdArg, capability);
|
|
202
285
|
|
|
203
286
|
const packHelp = await smartshellArg.execSpawn(
|
|
204
287
|
"pnpm",
|
|
@@ -210,12 +293,12 @@ export const assertPnpmReleaseCapability = async (
|
|
|
210
293
|
timeoutKillGraceMs: 5_000,
|
|
211
294
|
},
|
|
212
295
|
);
|
|
213
|
-
if (packHelp.exitCode !== 0) {
|
|
296
|
+
if (packHelp.exitCode !== 0 || packHelp.timedOut) {
|
|
214
297
|
throw new Error(
|
|
215
298
|
"Unable to inspect the selected pnpm pack capabilities. Exact release commands require standalone pnpm with support; Corepack launchers are unsupported.",
|
|
216
299
|
);
|
|
217
300
|
}
|
|
218
|
-
requireHelpFragments(packHelp.combinedOutput,
|
|
301
|
+
requireHelpFragments(packHelp.combinedOutput, "pack");
|
|
219
302
|
|
|
220
303
|
const publishHelp = await smartshellArg.execSpawn(
|
|
221
304
|
"pnpm",
|
|
@@ -227,14 +310,10 @@ export const assertPnpmReleaseCapability = async (
|
|
|
227
310
|
timeoutKillGraceMs: 5_000,
|
|
228
311
|
},
|
|
229
312
|
);
|
|
230
|
-
if (publishHelp.exitCode !== 0) {
|
|
313
|
+
if (publishHelp.exitCode !== 0 || publishHelp.timedOut) {
|
|
231
314
|
throw new Error("Unable to inspect pnpm publish capabilities.");
|
|
232
315
|
}
|
|
233
|
-
requireHelpFragments(
|
|
234
|
-
publishHelp.combinedOutput,
|
|
235
|
-
requirements.publish,
|
|
236
|
-
"publish",
|
|
237
|
-
);
|
|
316
|
+
requireHelpFragments(publishHelp.combinedOutput, "publish");
|
|
238
317
|
return capability;
|
|
239
318
|
};
|
|
240
319
|
|
package/ts/mod_standard/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ const commandSummaries: ICommandHelpSummary[] = [
|
|
|
17
17
|
{
|
|
18
18
|
name: "commit",
|
|
19
19
|
description:
|
|
20
|
-
"
|
|
20
|
+
"Create semantic source commits from AI or manual input",
|
|
21
21
|
},
|
|
22
22
|
{ name: "release", description: "Create versioned releases from pending changelog entries" },
|
|
23
23
|
{ name: "format", description: "Plan or apply project formatting changes" },
|
|
@@ -992,7 +992,7 @@ function getLatestVersionFromMetadata(metadata: any): string | null {
|
|
|
992
992
|
return typeof latest === "string" && latest.length > 0 ? latest : null;
|
|
993
993
|
}
|
|
994
994
|
|
|
995
|
-
function getDefaultMinimumReleaseAgeMinutes(currentPnpmVersion: string): number {
|
|
995
|
+
export function getDefaultMinimumReleaseAgeMinutes(currentPnpmVersion: string): number {
|
|
996
996
|
const majorVersion = normalizeSemver(currentPnpmVersion)[0] || 0;
|
|
997
997
|
return majorVersion >= 11 ? 1440 : 0;
|
|
998
998
|
}
|
|
@@ -1086,7 +1086,7 @@ function normalizePnpmConfigListItem(rawItem: string): string {
|
|
|
1086
1086
|
.trim();
|
|
1087
1087
|
}
|
|
1088
1088
|
|
|
1089
|
-
function packageSelectorMatches(
|
|
1089
|
+
export function packageSelectorMatches(
|
|
1090
1090
|
packageName: string,
|
|
1091
1091
|
version: string,
|
|
1092
1092
|
pattern: string,
|