mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-02 20:29:43 +00:00
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
83 lines
2.7 KiB
Go
83 lines
2.7 KiB
Go
package installtests
|
|
|
|
import (
|
|
"os"
|
|
"regexp"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
alpineRuntimeLine = "3.24"
|
|
alpineRuntimeSupportEnd = "2028-06-01"
|
|
nodeToolchainLine = "24"
|
|
nodeToolchainSupportEnd = "2028-04-30"
|
|
containerSupportLead = 180 * 24 * time.Hour
|
|
)
|
|
|
|
// assertDigestPinnedDockerStage allows automated digest refreshes while still
|
|
// rejecting shortened, malformed, mutable, or decoy base-image references for
|
|
// the named production stage.
|
|
func assertDigestPinnedDockerStage(t *testing.T, dockerfile, prefix, suffix string) {
|
|
t.Helper()
|
|
pattern := regexp.MustCompile(
|
|
`(?m)^` + regexp.QuoteMeta(prefix) + `[0-9a-f]{64}` + regexp.QuoteMeta(suffix) + `$`,
|
|
)
|
|
if !pattern.MatchString(dockerfile) {
|
|
t.Fatalf(
|
|
"Dockerfile stage must use a full immutable digest: %s<64 lowercase hex characters>%s",
|
|
prefix,
|
|
suffix,
|
|
)
|
|
}
|
|
}
|
|
|
|
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.
|
|
func TestGovernedContainerBaseSupportWindow(t *testing.T) {
|
|
for _, policy := range []struct {
|
|
name string
|
|
line string
|
|
supportEnd string
|
|
}{
|
|
{name: "Alpine", line: alpineRuntimeLine, supportEnd: alpineRuntimeSupportEnd},
|
|
{name: "Node.js", line: nodeToolchainLine, supportEnd: nodeToolchainSupportEnd},
|
|
} {
|
|
supportEnd, err := time.Parse("2006-01-02", policy.supportEnd)
|
|
if err != nil {
|
|
t.Fatalf("parse %s %s support end: %v", policy.name, policy.line, err)
|
|
}
|
|
remaining := time.Until(supportEnd)
|
|
if remaining < containerSupportLead {
|
|
t.Fatalf(
|
|
"%s %s has less than 180 days of normal support remaining (support ends %s); select and qualify a newer line",
|
|
policy.name,
|
|
policy.line,
|
|
policy.supportEnd,
|
|
)
|
|
}
|
|
}
|
|
}
|