@intentius/plywood 0.3.5 → 0.3.8
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/image-digests.json +2 -2
- package/dist/plywood.mjs +124 -169
- package/dist/plywood.mjs.map +4 -4
- package/package.json +19 -7
package/dist/plywood.mjs
CHANGED
|
@@ -20,7 +20,7 @@ var __export = (target, all) => {
|
|
|
20
20
|
var define_PLYWOOD_IMAGE_DIGESTS_default;
|
|
21
21
|
var init_define_PLYWOOD_IMAGE_DIGESTS = __esm({
|
|
22
22
|
"<define:__PLYWOOD_IMAGE_DIGESTS__>"() {
|
|
23
|
-
define_PLYWOOD_IMAGE_DIGESTS_default = { "ghcr.io/intentius/plywood-pulumi:0.3.
|
|
23
|
+
define_PLYWOOD_IMAGE_DIGESTS_default = { "ghcr.io/intentius/plywood-pulumi:0.3.8-pulumi3.272.0": "sha256:b26afcdd7dd108768663bd5b3cef524b5323b5f5fff8ccb79d717c2895713ae3", "ghcr.io/intentius/plywood-plunge:0.3.8-plunge0.2.0": "sha256:48878580388a54ad5635c378d4848424354f9ca4b8f67434b7614a8210446b3e" };
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
26
|
|
|
@@ -409,38 +409,24 @@ function wordsForJobs(jobs2) {
|
|
|
409
409
|
function driftOpName(stack) {
|
|
410
410
|
return DRIFT_OP_PREFIX + stack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
411
411
|
}
|
|
412
|
-
function driftIssueMarker(stack) {
|
|
413
|
-
return `<!-- plywood:drift ${stack} -->`;
|
|
414
|
-
}
|
|
415
412
|
function driftIssueTitle(stack) {
|
|
416
413
|
return `plywood: ${stack} has drifted`;
|
|
417
414
|
}
|
|
418
|
-
function
|
|
419
|
-
return
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
"
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
...input.attribution?.length ? ["Who changed each attribute, from the known writes and the audit log:", "", ...input.attribution, ""] : [],
|
|
432
|
-
`To put the cloud back to the program, merge a change to ${stack} or run \`${PRODUCT} up\`. To keep the cloud's values, change the program to match and let its preview show no changes.`,
|
|
433
|
-
...input.respond === "up" ? ["", `respond.drift is up, so this run also asked for an update of ${stack}'s wave; its gate decides.`] : [],
|
|
434
|
-
...input.runUrl ? ["", `Read by ${input.runUrl}.`] : [],
|
|
435
|
-
"",
|
|
436
|
-
`<!-- plywood:drift-fingerprint ${input.fingerprint} -->`
|
|
437
|
-
];
|
|
438
|
-
return lines2.join("\n");
|
|
439
|
-
}
|
|
440
|
-
function driftClearedComment(stack, observedAt2) {
|
|
441
|
-
return `plywood's drift check at ${observedAt2} found ${stack} matching its state, so this issue is closed.`;
|
|
415
|
+
function driftIssueWords(stack, respond) {
|
|
416
|
+
return {
|
|
417
|
+
product: PRODUCT,
|
|
418
|
+
title: () => driftIssueTitle(stack),
|
|
419
|
+
intro: ({ drifted, observedAt: observedAt2 }) => `plywood's drift check read ${stack} against the cloud at ${observedAt2} and found ${drifted.length} resource${drifted.length === 1 ? "" : "s"} that differ from the stack's state.`,
|
|
420
|
+
address: "URN",
|
|
421
|
+
advice: () => [
|
|
422
|
+
`To put the cloud back to the program, merge a change to ${stack} or run \`${PRODUCT} up\`. To keep the cloud's values, change the program to match and let its preview show no changes.`,
|
|
423
|
+
...respond === "up" ? ["", `respond.drift is up, so this run also asked for an update of ${stack}'s wave; its gate decides.`] : []
|
|
424
|
+
].join("\n"),
|
|
425
|
+
foundBy: (runUrl) => `Read by ${runUrl}.`,
|
|
426
|
+
cleared: ({ observedAt: observedAt2 }) => `plywood's drift check at ${observedAt2} found ${stack} matching its state, so this issue is closed.`
|
|
427
|
+
};
|
|
442
428
|
}
|
|
443
|
-
var PRODUCT, TAGLINE, OP_NAME, PR_GATE, VERBS, BIN, NOTIFY_WORDS, PRODUCT_WORDS, ACTION_COMMAND, POLICY_RULE_FORMS, CLOUD_NAMES, NO_IDENTITY, TEMPLATE_REQUEST_WORDS, STACK_OP_WORDS, DRIFT_OP_PREFIX, LOCK_GRAIN_WORDS, PLUNGE_TIMING_ATTRIBUTES;
|
|
429
|
+
var PRODUCT, TAGLINE, OP_NAME, PR_GATE, VERBS, BIN, NOTIFY_WORDS, PRODUCT_WORDS, ACTION_COMMAND, POLICY_RULE_FORMS, CLOUD_NAMES, NO_IDENTITY, TEMPLATE_REQUEST_WORDS, STACK_OP_WORDS, DRIFT_OP_PREFIX, DRIFT_ATTRIBUTION_HEADING, LOCK_GRAIN_WORDS, PLUNGE_TIMING_ATTRIBUTES;
|
|
444
430
|
var init_words = __esm({
|
|
445
431
|
"src/words.ts"() {
|
|
446
432
|
"use strict";
|
|
@@ -484,7 +470,7 @@ var init_words = __esm({
|
|
|
484
470
|
};
|
|
485
471
|
STACK_OP_WORDS = {
|
|
486
472
|
usage: {
|
|
487
|
-
export: `${PRODUCT} export <project/stack> --out <file
|
|
473
|
+
export: `${PRODUCT} export <project/stack> --out <file> [--version <n>]`,
|
|
488
474
|
cancel: `${PRODUCT} cancel <project/stack> [--lock <id>]`,
|
|
489
475
|
move: `${PRODUCT} move <urn>... --from <project/stack> --to <project/stack>, or ${PRODUCT} move <project/stack> --onto plunge`,
|
|
490
476
|
rollback: `${PRODUCT} rollback <project/stack> [--digest <sha256:...>], or ${PRODUCT} rollback --release <name> --env <env>`,
|
|
@@ -495,7 +481,7 @@ var init_words = __esm({
|
|
|
495
481
|
acted: (stack, name, r) => `Ran action ${name} on ${stack}: ${r.engine} replaced ${r.urn}.${r.tail ? `
|
|
496
482
|
${r.tail}` : ""}`,
|
|
497
483
|
noAction: (stack, name, declared) => declared.length ? `${stack} has no action ${name} in plywood.yml; its actions are ${declared.join(", ")}` : `${stack} declares no actions in plywood.yml; add one under stacks.${stack}.actions with a name and the URN of a command resource`,
|
|
498
|
-
exported: (stack, r) => `Exported ${stack} to ${r.file} (${r.resources} resources, ${r.bytes} bytes, sha256 ${r.sha256}). The file is readable by you alone; the ledger keeps its digest and size, never its content.`,
|
|
484
|
+
exported: (stack, r) => `Exported version ${r.version} of ${stack} to ${r.file} (${r.resources} resources, ${r.bytes} bytes, sha256 ${r.sha256}). The file is readable by you alone; the ledger keeps its digest and size, never its content.`,
|
|
499
485
|
cancelled: (stack, lock, checked) => `Released lock ${lock} on ${stack}.${checked ? "" : " The backend's lock could not be read, so it was not checked against the approved one first."}`,
|
|
500
486
|
moved: (from, to, r) => `Moved ${r.moved.length} resource${r.moved.length === 1 ? "" : "s"} from ${from} to ${to} on ${r.engine}. Both stacks preview no change.`,
|
|
501
487
|
needsLock: "cancel needs --lock <id>, the lock the stack holds: the id pulumi printed when it refused the update, or the file name under .pulumi/locks/ on a file:// backend",
|
|
@@ -509,6 +495,7 @@ ${r.tail}` : ""}`,
|
|
|
509
495
|
releaseIsEnvWide: (stack, env) => `--release rolls back every stack the release records in an environment, so it takes --env, not a stack. Run '${PRODUCT} rollback --release <name> --env ${env}', or '${PRODUCT} rollback ${stack}' for this stack's previous release.`
|
|
510
496
|
};
|
|
511
497
|
DRIFT_OP_PREFIX = "plywood-drift-";
|
|
498
|
+
DRIFT_ATTRIBUTION_HEADING = "Who changed each attribute, from the known writes and the audit log:";
|
|
512
499
|
LOCK_GRAIN_WORDS = {
|
|
513
500
|
perEngine: (engine3) => engine3 === "plunge" ? "resource, plunge's default (no ci.lockGrain; chant's pulumi lexicon sets it)" : engine3 === "pulumi" ? "stack, stock Pulumi's default (no ci.lockGrain; chant's pulumi lexicon sets it)" : "per engine: resource on plunge, stack on stock Pulumi (no ci.lockGrain; chant's pulumi lexicon sets it)"
|
|
514
501
|
};
|
|
@@ -618,47 +605,29 @@ var init_control = __esm({
|
|
|
618
605
|
var version, dependencies;
|
|
619
606
|
var init_package = __esm({
|
|
620
607
|
"package.json"() {
|
|
621
|
-
version = "0.3.
|
|
608
|
+
version = "0.3.8";
|
|
622
609
|
dependencies = {
|
|
623
|
-
"@intentius/chant": "0.124.
|
|
624
|
-
"@intentius/chant-lexicon-forgejo": "0.124.
|
|
625
|
-
"@intentius/chant-lexicon-github": "0.124.
|
|
626
|
-
"@intentius/chant-lexicon-gitlab": "0.124.
|
|
627
|
-
"@intentius/chant-lexicon-pulumi": "0.124.
|
|
610
|
+
"@intentius/chant": "0.124.87",
|
|
611
|
+
"@intentius/chant-lexicon-forgejo": "0.124.87",
|
|
612
|
+
"@intentius/chant-lexicon-github": "0.124.87",
|
|
613
|
+
"@intentius/chant-lexicon-gitlab": "0.124.87",
|
|
614
|
+
"@intentius/chant-lexicon-pulumi": "0.124.87"
|
|
628
615
|
};
|
|
629
616
|
}
|
|
630
617
|
});
|
|
631
618
|
|
|
632
619
|
// src/images.ts
|
|
633
|
-
import {
|
|
620
|
+
import { ciToolSha256, derivedImageDockerfile, productImageDockerfile } from "@intentius/chant/ci-image";
|
|
621
|
+
import { plungeInstallLine, pulumiInstallLine } from "@intentius/chant-lexicon-pulumi/ci-setup";
|
|
634
622
|
function engineDir(engine3, version2) {
|
|
635
623
|
return `${ENGINE_ROOT}/${engine3}-${version2}`;
|
|
636
624
|
}
|
|
637
625
|
function engineBin(engine3, version2) {
|
|
638
626
|
return `${engineDir(engine3, version2)}/${engine3}`;
|
|
639
627
|
}
|
|
640
|
-
function release(engine3, version2) {
|
|
641
|
-
if (engine3 === "pulumi") {
|
|
642
|
-
return {
|
|
643
|
-
base: `https://github.com/pulumi/pulumi/releases/download/v${version2}`,
|
|
644
|
-
archive: (arch) => `pulumi-v${version2}-linux-${arch}.tar.gz`,
|
|
645
|
-
checksums: `pulumi-${version2}-checksums.txt`
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
return {
|
|
649
|
-
base: `https://github.com/INTENTIUS/plunge/releases/download/plunge-v${version2}`,
|
|
650
|
-
archive: (arch) => `plunge-v${version2}-linux-${arch}.tar.gz`,
|
|
651
|
-
checksums: `plunge-v${version2}-checksums.txt`
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
628
|
function pinnedSums(engine3, version2) {
|
|
655
|
-
const
|
|
656
|
-
|
|
657
|
-
for (const arch of ARCHES) {
|
|
658
|
-
const sum = PINNED_SHA256[r.archive(arch)];
|
|
659
|
-
if (sum) out[arch] = sum;
|
|
660
|
-
}
|
|
661
|
-
return out;
|
|
629
|
+
const sums = ciToolSha256(engine3, version2);
|
|
630
|
+
return { ...sums.amd64 ? { x64: sums.amd64 } : {}, ...sums.arm64 ? { arm64: sums.arm64 } : {} };
|
|
662
631
|
}
|
|
663
632
|
function installLine(engine3, version2, link = true) {
|
|
664
633
|
const sums = pinnedSums(engine3, version2);
|
|
@@ -704,7 +673,7 @@ function chantPipelineOptions(p) {
|
|
|
704
673
|
const lines2 = p.engineSetup ?? [];
|
|
705
674
|
return { ...p.image ? { image: p.image } : {}, ...p.runner !== void 0 ? { runner: p.runner } : {}, ...lines2.length ? { beforeScript: [...lines2] } : {} };
|
|
706
675
|
}
|
|
707
|
-
var digests, REGISTRY, TOOL_VERSIONS,
|
|
676
|
+
var digests, REGISTRY, TOOL_VERSIONS, ENGINE_ROOT, DIGEST, PACK_DIR, RELEASE_LABEL_ARG, LABEL_REF, DOCKERFILE_HEADER, PLUGIN;
|
|
708
677
|
var init_images = __esm({
|
|
709
678
|
"src/images.ts"() {
|
|
710
679
|
"use strict";
|
|
@@ -717,17 +686,17 @@ var init_images = __esm({
|
|
|
717
686
|
/** A plunge release (INTENTIUS/plunge, tag plunge-v<ver>), not the Pulumi version it is built from. */
|
|
718
687
|
plunge: "0.2.0"
|
|
719
688
|
};
|
|
720
|
-
ARCHES = ["x64", "arm64"];
|
|
721
|
-
PINNED_SHA256 = {
|
|
722
|
-
"pulumi-v3.272.0-linux-x64.tar.gz": "58d545f2b98761051922008ebd381ecef95484d7f7a5ff7faa15d7a780ea84f6",
|
|
723
|
-
"pulumi-v3.272.0-linux-arm64.tar.gz": "4f0741901b8982c4326b702dabf483c63d2cf77c88ac42dd752b72541284a534",
|
|
724
|
-
"plunge-v0.2.0-linux-x64.tar.gz": "c9c73d05cca9ad214b7f44230a6162cdcb6ad64bbfc725bc94688b997b191495",
|
|
725
|
-
"plunge-v0.2.0-linux-arm64.tar.gz": "c176a82f038164085aa19c8ad6530d6022e560e124050e535dbe364ae0473357"
|
|
726
|
-
};
|
|
727
689
|
ENGINE_ROOT = "/opt/plywood";
|
|
728
690
|
DIGEST = /@sha256:[0-9a-f]{64}$/;
|
|
691
|
+
PACK_DIR = "images/pack";
|
|
729
692
|
RELEASE_LABEL_ARG = "CHANT_RELEASE_LABEL";
|
|
730
693
|
LABEL_REF = `\${${RELEASE_LABEL_ARG}}`;
|
|
694
|
+
DOCKERFILE_HEADER = [
|
|
695
|
+
"Rendered from packages/plywood/src/images.ts by packages/plywood/scripts/build-images.mjs.",
|
|
696
|
+
"Edit the module, then run npm run images -w @intentius/plywood. Build from the repository root",
|
|
697
|
+
`after npm pack -w @intentius/plywood --pack-destination ${PACK_DIR}, with --build-arg ${RELEASE_LABEL_ARG}=<the packed version>`,
|
|
698
|
+
"(just images passes the committed one; a release passes its label); nothing pushes it."
|
|
699
|
+
];
|
|
731
700
|
PLUGIN = /^(?:(resource|converter|language|analyzer|tool):)?([a-z0-9][a-z0-9-]*)@(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/;
|
|
732
701
|
}
|
|
733
702
|
});
|
|
@@ -2666,8 +2635,9 @@ var init_agent_jobs = __esm({
|
|
|
2666
2635
|
|
|
2667
2636
|
// src/drift-notify.ts
|
|
2668
2637
|
import { createHash } from "node:crypto";
|
|
2669
|
-
|
|
2670
|
-
|
|
2638
|
+
import { driftIssueFingerprint } from "@intentius/chant/drift-issue";
|
|
2639
|
+
function runFingerprint(results) {
|
|
2640
|
+
const parts = results.filter((r) => r.ok && r.drifted > 0).map((r) => `${r.stack} ${driftIssueFingerprint(r.records)}`).sort();
|
|
2671
2641
|
return createHash("sha256").update(parts.join("\n")).digest("hex").slice(0, 16);
|
|
2672
2642
|
}
|
|
2673
2643
|
function notifiesDrift(notify2) {
|
|
@@ -2677,7 +2647,7 @@ async function sendDriftNotice(input) {
|
|
|
2677
2647
|
if (!notifiesDrift(input.notify)) return void 0;
|
|
2678
2648
|
const drifted = input.results.filter((r) => r.ok && r.drifted > 0);
|
|
2679
2649
|
if (drifted.length === 0) return void 0;
|
|
2680
|
-
const fingerprint = runFingerprint(input.results
|
|
2650
|
+
const fingerprint = runFingerprint(input.results);
|
|
2681
2651
|
if (drifted.every((r) => r.issue?.action === "unchanged")) {
|
|
2682
2652
|
return { sent: false, reason: "no drift event was sent: every drifted stack's finding is the one its issue already holds", fingerprint };
|
|
2683
2653
|
}
|
|
@@ -3589,26 +3559,23 @@ var init_up = __esm({
|
|
|
3589
3559
|
});
|
|
3590
3560
|
|
|
3591
3561
|
// src/drift.ts
|
|
3592
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
3593
3562
|
import { resolveTargetCloudIdentity } from "@intentius/chant/ci-identity";
|
|
3563
|
+
import { ForgeFlagError, forgeTargetOptionsFromFlags, forgeTargetWith } from "@intentius/chant/forge-flags";
|
|
3564
|
+
import { forgeClient } from "@intentius/chant/pr-forge";
|
|
3565
|
+
import { keepDriftIssue } from "@intentius/chant/drift-issue";
|
|
3594
3566
|
import { existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync, readdirSync as readdirSync4, readFileSync as readFileSync8, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
3595
3567
|
import { tmpdir } from "node:os";
|
|
3596
3568
|
import { dirname as dirname6, join as join7 } from "node:path";
|
|
3597
3569
|
function driftRows(doc) {
|
|
3598
3570
|
return (doc.records ?? []).filter((r) => DRIFT_STATUSES.includes(r.status)).map((r) => ({ urn: r.address, status: r.status, attributes: (r.attributes ?? []).map((a) => a.path).sort() })).sort((a, b) => a.urn < b.urn ? -1 : a.urn > b.urn ? 1 : 0);
|
|
3599
3571
|
}
|
|
3600
|
-
function driftFingerprint(rows) {
|
|
3601
|
-
const text = rows.map((r) => `${r.urn} ${r.status} ${r.attributes.join(",")}`).join("\n");
|
|
3602
|
-
return createHash2("sha256").update(text).digest("hex").slice(0, 16);
|
|
3603
|
-
}
|
|
3604
3572
|
function observedAt(doc) {
|
|
3605
3573
|
const times = (doc.records ?? []).map((r) => r.observedAt).filter((t) => typeof t === "string").sort();
|
|
3606
3574
|
return times[times.length - 1] ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
3607
3575
|
}
|
|
3608
3576
|
async function forgeFor(kind, env) {
|
|
3609
3577
|
if (forgeOverride) return forgeOverride(kind, env);
|
|
3610
|
-
|
|
3611
|
-
return m.forgeClient(m.forgeTargetFromEnv(env, { kind }));
|
|
3578
|
+
return forgeClient(forgeTargetWith(env, { kind }));
|
|
3612
3579
|
}
|
|
3613
3580
|
function wavesHolding(doc, stacks2) {
|
|
3614
3581
|
if (!Array.isArray(doc.waves)) return "all";
|
|
@@ -3626,7 +3593,13 @@ async function drift2(args, json, table, io) {
|
|
|
3626
3593
|
}
|
|
3627
3594
|
const unknown = stackFlag.rest.filter((a) => a.startsWith("-"));
|
|
3628
3595
|
if (unknown.length) return usage(`drift does not take ${unknown.join(" ")}`, table, io);
|
|
3629
|
-
|
|
3596
|
+
let forge;
|
|
3597
|
+
try {
|
|
3598
|
+
forge = forgeTargetOptionsFromFlags({ forge: forgeFlag.value }).kind;
|
|
3599
|
+
} catch (e) {
|
|
3600
|
+
if (e instanceof ForgeFlagError) return usage(e.message, table, io);
|
|
3601
|
+
throw e;
|
|
3602
|
+
}
|
|
3630
3603
|
if (respondFlag.value !== void 0 && !DRIFT_RESPONSES.includes(respondFlag.value)) return usage(`--respond takes one of ${DRIFT_RESPONSES.join(", ")}`, table, io);
|
|
3631
3604
|
const path = findConfig(io.cwd);
|
|
3632
3605
|
if (!path) return usage(`no plywood.yml in ${io.cwd} or above it; run '${PRODUCT} init' first`, table, io);
|
|
@@ -3650,7 +3623,6 @@ async function drift2(args, json, table, io) {
|
|
|
3650
3623
|
if (strangers.length) return usage(`${strangers.join(", ")} ${strangers.length === 1 ? "is" : "are"} not under stacks in ${path}`, table, io);
|
|
3651
3624
|
if (resource.value !== void 0 && stacks2.length !== 1) return usage("--resource reads one resource of one stack; name the stack", table, io);
|
|
3652
3625
|
const respond = respondFlag.value ?? driftResponseOf(doc);
|
|
3653
|
-
const forge = forgeFlag.value;
|
|
3654
3626
|
return withChant(`${PRODUCT} drift`, table, io, async (chant) => {
|
|
3655
3627
|
const dir = mkdtempSync(join7(tmpdir(), "plywood-drift-"));
|
|
3656
3628
|
const results = [];
|
|
@@ -3703,7 +3675,7 @@ async function drift2(args, json, table, io) {
|
|
|
3703
3675
|
const failed = results.some((r) => !r.ok) || upkeepFailed;
|
|
3704
3676
|
const code = failed ? table.failed : upCode !== void 0 && upCode !== table.done ? upCode : drifted.length ? table.drift : table.done;
|
|
3705
3677
|
if (json) {
|
|
3706
|
-
io.out(JSON.stringify({ command: "drift", ok: code === table.done, exitCode: code, respond, stacks: results, ...notice ? { notify: notice } : {} }));
|
|
3678
|
+
io.out(JSON.stringify({ command: "drift", ok: code === table.done, exitCode: code, respond, stacks: results.map(({ records: _, ...r }) => r), ...notice ? { notify: notice } : {} }));
|
|
3707
3679
|
} else {
|
|
3708
3680
|
if (notice) io.err(`${PRODUCT} drift: ${notice.sent ? `sent the drift event, fingerprint ${notice.fingerprint}` : notice.reason}`);
|
|
3709
3681
|
for (const r of results) {
|
|
@@ -3725,7 +3697,6 @@ async function driftNotice(chant, doc, results, environment, io) {
|
|
|
3725
3697
|
return sendDriftNotice({
|
|
3726
3698
|
notify: notify2,
|
|
3727
3699
|
results,
|
|
3728
|
-
stackFingerprint: driftFingerprint,
|
|
3729
3700
|
chant: { ...await chantDriftNotify(), words: chant.assertProductWords(PRODUCT_WORDS) },
|
|
3730
3701
|
env: io.env,
|
|
3731
3702
|
...environment ? { environment } : {},
|
|
@@ -3759,20 +3730,21 @@ async function readStack(chant, stack, member, dir, opts) {
|
|
|
3759
3730
|
try {
|
|
3760
3731
|
if (existsSync7(file)) doc = JSON.parse(readFileSync8(file, "utf8"));
|
|
3761
3732
|
} catch (e) {
|
|
3762
|
-
return { stack, ok: false, drifted: 0, rows: [], error: `chant wrote a drift document plywood cannot read: ${e.message}` };
|
|
3733
|
+
return { stack, ok: false, drifted: 0, rows: [], records: [], error: `chant wrote a drift document plywood cannot read: ${e.message}` };
|
|
3763
3734
|
}
|
|
3764
3735
|
if (code !== 0 || !doc || doc.error) {
|
|
3765
|
-
return { stack, ok: false, drifted: 0, rows: [], error: doc?.error ? `${doc.error.code}: ${doc.error.message}` : `chant workspace drift exited ${code}` };
|
|
3736
|
+
return { stack, ok: false, drifted: 0, rows: [], records: [], error: doc?.error ? `${doc.error.code}: ${doc.error.message}` : `chant workspace drift exited ${code}` };
|
|
3766
3737
|
}
|
|
3767
3738
|
const rows = driftRows(doc);
|
|
3739
|
+
const records = (doc.records ?? []).map((r) => ({ ...r, member: r.member ?? member }));
|
|
3768
3740
|
const unread = (doc.records ?? []).filter((r) => r.status === "not-observed");
|
|
3769
3741
|
if (rows.length === 0 && unread.length > 0) {
|
|
3770
3742
|
const first = unread[0];
|
|
3771
3743
|
const why = first.unobserved?.detail ?? first.unobserved?.reason ?? "no reason given";
|
|
3772
|
-
return { stack, ok: false, drifted: 0, rows: [], error: `${unread.length} resource${unread.length === 1 ? "" : "s"} could not be read, so the stack's drift is unknown: ${first.address}: ${why}` };
|
|
3744
|
+
return { stack, ok: false, drifted: 0, rows: [], records: [], error: `${unread.length} resource${unread.length === 1 ? "" : "s"} could not be read, so the stack's drift is unknown: ${first.address}: ${why}` };
|
|
3773
3745
|
}
|
|
3774
3746
|
const attribution = rows.length && opts.attribute ? await attributeStack(opts.attribute, stack, doc) : void 0;
|
|
3775
|
-
return { stack, ok: true, drifted: rows.length, rows, observedAt: observedAt(doc), ...attribution ? { attribution } : {} };
|
|
3747
|
+
return { stack, ok: true, drifted: rows.length, rows, records, observedAt: observedAt(doc), ...attribution ? { attribution } : {} };
|
|
3776
3748
|
}
|
|
3777
3749
|
async function withBackend(backend, read) {
|
|
3778
3750
|
if (backend === void 0) return read();
|
|
@@ -3813,13 +3785,13 @@ function specHasUpdate(cwd, op) {
|
|
|
3813
3785
|
return false;
|
|
3814
3786
|
}
|
|
3815
3787
|
}
|
|
3788
|
+
function driftIssueNotes(attribution) {
|
|
3789
|
+
return attribution?.length ? [DRIFT_ATTRIBUTION_HEADING, "", ...attribution] : void 0;
|
|
3790
|
+
}
|
|
3816
3791
|
async function keepIssue(client, r, respond) {
|
|
3817
|
-
const
|
|
3818
|
-
const
|
|
3819
|
-
|
|
3820
|
-
const fingerprint = driftFingerprint(r.rows);
|
|
3821
|
-
const body = driftIssueBody({ stack: r.stack, rows: r.rows, observedAt: at, fingerprint, ...client.runUrl ? { runUrl: client.runUrl } : {}, respond, ...r.attribution?.length ? { attribution: r.attribution } : {} });
|
|
3822
|
-
return client.trackIssue(marker, { title: driftIssueTitle(r.stack), body }, { sameWhen: fingerprint });
|
|
3792
|
+
const notes = driftIssueNotes(r.attribution);
|
|
3793
|
+
const kept = await keepDriftIssue(client, { words: driftIssueWords(r.stack, respond), environment: r.stack, records: r.records, ...client.runUrl ? { runUrl: client.runUrl } : {}, ...notes ? { notes } : {} });
|
|
3794
|
+
return { action: kept.action, ...kept.number !== void 0 ? { number: kept.number } : {}, ...kept.url ? { url: kept.url } : {} };
|
|
3823
3795
|
}
|
|
3824
3796
|
function driftOpFile(doc, stacks2, schedule) {
|
|
3825
3797
|
const listed = stacksOf(doc);
|
|
@@ -3923,7 +3895,6 @@ var init_drift2 = __esm({
|
|
|
3923
3895
|
init_stacks();
|
|
3924
3896
|
init_detect();
|
|
3925
3897
|
init_render();
|
|
3926
|
-
init_routing();
|
|
3927
3898
|
init_images();
|
|
3928
3899
|
init_stages();
|
|
3929
3900
|
init_up();
|
|
@@ -4533,14 +4504,12 @@ function chantReferenceReader() {
|
|
|
4533
4504
|
}
|
|
4534
4505
|
async function exportOf(reader, root, s) {
|
|
4535
4506
|
const dir = join9(root, s.dir);
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
} catch {
|
|
4541
|
-
}
|
|
4507
|
+
try {
|
|
4508
|
+
const found = await reader.memberExportOf(dir, { stack: s.stack });
|
|
4509
|
+
if (found !== void 0) return found;
|
|
4510
|
+
} catch {
|
|
4542
4511
|
}
|
|
4543
|
-
return reader.readMemberExport
|
|
4512
|
+
return reader.readMemberExport(dir);
|
|
4544
4513
|
}
|
|
4545
4514
|
async function stackOrder(root, stacks2, after = {}) {
|
|
4546
4515
|
const edges = [];
|
|
@@ -5647,9 +5616,7 @@ __export(control_exports, {
|
|
|
5647
5616
|
wavesControl: () => wavesControl
|
|
5648
5617
|
});
|
|
5649
5618
|
import { existsSync as existsSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "node:fs";
|
|
5650
|
-
import { createRequire } from "node:module";
|
|
5651
5619
|
import { dirname as dirname10, join as join14 } from "node:path";
|
|
5652
|
-
import { pathToFileURL } from "node:url";
|
|
5653
5620
|
import { emitYAMLEntry as emitYAMLEntry3, parseYAML as parseYAML4 } from "@intentius/chant/yaml";
|
|
5654
5621
|
async function wavesControl(cwd) {
|
|
5655
5622
|
const file = findConfig(cwd);
|
|
@@ -5744,14 +5711,14 @@ async function control2(args, json, table, io) {
|
|
|
5744
5711
|
return table.failed;
|
|
5745
5712
|
}
|
|
5746
5713
|
}
|
|
5747
|
-
async function forgeControlPipeline(
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5714
|
+
async function forgeControlPipeline(forge) {
|
|
5715
|
+
switch (forge) {
|
|
5716
|
+
case "github":
|
|
5717
|
+
return (await import("@intentius/chant-lexicon-github/components/control-pipeline")).generateControlPipeline;
|
|
5718
|
+
case "gitlab":
|
|
5719
|
+
return (await import("@intentius/chant-lexicon-gitlab/components/control-pipeline")).generateControlPipeline;
|
|
5720
|
+
case "forgejo":
|
|
5721
|
+
return (await import("@intentius/chant-lexicon-forgejo/components/control-pipeline")).generateControlPipeline;
|
|
5755
5722
|
}
|
|
5756
5723
|
}
|
|
5757
5724
|
async function controlInit(chant, args, emit, table, io) {
|
|
@@ -5762,10 +5729,7 @@ async function controlInit(chant, args, emit, table, io) {
|
|
|
5762
5729
|
const dryRun = forgeFlag.rest.includes("--dry-run");
|
|
5763
5730
|
const forge = forgeFlag.value ?? "github";
|
|
5764
5731
|
if (!FORGES.includes(forge)) return usage(`--forge ${forge} is not one of ${FORGES.join(", ")}`, table, io);
|
|
5765
|
-
const generate = await forgeControlPipeline(
|
|
5766
|
-
if (!generate) {
|
|
5767
|
-
return usage(`control init writes the control repo's workflow with @intentius/chant-lexicon-${forge}'s generateControlPipeline (chant#4568); install it in the control repo at the chant release that has it`, table, io);
|
|
5768
|
-
}
|
|
5732
|
+
const generate = await forgeControlPipeline(forge);
|
|
5769
5733
|
const file = generate({ words: PRODUCT_WORDS });
|
|
5770
5734
|
const path = join14(io.cwd, file.path);
|
|
5771
5735
|
const before = existsSync11(path) ? readFileSync13(path, "utf8") : void 0;
|
|
@@ -6168,7 +6132,9 @@ function workflowPlan(chant, doc, forge, env, waves, extra = [], opts = {}) {
|
|
|
6168
6132
|
staleNotes: true,
|
|
6169
6133
|
...respond.options,
|
|
6170
6134
|
...applyMerge ? { applyMerge } : {},
|
|
6171
|
-
...actionJob ? { actionJob: true } : {}
|
|
6135
|
+
...actionJob ? { actionJob: true } : {},
|
|
6136
|
+
// chant#4785: GitLab starts no pipeline on a note, so a scheduled note-commands job answers the comments.
|
|
6137
|
+
...forge === "gitlab" ? { noteCommands: true } : {}
|
|
6172
6138
|
});
|
|
6173
6139
|
const prWords = shape.applyBeforeMerge ? words : wordsForJobs(jobsWanted.filter((j) => j !== "apply"));
|
|
6174
6140
|
const argv = [
|
|
@@ -6188,6 +6154,7 @@ function workflowPlan(chant, doc, forge, env, waves, extra = [], opts = {}) {
|
|
|
6188
6154
|
"--preview-comment",
|
|
6189
6155
|
"--stale-notes",
|
|
6190
6156
|
...actionJob ? ["--action-job"] : [],
|
|
6157
|
+
...forge === "gitlab" ? ["--note-commands"] : [],
|
|
6191
6158
|
// Review stacks (plywood#15): chant's pr-env jobs.
|
|
6192
6159
|
...doc.review_stacks !== void 0 ? ["--pr-env"] : [],
|
|
6193
6160
|
...opts.prJobs?.flags ?? [],
|
|
@@ -6264,7 +6231,7 @@ var init_stages = __esm({
|
|
|
6264
6231
|
forgejo: ".forgejo/workflows/plywood.yml",
|
|
6265
6232
|
gitlab: ".gitlab-ci.yml"
|
|
6266
6233
|
};
|
|
6267
|
-
ACTIONS_NOT_ON_GITLAB = "plywood.yml declares actions, and
|
|
6234
|
+
ACTIONS_NOT_ON_GITLAB = "plywood.yml declares actions, and chant's GitLab pipeline has no action job: GitLab has no dispatch with inputs, and the note-commands job answers no /plywood action; run 'plywood action <stack> <name>' from a pipeline of your own";
|
|
6268
6235
|
CHANT_RESPOND_DEFAULTS = Object.freeze({ "wave-refused": "diff", "apply-failed": "triage", description: "off" });
|
|
6269
6236
|
DECIDE_LEFT_OFF = "decide is set and respond.description is not check, so plywood leaves the decide service off the pull request jobs";
|
|
6270
6237
|
}
|
|
@@ -6272,32 +6239,7 @@ var init_stages = __esm({
|
|
|
6272
6239
|
|
|
6273
6240
|
// src/bin.ts
|
|
6274
6241
|
init_define_PLYWOOD_IMAGE_DIGESTS();
|
|
6275
|
-
|
|
6276
|
-
// src/chant-resolve.ts
|
|
6277
|
-
init_define_PLYWOOD_IMAGE_DIGESTS();
|
|
6278
|
-
import * as nodeModule from "node:module";
|
|
6279
|
-
var CHANT_SPECIFIER = /^@intentius\/chant(?:-lexicon-[a-z0-9-]+)?(?:\/|$)/;
|
|
6280
|
-
function chantResolveHook(from) {
|
|
6281
|
-
return (specifier, context, next) => {
|
|
6282
|
-
try {
|
|
6283
|
-
return next(specifier, context);
|
|
6284
|
-
} catch (err) {
|
|
6285
|
-
const code = err.code;
|
|
6286
|
-
if (!CHANT_SPECIFIER.test(specifier) || code !== "ERR_MODULE_NOT_FOUND" && code !== "MODULE_NOT_FOUND") throw err;
|
|
6287
|
-
if (context.parentURL === from) throw err;
|
|
6288
|
-
return next(specifier, { ...context, parentURL: from });
|
|
6289
|
-
}
|
|
6290
|
-
};
|
|
6291
|
-
}
|
|
6292
|
-
var installed = false;
|
|
6293
|
-
function installChantResolution(from = import.meta.url) {
|
|
6294
|
-
if (installed) return true;
|
|
6295
|
-
const register = nodeModule.registerHooks;
|
|
6296
|
-
if (typeof register !== "function") return false;
|
|
6297
|
-
register({ resolve: chantResolveHook(from) });
|
|
6298
|
-
installed = true;
|
|
6299
|
-
return true;
|
|
6300
|
-
}
|
|
6242
|
+
import { installChantResolveFallback } from "@intentius/chant/chant-install";
|
|
6301
6243
|
|
|
6302
6244
|
// src/cli.ts
|
|
6303
6245
|
init_define_PLYWOOD_IMAGE_DIGESTS();
|
|
@@ -6349,7 +6291,7 @@ async function lockToCancel(given, stack, env) {
|
|
|
6349
6291
|
}
|
|
6350
6292
|
var cachedOps;
|
|
6351
6293
|
function chantStackOps() {
|
|
6352
|
-
cachedOps ??= import("@intentius/chant-lexicon-pulumi")
|
|
6294
|
+
cachedOps ??= import("@intentius/chant-lexicon-pulumi");
|
|
6353
6295
|
return cachedOps;
|
|
6354
6296
|
}
|
|
6355
6297
|
function readConfig(cwd) {
|
|
@@ -6424,7 +6366,7 @@ function reportOutcome(verb, outcome, gate, rules, done, json, table, io) {
|
|
|
6424
6366
|
text = done(outcome.result);
|
|
6425
6367
|
break;
|
|
6426
6368
|
case "failed":
|
|
6427
|
-
code = table.failed;
|
|
6369
|
+
code = outcome.check === "moved" ? table.moved : table.failed;
|
|
6428
6370
|
text = `${PRODUCT} ${verb}: ${outcome.error}`;
|
|
6429
6371
|
break;
|
|
6430
6372
|
}
|
|
@@ -6439,7 +6381,7 @@ function reportOutcome(verb, outcome, gate, rules, done, json, table, io) {
|
|
|
6439
6381
|
digest: outcome.digest,
|
|
6440
6382
|
...approveLine ? { approve: approveLine } : {},
|
|
6441
6383
|
...outcome.status === "done" ? { result: outcome.result } : {},
|
|
6442
|
-
...outcome.status === "failed" ? { error: outcome.error } : {},
|
|
6384
|
+
...outcome.status === "failed" ? { error: outcome.error, ...outcome.check ? { check: outcome.check } : {} } : {},
|
|
6443
6385
|
...outcome.status === "refused" ? { refusedBy: outcome.by, reason: outcome.reason } : {}
|
|
6444
6386
|
}));
|
|
6445
6387
|
} else (code === table.done ? io.out : io.err)(text);
|
|
@@ -6451,9 +6393,11 @@ async function runRequest(verb, json, table, io, call) {
|
|
|
6451
6393
|
return await call(ops);
|
|
6452
6394
|
} catch (e) {
|
|
6453
6395
|
const message = e.message;
|
|
6454
|
-
|
|
6396
|
+
const refusal = e instanceof ops.PulumiStackOpRefused ? e.code : void 0;
|
|
6397
|
+
const code = refusal === "live-run" || refusal === "held" ? table.held : table.failed;
|
|
6398
|
+
if (json) io.out(JSON.stringify({ command: verb, ok: false, exitCode: code, error: message, ...refusal ? { refusal } : {} }));
|
|
6455
6399
|
else io.err(`${PRODUCT} ${verb}: ${message}`);
|
|
6456
|
-
return
|
|
6400
|
+
return code;
|
|
6457
6401
|
}
|
|
6458
6402
|
}
|
|
6459
6403
|
function commonFlags(args) {
|
|
@@ -6468,9 +6412,11 @@ async function exportStack(args, json, table, io) {
|
|
|
6468
6412
|
if (common.missing) return usage(`${common.missing} takes a value`, table, io);
|
|
6469
6413
|
const out = takeFlag(common.rest, "--out");
|
|
6470
6414
|
if (out.missing) return usage("--out takes a file path outside the repository", table, io);
|
|
6471
|
-
const
|
|
6415
|
+
const version2 = takeFlag(out.rest, "--version");
|
|
6416
|
+
if (version2.missing) return usage("--version takes the update number, or the sha256: digest of an export, that the stack holds now", table, io);
|
|
6417
|
+
const extra = version2.rest.filter((a) => a.startsWith("-"));
|
|
6472
6418
|
if (extra.length) return usage(`export does not take ${extra.join(" ")}`, table, io);
|
|
6473
|
-
const named = positionals(
|
|
6419
|
+
const named = positionals(version2.rest);
|
|
6474
6420
|
if (named.length !== 1) return usage(`export takes one stack: ${STACK_OP_WORDS.usage.export}`, table, io);
|
|
6475
6421
|
if (!out.value) return usage(`export needs --out <file>, a path on your machine outside every git working tree: ${STACK_OP_WORDS.usage.export}`, table, io);
|
|
6476
6422
|
const read = readConfig(io.cwd);
|
|
@@ -6490,11 +6436,19 @@ async function exportStack(args, json, table, io) {
|
|
|
6490
6436
|
dir: stack.dir,
|
|
6491
6437
|
stack: stack.stack,
|
|
6492
6438
|
out: outFile,
|
|
6439
|
+
...version2.value ? { version: version2.value } : {},
|
|
6493
6440
|
...stack.engine ? { engine: stack.engine } : {}
|
|
6494
6441
|
});
|
|
6495
6442
|
return reportOutcome("export", outcome, stack.stack, rules, (r) => STACK_OP_WORDS.exported(stack.key, r), json, table, io);
|
|
6496
6443
|
});
|
|
6497
6444
|
}
|
|
6445
|
+
function cancelForge(config2, root) {
|
|
6446
|
+
const f = toChantSettings(config2).pipeline.forge;
|
|
6447
|
+
const detected = f?.kind ? void 0 : detectForge(root);
|
|
6448
|
+
const kind = f?.kind ?? detected?.kind;
|
|
6449
|
+
const url = f?.url ?? detected?.url;
|
|
6450
|
+
return { ...kind ? { kind } : {}, ...url ? { url } : {} };
|
|
6451
|
+
}
|
|
6498
6452
|
async function cancelStack(args, json, table, io) {
|
|
6499
6453
|
const common = commonFlags(args);
|
|
6500
6454
|
if (common.missing) return usage(`${common.missing} takes a value`, table, io);
|
|
@@ -6524,7 +6478,8 @@ async function cancelStack(args, json, table, io) {
|
|
|
6524
6478
|
stack: stack.stack,
|
|
6525
6479
|
lockId: lockId.lockId,
|
|
6526
6480
|
project: stack.project,
|
|
6527
|
-
...stack.engine ? { engine: stack.engine } : {}
|
|
6481
|
+
...stack.engine ? { engine: stack.engine } : {},
|
|
6482
|
+
forge: cancelForge(read.config, dirname11(read.path))
|
|
6528
6483
|
});
|
|
6529
6484
|
return reportOutcome("cancel", outcome, stack.stack, rules, (r) => STACK_OP_WORDS.cancelled(stack.key, lockId.lockId, r.lockChecked), json, table, io);
|
|
6530
6485
|
});
|
|
@@ -6596,11 +6551,11 @@ async function moveOntoPlunge(engine3, args, json, table, io) {
|
|
|
6596
6551
|
});
|
|
6597
6552
|
}
|
|
6598
6553
|
async function rollbackStack(args, json, table, io) {
|
|
6599
|
-
const
|
|
6600
|
-
const env = takeFlag(
|
|
6554
|
+
const release = takeFlag(args, "--release");
|
|
6555
|
+
const env = takeFlag(release.rest, "--env");
|
|
6601
6556
|
const digest = takeFlag(env.rest, "--digest");
|
|
6602
6557
|
const actor = takeFlag(digest.rest, "--actor");
|
|
6603
|
-
for (const [flag, f] of [["--release",
|
|
6558
|
+
for (const [flag, f] of [["--release", release], ["--env", env], ["--digest", digest], ["--actor", actor]]) {
|
|
6604
6559
|
if (f.missing) return usage(`${flag} takes a value`, table, io);
|
|
6605
6560
|
}
|
|
6606
6561
|
const switches = actor.rest.filter((a) => a === "--dry-run" || a === "--events-json");
|
|
@@ -6610,11 +6565,11 @@ async function rollbackStack(args, json, table, io) {
|
|
|
6610
6565
|
const named = positionals(rest);
|
|
6611
6566
|
if (named.length > 1) return usage(`rollback takes one stack: ${STACK_OP_WORDS.usage.rollback}`, table, io);
|
|
6612
6567
|
let argv;
|
|
6613
|
-
if (
|
|
6568
|
+
if (release.value !== void 0) {
|
|
6614
6569
|
if (named.length) return usage(STACK_OP_WORDS.releaseIsEnvWide(named[0], environmentOf(named[0])), table, io);
|
|
6615
6570
|
if (digest.value !== void 0) return usage("--release takes no --digest: the release names what each stack goes back to", table, io);
|
|
6616
6571
|
if (!env.value) return usage(`rollback --release needs --env <env>, the environment whose stacks go back: ${STACK_OP_WORDS.usage.rollback}`, table, io);
|
|
6617
|
-
argv = ["components", "rollback", env.value, "--release",
|
|
6572
|
+
argv = ["components", "rollback", env.value, "--release", release.value];
|
|
6618
6573
|
} else {
|
|
6619
6574
|
if (named.length !== 1) return usage(`rollback takes a stack, or --release <name> --env <env>: ${STACK_OP_WORDS.usage.rollback}`, table, io);
|
|
6620
6575
|
const read = readConfig(io.cwd);
|
|
@@ -7259,11 +7214,11 @@ async function upgrade(args, json, table, io) {
|
|
|
7259
7214
|
const configFile = findConfig(io.cwd);
|
|
7260
7215
|
const configDir = configFile ? dirname14(configFile) : pkgDir;
|
|
7261
7216
|
const rel = (f) => relative2(io.cwd, f) || f;
|
|
7262
|
-
const
|
|
7263
|
-
if ("error" in
|
|
7264
|
-
const chant = opts.chant ??
|
|
7217
|
+
const release = await viewRelease(exec, pkgDir, io.env, opts.version);
|
|
7218
|
+
if ("error" in release) return fail(release.error);
|
|
7219
|
+
const chant = opts.chant ?? release.chant;
|
|
7265
7220
|
const pkgText = readFileSync16(pkgFile, "utf8");
|
|
7266
|
-
const pkgMove = movePackagePins(pkgText, rel(pkgFile),
|
|
7221
|
+
const pkgMove = movePackagePins(pkgText, rel(pkgFile), release.version, chant);
|
|
7267
7222
|
const declFile = join19(configDir, "chant.workspace.json");
|
|
7268
7223
|
const declText = existsSync15(declFile) ? readFileSync16(declFile, "utf8") : void 0;
|
|
7269
7224
|
let declMove;
|
|
@@ -7278,7 +7233,7 @@ async function upgrade(args, json, table, io) {
|
|
|
7278
7233
|
if (existsSync15(join19(configDir, "chant.workspace.jsonc"))) notes.push(`chant.workspace.jsonc is yours: move its @intentius/chant* pins to ${chant} by hand`);
|
|
7279
7234
|
if (configFile) {
|
|
7280
7235
|
try {
|
|
7281
|
-
const note = imageNote(loadConfig(configFile).doc,
|
|
7236
|
+
const note = imageNote(loadConfig(configFile).doc, release.version);
|
|
7282
7237
|
if (note) notes.push(note);
|
|
7283
7238
|
} catch {
|
|
7284
7239
|
}
|
|
@@ -7291,11 +7246,11 @@ async function upgrade(args, json, table, io) {
|
|
|
7291
7246
|
install: { cwd: rel(pkgDir) || ".", command: "npm install --no-audit --no-fund" },
|
|
7292
7247
|
ci: { cwd: rel(configDir) || ".", command: `npx ${ciArgs.join(" ")}` }
|
|
7293
7248
|
};
|
|
7294
|
-
const envelope = { command: "upgrade", plywood:
|
|
7249
|
+
const envelope = { command: "upgrade", plywood: release.version, chant, moves, notes, dryRun: opts.dryRun };
|
|
7295
7250
|
const say = (line) => {
|
|
7296
7251
|
if (!json) io.err(line);
|
|
7297
7252
|
};
|
|
7298
|
-
say(`${PRODUCT} upgrade: ${PLYWOOD_PACKAGE} ${
|
|
7253
|
+
say(`${PRODUCT} upgrade: ${PLYWOOD_PACKAGE} ${release.version}, ${CHANT_PACKAGE} ${chant}`);
|
|
7299
7254
|
for (const m of moves) say(` ${m.file} ${m.name} ${m.from} -> ${m.to}`);
|
|
7300
7255
|
if (moves.length === 0) say(" every pin is already there");
|
|
7301
7256
|
if (opts.dryRun) {
|
|
@@ -7314,14 +7269,14 @@ async function upgrade(args, json, table, io) {
|
|
|
7314
7269
|
return table.done;
|
|
7315
7270
|
}
|
|
7316
7271
|
say(` $ ${steps.install.command}`);
|
|
7317
|
-
const
|
|
7318
|
-
if (
|
|
7272
|
+
const installed = await exec("npm", ["install", "--no-audit", "--no-fund"], { cwd: pkgDir, env: io.env });
|
|
7273
|
+
if (installed.code !== 0) {
|
|
7319
7274
|
for (const n of notes) say(` note: ${n}`);
|
|
7320
|
-
return fail(`npm install failed (exit ${
|
|
7321
|
-
${
|
|
7275
|
+
return fail(`npm install failed (exit ${installed.code}); package.json is moved, so fix the install and run '${steps.ci.command}'
|
|
7276
|
+
${installed.stderr.trim()}`);
|
|
7322
7277
|
}
|
|
7323
7278
|
const got = installedVersion(pkgDir);
|
|
7324
|
-
if (got !== void 0 && got !==
|
|
7279
|
+
if (got !== void 0 && got !== release.version) notes.push(`node_modules holds ${PLYWOOD_PACKAGE} ${got}, not ${release.version}; check the install`);
|
|
7325
7280
|
let ci2;
|
|
7326
7281
|
if (configFile) {
|
|
7327
7282
|
say(` $ ${steps.ci.command}`);
|
|
@@ -7363,7 +7318,7 @@ var execChild = (bin, args, opts) => new Promise((done) => {
|
|
|
7363
7318
|
|
|
7364
7319
|
// src/cli.ts
|
|
7365
7320
|
init_words();
|
|
7366
|
-
var VERSION3 = true ? "0.3.
|
|
7321
|
+
var VERSION3 = true ? "0.3.8" : "0.0.0-dev";
|
|
7367
7322
|
var stdio = {
|
|
7368
7323
|
out: (s) => process.stdout.write(s + "\n"),
|
|
7369
7324
|
err: (s) => process.stderr.write(s + "\n")
|
|
@@ -7408,7 +7363,7 @@ function helpText() {
|
|
|
7408
7363
|
" override <stack> --rule <id>... --reason <text> override a policy denial, spent once its update runs",
|
|
7409
7364
|
"",
|
|
7410
7365
|
"Stack operations (each waits for a second person's approval):",
|
|
7411
|
-
" export <stack> --out <file>
|
|
7366
|
+
" export <stack> --out <file> [--version <v>] the stack's export, or one version of it, to a file on your machine",
|
|
7412
7367
|
" cancel <stack> [--lock <id>] release a stuck stack lock; on file:// it reads the id",
|
|
7413
7368
|
" move <urn>... --from <stack> --to <stack> move resources; both stacks preview no change",
|
|
7414
7369
|
" move <stack> --onto plunge adopt the stacks onto plunge (plywood.adopt.op.ts)",
|
|
@@ -7560,6 +7515,6 @@ function config(args, table, emit) {
|
|
|
7560
7515
|
}
|
|
7561
7516
|
|
|
7562
7517
|
// src/bin.ts
|
|
7563
|
-
|
|
7518
|
+
installChantResolveFallback(import.meta.url);
|
|
7564
7519
|
process.exitCode = await main(process.argv.slice(2));
|
|
7565
7520
|
//# sourceMappingURL=plywood.mjs.map
|