Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions pkg/dockerfile/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import (
// RegistryRegex matches registry references to registry.ci.openshift.org or quay-proxy.ci.openshift.org
var RegistryRegex = regexp.MustCompile(`(registry\.(?:svc\.)?ci\.openshift\.org|quay-proxy\.ci\.openshift\.org)/[^\s\\]+`)

// dockerfileLineContinuation matches Dockerfile backslash line continuations.
var dockerfileLineContinuation = regexp.MustCompile(`\\\r?\n[ \t]*`)

// OrgRepoTag represents a parsed image reference
type OrgRepoTag struct {
Org, Repo, Tag string
Expand All @@ -23,37 +26,44 @@ func (ort OrgRepoTag) String() string {
return ort.Org + "_" + ort.Repo + "_" + ort.Tag
}

// ExtractRegistryReferences finds all registry.ci.openshift.org and quay-proxy.ci.openshift.org references in the Dockerfile
// ExtractRegistryReferences finds registry.ci.openshift.org and quay-proxy.ci.openshift.org references in
// Dockerfile FROM, COPY --from=, and RUN instructions (e.g. podman pull).
func ExtractRegistryReferences(dockerfile []byte, from api.PipelineImageStreamTagReference) []string {
dockerfile = dockerfileLineContinuation.ReplaceAll(dockerfile, []byte(" "))

var refs []string
seen := sets.Set[string]{}
lastFromRef := ""
var lastFromLineRegistryRef string

for _, line := range bytes.Split(dockerfile, []byte("\n")) {
upper := bytes.ToUpper(line)
if !bytes.Contains(upper, []byte("FROM")) && !bytes.Contains(upper, []byte("COPY")) {
if !bytes.Contains(upper, []byte("FROM")) && !bytes.Contains(upper, []byte("COPY")) && !bytes.Contains(upper, []byte("RUN")) {
continue
}

if bytes.HasPrefix(upper, []byte("FROM")) {
lastFromLineRegistryRef = ""
if match := RegistryRegex.Find(line); match != nil {
lastFromLineRegistryRef = string(match)
}
}

match := RegistryRegex.Find(line)
if match == nil {
continue
}
ref := string(match)
if bytes.HasPrefix(upper, []byte("FROM")) {
lastFromRef = ref
}

if !seen.Has(ref) {
refs = append(refs, ref)
seen.Insert(ref)
}
}
if from != "" {
// If from is specified, remove the last detected FROM ref, it will be replaced
if from != "" && lastFromLineRegistryRef != "" {
// images[].from replaces the final Dockerfile stage; exclude only that stage's registry.ci reference
var newRefs []string
for _, ref := range refs {
if ref != lastFromRef {
if ref != lastFromLineRegistryRef {
newRefs = append(newRefs, ref)
}
}
Expand Down
44 changes: 44 additions & 0 deletions pkg/dockerfile/inputs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,50 @@ RUN echo "hello"
},
},
},
{
name: "RUN podman pull registry.ci reference",
dockerfile: `FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
RUN podman pull registry.ci.openshift.org/ocp/4.19:tools && cp bin/tool /usr/bin/tool
`,
expected: map[string]api.ImageStreamTagReference{
"ocp_4.19_tools": {
Namespace: "ocp",
Name: "4.19",
Tag: "tools",
As: "registry.ci.openshift.org/ocp/4.19:tools",
},
},
},
{
name: "RUN podman pull with line continuation",
dockerfile: `FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
RUN podman pull \
registry.ci.openshift.org/ocp/4.19:tools && cp bin/tool /usr/bin/tool
`,
expected: map[string]api.ImageStreamTagReference{
"ocp_4.19_tools": {
Namespace: "ocp",
Name: "4.19",
Tag: "tools",
As: "registry.ci.openshift.org/ocp/4.19:tools",
},
},
},
{
name: "from: ubi with external final stage keeps builder registry.ci FROM",
dockerfile: `FROM registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.22-openshift-4.18 AS builder
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
`,
from: "ubi",
expected: map[string]api.ImageStreamTagReference{
"ocp_builder_rhel-9-golang-1.22-openshift-4.18": {
Namespace: "ocp",
Name: "builder",
Tag: "rhel-9-golang-1.22-openshift-4.18",
As: "registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.22-openshift-4.18",
},
},
},
{
name: "from: is specified - should exclude the last detected FROM ref with COPY",
dockerfile: `FROM registry.ci.openshift.org/ocp/4.18:base AS builder
Expand Down