diff --git a/docs/GUIX_DIFFERENCES.md b/docs/GUIX_DIFFERENCES.md index 322f40b..c94945e 100644 --- a/docs/GUIX_DIFFERENCES.md +++ b/docs/GUIX_DIFFERENCES.md @@ -294,6 +294,22 @@ Compared with Guix, this is a more explicit split between: - a mutable result/staging area for native build execution - and the immutable store identities that Fruix treats as the real promoted result +Fruix also now models native-build placement more explicitly as an executor choice. + +Current executor kinds are: + +- `host` +- `ssh-guest` +- `self-hosted` + +So instead of treating: + +- host-driven builds +- host-initiated guest builds +- guest self-hosted builds + +as three unrelated architectural forks, Fruix is moving toward one native-build result model with different executor policies attached to it. + ## Where Fruix is intentionally trying to improve on Guix's representation Fruix is not trying to improve on Guix's core semantics. Guix already got those right. diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index b69376a..678b649 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -53,6 +53,13 @@ Fruix currently has: - `/frx/store/...-fruix-native-headers-...` - `/frx/store/...-fruix-native-bootloader-...` - `/frx/store/...-fruix-native-build-result-...` +- an explicit executor model for native base builds with current executor kinds: + - `host` + - `ssh-guest` + - `self-hosted` +- end-to-end validated staged-result-plus-promotion paths for executor policies: + - `ssh-guest` + - `self-hosted` Validated boot modes still are: @@ -65,37 +72,30 @@ The validated Phase 18 installation work currently uses: ## Latest completed achievement -### 2026-04-05 — Native base builds promoted into first-class Fruix store objects +### 2026-04-06 — Native build executor model introduced and validated across two executor policies -Fruix now has a validated end-to-end path that treats guest native base-build results as **staged mutable results first**, and then promotes them into **immutable Fruix store identities**. +Fruix now has an explicit executor model for native base builds, and the same staged-result-plus-promotion flow is validated across both host-initiated guest execution and guest self-hosted execution. Highlights: -- guest self-hosted runs still record staged results under: - - `/var/lib/fruix/native-builds/` - - `/var/lib/fruix/native-builds/latest` -- those result roots now carry promotion metadata describing: - - executor / executor-version - - closure path - - source store provenance - - build policy - - artifact entries for: - - `world` - - `kernel` - - `headers` - - `bootloader` -- the host can now run: +- native base-build placement is now modeled as executor policy rather than as separate unrelated paths +- current executor kinds are: + - `host` + - `ssh-guest` + - `self-hosted` +- guest result roots now carry explicit executor metadata instead of only an ad hoc executor string +- both validated executor paths now converge on the same Fruix-native flow: + - stage mutable results under `/var/lib/fruix/native-builds/` + - emit promotion metadata with shared provenance/build-policy/artifact shape + - promote immutable identities into `/frx/store/...` +- the `ssh-guest` path now also stages promotable native-build result roots rather than only temporary build directories under `/var/tmp` +- the host can now promote both executor paths through the same command: - `fruix native-build promote RESULT_ROOT` -- promotion creates immutable `/frx/store` objects for: - - `world` - - `kernel` - - `headers` - - `bootloader` -- promotion also creates a result-bundle store object that references those artifact stores -- the validated promotion metadata now makes Fruix-native native-build identity explicit instead of leaving results only as ad hoc files under `/var/lib/fruix/native-builds/...` Validation: +- `PASS phase20-host-initiated-native-build-xcpng` +- `PASS phase20-host-initiated-native-build-store-promotion-xcpng` - `PASS phase20-self-hosted-native-build-xcpng` - `PASS phase20-native-build-store-promotion-xcpng` @@ -107,6 +107,7 @@ Reports: - `docs/reports/phase20-host-initiated-native-builds-freebsd.md` - `docs/reports/phase20-self-hosted-native-builds-freebsd.md` - `docs/reports/phase20-native-build-store-promotion-freebsd.md` +- `docs/reports/phase20-native-build-executor-model-freebsd.md` ## Recent major milestones @@ -134,12 +135,12 @@ Reports: The next practical follow-up is now clearer: -- unify host-initiated and self-hosted native-build execution behind a shared Fruix executor/result model -- make the same first-class promotion story available regardless of whether the outer loop is host-driven or guest-driven -- decide how much of result import/promotion should remain host-side versus become a more integrated Fruix deployment action +- extend the shared executor/result model from validated `ssh-guest` and `self-hosted` paths to the `host` path as well +- decide how much of result import/promotion should remain host-side versus become a more integrated Fruix action +- determine whether executor selection should become part of a higher-level Fruix native-build/deployment command surface The immediate architectural direction is no longer just “can guest self-hosting work?” It is now: -- how should Fruix represent native base builds as real first-class objects and workflows across different executors? +- how should Fruix expose executor selection, execution policy, and result promotion as one coherent operator-facing workflow? diff --git a/docs/reports/phase20-native-build-executor-model-freebsd.md b/docs/reports/phase20-native-build-executor-model-freebsd.md new file mode 100644 index 0000000..8c06ee7 --- /dev/null +++ b/docs/reports/phase20-native-build-executor-model-freebsd.md @@ -0,0 +1,202 @@ +# Post-Phase 20: native build executor model + +Date: 2026-04-06 + +## Goal + +Turn the now-proven native base-build placement options into one Fruix abstraction instead of treating them as unrelated paths. + +The desired model is: + +- same declared source identity +- same expected artifact kinds +- same staged-result shape +- same promotion/provenance shape +- different executor policy + +So the question becomes: + +- where should the build run? + +and the answer is expressed as executor policy rather than as a separate architecture each time. + +## Executor model + +Fruix now has an explicit native-build executor model with current executor kinds: + +- `host` +- `ssh-guest` +- `self-hosted` + +and intended future extension points: + +- `jail` +- `remote-builder` + +The new executor model is implemented in: + +- `modules/fruix/system/freebsd/executor.scm` + +It defines a structured executor object that records at least: + +- `kind` +- `name` +- `version` +- `properties` + +## What changed + +### 1. Structured executor metadata + +Native-build result metadata is no longer limited to a flat string such as: + +- `guest-self-hosted` + +Instead, result/promotion objects now carry a structured executor description. + +Representative executor objects now look like: + +```scheme +((kind . self-hosted) + (name . "guest-self-hosted") + (version . "4") + (properties . (...))) +``` + +or: + +```scheme +((kind . ssh-guest) + (name . "ssh-guest") + (version . "1") + (properties . (...))) +``` + +Promoted store metadata also now records compatibility fields derived from that executor object: + +- `executor-kind` +- `executor-name` +- `executor-version` + +### 2. Shared staged-result shape across executors + +Both validated executor paths now converge on the same mutable staging layout under: + +- `/var/lib/fruix/native-builds/` + +with promoted artifacts staged under: + +- `artifacts/world` +- `artifacts/kernel` +- `artifacts/headers` +- `artifacts/bootloader` + +and promotion metadata recorded in: + +- `promotion.scm` + +The heavy build work remains executor-specific, but the result shape is now shared. + +### 3. Shared immutable promotion path + +Both validated executor paths now promote through the same command: + +```sh +fruix native-build promote RESULT_ROOT +``` + +That promotion creates immutable store identities for: + +- `world` +- `kernel` +- `headers` +- `bootloader` +- result bundle + +under `/frx/store/...`. + +## Validated executor policies + +### `self-hosted` + +The self-hosted guest helper now emits the structured executor metadata directly from: + +- `/usr/local/bin/fruix-self-hosted-native-build` + +Validated self-hosted promotion flow: + +- `PASS phase20-self-hosted-native-build-xcpng` +- `PASS phase20-native-build-store-promotion-xcpng` + +Representative promoted result: + +```text +result_store=/frx/store/0423193b9bd5e652bdb9d94d077e40dfcc3e9e78-fruix-native-build-result-15.0-STABLE-guest-self-hosted +world_store=/frx/store/5f67e95058186147206ff6f5da2243a09212e358-fruix-native-world-15.0-STABLE-guest-self-hosted +kernel_store=/frx/store/3a32797cc187a90e8273f205eababae6246568d9-fruix-native-kernel-15.0-STABLE-guest-self-hosted +headers_store=/frx/store/1d54d9814461f003e91add8cd37e94ac5f3d04ce-fruix-native-headers-15.0-STABLE-guest-self-hosted +bootloader_store=/frx/store/49f4885f0f05a324ac826f2618d4c7a923ca30d2-fruix-native-bootloader-15.0-STABLE-guest-self-hosted +``` + +### `ssh-guest` + +The host-initiated guest path now also stages a shared native-build result root under: + +- `/var/lib/fruix/native-builds/` + +instead of stopping at temporary build directories alone. + +Its promotion metadata records executor policy as: + +- `kind = ssh-guest` +- `name = ssh-guest` +- `version = 1` + +with executor properties including: + +- `transport = ssh` +- `orchestrator = host` +- guest addressing / VM identity metadata + +Validated host-initiated promotion flow: + +- `PASS phase20-host-initiated-native-build-xcpng` +- `PASS phase20-host-initiated-native-build-store-promotion-xcpng` + +Representative promoted result: + +```text +result_store=/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest +world_store=/frx/store/89c7a71c3df148a1f99b13d57fd6be88243eb2cb-fruix-native-world-15.0-STABLE-ssh-guest +kernel_store=/frx/store/93bac81122022b40438d356146a6854b4ee48513-fruix-native-kernel-15.0-STABLE-ssh-guest +headers_store=/frx/store/dd7f39f526bca4849caf1eaf96ae25d29b43493c-fruix-native-headers-15.0-STABLE-ssh-guest +bootloader_store=/frx/store/78b1c6b0b5c0c2c1549f5f42f3d64b6d9293669b-fruix-native-bootloader-15.0-STABLE-ssh-guest +``` + +## Important result + +The same declared source and artifact contract now works across two different executor policies: + +- `ssh-guest` +- `self-hosted` + +while preserving the same Fruix-native staging/promotion split: + +- mutable result roots under `/var/lib/fruix/native-builds/...` +- immutable promoted identities under `/frx/store/...` + +That is the core architectural win of the executor model. + +## What is not yet fully unified + +The `host` executor kind now exists in the model, but the fully shared staged-result-plus-promotion workflow is not yet wired through the existing host-local native build path. + +So the executor model is introduced and real-VM validated across two policies, but not yet uniformly productized across every native-build entry point. + +## Result + +Fruix now treats native-build placement as executor policy rather than as an architectural fork. + +That means the next step is no longer to invent another build path from scratch. + +It is to keep extending the same executor/result/promotion model so additional execution policies can plug into the same Fruix-native object story. \ No newline at end of file diff --git a/docs/system-deployment-workflow.md b/docs/system-deployment-workflow.md index d9ef38d..7480341 100644 --- a/docs/system-deployment-workflow.md +++ b/docs/system-deployment-workflow.md @@ -337,7 +337,7 @@ Current metadata split: The promoted store objects record explicit Fruix-native metadata including at least: -- executor / executor-version +- executor kind / name / version - run-id / guest-host-name - closure path - source store provenance @@ -353,6 +353,42 @@ This is the current Fruix-native answer to the question: - where should immutable native-build identity live? - `/frx/store/...` +### Native-build executor model + +Fruix now has an explicit executor model for native base builds. + +Current executor kinds are: + +- `host` +- `ssh-guest` +- `self-hosted` + +and the intended future extension points are: + +- `jail` +- `remote-builder` + +The important change is architectural: + +- declared source identity stays the same +- expected artifact kinds stay the same +- result/promotion metadata shape stays the same +- only the executor policy changes + +So “where the build runs” is now treated as executor policy rather than as a separate native-build architecture each time. + +Current end-to-end validated executors for the staged-result-plus-promotion model are: + +- `ssh-guest` +- `self-hosted` + +Both now converge on the same Fruix-native flow: + +1. run the build under a selected executor +2. stage a result root under `/var/lib/fruix/native-builds/...` +3. emit the same promotion/provenance shape +4. promote the result into immutable `/frx/store/...` objects + ## Deployment patterns ### 1. Build-first workflow diff --git a/modules/fruix/system/freebsd.scm b/modules/fruix/system/freebsd.scm index b4ad21b..e48d702 100644 --- a/modules/fruix/system/freebsd.scm +++ b/modules/fruix/system/freebsd.scm @@ -1,6 +1,7 @@ (define-module (fruix system freebsd) #:use-module (fruix system freebsd model) #:use-module (fruix system freebsd source) + #:use-module (fruix system freebsd executor) #:use-module (fruix system freebsd build) #:use-module (fruix system freebsd media) #:re-export (user-group @@ -44,6 +45,17 @@ operating-system-root-authorized-keys validate-operating-system materialize-freebsd-source + native-build-executor + native-build-executor? + native-build-executor-ref + native-build-executor-kind + native-build-executor-name + native-build-executor-version + native-build-executor-properties + normalize-native-build-executor + host-native-build-executor + ssh-guest-native-build-executor + self-hosted-native-build-executor promote-native-build-result operating-system-closure-spec operating-system-install-spec diff --git a/modules/fruix/system/freebsd/build.scm b/modules/fruix/system/freebsd/build.scm index b9dba7b..b7dc4b9 100644 --- a/modules/fruix/system/freebsd/build.scm +++ b/modules/fruix/system/freebsd/build.scm @@ -2,6 +2,7 @@ #:use-module (fruix packages freebsd) #:use-module (fruix system freebsd model) #:use-module (fruix system freebsd source) + #:use-module (fruix system freebsd executor) #:use-module (fruix system freebsd utils) #:use-module (guix build utils) #:use-module (ice-9 format) @@ -396,6 +397,32 @@ ((_ . value) value) (#f default))) +(define (native-build-result-executor result) + (let* ((executor (native-build-result-ref result 'executor #f)) + (legacy-version (native-build-result-ref result 'executor-version "legacy"))) + (cond + ((native-build-executor? executor) + executor) + ((string? executor) + (let ((normalized (normalize-native-build-executor executor))) + `((kind . ,(native-build-executor-kind normalized)) + (name . ,(native-build-executor-name normalized)) + (version . ,legacy-version) + (properties . ,(native-build-executor-properties normalized))))) + (else + (native-build-executor #:kind 'unknown + #:name "unknown" + #:version legacy-version))))) + +(define (native-build-result-executor-kind result) + (native-build-executor-kind (native-build-result-executor result))) + +(define (native-build-result-executor-name result) + (native-build-executor-name (native-build-result-executor result))) + +(define (native-build-result-executor-version result) + (native-build-executor-version (native-build-result-executor result))) + (define (read-native-build-result result-root) (let ((promotion-file (string-append result-root "/promotion.scm"))) (unless (file-exists? promotion-file) @@ -442,21 +469,24 @@ (define (native-build-artifact-display-name result artifact-kind) (let* ((base (native-build-result-ref result 'freebsd-base '())) (version-label (native-build-result-ref base 'version-label "unknown")) - (executor (native-build-result-ref result 'executor "unknown"))) + (executor-name (native-build-result-executor-name result))) (string-append "fruix-native-" (symbol->string artifact-kind) "-" version-label "-" - executor))) + executor-name))) (define (native-build-promoted-artifact-metadata result artifact-kind content-signature) - (let* ((entry (native-build-artifact-entry result artifact-kind))) + (let* ((entry (native-build-artifact-entry result artifact-kind)) + (executor (native-build-result-executor result))) `((native-build-object-version . ,native-build-result-promotion-version) (object-kind . artifact) (artifact-kind . ,artifact-kind) - (executor . ,(native-build-result-ref result 'executor "unknown")) - (executor-version . ,(native-build-result-ref result 'executor-version "unknown")) + (executor . ,executor) + (executor-kind . ,(native-build-result-executor-kind result)) + (executor-name . ,(native-build-result-executor-name result)) + (executor-version . ,(native-build-result-executor-version result)) (run-id . ,(native-build-result-ref result 'run-id "unknown")) (guest-host-name . ,(native-build-result-ref result 'guest-host-name "unknown")) (closure-path . ,(native-build-result-ref result 'closure-path "")) @@ -494,28 +524,31 @@ (define (native-build-result-display-name result) (let* ((base (native-build-result-ref result 'freebsd-base '())) (version-label (native-build-result-ref base 'version-label "unknown")) - (executor (native-build-result-ref result 'executor "unknown"))) - (string-append "fruix-native-build-result-" version-label "-" executor))) + (executor-name (native-build-result-executor-name result))) + (string-append "fruix-native-build-result-" version-label "-" executor-name))) (define (native-build-promoted-result-object result promoted-artifacts) - `((native-build-result-version . ,native-build-result-promotion-version) - (object-kind . result-bundle) - (executor . ,(native-build-result-ref result 'executor "unknown")) - (executor-version . ,(native-build-result-ref result 'executor-version "unknown")) - (run-id . ,(native-build-result-ref result 'run-id "unknown")) - (guest-host-name . ,(native-build-result-ref result 'guest-host-name "unknown")) - (closure-path . ,(native-build-result-ref result 'closure-path "")) - (development-profile . ,(native-build-result-ref result 'development-profile "")) - (freebsd-base . ,(native-build-result-ref result 'freebsd-base '())) - (source . ,(native-build-result-ref result 'source '())) - (build-policy . ,(native-build-result-ref result 'build-policy '())) - (artifact-count . ,(length promoted-artifacts)) - (artifacts . ,(map (lambda (entry) - `((artifact-kind . ,(assoc-ref entry 'artifact-kind)) - (store-path . ,(assoc-ref entry 'store-path)) - (content-signature . ,(assoc-ref entry 'content-signature)) - (metadata-file . ,(assoc-ref entry 'metadata-file)))) - promoted-artifacts)))) + (let ((executor (native-build-result-executor result))) + `((native-build-result-version . ,native-build-result-promotion-version) + (object-kind . result-bundle) + (executor . ,executor) + (executor-kind . ,(native-build-result-executor-kind result)) + (executor-name . ,(native-build-result-executor-name result)) + (executor-version . ,(native-build-result-executor-version result)) + (run-id . ,(native-build-result-ref result 'run-id "unknown")) + (guest-host-name . ,(native-build-result-ref result 'guest-host-name "unknown")) + (closure-path . ,(native-build-result-ref result 'closure-path "")) + (development-profile . ,(native-build-result-ref result 'development-profile "")) + (freebsd-base . ,(native-build-result-ref result 'freebsd-base '())) + (source . ,(native-build-result-ref result 'source '())) + (build-policy . ,(native-build-result-ref result 'build-policy '())) + (artifact-count . ,(length promoted-artifacts)) + (artifacts . ,(map (lambda (entry) + `((artifact-kind . ,(assoc-ref entry 'artifact-kind)) + (store-path . ,(assoc-ref entry 'store-path)) + (content-signature . ,(assoc-ref entry 'content-signature)) + (metadata-file . ,(assoc-ref entry 'metadata-file)))) + promoted-artifacts))))) (define* (promote-native-build-result result-root #:key (store-dir "/frx/store")) (let* ((result (read-native-build-result result-root)) @@ -544,6 +577,9 @@ (write-file (string-append result-store "/.fruix-native-build-result.scm") payload)) `((result-root . ,result-root) + (executor-kind . ,(native-build-result-executor-kind result)) + (executor-name . ,(native-build-result-executor-name result)) + (executor-version . ,(native-build-result-executor-version result)) (result-store . ,result-store) (result-metadata-file . ,(string-append result-store "/.fruix-native-build-result.scm")) (artifact-store-count . ,(length promoted-artifacts)) diff --git a/modules/fruix/system/freebsd/executor.scm b/modules/fruix/system/freebsd/executor.scm new file mode 100644 index 0000000..32c5958 --- /dev/null +++ b/modules/fruix/system/freebsd/executor.scm @@ -0,0 +1,121 @@ +(define-module (fruix system freebsd executor) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:export (native-build-executor-model-version + native-build-executor + native-build-executor? + native-build-executor-ref + native-build-executor-kind + native-build-executor-name + native-build-executor-version + native-build-executor-properties + normalize-native-build-executor + host-native-build-executor + ssh-guest-native-build-executor + self-hosted-native-build-executor)) + +(define native-build-executor-model-version "1") + +(define (association-list? value) + (and (list? value) + (every pair? value))) + +(define (executor-name kind provided-name) + (or provided-name + (symbol->string kind))) + +(define* (native-build-executor #:key kind name + (version native-build-executor-model-version) + (properties '())) + (unless (symbol? kind) + (error "native build executor kind must be a symbol" kind)) + (unless (string? (executor-name kind name)) + (error "native build executor name must be a string" name)) + (unless (string? version) + (error "native build executor version must be a string" version)) + (unless (association-list? properties) + (error "native build executor properties must be an association list" properties)) + `((kind . ,kind) + (name . ,(executor-name kind name)) + (version . ,version) + (properties . ,properties))) + +(define (native-build-executor-ref executor key default) + (match (assoc key executor) + ((_ . value) value) + (#f default))) + +(define (native-build-executor? value) + (and (association-list? value) + (symbol? (native-build-executor-ref value 'kind #f)) + (string? (native-build-executor-ref value 'name #f)) + (string? (native-build-executor-ref value 'version #f)) + (association-list? (native-build-executor-ref value 'properties '())))) + +(define (native-build-executor-kind executor) + (native-build-executor-ref executor 'kind 'unknown)) + +(define (native-build-executor-name executor) + (native-build-executor-ref executor 'name "unknown")) + +(define (native-build-executor-version executor) + (native-build-executor-ref executor 'version "unknown")) + +(define (native-build-executor-properties executor) + (native-build-executor-ref executor 'properties '())) + +(define (legacy-executor-kind name) + (cond + ((member name '("host")) 'host) + ((member name '("ssh-guest" "guest-ssh" "guest-host-initiated")) 'ssh-guest) + ((member name '("self-hosted" "guest-self-hosted")) 'self-hosted) + ((member name '("jail")) 'jail) + ((member name '("remote-builder")) 'remote-builder) + (else 'legacy))) + +(define (normalize-native-build-executor value) + (cond + ((native-build-executor? value) + value) + ((string? value) + (native-build-executor #:kind (legacy-executor-kind value) + #:name value + #:version "legacy")) + (else + (error "unsupported native build executor representation" value)))) + +(define* (host-native-build-executor #:key (name "host") + host-name working-directory) + (native-build-executor + #:kind 'host + #:name name + #:properties (filter-map identity + `((host-name . ,host-name) + (working-directory . ,working-directory))))) + +(define* (ssh-guest-native-build-executor #:key (name "ssh-guest") + transport orchestrator + guest-host-name guest-ip vm-id vdi-id) + (native-build-executor + #:kind 'ssh-guest + #:name name + #:properties (filter-map identity + `((transport . ,(or transport "ssh")) + (orchestrator . ,(or orchestrator "host")) + (guest-host-name . ,guest-host-name) + (guest-ip . ,guest-ip) + (vm-id . ,vm-id) + (vdi-id . ,vdi-id))))) + +(define* (self-hosted-native-build-executor #:key (name "self-hosted") + helper-path helper-version + guest-host-name build-root-base result-root-base) + (native-build-executor + #:kind 'self-hosted + #:name name + #:version (or helper-version native-build-executor-model-version) + #:properties (filter-map identity + `((helper-path . ,helper-path) + (guest-host-name . ,guest-host-name) + (build-root-base . ,build-root-base) + (result-root-base . ,result-root-base))))) diff --git a/modules/fruix/system/freebsd/model.scm b/modules/fruix/system/freebsd/model.scm index 2333aad..b5b1248 100644 --- a/modules/fruix/system/freebsd/model.scm +++ b/modules/fruix/system/freebsd/model.scm @@ -334,7 +334,7 @@ (development-environment-helper-version . ,(if (null? (operating-system-development-packages os)) #f "1")) (self-hosted-native-build-helper-version - . ,(if (null? (operating-system-development-packages os)) #f "3")) + . ,(if (null? (operating-system-development-packages os)) #f "4")) (user-count . ,(length (operating-system-users os))) (users . ,(map user-account-name (operating-system-users os))) (group-count . ,(length (operating-system-groups os))) diff --git a/modules/fruix/system/freebsd/render.scm b/modules/fruix/system/freebsd/render.scm index 5f6f115..3da46e3 100644 --- a/modules/fruix/system/freebsd/render.scm +++ b/modules/fruix/system/freebsd/render.scm @@ -928,8 +928,13 @@ "ln -s \"$result_root\" \"$latest_link\"\n" "cat >\"$promotion_file\" <\"$metadata_file\" <&2; exit 1; } +[ -f "$local_result_root/promotion.scm" ] || { echo "imported result is missing promotion.scm" >&2; exit 1; } +[ -f "$local_result_root/artifacts/world/bin/sh" ] || { echo "imported result is missing world artifact" >&2; exit 1; } +[ -f "$local_result_root/artifacts/kernel/boot/kernel/kernel" ] || { echo "imported result is missing kernel artifact" >&2; exit 1; } +[ -f "$local_result_root/artifacts/headers/usr/include/sys/param.h" ] || { echo "imported result is missing headers artifact" >&2; exit 1; } +[ -f "$local_result_root/artifacts/bootloader/boot/loader.efi" ] || { echo "imported result is missing bootloader artifact" >&2; exit 1; } + +action_env() { + sudo env \ + HOME="$HOME" \ + GUILE_AUTO_COMPILE=0 \ + GUIX_SOURCE_DIR="${GUIX_SOURCE_DIR:-$HOME/repos/guix}" \ + GUILE_BIN="${GUILE_BIN:-/tmp/guile-freebsd-validate-install/bin/guile}" \ + GUILE_EXTRA_PREFIX="${GUILE_EXTRA_PREFIX:-/tmp/guile-gnutls-freebsd-validate-install}" \ + SHEPHERD_PREFIX="${SHEPHERD_PREFIX:-/tmp/shepherd-freebsd-validate-install}" \ + "$@" +} + +action_env "$repo_root/bin/fruix" native-build promote "$local_result_root" --store "$store_dir" >"$promotion_out" + +field() { + sed -n "s/^$1=//p" "$promotion_out" | tail -n 1 +} + +executor_kind=$(field executor_kind) +executor_name=$(field executor_name) +executor_version=$(field executor_version) +result_store=$(field result_store) +result_metadata_file=$(field result_metadata_file) +artifact_store_count=$(field artifact_store_count) +artifact_stores=$(field artifact_stores) +world_store=$(field world_store) +kernel_store=$(field kernel_store) +headers_store=$(field headers_store) +bootloader_store=$(field bootloader_store) + +[ "$executor_kind" = ssh-guest ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; } +[ "$executor_name" = ssh-guest ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; } +[ "$executor_version" = 1 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; } +[ "$artifact_store_count" = 4 ] || { echo "unexpected artifact store count: $artifact_store_count" >&2; exit 1; } +case "$result_store" in + /frx/store/*-fruix-native-build-result-*-ssh-guest) : ;; + *) echo "unexpected result store path: $result_store" >&2; exit 1 ;; +esac +case "$world_store" in + /frx/store/*-fruix-native-world-*-ssh-guest) : ;; + *) echo "unexpected world store path: $world_store" >&2; exit 1 ;; +esac +case "$kernel_store" in + /frx/store/*-fruix-native-kernel-*-ssh-guest) : ;; + *) echo "unexpected kernel store path: $kernel_store" >&2; exit 1 ;; +esac +case "$headers_store" in + /frx/store/*-fruix-native-headers-*-ssh-guest) : ;; + *) echo "unexpected headers store path: $headers_store" >&2; exit 1 ;; +esac +case "$bootloader_store" in + /frx/store/*-fruix-native-bootloader-*-ssh-guest) : ;; + *) echo "unexpected bootloader store path: $bootloader_store" >&2; exit 1 ;; +esac + +[ -f "$result_metadata_file" ] || { echo "missing result metadata file: $result_metadata_file" >&2; exit 1; } +[ -f "$world_store/.fruix-native-build-object.scm" ] || { echo "missing world store metadata" >&2; exit 1; } +[ -f "$kernel_store/.fruix-native-build-object.scm" ] || { echo "missing kernel store metadata" >&2; exit 1; } +[ -f "$headers_store/.fruix-native-build-object.scm" ] || { echo "missing headers store metadata" >&2; exit 1; } +[ -f "$bootloader_store/.fruix-native-build-object.scm" ] || { echo "missing bootloader store metadata" >&2; exit 1; } +[ -L "$result_store/artifacts/world" ] || { echo "missing promoted world artifact link" >&2; exit 1; } +[ -L "$result_store/artifacts/kernel" ] || { echo "missing promoted kernel artifact link" >&2; exit 1; } +[ -L "$result_store/artifacts/headers" ] || { echo "missing promoted headers artifact link" >&2; exit 1; } +[ -L "$result_store/artifacts/bootloader" ] || { echo "missing promoted bootloader artifact link" >&2; exit 1; } +[ "$(readlink "$result_store/artifacts/world")" = "$world_store" ] || { echo "world artifact link mismatch" >&2; exit 1; } +[ "$(readlink "$result_store/artifacts/kernel")" = "$kernel_store" ] || { echo "kernel artifact link mismatch" >&2; exit 1; } +[ "$(readlink "$result_store/artifacts/headers")" = "$headers_store" ] || { echo "headers artifact link mismatch" >&2; exit 1; } +[ "$(readlink "$result_store/artifacts/bootloader")" = "$bootloader_store" ] || { echo "bootloader artifact link mismatch" >&2; exit 1; } +[ -f "$world_store/bin/sh" ] || { echo "promoted world store missing /bin/sh" >&2; exit 1; } +[ -f "$kernel_store/boot/kernel/kernel" ] || { echo "promoted kernel store missing kernel" >&2; exit 1; } +[ -f "$headers_store/usr/include/sys/param.h" ] || { echo "promoted headers store missing param.h" >&2; exit 1; } +[ -f "$bootloader_store/boot/loader.efi" ] || { echo "promoted bootloader store missing loader.efi" >&2; exit 1; } + +promoted_kernel_sha=$(sha256 -q "$kernel_store/boot/kernel/kernel") +promoted_loader_sha=$(sha256 -q "$bootloader_store/boot/loader.efi") +promoted_param_sha=$(sha256 -q "$headers_store/usr/include/sys/param.h") +[ "$promoted_kernel_sha" = "$sha_kernel" ] || { echo "kernel sha mismatch after promotion" >&2; exit 1; } +[ "$promoted_loader_sha" = "$sha_loader" ] || { echo "loader sha mismatch after promotion" >&2; exit 1; } +[ "$promoted_param_sha" = "$sha_param" ] || { echo "param.h sha mismatch after promotion" >&2; exit 1; } + +grep -F '(executor-kind . ssh-guest)' "$result_metadata_file" >/dev/null || { + echo "result metadata file is missing ssh-guest executor kind" >&2 + exit 1 +} +grep -F '(executor-name . "ssh-guest")' "$result_metadata_file" >/dev/null || { + echo "result metadata file is missing ssh-guest executor name" >&2 + exit 1 +} +grep -F "$source_store" "$result_metadata_file" >/dev/null || { + echo "result metadata file is missing source store provenance" >&2 + exit 1 +} +grep -F '(artifact-kind . kernel)' "$kernel_store/.fruix-native-build-object.scm" >/dev/null || { + echo "kernel store metadata is missing artifact kind" >&2 + exit 1 +} +grep -F '(artifact-kind . world)' "$world_store/.fruix-native-build-object.scm" >/dev/null || { + echo "world store metadata is missing artifact kind" >&2 + exit 1 +} + +cat >"$metadata_file" < "$status_file" +fail_mark() { + rc=$? + if [ "$rc" -ne 0 ]; then + printf 'failed\n' > "$status_file" + fi +} +trap fail_mark EXIT HUP INT TERM export MAKEOBJDIRPREFIX="$build_root/obj" -common='TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no DB_FROM_SRC=yes' make -j"$BUILD_JOBS" -C "$source_root" TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no buildworld > "$logdir/buildworld.log" 2>&1 make -j"$BUILD_JOBS" -C "$source_root" TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no buildkernel > "$logdir/buildkernel.log" 2>&1 -make -C "$source_root" $common DESTDIR="$world_stage" installworld > "$logdir/installworld.log" 2>&1 -make -C "$source_root" $common DESTDIR="$world_stage" distribution > "$logdir/distribution.log" 2>&1 -make -C "$source_root" $common DESTDIR="$kernel_stage" installkernel > "$logdir/installkernel.log" 2>&1 +make -C "$source_root" $install_common DESTDIR="$world_stage" installworld > "$logdir/installworld.log" 2>&1 +make -C "$source_root" $install_common DESTDIR="$world_stage" distribution > "$logdir/distribution.log" 2>&1 +make -C "$source_root" $install_common DESTDIR="$kernel_stage" installkernel > "$logdir/installkernel.log" 2>&1 mkdir -p "$headers_stage/usr" "$bootloader_stage/boot" +cp -a "$world_stage/." "$world_artifact/" +cp -a "$kernel_stage/boot/kernel" "$kernel_artifact/boot/kernel" cp -a "$world_stage/usr/include" "$headers_stage/usr/include" mkdir -p "$headers_stage/usr/share" cp -a "$world_stage/usr/share/mk" "$headers_stage/usr/share/mk" +cp -a "$headers_stage/usr/." "$headers_artifact/usr/" cp -a "$world_stage/boot/loader" "$bootloader_stage/boot/loader" cp -a "$world_stage/boot/loader.efi" "$bootloader_stage/boot/loader.efi" cp -a "$world_stage/boot/device.hints" "$bootloader_stage/boot/device.hints" cp -a "$world_stage/boot/defaults" "$bootloader_stage/boot/defaults" cp -a "$world_stage/boot/lua" "$bootloader_stage/boot/lua" -[ -f "$kernel_stage/boot/kernel/kernel" ] -[ -f "$headers_stage/usr/include/sys/param.h" ] -[ -f "$headers_stage/usr/share/mk/bsd.prog.mk" ] -[ -f "$bootloader_stage/boot/loader.efi" ] -[ -f "$bootloader_stage/boot/defaults/loader.conf" ] -[ -f "$bootloader_stage/boot/lua/loader.lua" ] -sha_kernel=$(sha256 -q "$kernel_stage/boot/kernel/kernel") -sha_loader=$(sha256 -q "$bootloader_stage/boot/loader.efi") -sha_param=$(sha256 -q "$headers_stage/usr/include/sys/param.h") +cp -a "$bootloader_stage/boot/." "$bootloader_artifact/boot/" +[ -f "$world_artifact/bin/sh" ] +[ -f "$kernel_artifact/boot/kernel/kernel" ] +[ -f "$headers_artifact/usr/include/sys/param.h" ] +[ -f "$headers_artifact/usr/share/mk/bsd.prog.mk" ] +[ -f "$bootloader_artifact/boot/loader.efi" ] +[ -f "$bootloader_artifact/boot/defaults/loader.conf" ] +[ -f "$bootloader_artifact/boot/lua/loader.lua" ] +sha_kernel=$(sha256 -q "$kernel_artifact/boot/kernel/kernel") +sha_loader=$(sha256 -q "$bootloader_artifact/boot/loader.efi") +sha_param=$(sha256 -q "$headers_artifact/usr/include/sys/param.h") buildworld_tail=$(tail -n 20 "$logdir/buildworld.log" | tr '\n' ' ') buildkernel_tail=$(tail -n 20 "$logdir/buildkernel.log" | tr '\n' ' ') installworld_tail=$(tail -n 20 "$logdir/installworld.log" | tr '\n' ' ') @@ -120,46 +146,131 @@ distribution_tail=$(tail -n 20 "$logdir/distribution.log" | tr '\n' ' ') installkernel_tail=$(tail -n 20 "$logdir/installkernel.log" | tr '\n' ' ') root_df=$(df -h / | tail -n 1 | tr -s ' ' | tr '\t' ' ') build_root_size=$(du -sh "$build_root" | awk '{print $1}') +result_root_size=$(du -sh "$result_root" | awk '{print $1}') world_stage_size=$(du -sh "$world_stage" | awk '{print $1}') kernel_stage_size=$(du -sh "$kernel_stage" | awk '{print $1}') headers_stage_size=$(du -sh "$headers_stage" | awk '{print $1}') bootloader_stage_size=$(du -sh "$bootloader_stage" | awk '{print $1}') -printf 'build_jobs=%s\n' "$BUILD_JOBS" -printf 'source_store=%s\n' "$source_store" -printf 'source_root=%s\n' "$source_root" -printf 'build_root=%s\n' "$build_root" -printf 'logdir=%s\n' "$logdir" -printf 'buildworld_log=%s\n' "$logdir/buildworld.log" -printf 'buildkernel_log=%s\n' "$logdir/buildkernel.log" -printf 'installworld_log=%s\n' "$logdir/installworld.log" -printf 'distribution_log=%s\n' "$logdir/distribution.log" -printf 'installkernel_log=%s\n' "$logdir/installkernel.log" -printf 'world_stage=%s\n' "$world_stage" -printf 'kernel_stage=%s\n' "$kernel_stage" -printf 'headers_stage=%s\n' "$headers_stage" -printf 'bootloader_stage=%s\n' "$bootloader_stage" -printf 'root_df=%s\n' "$root_df" -printf 'build_root_size=%s\n' "$build_root_size" -printf 'world_stage_size=%s\n' "$world_stage_size" -printf 'kernel_stage_size=%s\n' "$kernel_stage_size" -printf 'headers_stage_size=%s\n' "$headers_stage_size" -printf 'bootloader_stage_size=%s\n' "$bootloader_stage_size" -printf 'sha_kernel=%s\n' "$sha_kernel" -printf 'sha_loader=%s\n' "$sha_loader" -printf 'sha_param=%s\n' "$sha_param" -printf 'buildworld_tail=%s\n' "$buildworld_tail" -printf 'buildkernel_tail=%s\n' "$buildkernel_tail" -printf 'installworld_tail=%s\n' "$installworld_tail" -printf 'distribution_tail=%s\n' "$distribution_tail" -printf 'installkernel_tail=%s\n' "$installkernel_tail" +world_artifact_size=$(du -sh "$world_artifact" | awk '{print $1}') +kernel_artifact_size=$(du -sh "$kernel_artifact" | awk '{print $1}') +headers_artifact_size=$(du -sh "$headers_artifact" | awk '{print $1}') +bootloader_artifact_size=$(du -sh "$bootloader_artifact" | awk '{print $1}') +rm -f "$latest_link" +ln -s "$result_root" "$latest_link" +cat >"$promotion_file" <"$guest_metadata_file" < "$status_file" +cat "$guest_metadata_file" EOF ) -build_jobs=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_jobs=//p') +run_id=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^run_id=//p') +executor_kind=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^executor_kind=//p') +executor_name=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^executor_name=//p') +executor_version=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^executor_version=//p') +guest_host_name=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^guest_host_name=//p') source_store=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^source_store=//p') source_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^source_root=//p') +build_jobs=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_jobs=//p') +build_common=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_common=//p') +install_common=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^install_common=//p') build_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_root=//p') +result_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^result_root=//p') logdir=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^logdir=//p') +status_file=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^status_file=//p') +guest_metadata_file=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^metadata_file=//p') +promotion_file=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^promotion_file=//p') buildworld_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildworld_log=//p') buildkernel_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildkernel_log=//p') installworld_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installworld_log=//p') @@ -169,12 +280,22 @@ world_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_stage=// kernel_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_stage=//p') headers_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_stage=//p') bootloader_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_stage=//p') +world_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_artifact=//p') +kernel_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_artifact=//p') +headers_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_artifact=//p') +bootloader_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_artifact=//p') +latest_link=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^latest_link=//p') root_df=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^root_df=//p') build_root_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_root_size=//p') +result_root_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^result_root_size=//p') world_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_stage_size=//p') kernel_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_stage_size=//p') headers_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_stage_size=//p') bootloader_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_stage_size=//p') +world_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_artifact_size=//p') +kernel_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_artifact_size=//p') +headers_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_artifact_size=//p') +bootloader_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_artifact_size=//p') sha_kernel=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_kernel=//p') sha_loader=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_loader=//p') sha_param=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_param=//p') @@ -184,6 +305,17 @@ installworld_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installw distribution_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^distribution_tail=//p') installkernel_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installkernel_tail=//p') +status_value=$(ssh_guest "cat '$status_file'") +latest_target=$(ssh_guest "readlink '$latest_link'") +ssh_guest "[ -f '$promotion_file' ]" +ssh_guest "[ -f '$world_artifact/bin/sh' ]" + +[ "$executor_kind" = ssh-guest ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; } +[ "$executor_name" = ssh-guest ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; } +[ "$executor_version" = 1 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; } +[ "$status_value" = ok ] || { echo "host-initiated build status is not ok: $status_value" >&2; exit 1; } +[ "$latest_target" = "$result_root" ] || { echo "latest link target mismatch: $latest_target" >&2; exit 1; } + case "$source_store" in /frx/store/*-freebsd-source-*) : ;; *) echo "unexpected source store path: $source_store" >&2; exit 1 ;; @@ -196,6 +328,10 @@ case "$build_root" in /var/tmp/fruix-phase20-native-build) : ;; *) echo "unexpected build root: $build_root" >&2; exit 1 ;; esac +case "$result_root" in + /var/lib/fruix/native-builds/*) : ;; + *) echo "unexpected result root: $result_root" >&2; exit 1 ;; +esac printf '%s\n' "$sha_kernel" | grep -E '^[0-9a-f]{64}$' >/dev/null || { echo "invalid kernel sha256: $sha_kernel" >&2 exit 1 @@ -227,11 +363,22 @@ vm_id=$vm_id vdi_id=$vdi_id guest_ip=$guest_ip root_size=$root_size +run_id=$run_id +executor_kind=$executor_kind +executor_name=$executor_name +executor_version=$executor_version +guest_host_name=$guest_host_name build_jobs=$build_jobs source_store=$source_store source_root=$source_root +build_common=$build_common +install_common=$install_common build_root=$build_root +result_root=$result_root logdir=$logdir +status_file=$status_file +guest_metadata_file=$guest_metadata_file +promotion_file=$promotion_file buildworld_log=$buildworld_log buildkernel_log=$buildkernel_log installworld_log=$installworld_log @@ -241,12 +388,24 @@ world_stage=$world_stage kernel_stage=$kernel_stage headers_stage=$headers_stage bootloader_stage=$bootloader_stage +world_artifact=$world_artifact +kernel_artifact=$kernel_artifact +headers_artifact=$headers_artifact +bootloader_artifact=$bootloader_artifact +latest_link=$latest_link +latest_target=$latest_target +status_value=$status_value root_df=$root_df build_root_size=$build_root_size +result_root_size=$result_root_size world_stage_size=$world_stage_size kernel_stage_size=$kernel_stage_size headers_stage_size=$headers_stage_size bootloader_stage_size=$bootloader_stage_size +world_artifact_size=$world_artifact_size +kernel_artifact_size=$kernel_artifact_size +headers_artifact_size=$headers_artifact_size +bootloader_artifact_size=$bootloader_artifact_size sha_kernel=$sha_kernel sha_loader=$sha_loader sha_param=$sha_param diff --git a/tests/system/run-phase20-native-build-store-promotion-xcpng.sh b/tests/system/run-phase20-native-build-store-promotion-xcpng.sh index 7419aff..d33a55a 100755 --- a/tests/system/run-phase20-native-build-store-promotion-xcpng.sh +++ b/tests/system/run-phase20-native-build-store-promotion-xcpng.sh @@ -104,6 +104,9 @@ field() { sed -n "s/^$1=//p" "$promotion_out" | tail -n 1 } +executor_kind=$(field executor_kind) +executor_name=$(field executor_name) +executor_version=$(field executor_version) result_store=$(field result_store) result_metadata_file=$(field result_metadata_file) artifact_store_count=$(field artifact_store_count) @@ -113,6 +116,9 @@ kernel_store=$(field kernel_store) headers_store=$(field headers_store) bootloader_store=$(field bootloader_store) +[ "$executor_kind" = self-hosted ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; } +[ "$executor_name" = guest-self-hosted ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; } +[ "$executor_version" = 4 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; } [ "$artifact_store_count" = 4 ] || { echo "unexpected artifact store count: $artifact_store_count" >&2; exit 1; } case "$result_store" in /frx/store/*-fruix-native-build-result-*-guest-self-hosted) : ;; @@ -160,8 +166,12 @@ promoted_param_sha=$(sha256 -q "$headers_store/usr/include/sys/param.h") [ "$promoted_loader_sha" = "$sha_loader" ] || { echo "loader sha mismatch after promotion" >&2; exit 1; } [ "$promoted_param_sha" = "$sha_param" ] || { echo "param.h sha mismatch after promotion" >&2; exit 1; } -grep -F '(executor . "guest-self-hosted")' "$result_metadata_file" >/dev/null || { - echo "result metadata file is missing guest-self-hosted executor" >&2 +grep -F '(executor-kind . self-hosted)' "$result_metadata_file" >/dev/null || { + echo "result metadata file is missing self-hosted executor kind" >&2 + exit 1 +} +grep -F '(executor-name . "guest-self-hosted")' "$result_metadata_file" >/dev/null || { + echo "result metadata file is missing guest-self-hosted executor name" >&2 exit 1 } grep -F "$source_store" "$result_metadata_file" >/dev/null || { @@ -197,6 +207,9 @@ guest_headers_artifact=$headers_artifact guest_bootloader_artifact=$bootloader_artifact local_result_root=$local_result_root store_dir=$store_dir +executor_kind=$executor_kind +executor_name=$executor_name +executor_version=$executor_version result_store=$result_store result_metadata_file=$result_metadata_file artifact_store_count=$artifact_store_count diff --git a/tests/system/run-phase20-self-hosted-native-build-xcpng.sh b/tests/system/run-phase20-self-hosted-native-build-xcpng.sh index 3b1bb53..4acc787 100755 --- a/tests/system/run-phase20-self-hosted-native-build-xcpng.sh +++ b/tests/system/run-phase20-self-hosted-native-build-xcpng.sh @@ -78,6 +78,9 @@ self_hosted_metadata=$(ssh_guest env FRUIX_SELF_HOSTED_NATIVE_BUILD_JOBS="$guest run_id=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^run_id=//p') helper_version=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^helper_version=//p') +executor_kind=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^executor_kind=//p') +executor_name=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^executor_name=//p') +executor_version=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^executor_version=//p') source_store=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^source_store=//p') source_root=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^source_root=//p') build_jobs=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_jobs=//p') @@ -118,7 +121,10 @@ latest_target=$(ssh_guest "readlink '$latest_link'") ssh_guest "[ -f '$promotion_file' ]" ssh_guest "[ -f '$world_artifact/bin/sh' ]" -[ "$helper_version" = 3 ] || { echo "unexpected helper version: $helper_version" >&2; exit 1; } +[ "$helper_version" = 4 ] || { echo "unexpected helper version: $helper_version" >&2; exit 1; } +[ "$executor_kind" = self-hosted ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; } +[ "$executor_name" = guest-self-hosted ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; } +[ "$executor_version" = 4 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; } [ "$build_jobs" = "$guest_build_jobs" ] || { echo "unexpected build job count: $build_jobs" >&2; exit 1; } [ "$status_value" = ok ] || { echo "self-hosted build status is not ok: $status_value" >&2; exit 1; } [ "$latest_target" = "$result_root" ] || { echo "latest link target mismatch: $latest_target" >&2; exit 1; } @@ -197,6 +203,9 @@ guest_ip=$guest_ip root_size=$root_size run_id=$run_id helper_version=$helper_version +executor_kind=$executor_kind +executor_name=$executor_name +executor_version=$executor_version build_jobs=$build_jobs source_store=$source_store source_root=$source_root