@stll/oxlint-config 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -11
- package/dist/cloud-setup-cli.cjs +1 -1
- package/dist/cloud-setup-cli.cjs.map +1 -1
- package/dist/cloud-setup-cli.mjs +2 -2
- package/dist/cloud-setup-cli.mjs.map +1 -1
- package/dist/toolchain-changed.cjs +6 -1
- package/dist/toolchain-changed.cjs.map +1 -1
- package/dist/toolchain-changed.mjs +6 -1
- package/dist/toolchain-changed.mjs.map +1 -1
- package/dist/toolchain-guard.cjs +10 -2
- package/dist/toolchain-guard.cjs.map +1 -1
- package/dist/toolchain-guard.mjs +11 -3
- package/dist/toolchain-guard.mjs.map +1 -1
- package/dist/toolchain-inputs.cjs +182 -57
- package/dist/toolchain-inputs.cjs.map +1 -1
- package/dist/toolchain-inputs.mjs +169 -56
- package/dist/toolchain-inputs.mjs.map +1 -1
- package/dist/toolchain-schema.mjs +1 -1
- package/package.json +1 -1
|
@@ -171,7 +171,7 @@ const postgresInstall = String.raw`
|
|
|
171
171
|
rm -- "$key"
|
|
172
172
|
printf '%s\n' '@PGDG_SOURCE@' > /etc/apt/sources.list.d/stll-pgdg.list
|
|
173
173
|
fi
|
|
174
|
-
|
|
174
|
+
apt_refresh_for postgresql-@POSTGRES@ postgresql-client-@POSTGRES@
|
|
175
175
|
apt_install postgresql-@POSTGRES@ postgresql-client-@POSTGRES@
|
|
176
176
|
fi
|
|
177
177
|
postgres_ready || fail 'PostgreSQL toolchain is incomplete or differs from the policy major'
|
|
@@ -194,7 +194,7 @@ const valkeyInstall = String.raw`
|
|
|
194
194
|
[[ "$(dpkg-deb -f "$scratch/$package.deb" Version)" == '@VALKEY@-1.noble' ]] || fail 'Valkey artifact version mismatch'
|
|
195
195
|
[[ "$(dpkg-deb -f "$scratch/$package.deb" Architecture)" == "$ARCH" ]] || fail 'Valkey artifact architecture mismatch'
|
|
196
196
|
done
|
|
197
|
-
|
|
197
|
+
apt_refresh_for "$scratch/valkey-server.deb" "$scratch/valkey-tools.deb"
|
|
198
198
|
apt_install "$scratch/valkey-server.deb" "$scratch/valkey-tools.deb"
|
|
199
199
|
rm -rf -- "$scratch"
|
|
200
200
|
fi
|
|
@@ -295,6 +295,15 @@ apt_network() {
|
|
|
295
295
|
[[ -n "$hosts" ]] || hosts='configured APT hosts'
|
|
296
296
|
network_run "$hosts" 180 apt-get -o Acquire::http::Timeout=20 -o Acquire::https::Timeout=20 -o Acquire::Retries=3 -o APT::Update::Error-Mode=any "$@"
|
|
297
297
|
}
|
|
298
|
+
apt_refresh_for() {
|
|
299
|
+
# Skip the refresh only when the install downloads nothing: then no package
|
|
300
|
+
# source is contacted and stale cached indexes cannot point at missing files.
|
|
301
|
+
local uris
|
|
302
|
+
if uris="$(DEBIAN_FRONTEND=noninteractive apt-get --print-uris -qq -y --no-install-recommends install "$@" 2>/dev/null)" && [[ -z "$uris" ]]; then
|
|
303
|
+
return 0
|
|
304
|
+
fi
|
|
305
|
+
apt_network update
|
|
306
|
+
}
|
|
298
307
|
`;
|
|
299
308
|
//#endregion
|
|
300
309
|
//#region src/cloud-setup-artifacts.ts
|
|
@@ -414,12 +423,29 @@ const getCloudSetupArtifact = (tool, version) => {
|
|
|
414
423
|
if (artifact === void 0) throw new Error(`Unsupported ${tool} version ${version}; supported versions: ${releases.map((release) => release.version).join(", ")}`);
|
|
415
424
|
return artifact;
|
|
416
425
|
};
|
|
426
|
+
/** Ubuntu 24.04 packages; apt resolves them from the image's configured sources. */
|
|
427
|
+
const cloudSetupPackages = { time: {
|
|
428
|
+
version: "1.9",
|
|
429
|
+
package: "time",
|
|
430
|
+
binary: "/usr/bin/time",
|
|
431
|
+
identity: "time (GNU Time) "
|
|
432
|
+
} };
|
|
433
|
+
/** Ubuntu 24.04 ships one release per package; other versions are unsupported. */
|
|
434
|
+
const getCloudSetupPackage = (tool, version) => {
|
|
435
|
+
const release = cloudSetupPackages[tool];
|
|
436
|
+
if (release.version !== version) throw new Error(`Unsupported ${tool} version ${version}; supported versions: ${release.version}`);
|
|
437
|
+
return release;
|
|
438
|
+
};
|
|
417
439
|
//#endregion
|
|
418
440
|
//#region src/cloud-setup-schema.ts
|
|
419
441
|
const cloudServices = ["postgres", "valkey"];
|
|
420
|
-
const
|
|
442
|
+
const cloudArtifactTools = Object.keys(cloudSetupArtifacts).filter((tool) => tool !== "rustup-init" && Object.hasOwn(cloudSetupArtifacts, tool));
|
|
443
|
+
const cloudPackageTools = Object.keys(cloudSetupPackages).filter((tool) => Object.hasOwn(cloudSetupPackages, tool));
|
|
444
|
+
const cloudExtraTools = [...cloudArtifactTools, ...cloudPackageTools];
|
|
445
|
+
const isCloudPackageTool = (tool) => cloudPackageTools.some((candidate) => candidate === tool);
|
|
421
446
|
const object = (input) => typeof input === "object" && input !== null && !Array.isArray(input);
|
|
422
447
|
const exactPin = (input) => typeof input === "string" && /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/.test(input);
|
|
448
|
+
const exactToolPin = (tool, input) => isCloudPackageTool(tool) ? typeof input === "string" && /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:\.(?:0|[1-9]\d*))?$/.test(input) : exactPin(input);
|
|
423
449
|
const cloudRustComponentBinaries = {
|
|
424
450
|
clippy: ["cargo-clippy", "clippy-driver"],
|
|
425
451
|
rustfmt: ["rustfmt", "cargo-fmt"],
|
|
@@ -463,12 +489,14 @@ const parseTools = (input) => {
|
|
|
463
489
|
if (Object.hasOwn(input, tool)) throw new Error(`cloud.tools.${tool} must be an exact stable release`);
|
|
464
490
|
continue;
|
|
465
491
|
}
|
|
466
|
-
if (!
|
|
492
|
+
if (!exactToolPin(tool, pin)) throw new Error(`cloud.tools.${tool} must be an exact stable release`);
|
|
467
493
|
result[tool] = pin;
|
|
468
494
|
}
|
|
469
495
|
return result;
|
|
470
496
|
};
|
|
471
497
|
const cloudInstallCommand = "bun install --frozen-lockfile";
|
|
498
|
+
const cloudInstallCommands = [cloudInstallCommand, `${cloudInstallCommand} --ignore-scripts`];
|
|
499
|
+
const cloudInstall = (value) => cloudInstallCommands.some((command) => value === command);
|
|
472
500
|
const cloudService = (value) => cloudServices.some((service) => value === service);
|
|
473
501
|
const parseEnvFile = (input) => {
|
|
474
502
|
if (!("envFile" in input) || typeof input.envFile !== "string") throw new Error("cloud.envFile must be a canonical repository-relative path");
|
|
@@ -489,7 +517,8 @@ const parseCloudSetup = (input) => {
|
|
|
489
517
|
};
|
|
490
518
|
const selected = "services" in input ? input.services : [];
|
|
491
519
|
if (!Array.isArray(selected)) throw new Error("cloud.services must be an array when provided");
|
|
492
|
-
if (!("install" in input) || input.install
|
|
520
|
+
if (!("install" in input) || !cloudInstall(input.install)) throw new Error(`cloud.install must be exactly one of: ${cloudInstallCommands.join(", ")}`);
|
|
521
|
+
const install = input.install;
|
|
493
522
|
const seen = /* @__PURE__ */ new Set();
|
|
494
523
|
const services = Array.from(selected, (service) => {
|
|
495
524
|
if (!cloudService(service)) throw new Error("cloud.services contains an unsupported service");
|
|
@@ -500,7 +529,7 @@ const parseCloudSetup = (input) => {
|
|
|
500
529
|
if (services.length === 0 && "envFile" in input) throw new Error("cloud.envFile is not allowed without services");
|
|
501
530
|
return {
|
|
502
531
|
services,
|
|
503
|
-
install
|
|
532
|
+
install,
|
|
504
533
|
...extensions,
|
|
505
534
|
...services.length === 0 ? {} : { envFile: parseEnvFile(input) }
|
|
506
535
|
};
|
|
@@ -762,9 +791,12 @@ const resolveCloudToolchains = ({ cloud, files, rust, rustExceptions }) => {
|
|
|
762
791
|
}
|
|
763
792
|
const components = [.../* @__PURE__ */ new Set([...parseCloudRustNames(declared?.["components"], "components"), ...cloud.rust?.components ?? []])].sort();
|
|
764
793
|
const targets = [.../* @__PURE__ */ new Set([...parseCloudRustNames(declared?.["targets"], "targets"), ...cloud.rust?.targets ?? []])].sort();
|
|
765
|
-
const
|
|
766
|
-
|
|
767
|
-
|
|
794
|
+
const resolveTool = (tool, version) => {
|
|
795
|
+
if (isCloudPackageTool(tool)) return {
|
|
796
|
+
type: "package",
|
|
797
|
+
tool,
|
|
798
|
+
release: getCloudSetupPackage(tool, version)
|
|
799
|
+
};
|
|
768
800
|
if (tool === "cargo-nextest" && !rustEnabled) throw new Error("cloud.tools.cargo-nextest requires a Rust toolchain");
|
|
769
801
|
if (tool === "wasm-bindgen-cli") {
|
|
770
802
|
const lock = files["Cargo.lock"];
|
|
@@ -774,10 +806,15 @@ const resolveCloudToolchains = ({ cloud, files, rust, rustExceptions }) => {
|
|
|
774
806
|
const versions = new Set(packages.flatMap((entry) => record$2(entry) && entry["name"] === "wasm-bindgen" ? [entry["version"]] : []));
|
|
775
807
|
if (versions.size !== 1 || !versions.has(version)) throw new Error(`cloud.tools.wasm-bindgen-cli ${version} must equal the unique wasm-bindgen crate version in Cargo.lock (found ${[...versions].join(", ") || "none"})`);
|
|
776
808
|
}
|
|
777
|
-
return
|
|
809
|
+
return {
|
|
810
|
+
type: "artifact",
|
|
778
811
|
tool,
|
|
779
812
|
release: getCloudSetupArtifact(tool, version)
|
|
780
|
-
}
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
const tools = cloudExtraTools.flatMap((tool) => {
|
|
816
|
+
const version = cloud.tools?.[tool];
|
|
817
|
+
return version === void 0 ? [] : [resolveTool(tool, version)];
|
|
781
818
|
});
|
|
782
819
|
return {
|
|
783
820
|
rust: rustEnabled && typeof channel === "string" ? {
|
|
@@ -835,7 +872,7 @@ rust_ready() {
|
|
|
835
872
|
verify_rust() { rust_ready || fail 'Pinned Rust, components or targets are unavailable; run install'; }
|
|
836
873
|
install_rust() (
|
|
837
874
|
if ! command -v cc >/dev/null || ! command -v ld >/dev/null || [[ ! -f /usr/include/stdlib.h ]]; then
|
|
838
|
-
|
|
875
|
+
apt_refresh_for build-essential
|
|
839
876
|
apt_install build-essential
|
|
840
877
|
fi
|
|
841
878
|
local artifact_url artifact_sha
|
|
@@ -872,14 +909,31 @@ install_rust() (
|
|
|
872
909
|
)
|
|
873
910
|
`.replaceAll("@RUSTUP@", rust.installer.version).replaceAll("@RUST@", rust.channel).replace("@RUSTUP_ARTIFACT@", artifactSelection(rust.installer)).replace("@RUST_ARGS@", args).replace("@RUST_PROXIES@", Object.entries(cloudRustComponentBinaries).flatMap(([component, binaries]) => rust.components.includes(component) ? Array.from(binaries) : []).join(" ")).replace("@VERIFY_COMPONENTS@", rust.components.map((name) => `rust_run local "$CARGO_HOME/bin/rustup" component list --toolchain ${quote(rust.channel)} --installed | awk -v name=${quote(name)} -v host="$host" '$1 == name || $1 == name "-" host { found=1 } END { exit !found }' || return 1`).join("\n ")).replace("@VERIFY_TARGETS@", rust.targets.map((name) => `rust_run local "$CARGO_HOME/bin/rustup" target list --toolchain ${quote(rust.channel)} --installed | awk -v name=${quote(name)} '$1 == name { found=1 } END { exit !found }' || return 1`).join("\n "));
|
|
874
911
|
};
|
|
875
|
-
const
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
912
|
+
const packageToolInstall = ({ tool, release }) => {
|
|
913
|
+
const name = tool.replaceAll("-", "_");
|
|
914
|
+
return {
|
|
915
|
+
name,
|
|
916
|
+
text: `verify_${name}() {
|
|
917
|
+
[[ -x ${quote(release.binary)} && "$(${quote(release.binary)} --version 2>/dev/null)" == ${quote(release.identity)}* ]] || return 1
|
|
918
|
+
[[ "$(dpkg-query -W -f='\${Version}' ${quote(release.package)} 2>/dev/null)" == ${quote(`${release.version}-`)}* ]]
|
|
919
|
+
}
|
|
920
|
+
install_${name}() {
|
|
921
|
+
if ! verify_${name}; then
|
|
922
|
+
apt_network update
|
|
923
|
+
apt_install ${quote(release.package)}
|
|
924
|
+
verify_${name} || fail ${quote(`Installed ${tool} version differs from its pin`)}
|
|
925
|
+
fi
|
|
926
|
+
}
|
|
927
|
+
`
|
|
928
|
+
};
|
|
929
|
+
};
|
|
930
|
+
const artifactToolInstall = ({ tool, release }) => {
|
|
931
|
+
const directory = `/opt/stll-cloud/tools/${tool}/${release.version}`;
|
|
932
|
+
const command = tool === "wasm-bindgen-cli" ? "wasm-bindgen" : tool;
|
|
933
|
+
const marker = `${tool === "cargo-nextest" ? "cargo-nextest" : command} ${release.version}`;
|
|
934
|
+
return {
|
|
935
|
+
name: tool.replaceAll("-", "_"),
|
|
936
|
+
text: `verify_${tool.replaceAll("-", "_")}() {
|
|
883
937
|
${Object.keys(release.amd64.binaries).map((binary) => `[[ -x ${quote(`${directory}/${binary}`)} ]] || return 1`).join("\n ")}
|
|
884
938
|
[[ "$( ${quote(`${directory}/${command}`)} --version)" == ${quote(marker)} || "$( ${quote(`${directory}/${command}`)} --version)" == ${quote(`${marker} `)}* ]]
|
|
885
939
|
}
|
|
@@ -901,7 +955,15 @@ ${["amd64", "arm64"].map((arch) => ` ${arch})\n${Object.entries(release[arc
|
|
|
901
955
|
${Object.keys(release.amd64.binaries).map((binary) => ` ln -sfnT -- ${quote(`${directory}/${binary}`)} ${quote(`/usr/local/bin/${binary}`)}`).join("\n")}
|
|
902
956
|
)
|
|
903
957
|
`
|
|
904
|
-
|
|
958
|
+
};
|
|
959
|
+
};
|
|
960
|
+
const renderCloudToolInstall = ({ rust, tools }) => {
|
|
961
|
+
const installs = tools.map((entry) => {
|
|
962
|
+
switch (entry.type) {
|
|
963
|
+
case "package": return packageToolInstall(entry);
|
|
964
|
+
case "artifact": return artifactToolInstall(entry);
|
|
965
|
+
default: throw new Error(`Unsupported cloud tool: ${String(entry)}`);
|
|
966
|
+
}
|
|
905
967
|
});
|
|
906
968
|
return `${helpers}${rust === void 0 ? "" : rustInstall(rust)}\n${installs.map(({ text }) => text).join("\n")}
|
|
907
969
|
install_tools() {
|
|
@@ -952,6 +1014,14 @@ usage() { echo 'Usage: cloud-setup.sh install|start' >&2; exit 2; }
|
|
|
952
1014
|
case "$1" in install|start) MODE="$1" ;; *) usage ;; esac
|
|
953
1015
|
fail() { echo "cloud-setup: $*" >&2; exit 1; }
|
|
954
1016
|
trap 'echo "cloud-setup: command failed at line $LINENO" >&2' ERR
|
|
1017
|
+
# Each phase logs its start and duration so a stalled phase is visible in the task log.
|
|
1018
|
+
step() {
|
|
1019
|
+
local name="$1" started="$SECONDS"
|
|
1020
|
+
shift
|
|
1021
|
+
echo "cloud-setup: $name started" >&2
|
|
1022
|
+
"$@"
|
|
1023
|
+
echo "cloud-setup: $name done in $((SECONDS - started))s" >&2
|
|
1024
|
+
}
|
|
955
1025
|
[[ -f /etc/os-release ]] || fail 'Ubuntu 24.04 is required'
|
|
956
1026
|
. /etc/os-release
|
|
957
1027
|
[[ "$ID" == ubuntu && "$VERSION_ID" == 24.04 && "$VERSION_CODENAME" == noble ]] || fail 'Only Ubuntu 24.04 (noble) is supported'
|
|
@@ -995,7 +1065,7 @@ runtime_ready() {
|
|
|
995
1065
|
}
|
|
996
1066
|
install_runtimes() {
|
|
997
1067
|
if ! command -v curl >/dev/null || ! command -v unzip >/dev/null || ! command -v xz >/dev/null || ! command -v openssl >/dev/null || ! command -v gpg >/dev/null || ! ldconfig -p | awk '$1 == "libatomic.so.1" { found=1 } END { exit !found }'; then
|
|
998
|
-
|
|
1068
|
+
apt_refresh_for ca-certificates curl unzip xz-utils openssl gnupg util-linux libatomic1
|
|
999
1069
|
DEBIAN_FRONTEND=noninteractive apt_install ca-certificates curl unzip xz-utils openssl gnupg util-linux libatomic1
|
|
1000
1070
|
fi
|
|
1001
1071
|
local scratch node_archive bun_archive bun_folder
|
|
@@ -1061,7 +1131,7 @@ for (const input of inputs) {
|
|
|
1061
1131
|
process.stdout.write([...hosts].sort().join(","));
|
|
1062
1132
|
')"
|
|
1063
1133
|
# Bun 1.4.3 socket inactivity timeout, in seconds; the outer bound includes scripts.
|
|
1064
|
-
network_run "$download_hosts" 240 runuser -u "$OUTPUT_USER" -- env HOME="$OUTPUT_HOME" BUN_INSTALL_CACHE_DIR="$BUN_CACHE" PATH="$PATH" BUN_CONFIG_HTTP_IDLE_TIMEOUT=20 "$BUN_DIR/bun"
|
|
1134
|
+
network_run "$download_hosts" 240 runuser -u "$OUTPUT_USER" -- env HOME="$OUTPUT_HOME" BUN_INSTALL_CACHE_DIR="$BUN_CACHE" PATH="$PATH" BUN_CONFIG_HTTP_IDLE_TIMEOUT=20 "$BUN_DIR/bun" @INSTALL_ARGS@
|
|
1065
1135
|
}
|
|
1066
1136
|
|
|
1067
1137
|
@SERVICE_INSTALL@
|
|
@@ -1074,20 +1144,20 @@ process.stdout.write([...hosts].sort().join(","));
|
|
|
1074
1144
|
@ENV_FUNCTIONS@
|
|
1075
1145
|
|
|
1076
1146
|
if [[ "$MODE" == install ]]; then
|
|
1077
|
-
install_runtimes
|
|
1078
|
-
install_services
|
|
1079
|
-
install_tools
|
|
1080
|
-
install_shell_environment
|
|
1081
|
-
dependency_install
|
|
1147
|
+
step runtimes install_runtimes
|
|
1148
|
+
step services install_services
|
|
1149
|
+
step tools install_tools
|
|
1150
|
+
step shell install_shell_environment
|
|
1151
|
+
step dependencies dependency_install
|
|
1082
1152
|
exit 0
|
|
1083
1153
|
fi
|
|
1084
|
-
runtime_ready
|
|
1085
|
-
verify_tools
|
|
1086
|
-
install_shell_environment
|
|
1087
|
-
verify_shell_environment
|
|
1154
|
+
step runtime-check runtime_ready
|
|
1155
|
+
step tool-check verify_tools
|
|
1156
|
+
step shell install_shell_environment
|
|
1157
|
+
step shell-check verify_shell_environment
|
|
1088
1158
|
@ENV_VALIDATE@
|
|
1089
|
-
prepare_state
|
|
1090
|
-
start_services
|
|
1159
|
+
step state prepare_state
|
|
1160
|
+
step service-start start_services
|
|
1091
1161
|
@ENV_WRITE@
|
|
1092
1162
|
`;
|
|
1093
1163
|
const environmentFunctions = String.raw`
|
|
@@ -1132,6 +1202,7 @@ const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExcept
|
|
|
1132
1202
|
});
|
|
1133
1203
|
const services = cloudServices.filter((service) => selected.services.includes(service));
|
|
1134
1204
|
const replacements = /* @__PURE__ */ new Map([
|
|
1205
|
+
["@INSTALL_ARGS@", selected.install.replace(/^bun /, "")],
|
|
1135
1206
|
["@NETWORK@", renderCloudNetwork()],
|
|
1136
1207
|
["@TOOL_INSTALL@", renderCloudToolInstall(toolchains) + renderCloudShellInstall({
|
|
1137
1208
|
nodeVersion: exactNode,
|
|
@@ -1175,12 +1246,12 @@ const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExcept
|
|
|
1175
1246
|
//#endregion
|
|
1176
1247
|
//#region src/cloud-setup-claude.ts
|
|
1177
1248
|
const cloudClaudeSettingsPath = ".claude/settings.json";
|
|
1178
|
-
const
|
|
1249
|
+
const sessionStartHook = (script) => ({
|
|
1179
1250
|
matcher: "",
|
|
1180
1251
|
hooks: [{
|
|
1181
1252
|
type: "command",
|
|
1182
1253
|
command: `if [ "\${CLAUDE_CODE_REMOTE:-}" = "true" ]; then
|
|
1183
|
-
|
|
1254
|
+
${script} start || exit "$?"
|
|
1184
1255
|
if [ -n "\${CLAUDE_ENV_FILE:-}" ]; then
|
|
1185
1256
|
if [ ! -f ${cloudShellProfilePath} ]; then
|
|
1186
1257
|
printf '%s\\n' 'cloud-setup: cloud shell profile is unavailable; run install' >&2
|
|
@@ -1191,6 +1262,12 @@ const cloudSessionStartHook = {
|
|
|
1191
1262
|
fi
|
|
1192
1263
|
fi`
|
|
1193
1264
|
}]
|
|
1265
|
+
});
|
|
1266
|
+
const cloudSessionStartHook = sessionStartHook(`bash "$CLAUDE_PROJECT_DIR/${cloudSetupPath}"`);
|
|
1267
|
+
const previousCloudSessionStartHooks = [sessionStartHook(`bash ${cloudSetupPath}`)];
|
|
1268
|
+
const cloudAttribution = {
|
|
1269
|
+
commit: "",
|
|
1270
|
+
pr: ""
|
|
1194
1271
|
};
|
|
1195
1272
|
const record$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1196
1273
|
const array = (value) => Array.isArray(value);
|
|
@@ -1222,33 +1299,69 @@ const readSettings = (text) => {
|
|
|
1222
1299
|
};
|
|
1223
1300
|
const cloudHookGroups = (sessionStart) => sessionStart.filter((entry) => record$1(entry) && array(entry["hooks"]) && entry["hooks"].some((hook) => record$1(hook) && typeof hook["command"] === "string" && hook["command"].includes(".agents/cloud-setup.sh")));
|
|
1224
1301
|
const cloudSessionStartFix = `preserve unrelated settings in ${cloudClaudeSettingsPath}, repair its JSON/hooks structure and set disableAllHooks to false if needed, and ensure hooks.SessionStart contains exactly this cloud setup entry (replace conflicting cloud setup entries):\n` + JSON.stringify(cloudSessionStartHook, null, 2);
|
|
1225
|
-
|
|
1226
|
-
const
|
|
1302
|
+
const cloudAttributionFix = `preserve unrelated settings in ${cloudClaudeSettingsPath} and set its top-level attribution to exactly:\n` + JSON.stringify({ attribution: cloudAttribution }, null, 2);
|
|
1303
|
+
const sessionStartState = (sessionStart) => {
|
|
1304
|
+
const groups = cloudHookGroups(sessionStart);
|
|
1305
|
+
const group = groups.at(0);
|
|
1306
|
+
if (group === void 0) return { type: "missing" };
|
|
1307
|
+
if (groups.length === 1 && isDeepStrictEqual(group, cloudSessionStartHook)) return { type: "current" };
|
|
1308
|
+
if (groups.length === 1 && previousCloudSessionStartHooks.some((hook) => isDeepStrictEqual(group, hook))) return {
|
|
1309
|
+
type: "previous",
|
|
1310
|
+
group
|
|
1311
|
+
};
|
|
1312
|
+
return { type: "conflict" };
|
|
1313
|
+
};
|
|
1314
|
+
const attributionState = (settings) => {
|
|
1315
|
+
const attribution = settings["attribution"];
|
|
1316
|
+
if (attribution === void 0) return "missing";
|
|
1317
|
+
return isDeepStrictEqual(attribution, cloudAttribution) ? "current" : "conflict";
|
|
1318
|
+
};
|
|
1319
|
+
const mergeError = (reason, fix) => /* @__PURE__ */ new Error(`cannot safely merge ${cloudClaudeSettingsPath}: ${reason}; ${fix}`);
|
|
1320
|
+
const readMergeableSettings = (text) => {
|
|
1227
1321
|
try {
|
|
1228
|
-
|
|
1229
|
-
const cloudGroups = cloudHookGroups(sessionStart);
|
|
1230
|
-
if (cloudGroups.length !== 0) {
|
|
1231
|
-
if (cloudGroups.length === 1 && isDeepStrictEqual(cloudGroups.at(0), cloudSessionStartHook) && text !== void 0) return text;
|
|
1232
|
-
throw new Error("existing cloud setup SessionStart hook differs");
|
|
1233
|
-
}
|
|
1234
|
-
return `${JSON.stringify({
|
|
1235
|
-
...settings,
|
|
1236
|
-
hooks: {
|
|
1237
|
-
...hooks,
|
|
1238
|
-
SessionStart: [...sessionStart, cloudSessionStartHook]
|
|
1239
|
-
}
|
|
1240
|
-
}, null, 2)}\n`;
|
|
1322
|
+
return readSettings(text);
|
|
1241
1323
|
} catch (error) {
|
|
1242
|
-
throw
|
|
1324
|
+
throw mergeError(error instanceof Error ? error.message : String(error), cloudSessionStartFix);
|
|
1243
1325
|
}
|
|
1244
1326
|
};
|
|
1327
|
+
/** Add the cloud hook and attribution; never overwrite conflicting values. */
|
|
1328
|
+
const mergeCloudClaudeSettings = (text) => {
|
|
1329
|
+
const { settings, hooks, sessionStart } = readMergeableSettings(text);
|
|
1330
|
+
const hook = sessionStartState(sessionStart);
|
|
1331
|
+
if (hook.type === "conflict") throw mergeError("existing cloud setup SessionStart hook differs", cloudSessionStartFix);
|
|
1332
|
+
const attribution = attributionState(settings);
|
|
1333
|
+
if (attribution === "conflict") throw mergeError("existing attribution differs", cloudAttributionFix);
|
|
1334
|
+
if (hook.type === "current" && attribution === "current" && text !== void 0) return text;
|
|
1335
|
+
const mergedSessionStart = (() => {
|
|
1336
|
+
switch (hook.type) {
|
|
1337
|
+
case "current": return sessionStart;
|
|
1338
|
+
case "missing": return [...sessionStart, cloudSessionStartHook];
|
|
1339
|
+
case "previous": return sessionStart.map((entry) => entry === hook.group ? cloudSessionStartHook : entry);
|
|
1340
|
+
default: throw new Error(`Unsupported hook state: ${String(hook)}`);
|
|
1341
|
+
}
|
|
1342
|
+
})();
|
|
1343
|
+
return `${JSON.stringify({
|
|
1344
|
+
...settings,
|
|
1345
|
+
attribution: cloudAttribution,
|
|
1346
|
+
hooks: {
|
|
1347
|
+
...hooks,
|
|
1348
|
+
SessionStart: mergedSessionStart
|
|
1349
|
+
}
|
|
1350
|
+
}, null, 2)}\n`;
|
|
1351
|
+
};
|
|
1245
1352
|
/** Settings formatting and unrelated hooks do not affect the generated contract. */
|
|
1246
1353
|
const hasCloudSessionStartHook = (text) => {
|
|
1247
1354
|
if (text === void 0) return false;
|
|
1248
1355
|
try {
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
return
|
|
1356
|
+
return sessionStartState(readSettings(text).sessionStart).type === "current";
|
|
1357
|
+
} catch {
|
|
1358
|
+
return false;
|
|
1359
|
+
}
|
|
1360
|
+
};
|
|
1361
|
+
const hasCloudAttribution = (text) => {
|
|
1362
|
+
if (text === void 0) return false;
|
|
1363
|
+
try {
|
|
1364
|
+
return attributionState(readSettings(text).settings) === "current";
|
|
1252
1365
|
} catch {
|
|
1253
1366
|
return false;
|
|
1254
1367
|
}
|
|
@@ -1427,6 +1540,6 @@ const toolchainInputKind = (file, text = "") => {
|
|
|
1427
1540
|
if (githubAutomationFileKind(file) !== void 0 || isShellScript(file, text) || /(?:^|\/)ci-service-images\.json$/.test(file) || isMiseConfigPath(file) || isPythonDependencyManifest(file) || isDockerDefinitionPath(file) || isComposeDefinitionPath(file) || isKubernetesDefinitionPath(file) || /(?:^|\/)(?:package\.json|consumer-compat\.json|pnpm-workspace\.yaml|stll-toolchain\.json|\.bun-version|\.node-version|\.nvmrc|\.python-version|rust-toolchain(?:\.toml)?|\.tool-versions|\.?mise\.toml|uv\.toml|\.uv\.toml|\.github\/dependabot\.ya?ml|Cargo\.toml)$/.test(file)) return "config";
|
|
1428
1541
|
};
|
|
1429
1542
|
//#endregion
|
|
1430
|
-
export {
|
|
1543
|
+
export { nodeSelectorMatches as C, nodePolicyValid as S, parseCloudSetup as T, hasCloudAttribution as _, isPythonDependencyManifest as a, cloudSetupPath as b, pythonDependencyManifestKind as c, isComposeDefinitionPath as d, isKubernetesDefinitionPath as f, cloudSessionStartFix as g, cloudClaudeSettingsPath as h, isMiseConfigPath as i, toolchainInputKind as l, cloudAttributionFix as m, isDependabotGithubActionsPath as n, isShellScript as o, workspaceContains as p, isDockerDefinitionPath as r, javascriptDependencyLockfiles as s, githubAutomationFileKind as t, containerDocumentImages as u, hasCloudSessionStartHook as v, nodeSupportRangeMatches as w, generateCloudSetup as x, mergeCloudClaudeSettings as y };
|
|
1431
1544
|
|
|
1432
1545
|
//# sourceMappingURL=toolchain-inputs.mjs.map
|