Review: one local name is still a local name; a local name is unique; recovery knows it; recipes read as instructions; a tag before a digest; ask fails at once when nothing serves

A secrets object with one local name delivered no file. Two requirements could share
a local name. secret recover and the export could not tell two locals apart. The
recipe check missed continued lines and read heredoc bodies as bases. repo:tag@digest
kept the tag in the repository. ask now publishes mandatory, so a tool nothing serves
is said at once rather than after the wait.
This commit is contained in:
2026-09-21 21:03:22 +02:00
parent e81f352979
commit 9f3790dcda
13 changed files with 229 additions and 29 deletions
+19
View File
@@ -133,3 +133,22 @@ FROM golang:1.25-alpine AS go
t.Fatalf("declared arguments are not fetches: %v", copies)
}
}
// Continued lines are one instruction, heredoc bodies are not instructions, and a RUN --mount reaches
// for an image as a COPY --from does (review C4, C5).
func TestARecipeIsReadAsInstructions(t *testing.T) {
recipe := "ARG RUNTIME_BASE\n" +
"FROM ${RUNTIME_BASE} \\\n AS build\n" +
"COPY \\\n --from=docker.io/vendor/one:latest /a /a\n" +
"COPY --from=build /out /out\n" +
"COPY <<EOF /app/x.py\nfrom os import path\nEOF\n" +
"RUN --mount=type=bind,from=docker.io/vendor/two:1,target=/t cp /t/x /x\n" +
"FROM scratch\n"
bases, copies := undeclaredFetches(recipe, map[string]bool{"RUNTIME_BASE": true})
if strings.Join(copies, "|") != "docker.io/vendor/one:latest|docker.io/vendor/two:1" {
t.Fatalf("copies: %v", copies)
}
if len(bases) != 0 {
t.Fatalf("a heredoc line or a continued stage was read as a base: %v", bases)
}
}