Strengthen dependency maintenance contracts

This commit is contained in:
pulse-triage[bot]
2026-08-30 04:05:02 +01:00
parent 560c2de026
commit f9ffbf701a
4 changed files with 41 additions and 25 deletions
@@ -1478,9 +1478,10 @@ func TestDockerBuildUsesCanonicalReleaseLdflags(t *testing.T) {
t.Fatalf("Dockerfile missing canonical release ldflags usage: %s", needle)
}
}
assertDigestPinnedDockerBase(t, dockerfile, `FROM --platform=linux/amd64 node:20-alpine@sha256:`)
assertDigestPinnedDockerBase(t, dockerfile, `FROM --platform=linux/amd64 golang:1.26.7-alpine@sha256:`)
assertDigestPinnedDockerBase(t, dockerfile, `FROM alpine:3.20@sha256:`)
assertDigestPinnedDockerStage(t, dockerfile, `FROM --platform=linux/amd64 node:20-alpine@sha256:`, ` AS frontend-builder`)
assertDigestPinnedDockerStage(t, dockerfile, `FROM --platform=linux/amd64 golang:1.26.7-alpine@sha256:`, ` AS backend-builder`)
assertDigestPinnedDockerStage(t, dockerfile, `FROM alpine:3.20@sha256:`, ` AS agent_runtime`)
assertDigestPinnedDockerStage(t, dockerfile, `FROM alpine:3.20@sha256:`, ` AS pulse-runtime-foundation`)
hostedStart := strings.Index(dockerfile, `FROM pulse-runtime-base AS hosted_runtime`)
runtimeStart := strings.Index(dockerfile, `FROM pulse-runtime-base AS runtime`)
if hostedStart == -1 || runtimeStart == -1 || hostedStart > runtimeStart {
+12 -5
View File
@@ -5,12 +5,19 @@ import (
"testing"
)
// assertDigestPinnedDockerBase allows automated digest refreshes while still
// rejecting shortened, malformed, or mutable base-image references.
func assertDigestPinnedDockerBase(t *testing.T, dockerfile, prefix string) {
// 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(regexp.QuoteMeta(prefix) + `[0-9a-f]{64}(?:\s|$)`)
pattern := regexp.MustCompile(
`(?m)^` + regexp.QuoteMeta(prefix) + `[0-9a-f]{64}` + regexp.QuoteMeta(suffix) + `$`,
)
if !pattern.MatchString(dockerfile) {
t.Fatalf("Dockerfile base image must use a full immutable digest: %s<64 lowercase hex characters>", prefix)
t.Fatalf(
"Dockerfile stage must use a full immutable digest: %s<64 lowercase hex characters>%s",
prefix,
suffix,
)
}
}
@@ -332,9 +332,9 @@ func TestProviderMSPControlPlaneDockerfileBuildsReleaseLicenseBinary(t *testing.
"FROM alpine:3.21",
"CGO_ENABLED=0 go build -o /pulse-control-plane ./cmd/pulse-control-plane",
)
assertDigestPinnedDockerBase(t, text, `FROM --platform=linux/amd64 node:20-alpine@sha256:`)
assertDigestPinnedDockerBase(t, text, `FROM --platform=$BUILDPLATFORM golang:1.26.7-alpine@sha256:`)
assertDigestPinnedDockerBase(t, text, `FROM alpine:3.20@sha256:`)
assertDigestPinnedDockerStage(t, text, `FROM --platform=linux/amd64 node:20-alpine@sha256:`, ` AS frontend-builder`)
assertDigestPinnedDockerStage(t, text, `FROM --platform=$BUILDPLATFORM golang:1.26.7-alpine@sha256:`, ` AS builder`)
assertDigestPinnedDockerStage(t, text, `FROM alpine:3.20@sha256:`, ` AS control-plane-runtime-foundation`)
}
func assertContainsAll(t *testing.T, text string, required ...string) {
+22 -14
View File
@@ -12,6 +12,18 @@ CONFIG = ROOT / ".github" / "dependabot.yml"
SECURITY_SCAN = ROOT / ".github" / "workflows" / "security-scan.yml"
def manifest_directories(filename: str) -> list[str]:
"""Return repository-relative Dependabot directories for every manifest."""
directories = set()
for manifest in ROOT.rglob(filename):
relative = manifest.relative_to(ROOT)
if "node_modules" in relative.parts:
continue
parent = relative.parent.as_posix()
directories.add("/" if parent == "." else f"/{parent}")
return sorted(directories)
class DependabotConfigTest(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
@@ -26,17 +38,12 @@ class DependabotConfigTest(unittest.TestCase):
)
self.assertEqual(self.updates["github-actions"]["directory"], "/")
self.assertEqual(
self.updates["gomod"]["directories"],
["/", "/tests/integration/mock-github-server"],
sorted(self.updates["gomod"]["directories"]),
manifest_directories("go.mod"),
)
self.assertEqual(
self.updates["npm"]["directories"],
[
"/",
"/frontend-modern",
"/internal/cloudcp/portal/frontend",
"/tests/integration",
],
sorted(self.updates["npm"]["directories"]),
manifest_directories("package-lock.json"),
)
self.assertEqual(
self.updates["docker"]["directories"],
@@ -98,16 +105,17 @@ class DependabotConfigTest(unittest.TestCase):
jobs = workflow["jobs"]
self.assertEqual(
set(jobs["govulncheck"]["strategy"]["matrix"]["directory"]),
{".", "tests/integration/mock-github-server"},
{
"." if path == "/" else path.removeprefix("/")
for path in manifest_directories("go.mod")
},
)
npm_sets = jobs["npm-audit"]["strategy"]["matrix"]["include"]
self.assertEqual(
{item["directory"] for item in npm_sets},
{
".",
"frontend-modern",
"internal/cloudcp/portal/frontend",
"tests/integration",
"." if path == "/" else path.removeprefix("/")
for path in manifest_directories("package-lock.json")
},
)
scan_steps = jobs["npm-audit"]["steps"]