fix: enable v02 env reuse code-only rollout
This commit is contained in:
@@ -1994,6 +1994,7 @@ function artifactRecordForCatalogReuse({ service, catalogService, commitId }) {
|
||||
imageTag,
|
||||
buildCreatedAt: catalogService?.buildCreatedAt ?? null,
|
||||
buildSource: catalogService?.buildSource ?? null,
|
||||
buildBackend: "reused-catalog",
|
||||
digest,
|
||||
repositoryDigest: repositoryDigestFor(image, digest),
|
||||
reusedFrom: null,
|
||||
@@ -2040,6 +2041,7 @@ function artifactRecordForEnvReuseCatalogReuse({ service, catalogService, commit
|
||||
bootSh: service.bootSh ?? catalogService?.bootSh ?? `deploy/runtime/boot/${service.serviceId}.sh`,
|
||||
buildCreatedAt: catalogService?.buildCreatedAt ?? null,
|
||||
buildSource: catalogService?.buildSource ?? null,
|
||||
buildBackend: "reused-env-catalog",
|
||||
repositoryDigest: catalogService?.repositoryDigest ?? repositoryDigestFor(environmentImage, environmentDigest),
|
||||
bootEnvEvidence: bootEnvEvidence({ service, commitId, environmentImage, environmentDigest })
|
||||
};
|
||||
@@ -2092,11 +2094,15 @@ async function readExternalServiceArtifacts({ dir, services, commitId }) {
|
||||
const artifacts = new Map();
|
||||
const blockers = [];
|
||||
for (const service of services) {
|
||||
const buildRequired = service.buildRequired === true || service.ciBuildRequired === true;
|
||||
const reportPath = externalServiceReportPath(dir, service.serviceId);
|
||||
let report;
|
||||
try {
|
||||
report = JSON.parse(await readFile(reportPath, "utf8"));
|
||||
} catch (error) {
|
||||
if (!buildRequired) {
|
||||
continue;
|
||||
}
|
||||
blockers.push(blocker({
|
||||
type: "environment_blocker",
|
||||
scope: service.serviceId,
|
||||
@@ -2119,11 +2125,11 @@ async function readExternalServiceArtifacts({ dir, services, commitId }) {
|
||||
|
||||
const artifact = artifactRecordFromExternalReport({ service, record, reportPath });
|
||||
artifacts.set(service.serviceId, artifact);
|
||||
if (artifact.status !== "published" || !shaDigestPattern.test(artifact.digest ?? "")) {
|
||||
if (!publishReadyStatuses.has(artifact.status) || !shaDigestPattern.test(artifact.digest ?? "")) {
|
||||
blockers.push(blocker({
|
||||
type: "environment_blocker",
|
||||
scope: service.serviceId,
|
||||
summary: `per-service artifact report ${reportPath} is not a verified published image for ${service.serviceId}`,
|
||||
summary: `per-service artifact report ${reportPath} is not a verified published/reused image for ${service.serviceId}`,
|
||||
next: "Inspect the corresponding service TaskRun logs and rerun the failed service build."
|
||||
}));
|
||||
}
|
||||
@@ -2280,6 +2286,7 @@ function plannerFieldsFor(servicePlan) {
|
||||
bootRepo: servicePlan.bootRepo ?? null,
|
||||
bootCommit: servicePlan.bootCommit ?? null,
|
||||
bootSh: servicePlan.bootSh ?? null,
|
||||
buildRequired: servicePlan.buildRequired ?? servicePlan.affected ?? false,
|
||||
environmentImage: servicePlan.environmentImage ?? null,
|
||||
environmentDigest: servicePlan.environmentDigest ?? null,
|
||||
dockerfileHash: servicePlan.dockerfileHash ?? null,
|
||||
@@ -2312,6 +2319,8 @@ function ciPlanReportSummary(ciPlan) {
|
||||
changedPathSummary: ciPlan.changedPathSummary,
|
||||
imageBuildRequired: ciPlan.imageBuildRequired,
|
||||
affectedServices: ciPlan.affectedServices,
|
||||
rolloutServices: ciPlan.rolloutServices ?? ciPlan.affectedServices,
|
||||
buildServices: ciPlan.buildServices ?? ciPlan.affectedServices,
|
||||
reusedServices: ciPlan.reusedServices,
|
||||
buildSkippedCount: ciPlan.buildSkippedCount,
|
||||
ciCdPlan: ciPlan.ciCdPlan
|
||||
@@ -2569,6 +2578,7 @@ async function main() {
|
||||
const producer = g14ArtifactProducer(process.env);
|
||||
const ciPlan = await createG14CiPlan({
|
||||
repoRoot,
|
||||
lane: args.lane,
|
||||
targetRef: "HEAD",
|
||||
deployJsonPath: args.deployPath,
|
||||
artifactCatalogPath: effectiveCatalogPath,
|
||||
@@ -2579,11 +2589,10 @@ async function main() {
|
||||
const services = enrichServicesWithCiPlan(await resolveServices(args.services, catalog), ciPlan);
|
||||
const catalogByServiceId = new Map((catalog?.services ?? []).map((service) => [service.serviceId, service]));
|
||||
const affectedServiceIds = new Set(ciPlan?.affectedServices ?? []);
|
||||
const buildServiceIds = new Set(
|
||||
services
|
||||
.filter((service) => service.artifactRequired && (service.envReuse ? service.envChanged === true : affectedServiceIds.has(service.serviceId)))
|
||||
.map((service) => service.serviceId)
|
||||
);
|
||||
const plannedBuildServices = Array.isArray(ciPlan?.buildServices) ? ciPlan.buildServices : null;
|
||||
const buildServiceIds = new Set(plannedBuildServices ?? services
|
||||
.filter((service) => service.artifactRequired && (service.envReuse ? service.envChanged === true : affectedServiceIds.has(service.serviceId)))
|
||||
.map((service) => service.serviceId));
|
||||
|
||||
const preflightBuildServiceIds = args.externalServiceReportDir || args.externalServiceResultsEnv ? new Set() : buildServiceIds;
|
||||
let blockers = await preflight({ args, services, catalog, deployManifest, baseImagePreflight, registryCapabilities, buildServiceIds: preflightBuildServiceIds });
|
||||
|
||||
@@ -90,11 +90,12 @@ test("global change classifier distinguishes gitops-only and test-only", () => {
|
||||
|
||||
test("v02 planner marks device-pod code-only change as env reuse rollout", async () => {
|
||||
const repo = await createFixtureRepo({ includeDevicePod: true });
|
||||
const initialSha = (await git(repo, ["rev-parse", "HEAD"])).stdout.trim();
|
||||
const initialPlan = await createG14CiPlan({
|
||||
repoRoot: repo,
|
||||
lane: "v02",
|
||||
baseRef: "HEAD",
|
||||
targetRef: "HEAD",
|
||||
targetRef: initialSha,
|
||||
artifactCatalogPath: "deploy/artifact-catalog.v02.json",
|
||||
services: ["hwlab-device-pod"]
|
||||
});
|
||||
@@ -123,8 +124,15 @@ test("v02 planner marks device-pod code-only change as env reuse rollout", async
|
||||
assert.equal(devicePod.runtimeMode, "env-reuse-git-mirror-checkout");
|
||||
assert.equal(devicePod.envChanged, false);
|
||||
assert.equal(devicePod.codeChanged, true);
|
||||
assert.equal(devicePod.buildRequired, false);
|
||||
assert.equal(devicePod.bootSh, "deploy/runtime/boot/hwlab-device-pod.sh");
|
||||
assert.deepEqual(plan.affectedServices, ["hwlab-device-pod"]);
|
||||
assert.deepEqual(plan.rolloutServices, ["hwlab-device-pod"]);
|
||||
assert.deepEqual(plan.buildServices, []);
|
||||
assert.equal(plan.imageBuildRequired, false);
|
||||
assert.deepEqual(plan.ciCdPlan.willBuild, []);
|
||||
assert.deepEqual(plan.ciCdPlan.willRollout, ["hwlab-device-pod"]);
|
||||
assert.equal(plan.ciCdPlan.noImageBuildReason, "env-reuse-code-only-rollout");
|
||||
});
|
||||
|
||||
async function createFixtureRepo(options = {}) {
|
||||
|
||||
@@ -235,7 +235,6 @@ function parseArgs(argv) {
|
||||
if (args.lane === "v02") {
|
||||
assert.equal(args.sourceBranch, "v0.2", "v02 source branch must be v0.2");
|
||||
assert.equal(args.gitopsBranch, "v0.2-gitops", "v02 GitOps branch must be v0.2-gitops");
|
||||
assert.equal(args.catalogPath, "deploy/artifact-catalog.v02.json", "v02 catalog path must be deploy/artifact-catalog.v02.json");
|
||||
}
|
||||
return args;
|
||||
}
|
||||
@@ -761,7 +760,7 @@ function transformWorkloads({ workloads, deploy, catalog, source, registryPrefix
|
||||
if (!podTemplate?.spec?.containers) continue;
|
||||
const templateServiceId = serviceIdForWorkload(item, podTemplate.spec.containers[0]);
|
||||
const templateArtifact = runtimeArtifactForService({ catalog, serviceId: templateServiceId, source, registryPrefix, useDeployImages, digestPin });
|
||||
const templateSourceCommit = source.full;
|
||||
const templateSourceCommit = profile === "v02" ? (templateArtifact.commit ?? source.full) : source.full;
|
||||
const templateArtifactCommit = templateArtifact.commit;
|
||||
label(podTemplate.metadata ??= {}, {
|
||||
...stableRuntimeLabels,
|
||||
@@ -807,7 +806,7 @@ function transformWorkloads({ workloads, deploy, catalog, source, registryPrefix
|
||||
}
|
||||
upsertEnv(container.env, "HWLAB_GITOPS_TARGET", gitopsTarget);
|
||||
upsertEnv(container.env, "HWLAB_GITOPS_PROFILE", profileLabel);
|
||||
upsertEnv(container.env, "HWLAB_GITOPS_SOURCE_COMMIT", source.full);
|
||||
upsertEnv(container.env, "HWLAB_GITOPS_SOURCE_COMMIT", profile === "v02" ? runtimeCommit : source.full);
|
||||
if (bootMetadata) {
|
||||
upsertEnv(container.env, "HWLAB_RUNTIME_MODE", bootMetadata.runtimeMode);
|
||||
upsertEnv(container.env, "HWLAB_BOOT_REPO", bootMetadata.bootRepo);
|
||||
@@ -1239,6 +1238,7 @@ const plan = JSON.parse(fs.readFileSync("/workspace/source/ci-plan.json", "utf8"
|
||||
const selected = String(process.env.HWLAB_SELECTED_SERVICES || "").split(",").map((item) => item.trim()).filter(Boolean);
|
||||
const allServices = selected.length > 0 ? selected : ${JSON.stringify(defaultServiceIds)};
|
||||
const affected = new Set(plan.affectedServices || []);
|
||||
const plannedBuildServices = Array.isArray(plan.buildServices) ? new Set(plan.buildServices) : null;
|
||||
const selectedSet = new Set(selected);
|
||||
const byService = new Map((plan.services || []).map((service) => [service.serviceId, service]));
|
||||
const entries = allServices.map((serviceId) => {
|
||||
@@ -1246,11 +1246,12 @@ const entries = allServices.map((serviceId) => {
|
||||
const serviceSelected = selectedSet.has(serviceId);
|
||||
const rolloutAffected = serviceSelected && affected.has(serviceId);
|
||||
const envReuse = service.runtimeMode === "env-reuse-git-mirror-checkout" || service.envReuse === true;
|
||||
const buildRequired = envReuse ? service.envChanged === true : rolloutAffected;
|
||||
const buildRequired = serviceSelected && (plannedBuildServices ? plannedBuildServices.has(serviceId) : (envReuse ? service.envChanged === true : rolloutAffected));
|
||||
return {
|
||||
serviceId,
|
||||
selected: serviceSelected,
|
||||
affected: buildRequired,
|
||||
buildRequired,
|
||||
rolloutAffected,
|
||||
runtimeMode: service.runtimeMode || "service-image",
|
||||
envChanged: service.envChanged ?? null,
|
||||
@@ -1263,12 +1264,14 @@ for (const entry of entries) {
|
||||
fs.writeFileSync("/workspace/source/affected-services.json", JSON.stringify({
|
||||
sourceCommitId: plan.sourceCommitId,
|
||||
affectedServices: plan.affectedServices || [],
|
||||
rolloutServices: plan.rolloutServices || plan.affectedServices || [],
|
||||
buildServices: plan.buildServices || entries.filter((entry) => entry.buildRequired).map((entry) => entry.serviceId),
|
||||
reusedServices: plan.reusedServices || [],
|
||||
buildSkippedCount: plan.buildSkippedCount || 0,
|
||||
services: plan.services || [],
|
||||
entries
|
||||
}, null, 2) + String.fromCharCode(10));
|
||||
console.log(JSON.stringify({ event: "g14-ci-plan", sourceCommitId: plan.sourceCommitId, affectedServices: plan.affectedServices || [], reusedServices: plan.reusedServices || [], buildSkippedCount: plan.buildSkippedCount || 0 }));
|
||||
console.log(JSON.stringify({ event: "g14-ci-plan", sourceCommitId: plan.sourceCommitId, affectedServices: plan.affectedServices || [], rolloutServices: plan.rolloutServices || plan.affectedServices || [], buildServices: plan.buildServices || [], reusedServices: plan.reusedServices || [], buildSkippedCount: plan.buildSkippedCount || 0 }));
|
||||
NODE
|
||||
`;
|
||||
}
|
||||
@@ -1292,6 +1295,7 @@ export HWLAB_ARTIFACT_LANE="$(params.lane)"
|
||||
export HWLAB_ARTIFACT_CATALOG_PATH="$(params.catalog-path)"
|
||||
export HWLAB_DEPLOY_MANIFEST_PATH="deploy/deploy.json"
|
||||
export HWLAB_ARTIFACT_IMAGE_TAG_MODE="$(params.image-tag-mode)"
|
||||
mkdir -p /workspace/source/service-results
|
||||
if [ -s /workspace/source/affected-services.json ] && ! node -e 'const fs=require("node:fs"); const p=JSON.parse(fs.readFileSync("/workspace/source/affected-services.json","utf8")); const service=process.argv[1]; const item=(p.entries||[]).find((entry)=>entry.serviceId===service); process.exit(item && item.affected ? 0 : 1);' "$(params.service-id)"; then
|
||||
node - "$(params.service-id)" <<'NODE'
|
||||
const fs = require("node:fs");
|
||||
@@ -1365,7 +1369,7 @@ if [ "$buildkit_ready" != "1" ]; then
|
||||
echo '{"event":"buildkit-sidecar-not-ready","serviceId":"'"$(params.service-id)"'","addr":"'"$HWLAB_BUILDKIT_ADDR"'"}' >&2
|
||||
exit 1
|
||||
fi
|
||||
node scripts/g14-artifact-publish.mjs --publish --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-json deploy/deploy.json --image-tag-mode "$(params.image-tag-mode)" --registry-prefix "$(params.registry-prefix)" --no-report --tekton-results-dir /tekton/results --quiet-build --concurrency 1 --services "$(params.service-id)" --buildkit-command /workspace/buildkit-bin/buildctl --buildkit-addr "$HWLAB_BUILDKIT_ADDR"
|
||||
node scripts/g14-artifact-publish.mjs --publish --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-json deploy/deploy.json --image-tag-mode "$(params.image-tag-mode)" --registry-prefix "$(params.registry-prefix)" --report "/workspace/source/service-results/$(params.service-id).json" --tekton-results-dir /tekton/results --quiet-build --concurrency 1 --services "$(params.service-id)" --buildkit-command /workspace/buildkit-bin/buildctl --buildkit-addr "$HWLAB_BUILDKIT_ADDR"
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1386,7 +1390,7 @@ export HWLAB_ARTIFACT_LANE="$(params.lane)"
|
||||
export HWLAB_ARTIFACT_CATALOG_PATH="$(params.catalog-path)"
|
||||
export HWLAB_DEPLOY_MANIFEST_PATH="deploy/deploy.json"
|
||||
export HWLAB_ARTIFACT_IMAGE_TAG_MODE="$(params.image-tag-mode)"
|
||||
node scripts/g14-artifact-publish.mjs --publish --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-json deploy/deploy.json --image-tag-mode "$(params.image-tag-mode)" --registry-prefix "$(params.registry-prefix)" --report /workspace/source/dev-artifacts.json --quiet-build --concurrency 1 --services "$(params.services)" --external-service-results-env
|
||||
node scripts/g14-artifact-publish.mjs --publish --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-json deploy/deploy.json --image-tag-mode "$(params.image-tag-mode)" --registry-prefix "$(params.registry-prefix)" --report /workspace/source/dev-artifacts.json --quiet-build --concurrency 1 --services "$(params.services)" --external-service-report-dir /workspace/source/service-results
|
||||
node scripts/refresh-artifact-catalog.mjs --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-json deploy/deploy.json --image-tag-mode "$(params.image-tag-mode)" --target-ref HEAD --publish-report /workspace/source/dev-artifacts.json --no-write
|
||||
`;
|
||||
}
|
||||
@@ -2140,6 +2144,7 @@ function perServiceBuildTask(serviceId, { runAfter = ["plan-artifacts"] } = {})
|
||||
name: buildTaskName(serviceId),
|
||||
runAfter,
|
||||
workspaces: [{ name: "source", workspace: "source" }],
|
||||
when: [{ input: `$(tasks.plan-artifacts.results.${affectedResultName(serviceId)})`, operator: "in", values: ["true"] }],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "revision" },
|
||||
@@ -2191,11 +2196,10 @@ function collectArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
{ name: "image-tag-mode" },
|
||||
{ name: "registry-prefix" },
|
||||
{ name: "services" },
|
||||
{ name: "base-image" },
|
||||
...serviceResultParams(serviceIds)
|
||||
{ name: "base-image" }
|
||||
],
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [{ name: "collect", image: ciToolsRunnerImage, env: [...proxyEnv(), ...serviceResultEnv(serviceIds)], script: collectArtifactsScript() }]
|
||||
steps: [{ name: "collect", image: ciToolsRunnerImage, env: proxyEnv(), script: collectArtifactsScript() }]
|
||||
},
|
||||
params: [
|
||||
{ name: "revision", value: "$(params.revision)" },
|
||||
@@ -2204,8 +2208,7 @@ function collectArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
{ name: "image-tag-mode", value: "$(params.image-tag-mode)" },
|
||||
{ name: "registry-prefix", value: "$(params.registry-prefix)" },
|
||||
{ name: "services", value: "$(params.services)" },
|
||||
{ name: "base-image", value: "$(params.base-image)" },
|
||||
...serviceResultParamValues(serviceIds)
|
||||
{ name: "base-image", value: "$(params.base-image)" }
|
||||
]
|
||||
};
|
||||
}
|
||||
@@ -2310,10 +2313,10 @@ async function runtimeItems() {
|
||||
}
|
||||
|
||||
function runtimeSourceCommit(item) {
|
||||
return item.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/source-commit"] ||
|
||||
item.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/source-commit"] ||
|
||||
item.metadata?.labels?.["hwlab.pikastech.local/source-commit"] ||
|
||||
return item.metadata?.labels?.["hwlab.pikastech.local/source-commit"] ||
|
||||
item.metadata?.annotations?.["hwlab.pikastech.local/source-commit"] ||
|
||||
item.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/source-commit"] ||
|
||||
item.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/source-commit"] ||
|
||||
null;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
assert.match(pipeline, /node scripts\/run-bun\.mjs test cmd\/hwlab-codex-api-responses-forwarder\/main\.test\.ts/u);
|
||||
assert.doesNotMatch(pipeline, /cmd\/hwlab-codex-api-responses-forwarder\/main\.mjs/u);
|
||||
assert.match(pipeline, /process\.exitCode = 1/u);
|
||||
assert.match(pipeline, /item\.spec\?\.template\?\.metadata\?\.labels\?\.\[\\"hwlab\.pikastech\.local\/source-commit\\"\]/u);
|
||||
assert.match(pipeline, /item\.metadata\?\.labels\?\.\[\\"hwlab\.pikastech\.local\/source-commit\\"\]/u);
|
||||
|
||||
const runtimeReady = taskByName(pipelineJson, "runtime-ready");
|
||||
const runtimeReadyScript = runtimeReady.taskSpec.steps[0].script;
|
||||
@@ -113,8 +113,16 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
const task = taskByName(pipelineJson, `build-${serviceId}`);
|
||||
const expectedRunAfter = index === 0 ? ["plan-artifacts"] : [`build-${retainedServiceIds[index - 1]}`];
|
||||
assert.deepEqual(task.runAfter, expectedRunAfter);
|
||||
assert.deepEqual(task.when, [{ input: `$(tasks.plan-artifacts.results.affected-${serviceId})`, operator: "in", values: ["true"] }]);
|
||||
}
|
||||
|
||||
const collectArtifacts = taskByName(pipelineJson, "collect-artifacts");
|
||||
const collectScript = collectArtifacts.taskSpec.steps[0].script;
|
||||
assert.match(collectScript, /--external-service-report-dir \/workspace\/source\/service-results/u);
|
||||
assert.doesNotMatch(JSON.stringify(collectArtifacts), /tasks\.build-hwlab-device-pod\.results/u);
|
||||
const devicePodBuildScript = taskByName(pipelineJson, "build-hwlab-device-pod").taskSpec.steps.find((step) => step.name === "publish")?.script ?? "";
|
||||
assert.match(devicePodBuildScript, /--report "\/workspace\/source\/service-results\/\$\(params\.service-id\)\.json"/u);
|
||||
|
||||
const workloads = await readFile(path.join(outDir, "runtime-v02", "workloads.yaml"), "utf8");
|
||||
const workloadsJson = JSON.parse(workloads);
|
||||
const services = await readFile(path.join(outDir, "runtime-v02", "services.yaml"), "utf8");
|
||||
@@ -140,10 +148,8 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
assert.equal(agentWorkerEnv.some((entry) => entry.name === "HWLAB_BOOT_COMMIT"), false, "agent-worker must not be switched to env reuse by device-pod work");
|
||||
const workloadTemplates = workloadsJson.items.filter((item) => item.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/source-commit"]);
|
||||
assert.ok(workloadTemplates.length > 0, "expected rendered pod-template source labels");
|
||||
for (const item of workloadTemplates) {
|
||||
assert.equal(item.spec.template.metadata.labels["hwlab.pikastech.local/source-commit"], sourceRevision);
|
||||
assert.equal(item.spec.template.metadata.annotations["hwlab.pikastech.local/source-commit"], sourceRevision);
|
||||
}
|
||||
assert.equal(devicePod.spec.template.metadata.labels["hwlab.pikastech.local/source-commit"], sourceRevision);
|
||||
assert.equal(devicePod.spec.template.metadata.annotations["hwlab.pikastech.local/source-commit"], sourceRevision);
|
||||
assert.ok(workloadTemplates.some((item) => item.spec.template.metadata.labels["hwlab.pikastech.local/artifact-source-commit"]), "expected artifact source labels on pod templates");
|
||||
assert.doesNotMatch(workloads, /HWLAB_GATEWAY_SIMU_URL/u);
|
||||
assert.doesNotMatch(workloads, /HWLAB_BOX_SIMU_URL/u);
|
||||
@@ -152,7 +158,8 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
assert.doesNotMatch(workloads, /HWLAB_TUNNEL_CLIENT_URL/u);
|
||||
|
||||
assert.doesNotMatch(pipeline, /hwlab-gateway-simu-status/u);
|
||||
assert.match(pipeline, /hwlab-cloud-api-status/u);
|
||||
assert.doesNotMatch(pipeline, /tasks\.build-hwlab-cloud-api\.results/u);
|
||||
assert.match(pipeline, /--external-service-report-dir \/workspace\/source\/service-results/u);
|
||||
|
||||
const application = await readFile(path.join(outDir, "argocd", "application-v02.yaml"), "utf8");
|
||||
assert.match(application, /"prune": true/u);
|
||||
|
||||
@@ -145,11 +145,12 @@ export async function createG14CiPlan(options = {}) {
|
||||
const environmentDigest = envReuse ? environmentDigestFromCatalog(catalogRecord) : null;
|
||||
const environmentReady = envReuse && /^sha256:[a-f0-9]{64}$/u.test(environmentDigest ?? "") && Boolean(environmentImage);
|
||||
const envChanged = envReuse ? relevantEnvMatches.length > 0 || !environmentReady || catalogRecord?.environmentInputHash !== environmentInputHash : null;
|
||||
const codeChanged = envReuse ? relevantCodeMatches.length > 0 || catalogRecord?.codeInputHash !== codeInputHash || catalogRecord?.bootCommit !== sourceCommitId : null;
|
||||
const codeChanged = envReuse ? relevantCodeMatches.length > 0 || catalogRecord?.codeInputHash !== codeInputHash : null;
|
||||
const catalogReuse = envReuse ? envReuseCandidate(catalogRecord, envChanged) : reuseCandidate(catalogRecord, imageRelevantChangedPaths.length > 0);
|
||||
const affected = envReuse
|
||||
? Boolean(envChanged || codeChanged)
|
||||
: imageRelevantChangedPaths.length > 0 || catalogReuse.status === "candidate-no-catalog" || catalogReuse.status === "candidate-unverified-digest";
|
||||
const buildRequired = envReuse ? envChanged === true : affected;
|
||||
const componentInputPaths = uniqueSorted([
|
||||
...model.componentPaths,
|
||||
...model.sharedPaths,
|
||||
@@ -183,6 +184,7 @@ export async function createG14CiPlan(options = {}) {
|
||||
buildArgsHash,
|
||||
changedPaths: imageRelevantChangedPaths,
|
||||
affected,
|
||||
buildRequired,
|
||||
runtimeMode: envReuse ? V02_ENV_REUSE_RUNTIME_MODE : "service-image",
|
||||
envReuse,
|
||||
envChanged,
|
||||
@@ -204,6 +206,7 @@ export async function createG14CiPlan(options = {}) {
|
||||
}
|
||||
|
||||
const affectedServices = services.filter((service) => service.affected).map((service) => service.serviceId);
|
||||
const buildServices = services.filter((service) => service.buildRequired).map((service) => service.serviceId);
|
||||
const reusedServices = services.filter((service) => !service.affected).map((service) => service.serviceId);
|
||||
return {
|
||||
planVersion: G14_CI_PLAN_VERSION,
|
||||
@@ -222,6 +225,7 @@ export async function createG14CiPlan(options = {}) {
|
||||
serviceIdSource: serviceIdResolution.source,
|
||||
v02EnvReuseServiceIds: [...envReuseServices],
|
||||
defaultComponentLazyBuild: true,
|
||||
envReuseCodeOnlyFastLane: true,
|
||||
fullBuildFallback: false
|
||||
},
|
||||
inputs: {
|
||||
@@ -231,16 +235,21 @@ export async function createG14CiPlan(options = {}) {
|
||||
},
|
||||
changedPaths: normalizedChangedPaths,
|
||||
changedPathSummary: globalChange,
|
||||
imageBuildRequired: affectedServices.length > 0,
|
||||
imageBuildRequired: buildServices.length > 0,
|
||||
affectedServices,
|
||||
rolloutServices: affectedServices,
|
||||
buildServices,
|
||||
reusedServices,
|
||||
buildSkippedCount: reusedServices.length,
|
||||
buildSkippedCount: services.length - buildServices.length,
|
||||
services,
|
||||
ciCdPlan: {
|
||||
willBuild: affectedServices,
|
||||
willBuild: buildServices,
|
||||
willRollout: affectedServices,
|
||||
willReuse: reusedServices,
|
||||
willRunGitopsPromote: globalChange.gitopsOnly || affectedServices.length > 0,
|
||||
noImageBuildReason: affectedServices.length === 0 ? globalChange.summary : null
|
||||
noImageBuildReason: buildServices.length === 0
|
||||
? (affectedServices.length > 0 ? "env-reuse-code-only-rollout" : globalChange.summary)
|
||||
: null
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -354,7 +363,7 @@ export async function hashGitPaths(repoRoot, targetRef, paths, options = {}) {
|
||||
return !options.skipPath?.(filePath);
|
||||
})
|
||||
.sort();
|
||||
return stableHash({ targetRef, entries: lines });
|
||||
return stableHash({ entries: lines });
|
||||
}
|
||||
|
||||
export async function lastCommitForPaths(repoRoot, targetRef, paths) {
|
||||
|
||||
Reference in New Issue
Block a user