@intentius/chant 0.124.33 → 0.124.35
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/cli/handlers/graph.js +2 -2
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +147 -51
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +284 -81
- package/dist/cli/handlers/release.d.ts +12 -0
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +125 -10
- package/dist/cli/handlers/run.d.ts +3 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +12 -2
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +37 -2
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +24 -0
- package/dist/cli/registry.d.ts +17 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/auto-release.d.ts +8 -1
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/auto-release.js +3 -2
- package/dist/components/green-cover.d.ts +77 -0
- package/dist/components/green-cover.d.ts.map +1 -0
- package/dist/components/green-cover.js +153 -0
- package/dist/components/pr-pipeline.d.ts +34 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +39 -5
- package/dist/components/promote-rounds.d.ts +102 -0
- package/dist/components/promote-rounds.d.ts.map +1 -0
- package/dist/components/promote-rounds.js +174 -0
- package/dist/components/promote.d.ts +4 -1
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +6 -3
- package/dist/components/release-gate.d.ts +30 -0
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +92 -42
- package/dist/components/release-promote.d.ts +9 -0
- package/dist/components/release-promote.d.ts.map +1 -1
- package/dist/components/release-promote.js +15 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/deep-observation.d.ts +11 -0
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/graph-declared.d.ts +9 -1
- package/dist/graph-declared.d.ts.map +1 -1
- package/dist/graph-declared.js +18 -3
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +30 -1
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +13 -2
- package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -1
- package/dist/lifecycle/__fixtures__/publish-fakes.js +5 -1
- package/dist/lifecycle/compose-refs.d.ts +52 -0
- package/dist/lifecycle/compose-refs.d.ts.map +1 -0
- package/dist/lifecycle/compose-refs.js +115 -0
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.js +3 -2
- package/dist/lifecycle/green-apply.d.ts +39 -0
- package/dist/lifecycle/green-apply.d.ts.map +1 -0
- package/dist/lifecycle/green-apply.js +51 -0
- package/dist/lifecycle/publish-declaration.d.ts +4 -0
- package/dist/lifecycle/publish-declaration.d.ts.map +1 -1
- package/dist/lifecycle/publish-declaration.js +15 -0
- package/dist/lifecycle/publish-npm.d.ts +7 -4
- package/dist/lifecycle/publish-npm.d.ts.map +1 -1
- package/dist/lifecycle/publish-npm.js +60 -13
- package/dist/lifecycle/release-compose.d.ts +91 -0
- package/dist/lifecycle/release-compose.d.ts.map +1 -0
- package/dist/lifecycle/release-compose.js +235 -0
- package/dist/lifecycle/release-cut.d.ts +8 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -1
- package/dist/lifecycle/release-cut.js +2 -0
- package/dist/lifecycle/release-publish.d.ts +2 -0
- package/dist/lifecycle/release-publish.d.ts.map +1 -1
- package/dist/lifecycle/release-publish.js +2 -1
- package/dist/lifecycle/release-store.d.ts +15 -0
- package/dist/lifecycle/release-store.d.ts.map +1 -1
- package/dist/lifecycle/release-store.js +5 -1
- package/dist/wave-runtime.mjs +226 -224
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.js +13 -2
- package/dist/workspace/check.schema.json +20 -2
- package/dist/workspace/checks/ci-workflow.d.ts +17 -0
- package/dist/workspace/checks/ci-workflow.d.ts.map +1 -0
- package/dist/workspace/checks/ci-workflow.js +130 -0
- package/dist/workspace/checks/security.d.ts +16 -1
- package/dist/workspace/checks/security.d.ts.map +1 -1
- package/dist/workspace/checks/security.js +4 -4
- package/dist/workspace/checks.d.ts +1 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +4 -1
- package/dist/workspace/ci-green-cli.d.ts.map +1 -1
- package/dist/workspace/ci-green-cli.js +5 -3
- package/dist/workspace/ci-green-workflow.d.ts +18 -2
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +27 -5
- package/dist/workspace/ci-green.d.ts +31 -0
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +78 -4
- package/dist/workspace/ci-init.d.ts +100 -0
- package/dist/workspace/ci-init.d.ts.map +1 -0
- package/dist/workspace/ci-init.js +434 -0
- package/dist/workspace/ci-run.d.ts +6 -0
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +2 -1
- package/dist/workspace/ci-serve.d.ts +94 -13
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +248 -30
- package/dist/workspace/ci-workflow.d.ts +91 -0
- package/dist/workspace/ci-workflow.d.ts.map +1 -0
- package/dist/workspace/ci-workflow.js +33 -0
- package/dist/workspace/declaration.d.ts +18 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +9 -2
- package/dist/workspace/declaration.schema.json +28 -0
- package/dist/workspace/delivery-metrics.d.ts +3 -1
- package/dist/workspace/delivery-metrics.d.ts.map +1 -1
- package/dist/workspace/delivery-metrics.js +12 -3
- package/dist/workspace/init.js +2 -2
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +4 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +1 -0
- package/dist/workspace/reason-codes.d.ts +9 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +10 -0
- package/dist/workspace/release-candidates.d.ts +28 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -1
- package/dist/workspace/release-candidates.js +38 -2
- package/dist/workspace/release-candidates.schema.json +51 -0
- package/dist/workspace/release-workflow.d.ts +31 -0
- package/dist/workspace/release-workflow.d.ts.map +1 -0
- package/dist/workspace/release-workflow.js +150 -0
- package/dist/workspace/releases.schema.json +30 -0
- package/package.json +1 -1
- package/src/cli/handlers/graph.ts +2 -2
- package/src/cli/handlers/pr-green.test.ts +230 -0
- package/src/cli/handlers/pr.ts +148 -66
- package/src/cli/handlers/promote.test.ts +34 -0
- package/src/cli/handlers/promote.ts +302 -91
- package/src/cli/handlers/release-compose.e2e.test.ts +133 -0
- package/src/cli/handlers/release.ts +112 -10
- package/src/cli/handlers/run.ts +12 -1
- package/src/cli/main.ts +37 -2
- package/src/cli/parse-args.ts +18 -0
- package/src/cli/registry.ts +17 -1
- package/src/codegen/release-wiring.test.ts +56 -9
- package/src/components/auto-release.test.ts +22 -0
- package/src/components/auto-release.ts +9 -2
- package/src/components/green-cover.test.ts +170 -0
- package/src/components/green-cover.ts +186 -0
- package/src/components/pr-pipeline.test.ts +14 -4
- package/src/components/pr-pipeline.ts +56 -5
- package/src/components/promote-rounds.test.ts +220 -0
- package/src/components/promote-rounds.ts +232 -0
- package/src/components/promote.test.ts +7 -0
- package/src/components/promote.ts +9 -4
- package/src/components/release-gate.test.ts +47 -0
- package/src/components/release-gate.ts +111 -46
- package/src/components/release-promote.test.ts +24 -1
- package/src/components/release-promote.ts +15 -0
- package/src/deep-observation.ts +8 -0
- package/src/graph-declared-exports.test.ts +40 -0
- package/src/graph-declared.test.ts +18 -0
- package/src/graph-declared.ts +17 -2
- package/src/graph-detail.test.ts +68 -1
- package/src/graph-detail.ts +29 -1
- package/src/graph-ir.ts +12 -4
- package/src/lifecycle/__fixtures__/publish-fakes.ts +5 -1
- package/src/lifecycle/compose-refs.ts +125 -0
- package/src/lifecycle/deep-observe.test.ts +20 -0
- package/src/lifecycle/deep-observe.ts +4 -2
- package/src/lifecycle/green-apply.ts +71 -0
- package/src/lifecycle/publish-declaration.ts +15 -0
- package/src/lifecycle/publish-npm.ts +55 -13
- package/src/lifecycle/publish-targets.test.ts +45 -0
- package/src/lifecycle/release-compose.test.ts +125 -0
- package/src/lifecycle/release-compose.ts +312 -0
- package/src/lifecycle/release-cut.ts +6 -0
- package/src/lifecycle/release-publish.ts +4 -1
- package/src/lifecycle/release-store.ts +16 -1
- package/src/workspace/__fixtures__/contract-repo.ts +11 -2
- package/src/workspace/check-contract.test.ts +3 -2
- package/src/workspace/check.schema.json +20 -2
- package/src/workspace/checks/ci-workflow.test.ts +160 -0
- package/src/workspace/checks/ci-workflow.ts +135 -0
- package/src/workspace/checks/security.ts +4 -4
- package/src/workspace/checks.ts +4 -1
- package/src/workspace/ci-green-cli.ts +5 -3
- package/src/workspace/ci-green-workflow.test.ts +52 -0
- package/src/workspace/ci-green-workflow.ts +34 -5
- package/src/workspace/ci-green.test.ts +33 -0
- package/src/workspace/ci-green.ts +85 -4
- package/src/workspace/ci-init.test.ts +159 -0
- package/src/workspace/ci-init.ts +445 -0
- package/src/workspace/ci-report-url.test.ts +6 -1
- package/src/workspace/ci-run.test.ts +18 -13
- package/src/workspace/ci-run.ts +8 -1
- package/src/workspace/ci-serve-land.e2e.test.ts +138 -0
- package/src/workspace/ci-serve-land.test.ts +176 -0
- package/src/workspace/ci-serve.test.ts +77 -43
- package/src/workspace/ci-serve.ts +268 -34
- package/src/workspace/ci-workflow.ts +71 -0
- package/src/workspace/declaration.schema.json +28 -0
- package/src/workspace/declaration.ts +32 -3
- package/src/workspace/delivery-metrics.ts +12 -3
- package/src/workspace/graph-contract.test.ts +3 -2
- package/src/workspace/init.ts +2 -2
- package/src/workspace/member-commands.test.ts +11 -4
- package/src/workspace/member-commands.ts +3 -0
- package/src/workspace/nested-graph.test.ts +4 -0
- package/src/workspace/nested-graph.ts +1 -0
- package/src/workspace/reason-codes.test.ts +2 -0
- package/src/workspace/reason-codes.ts +10 -0
- package/src/workspace/release-candidates.schema.json +51 -0
- package/src/workspace/release-candidates.test.ts +30 -3
- package/src/workspace/release-candidates.ts +54 -2
- package/src/workspace/release-workflow.ts +167 -0
- package/src/workspace/releases.schema.json +30 -0
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
* environment: every component of the release at the digest the environment
|
|
21
21
|
* ran from it, through the release gate `promote --release` binds (#4045).
|
|
22
22
|
*/
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
23
|
+
import { ENV_VAR } from "../../env.js";
|
|
24
|
+
import { dirname, join, resolve } from "node:path";
|
|
25
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
25
26
|
import { loadChantConfig } from "../../config.js";
|
|
26
27
|
import { promotionOrder } from "../../workspace/promotion-order.js";
|
|
27
28
|
import { resolvePromotionSource } from "../../components/promote-order.js";
|
|
@@ -41,7 +42,7 @@ import { resolveCliBuildParams, parseParamFlags } from "../build-params-cli.js";
|
|
|
41
42
|
import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format.js";
|
|
42
43
|
import { GATED_EXIT_CODE } from "./run.js";
|
|
43
44
|
import { redeployLine, releaseRollbackLine, rollbackTarget, unsettledComponents } from "../../lifecycle/mixed-environment.js";
|
|
44
|
-
const PROMOTE_USAGE = "chant components promote --to <env> [--from <env>] [--allow-skip] [--release <label|digest>] [--component <name> [--digest <sha256:...>] | --digest <component>=<sha256:...> ...] [--dry-run] [--json]";
|
|
45
|
+
const PROMOTE_USAGE = "chant components promote --to <env> [--from <env>] [--allow-skip] [--release <label|digest>] [--component <name> [--digest <sha256:...>] | --digest <component>=<sha256:...> ...] [--wave-gate <gate>] [--resume <file>] [--dry-run] [--json]";
|
|
45
46
|
const ROLLBACK_USAGE = "chant components rollback <env> (--component <name> [--digest <sha256:...>] | --release <label|digest>) [--dry-run] [--json]";
|
|
46
47
|
const REDEPLOY_USAGE = "chant components redeploy <env> --component <name> [--digest <sha256:...>] [--dry-run] [--json]";
|
|
47
48
|
function renderPlan(verb, plan, removed) {
|
|
@@ -73,9 +74,16 @@ function planJson(plan, removed) {
|
|
|
73
74
|
function resolveActor(ctx) {
|
|
74
75
|
return ctx.args.actor ?? process.env.GITHUB_ACTOR ?? process.env.GITLAB_USER_LOGIN ?? process.env.USER;
|
|
75
76
|
}
|
|
76
|
-
/**
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Config, params and the declared components, or the exit code of a refusal
|
|
79
|
+
* already printed. `env` is the environment being deployed: it is set as
|
|
80
|
+
* `CHANT_ENV` before the components load, as `--env` sets it for `chant run`
|
|
81
|
+
* (../main.ts), so a component that reads it (a stack name per environment)
|
|
82
|
+
* deploys to that environment and not to the one it was promoted from (#4222).
|
|
83
|
+
*/
|
|
84
|
+
async function loadProject(ctx, selector, env) {
|
|
78
85
|
const { args } = ctx;
|
|
86
|
+
process.env[ENV_VAR] = env;
|
|
79
87
|
const projectPath = resolve(".");
|
|
80
88
|
const { config } = await loadChantConfig(projectPath).catch(() => ({ config: {} }));
|
|
81
89
|
const paramsResolution = resolveCliBuildParams(config.buildParams, {
|
|
@@ -115,6 +123,11 @@ async function readLedger(env) {
|
|
|
115
123
|
* a refusal already printed: a provisional member, or a member that failed
|
|
116
124
|
* to plan. On an empty change set, each gate gets an `empty: true`
|
|
117
125
|
* resolution the run then counts once it reads the stored document back.
|
|
126
|
+
*
|
|
127
|
+
* A dependent is planned against what a promoted upstream's plan says it will
|
|
128
|
+
* expose (#4168 step 4). With a resume record, only what is left is planned,
|
|
129
|
+
* against the outputs the record kept, and the approval the record names
|
|
130
|
+
* carries on when it covers that plan.
|
|
118
131
|
*/
|
|
119
132
|
async function bindReleaseGate(input) {
|
|
120
133
|
const { plan, under, port } = input;
|
|
@@ -145,71 +158,157 @@ async function bindReleaseGate(input) {
|
|
|
145
158
|
for (const [component, u] of unsettledComponents(envRecords, await readDeployOutcomes(env).catch(() => []))) {
|
|
146
159
|
unsettled.set(component, `the ${u.outcome.verb} run ${u.outcome.runId} left ${component} ${u.state} in "${env}" and nothing has been recorded for it since, so what it runs is not known`);
|
|
147
160
|
}
|
|
148
|
-
const
|
|
161
|
+
const digests = new Map(plan.items.map((i) => [i.component, i.digest]));
|
|
162
|
+
const planSet = (only, outputs) => gate.planReleaseSet({
|
|
149
163
|
release: under.release,
|
|
150
164
|
env,
|
|
151
165
|
components: input.prepared,
|
|
152
|
-
digests
|
|
166
|
+
digests,
|
|
153
167
|
registry: input.registry,
|
|
154
168
|
current,
|
|
155
169
|
unsettled,
|
|
156
|
-
seededOutputs:
|
|
170
|
+
seededOutputs: outputs,
|
|
171
|
+
...(only ? { only } : {}),
|
|
157
172
|
});
|
|
158
|
-
const provisional = gate.provisionalMembers(doc);
|
|
159
|
-
if (provisional.length > 0) {
|
|
160
|
-
console.error(formatError({
|
|
161
|
-
message: `the change set of release ${under.label ?? releaseDigest} for "${env}" has provisional members (${provisional.join(", ")}), which no approval covers; nothing was deployed`,
|
|
162
|
-
hint: "Deploy what they read first, so they plan against real values.",
|
|
163
|
-
}));
|
|
164
|
-
return 1;
|
|
165
|
-
}
|
|
166
|
-
const failed = doc.members.filter((m) => m.status === "failed");
|
|
167
|
-
if (failed.length > 0) {
|
|
168
|
-
for (const m of failed)
|
|
169
|
-
console.error(formatError({ message: `${m.member} failed to plan for "${env}"${m.error ? `: ${m.error}` : ""}` }));
|
|
170
|
-
console.error(formatError({ message: "nothing was deployed" }));
|
|
171
|
-
return 1;
|
|
172
|
-
}
|
|
173
|
-
// The document is stored before the gate is decided, so the plan a pending
|
|
174
|
-
// gate waits on can be read, and an empty pass can be checked.
|
|
175
173
|
const { storeGateChangeSet } = await import("../../lifecycle/gate-change-set.js");
|
|
176
|
-
|
|
177
|
-
const stored = await storeGateChangeSet({ doc, cwd: input.projectPath, at: input.head ?? null });
|
|
178
|
-
if (stored.warning)
|
|
179
|
-
console.error(formatWarning({ message: stored.warning }));
|
|
180
|
-
}
|
|
181
|
-
catch (err) {
|
|
182
|
-
console.error(formatWarning({ message: `could not store the change set ${doc.digest}: ${err instanceof Error ? err.message : String(err)}` }));
|
|
183
|
-
}
|
|
174
|
+
const { readStoredChangeSet } = await import("../../lifecycle/change-set-store.js");
|
|
184
175
|
const { isEmptyChangeSet } = await import("../../change-set.js");
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const standing = resolutions.some((r) => r.empty === true && r.gate === name && r.environment === env && r.releaseDigest === releaseDigest && r.planDigest === doc.digest);
|
|
196
|
-
if (standing)
|
|
197
|
-
continue;
|
|
198
|
-
// Pushed with the resolution; the deploy records the promote writes push the same branch.
|
|
199
|
-
await port.appendResolution(gate.emptyResolution({ gate: name, doc, actor: input.actor, timestamp, ...(input.head ? { gitSha: input.head } : {}) }));
|
|
176
|
+
const verifyEmpty = gate.emptyVerifier((digest) => readStoredChangeSet(digest, { cwd: input.projectPath }), { releaseDigest, environment: env });
|
|
177
|
+
/** Refuse, store, and pass the gates of an empty plan; the binding, or the exit code of a refusal already printed. */
|
|
178
|
+
const bindDoc = async (doc, names, what) => {
|
|
179
|
+
const provisional = gate.provisionalMembers(doc);
|
|
180
|
+
if (provisional.length > 0) {
|
|
181
|
+
console.error(formatError({
|
|
182
|
+
message: `${what} of release ${under.label ?? releaseDigest} for "${env}" has provisional members (${provisional.join(", ")}), which no approval covers; nothing more was deployed`,
|
|
183
|
+
hint: "Deploy what they read first, so they plan against real values.",
|
|
184
|
+
}));
|
|
185
|
+
return 1;
|
|
200
186
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
187
|
+
const failed = doc.members.filter((m) => m.status === "failed");
|
|
188
|
+
if (failed.length > 0) {
|
|
189
|
+
for (const m of failed)
|
|
190
|
+
console.error(formatError({ message: `${m.member} failed to plan for "${env}"${m.error ? `: ${m.error}` : ""}` }));
|
|
191
|
+
console.error(formatError({ message: "nothing more was deployed" }));
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
// The document is stored before the gate is decided, so the plan a pending
|
|
195
|
+
// gate waits on can be read, and an empty pass can be checked.
|
|
196
|
+
try {
|
|
197
|
+
const stored = await storeGateChangeSet({ doc, cwd: input.projectPath, at: input.head ?? null });
|
|
198
|
+
if (stored.warning)
|
|
199
|
+
console.error(formatWarning({ message: stored.warning }));
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
console.error(formatWarning({ message: `could not store the change set ${doc.digest}: ${err instanceof Error ? err.message : String(err)}` }));
|
|
203
|
+
}
|
|
204
|
+
const empty = isEmptyChangeSet(doc);
|
|
205
|
+
console.error(formatInfo(`release gate: ${what} ${doc.digest} for "${env}"` +
|
|
206
|
+
(empty ? ", empty: its gates pass without an approval" : `, ${doc.summary.entries} entr${doc.summary.entries === 1 ? "y" : "ies"}, ${doc.summary.holes} hole(s)`) +
|
|
207
|
+
` (chant change-set show ${doc.digest})`));
|
|
208
|
+
if (empty) {
|
|
209
|
+
if (!port.appendResolution)
|
|
210
|
+
throw new Error("the gate ledger can't record a resolution, so an empty change set can't pass its gates");
|
|
211
|
+
const { resolutions } = await port.read(gate.RELEASE_GATE_OP);
|
|
212
|
+
const timestamp = new Date().toISOString();
|
|
213
|
+
for (const name of names) {
|
|
214
|
+
const standing = resolutions.some((r) => r.empty === true && r.gate === name && r.environment === env && r.releaseDigest === releaseDigest && r.planDigest === doc.digest);
|
|
215
|
+
if (standing)
|
|
216
|
+
continue;
|
|
217
|
+
// Pushed with the resolution; the deploy records the promote writes push the same branch.
|
|
218
|
+
await port.appendResolution(gate.emptyResolution({ gate: name, doc, actor: input.actor, timestamp, ...(input.head ? { gitSha: input.head } : {}) }));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return { binding: { op: gate.RELEASE_GATE_OP, planDigest: doc.digest, releaseDigest, verifyEmpty }, empty };
|
|
222
|
+
};
|
|
223
|
+
const later = {
|
|
224
|
+
replan: async (only, outputs) => (await planSet(only, outputs)).doc,
|
|
225
|
+
bind: async (doc, names) => {
|
|
226
|
+
const bound = await bindDoc(doc, names, "a later plan");
|
|
227
|
+
if (typeof bound === "number")
|
|
228
|
+
throw new PromoteStageRefused();
|
|
229
|
+
return bound.binding;
|
|
211
230
|
},
|
|
212
231
|
};
|
|
232
|
+
// #4168 step 4: a resume plans what is left against the outputs it kept.
|
|
233
|
+
if (input.resume) {
|
|
234
|
+
const done = new Set(input.resume.completed);
|
|
235
|
+
const left = new Set(plan.items.map((i) => i.component).filter((c) => !done.has(c)));
|
|
236
|
+
const fresh = await planSet(left, { ...input.seededOutputs, ...input.resume.outputs });
|
|
237
|
+
const stored = await readStoredChangeSet(input.resume.approvedDigest, { cwd: input.projectPath });
|
|
238
|
+
if (stored.status === "found") {
|
|
239
|
+
const { waveNotCovered } = await import("../../components/pr-run.js");
|
|
240
|
+
const notCovered = waveNotCovered(stored.document, fresh.doc);
|
|
241
|
+
if (notCovered.length === 0) {
|
|
242
|
+
console.error(formatInfo(`resuming: ${done.size} component(s) applied earlier; what is left is covered by change set ${stored.document.digest}`));
|
|
243
|
+
return {
|
|
244
|
+
doc: stored.document,
|
|
245
|
+
empty: isEmptyChangeSet(stored.document),
|
|
246
|
+
binding: { op: gate.RELEASE_GATE_OP, planDigest: stored.document.digest, releaseDigest, verifyEmpty },
|
|
247
|
+
reads: fresh.reads,
|
|
248
|
+
resumedFrom: stored.document.digest,
|
|
249
|
+
...(fresh.plannedOutputs ? { plannedOutputs: fresh.plannedOutputs } : {}),
|
|
250
|
+
...(fresh.unknownInputs ? { unknownInputs: fresh.unknownInputs } : {}),
|
|
251
|
+
...later,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
for (const line of notCovered)
|
|
255
|
+
console.error(formatWarning({ message: `resume: ${line}` }));
|
|
256
|
+
}
|
|
257
|
+
const bound = await bindDoc(fresh.doc, gates, "change set");
|
|
258
|
+
if (typeof bound === "number")
|
|
259
|
+
return bound;
|
|
260
|
+
return { doc: fresh.doc, ...bound, reads: fresh.reads, ...(fresh.plannedOutputs ? { plannedOutputs: fresh.plannedOutputs } : {}), ...(fresh.unknownInputs ? { unknownInputs: fresh.unknownInputs } : {}), ...later };
|
|
261
|
+
}
|
|
262
|
+
const first = await planSet(undefined, input.seededOutputs);
|
|
263
|
+
const bound = await bindDoc(first.doc, gates, "change set");
|
|
264
|
+
if (typeof bound === "number")
|
|
265
|
+
return bound;
|
|
266
|
+
for (const [component, refs] of Object.entries(first.unknownInputs ?? {})) {
|
|
267
|
+
console.error(formatInfo(`${component} reads ${refs.join(", ")}, known only once its upstream applies; it is planned again then, and needs its own approval if its plan moves`));
|
|
268
|
+
}
|
|
269
|
+
return { doc: first.doc, ...bound, reads: first.reads, ...(first.plannedOutputs ? { plannedOutputs: first.plannedOutputs } : {}), ...(first.unknownInputs ? { unknownInputs: first.unknownInputs } : {}), ...later };
|
|
270
|
+
}
|
|
271
|
+
/** A later round's or wave's plan was refused (provisional or failed members); the refusal is already printed. */
|
|
272
|
+
class PromoteStageRefused extends Error {
|
|
273
|
+
constructor() {
|
|
274
|
+
super("a later round's plan was refused");
|
|
275
|
+
this.name = "PromoteStageRefused";
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The pull requests a release carries into `env` and how each was approved
|
|
280
|
+
* on merge (#4168 decision 2): shown beside the release gate, never counted
|
|
281
|
+
* by it. The commits are the release commit's first-parent history since
|
|
282
|
+
* the commits `env` runs, at most 200, read from the merge records.
|
|
283
|
+
*/
|
|
284
|
+
async function pullRequestApprovals(release, since, cwd) {
|
|
285
|
+
const { execFileSync } = await import("node:child_process");
|
|
286
|
+
const { readMergeRecord } = await import("../../lifecycle/merge-record.js");
|
|
287
|
+
let commits = [];
|
|
288
|
+
try {
|
|
289
|
+
const out = execFileSync("git", ["rev-list", "--first-parent", "--max-count=200", release.commit, ...since.map((c) => `^${c}`)], { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
290
|
+
commits = out.split("\n").filter(Boolean);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
const records = [];
|
|
296
|
+
for (const commit of commits) {
|
|
297
|
+
const record = await readMergeRecord(commit, { cwd }).catch(() => null);
|
|
298
|
+
if (record)
|
|
299
|
+
records.push(record);
|
|
300
|
+
}
|
|
301
|
+
return records;
|
|
302
|
+
}
|
|
303
|
+
/** One line per merge record: where it came from and how its plan stood against its approval. */
|
|
304
|
+
function approvalLine(r) {
|
|
305
|
+
const from = r.source.kind === "pull-request" ? `#${r.source.pr}` : r.source.kind === "work-item" ? r.source.records.map((x) => `${x.kind}:${x.id}`).join(", ") : "direct push";
|
|
306
|
+
const how = r.plan === "approved"
|
|
307
|
+
? `approved by ${r.approvedBy.join(", ") || "nobody named"}${r.authorApproved?.length ? ` (by its author: ${r.authorApproved.join(", ")})` : ""}`
|
|
308
|
+
: r.plan === "changed"
|
|
309
|
+
? `its plan moved after the approval of ${r.approvedDigest ?? "another digest"}`
|
|
310
|
+
: r.plan;
|
|
311
|
+
return `${r.commit.slice(0, 12)} ${from}: ${how}`;
|
|
213
312
|
}
|
|
214
313
|
/**
|
|
215
314
|
* Prepare, run and record a plan. Shared by promote, rollback and redeploy,
|
|
@@ -224,15 +323,21 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
|
|
|
224
323
|
const prepared = [];
|
|
225
324
|
const removed = new Map();
|
|
226
325
|
const refusals = [];
|
|
326
|
+
// #4222: a component with no artifact, deployed from the templates the release records, and its record's digest.
|
|
327
|
+
const templateDigests = new Map();
|
|
328
|
+
const { releaseTemplatesDigest } = await import("../../components/release-promote.js");
|
|
227
329
|
for (const item of plan.items) {
|
|
330
|
+
const templates = under ? releaseTemplatesDigest(under.target, item.component) : null;
|
|
228
331
|
// A rollback and a redeploy deploy a release this environment already
|
|
229
332
|
// received, so neither runs the publish step.
|
|
230
|
-
const result = withoutBuildSteps(byName.get(item.component), verb === "promote" ? {} : { pinDigest: item.digest, verb: `a ${verb}` });
|
|
333
|
+
const result = withoutBuildSteps(byName.get(item.component), { ...(verb === "promote" ? {} : { pinDigest: item.digest, verb: `a ${verb}` }), templatesPinned: templates !== null });
|
|
231
334
|
if ("error" in result)
|
|
232
335
|
refusals.push(result.error);
|
|
233
336
|
else {
|
|
234
337
|
prepared.push(result.component);
|
|
235
338
|
removed.set(item.component, result.removed);
|
|
339
|
+
if (result.templateOnly && templates !== null)
|
|
340
|
+
templateDigests.set(item.component, templates);
|
|
236
341
|
}
|
|
237
342
|
}
|
|
238
343
|
if (refusals.length > 0) {
|
|
@@ -319,16 +424,43 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
|
|
|
319
424
|
// #4045: under a release, every gate binds the release's change set for this environment.
|
|
320
425
|
let releaseGate;
|
|
321
426
|
let changeSetJson;
|
|
427
|
+
let bound;
|
|
428
|
+
// #4168 step 4: a promote that stopped at a round's or a wave's gate left a resume record.
|
|
429
|
+
const rounds = await import("../../components/promote-rounds.js");
|
|
430
|
+
const resumePath = resolve(project.projectPath, args.resume ?? join(".chant", "promote", `${plan.to}.resume.json`));
|
|
431
|
+
let resume;
|
|
432
|
+
if (under && existsSync(resumePath)) {
|
|
433
|
+
try {
|
|
434
|
+
const record = JSON.parse(readFileSync(resumePath, "utf8"));
|
|
435
|
+
if (record.schema === rounds.PROMOTE_RESUME_SCHEMA && record.env === plan.to && record.releaseDigest === under.release.releaseDigest)
|
|
436
|
+
resume = record;
|
|
437
|
+
else if (args.resume)
|
|
438
|
+
console.error(formatWarning({ message: `--resume ${args.resume} is for another release or environment; planning from the start` }));
|
|
439
|
+
}
|
|
440
|
+
catch (err) {
|
|
441
|
+
console.error(formatWarning({ message: `could not read the resume record ${resumePath}: ${err instanceof Error ? err.message : String(err)}` }));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
let pullRequests = [];
|
|
322
445
|
if (under) {
|
|
323
446
|
try {
|
|
324
|
-
const
|
|
325
|
-
if (typeof
|
|
447
|
+
const result = await bindReleaseGate({ plan, prepared, under, registry, port, seededOutputs, actor: actor, projectPath: project.projectPath, head, ...(resume ? { resume } : {}) });
|
|
448
|
+
if (typeof result === "number") {
|
|
326
449
|
tidy();
|
|
327
|
-
return
|
|
450
|
+
return result;
|
|
328
451
|
}
|
|
329
|
-
if (
|
|
330
|
-
|
|
331
|
-
|
|
452
|
+
if (result) {
|
|
453
|
+
bound = result;
|
|
454
|
+
releaseGate = result.binding;
|
|
455
|
+
changeSetJson = { changeSet: result.doc.digest, empty: result.empty };
|
|
456
|
+
// #4168 decision 2: the pull requests' own approvals, shown beside the gate.
|
|
457
|
+
const since = [...new Set((await readLedger(plan.to)).filter((r) => r.env === plan.to).map((r) => r.gitSha))];
|
|
458
|
+
pullRequests = await pullRequestApprovals(under.release, since, project.projectPath);
|
|
459
|
+
if (pullRequests.length > 0 && !args.json) {
|
|
460
|
+
console.error(formatInfo(`pull requests this release carries into "${plan.to}" (shown, not counted by the release gate):`));
|
|
461
|
+
for (const r of pullRequests)
|
|
462
|
+
console.error(` ${approvalLine(r)}`);
|
|
463
|
+
}
|
|
332
464
|
}
|
|
333
465
|
}
|
|
334
466
|
catch (err) {
|
|
@@ -336,6 +468,11 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
|
|
|
336
468
|
throw err;
|
|
337
469
|
}
|
|
338
470
|
}
|
|
471
|
+
if (args.waveGate && !bound) {
|
|
472
|
+
console.error(formatError({ message: "--wave-gate needs a promote under --release whose compositions declare a gate", hint: PROMOTE_USAGE }));
|
|
473
|
+
tidy();
|
|
474
|
+
return 1;
|
|
475
|
+
}
|
|
339
476
|
// The run id the release records carry, chosen before the run so that
|
|
340
477
|
// `--events-json` (#4041) names the run by it too.
|
|
341
478
|
const { runId, runOrigin } = resolveRunId(args.runId);
|
|
@@ -346,25 +483,88 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
|
|
|
346
483
|
cwd: project.projectPath,
|
|
347
484
|
});
|
|
348
485
|
let run;
|
|
486
|
+
let staged;
|
|
487
|
+
// #4168 step 4: a wave at a time when a dependent read an upstream's plan,
|
|
488
|
+
// under --wave-gate, or on a resume; one run otherwise.
|
|
489
|
+
const inPlan = new Set(plan.items.map((i) => i.component));
|
|
490
|
+
const readsPlanned = bound?.plannedOutputs !== undefined && Object.keys(bound.plannedOutputs).some((d) => inPlan.has(d));
|
|
491
|
+
const inRounds = bound !== undefined && (readsPlanned || args.waveGate !== undefined || resume !== undefined);
|
|
349
492
|
try {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
493
|
+
if (inRounds && bound) {
|
|
494
|
+
staged = await rounds.runPromotionInRounds({
|
|
495
|
+
components: prepared,
|
|
496
|
+
outputs: { ...seededOutputs, ...(resume?.outputs ?? {}) },
|
|
497
|
+
binding: bound.binding,
|
|
498
|
+
approved: bound.doc,
|
|
499
|
+
reads: bound.reads,
|
|
500
|
+
...(resume ? { completed: resume.completed } : {}),
|
|
501
|
+
...(args.waveGate ? { waveGate: args.waveGate } : {}),
|
|
502
|
+
replan: bound.replan,
|
|
503
|
+
bind: bound.bind,
|
|
504
|
+
run: (components, outputs, binding) => runPromotion({
|
|
505
|
+
plan: { ...plan, items: plan.items.filter((i) => components.some((c) => c.name === i.component)) },
|
|
506
|
+
components,
|
|
507
|
+
registry,
|
|
508
|
+
componentOutputs: outputs,
|
|
509
|
+
gates: port,
|
|
510
|
+
releaseGate: binding,
|
|
511
|
+
...(args.progressJson ? { onProgress: ndjsonProgressSink() } : {}),
|
|
512
|
+
...(events ? { onRunEvent: events.emit } : {}),
|
|
513
|
+
}),
|
|
514
|
+
});
|
|
515
|
+
run = staged.run;
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
run = await runPromotion({
|
|
519
|
+
plan,
|
|
520
|
+
components: prepared,
|
|
521
|
+
registry,
|
|
522
|
+
componentOutputs: seededOutputs,
|
|
523
|
+
gates: port,
|
|
524
|
+
...(releaseGate ? { releaseGate } : {}),
|
|
525
|
+
...(args.progressJson ? { onProgress: ndjsonProgressSink() } : {}),
|
|
526
|
+
...(events ? { onRunEvent: events.emit } : {}),
|
|
527
|
+
});
|
|
528
|
+
}
|
|
360
529
|
}
|
|
361
530
|
catch (err) {
|
|
531
|
+
if (err instanceof PromoteStageRefused) {
|
|
532
|
+
events?.settle("failed", err.message);
|
|
533
|
+
return 1;
|
|
534
|
+
}
|
|
362
535
|
events?.settle("failed", err instanceof Error ? err.message : String(err));
|
|
363
536
|
throw err;
|
|
364
537
|
}
|
|
365
538
|
finally {
|
|
366
539
|
tidy();
|
|
367
540
|
}
|
|
541
|
+
if (staged && bound) {
|
|
542
|
+
for (const stage of staged.stages) {
|
|
543
|
+
const label = stage.kind === "round" ? `round ${stage.number}` : `wave ${stage.number}`;
|
|
544
|
+
console.error(formatInfo(`${label} (${stage.components.join(", ")}): planned again as ${stage.digest}, ${stage.status}`));
|
|
545
|
+
for (const line of stage.notCovered)
|
|
546
|
+
console.error(` not covered by ${bound.doc.digest}: ${line}`);
|
|
547
|
+
if (stage.message)
|
|
548
|
+
console.error(formatError({ message: stage.message }));
|
|
549
|
+
}
|
|
550
|
+
if (run.status === "ok") {
|
|
551
|
+
rmSync(resumePath, { force: true });
|
|
552
|
+
}
|
|
553
|
+
else if (staged.completed.length > 0) {
|
|
554
|
+
const record = {
|
|
555
|
+
schema: rounds.PROMOTE_RESUME_SCHEMA,
|
|
556
|
+
env: plan.to,
|
|
557
|
+
releaseDigest: under.release.releaseDigest,
|
|
558
|
+
approvedDigest: resume?.approvedDigest ?? bound.resumedFrom ?? bound.doc.digest,
|
|
559
|
+
completed: staged.completed,
|
|
560
|
+
outputs: staged.outputs,
|
|
561
|
+
at: new Date().toISOString(),
|
|
562
|
+
};
|
|
563
|
+
mkdirSync(dirname(resumePath), { recursive: true });
|
|
564
|
+
writeFileSync(resumePath, `${JSON.stringify(record, null, 2)}\n`);
|
|
565
|
+
console.error(formatInfo(`resume record: ${resumePath}; the same promote carries on from here`));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
368
568
|
// The driver settles the stream; this only ends one it left open.
|
|
369
569
|
events?.settle(run.status === "fail" ? "failed" : run.status);
|
|
370
570
|
if (!args.json)
|
|
@@ -387,7 +587,8 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
|
|
|
387
587
|
const approver = gateApprover(result);
|
|
388
588
|
const admission = gateAdmission(result);
|
|
389
589
|
const input = record(item, plan.to, { runId, ...(runOrigin ? { runOrigin } : {}), actor: actor, timestamp, ...(approver ? { approver } : {}), ...(admission ? { admission } : {}) });
|
|
390
|
-
const
|
|
590
|
+
const templates = templateDigests.get(item.component);
|
|
591
|
+
const { record: written } = await appendReleaseRecord(under ? { ...input, ...(templates ? { digest: templates } : {}), releaseDigest: under.release.releaseDigest } : input);
|
|
391
592
|
recorded.push(written);
|
|
392
593
|
}
|
|
393
594
|
if (outcome)
|
|
@@ -400,7 +601,9 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
|
|
|
400
601
|
}
|
|
401
602
|
if (args.json) {
|
|
402
603
|
const withChangeSet = under && changeSetJson ? { release: { ...releaseJson.release, ...changeSetJson } } : releaseJson;
|
|
403
|
-
|
|
604
|
+
const stagedJson = staged ? { stages: staged.stages, ...(bound?.plannedOutputs ? { plannedOutputs: bound.plannedOutputs } : {}), ...(bound?.unknownInputs ? { unknownInputs: bound.unknownInputs } : {}) } : {};
|
|
605
|
+
const prJson = pullRequests.length > 0 ? { pullRequests: pullRequests.map((r) => ({ commit: r.commit, source: r.source, plan: r.plan, digest: r.digest, approvedBy: r.approvedBy, ...(r.authorApproved ? { authorApproved: r.authorApproved } : {}) })) } : {};
|
|
606
|
+
console.log(JSON.stringify({ ...planJson(plan, removed), ...withChangeSet, ...stagedJson, ...prJson, run, recorded, ...(outcome ? { outcome } : {}) }, null, 2));
|
|
404
607
|
}
|
|
405
608
|
else {
|
|
406
609
|
for (const r of recorded) {
|
|
@@ -604,7 +807,7 @@ export async function runComponentsPromote(ctx) {
|
|
|
604
807
|
const who = actorOrRefuse(ctx);
|
|
605
808
|
if (typeof who === "number")
|
|
606
809
|
return who;
|
|
607
|
-
const project = await loadProject(ctx, args.component ?? "all");
|
|
810
|
+
const project = await loadProject(ctx, args.component ?? "all", to);
|
|
608
811
|
if (typeof project === "number")
|
|
609
812
|
return project;
|
|
610
813
|
// The member's `environments` array is its promotion order (#4030). It
|
|
@@ -686,7 +889,7 @@ export async function runComponentsRollback(ctx) {
|
|
|
686
889
|
return who;
|
|
687
890
|
if (args.release)
|
|
688
891
|
return runReleaseRollback(ctx, env, args.release, who.actor);
|
|
689
|
-
const project = await loadProject(ctx, args.component);
|
|
892
|
+
const project = await loadProject(ctx, args.component, env);
|
|
690
893
|
if (typeof project === "number")
|
|
691
894
|
return project;
|
|
692
895
|
await fetchLifecycle().catch(() => false);
|
|
@@ -716,7 +919,7 @@ export async function runComponentsRollback(ctx) {
|
|
|
716
919
|
* runs now, as `promote --release` binds them (#4045).
|
|
717
920
|
*/
|
|
718
921
|
async function runReleaseRollback(ctx, env, ref, actor) {
|
|
719
|
-
const project = await loadProject(ctx, "all");
|
|
922
|
+
const project = await loadProject(ctx, "all", env);
|
|
720
923
|
if (typeof project === "number")
|
|
721
924
|
return project;
|
|
722
925
|
await fetchLifecycle().catch(() => false);
|
|
@@ -754,7 +957,7 @@ export async function runComponentsRedeploy(ctx) {
|
|
|
754
957
|
const who = actorOrRefuse(ctx);
|
|
755
958
|
if (typeof who === "number")
|
|
756
959
|
return who;
|
|
757
|
-
const project = await loadProject(ctx, args.component);
|
|
960
|
+
const project = await loadProject(ctx, args.component, env);
|
|
758
961
|
if (typeof project === "number")
|
|
759
962
|
return project;
|
|
760
963
|
await fetchLifecycle().catch(() => false);
|
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
* release candidates [--env <env>] [--json]
|
|
21
21
|
* the green commits of trunk a release can be cut from, each with what it
|
|
22
22
|
* would ship, and what each environment runs (#4168 4.2)
|
|
23
|
+
* release compose <name> [--base <label|sha>] (--pr <n> | --work <id>)... [--yes] [--json]
|
|
24
|
+
* pick chosen trunk changes onto a base, each with a Chant-Composed-From
|
|
25
|
+
* trailer, on the pushed branch chant/compose/<name> (#4168 4.3); a dry
|
|
26
|
+
* run unless --yes. `release cut` takes a green commit of that branch,
|
|
27
|
+
* and `--channel <tag>` makes its publish move that tag, not latest
|
|
23
28
|
* release list [--json]
|
|
24
29
|
* every release of this member with its targets, its cuts and where it runs;
|
|
25
30
|
* `--json` prints the read contract's `releases` document
|
|
@@ -103,4 +108,11 @@ export declare function runReleaseExport(ctx: CommandContext): Promise<number>;
|
|
|
103
108
|
/** Internal: compile one environment, or build artifacts, in this process, and print the JSON the cut reads. */
|
|
104
109
|
export declare function runReleaseCompile(ctx: CommandContext): Promise<number>;
|
|
105
110
|
export declare function runReleaseUnknown(ctx: CommandContext): Promise<number>;
|
|
111
|
+
/**
|
|
112
|
+
* `release compose <name> [--base <label|sha>] (--pr <n> | --work <id>)... [--yes] [--json]`
|
|
113
|
+
* (#4168 4.3): pick the chosen trunk changes onto a base, on
|
|
114
|
+
* `chant/compose/<name>` (../../lifecycle/release-compose.ts). A dry run
|
|
115
|
+
* unless `--yes`, which moves the branch and pushes it so CI builds it.
|
|
116
|
+
*/
|
|
117
|
+
export declare function runReleaseCompose(ctx: CommandContext): Promise<number>;
|
|
106
118
|
//# sourceMappingURL=release.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/release.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/release.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAyBlD,0HAA0H;AAC1H,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uFAAuF;IACvF,YAAY,EAAE,OAAO,CAAC;CACvB,GAAG,MAAM,EAAE,CASX;AAED,wGAAwG;AACxG,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAG3D;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqPxE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA4G5E;AAQD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAkC3E;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsC/E;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BzE;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC3E;AAED,gHAAgH;AAChH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB5E;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5E;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsD5E"}
|