@task-handoff/node-agent 0.0.20 → 0.0.22-alpha.1
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/bin/task-handoff-node-update-worker +1 -230
- package/dist/cli.js +1 -1
- package/dist/node-update-worker.js +2 -0
- package/package.json +1 -1
- package/runtime-artifacts/{controlled-instance-runtime-0.0.20-linux-universal.manifest.json → controlled-instance-runtime-0.0.22-alpha.1-linux-universal.manifest.json} +2 -2
- package/runtime-artifacts/controlled-instance-runtime-0.0.22-alpha.1-linux-universal.tar.gz +0 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.22-alpha.1-linux-universal.tar.gz.sha256 +1 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.20-linux-universal.tar.gz +0 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.20-linux-universal.tar.gz.sha256 +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e=require("node:fs"),t=require("node:path"),{spawnSync:n}=require("node:child_process"),{Command:r,InvalidArgumentError:o}=require("commander"),a=require("semver"),i=require("write-file-atomic"),{ControlPlaneHealthResponseSchema:s}=require("../packages/protocol/src/control-plane.ts");function c(e){const t=s.safeParse(e);return t.success?t.data.data.build.packageVersion:void 0}const d=(new r).name("task-handoff-node-update-worker").description("Apply a detached TaskHandoff node update.").requiredOption("--job-file <path>","persisted update job file").requiredOption("--target-version <version>","exact semantic version",function(e){if(e.trim()!==e||/^[v=]/.test(e)||null===a.valid(e))throw new o("must be an exact semantic version");return e}).option("--service <name>","systemd service to restart","task-handoff-node-agent.service").option("--npm-command <path>","npm executable",process.env.TASK_HANDOFF_NPM_COMMAND||"npm").option("--control-plane-health-url <url>","local control-plane health endpoint",function(e){let t;try{t=new URL(e)}catch{throw new o("must be a valid loopback HTTP URL")}if(!["http:","https:"].includes(t.protocol)||!["127.0.0.1","localhost","::1"].includes(t.hostname))throw new o("must be a valid loopback HTTP URL");return t.toString()}).parse(process.argv).opts(),f=d.jobFile,l=d.targetVersion,u=d.service,p=d.npmCommand,h=d.controlPlaneHealthUrl,m=new Set(["succeeded","degraded","failed"]),w=new Set(["@task-handoff/node-agent","@task-handoff/server"]);function g(n,r){const o=JSON.parse(e.readFileSync(f,"utf8"));process.env.TASK_HANDOFF_UPDATE_WORKER_TEST_CAS_HOOK&&require(t.resolve(process.env.TASK_HANDOFF_UPDATE_WORKER_TEST_CAS_HOOK))({jobFile:f,observed:o});const a=`${f}.worker-lock`;e.mkdirSync(a);try{const t=JSON.parse(e.readFileSync(f,"utf8"));if(m.has(t.status)||!n.includes(t.status))return!1;const o="function"==typeof r?r(t):r,a={...t,...o,updatedAt:(new Date).toISOString()};return i.sync(f,`${JSON.stringify(a,null,2)}\n`,{encoding:"utf8"}),!0}finally{e.rmdirSync(a)}}function v(e,t){const r=n(e,t,{stdio:"inherit"});if(0!==r.status)throw new Error(`${e} exited with status ${r.status??"unknown"}`)}function S(n,r,o){const a=o?t.join(r,...o.split("/"),"node_modules",...n.split("/"),"package.json"):t.join(r,...n.split("/"),"package.json");try{return JSON.parse(e.readFileSync(a,"utf8")).version}catch(e){if("ENOENT"===e?.code)return;throw e}}function y(e,t){const n=S(e,t);if(n!==l)throw new Error(`Updated ${e} verification failed: expected ${l}, found ${n||"unknown"}.`)}function E(e){const t=n(p,["view",`${e}@${l}`,"dist.integrity","--json"],{encoding:"utf8"});if(0!==t.status)throw new Error(`Could not verify the ${e} npm artifact integrity.`);let r;try{r=JSON.parse(t.stdout)}catch{throw new Error(`npm returned invalid ${e} artifact integrity metadata.`)}if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw new Error(`npm returned invalid ${e} artifact integrity metadata.`);return r}!async function(){try{g(["queued"],e=>({status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:(new Date).toISOString(),error:void 0}))||process.exit(0);const t=function(){const t=JSON.parse(e.readFileSync(f,"utf8")),n=`@${l}#`;if("string"!=typeof t.artifactRef||!t.artifactRef.startsWith("npm:")||!t.artifactRef.includes(n))throw new Error(`Update job does not pin npm integrity for version ${l}.`);const r=t.artifactRef.indexOf(n),o=t.artifactRef.slice(4,r),a=t.artifactRef.slice(r+n.length);if(!w.has(o)||!a)throw new Error("Update job does not identify a supported immutable npm artifact.");const i=E(o);if(i!==a)throw new Error(`${o} npm artifact integrity mismatch: expected ${a}, found ${String(i||"unknown")}.`);return{packageName:o,integrity:i}}(),r=t.packageName,o=n(p,["prefix","--global"],{encoding:"utf8"});if(0!==o.status)throw new Error("Could not determine the npm global prefix.");const a=o.stdout.trim(),i=n(p,["root","--global"],{encoding:"utf8"});if(0!==i.status)throw new Error("Could not determine the npm global module root.");const s=i.stdout.trim(),d=[r];"@task-handoff/server"===r&&void 0!==S("@task-handoff/node-agent",s)&&d.push("@task-handoff/node-agent");const m=new Map([[r,t.integrity]]);for(const e of d.slice(1))m.set(e,E(e));for(const e of d){if(v(p,["install","--global","--prefix",a,`${e}@${l}`]),E(e)!==m.get(e))throw new Error(`${e} npm artifact integrity changed during installation.`);y(e,s)}if("@task-handoff/server"===r&&function(e){for(const t of["@task-handoff/control-plane","@task-handoff/node-agent","@task-handoff/controlled-instance"]){const n=S(t,e,"@task-handoff/server")||S(t,e);if(n!==l)throw new Error(`Updated @task-handoff/server does not provide ${t} ${l}; found ${n||"unknown"}.`)}}(s),"@task-handoff/server"===r){if(!h)throw new Error("A control-plane health URL is required for a complete server update.");v("systemctl",["restart","task-handoff-control-plane.service"]),await async function(t,n=6e4){const r=Date.now()+n;let o="not reachable";for(;Date.now()<r;){try{if(process.env.TASK_HANDOFF_UPDATE_WORKER_TEST_HEALTH_FILE){const t=c(JSON.parse(e.readFileSync(process.env.TASK_HANDOFF_UPDATE_WORKER_TEST_HEALTH_FILE,"utf8")));if(t===l)return;o=`reported version ${String(t||"unknown")}`,await new Promise(e=>setTimeout(e,10));continue}const n=await fetch(t,{headers:{"cache-control":"no-cache"},signal:AbortSignal.timeout(2e3)}),r=c(await n.json().catch(()=>({})));if(n.ok&&r===l)return;o=n.ok?`reported version ${String(r||"unknown")}`:`returned HTTP ${n.status}`}catch(e){o=e instanceof Error?e.message:String(e)}await new Promise(e=>setTimeout(e,500))}throw new Error(`Control plane did not become healthy at ${t} with version ${l}: ${o}.`)}(h)}g(["updating-node"],e=>({status:"restarting-node",rollout:{...e.rollout,phase:"restarting-node"}}))||process.exit(0),v("systemctl",["restart",u])}catch(e){g(["queued","updating-node","restarting-node"],t=>({status:"failed",rollout:{...t.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:e instanceof Error?e.message:String(e),retryable:!1},completedAt:(new Date).toISOString()})),console.error(e),process.exit(1)}}();
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@task-handoff/controlled-instance",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22-alpha.1",
|
|
4
4
|
"platform": "linux",
|
|
5
5
|
"arch": "universal",
|
|
6
6
|
"formatVersion": 1,
|
|
7
7
|
"launcherAbi": 1,
|
|
8
8
|
"entrypoint": "dist/controlled-instance-cli.js",
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "879f3a06c7d80deead071adc33b26a6aeca37dab6598c6d9f59db67d02b82899"
|
|
10
10
|
}
|
|
Binary file
|
package/runtime-artifacts/controlled-instance-runtime-0.0.22-alpha.1-linux-universal.tar.gz.sha256
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2f35c5e9ebc9551d672d369f69592bf06c76ed62957f35090ee687aa4bc6b8dd controlled-instance-runtime-0.0.22-alpha.1-linux-universal.tar.gz
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
e7821e82b4127ee9729680ee9c6167e225aaec148d71029ce8785bda8b9482f2 controlled-instance-runtime-0.0.20-linux-universal.tar.gz
|