Merge pull request #2074 from pikasTech/fix/2065-selfmedia-semantic-env-identity
Pipelines as Code CI / hwlab-web-probe-sentinel-nc01- Success
Pipelines as Code CI / platform-infra-gitea-nc01- Success
Pipelines as Code CI / unidesk-host- Success

fix: 按依赖语义计算 SELFMEDIA env identity
This commit is contained in:
Lyon
2026-07-15 03:29:23 +08:00
committed by GitHub
4 changed files with 55 additions and 5 deletions
+3 -2
View File
@@ -40,9 +40,7 @@ delivery:
mode: buildkit-state-host-path
statePath: /var/lib/unidesk/selfmedia-ci/buildkit-state
identityFiles:
- package.json
- bun.lock
- web/package.json
- web/bun.lock
- config/tools.yaml
- deploy/Dockerfile
@@ -52,6 +50,9 @@ delivery:
- scripts/src/tools-config.ts
- scripts/src/tools-install.ts
- scripts/src/types.ts
semanticPackageManifests:
policyFile: config/env-identity.yaml
renderer: deploy/scripts/render-install-manifests.ts
proxy:
http: http://127.0.0.1:10808
https: http://127.0.0.1:10808
+16
View File
@@ -0,0 +1,16 @@
import { describe, expect, test } from "bun:test";
import { resolveSelfMediaDeliveryTarget } from "./selfmedia-config";
describe("selfmedia env reuse config", () => {
test("separates semantic package manifests from raw identity files", () => {
const target = resolveSelfMediaDeliveryTarget("NC01");
expect(target.build.envReuse.identityFiles).not.toContain("package.json");
expect(target.build.envReuse.identityFiles).not.toContain("web/package.json");
expect(target.build.envReuse.semanticPackageManifests).toEqual({
policyFile: "config/env-identity.yaml",
renderer: "deploy/scripts/render-install-manifests.ts",
});
});
});
+20
View File
@@ -39,6 +39,10 @@ export interface SelfMediaDeliveryTarget {
readonly mode: "buildkit-state-host-path";
readonly statePath: string;
readonly identityFiles: readonly string[];
readonly semanticPackageManifests: {
readonly policyFile: string;
readonly renderer: string;
};
};
readonly proxy: Record<string, unknown>;
};
@@ -159,6 +163,7 @@ function parseDeliveryTarget(id: string, value: Record<string, unknown>): SelfMe
const source = record(value.source, `${path}.source`);
const build = record(value.build, `${path}.build`);
const envReuse = record(build.envReuse, `${path}.build.envReuse`);
const semanticPackageManifests = record(envReuse.semanticPackageManifests, `${path}.build.envReuse.semanticPackageManifests`);
const proxy = record(build.proxy, `${path}.build.proxy`);
const gitops = record(value.gitops, `${path}.gitops`);
const deployment = record(value.deployment, `${path}.deployment`);
@@ -182,6 +187,17 @@ function parseDeliveryTarget(id: string, value: Record<string, unknown>): SelfMe
const identityFiles = stringArray(envReuse.identityFiles, `${path}.build.envReuse.identityFiles`)
.map((item, index) => relativePath(item, `${path}.build.envReuse.identityFiles[${index}]`));
if (identityFiles.length === 0 || new Set(identityFiles).size !== identityFiles.length) throw new Error(`${path}.build.envReuse.identityFiles must be non-empty and unique`);
const packageManifestPolicyFile = relativePath(
semanticPackageManifests.policyFile,
`${path}.build.envReuse.semanticPackageManifests.policyFile`,
);
const packageManifestRenderer = relativePath(
semanticPackageManifests.renderer,
`${path}.build.envReuse.semanticPackageManifests.renderer`,
);
if (packageManifestPolicyFile === packageManifestRenderer) {
throw new Error(`${path}.build.envReuse.semanticPackageManifests paths must be distinct`);
}
return {
id,
node,
@@ -217,6 +233,10 @@ function parseDeliveryTarget(id: string, value: Record<string, unknown>): SelfMe
mode: "buildkit-state-host-path",
statePath: absolutePath(envReuse.statePath, `${path}.build.envReuse.statePath`),
identityFiles,
semanticPackageManifests: {
policyFile: packageManifestPolicyFile,
renderer: packageManifestRenderer,
},
},
proxy: structuredClone(proxy),
},
+16 -3
View File
@@ -204,7 +204,14 @@ function prepareBuildkitStep(target: SelfMediaDeliveryTarget): Record<string, un
}
function envReuseStep(target: SelfMediaDeliveryTarget): Record<string, unknown> {
const identityFiles = target.build.envReuse.identityFiles.map((path) => `/workspace/source/${path}`);
const semanticPackageManifests = target.build.envReuse.semanticPackageManifests;
const semanticPolicyFile = `/workspace/source/${semanticPackageManifests.policyFile}`;
const semanticRenderer = `/workspace/source/${semanticPackageManifests.renderer}`;
const identityFiles = [
...target.build.envReuse.identityFiles.map((path) => `/workspace/source/${path}`),
semanticPolicyFile,
semanticRenderer,
];
const identityInputs = [...identityFiles, "/workspace/release/codex-version"]
.map(shellSingleQuote)
.join(" ");
@@ -217,7 +224,13 @@ set -eu
stage_started_seconds=$(date +%s)
identity_file=/home/user/.local/share/buildkit/.unidesk/selfmedia-env-identity
for input in ${identityInputs}; do test -f "$input"; done
env_identity="sha256:$(sha256sum ${identityInputs} | sha256sum | awk '{print $1}')"
rm -rf /workspace/semantic-package-manifests
bun ${shellSingleQuote(semanticRenderer)} \
--config ${shellSingleQuote(semanticPolicyFile)} \
--source-root /workspace/source \
--output-root /workspace/semantic-package-manifests
test -f /workspace/semantic-package-manifests/identity.json
env_identity="sha256:$(sha256sum ${identityInputs} /workspace/semantic-package-manifests/identity.json | sha256sum | awk '{print $1}')"
previous_identity=""
if [ -f "$identity_file" ]; then previous_identity=$(cat "$identity_file"); fi
if [ "$previous_identity" = "$env_identity" ]; then
@@ -229,7 +242,7 @@ else
fi
printf '%s\n' "$env_identity" > /workspace/env-identity
stage_finished_seconds=$(date +%s)
printf '{"ok":true,"phase":"env-reuse","envIdentity":"%s","envReuseStatus":"%s","envReuse":{"status":"%s","mode":"${target.build.envReuse.mode}","identitySource":"owning-yaml-source-artifact","previousIdentityPresent":%s},"stageTimings":{"envIdentitySeconds":%s},"valuesPrinted":false}\n' "$env_identity" "$reuse_status" "$reuse_status" "$previous_present" "$((stage_finished_seconds-stage_started_seconds))"
printf '{"ok":true,"phase":"env-reuse","envIdentity":"%s","envReuseStatus":"%s","envReuse":{"status":"%s","mode":"${target.build.envReuse.mode}","identitySource":"owning-yaml-semantic-package-manifest-source-artifact","previousIdentityPresent":%s},"stageTimings":{"envIdentitySeconds":%s},"valuesPrinted":false}\n' "$env_identity" "$reuse_status" "$reuse_status" "$previous_present" "$((stage_finished_seconds-stage_started_seconds))"
`,
securityContext: nonRootSecurity(),
volumeMounts: [