fix: keep deploy manifest human-authored
This commit is contained in:
@@ -914,7 +914,7 @@ check_source_head before-render
|
||||
git config --global user.name "HWLAB G14 GitOps Bot"
|
||||
git config --global user.email "hwlab-g14-gitops-bot@users.noreply.github.com"
|
||||
if [ -s /workspace/source/dev-artifacts.json ]; then
|
||||
node scripts/refresh-artifact-catalog.mjs --target-ref "$(params.revision)" --publish-report /workspace/source/dev-artifacts.json
|
||||
node scripts/refresh-artifact-catalog.mjs --target-ref "$(params.revision)" --publish-report /workspace/source/dev-artifacts.json --write
|
||||
fi
|
||||
node scripts/g14-gitops-render.mjs --source-revision "$(params.revision)" --source-repo "$(params.git-url)" --source-branch "$(params.source-branch)" --gitops-branch "$(params.gitops-branch)" --registry-prefix "$(params.registry-prefix)" --use-deploy-images
|
||||
node scripts/g14-gitops-render.mjs --source-revision "$(params.revision)" --source-repo "$(params.git-url)" --source-branch "$(params.source-branch)" --gitops-branch "$(params.gitops-branch)" --registry-prefix "$(params.registry-prefix)" --use-deploy-images --check
|
||||
|
||||
@@ -29,7 +29,7 @@ function parseArgs(argv) {
|
||||
targetRef: "HEAD",
|
||||
publishReportPath: null,
|
||||
blocked: false,
|
||||
write: true
|
||||
write: false
|
||||
};
|
||||
|
||||
for (let index = 0; index < argv.length; index += 1) {
|
||||
@@ -40,6 +40,8 @@ function parseArgs(argv) {
|
||||
args.publishReportPath = readOption(argv, ++index, arg);
|
||||
} else if (arg === "--blocked") {
|
||||
args.blocked = true;
|
||||
} else if (arg === "--write") {
|
||||
args.write = true;
|
||||
} else if (arg === "--no-write") {
|
||||
args.write = false;
|
||||
} else if (arg === "--help" || arg === "-h") {
|
||||
@@ -52,6 +54,7 @@ function parseArgs(argv) {
|
||||
if (!args.help) {
|
||||
assert.notEqual(args.blocked && Boolean(args.publishReportPath), true, "--blocked and --publish-report are mutually exclusive");
|
||||
assert.ok(args.blocked || args.publishReportPath, `choose --blocked or --publish-report ${defaultPublishReportPath}`);
|
||||
assert.ok(!args.write || args.publishReportPath, "--write requires --publish-report; blocked skeleton refresh must stay preview-only");
|
||||
}
|
||||
|
||||
return args;
|
||||
@@ -67,13 +70,15 @@ function readOption(argv, index, name) {
|
||||
|
||||
function usage() {
|
||||
return [
|
||||
"usage: node scripts/refresh-artifact-catalog.mjs --target-ref REF (--blocked|--publish-report PATH) [--no-write]",
|
||||
"usage: node scripts/refresh-artifact-catalog.mjs --target-ref REF (--blocked|--publish-report PATH) [--write|--no-write]",
|
||||
"",
|
||||
"Refresh DEV deploy/catalog artifact identity without faking digest evidence.",
|
||||
"Preview or explicitly write DEV artifact catalog identity without faking digest evidence.",
|
||||
"Default mode is read-only. --write is reserved for G14 Tekton GitOps promotion and never writes deploy/deploy.json.",
|
||||
"",
|
||||
"examples:",
|
||||
" node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked",
|
||||
` node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report ${defaultPublishReportPath}`
|
||||
" node scripts/refresh-artifact-catalog.mjs --target-ref HEAD --blocked --no-write",
|
||||
` node scripts/refresh-artifact-catalog.mjs --target-ref HEAD --publish-report ${defaultPublishReportPath} --no-write`,
|
||||
` node scripts/refresh-artifact-catalog.mjs --target-ref HEAD --publish-report ${defaultPublishReportPath} --write`
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,63 @@ test("refresh accepts an absolute publish report path", async () => {
|
||||
assert.equal(payload.services[0].componentInputHash, `${String(1).padStart(64, "a")}`);
|
||||
});
|
||||
|
||||
test("refresh is read-only by default", async () => {
|
||||
const commitId = await git(["rev-parse", "HEAD"]);
|
||||
const shortCommitId = await git(["rev-parse", "--short=7", "HEAD"]);
|
||||
const tempDir = await mkdtemp(path.join(os.tmpdir(), "hwlab-refresh-default-readonly-"));
|
||||
const reportPath = path.join(tempDir, "dev-artifacts.json");
|
||||
await writeFile(reportPath, `${JSON.stringify({
|
||||
reportVersion: "v1",
|
||||
taskId: "g14-artifact-publish",
|
||||
commitId: shortCommitId,
|
||||
artifactPublish: {
|
||||
status: "published",
|
||||
mode: "publish",
|
||||
sourceCommitId: commitId,
|
||||
registryPrefix: "127.0.0.1:5000/hwlab",
|
||||
serviceCount: SERVICE_IDS.length,
|
||||
requiredServiceCount: SERVICE_IDS.length,
|
||||
disabledServiceCount: 0,
|
||||
publishedCount: SERVICE_IDS.length,
|
||||
publishPlan: {
|
||||
version: "v2",
|
||||
services: SERVICE_IDS.map((serviceId, index) => ({
|
||||
serviceId,
|
||||
required: true,
|
||||
digest: digestFor(index),
|
||||
image: `127.0.0.1:5000/hwlab/${serviceId}:${shortCommitId}`,
|
||||
imageTag: shortCommitId
|
||||
}))
|
||||
},
|
||||
services: SERVICE_IDS.map((serviceId, index) => ({
|
||||
serviceId,
|
||||
status: "published",
|
||||
artifactRequired: true,
|
||||
image: `127.0.0.1:5000/hwlab/${serviceId}:${shortCommitId}`,
|
||||
imageTag: shortCommitId,
|
||||
digest: digestFor(index),
|
||||
repositoryDigest: `127.0.0.1:5000/hwlab/${serviceId}@${digestFor(index)}`
|
||||
}))
|
||||
}
|
||||
}, null, 2)}\n`);
|
||||
|
||||
const result = await execFileAsync(process.execPath, [
|
||||
"scripts/refresh-artifact-catalog.mjs",
|
||||
"--target-ref",
|
||||
"HEAD",
|
||||
"--publish-report",
|
||||
reportPath
|
||||
], {
|
||||
cwd: repoRoot,
|
||||
timeout: 15000,
|
||||
maxBuffer: 10 * 1024 * 1024
|
||||
});
|
||||
const payload = JSON.parse(result.stdout);
|
||||
assert.equal(payload.status, "published");
|
||||
assert.deepEqual(payload.wrote, []);
|
||||
assert.equal(payload.deployTruthPolicy, "deploy.json is human-authored runtime config; artifact promotion must not rewrite it");
|
||||
});
|
||||
|
||||
test("refresh keeps reused service image tags from the publish report", async () => {
|
||||
const commitId = await git(["rev-parse", "HEAD"]);
|
||||
const shortCommitId = await git(["rev-parse", "--short=7", "HEAD"]);
|
||||
|
||||
@@ -98,7 +98,7 @@ export function evaluateArtifactRuntimeReadiness({
|
||||
pass: commitsMatch(catalog.commitId, target.commitId),
|
||||
type: "observability_blocker",
|
||||
summary: `Artifact catalog commit=${catalog.shortCommitId}; target=${target.shortCommitId}.`,
|
||||
nextTask: "Refresh desired-state and artifact catalog identity to latest origin/main before apply."
|
||||
nextTask: "Do not refresh source desired-state. Let G14 Tekton promotion write artifact catalog identity to G14-gitops, then verify Argo/runtime revision."
|
||||
});
|
||||
addCheck(checks, {
|
||||
id: "artifact-report-catalog-match",
|
||||
@@ -119,7 +119,7 @@ export function evaluateArtifactRuntimeReadiness({
|
||||
pass: desiredState.matchesTarget,
|
||||
type: "observability_blocker",
|
||||
summary: `Desired-state deploy=${desiredState.deployCommitId}; target=${target.shortCommitId}; convergence=${desiredState.targetConvergence.state}; pending=${desiredState.targetConvergence.pendingTargetFields}.`,
|
||||
nextTask: `Run node scripts/deploy-desired-state-plan.mjs --promotion-commit ${target.shortCommitId} --check after refreshing desired-state for latest origin/main.`
|
||||
nextTask: `Run node scripts/deploy-desired-state-plan.mjs --promotion-commit ${target.shortCommitId} --check as a read-only review, then rely on G14 Tekton promotion for catalog writes.`
|
||||
});
|
||||
addCheck(checks, {
|
||||
id: "rollout-read-access",
|
||||
@@ -140,7 +140,7 @@ export function evaluateArtifactRuntimeReadiness({
|
||||
pass: apiRuntime.observed && commitsMatch(apiRuntime.commitId, target.commitId),
|
||||
type: "runtime_blocker",
|
||||
summary: `API /health/live commit=${apiRuntime.shortCommitId}; target=${target.shortCommitId}.`,
|
||||
nextTask: "After publish and desired-state refresh, run the authorized DEV rollout path and re-observe /health/live."
|
||||
nextTask: "After publish and GitOps promotion, verify Argo DEV rollout and re-observe /health/live."
|
||||
});
|
||||
addCheck(checks, {
|
||||
id: "api-runtime-artifact-match",
|
||||
|
||||
@@ -709,8 +709,8 @@ function targetCommands(target) {
|
||||
if (target.targetRef) {
|
||||
commands.push(
|
||||
`node scripts/deploy-desired-state-plan.mjs --target-ref ${target.targetRef} --pretty`,
|
||||
`node scripts/refresh-artifact-catalog.mjs --target-ref ${target.targetRef} --blocked`,
|
||||
`node scripts/refresh-artifact-catalog.mjs --target-ref ${target.targetRef} --publish-report ${artifactReportPath}`
|
||||
`node scripts/refresh-artifact-catalog.mjs --target-ref ${target.targetRef} --blocked --no-write`,
|
||||
`node scripts/refresh-artifact-catalog.mjs --target-ref ${target.targetRef} --publish-report ${artifactReportPath} --no-write`
|
||||
);
|
||||
}
|
||||
return commands;
|
||||
@@ -971,7 +971,7 @@ export async function buildDesiredStatePlan(options = {}) {
|
||||
humanAuthoredTruth: [deployPath, workloadsPath],
|
||||
artifactIdentityTruth: [catalogPath],
|
||||
nonAuthoritativeEvidence: [artifactReportPath],
|
||||
note: "This planner reviews source desired-state only. deploy.json is human-authored config; artifact-catalog carries generated image identity. It does not prove image existence, registry reachability, a real DEV apply, or M3 DEV-LIVE hardware-loop evidence."
|
||||
note: "This planner is read-only. deploy.json is human-authored config; artifact-catalog carries generated image identity and is written by G14 Tekton promotion only to G14-gitops. It does not prove image existence, registry reachability, a real DEV apply, or M3 DEV-LIVE hardware-loop evidence."
|
||||
},
|
||||
cloudApiDb: cloudApiDb ?? {
|
||||
status: "blocked",
|
||||
|
||||
@@ -465,8 +465,8 @@ async function artifactIdentityFor({ deploy, catalog, artifactReport, targetComm
|
||||
matchesSource: targetCoverage.covered && catalogMatchesSource && servicesMatchSource,
|
||||
publishVerified,
|
||||
refreshCommands: {
|
||||
blocked: `node scripts/refresh-artifact-catalog.mjs --target-ref ${targetRef} --blocked`,
|
||||
published: `node scripts/refresh-artifact-catalog.mjs --target-ref ${targetRef} --publish-report ${defaultArtifactReportPath}`
|
||||
blocked: `node scripts/refresh-artifact-catalog.mjs --target-ref ${targetRef} --blocked --no-write`,
|
||||
published: `node scripts/refresh-artifact-catalog.mjs --target-ref ${targetRef} --publish-report ${defaultArtifactReportPath} --no-write`
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user