Skip to content

pkg/steps: retry network-unreachable builds, capture failed build logs - #5363

Open
kaovilai wants to merge 1 commit into
openshift:mainfrom
kaovilai:worktree-flickering-petting-kahan
Open

pkg/steps: retry network-unreachable builds, capture failed build logs#5363
kaovilai wants to merge 1 commit into
openshift:mainfrom
kaovilai:worktree-flickering-petting-kahan

Conversation

@kaovilai

@kaovilai kaovilai commented Aug 12, 2026

Copy link
Copy Markdown
Member

Summary

  • hintsAtInfraReason() (pkg/steps/source.go) now matches "network is unreachable" and "no route to host", so a transient ENETUNREACH-style dial failure during a build (e.g. a Go module/sumdb fetch mid-Dockerfile-build) is classified as an infra-side retryable failure instead of falling through to "classified as legitimate failure, will not be retried".
  • Renamed the outcome-agnostic gatherSuccessfulBuildLog to gatherBuildLog (pkg/steps/artifacts.go) and call it from both the success path and the failure path (waitForBuild's BuildPhaseFailed/Cancelled/Error case, alongside the existing printBuildLogs stdout dump), so failed builds get the same discrete build-logs/<name>.log.gz artifact successful builds already do, instead of only being interleaved into ci-operator's own stdout log.

No config schema changes. No behavior change for legitimate (non-infra) DockerBuildFailed failures — those still won't retry, they just also get a log artifact now.

Context

Root-caused from a DockerBuildFailed flake on an oadp-operator rehearsal build (oadp-operator-1.5-amd64): a sibling job on the identical commit/Dockerfile succeeded in parallel on a different build pod, confirming a build-farm-node-level transient network flake rather than a real Dockerfile bug. The failing line (dial tcp [...]:443: connect: network is unreachable) was hard to find because it was buried inside the monolithic build-log.txt rather than a small dedicated per-build log artifact.

Test plan

  • go build ./pkg/steps/...
  • go vet ./pkg/steps/...
  • gofmt -l clean on both changed files
  • go test ./pkg/steps/... — all packages pass

Summary

  • Updates pkg/steps to retry builds that fail with "network is unreachable" or "no route to host".
  • Captures build-logs/<name>.log.gz artifacts for successful, failed, cancelled, and errored builds.
  • Preserves non-retryable behavior for legitimate DockerBuildFailed failures.
  • Renames the internal helper to gatherBuildLog.
  • No configuration schema changes.
  • Tests and formatting checks pass.

hintsAtInfraReason() classifies a Build's Status.LogSnippet as an
infra-side (retryable) failure by matching a fixed set of substrings.
"network is unreachable" (ENETUNREACH) and "no route to host" were
missing, so a transient dial failure during a Go module/sumdb fetch
mid-build (e.g. an IPv6 blip) fell through to "classified as legitimate
failure, will not be retried" instead of being retried.

Failed builds also had no discrete log artifact: gatherSuccessfulBuildLog
only ran on the success path, while the failure path just streamed the
build pod log to ci-operator's own stdout, making the failing line hard
to find without grepping the whole ci-operator log. Renamed the (already
outcome-agnostic) helper to gatherBuildLog and call it from both the
success and failure paths, so failed builds get the same build-logs/<name>.log.gz
artifact successful ones do.

Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com>
Copilot AI lite review requested due to automatic review settings August 12, 2026 02:36
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: automatic mode

@openshift-ci
openshift-ci Bot requested review from Prucek and jmguzik August 12, 2026 02:36
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The build steps rename the log-gathering helper, collect logs for failed builds, preserve warning behavior for collection failures, and classify additional network errors as infrastructure failures.

Changes

Build log and retry handling

Layer / File(s) Summary
Collect logs for build outcomes
pkg/steps/artifacts.go, pkg/steps/source.go
The helper is renamed to gatherBuildLog. Successful and failed builds use it to create log artifacts. Collection failures remain warnings.
Recognize infrastructure errors
pkg/steps/source.go
Infrastructure-error detection now includes connection reset by peer, network is unreachable, and no route to host.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: droslean, danilo-gemoli, prucek


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
No-Sensitive-Data-In-Logs ❌ Error The new failure path copies complete BuildClient.Logs output into an artifact with io.Copy, bypassing api.SaveArtifact censoring; build logs may contain tokens, hostnames, or customer data. Redact build-log content with the configured censor before writing artifacts, or do not persist raw failed-build logs; add a test that verifies secret values are absent.
Test Coverage For New Features ⚠️ Warning The PR adds two pure hintsAtInfraReason matches and failed-build artifact behavior, but changes no test files and no tests reference these cases or build-logs. Add table-driven regression tests for both new log strings and a failed-build artifact test that verifies the compressed build-logs/<name>.log.gz output.
✅ Passed checks (15 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main changes: retrying network-related build failures and capturing logs for failed builds.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Go Error Handling ✅ Passed The diff adds no ignored errors, panic calls, or unchecked pointers. New gatherBuildLog errors are checked and logged; its %w handling is unchanged from the prior helper.
Stable And Deterministic Test Names ✅ Passed The diff changes only pkg/steps/artifacts.go and source.go; no *_test.go files or Ginkgo test declarations/titles were added or modified.
Test Structure And Quality ✅ Passed The PR changes only pkg/steps/artifacts.go and source.go; the parent-to-HEAD diff contains no *_test.go files, so the Ginkgo test-quality check is inapplicable.
Microshift Test Compatibility ✅ Passed The patch changes only two implementation files and adds no *_test.go files or Ginkgo declarations, so the MicroShift new-test compatibility check is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The diff changes only pkg/steps/artifacts.go and source.go; it adds no Ginkgo tests or multi-node/HA assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The exact diff changes only build-log capture and infrastructure-error matching in pkg/steps; it adds no manifests, controllers, replicas, affinity, topology, selectors, tolerations, or PDB constra...
Ote Binary Stdout Contract ✅ Passed The diff adds artifact-file copying and infra string checks, not stdout writes or process-level entry-point code; existing printBuildLogs os.Stdout use is unchanged.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The commit changes only pkg/steps/artifacts.go and source.go. It adds no Ginkgo e2e tests or test files, so this compatibility check is not applicable.
No-Weak-Crypto ✅ Passed The commit changes build-log naming, artifact capture, and infrastructure-error strings only; it adds no weak crypto, custom crypto, or secret/token comparison code.
Container-Privileges ✅ Passed The patch changes only Go log handling and retry-string matching. It adds no container/Kubernetes manifest or privilege settings such as privileged, hostPID, SYS_ADMIN, or allowPrivilegeEscalation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves build flake handling in pkg/steps by (1) recognizing additional transient network failures as infrastructure-side retryable errors and (2) ensuring failed builds also produce a dedicated compressed build log artifact, matching the successful-build behavior.

Changes:

  • Extend hintsAtInfraReason() to classify "network is unreachable" and "no route to host" as retryable infra signals.
  • Rename gatherSuccessfulBuildLoggatherBuildLog and invoke it on both build success and build failure to always emit build-logs/<name>.log.gz.
  • Capture failed build logs as artifacts in waitForBuild failure/cancel/error phases (in addition to the existing stdout log dump).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
pkg/steps/source.go Adds new infra log-snippet matches and calls gatherBuildLog for both successful and failed builds.
pkg/steps/artifacts.go Renames/clarifies the build-log artifact helper to be outcome-agnostic.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pkg/steps/source.go
if err := gatherSuccessfulBuildLog(client, ns, name); err != nil {
if err := gatherBuildLog(client, ns, name); err != nil {
// log error but do not fail successful build
logrus.WithError(err).Warnf("Failed gathering successful build %s logs into artifacts.", name)
Comment thread pkg/steps/artifacts.go
// api logging capabilities; also, without needing to inject an artifacts container, some of the complexities
// around download/copy from the artifacts container's volume mount and multiple pods are avoided.
func gatherSuccessfulBuildLog(buildClient BuildClient, namespace, buildName string) error {
func gatherBuildLog(buildClient BuildClient, namespace, buildName string) error {

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
pkg/steps/artifacts.go (1)

667-672: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document gatherBuildLog as a Go function.

The comment is a sentence fragment and does not start with gatherBuildLog. State that the function writes the compressed build log for the specified build and returns an error when collection fails.

Proposed documentation
-// for gathering build logs (successful or failed) to the artifacts, there is no way to augment the pod spec
+// gatherBuildLog writes the compressed build log for buildName to the build artifacts.
+// It returns an error when artifact creation or log collection fails.

As per coding guidelines, Go documentation on functions should be written properly.

🤖 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 `@pkg/steps/artifacts.go` around lines 667 - 672, Update the documentation
immediately above gatherBuildLog to begin with “gatherBuildLog” and state that
it writes the compressed build log for the specified build, returning an error
if collection fails.

Source: Coding guidelines

pkg/steps/source.go (1)

662-664: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add regression tests for the new retry and artifact paths.

Extend pkg/steps/source_test.go with table-driven cases that verify:

  • "network is unreachable" and "no route to host" cause infrastructure retry handling.
  • A non-infrastructure DockerBuildFailed result remains non-retryable.
  • Failed, cancelled, and errored builds invoke gatherBuildLog.
  • Artifact collection failures remain warnings and do not replace the build result.

Also applies to: 751-753

🤖 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 `@pkg/steps/source.go` around lines 662 - 664, The source error classification
and build-result handling lack regression coverage. Extend the table-driven
tests in source_test.go to verify the new infrastructure retry messages,
preserve non-retryability for non-infrastructure DockerBuildFailed results,
ensure failed/cancelled/errored builds call gatherBuildLog, and confirm artifact
collection failures remain warnings without replacing the build result.
🤖 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.

Nitpick comments:
In `@pkg/steps/artifacts.go`:
- Around line 667-672: Update the documentation immediately above gatherBuildLog
to begin with “gatherBuildLog” and state that it writes the compressed build log
for the specified build, returning an error if collection fails.

In `@pkg/steps/source.go`:
- Around line 662-664: The source error classification and build-result handling
lack regression coverage. Extend the table-driven tests in source_test.go to
verify the new infrastructure retry messages, preserve non-retryability for
non-infrastructure DockerBuildFailed results, ensure failed/cancelled/errored
builds call gatherBuildLog, and confirm artifact collection failures remain
warnings without replacing the build result.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: bd4b26a6-b9eb-4524-b8ae-5d045d17f565

📥 Commits

Reviewing files that changed from the base of the PR and between 3e8efbe and 29943dd.

📒 Files selected for processing (2)
  • pkg/steps/artifacts.go
  • pkg/steps/source.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift/release (manual)
  • openshift/ci-docs (manual)
  • openshift/release-controller (manual)
  • openshift/ci-chat-bot (manual)

@Prucek

Prucek commented Aug 12, 2026

Copy link
Copy Markdown
Member

/retest
/lgtm

@openshift-ci openshift-ci Bot added lgtm Indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Aug 12, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 3e8efbe and 2 for PR HEAD 29943dd in total

@kaovilai

Copy link
Copy Markdown
Member Author

/test images

@kaovilai

Copy link
Copy Markdown
Member Author

/test core-valid

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test owners

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test release-controller-config

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test openshift-image-mirror-mappings

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test images

Note

Responses generated with Claude

@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: deepsm007, kaovilai, Prucek

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

@kaovilai

Copy link
Copy Markdown
Member Author

/test core-valid

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test owners

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test release-controller-config

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

/test openshift-image-mirror-mappings

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

Apologies for the duplicate /test core-valid, /test owners, and /test release-controller-config comments above — a monitoring script restart re-triggered nudges for checks it had already flagged, and it also didn't account for this repo's pipeline-controller gating (those second-stage tests aren't stuck, they trigger on lgtm/automatic mode by design). Fixed the script to dedupe against actual PR comment history and to recognize pipeline-controller repos so this won't recur.

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

Heads up: ci/prow/images has now failed 5/5 times on this exact commit (29943ddd7ac), always at the same spot — bin-arm64 build, go install in hack/install.sh:45 exiting 1 after ~3-7min — while bin-amd64 succeeds every time. That's a reproducible failure, not a flake, so keeping /test images isn't the right hammer here.

Can't get the actual compiler error though: artifacts/build-logs/ only captures logs for successful builds today (only bin-amd64.log is present), so the bin-arm64 stderr that would show why go install fails is lost — ironically the log-capture-on-failure feature this very PR adds isn't live yet to catch its own build's failure. The diff itself (renaming a helper, adding failed-build log capture, 2 new infra-string matches) doesn't look like it should affect compilation on any arch, so this may be arm64-builder-side rather than code — but I don't have enough visibility to confirm either way from here.

Note

Responses generated with Claude

@kaovilai

Copy link
Copy Markdown
Member Author

Update: root-caused (with help from a local repro on real arm64 hardware). This is not a regression from this PR's diff.

  • Checked out this PR at head 29943ddd7ac locally on arm64 and ran GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build ./..., plus the full make production-install (hack/install.sh + npm/webpack dist assets) — both succeed cleanly, no compile errors.
  • ci-operator.log for these runs is running the released ci-operator (v20260810-3e8efbe0b, built from base SHA), so this PR's gatherBuildLog change isn't even active yet — and indeed the log shows Unable to retrieve logs from failed build: pod bin-arm64-build not found, literally the gap this PR closes.
  • bin-arm64 gets the same cpu:1/memory:1Gi request as bin-amd64. bin-amd64 needed 23m18s to succeed; bin-arm64 failed at ~7m16s — consistent with the arm64 build hitting a resource ceiling (OOM/starved) on that node rather than a real compile error.
  • Cross-check: PR Fix dispatcher capacity and add ipCapacity field to count for maxNodes #5346, same base SHA, images job passed clean.

So: looks like an infra-side thin-margin issue on the arm64 builder, not code. Retrying once more; if it keeps failing deterministically, worth flagging to DPTP that the arm64 images build (go install of ~50 binaries + webpack bundle) may need more than 1Gi.

/test images

Note

Responses generated with Claude

@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@kaovilai: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/images 29943dd link true /test images

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. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants