From ffee736872c83ccfc02c3328fd7f4fe5f48603f4 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 18:46:18 +0100 Subject: [PATCH] build: refresh Node 24 builder digest Keep the canonical release and provider-MSP frontend builders on the proposed immutable amd64 Node 24 digest. Bind the same-commit change to the deployment contract, release-build metadata proof and provider-MSP rollout-control proof; hosted build and installed rollout remain separate evidence. Change-source: pulse-maintainer --- Dockerfile | 2 +- deploy/provider-msp/Dockerfile.control-plane | 2 +- .../subsystems/deployment-installability.md | 14 +++++++++++ .../installtests/build_release_assets_test.go | 2 +- .../installtests/dependency_update_test.go | 23 +++++++++++++++++++ .../installtests/provider_msp_deploy_test.go | 2 +- 6 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8ec1e6c2c2..4385fce29d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG APPRISE_VERSION=1.12.0 # Build stage for frontend (must be built first for embedding) # Force amd64 platform to avoid slow QEMU emulation during multi-arch builds -FROM --platform=linux/amd64 node:24-alpine@sha256:50c8e8ca1d27439048670df5883f32d57cf81cff6233222c893fd0d9884cbd81 AS frontend-builder +FROM --platform=linux/amd64 node:24-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 AS frontend-builder WORKDIR /app/frontend-modern diff --git a/deploy/provider-msp/Dockerfile.control-plane b/deploy/provider-msp/Dockerfile.control-plane index 2f2002055b..cde348f419 100644 --- a/deploy/provider-msp/Dockerfile.control-plane +++ b/deploy/provider-msp/Dockerfile.control-plane @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.7 -FROM --platform=linux/amd64 node:24-alpine@sha256:50c8e8ca1d27439048670df5883f32d57cf81cff6233222c893fd0d9884cbd81 AS frontend-builder +FROM --platform=linux/amd64 node:24-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 AS frontend-builder WORKDIR /app/frontend-modern COPY frontend-modern/package*.json ./ RUN --mount=type=cache,id=pulse-control-plane-npm-cache,target=/root/.npm \ diff --git a/docs/release-control/v6/internal/subsystems/deployment-installability.md b/docs/release-control/v6/internal/subsystems/deployment-installability.md index 013b563c0f..eaa6eb2501 100644 --- a/docs/release-control/v6/internal/subsystems/deployment-installability.md +++ b/docs/release-control/v6/internal/subsystems/deployment-installability.md @@ -5538,6 +5538,20 @@ a valid pinned SSH signature and the extracted request expression with absent and synthetic email. It does not establish installed onboarding, server acceptance or legal identity. See the qualification evidence below. +### Node 24 amd64 release-builder digest parity + +The canonical Pulse release Dockerfile and provider-MSP control-plane Dockerfile +pin the same immutable amd64 Node 24 Alpine frontend-builder image. The +`TestNode24FrontendBuilderDigestIsAligned` installability test binds both +build inputs to the current dependency digest. The canonical release-build +metadata proof `TestDockerBuildUsesCanonicalReleaseLdflags` and hosted +provider-MSP control proof `TestProviderMSPControlPlaneDockerfileBuildsReleaseLicenseBinary` +also require that exact digest while retaining their release metadata and +license-build assertions. These are source-contract checks, not an image build. +The hosted release build must verify the landed exact source, and provider-MSP +rollout and installed acceptance must be observed separately before this refresh +is considered operationally complete. + ### Pinned release action consumer compatibility The grouped release actions use immutable revisions recorded in diff --git a/scripts/installtests/build_release_assets_test.go b/scripts/installtests/build_release_assets_test.go index 4417d5955b..5b83d84706 100644 --- a/scripts/installtests/build_release_assets_test.go +++ b/scripts/installtests/build_release_assets_test.go @@ -1641,7 +1641,7 @@ func TestDockerBuildUsesCanonicalReleaseLdflags(t *testing.T) { } dockerfile := string(dockerfileBytes) dockerRequired := []string{ - `FROM --platform=linux/amd64 node:24-alpine@sha256:`, + "FROM --platform=linux/amd64 node:24-alpine@sha256:" + node24Amd64FrontendDigest + " AS frontend-builder", `FROM --platform=linux/amd64 golang:1.26.8-alpine@sha256:`, `FROM backend-builder AS release-assets-builder`, `AS agent_runtime`, diff --git a/scripts/installtests/dependency_update_test.go b/scripts/installtests/dependency_update_test.go index ba77d0ebb3..453cc8d82a 100644 --- a/scripts/installtests/dependency_update_test.go +++ b/scripts/installtests/dependency_update_test.go @@ -1,6 +1,7 @@ package installtests import ( + "os" "regexp" "testing" "time" @@ -31,6 +32,28 @@ func assertDigestPinnedDockerStage(t *testing.T, dockerfile, prefix, suffix stri } } +const node24Amd64FrontendDigest = "ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1" + +func TestNode24FrontendBuilderDigestIsAligned(t *testing.T) { + pattern := regexp.MustCompile(`(?m)^FROM --platform=linux/amd64 node:24-alpine@sha256:([0-9a-f]{64}) AS frontend-builder$`) + for _, path := range []string{ + repoFile("Dockerfile"), + repoFile("deploy", "provider-msp", "Dockerfile.control-plane"), + } { + contents, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read Node 24 builder Dockerfile %s: %v", path, err) + } + matches := pattern.FindStringSubmatch(string(contents)) + if len(matches) != 2 { + t.Fatalf("%s must pin its amd64 Node 24 frontend builder by a full immutable digest", path) + } + if matches[1] != node24Amd64FrontendDigest { + t.Fatalf("%s Node 24 frontend builder digest is %s; expected %s", path, matches[1], node24Amd64FrontendDigest) + } + } +} + // TestGovernedContainerBaseSupportWindow turns the upstream lifecycle date // into an advance operational signal. Digest automation keeps a selected line // patched, but it cannot move a deliberately governed major/minor tag. diff --git a/scripts/installtests/provider_msp_deploy_test.go b/scripts/installtests/provider_msp_deploy_test.go index 113218d23e..cfe375ec9d 100644 --- a/scripts/installtests/provider_msp_deploy_test.go +++ b/scripts/installtests/provider_msp_deploy_test.go @@ -303,7 +303,7 @@ func TestProviderMSPControlPlaneDockerfileBuildsReleaseLicenseBinary(t *testing. text := string(dockerfileBytes) assertContainsAll(t, text, "# syntax=docker/dockerfile:1.7", - "FROM --platform=linux/amd64 node:24-alpine@sha256:", + "FROM --platform=linux/amd64 node:24-alpine@sha256:"+node24Amd64FrontendDigest+" AS frontend-builder", "npm ci", "npm run build", "FROM --platform=$BUILDPLATFORM golang:1.26.8-alpine@sha256:",