Skip to content

NO-JIRA: Align CI builder image with hypershift (openshift-4.23)#252

Draft
jparrill wants to merge 1 commit intoopenshift:mainfrom
jparrill:NO-JIRA-align-builders-4.23
Draft

NO-JIRA: Align CI builder image with hypershift (openshift-4.23)#252
jparrill wants to merge 1 commit intoopenshift:mainfrom
jparrill:NO-JIRA-align-builders-4.23

Conversation

@jparrill
Copy link
Copy Markdown
Contributor

@jparrill jparrill commented May 7, 2026

Summary

  • Update Dockerfile CI builder from openshift-4.22 to openshift-4.23 to align with the hypershift repository
  • Add integration tests to validate golang version consistency across all Dockerfiles and detect stale OCP version references
  • Dockerfile.oadp and konflux.Dockerfile already use brew-based images (rhel_9_golang_1.25) and require no changes

Test plan

  • go build ./... passes
  • go test -race ./tests/integration/builders/... passes (14 test cases)
  • CI image build succeeds with the new openshift-4.23 builder
  • Verify golang version consistency across all three Dockerfiles

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Updated Docker base image to the latest OpenShift 4.23 release version.
  • Tests

    • Added integration tests to validate Go version consistency across Dockerfiles.

Update the Dockerfile CI builder from openshift-4.22 to openshift-4.23
to stay aligned with the hypershift repository. Add integration tests
to validate golang version consistency across all Dockerfiles and detect
stale OCP version references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Juan Manuel Parrilla Madrid <jparrill@redhat.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 7, 2026
@openshift-ci-robot
Copy link
Copy Markdown

@jparrill: This pull request explicitly references no jira issue.

Details

In response to this:

Summary

  • Update Dockerfile CI builder from openshift-4.22 to openshift-4.23 to align with the hypershift repository
  • Add integration tests to validate golang version consistency across all Dockerfiles and detect stale OCP version references
  • Dockerfile.oadp and konflux.Dockerfile already use brew-based images (rhel_9_golang_1.25) and require no changes

Test plan

  • go build ./... passes
  • go test -race ./tests/integration/builders/... passes (14 test cases)
  • CI image build succeeds with the new openshift-4.23 builder
  • Verify golang version consistency across all three Dockerfiles

🤖 Generated with Claude Code

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 added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 7, 2026
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 7, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Walkthrough

The Docker build stage base image is updated from OpenShift 4.22 to 4.23. A new integration test suite validates Go version consistency across Dockerfiles and prevents introduction of stale OpenShift version references.

Changes

Base Image and Dockerfile Validation

Layer / File(s) Summary
Base Image Update
Dockerfile
Multi-stage build image tag updated from openshift-4.22 to openshift-4.23.
Dockerfile Parsing Logic
tests/integration/builders/builders_test.go
Helper functions extract Go versions from Dockerfile FROM lines and #@follow_tag annotations; additional helpers deduplicate versions, format debug output, and locate project root via go.mod.
Validation Tests
tests/integration/builders/builders_test.go
TestBuilderImages ensures consistent Go versions across all Dockerfiles and validates that the main Dockerfile does not reference stale openshift-4.21 or openshift-4.22 versions. TestExtractGolangVersions verifies parsing of multiple FROM lines, #@follow_tag annotations, and edge cases. TestVersionConsistencyDetection validates deduplication logic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Stable And Deterministic Test Names ❌ Error Line 84 uses fmt.Sprintf() to construct test name with dynamic content from staleOCPVersions loop, violating stable deterministic name requirement. Replace fmt.Sprintf() test name with static string. Dynamic values belong in test bodies, not titles. Use generic name like "should not reference stale OCP versions".
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: updating the CI builder image from openshift-4.22 to openshift-4.23 to align with hypershift, which is the primary modification in the Dockerfile.
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.
Test Structure And Quality ✅ Passed Tests meet quality requirements: proper single responsibility via t.Run, automatic cleanup via t.TempDir, no cluster ops (timeouts N/A), helpful assertion messages, repo pattern consistency.
Microshift Test Compatibility ✅ Passed Not applicable: The PR adds standard Go tests using testing.T, not Ginkgo e2e tests. Tests only validate Dockerfile content; no cluster or API interaction.
Single Node Openshift (Sno) Test Compatibility ✅ Passed Tests added use standard Go testing framework, not Ginkgo e2e tests. They test Dockerfile parsing and CI builder image versions, not OpenShift cluster topology.
Topology-Aware Scheduling Compatibility ✅ Passed The check applies to deployment manifests and operator code. This PR only updates a Dockerfile image reference and adds tests—no scheduling constraints are introduced.
Ote Binary Stdout Contract ✅ Passed Test file added contains no process-level stdout writes. No TestMain, init, suite setup. Top-level variables use safe initialization. All fmt usage within test functions.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Tests are standard Go unit tests for Dockerfile parsing, not Ginkgo e2e tests. No IPv4 assumptions or external connectivity requirements detected. Check not applicable.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 7, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jparrill

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

Copy link
Copy Markdown

@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

🤖 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 `@tests/integration/builders/builders_test.go`:
- Around line 51-57: The test currently appends dockerfileInfo even when
extractGolangVersionsFromDockerfile(df.path) returns an empty versions slice,
allowing a file with no parsed Go versions to slip through; update the test loop
so after calling extractGolangVersionsFromDockerfile (the call using df.path and
df.name) you assert that the returned versions slice is non-empty (fail fast per
file) before appending to parsedFiles, e.g. use a Gomega Expect/Require on
len(versions) > 0 with a message referencing df.name to surface parser drift or
tag-format changes immediately; apply the same per-file guard for the other loop
block that handles files at lines 63-71.
- Around line 198-204: The helper function extractGolangVersionsFromDockerfile
currently ignores errors from file.Close(), which can hide IO failures; change
the function to use named return values (e.g., results []string, err error) and
replace defer file.Close() with a deferred closure that captures the close error
(if cerr := file.Close(); cerr != nil && err == nil { err = fmt.Errorf("close
failed: %w", cerr) }) so the close error is propagated while preserving any
existing error from the function.
- Around line 150-153: The tmpFile.Close() call currently ignores its returned
error; change it to capture and assert the result (e.g., err = tmpFile.Close();
g.Expect(err).NotTo(HaveOccurred()) or use a short variable like if cerr :=
tmpFile.Close(); g.Expect(cerr).NotTo(HaveOccurred())). Update the Close
invocation where tmpFile is used so any flush/I/O errors are checked and cause
the test to fail.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9a20185c-4858-494c-9b83-f36709f49c8b

📥 Commits

Reviewing files that changed from the base of the PR and between 0764600 and d09dc0d.

📒 Files selected for processing (2)
  • Dockerfile
  • tests/integration/builders/builders_test.go

Comment on lines +51 to +57
versions, err := extractGolangVersionsFromDockerfile(df.path)
g.Expect(err).NotTo(HaveOccurred(), "Should parse %s without error", df.name)

parsedFiles = append(parsedFiles, dockerfileInfo{
path: df.name,
golangVersions: versions,
})
Copy link
Copy Markdown

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

Add a per-Dockerfile guard for empty extracted Go versions.

Right now, consistency can still pass if one file contributes no extracted version at all. Please fail fast per file so parser drift or tag format changes are caught.

Suggested fix
 			versions, err := extractGolangVersionsFromDockerfile(df.path)
 			g.Expect(err).NotTo(HaveOccurred(), "Should parse %s without error", df.name)
+			g.Expect(versions).NotTo(BeEmpty(),
+				"%s should expose at least one golang version via FROM or #@follow_tag", df.name)

 			parsedFiles = append(parsedFiles, dockerfileInfo{
 				path:           df.name,
 				golangVersions: versions,
 			})

Also applies to: 63-71

🤖 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 `@tests/integration/builders/builders_test.go` around lines 51 - 57, The test
currently appends dockerfileInfo even when
extractGolangVersionsFromDockerfile(df.path) returns an empty versions slice,
allowing a file with no parsed Go versions to slip through; update the test loop
so after calling extractGolangVersionsFromDockerfile (the call using df.path and
df.name) you assert that the returned versions slice is non-empty (fail fast per
file) before appending to parsedFiles, e.g. use a Gomega Expect/Require on
len(versions) > 0 with a message referencing df.name to surface parser drift or
tag-format changes immediately; apply the same per-file guard for the other loop
block that handles files at lines 63-71.

Comment on lines +150 to +153
_, err = tmpFile.WriteString(tc.dockerfileContent)
g.Expect(err).NotTo(HaveOccurred())
tmpFile.Close()

Copy link
Copy Markdown

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:

cat -n tests/integration/builders/builders_test.go | sed -n '145,160p'

Repository: openshift/hypershift-oadp-plugin

Length of output: 599


🏁 Script executed:

rg -A 2 'WriteString' tests/integration/builders/builders_test.go

Repository: openshift/hypershift-oadp-plugin

Length of output: 188


🏁 Script executed:

rg -A 2 'os.CreateTemp' tests/ | head -30

Repository: openshift/hypershift-oadp-plugin

Length of output: 310


🏁 Script executed:

rg '\.Close\(\)' tests/ -A 1 | head -30

Repository: openshift/hypershift-oadp-plugin

Length of output: 988


🏁 Script executed:

fd -e yml -e yaml | xargs rg -l 'errcheck|linter' 2>/dev/null | head -5

Repository: openshift/hypershift-oadp-plugin

Length of output: 58


🏁 Script executed:

fd -e toml -e yaml -e yml | xargs cat 2>/dev/null | rg -i 'errcheck|lint' | head -20

Repository: openshift/hypershift-oadp-plugin

Length of output: 58


🏁 Script executed:

find . -maxdepth 2 -name '.golangci.*' -o -name 'Makefile' -o -name '.github' | head -10

Repository: openshift/hypershift-oadp-plugin

Length of output: 97


🏁 Script executed:

cat Makefile | rg -i 'lint|errcheck' -A 2 -B 2

Repository: openshift/hypershift-oadp-plugin

Length of output: 58


🏁 Script executed:

find . -maxdepth 3 -name '.golangci*' -o -name 'golangci*'

Repository: openshift/hypershift-oadp-plugin

Length of output: 58


🏁 Script executed:

cat -n go.mod | head -30

Repository: openshift/hypershift-oadp-plugin

Length of output: 1400


🏁 Script executed:

ls -la | grep -i golangci

Repository: openshift/hypershift-oadp-plugin

Length of output: 58


🏁 Script executed:

cat .github/workflows/* 2>/dev/null | rg -i 'errcheck|lint|golangci' | head -20

Repository: openshift/hypershift-oadp-plugin

Length of output: 58


🏁 Script executed:

rg -i 'errcheck' . --type go | head -10

Repository: openshift/hypershift-oadp-plugin

Length of output: 558


Check the tmpFile.Close() error explicitly.

Line 152 ignores a returned error from Close(); unchecked file close operations can mask flush and I/O failures.

Suggested fix
 			_, err = tmpFile.WriteString(tc.dockerfileContent)
 			g.Expect(err).NotTo(HaveOccurred())
-			tmpFile.Close()
+			err = tmpFile.Close()
+			g.Expect(err).NotTo(HaveOccurred())
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_, err = tmpFile.WriteString(tc.dockerfileContent)
g.Expect(err).NotTo(HaveOccurred())
tmpFile.Close()
_, err = tmpFile.WriteString(tc.dockerfileContent)
g.Expect(err).NotTo(HaveOccurred())
err = tmpFile.Close()
g.Expect(err).NotTo(HaveOccurred())
🧰 Tools
🪛 golangci-lint (2.12.1)

[error] 152-152: Error return value of tmpFile.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 `@tests/integration/builders/builders_test.go` around lines 150 - 153, The
tmpFile.Close() call currently ignores its returned error; change it to capture
and assert the result (e.g., err = tmpFile.Close();
g.Expect(err).NotTo(HaveOccurred()) or use a short variable like if cerr :=
tmpFile.Close(); g.Expect(cerr).NotTo(HaveOccurred())). Update the Close
invocation where tmpFile is used so any flush/I/O errors are checked and cause
the test to fail.

Comment on lines +198 to +204
func extractGolangVersionsFromDockerfile(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("failed to open %s: %w", path, err)
}
defer file.Close()

Copy link
Copy Markdown

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:

# First, let's locate and read the file to see the actual code
find . -type f -name "builders_test.go" -path "*/tests/integration/builders/*"

Repository: openshift/hypershift-oadp-plugin

Length of output: 122


🏁 Script executed:

# Read the file around the mentioned lines to see the actual implementation
cat -n tests/integration/builders/builders_test.go | sed -n '195,225p'

Repository: openshift/hypershift-oadp-plugin

Length of output: 1038


🏁 Script executed:

# Also search for the function name to ensure we're looking at the right location
rg "extractGolangVersionsFromDockerfile" -n -A 15 tests/integration/builders/builders_test.go

Repository: openshift/hypershift-oadp-plugin

Length of output: 1800


Capture errors from deferred file.Close() in the helper function.

Line 203 drops close errors. This triggers errcheck and can hide IO failures (e.g., write buffer flushes). Use named return values with a deferred function wrapper to propagate close errors properly.

Suggested fix
-func extractGolangVersionsFromDockerfile(path string) ([]string, error) {
+func extractGolangVersionsFromDockerfile(path string) (versions []string, err error) {
 	file, err := os.Open(path)
 	if err != nil {
 		return nil, fmt.Errorf("failed to open %s: %w", path, err)
 	}
-	defer file.Close()
+	defer func() {
+		if cerr := file.Close(); err == nil && cerr != nil {
+			err = fmt.Errorf("failed to close %s: %w", path, cerr)
+		}
+	}()
 
-	var versions []string
 	scanner := bufio.NewScanner(file)
 	for scanner.Scan() {
 		line := strings.TrimSpace(scanner.Text())
 		if strings.HasPrefix(line, "#@follow_tag") || strings.HasPrefix(line, "FROM") {
 			matches := golangVersionPattern.FindStringSubmatch(line)
 			if len(matches) >= 2 {
 				versions = append(versions, matches[1])
 			}
 		}
 	}
 
-	return versions, scanner.Err()
+	if scanErr := scanner.Err(); scanErr != nil {
+		return nil, scanErr
+	}
+	return versions, nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func extractGolangVersionsFromDockerfile(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("failed to open %s: %w", path, err)
}
defer file.Close()
func extractGolangVersionsFromDockerfile(path string) (versions []string, err error) {
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("failed to open %s: %w", path, err)
}
defer func() {
if cerr := file.Close(); err == nil && cerr != nil {
err = fmt.Errorf("failed to close %s: %w", path, cerr)
}
}()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "#@follow_tag") || strings.HasPrefix(line, "FROM") {
matches := golangVersionPattern.FindStringSubmatch(line)
if len(matches) >= 2 {
versions = append(versions, matches[1])
}
}
}
if scanErr := scanner.Err(); scanErr != nil {
return nil, scanErr
}
return versions, nil
}
🧰 Tools
🪛 golangci-lint (2.12.1)

[error] 203-203: Error return value of file.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 `@tests/integration/builders/builders_test.go` around lines 198 - 204, The
helper function extractGolangVersionsFromDockerfile currently ignores errors
from file.Close(), which can hide IO failures; change the function to use named
return values (e.g., results []string, err error) and replace defer file.Close()
with a deferred closure that captures the close error (if cerr := file.Close();
cerr != nil && err == nil { err = fmt.Errorf("close failed: %w", cerr) }) so the
close error is propagated while preserving any existing error from the function.

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 7, 2026
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. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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