diff --git a/config/selfmedia.yaml b/config/selfmedia.yaml index 2889bf8c..c1d32448 100644 --- a/config/selfmedia.yaml +++ b/config/selfmedia.yaml @@ -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 diff --git a/scripts/src/selfmedia-config.test.ts b/scripts/src/selfmedia-config.test.ts new file mode 100644 index 00000000..f2c811e7 --- /dev/null +++ b/scripts/src/selfmedia-config.test.ts @@ -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", + }); + }); +}); diff --git a/scripts/src/selfmedia-config.ts b/scripts/src/selfmedia-config.ts index 8c1d3157..9011150f 100644 --- a/scripts/src/selfmedia-config.ts +++ b/scripts/src/selfmedia-config.ts @@ -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; }; @@ -159,6 +163,7 @@ function parseDeliveryTarget(id: string, value: Record): 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): 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): SelfMe mode: "buildkit-state-host-path", statePath: absolutePath(envReuse.statePath, `${path}.build.envReuse.statePath`), identityFiles, + semanticPackageManifests: { + policyFile: packageManifestPolicyFile, + renderer: packageManifestRenderer, + }, }, proxy: structuredClone(proxy), }, diff --git a/scripts/src/selfmedia-delivery-renderer.ts b/scripts/src/selfmedia-delivery-renderer.ts index c6c97ea4..8321f912 100644 --- a/scripts/src/selfmedia-delivery-renderer.ts +++ b/scripts/src/selfmedia-delivery-renderer.ts @@ -204,7 +204,14 @@ function prepareBuildkitStep(target: SelfMediaDeliveryTarget): Record { - 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: [