refactor: make v0.3 runtime node-scoped
This commit is contained in:
@@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url";
|
||||
|
||||
import { activeReportLifecycle } from "../internal/dev-report-lifecycle.mjs";
|
||||
import { ENVIRONMENT_DEV, SERVICE_IDS } from "../internal/protocol/index.mjs";
|
||||
import { createG14CiPlan } from "./src/g14-ci-plan-lib.mjs";
|
||||
import { createCiPlan } from "./src/ci-plan-lib.mjs";
|
||||
import {
|
||||
BUILDABLE_IMPLEMENTATION_STATES,
|
||||
resolveDevArtifactServices,
|
||||
@@ -26,7 +26,7 @@ import { readStructuredFile } from "./src/structured-config.mjs";
|
||||
|
||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const cliEntrypoint = process.env.HWLAB_ARTIFACT_PUBLISH_ENTRYPOINT || "scripts/artifact-publish.mjs";
|
||||
const defaultLane = process.env.HWLAB_ARTIFACT_LANE || process.env.HWLAB_GITOPS_LANE || "g14";
|
||||
const defaultLane = process.env.HWLAB_ARTIFACT_LANE || process.env.HWLAB_GITOPS_LANE || "node";
|
||||
const defaultRegistryPrefix =
|
||||
process.env.HWLAB_DEV_REGISTRY_PREFIX || process.env.HWLAB_DEV_REGISTRY || "127.0.0.1:5000/hwlab";
|
||||
const defaultBaseImage = process.env.HWLAB_DEV_BASE_IMAGE || null;
|
||||
@@ -121,7 +121,7 @@ function parseArgs(argv) {
|
||||
else throw new Error(`unknown argument ${arg}`);
|
||||
}
|
||||
|
||||
assert.ok(args.lane === "g14" || isRuntimeArtifactLane(args.lane), `unknown artifact lane ${args.lane}`);
|
||||
assert.ok(args.lane === "node" || isRuntimeArtifactLane(args.lane), `unknown artifact lane ${args.lane}`);
|
||||
assert.ok(["short", "full"].includes(args.imageTagMode), `unknown image tag mode ${args.imageTagMode}`);
|
||||
|
||||
return args;
|
||||
@@ -146,12 +146,12 @@ function artifactIdentityValue(env, name) {
|
||||
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
||||
}
|
||||
|
||||
function g14ArtifactIdentityName(env = process.env) {
|
||||
function artifactIdentityName(env = process.env) {
|
||||
return ciArtifactIdentityEnvNames.find((name) => artifactIdentityValue(env, name));
|
||||
}
|
||||
|
||||
function g14ArtifactProducer(env = process.env) {
|
||||
const idName = g14ArtifactIdentityName(env);
|
||||
function artifactProducer(env = process.env) {
|
||||
const idName = artifactIdentityName(env);
|
||||
if (!idName) {
|
||||
return {
|
||||
kind: "missing",
|
||||
@@ -160,24 +160,24 @@ function g14ArtifactProducer(env = process.env) {
|
||||
};
|
||||
}
|
||||
return {
|
||||
kind: "g14-ci-artifact",
|
||||
kind: "node-ci-artifact",
|
||||
runId: artifactIdentityValue(env, idName),
|
||||
owner: artifactIdentityValue(env, "HWLAB_CI_ARTIFACT_RUN_OWNER") ?? idName
|
||||
};
|
||||
}
|
||||
|
||||
function g14ArtifactPublishIdentityGuardFailure({ script, mode }) {
|
||||
function artifactPublishIdentityGuardFailure({ script, mode }) {
|
||||
return {
|
||||
ok: false,
|
||||
status: "blocked",
|
||||
error: "g14-artifact-publish-identity-required",
|
||||
code: "g14-artifact-publish-identity-required",
|
||||
error: "artifact-publish-identity-required",
|
||||
code: "artifact-publish-identity-required",
|
||||
script,
|
||||
mode,
|
||||
requiredEnv: "HWLAB_CI_ARTIFACT_RUN_ID or standard CI run identity",
|
||||
acceptedEnv: ciArtifactIdentityEnvNames,
|
||||
entrypoint: `HWLAB_CI_ARTIFACT_RUN_ID=<run-id> HWLAB_CI_ARTIFACT_RUN_OWNER=<owner> node scripts/g14-artifact-publish.mjs --publish --report ${tempReportPath("dev-artifacts.json")}`,
|
||||
summary: `${script} ${mode} is a G14 artifact publish side-effect step and must run under CI artifact identity. Legacy D601 CD transaction identity is not accepted.`,
|
||||
entrypoint: `HWLAB_CI_ARTIFACT_RUN_ID=<run-id> HWLAB_CI_ARTIFACT_RUN_OWNER=<owner> node scripts/artifact-publish.mjs --publish --report ${tempReportPath("dev-artifacts.json")}`,
|
||||
summary: `${script} ${mode} is a node artifact publish side-effect step and must run under CI artifact identity. Legacy D601 CD transaction identity is not accepted.`,
|
||||
devOnly: true,
|
||||
prodTouched: false,
|
||||
cdLockRequired: false,
|
||||
@@ -186,8 +186,8 @@ function g14ArtifactPublishIdentityGuardFailure({ script, mode }) {
|
||||
};
|
||||
}
|
||||
|
||||
function requireG14ArtifactPublishIdentity({ env = process.env, script, mode }) {
|
||||
return g14ArtifactIdentityName(env) ? null : g14ArtifactPublishIdentityGuardFailure({ script, mode });
|
||||
function requireArtifactPublishIdentity({ env = process.env, script, mode }) {
|
||||
return artifactIdentityName(env) ? null : artifactPublishIdentityGuardFailure({ script, mode });
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
@@ -197,7 +197,7 @@ function printHelp() {
|
||||
"Commit-pinned artifact build/publish helper for controlled CI execution.",
|
||||
"",
|
||||
"options:",
|
||||
" --lane LANE g14 or runtime lane vNN; default: g14",
|
||||
" --lane LANE node or runtime lane vNN; default: node",
|
||||
` --catalog-path PATH default: ${defaultCatalogPath}`,
|
||||
` --deploy-config PATH default: ${defaultDeployPath}`,
|
||||
" --image-tag-mode MODE short or full; v02 uses full source commit IDs",
|
||||
@@ -235,11 +235,11 @@ function emit(event, payload = {}) {
|
||||
}
|
||||
|
||||
function ciTimingEnabled(env = process.env) {
|
||||
return env.HWLAB_G14_CICD_TIMING === "1" || env.HWLAB_CI_TIMING === "1";
|
||||
return env.HWLAB_NODE_CICD_TIMING === "1" || env.HWLAB_CI_TIMING === "1";
|
||||
}
|
||||
|
||||
function emitCiTiming(payload) {
|
||||
emit("g14-cicd-timing", {
|
||||
emit("node-cicd-timing", {
|
||||
schemaVersion: "v1",
|
||||
source: "scripts/artifact-publish.mjs",
|
||||
pipelineRun: process.env.HWLAB_TEKTON_PIPELINERUN ?? null,
|
||||
@@ -305,7 +305,7 @@ function parseDockerfileStepTimings(text) {
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
if (parsed?.event !== "g14-cicd-build-step-timing") continue;
|
||||
if (parsed?.event !== "node-cicd-build-step-timing") continue;
|
||||
timings.push({
|
||||
stage: parsed.stage,
|
||||
status: parsed.status ?? "unknown",
|
||||
@@ -369,7 +369,7 @@ function buildkitBaseImagePreflight(baseImage) {
|
||||
blockers: [],
|
||||
nextSteps: [],
|
||||
recommendation: {
|
||||
source: "G14 k8s registry image used by rootless BuildKit.",
|
||||
source: "node k8s registry image used by rootless BuildKit.",
|
||||
envVar: "HWLAB_DEV_BASE_IMAGE",
|
||||
recommendedEnvValue: requestedImage
|
||||
},
|
||||
@@ -638,7 +638,7 @@ function artifactCatalogSkeleton({ args, deployManifest, commitId }) {
|
||||
ciPublished: false,
|
||||
registryVerified: false,
|
||||
provenance: "not_available_until_publish",
|
||||
note: `${artifactEnvironment(args)} artifact catalog skeleton initialized without DEV/G14 fallback.`
|
||||
note: `${artifactEnvironment(args)} artifact catalog skeleton initialized without DEV/node fallback.`
|
||||
},
|
||||
allowedProfiles: [artifactEnvironment(args)],
|
||||
forbiddenProfiles: isRuntimeArtifactLane(args.lane) ? ["dev", "prod"] : ["prod"],
|
||||
@@ -808,7 +808,7 @@ async function resolveServices(serviceIds, catalog) {
|
||||
}
|
||||
|
||||
function dockerfile(baseImage, port, labels = []) {
|
||||
const dependencyTimingScript = `started_at=$(node -e "console.log(Date.now())"); status=succeeded; if [ -d /opt/hwlab-node-runtime-base/node_modules ]; then cp -a /opt/hwlab-node-runtime-base/node_modules ./node_modules; fi && if [ -f package-lock.json ]; then npm install --omit=dev --include=optional --ignore-scripts; else npm install --omit=dev --include=optional --ignore-scripts; fi && if [ "\${HWLAB_ARTIFACT_KIND:-}" = "bun-command" ]; then bun_pkg=""; case "$(uname -m)" in x86_64|amd64) bun_pkg="@oven/bun-linux-x64@1.3.13" ;; aarch64|arm64) bun_pkg="@oven/bun-linux-aarch64@1.3.13" ;; *) echo "unsupported bun-command architecture: $(uname -m)" >&2; false ;; esac && npm install --no-save --omit=dev --include=optional --ignore-scripts "$bun_pkg" && test -x "node_modules/\${bun_pkg%@*}/bin/bun" && ln -sf "/app/node_modules/\${bun_pkg%@*}/bin/bun" /usr/local/bin/bun; fi && codex_version="$(node -p "require('./node_modules/@openai/codex/package.json').version")" && case "$(uname -m)" in x86_64|amd64) test -e node_modules/@openai/codex-linux-x64 || npm install --omit=dev --include=optional --ignore-scripts "@openai/codex-linux-x64@npm:@openai/codex@\${codex_version}-linux-x64" ;; aarch64|arm64) test -e node_modules/@openai/codex-linux-arm64 || npm install --omit=dev --include=optional --ignore-scripts "@openai/codex-linux-arm64@npm:@openai/codex@\${codex_version}-linux-arm64" ;; esac || status=failed; finished_at=$(node -e "console.log(Date.now())"); node -e "console.log(JSON.stringify({event:'g14-cicd-build-step-timing',stage:'dependency-install',status:process.argv[1],durationMs:Number(process.argv[3])-Number(process.argv[2]),source:'dockerfile-run'}))" "$status" "$started_at" "$finished_at"; test "$status" = succeeded`;
|
||||
const dependencyTimingScript = `started_at=$(node -e "console.log(Date.now())"); status=succeeded; if [ -d /opt/hwlab-node-runtime-base/node_modules ]; then cp -a /opt/hwlab-node-runtime-base/node_modules ./node_modules; fi && if [ -f package-lock.json ]; then npm install --omit=dev --include=optional --ignore-scripts; else npm install --omit=dev --include=optional --ignore-scripts; fi && if [ "\${HWLAB_ARTIFACT_KIND:-}" = "bun-command" ]; then bun_pkg=""; case "$(uname -m)" in x86_64|amd64) bun_pkg="@oven/bun-linux-x64@1.3.13" ;; aarch64|arm64) bun_pkg="@oven/bun-linux-aarch64@1.3.13" ;; *) echo "unsupported bun-command architecture: $(uname -m)" >&2; false ;; esac && npm install --no-save --omit=dev --include=optional --ignore-scripts "$bun_pkg" && test -x "node_modules/\${bun_pkg%@*}/bin/bun" && ln -sf "/app/node_modules/\${bun_pkg%@*}/bin/bun" /usr/local/bin/bun; fi && codex_version="$(node -p "require('./node_modules/@openai/codex/package.json').version")" && case "$(uname -m)" in x86_64|amd64) test -e node_modules/@openai/codex-linux-x64 || npm install --omit=dev --include=optional --ignore-scripts "@openai/codex-linux-x64@npm:@openai/codex@\${codex_version}-linux-x64" ;; aarch64|arm64) test -e node_modules/@openai/codex-linux-arm64 || npm install --omit=dev --include=optional --ignore-scripts "@openai/codex-linux-arm64@npm:@openai/codex@\${codex_version}-linux-arm64" ;; esac || status=failed; finished_at=$(node -e "console.log(Date.now())"); node -e "console.log(JSON.stringify({event:'node-cicd-build-step-timing',stage:'dependency-install',status:process.argv[1],durationMs:Number(process.argv[3])-Number(process.argv[2]),source:'dockerfile-run'}))" "$status" "$started_at" "$finished_at"; test "$status" = succeeded`;
|
||||
const runtimeReadinessScript = `set -eu; fail() { echo "hwlab-artifact-runtime-check-failed:$1" >&2; exit 1; }; mkdir -p /workspace /codex-home; rm -rf /workspace/hwlab; ln -s /app /workspace/hwlab; if [ "\${HWLAB_ARTIFACT_KIND:-}" = "bun-command" ]; then test -x /usr/local/bin/bun || fail bun-missing; /usr/local/bin/bun --version >/tmp/hwlab-bun-version.txt || fail bun-version; fi; chmod -R a+rwX /app /workspace /codex-home || fail chmod; test -x /app/node_modules/.bin/codex || fail codex-bin-missing; /app/node_modules/.bin/codex --version >/tmp/hwlab-codex-version.txt || fail codex-version; test -x /app/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex/codex || test -x /app/node_modules/@openai/codex-linux-arm64/vendor/aarch64-unknown-linux-musl/codex/codex || fail codex-native-missing`;
|
||||
return [
|
||||
`FROM ${baseImage}`,
|
||||
@@ -1032,7 +1032,7 @@ async function preflight({ args, services, catalog, deployManifest, baseImagePre
|
||||
type: "safety_blocker",
|
||||
scope: "registry",
|
||||
summary: error.message,
|
||||
next: "Use the G14 local/internal registry prefix, for example 127.0.0.1:5000/hwlab."
|
||||
next: "Use the node local/internal registry prefix, for example 127.0.0.1:5000/hwlab."
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -1072,7 +1072,7 @@ async function preflight({ args, services, catalog, deployManifest, baseImagePre
|
||||
type: "environment_blocker",
|
||||
scope: "buildkit-command",
|
||||
summary: `BuildKit command ${args.buildkitCommand} is not available in the publish task image.`,
|
||||
next: "Use the G14 Tekton BuildKit path that prepares buildctl/buildkitd before running --publish."
|
||||
next: "Use the node Tekton BuildKit path that prepares buildctl/buildkitd before running --publish."
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -2038,14 +2038,14 @@ function createReport({ args, repo, commitId, shortCommit, mode, services, artif
|
||||
documents: [
|
||||
"docs/reference/MVP-e2e-acceptance.md",
|
||||
"docs/reference/spec-v02-documentation-governance.md",
|
||||
"docs/reference/g14-gitops-cicd.md",
|
||||
"docs/reference/node-gitops-cicd.md",
|
||||
"docs/reference/spec-v02-cicd.md"
|
||||
],
|
||||
summary: `${environment} artifact publish evidence; runtime acceptance stays separate from artifact publication.`
|
||||
},
|
||||
validationCommands: [
|
||||
"node --check scripts/artifact-publish.mjs",
|
||||
"node --check scripts/g14-artifact-publish.mjs",
|
||||
"node --check scripts/artifact-publish.mjs",
|
||||
"node --check scripts/src/dev-artifact-services.mjs",
|
||||
"node --check scripts/src/registry-capabilities.mjs",
|
||||
"node --check scripts/preflight-dev-base-image.mjs",
|
||||
@@ -2053,7 +2053,7 @@ function createReport({ args, repo, commitId, shortCommit, mode, services, artif
|
||||
"node --check scripts/dev-runtime-base-image.mjs",
|
||||
"node --test scripts/refresh-artifact-catalog.test.mjs",
|
||||
"node scripts/preflight-dev-base-image.mjs",
|
||||
"node scripts/g14-artifact-publish.mjs --preflight --no-report",
|
||||
"node scripts/artifact-publish.mjs --preflight --no-report",
|
||||
"node --check scripts/validate-dev-gate-report.mjs",
|
||||
"node scripts/validate-dev-gate-report.mjs"
|
||||
],
|
||||
@@ -2197,7 +2197,7 @@ async function main() {
|
||||
return;
|
||||
}
|
||||
if (args.mode === "publish") {
|
||||
const identityGuard = requireG14ArtifactPublishIdentity({
|
||||
const identityGuard = requireArtifactPublishIdentity({
|
||||
script: cliEntrypoint,
|
||||
mode: "--publish"
|
||||
});
|
||||
@@ -2237,8 +2237,8 @@ async function main() {
|
||||
}
|
||||
const buildCreatedAt = new Date().toISOString();
|
||||
const repo = repoLabelFromRemote(remoteUrl);
|
||||
const producer = g14ArtifactProducer(process.env);
|
||||
const ciPlan = await createG14CiPlan({
|
||||
const producer = artifactProducer(process.env);
|
||||
const ciPlan = await createCiPlan({
|
||||
repoRoot,
|
||||
lane: args.lane,
|
||||
targetRef: "HEAD",
|
||||
|
||||
Reference in New Issue
Block a user