Skip to content

CONSOLE-5293: Update Dockerfile.downloads for 4.22 and add RHEL 8/9 oc binaries#16455

Open
jhadvig wants to merge 1 commit into
openshift:mainfrom
jhadvig:CONSOLE-5293
Open

CONSOLE-5293: Update Dockerfile.downloads for 4.22 and add RHEL 8/9 oc binaries#16455
jhadvig wants to merge 1 commit into
openshift:mainfrom
jhadvig:CONSOLE-5293

Conversation

@jhadvig
Copy link
Copy Markdown
Member

@jhadvig jhadvig commented May 15, 2026

Analysis / Root cause:

The Dockerfile.downloads still references OCP 4.18 base images, preventing the console-downloads image from building against the current 4.22 release in CI. Additionally, the downloads server does not serve the
RHEL 8 and RHEL 9 specific oc binaries that were recently added to the cli-artifacts image (console-operator#1102, OCPBUGS-57468).

This is a follow-up to CONSOLE-3340 to wire the console-downloads image into CI so it is built and promoted to the release payload.

Solution description:

  1. Dockerfile.downloads — Updated all three FROM directives from 4.18 to 4.22:

    • quay.io/openshift/origin-cli-artifacts:4.22
    • registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22
    • registry.ci.openshift.org/ocp/4.22:base-rhel9
  2. defaultArtifactsConfig.yaml — Added 8 new entries for oc.rhel8 and oc.rhel9 binaries across all Linux architectures (amd64, arm64, ppc64le, s390x), matching the paths served by the console-operator.

  3. downloads_config.go — Added a displayName() helper that derives a human-readable label from the binary basename (e.g. oc.rhel8"amd64 linux - RHEL 8"), so the HTML index page distinguishes
    RHEL-specific variants from the generic binary.

  4. downloads_config_test.go — Added unit tests for displayName and configureArchivePath covering generic, RHEL 8, RHEL 9, and .exe inputs.

Screenshots / screen recording:

Test setup:

No special setup required. The downloads server can be tested locally:
go build ./cmd/downloads/...
go test ./cmd/downloads/config/...

Test cases:

  • Unit tests pass: go test ./cmd/downloads/config/...
  • Backend builds cleanly: go build ./cmd/downloads/...
  • Dockerfile.downloads builds successfully locally
  • Downloads server index page lists RHEL 8 and RHEL 9 variants with distinct display names
  • Archive files are generated correctly as oc.rhel8.tar, oc.rhel8.zip, oc.rhel9.tar, oc.rhel9.zip

Additional info:

Summary by CodeRabbit

  • New Features

    • Added RHEL 8 and RHEL 9 download variants for amd64, arm64, ppc64le, and s390x architectures.
  • Chores

    • Updated Docker base image versions (4.22, Go 1.25).
    • Changed default server port from 8081 to 8080.
    • Optimized archive generation to run in the background.

…c binaries

Update base images from 4.18 to 4.22 so the console-downloads image
builds in CI against the current release. Add oc.rhel8 and oc.rhel9
binary entries for all Linux architectures (amd64, arm64, ppc64le,
s390x) to match the console-operator change (OCPBUGS-57468).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 15, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented May 15, 2026

@jhadvig: This pull request references CONSOLE-5293 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Analysis / Root cause:

The Dockerfile.downloads still references OCP 4.18 base images, preventing the console-downloads image from building against the current 4.22 release in CI. Additionally, the downloads server does not serve the
RHEL 8 and RHEL 9 specific oc binaries that were recently added to the cli-artifacts image (console-operator#1102, OCPBUGS-57468).

This is a follow-up to CONSOLE-3340 to wire the console-downloads image into CI so it is built and promoted to the release payload.

Solution description:

  1. Dockerfile.downloads — Updated all three FROM directives from 4.18 to 4.22:

    • quay.io/openshift/origin-cli-artifacts:4.22
    • registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22
    • registry.ci.openshift.org/ocp/4.22:base-rhel9
  2. defaultArtifactsConfig.yaml — Added 8 new entries for oc.rhel8 and oc.rhel9 binaries across all Linux architectures (amd64, arm64, ppc64le, s390x), matching the paths served by the console-operator.

  3. downloads_config.go — Added a displayName() helper that derives a human-readable label from the binary basename (e.g. oc.rhel8"amd64 linux - RHEL 8"), so the HTML index page distinguishes
    RHEL-specific variants from the generic binary.

  4. downloads_config_test.go — Added unit tests for displayName and configureArchivePath covering generic, RHEL 8, RHEL 9, and .exe inputs.

Screenshots / screen recording:

Test setup:

No special setup required. The downloads server can be tested locally:
go build ./cmd/downloads/...
go test ./cmd/downloads/config/...

Test cases:

  • Unit tests pass: go test ./cmd/downloads/config/...
  • Backend builds cleanly: go build ./cmd/downloads/...
  • Dockerfile.downloads builds successfully locally
  • Downloads server index page lists RHEL 8 and RHEL 9 variants with distinct display names
  • Archive files are generated correctly as oc.rhel8.tar, oc.rhel8.zip, oc.rhel9.tar, oc.rhel9.zip

Additional info:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot requested review from Leo6Leo and spadgett May 15, 2026 17:36
@openshift-ci openshift-ci Bot added the component/backend Related to backend label May 15, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 15, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jhadvig

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 15, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

📝 Walkthrough

Walkthrough

This PR refactors the OpenShift Console downloads server to generate binary archives asynchronously. It extends the artifact configuration to include RHEL 8 and RHEL 9 variants across multiple architectures (amd64, arm64, ppc64le, s390x), upgrades container base images to newer versions, and introduces a synchronization mechanism that allows non-archive HTTP requests to be served immediately while blocking archive requests until tar/zip files are ready. The implementation uses concurrent goroutines to create archives in the background, a coordination channel to signal completion, and an HTTP handler wrapper that enforces request-level synchronization.

🚥 Pre-merge checks | ✅ 11 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (11 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and specifically references the main changes: updating Dockerfile.downloads for 4.22 and adding RHEL 8/9 oc binaries.
Description check ✅ Passed The description covers all required template sections: analysis/root cause, solution details, test setup, test cases, and related links. All critical information is present and well-structured.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PR uses standard Go testing, not Ginkgo. Check for stable Ginkgo test names is not applicable—no Ginkgo framework in codebase.
Test Structure And Quality ✅ Passed Custom check for Ginkgo test structure not applicable. Repository uses standard Go testing (testing.T), not Ginkgo BDD framework. PR test file follows established Go testing patterns in codebase.
Microshift Test Compatibility ✅ Passed PR does not add Ginkgo e2e tests. It only adds standard Go unit tests using testing.T in downloads_config_test.go. Custom check applies only to Ginkgo e2e tests, so it is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR contains only Go unit tests using standard testing package, not Ginkgo e2e tests. SNO compatibility check does not apply to unit tests.
Topology-Aware Scheduling Compatibility ✅ Passed Check not applicable. PR modifies only container image build config, HTTP server application code, and artifact listings—no K8s manifests, operator code, or controllers are added/modified.
Ote Binary Stdout Contract ✅ Passed cmd/downloads/main.go is a regular HTTP server, not an OTE test binary. klog v2 defaults to stderr; code properly initializes klog and has no stdout writes in process-level code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No Ginkgo e2e tests found in PR. The test file cmd/downloads/config/downloads_config_test.go uses standard Go testing package with 6 unit tests, not Ginkgo DSL. Check is not applicable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
cmd/downloads/config/downloads_config_test.go (1)

109-126: ⚡ Quick win

Avoid order-coupled assertions in generated entries.

Asserting content[1]/content[2] makes this test fragile to harmless ordering changes. Assert by URL key instead.

Suggested refactor
-	linux := content[1]
-	if linux.URL != "amd64/linux/oc" {
-		t.Errorf("expected URL %q, got %q", "amd64/linux/oc", linux.URL)
-	}
-	if linux.TarURL != "amd64/linux/oc.tar" {
-		t.Errorf("expected TarURL %q, got %q", "amd64/linux/oc.tar", linux.TarURL)
-	}
-
-	win := content[2]
-	if win.URL != "amd64/windows/oc.exe" {
-		t.Errorf("expected URL %q, got %q", "amd64/windows/oc.exe", win.URL)
-	}
-	if win.TarURL != "amd64/windows/oc.tar" {
-		t.Errorf("expected TarURL %q, got %q", "amd64/windows/oc.tar", win.TarURL)
-	}
-	if win.ZipURL != "amd64/windows/oc.zip" {
-		t.Errorf("expected ZipURL %q, got %q", "amd64/windows/oc.zip", win.ZipURL)
-	}
+	byURL := map[string]ListItemLink{}
+	for _, item := range content {
+		byURL[item.URL] = item
+	}
+
+	linux, ok := byURL["amd64/linux/oc"]
+	if !ok {
+		t.Fatalf("missing linux entry")
+	}
+	if linux.TarURL != "amd64/linux/oc.tar" {
+		t.Errorf("expected TarURL %q, got %q", "amd64/linux/oc.tar", linux.TarURL)
+	}
+
+	win, ok := byURL["amd64/windows/oc.exe"]
+	if !ok {
+		t.Fatalf("missing windows entry")
+	}
+	if win.TarURL != "amd64/windows/oc.tar" {
+		t.Errorf("expected TarURL %q, got %q", "amd64/windows/oc.tar", win.TarURL)
+	}
+	if win.ZipURL != "amd64/windows/oc.zip" {
+		t.Errorf("expected ZipURL %q, got %q", "amd64/windows/oc.zip", win.ZipURL)
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/downloads/config/downloads_config_test.go` around lines 109 - 126, The
test currently relies on fixed indices (content[1], content[2]) for entries
(variables linux, win) which makes it fragile; instead, build a lookup from the
content slice keyed by the entry.URL (or find entries by matching URL) and then
assert TarURL/ZipURL values from that map/lookup for the keys "amd64/linux/oc"
and "amd64/windows/oc.exe"; update assertions that reference
linux.URL/linux.TarURL and win.URL/win.TarURL/win.ZipURL to use the mapped
entries so the test no longer depends on ordering of the content slice.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/downloads/config/downloads_config_test.go`:
- Around line 158-161: The test currently ignores errors from os.Open and from
Close calls and should mirror production error handling: change the os.Open call
used before tar.NewReader to capture and check the error (e.g., handle the
returned error and fail the test on open failure), defer closing the opened file
and check the error returned by Close (or capture Close error from the deferred
call), and ensure the tar reader's tr.Next() error (the err after hdr, err :=
tr.Next()) is checked and handled; likewise move the zip reader Close
(zr.Close()) into a defer and check its returned error. Update the code around
os.Open, tar.NewReader/tr.Next, and zr.Close to perform proper error checks and
use defer for cleanup.

In `@cmd/downloads/config/downloads_config.go`:
- Around line 383-387: The final goroutine currently always logs "All archives
created successfully" after wg.Wait() and closing c.archivesReady; change it to
track whether any createArchive call failed (e.g., set a shared failure flag via
an atomic.Bool or send errors to an errs channel read before logging) and only
emit the success message when no failures were recorded; otherwise log a
distinct error/warning indicating that one or more archive creations failed.
Update the goroutine that calls wg.Wait() and close(c.archivesReady) to inspect
that failure indicator (or aggregated errors) and choose the appropriate log
message, referencing createArchive, c.archivesReady, and the wg.Wait()
goroutine.

In `@Dockerfile.downloads`:
- Around line 1-3: Replace the mutable UBI image tag used in the Dockerfile by
updating the image reference
"registry.access.redhat.com/ubi9/ubi-minimal:latest" to a stable versioned tag
(for example "registry.access.redhat.com/ubi9/ubi-minimal:9.7") so builds are
reproducible and consistent with the other versioned images like
"quay.io/openshift/origin-cli-artifacts:4.22" and
"registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22";
locate the line containing the
"registry.access.redhat.com/ubi9/ubi-minimal:latest" image and replace ":latest"
with the chosen stable version.

---

Nitpick comments:
In `@cmd/downloads/config/downloads_config_test.go`:
- Around line 109-126: The test currently relies on fixed indices (content[1],
content[2]) for entries (variables linux, win) which makes it fragile; instead,
build a lookup from the content slice keyed by the entry.URL (or find entries by
matching URL) and then assert TarURL/ZipURL values from that map/lookup for the
keys "amd64/linux/oc" and "amd64/windows/oc.exe"; update assertions that
reference linux.URL/linux.TarURL and win.URL/win.TarURL/win.ZipURL to use the
mapped entries so the test no longer depends on ordering of the content slice.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: c6874bf1-9a63-4e2c-aa91-08a658853e0d

📥 Commits

Reviewing files that changed from the base of the PR and between ee38b13 and 2516ced.

📒 Files selected for processing (5)
  • Dockerfile.downloads
  • cmd/downloads/config/defaultArtifactsConfig.yaml
  • cmd/downloads/config/downloads_config.go
  • cmd/downloads/config/downloads_config_test.go
  • cmd/downloads/main.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{yaml,yml,go}

📄 CodeRabbit inference engine (Custom checks)

When deployment manifests, operator code, or controllers are added/modified, check for scheduling constraints assuming standard HA topology (3+ CP nodes, dedicated workers). Flag: required pod anti-affinity with hostname topology key, pod topology spread with DoNotSchedule and hostname key, replica counts derived from node count, nodeSelector/affinity targeting control-plane nodes, broad tolerations that could schedule to resource-constrained arbiter nodes, assuming dedicated worker nodes exist, or PodDisruptionBudgets designed for 3+ nodes. Consider SNO (1 node), DualReplica (2 CP nodes), HighlyAvailableArbiter (2 CP + 1 arbiter), and External (HyperShift) topologies

Files:

  • cmd/downloads/main.go
  • cmd/downloads/config/downloads_config_test.go
  • cmd/downloads/config/downloads_config.go
  • cmd/downloads/config/defaultArtifactsConfig.yaml
**/*_test.go

📄 CodeRabbit inference engine (Custom checks)

**/*_test.go: When new Ginkgo e2e tests are added, check for IPv4 assumptions: hardcoded IPv4 addresses (10.0.0.1, 192.168.1.1, 172.16.0.0/12), IPv4 localhost (127.0.0.1 without ::1), IPv4-only IP parsing, hardcoded IPv4 CIDRs in Service/Endpoint objects, hardcoded net.ParseIP/ParseCIDR values, IPv4-only pod/node IP assumptions, IPv4-only network policies, and URLs built without brackets for IPv6 (use net.JoinHostPort instead)
When new Ginkgo e2e tests are added, check for external connectivity requirements: connections to public internet hosts, pulling images from public registries without mirrors, downloading from external URLs, DNS resolution of public hostnames, and connections to external APIs/services outside the cluster. If requiring external connectivity that cannot be adapted, add [Skipped:Disconnected] to test name
When new Ginkgo e2e tests are added, check for usage of unavailable MicroShift APIs: Project/ProjectRequest, Build/BuildConfig, DeploymentConfig, ClusterOperator, ClusterVersion, Etcd operator, CSV/OLM resources, MachineSet/Machine/MachineHealthCheck, ClusterAutoscaler, Console, Monitoring stack, ImageRegistry operator, Samples operator, OperatorHub/CatalogSource, CloudCredential, Storage operator, Network operator CRDs, and any OpenShift API except Route and SecurityContextConstraints. Also flag references to namespaces openshift-kube-apiserver, openshift-kube-controller-manager, openshift-kube-scheduler. If flagged and test is intentional, use [Skipped:MicroShift] label or [apigroup:...] tag or guard with exutil.IsMicroShiftCluster() check
OpenShift Tests Extension (OTE) binaries must output valid JSON to stdout at process level. Flag any non-JSON stdout writes in main(), init(), TestMain(), BeforeSuite(), AfterSuite(), SynchronizedBeforeSuite(), RunSpecs() setup, or top-level var/const initializers. Common violations: klog writing to stdout (use klog.SetOutput(os.Stderr) or klog.LogToStderr(true)), fmt.Print/Println/Printf to stdout in main...

Files:

  • cmd/downloads/config/downloads_config_test.go
🪛 golangci-lint (2.12.2)
cmd/downloads/config/downloads_config_test.go

[error] 161-161: Error return value of f.Close is not checked

(errcheck)


[error] 205-205: net/http/httptest.NewRequest must not be called. use net/http/httptest.NewRequestWithContext

(noctx)


[error] 216-216: net/http/httptest.NewRequest must not be called. use net/http/httptest.NewRequestWithContext

(noctx)


[error] 258-258: net/http/httptest.NewRequest must not be called. use net/http/httptest.NewRequestWithContext

(noctx)

🔀 Multi-repo context openshift/console-operator

Findings for openshift/console-operator:

  • pkg/console/controllers/clidownloads/controller.go: entries adding RHEL variants (display name, path, archive name):

    • lines with {"Linux for x86_64 - RHEL 8", "amd64/linux", "oc.rhel8.tar"} and {"Linux for x86_64 - RHEL 9", "amd64/linux", "oc.rhel9.tar"}; likewise for arm64, ppc64le, s390x. [::openshift/console-operator::pkg/console/controllers/clidownloads/controller.go]
  • pkg/console/controllers/clidownloads/controller_test.go: tests expecting Href links to oc.rhel8.tar and oc.rhel9.tar for amd64/arm64/ppc64le/s390x. [::openshift/console-operator::pkg/console/controllers/clidownloads/controller_test.go]

  • bindata/assets/deployments/downloads-deployment.yaml: deployment asset includes file paths for oc.rhel8 and oc.rhel9 under /usr/share/openshift/... for amd64, arm64, ppc64le, s390x and comment about stripping .exe vs keeping oc.rhel8. [::openshift/console-operator::bindata/assets/deployments/downloads-deployment.yaml]

  • test/e2e/downloads_test.go and other tests reference the clidownloads controller and downloads deployment; e2e tests may exercise the new RHEL variants. [::openshift/console-operator::test/e2e/downloads_test.go]

Implication: The console-operator repo already contains support and tests for oc.rhel8/oc.rhel9 artifacts and controller logic; the PR’s changes to console downloads (adding RHEL 8/9 artifacts and display/handler behavior) align with existing consumers and deployment assets in this repo. [::openshift/console-operator::]

🔇 Additional comments (11)
cmd/downloads/config/defaultArtifactsConfig.yaml (1)

5-10: LGTM!

Also applies to: 20-25, 32-46

cmd/downloads/config/downloads_config.go (5)

8-12: LGTM!


61-62: LGTM!


218-228: LGTM!


343-351: LGTM!


390-401: LGTM!

cmd/downloads/main.go (2)

33-34: LGTM!

Also applies to: 41-41


19-19: 💤 Low value

The premise is inaccurate. cmd/downloads/main.go is a new file added in this PR (status: Added), not a modification of an existing file. There was no prior port value to change from. The port 8080 is the initial default and aligns correctly with the console-operator's existing deployment expectations (confirmed in console-operator's downloads-deployment.yaml).

No coordination issue exists—the operator already expects port 8080.

			> Likely an incorrect or invalid review comment.
Dockerfile.downloads (1)

33-33: LGTM!

cmd/downloads/config/downloads_config_test.go (2)

17-107: LGTM!

Also applies to: 129-157, 168-204, 241-257, 262-269


205-205: ⚡ Quick win

This review comment does not apply to this project.

The openshift/console project does not enforce the noctx linting rule. No .golangci.yml or Go linting configuration exists in the repository, and the STYLEGUIDE.md (which documents Go best practices) makes no mention of requiring context with httptest.NewRequest. The pattern of using httptest.NewRequest without context is consistent throughout the codebase—including pkg/olm/handler_test.go, pkg/server/robots_test.go, and other test files—establishing it as the project's standard convention.

While using httptest.NewRequestWithContext(context.Background(), ...) is a general Go best practice, it is not a linting requirement in this project and would not "fail lint gates."

			> Likely an incorrect or invalid review comment.

Comment on lines +158 to +161
f, _ := os.Open(tarPath)
tr := tar.NewReader(f)
hdr, err := tr.Next()
f.Close()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify remaining unchecked open/close patterns in this test file
rg -n 'os\.Open\(|\.Close\(\)' --type go cmd/downloads/config/downloads_config_test.go

Repository: openshift/console

Length of output: 126


🏁 Script executed:

#!/bin/bash
# Read the test file to see the full context around lines 158-180
sed -n '150,185p' cmd/downloads/config/downloads_config_test.go | cat -n

Repository: openshift/console

Length of output: 1335


🏁 Script executed:

#!/bin/bash
# Check for errcheck or golangci-lint config
find . -maxdepth 2 -type f \( -name ".golangci.yml" -o -name "golangci.yaml" -o -name ".golangci.yaml" -o -name ".errcheck*" -o -name "Makefile" -o -name "go.mod" \) | head -20

Repository: openshift/console

Length of output: 70


🏁 Script executed:

#!/bin/bash
# Check if errcheck or linting is mentioned in the repo
rg -l "errcheck|golangci" --type go --type yaml . | head -10

Repository: openshift/console

Length of output: 605


🏁 Script executed:

#!/bin/bash
# Check for linting config at project root
ls -la | grep -E "^\.|Makefile|golangci|lint"

Repository: openshift/console

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Check if there's a Makefile with lint/test targets
head -100 Makefile 2>/dev/null | grep -E "lint|errcheck|vet|test" || echo "No Makefile or matches found"

Repository: openshift/console

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Check for CI configuration (GitHub Actions, etc.) that might run linting
find .github -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -5

Repository: openshift/console

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Check if there are other test files in the same directory with error handling patterns
ls -la cmd/downloads/config/ | grep test

Repository: openshift/console

Length of output: 136


🏁 Script executed:

#!/bin/bash
# Look at error handling patterns in other test files in this project
rg -l 'os\.Open|\.Close\(\)' --type go cmd/downloads/ | head -5

Repository: openshift/console

Length of output: 148


🏁 Script executed:

#!/bin/bash
# Check the non-test file for error handling patterns with file operations
rg -n 'os\.Open|\.Close\(\)' --type go cmd/downloads/config/downloads_config.go -A 2

Repository: openshift/console

Length of output: 743


🏁 Script executed:

#!/bin/bash
# Check the full context of the tar and zip handling in the test to understand the complete picture
sed -n '155,185p' cmd/downloads/config/downloads_config_test.go

Repository: openshift/console

Length of output: 890


Handle os.Open and Close errors in tar/zip verification.

The test ignores the error from os.Open() (line 158) and unchecked Close() calls (lines 161, 180), which violates error handling best practices and will fail errcheck. The production code properly checks errors after file operations; apply the same rigor here. Consider using defer for cleanup instead, matching the production pattern.

Suggested fix
-		f, _ := os.Open(tarPath)
+		f, err := os.Open(tarPath)
+		if err != nil {
+			t.Errorf("failed to open tar %s: %v", tarPath, err)
+			continue
+		}
+		defer f.Close()
 		tr := tar.NewReader(f)
 		hdr, err := tr.Next()
-		f.Close()
 		if err != nil {
 			t.Errorf("failed to read tar %s: %v", tarPath, err)
 		} else if hdr.Name != basename {

Also check zr.Close() at line 180 (zip reader) — move it into a defer or check the error.

🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 161-161: Error return value of f.Close is not checked

(errcheck)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/downloads/config/downloads_config_test.go` around lines 158 - 161, The
test currently ignores errors from os.Open and from Close calls and should
mirror production error handling: change the os.Open call used before
tar.NewReader to capture and check the error (e.g., handle the returned error
and fail the test on open failure), defer closing the opened file and check the
error returned by Close (or capture Close error from the deferred call), and
ensure the tar reader's tr.Next() error (the err after hdr, err := tr.Next()) is
checked and handled; likewise move the zip reader Close (zr.Close()) into a
defer and check its returned error. Update the code around os.Open,
tar.NewReader/tr.Next, and zr.Close to perform proper error checks and use defer
for cleanup.

Comment on lines +383 to +387
go func() {
wg.Wait()
close(c.archivesReady)
klog.Info("All archives created successfully")
}()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Success message logged unconditionally, even when archive creation fails.

If any createArchive call fails, the error is logged but archivesReady is still closed and the "All archives created successfully" message is emitted. This can mask failures during incident investigation.

Consider tracking failure state and adjusting the final log accordingly.

🛠️ Proposed fix
 func (c *DownloadsServerConfig) CreateArchivesInBackground() {
 	c.archivesReady = make(chan struct{})
 	var wg sync.WaitGroup
+	var errCount int32
+	var errMu sync.Mutex

 	for _, spec := range c.Spec {
 		basename := filepath.Base(spec.Path)
 		artifactPath := filepath.Join(c.TempDir, spec.Arch, spec.OperatingSystem, basename)

 		wg.Add(2)
 		go func(p string) {
 			defer wg.Done()
 			if err := createArchive(p, ".tar"); err != nil {
 				klog.Errorf("Failed to create tar archive for %s: %v", p, err)
+				errMu.Lock()
+				errCount++
+				errMu.Unlock()
 			}
 		}(artifactPath)
 		go func(p string) {
 			defer wg.Done()
 			if err := createArchive(p, ".zip"); err != nil {
 				klog.Errorf("Failed to create zip archive for %s: %v", p, err)
+				errMu.Lock()
+				errCount++
+				errMu.Unlock()
 			}
 		}(artifactPath)
 	}

 	go func() {
 		wg.Wait()
 		close(c.archivesReady)
-		klog.Info("All archives created successfully")
+		if errCount > 0 {
+			klog.Warningf("Archive creation completed with %d failures", errCount)
+		} else {
+			klog.Info("All archives created successfully")
+		}
 	}()
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/downloads/config/downloads_config.go` around lines 383 - 387, The final
goroutine currently always logs "All archives created successfully" after
wg.Wait() and closing c.archivesReady; change it to track whether any
createArchive call failed (e.g., set a shared failure flag via an atomic.Bool or
send errors to an errs channel read before logging) and only emit the success
message when no failures were recorded; otherwise log a distinct error/warning
indicating that one or more archive creations failed. Update the goroutine that
calls wg.Wait() and close(c.archivesReady) to inspect that failure indicator (or
aggregated errors) and choose the appropriate log message, referencing
createArchive, c.archivesReady, and the wg.Wait() goroutine.

Comment thread Dockerfile.downloads
Comment on lines +1 to +3
FROM quay.io/openshift/origin-cli-artifacts:4.22 AS origincli

FROM registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.22-openshift-4.18 AS gobuilder
FROM registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22 AS gobuilder
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="$(fd '^Dockerfile\.downloads$' | head -n1)"

echo "== FROM lines =="
awk '/^FROM / { print NR ":" $0 }' "$FILE"

echo
echo "== Unpinned FROM lines (missing `@sha256`) =="
awk '/^FROM / && $2 !~ /@sha256:/ { print NR ":" $0 }' "$FILE"

echo
echo "== Mutable latest tags =="
awk '/^FROM / && $2 ~ /:latest($|[[:space:]])/ { print NR ":" $0 }' "$FILE"

Repository: openshift/console

Length of output: 639


🏁 Script executed:

#!/bin/bash
# Find all Dockerfiles and check their FROM line patterns
find . -name "Dockerfile*" -type f | head -20

Repository: openshift/console

Length of output: 439


🏁 Script executed:

#!/bin/bash
# Check other Dockerfiles for digest pinning patterns
find . -name "Dockerfile*" -type f -exec grep -H "^FROM" {} + | head -30

Repository: openshift/console

Length of output: 2300


🏁 Script executed:

#!/bin/bash
# Check console-operator Dockerfiles for digest pinning patterns
find . -name "Dockerfile*" -type f -exec grep -H "^FROM" {} + | head -30

Repository: openshift/console-operator

Length of output: 767


🏁 Script executed:

#!/bin/bash
# Check context around the Dockerfile.downloads file to understand the UBI choice
cat -n Dockerfile.downloads | head -25

Repository: openshift/console

Length of output: 997


🌐 Web query:

registry.access.redhat.com/ubi9/ubi-minimal latest stable versions tags

💡 Result:

As of May 15, 2026, the latest stable version of the Red Hat Universal Base Image 9 Minimal (ubi9-minimal) is 9.7 [1][2]. The Red Hat Container Registry uses a tagging system that includes both major/minor version tags and specific build-based tags [1]. You can access the image using the following primary tags: - latest: Always points to the most recent stable release of the image [1]. - 9.7: Points to the current stable minor release [1]. - 9.7-: Points to a specific, immutable build of the 9.7 release (e.g., 9.7-1778562320) [1]. Additionally, Red Hat provides corresponding source images for these tags, which can be accessed by appending -source to the tag (e.g., 9.7-source) [1][2]. To view the most up-to-date list of available tags, you can check the Red Hat Ecosystem Catalog [2] or the official Red Hat repository on Docker Hub [1][3]. For programmatic access or to mirror images, it is recommended to use the skopeo tool to list tags directly from the registry [2][4].

Citations:


Replace mutable :latest tag on Line 17 with a stable version tag.

Line 17 uses registry.access.redhat.com/ubi9/ubi-minimal:latest, which is mutable and inconsistent with the versioned approach elsewhere in the Dockerfile. Replace with a stable version tag like 9.7 to ensure reproducible builds and align with the versioned tags used on lines 1 and 3.

Suggested change
-FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
+FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.downloads` around lines 1 - 3, Replace the mutable UBI image tag
used in the Dockerfile by updating the image reference
"registry.access.redhat.com/ubi9/ubi-minimal:latest" to a stable versioned tag
(for example "registry.access.redhat.com/ubi9/ubi-minimal:9.7") so builds are
reproducible and consistent with the other versioned images like
"quay.io/openshift/origin-cli-artifacts:4.22" and
"registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22";
locate the line containing the
"registry.access.redhat.com/ubi9/ubi-minimal:latest" image and replace ":latest"
with the chosen stable version.

@jhadvig
Copy link
Copy Markdown
Member Author

jhadvig commented May 15, 2026

/retest

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 15, 2026

@jhadvig: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. component/backend Related to backend jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants