fix: 校验 artifact 复用组件输入

This commit is contained in:
Codex
2026-05-31 21:05:44 +08:00
parent b135388316
commit bfcd6722f2
3 changed files with 67 additions and 7 deletions
+20 -6
View File
@@ -177,11 +177,6 @@ export async function createG14CiPlan(options = {}) {
const environmentReady = envReuse && /^sha256:[a-f0-9]{64}$/u.test(environmentDigest ?? "") && Boolean(environmentImage);
const envChanged = envReuse ? relevantEnvMatches.length > 0 || !environmentReady : 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,
@@ -200,6 +195,14 @@ export async function createG14CiPlan(options = {}) {
runtimeKind: model.runtimeKind,
entrypoint: model.entrypoint
});
const componentInputChanged = !envReuse && typeof catalogRecord?.componentInputHash === "string" && catalogRecord.componentInputHash !== componentInputHash;
const catalogReuse = envReuse
? envReuseCandidate(catalogRecord, envChanged)
: reuseCandidate(catalogRecord, imageRelevantChangedPaths.length > 0, componentInputChanged);
const affected = envReuse
? Boolean(envChanged || codeChanged)
: imageRelevantChangedPaths.length > 0 || componentInputChanged || catalogReuse.status === "candidate-no-catalog" || catalogReuse.status === "candidate-unverified-digest";
const buildRequired = envReuse ? envChanged === true : affected;
services.push({
serviceId: model.serviceId,
runtimeKind: model.runtimeKind,
@@ -217,6 +220,7 @@ export async function createG14CiPlan(options = {}) {
changedPaths: imageRelevantChangedPaths,
affected,
buildRequired,
componentInputChanged,
runtimeMode: envReuse ? V02_ENV_REUSE_RUNTIME_MODE : "service-image",
envReuse,
envChanged,
@@ -496,6 +500,7 @@ function reasonForService({ directMatches, sharedMatches, runtimeDepMatches, bui
if (sharedMatches.some((item) => !isTestOnlyPath(item) && !isDocsOnlyPath(item))) reasons.push("shared-runtime-changed");
if (runtimeDepMatches.some((item) => !isTestOnlyPath(item) && !isDocsOnlyPath(item))) reasons.push("runtime-deps-changed");
if (buildSystemMatches.some((item) => !isTestOnlyPath(item) && !isDocsOnlyPath(item))) reasons.push("build-system-changed");
if (catalogReuse?.status === "component-input-mismatch") reasons.push("component-input-mismatch");
if (catalogReuse?.status === "candidate-no-catalog") reasons.push("catalog-record-missing");
if (catalogReuse?.status === "candidate-unverified-digest") reasons.push("catalog-digest-missing");
return reasons.length ? reasons : ["affected"];
@@ -509,9 +514,18 @@ function reasonForUnchanged(globalChange) {
return ["component-inputs-unchanged"];
}
function reuseCandidate(catalogRecord, affected) {
function reuseCandidate(catalogRecord, affected, componentInputChanged = false) {
if (affected) return { status: "not-reused", reason: "component-affected" };
if (!catalogRecord) return { status: "candidate-no-catalog", reason: "no-previous-artifact-record" };
if (componentInputChanged) {
return {
status: "component-input-mismatch",
reason: "catalog-component-input-hash-differs-from-current-plan",
image: catalogRecord.image ?? null,
digest: catalogRecord.digest ?? null,
reusedFrom: catalogRecord.componentInputHash ?? catalogRecord.commitId ?? catalogRecord.imageTag ?? null
};
}
if (!/^sha256:[a-f0-9]{64}$/u.test(catalogRecord.digest ?? "")) {
return { status: "candidate-unverified-digest", image: catalogRecord.image ?? null, digest: catalogRecord.digest ?? null };
}