Build frontend for Pro packaging profile

This commit is contained in:
rcourtman 2026-08-21 19:04:23 +01:00
parent 0cd70edd90
commit 89eba99bb4
4 changed files with 74 additions and 7 deletions

View file

@ -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

View file

@ -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

View file

@ -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 \

View file

@ -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 {