feat(deploy): add typed command transport releases
This commit is contained in:
@@ -12,10 +12,19 @@ const devicePlaneRoot = resolve(platformRoot, "device-plane");
|
||||
const designRoot = resolve(process.env.NODEDC_DEVICE_MANAGER_SOURCE_ROOT || resolve(platformRoot, "../NODEDC_DESIGN_GUIDELINE"));
|
||||
const managerRoot = resolve(designRoot, "apps/device-manager");
|
||||
const artifactDir = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(scriptDir, "../deploy-artifacts"));
|
||||
const [patchId = "device-manager-release-20260811-018", ...extra] = process.argv.slice(2);
|
||||
const [patchId = "device-manager-release-v3-20260812-026", ...extra] = process.argv.slice(2);
|
||||
if (extra.length || !/^[A-Za-z0-9._-]{1,96}$/.test(patchId)) throw new Error("usage: build-device-manager-control-plane-artifact.mjs [patch-id]");
|
||||
|
||||
const entries = [
|
||||
const descriptorPath = patchId.startsWith("device-manager-release-v3-")
|
||||
? "deployment/device-manager-release-v3.json"
|
||||
: "deployment/device-manager-release-v1.json";
|
||||
|
||||
const isV3 = descriptorPath.endsWith("release-v3.json");
|
||||
const entries = isV3 ? [
|
||||
"docker-compose.device-manager.yml",
|
||||
"services/device-manager",
|
||||
descriptorPath,
|
||||
] : [
|
||||
".dockerignore",
|
||||
"package.json",
|
||||
"package-lock.json",
|
||||
@@ -27,7 +36,7 @@ const entries = [
|
||||
"services/device-gateway/package.json",
|
||||
"services/device-edge-relay/package.json",
|
||||
"services/device-manager",
|
||||
"deployment/device-manager-release-v1.json",
|
||||
descriptorPath,
|
||||
];
|
||||
const stage = await mkdtemp(join(tmpdir(), "nodedc-device-manager-control-plane-"));
|
||||
const payload = join(stage, "payload");
|
||||
@@ -41,7 +50,7 @@ try {
|
||||
if (build.status !== 0) throw new Error(`device_manager_build_failed:${build.stderr || build.stdout}`);
|
||||
await mkdir(payload, { recursive: true });
|
||||
for (const entry of entries) {
|
||||
if (entry === "deployment/device-manager-release-v1.json") {
|
||||
if (entry === descriptorPath) {
|
||||
const descriptor = JSON.parse(await readFile(resolve(devicePlaneRoot, entry), "utf8"));
|
||||
if (descriptor.releaseId !== "__PATCH_ID__") {
|
||||
throw new Error("device_manager_release_template_id_mismatch");
|
||||
@@ -62,15 +71,17 @@ try {
|
||||
}
|
||||
await copySafe(resolve(devicePlaneRoot, entry), join(payload, entry), devicePlaneRoot);
|
||||
}
|
||||
await validateDockerCopySources(
|
||||
join(payload, "services/device-control-core/Dockerfile"),
|
||||
payload,
|
||||
);
|
||||
if (!isV3) {
|
||||
await validateDockerCopySources(
|
||||
join(payload, "services/device-control-core/Dockerfile"),
|
||||
payload,
|
||||
);
|
||||
}
|
||||
await validateDockerCopySources(
|
||||
join(payload, "services/device-manager/Dockerfile"),
|
||||
join(payload, "services/device-manager"),
|
||||
);
|
||||
for (const modulePath of [
|
||||
for (const modulePath of isV3 ? [] : [
|
||||
"services/device-control-core/src/sensitive-reference-management.mjs",
|
||||
"services/device-control-core/src/device-gateway-core-runtime.mjs",
|
||||
"packages/device-edge-channel-contract/src/index.mjs",
|
||||
@@ -115,14 +126,10 @@ try {
|
||||
]) {
|
||||
if (compose.includes(forbidden)) throw new Error(`device_manager_compose_boundary_violation:${forbidden}`);
|
||||
}
|
||||
const descriptor = JSON.parse(await readFile(
|
||||
join(payload, "deployment/device-manager-release-v1.json"),
|
||||
"utf8",
|
||||
));
|
||||
const descriptor = JSON.parse(await readFile(join(payload, descriptorPath), "utf8"));
|
||||
const predecessor = descriptor.predecessor;
|
||||
if (
|
||||
descriptor.schemaVersion !== "nodedc.device-plane.device-manager-release.v1"
|
||||
|| descriptor.releaseId !== patchId
|
||||
const commonContractInvalid = (
|
||||
descriptor.releaseId !== patchId
|
||||
|| !["activate", "upgrade"].includes(descriptor.action)
|
||||
|| !predecessor
|
||||
|| !["reconciliation", "release"].includes(predecessor.kind)
|
||||
@@ -131,7 +138,29 @@ try {
|
||||
|| (descriptor.action === "activate") !== (predecessor.kind === "reconciliation")
|
||||
|| descriptor.healthGate !== "bounded-container-grace+core-contract"
|
||||
|| descriptor.rollback !== "restore-preapply-snapshot"
|
||||
) throw new Error("device_manager_activation_successor_contract_mismatch");
|
||||
);
|
||||
if (commonContractInvalid) throw new Error("device_manager_activation_successor_contract_mismatch");
|
||||
if (descriptorPath.endsWith("release-v3.json")) {
|
||||
if (
|
||||
descriptor.schemaVersion !== "nodedc.device-plane.device-manager-release.v3"
|
||||
|| descriptor.commandTransport !== "typed-service-ping-v1"
|
||||
|| descriptor.commandCatalog !== "allowlisted-adapter-typed-commands-only"
|
||||
|| descriptor.credentialBoundary !== "transient-core-memory-then-single-pinned-mtls-command-envelope-to-edge-never-persisted-never-logged-never-returned"
|
||||
|| descriptor.controlCorePredecessor?.patchId !== "device-control-core-release-v2-20260812-025"
|
||||
|| descriptor.controlCorePredecessor?.artifactSha256 !== "c61b1f0de1bae23de0caa7289036865ea419ff5705611416f736ca929d1592db"
|
||||
|| descriptor.edgeChannelPredecessor?.patchId !== "device-edge-core-channel-upgrade-v4-20260812-023"
|
||||
|| descriptor.edgeChannelPredecessor?.artifactSha256 !== "c10d5b6b7d55ab239f85b6c8130e34ce9f84985e3b46e6e5534733156c7982fc"
|
||||
|| descriptor.edgeChannel !== "preserve-active-v4-core-initiated-pinned-mtls"
|
||||
|| descriptor.edgeChannelEgress !== "preserve-dedicated-core-only-bridge-no-host-ingress-public-ipv4-tcp-443-only"
|
||||
|| descriptor.gelios !== "untouched-legacy-only"
|
||||
) throw new Error("device_manager_v3_typed_command_contract_mismatch");
|
||||
} else if (
|
||||
descriptor.schemaVersion !== "nodedc.device-plane.device-manager-release.v1"
|
||||
|| descriptor.commandTransport !== "disabled"
|
||||
|| descriptor.gelios !== "untouched"
|
||||
) {
|
||||
throw new Error("device_manager_v1_contract_mismatch");
|
||||
}
|
||||
await writeFile(join(stage, "manifest.env"), `id=${patchId}\ncomponent=device-plane\ntype=app-overlay\n`, "utf8");
|
||||
await writeFile(join(stage, "files.txt"), `${entries.join("\n")}\n`, "utf8");
|
||||
await mkdir(artifactDir, { recursive: true });
|
||||
@@ -145,7 +174,7 @@ try {
|
||||
artifact: target,
|
||||
sha256,
|
||||
entries,
|
||||
services: ["device-control-core", "device-manager"],
|
||||
services: isV3 ? ["device-manager"] : ["device-control-core", "device-manager"],
|
||||
preserved: ["device-postgres", "device-gateway", "device-backhaul-target", "Gelios"],
|
||||
}, null, 2));
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user