diff --git a/docs/release-control/v6/internal/records/release-acceleration-v6.3.0-rc.5-2026-08-21.md b/docs/release-control/v6/internal/records/release-acceleration-v6.3.0-rc.5-2026-08-21.md index 0e7e79b54..59e193e69 100644 --- a/docs/release-control/v6/internal/records/release-acceleration-v6.3.0-rc.5-2026-08-21.md +++ b/docs/release-control/v6/internal/records/release-acceleration-v6.3.0-rc.5-2026-08-21.md @@ -131,6 +131,16 @@ artifact client, and performs heavyweight disk cleanup only below an explicit 8 GiB safety floor. Exact Pulse and pulse-enterprise SHA manifests remain the authority on both sides of the credential boundary. +The first non-publishing exact-SHA proof of that lean profile failed before Pro +compilation because the public server packages require +`frontend-modern/dist` as an embed source even though Pro never transfers the +frontend as a standalone payload. The corrected profile builds that exact-SHA +embed prerequisite concurrently with the public-agent matrix, leaves it in the +source checkout for the five Pro builds, and still excludes it from the +manifest-covered cross-repository payload. A governed regression test preserves +the distinction between a required local compile input and an unused transfer +product. + Public Docker publication took 5 minutes 1 second, but its prior dependency shape did not make it eligible until 12 minutes 33 seconds after dispatch. The corrected DAG makes exact-version Docker staging eligible as soon as the diff --git a/docs/release-control/v6/internal/subsystems/deployment-installability.md b/docs/release-control/v6/internal/subsystems/deployment-installability.md index 6b65adb68..a8b08e6ea 100644 --- a/docs/release-control/v6/internal/subsystems/deployment-installability.md +++ b/docs/release-control/v6/internal/subsystems/deployment-installability.md @@ -549,8 +549,11 @@ upgrade, update, release, or artifact-selection behavior. Private Pro compilation must additionally bind the exact Pulse and pulse-enterprise commits in a manifest-covered identity record. Its PVE job must compile only the public Unified Agent matrix actually embedded in Pro - archives plus the Pro server matrix; rebuilding the unused public frontend, - MCP, server, or control-plane payload is not part of this boundary. The + archives plus the Pro server matrix. The public frontend build is a required + source-checkout prerequisite because every Pro server embeds that exact-SHA + bundle, so it must overlap the public-agent matrix but must not enter the + transferred payload. Rebuilding the unused public MCP, server, or + control-plane payload is not part of this boundary. The cross-repository handoff must remain manifest-bound, use compressed artifact transfer, and let a hosted runner with sufficient free space skip destructive image/toolchain cleanup. The hosted private job must verify both SHAs before diff --git a/scripts/build-release-binaries.sh b/scripts/build-release-binaries.sh index 2cb260a9f..1f44ad106 100755 --- a/scripts/build-release-binaries.sh +++ b/scripts/build-release-binaries.sh @@ -89,14 +89,23 @@ if [[ -e "${OUTPUT_ROOT}" ]] && find "${OUTPUT_ROOT}" -mindepth 1 -print -quit | fi mkdir -p "${BINARIES_DIR}" "${MANIFEST_DIR}" -if [[ "${PROFILE}" == "full" ]]; then - mkdir -p "${FRONTEND_DIR}" - echo "Building exact-SHA frontend bundle..." +build_frontend() { + echo "Building exact-SHA frontend embed prerequisite..." npm --prefix frontend-modern ci npm --prefix frontend-modern run build - cp -a frontend-modern/dist/. "${FRONTEND_DIR}/" + if [[ "${PROFILE}" == "full" ]]; then + mkdir -p "${FRONTEND_DIR}" + cp -a frontend-modern/dist/. "${FRONTEND_DIR}/" + fi +} + +frontend_log="${OUTPUT_ROOT}/frontend.log" +build_frontend >"${frontend_log}" 2>&1 & +frontend_pid=$! +if [[ "${PROFILE}" == "full" ]]; then + echo "Building frontend bundle concurrently with the release binary matrix." else - echo "Using Pro packaging profile: public Unified Agent binaries only." + echo "Using Pro packaging profile: build the required frontend embed locally; transfer public Unified Agent binaries only." fi export CGO_ENABLED=0 @@ -191,6 +200,11 @@ terminate_active() { [[ -n "${pid}" ]] && terminate_tree "${pid}" done wait "${active_pids[@]:-}" >/dev/null 2>&1 || true + if [[ -n "${frontend_pid:-}" ]]; then + terminate_tree "${frontend_pid}" + wait "${frontend_pid}" >/dev/null 2>&1 || true + frontend_pid="" + fi } trap terminate_active INT TERM @@ -234,6 +248,19 @@ while (( completed_tasks < total_tasks )); do completed_tasks=$((completed_tasks + 1)) echo "Compiled ${task_name} (${completed_tasks}/${total_tasks})." done + +if wait "${frontend_pid}"; then + status=0 +else + status=$? + echo "Error: frontend embed prerequisite failed." >&2 + cat "${frontend_log}" >&2 + frontend_pid="" + exit "${status}" +fi +frontend_pid="" +rm -f "${frontend_log}" +echo "Built frontend embed prerequisite." trap - INT TERM python3 scripts/release_candidate_manifest.py create \ diff --git a/scripts/installtests/build_release_assets_test.go b/scripts/installtests/build_release_assets_test.go index 53d3c8058..ca5ee7e58 100644 --- a/scripts/installtests/build_release_assets_test.go +++ b/scripts/installtests/build_release_assets_test.go @@ -142,6 +142,33 @@ func TestBuildReleaseUsesV6InstallScripts(t *testing.T) { } } +func TestProPackagingBuildsFrontendEmbedWithoutTransferringBundle(t *testing.T) { + content, err := os.ReadFile(repoFile("scripts", "build-release-binaries.sh")) + if err != nil { + t.Fatalf("read build-release-binaries.sh: %v", err) + } + script := string(content) + + for _, needle := range []string{ + `build_frontend >"${frontend_log}" 2>&1 &`, + `npm --prefix frontend-modern ci`, + `npm --prefix frontend-modern run build`, + `if [[ "${PROFILE}" == "full" ]]; then`, + `cp -a frontend-modern/dist/. "${FRONTEND_DIR}/"`, + `transfer public Unified Agent binaries only`, + } { + if !strings.Contains(script, needle) { + t.Fatalf("build-release-binaries.sh missing Pro frontend embed contract: %s", needle) + } + } + if strings.Contains(script, `if [[ "${PROFILE}" == "full" ]]; then + mkdir -p "${FRONTEND_DIR}" + echo "Building exact-SHA frontend bundle..." + npm --prefix frontend-modern ci`) { + t.Fatal("Pro packaging must build the frontend embed prerequisite") + } +} + func TestReleaseContainerTargetsConsumeImmutableCandidate(t *testing.T) { dockerfileBytes, err := os.ReadFile(repoFile("Dockerfile")) if err != nil {