Skip to content

CNTRLPLANE-3773: Rewrite find-push-pipelinerun as Go CLI - #8935

Open
celebdor wants to merge 2 commits into
openshift:mainfrom
celebdor:feat/release-pipeline-tracking
Open

CNTRLPLANE-3773: Rewrite find-push-pipelinerun as Go CLI#8935
celebdor wants to merge 2 commits into
openshift:mainfrom
celebdor:feat/release-pipeline-tracking

Conversation

@celebdor

@celebdor celebdor commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Rewrites the 535-line find-push-pipelinerun.sh bash script as a Go CLI tool at hack/tools/find-push-pipelinerun/
  • Uses client-go for Kubernetes auth and the GitHub REST API directly (no gh, jq, curl dependencies)
  • Interface-based Querier design enables mock-driven unit tests for the watch loop
  • Fixes two bugs from the original bash implementation:
    • Release status now selects the Released condition by type instead of assuming conditions[0]
    • Watch loop continues polling when no Release CR exists yet (fixes premature exit after builds complete)
  • KubeArchive fallback messages are deduplicated and release PipelineRuns are consolidated into a single table
  • 41 unit tests covering formatting, watch loop scenarios, query client, and PR parsing

Test plan

  • cd hack/tools && go test ./find-push-pipelinerun/ — 41/41 pass
  • golangci-lint — 0 issues
  • hack/tools/bin/find-push-pipelinerun 8923 — push PipelineRuns displayed correctly
  • hack/tools/bin/find-push-pipelinerun --release 8923 — releases and release PipelineRuns displayed correctly with destination images
  • hack/tools/bin/find-push-pipelinerun --release --watch <recent-PR> — poll mode

Jira

CNTRLPLANE-3773

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added a guide for tracking post-merge build and release pipelines, including how to verify on-push completion, image release status, and downstream release pipeline activity.
  • New Features
    • Introduced find-push-pipelinerun to locate merged PR-triggered PipelineRuns by merge commit SHA, with optional component filtering and --watch polling.
    • Added --release mode to display release pipeline status and expected destination images, with live-to-archive fallback.
  • Build & Packaging
    • Updated the Makefile to build and expose the new tool.
  • Tests
    • Added unit and watcher tests, plus shell coverage for release/build formatting and pending-state detection.

@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: LGTM mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 6, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 6, 2026

Copy link
Copy Markdown

@celebdor: This pull request references CNTRLPLANE-3773 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 task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Extends find-push-pipelinerun.sh with a --release flag that tracks the downstream Konflux release pipeline after a push build completes
  • Shows Releases with destination images in full digest format (repo@sha256:digest) derived from ReleasePlan mappings and Snapshot digests
  • Shows release PipelineRuns in rhtap-releng-tenant, with KubeArchive fallback for archived resources
  • Adds documentation section to docs/content/contribute/konflux-scripts.md
  • Adds 10 new BATS unit tests (30 total)

Test plan

  • bats hack/tools/scripts/find-push-pipelinerun_test.bats — 30/30 pass
  • hack/tools/scripts/find-push-pipelinerun.sh --release 8908 — verified all destination URLs show correctly (acm-d, registry.stage.redhat.io, redhat-services-prod)
  • hack/tools/scripts/find-push-pipelinerun.sh --release --watch <recent-PR> — poll mode

Jira

CNTRLPLANE-3773

🤖 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.

@celebdor celebdor added the area/ci-tooling Indicates the PR includes changes for CI or tooling label Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: c9f8d3af-3e7f-4e09-94d9-c275a52f6300

📥 Commits

Reviewing files that changed from the base of the PR and between 9f27af0 and 91f7e26.

📒 Files selected for processing (7)
  • hack/tools/.golangci.yml
  • hack/tools/find-push-pipelinerun/format.go
  • hack/tools/find-push-pipelinerun/main.go
  • hack/tools/find-push-pipelinerun/pr.go
  • hack/tools/find-push-pipelinerun/query.go
  • hack/tools/find-push-pipelinerun/watch.go
  • hack/tools/go.mod
🚧 Files skipped from review as they are similar to previous changes (6)
  • hack/tools/find-push-pipelinerun/main.go
  • hack/tools/.golangci.yml
  • hack/tools/find-push-pipelinerun/watch.go
  • hack/tools/find-push-pipelinerun/pr.go
  • hack/tools/find-push-pipelinerun/format.go
  • hack/tools/find-push-pipelinerun/query.go

📝 Walkthrough

Walkthrough

This PR adds a new find-push-pipelinerun command-line tool, its GitHub PR and Kubernetes query layers, table-formatting and destination-image helpers, polling logic for build and release pipelines, Makefile wiring, lint configuration, and contributor documentation. It also adds Go and Bats tests covering PR parsing, merge-SHA lookup, resource queries, formatting, image resolution, and watch behavior.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Main as main.go
  participant PR as pr.go
  participant Query as query.go
  participant Watch as watch.go
  participant GitHub as GitHub API
  participant Kube as Kubernetes APIs

  User->>Main: run tool with PR input
  Main->>PR: ResolvePR()
  PR->>GitHub: GetMergeSHA()
  Main->>Query: ListPipelineRuns(sha)
  Query->>Kube: GET PipelineRuns
  Main->>Watch: WatchBuildPipeline() / WatchReleasePipeline()
  Watch->>Query: list PipelineRuns / Releases
  Query->>Kube: GET resources
Loading

Important

Pre-merge checks failed

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

❌ Failed checks (1 error)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error Error logs include raw git remote URLs and full API URLs/bodies, which can expose tokens or internal hostnames. Redact credentials/hostnames from git remote and HTTP error logs; avoid printing raw response bodies or full URLs in stderr.
✅ 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 clearly and concisely describes the main change: rewriting find-push-pipelinerun as a Go CLI.
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 No Ginkgo titles were added; the new tests use static Go Test... names only, with no dynamic values like timestamps, UUIDs, or generated suffixes.
Test Structure And Quality ✅ Passed PASS: These are standard testing unit tests, not Ginkgo; they use deferred httptest cleanup and have no cluster waits/Eventually calls to flag.
Topology-Aware Scheduling Compatibility ✅ Passed The PR only adds docs and a hack/tools CLI; no deployment manifests, controllers, or topology-sensitive scheduling constraints were introduced.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PASS: The added tests are plain Go unit tests, with no Ginkgo e2e patterns, hardcoded IPv4 literals, IP-family assumptions, or public internet connectivity.
No-Weak-Crypto ✅ Passed No weak crypto, ECB, or secret comparisons; auth is bearer-token only.
Container-Privileges ✅ Passed The PR only changes Go tooling and lint config; no container/K8s manifests were added or modified, so no privileged settings were introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci

openshift-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: celebdor
Once this PR has been reviewed and has the lgtm label, please assign devguyio for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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 requested review from enxebre and muraee July 6, 2026 15:52
@openshift-ci openshift-ci Bot added the area/documentation Indicates the PR includes changes for documentation label Jul 6, 2026
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 43.45%. Comparing base (8e1aa48) to head (91f7e26).
⚠️ Report is 856 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8935      +/-   ##
==========================================
+ Coverage   43.34%   43.45%   +0.11%     
==========================================
  Files         771      771              
  Lines       95534    95718     +184     
==========================================
+ Hits        41408    41597     +189     
+ Misses      51242    51234       -8     
- Partials     2884     2887       +3     

see 6 files with indirect coverage changes

Flag Coverage Δ
cmd-support 37.12% <ø> (+0.24%) ⬆️
cpo-hostedcontrolplane 45.21% <ø> (-0.10%) ⬇️
cpo-other 45.10% <ø> (ø)
hypershift-operator 53.65% <ø> (+0.07%) ⬆️
other 32.08% <ø> (+0.39%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (3)
hack/tools/scripts/find-push-pipelinerun_test.bats (1)

229-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Synthetic table bypasses format_releases output contract.

These tests hand-craft the input table with printf instead of piping real format_releases output into has_pending_releases. This tests the awk $4 parsing logic in isolation but won't catch a regression if format_releases' column order/count changes (e.g. STATUS moves from position 4). Consider at least one test that chains format_releases | has_pending_releases for end-to-end contract coverage.

🤖 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 `@hack/tools/scripts/find-push-pipelinerun_test.bats` around lines 229 - 245,
The current `has_pending_releases` tests only validate `awk` parsing against a
hand-built table, so they can miss regressions in the `format_releases` output
contract. Add at least one end-to-end test that feeds real `format_releases`
output directly into `has_pending_releases`, using the existing
`format_releases` and `has_pending_releases` helpers, so the STATUS column
position and column count are verified together.
docs/content/contribute/konflux-scripts.md (1)

149-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid over-specifying the release PipelineRun name.

The supplied implementation context matches Release PipelineRuns by label, not by a managed-* name pattern. Please verify that naming is guaranteed; otherwise rephrase this bullet to describe the label-based match instead.

Details

Suggested wording
-- **Release PipelineRuns** — the `managed-*` PipelineRuns in the
-  `rhtap-releng-tenant` namespace that execute the release (push to
-  registry, sign, create advisory, etc.).
+- **Release PipelineRuns** — the PipelineRuns in the
+  `rhtap-releng-tenant` namespace associated with the Release label
+  that execute the release (push to registry, sign, create advisory, etc.).
🤖 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 `@docs/content/contribute/konflux-scripts.md` around lines 149 - 155, The
“Release PipelineRuns” bullet over-specifies a managed-* name pattern that is
not guaranteed by the implementation. Update the documentation in the
contribute/konflux-scripts content to describe how these PipelineRuns are
actually identified by labels rather than by name, using the Release
PipelineRuns wording to match the existing release flow context.
hack/tools/scripts/find-push-pipelinerun.sh (1)

335-335: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unused snapshot_json declaration.

snapshot_json is declared but never assigned or read (the digest is derived directly into source_digest).

🧹 Drop the dead local
-            local rel_name snapshot_json source_digest
+            local rel_name source_digest
🤖 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 `@hack/tools/scripts/find-push-pipelinerun.sh` at line 335, Remove the dead
local declaration in the shell script: the `snapshot_json` variable in
`find-push-pipelinerun.sh` is never used because the digest is already handled
through `source_digest`. Update the local variable declaration near the related
parsing logic to keep only the identifiers that are actually assigned and read,
and ensure the surrounding flow in the same script still uses `rel_name` and
`source_digest` as before.

Source: Linters/SAST tools

🤖 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 `@hack/tools/scripts/find-push-pipelinerun.sh`:
- Around line 512-527: The watch loop in find-push-pipelinerun.sh can exit too
early after PipelineRuns finish because the Release CR may not exist yet; in the
watch block around query_releases and has_pending_releases, avoid breaking when
query_releases returns no results or fails immediately after push completion.
Update the logic in the watch loop so it keeps polling until a Release appears
and its release pipeline is no longer pending, using the existing helpers
query_releases, format_releases, has_pending, and has_pending_releases to locate
the behavior.
- Around line 278-291: The STATUS field in the jq formatting block is
order-dependent because it reads .status.conditions[0].reason, which can pick
the wrong condition. Update the transformation in the find-push-pipelinerun.sh
formatting pipeline to explicitly select the Released condition by name, and use
that condition’s reason for the STATUS column so the output reflects the release
outcome. Keep the change within the jq expression that builds the items list and
sorts by created.

---

Nitpick comments:
In `@docs/content/contribute/konflux-scripts.md`:
- Around line 149-155: The “Release PipelineRuns” bullet over-specifies a
managed-* name pattern that is not guaranteed by the implementation. Update the
documentation in the contribute/konflux-scripts content to describe how these
PipelineRuns are actually identified by labels rather than by name, using the
Release PipelineRuns wording to match the existing release flow context.

In `@hack/tools/scripts/find-push-pipelinerun_test.bats`:
- Around line 229-245: The current `has_pending_releases` tests only validate
`awk` parsing against a hand-built table, so they can miss regressions in the
`format_releases` output contract. Add at least one end-to-end test that feeds
real `format_releases` output directly into `has_pending_releases`, using the
existing `format_releases` and `has_pending_releases` helpers, so the STATUS
column position and column count are verified together.

In `@hack/tools/scripts/find-push-pipelinerun.sh`:
- Line 335: Remove the dead local declaration in the shell script: the
`snapshot_json` variable in `find-push-pipelinerun.sh` is never used because the
digest is already handled through `source_digest`. Update the local variable
declaration near the related parsing logic to keep only the identifiers that are
actually assigned and read, and ensure the surrounding flow in the same script
still uses `rel_name` and `source_digest` as before.
🪄 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: 203b1bf3-2a96-4ada-a115-549bcd139464

📥 Commits

Reviewing files that changed from the base of the PR and between da61727 and bed58a4.

📒 Files selected for processing (3)
  • docs/content/contribute/konflux-scripts.md
  • hack/tools/scripts/find-push-pipelinerun.sh
  • hack/tools/scripts/find-push-pipelinerun_test.bats

Comment thread hack/tools/scripts/find-push-pipelinerun.sh Outdated
Comment thread hack/tools/scripts/find-push-pipelinerun.sh Outdated
Replace the 535-line bash script with a Go CLI tool that uses
client-go for Kubernetes auth and the GitHub REST API directly.

Key improvements over the bash version:
- Interface-based Querier enables mock-driven tests for the watch
  loop, which was untestable in bash
- Release status selects the "Released" condition by type instead
  of assuming conditions[0]
- Watch loop continues polling when no Release CR exists yet
  (fixes premature exit after builds complete)
- KubeArchive fallback messages are deduplicated
- Release PipelineRuns are consolidated into a single table
- No dependency on jq, curl, or gh CLI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@celebdor
celebdor force-pushed the feat/release-pipeline-tracking branch from bed58a4 to fd53cb3 Compare July 7, 2026 13:44
@celebdor celebdor changed the title CNTRLPLANE-3773: Add --release flag to find-push-pipelinerun.sh CNTRLPLANE-3773: Rewrite find-push-pipelinerun as Go CLI Jul 7, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 5

🧹 Nitpick comments (5)
hack/tools/find-push-pipelinerun/query.go (2)

100-125: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Original live-query error is discarded when KubeArchive fallback is attempted.

When listResource against the live cluster fails with a real error (auth, RBAC, network) rather than just returning zero items, listWithFallback proceeds silently to KubeArchive without logging the original error. If the archive query also fails, only the archive error is surfaced, hiding the root cause of the live failure.

🔎 Proposed fix
 	items, err := listResource[T](q, q.kubeHost, apiPath, labelSelector)
 	if err == nil && len(items) > 0 {
 		return items, nil
 	}
+	if err != nil {
+		fmt.Fprintf(q.stderr, "Live query for %s failed: %v; falling back to KubeArchive...\n", resourceName, err)
+	}
🤖 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 `@hack/tools/find-push-pipelinerun/query.go` around lines 100 - 125, The
live-cluster error in listWithFallback is being dropped when the KubeArchive
fallback runs, so preserve and report the original listResource failure from
q.kubeHost before querying q.kaHost. Update listWithFallback to log or wrap the
live-query error when err is non-nil and items is empty, and if the archive
lookup also fails, include both the original live error and the KubeArchive
error in the returned error so the root cause is not hidden.

127-158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate request/response handling in listResource and getResource.

Both functions repeat identical URL parsing, request creation, status-code checking, and error-body reading. Extracting a shared doRequest(q, host, path) (*http.Response, error) helper would remove the duplication.

♻️ Sketch of a shared helper
+func (q *httpQuerier) doRequest(host, path string) (*http.Response, error) {
+	u, err := url.Parse(host)
+	if err != nil {
+		return nil, fmt.Errorf("parsing host URL %q: %w", host, err)
+	}
+	u.Path = path
+	req, err := http.NewRequest("GET", u.String(), nil) //nolint:noctx
+	if err != nil {
+		return nil, err
+	}
+	resp, err := q.client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	if resp.StatusCode != http.StatusOK {
+		body, _ := io.ReadAll(resp.Body)
+		resp.Body.Close()
+		return nil, fmt.Errorf("HTTP %d from %s: %s", resp.StatusCode, u.String(), string(body))
+	}
+	return resp, nil
+}

Also applies to: 160-188

🤖 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 `@hack/tools/find-push-pipelinerun/query.go` around lines 127 - 158, The
request/response setup in listResource and getResource is duplicated, including
URL parsing, GET request creation, status checking, and error-body handling.
Extract that shared logic into a reusable helper such as doRequest on the
httpQuerier path, then have both listResource and getResource call it and keep
only their resource-specific decode logic. Make sure the helper preserves the
existing error formatting and response body handling so both call sites behave
the same.
hack/tools/find-push-pipelinerun/watch.go (1)

54-54: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Redundant ListReleases call per iteration, and its errors are silently swallowed forever.

printReleasePipeline (line 76) and the terminal-state check (line 60) both call q.ListReleases(cfg.SHA) independently each iteration — doubling API calls for no benefit (confirmed by the comment in watch_test.go's TestWatchReleasePipeline_ExitsWhenAllTerminal). Additionally, line 61 treats any ListReleases error the same as "release not yet created" and silently continues — a persistent RBAC/network error would loop forever with no diagnostic beyond "--- refreshing ---", unlike ListPipelineRuns errors which are returned immediately.

♻️ Proposed consolidation
-		printReleasePipeline(q, cfg.SHA, cfg.Component, cfg.Stdout, cfg.Stderr)
-
 		if HasPending(prs) {
 			continue
 		}
-
 		releases, err := q.ListReleases(cfg.SHA)
-		if err != nil || len(releases) == 0 {
-			// No releases yet — keep polling
+		if err != nil {
+			fmt.Fprintf(cfg.Stderr, "Warning: failed to query Releases: %v\n", err)
+			continue
+		}
+		if len(releases) == 0 {
 			continue
 		}
 		if cfg.Component != "" {
 			releases = FilterReleasesByComponent(releases, cfg.Component)
 		}
+		printReleasePipelineWithReleases(q, releases, cfg.Stdout, cfg.Stderr)
 		if !HasPendingReleases(releases) {
 			return nil
 		}

Also applies to: 60-70, 75-79

🤖 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 `@hack/tools/find-push-pipelinerun/watch.go` at line 54, `watch` is making two
`ListReleases` calls per loop and swallowing release-listing errors, so
consolidate the release lookup in the main iteration and reuse it for both the
terminal-state check and `printReleasePipeline`. Update the `watch` loop and
`printReleasePipeline` to accept the already-fetched releases (or otherwise
avoid re-calling `q.ListReleases(cfg.SHA)`), and change the `ListReleases` error
handling to surface persistent failures instead of silently continuing, similar
to how `ListPipelineRuns` errors are handled.
hack/tools/find-push-pipelinerun/format.go (2)

169-243: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Redundant ReleasePlan/ReleasePlanAdmission lookups across releases.

ResolveDestImages calls resolveDestImagegetMappingForRelease once per release, re-fetching the same ReleasePlan (and possibly ReleasePlanAdmission) via HTTP every time, even when many releases share the same plan (typical for a single push build with multiple component releases). Caching by plan name within ResolveDestImages would cut this down to one request per distinct plan.

♻️ Proposed fix
 func ResolveDestImages(q Querier, releases []Release) map[string]string {
 	images := make(map[string]string)
+	mappingCache := make(map[string]*Mapping)
 	for _, rel := range releases {
-		img := resolveDestImage(q, rel)
+		img := resolveDestImage(q, rel, mappingCache)
 		if img != "" {
 			images[rel.Metadata.Name] = img
 		}
 	}
 	return images
 }

-func resolveDestImage(q Querier, rel Release) string {
-	mapping := getMappingForRelease(q, rel.Spec.ReleasePlan)
+func resolveDestImage(q Querier, rel Release, cache map[string]*Mapping) string {
+	mapping, ok := cache[rel.Spec.ReleasePlan]
+	if !ok {
+		mapping = getMappingForRelease(q, rel.Spec.ReleasePlan)
+		cache[rel.Spec.ReleasePlan] = mapping
+	}
 	if mapping == nil {
 		return ""
 	}
🤖 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 `@hack/tools/find-push-pipelinerun/format.go` around lines 169 - 243,
ResolveDestImages is repeatedly re-fetching the same ReleasePlan and
ReleasePlanAdmission for releases that share a plan, causing redundant HTTP
calls. Add plan-scoped caching inside ResolveDestImages so
resolveDestImage/getMappingForRelease only loads each distinct release plan once
per invocation, reusing the cached Mapping for subsequent releases with the same
rel.Spec.ReleasePlan.

67-165: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated sort+tabwriter boilerplate across four Format functions.*

FormatPipelineRuns, FormatReleases, FormatReleasesWithImages, and FormatReleasePipelineRuns each repeat: empty check → sort.Slice by CreationTimestamp → build a tabwriter → print header/rows → Flush. Consider extracting the shared scaffolding (empty-check, sort, tabwriter setup/flush) into a small generic helper that each caller feeds with its header string and per-row column values, reducing duplication.

🤖 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 `@hack/tools/find-push-pipelinerun/format.go` around lines 67 - 165, The four
Format* functions repeat the same empty check, CreationTimestamp sort, tabwriter
setup/flush, and row printing logic. Refactor the shared scaffolding in
FormatPipelineRuns, FormatReleases, FormatReleasesWithImages, and
FormatReleasePipelineRuns into a common helper that accepts the header and
row-rendering callback, while keeping each function responsible only for its
specific columns and data extraction.
🤖 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 `@hack/tools/find-push-pipelinerun/format.go`:
- Around line 13-40: The PipelineRun terminal status set in
pipelineRunTerminalStatuses is incomplete, so HasPending treats some finished
runs as pending and can cause WatchBuildPipeline and the PipelineRun path in
WatchReleasePipeline to poll forever. Update the terminal status map to include
any additional terminal PipelineRun reasons used by pipelineRunStatus, and keep
HasPending relying on that expanded set so finished runs are no longer reported
as pending.

In `@hack/tools/find-push-pipelinerun/main.go`:
- Around line 134-141: The watch interval parsing in watchInterval currently
accepts zero or negative values from WATCH_INTERVAL, which can make the polling
loop spin without delay. Update the watchInterval function to validate the
parsed integer and only return a custom duration when it is greater than zero;
otherwise fall back to defaultWatchInterval. Keep the change localized to
watchInterval and preserve the existing strconv.Atoi and time.Duration
conversion path for valid positive values.

In `@hack/tools/find-push-pipelinerun/pr.go`:
- Around line 76-133: The GitHub client created in newGitHubClient has no
request timeout, so a stalled API call can hang the tool indefinitely. Update
newGitHubClient to return an http.Client with a non-zero Timeout in both the
token and no-token cases, while keeping tokenTransport as the wrapper when
GITHUB_TOKEN is provided. Ensure GetMergeSHA continues to use the client
returned by newGitHubClient so all GitHub requests are covered.

In `@hack/tools/find-push-pipelinerun/query.go`:
- Around line 41-65: The HTTP querier currently has no cancellation or timeout
control, so requests in the watch loop can hang indefinitely. Update
newHTTPQuerier to configure a client-wide timeout on restConfig before calling
rest.HTTPClientFor, and ensure the request paths in httpQuerier use
context-aware request creation instead of nil contexts. Use the existing
newHTTPQuerier and httpQuerier symbols to centralize the timeout/cancellation
behavior so all external calls can recover if the API server or KubeArchive
endpoint stalls.

In `@hack/tools/find-push-pipelinerun/watch.go`:
- Around line 40-58: WatchReleasePipeline is fetching release data twice and
hiding real API failures by treating all ListReleases errors like “not found.”
Update WatchReleasePipeline and the printReleasePipeline path so releases are
only fetched once per loop, and distinguish expected empty/not-created cases
from unexpected errors. Use the existing Querier/ListReleases and
printReleasePipeline symbols to return non-expected errors immediately while
continuing to poll only for the missing-release case.

---

Nitpick comments:
In `@hack/tools/find-push-pipelinerun/format.go`:
- Around line 169-243: ResolveDestImages is repeatedly re-fetching the same
ReleasePlan and ReleasePlanAdmission for releases that share a plan, causing
redundant HTTP calls. Add plan-scoped caching inside ResolveDestImages so
resolveDestImage/getMappingForRelease only loads each distinct release plan once
per invocation, reusing the cached Mapping for subsequent releases with the same
rel.Spec.ReleasePlan.
- Around line 67-165: The four Format* functions repeat the same empty check,
CreationTimestamp sort, tabwriter setup/flush, and row printing logic. Refactor
the shared scaffolding in FormatPipelineRuns, FormatReleases,
FormatReleasesWithImages, and FormatReleasePipelineRuns into a common helper
that accepts the header and row-rendering callback, while keeping each function
responsible only for its specific columns and data extraction.

In `@hack/tools/find-push-pipelinerun/query.go`:
- Around line 100-125: The live-cluster error in listWithFallback is being
dropped when the KubeArchive fallback runs, so preserve and report the original
listResource failure from q.kubeHost before querying q.kaHost. Update
listWithFallback to log or wrap the live-query error when err is non-nil and
items is empty, and if the archive lookup also fails, include both the original
live error and the KubeArchive error in the returned error so the root cause is
not hidden.
- Around line 127-158: The request/response setup in listResource and
getResource is duplicated, including URL parsing, GET request creation, status
checking, and error-body handling. Extract that shared logic into a reusable
helper such as doRequest on the httpQuerier path, then have both listResource
and getResource call it and keep only their resource-specific decode logic. Make
sure the helper preserves the existing error formatting and response body
handling so both call sites behave the same.

In `@hack/tools/find-push-pipelinerun/watch.go`:
- Line 54: `watch` is making two `ListReleases` calls per loop and swallowing
release-listing errors, so consolidate the release lookup in the main iteration
and reuse it for both the terminal-state check and `printReleasePipeline`.
Update the `watch` loop and `printReleasePipeline` to accept the already-fetched
releases (or otherwise avoid re-calling `q.ListReleases(cfg.SHA)`), and change
the `ListReleases` error handling to surface persistent failures instead of
silently continuing, similar to how `ListPipelineRuns` errors are handled.
🪄 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: d090f0f3-6dd8-41e6-b5e6-01cf0da12886

📥 Commits

Reviewing files that changed from the base of the PR and between bed58a4 and fd53cb3.

⛔ Files ignored due to path filters (1)
  • docs/content/reference/aggregated-docs.md is excluded by !docs/content/reference/aggregated-docs.md
📒 Files selected for processing (14)
  • Makefile
  • docs/content/contribute/konflux-scripts.md
  • hack/tools/find-push-pipelinerun/format.go
  • hack/tools/find-push-pipelinerun/format_test.go
  • hack/tools/find-push-pipelinerun/main.go
  • hack/tools/find-push-pipelinerun/pr.go
  • hack/tools/find-push-pipelinerun/pr_test.go
  • hack/tools/find-push-pipelinerun/query.go
  • hack/tools/find-push-pipelinerun/query_test.go
  • hack/tools/find-push-pipelinerun/types.go
  • hack/tools/find-push-pipelinerun/watch.go
  • hack/tools/find-push-pipelinerun/watch_test.go
  • hack/tools/scripts/find-push-pipelinerun.sh
  • hack/tools/scripts/find-push-pipelinerun_test.bats
💤 Files with no reviewable changes (2)
  • hack/tools/scripts/find-push-pipelinerun.sh
  • hack/tools/scripts/find-push-pipelinerun_test.bats
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/content/contribute/konflux-scripts.md

Comment on lines +13 to +40
var (
pipelineRunTerminalStatuses = map[string]bool{
"Completed": true, "Failed": true, "Succeeded": true, "Error": true,
}
releaseTerminalStatuses = map[string]bool{
"Succeeded": true, "Failed": true, "Error": true, "Rejected": true,
}
)

// HasPending returns true if any PipelineRun has a non-terminal status.
func HasPending(prs []PipelineRun) bool {
for _, pr := range prs {
if !pipelineRunTerminalStatuses[pipelineRunStatus(pr)] {
return true
}
}
return false
}

// HasPendingReleases returns true if any Release has a non-terminal status.
func HasPendingReleases(releases []Release) bool {
for _, rel := range releases {
if !releaseTerminalStatuses[releaseStatus(rel)] {
return true
}
}
return false
}

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== format.go =="
nl -ba hack/tools/find-push-pipelinerun/format.go | sed -n '1,120p'

echo
echo "== watch loop usages =="
rg -n "HasPending\(|HasPendingReleases\(|WatchBuildPipeline|WatchReleasePipeline|pipelineRunTerminalStatuses|releaseTerminalStatuses" hack/tools/find-push-pipelinerun -n

echo
echo "== surrounding watch.go =="
nl -ba hack/tools/find-push-pipelinerun/watch.go | sed -n '1,220p'

Repository: openshift/hypershift

Length of output: 214


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== format.go =="
cat -n hack/tools/find-push-pipelinerun/format.go | sed -n '1,120p'

echo
echo "== watch loop usages =="
rg -n "HasPending\\(|HasPendingReleases\\(|WatchBuildPipeline|WatchReleasePipeline|pipelineRunTerminalStatuses|releaseTerminalStatuses" hack/tools/find-push-pipelinerun

echo
echo "== watch.go =="
cat -n hack/tools/find-push-pipelinerun/watch.go | sed -n '1,240p'

Repository: openshift/hypershift

Length of output: 10767


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== status helpers =="
rg -n "func pipelineRunStatus|func releaseStatus|Succeeded|Reason|Condition" hack/tools/find-push-pipelinerun/*.go

echo
echo "== relevant slices of format.go =="
sed -n '120,260p' hack/tools/find-push-pipelinerun/format.go | cat -n

echo
echo "== format tests around HasPending =="
sed -n '100,290p' hack/tools/find-push-pipelinerun/format_test.go | cat -n

Repository: openshift/hypershift

Length of output: 16571


Expand the PipelineRun terminal set. Any terminal reason missing from pipelineRunTerminalStatuses is treated as pending, so WatchBuildPipeline and the PipelineRun phase of WatchReleasePipeline can keep polling forever.

🤖 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 `@hack/tools/find-push-pipelinerun/format.go` around lines 13 - 40, The
PipelineRun terminal status set in pipelineRunTerminalStatuses is incomplete, so
HasPending treats some finished runs as pending and can cause WatchBuildPipeline
and the PipelineRun path in WatchReleasePipeline to poll forever. Update the
terminal status map to include any additional terminal PipelineRun reasons used
by pipelineRunStatus, and keep HasPending relying on that expanded set so
finished runs are no longer reported as pending.

Comment thread hack/tools/find-push-pipelinerun/main.go
Comment thread hack/tools/find-push-pipelinerun/pr.go
Comment thread hack/tools/find-push-pipelinerun/query.go
Comment on lines +40 to +58
func WatchReleasePipeline(q Querier, cfg WatchConfig) error {
for {
fmt.Fprintf(cfg.Stderr, "\n--- refreshing (%s) ---\n\n", cfg.Interval)
time.Sleep(cfg.Interval)

prs, err := q.ListPipelineRuns(cfg.SHA)
if err != nil {
return err
}
if cfg.Component != "" {
prs = FilterByComponent(prs, cfg.Component)
}
FormatPipelineRuns(cfg.Stdout, prs)

printReleasePipeline(q, cfg.SHA, cfg.Component, cfg.Stdout, cfg.Stderr)

if HasPending(prs) {
continue
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## File outline\n'
ast-grep outline hack/tools/find-push-pipelinerun/watch.go --view expanded || true

printf '\n## watch.go (relevant section)\n'
sed -n '1,180p' hack/tools/find-push-pipelinerun/watch.go

printf '\n## tests mentioning WatchReleasePipeline / ListReleases\n'
rg -n "WatchReleasePipeline|ListReleases|WatchBuildPipeline|HasPendingReleases|HasPending" hack/tools/find-push-pipelinerun -n -A3 -B3

printf '\n## watch_test.go relevant section\n'
sed -n '1,260p' hack/tools/find-push-pipelinerun/watch_test.go

Repository: openshift/hypershift

Length of output: 29818


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '80,130p' hack/tools/find-push-pipelinerun/main.go

Repository: openshift/hypershift

Length of output: 1345


Avoid fetching releases twice and swallowing API errors
WatchReleasePipeline already prints release data in the loop, so the extra ListReleases call only adds API traffic. More importantly, unexpected ListReleases failures are treated the same as “no release yet,” which can leave the watch spinning forever on RBAC/API errors. Return non-expected errors and only keep polling for the empty/not-created case.

🤖 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 `@hack/tools/find-push-pipelinerun/watch.go` around lines 40 - 58,
WatchReleasePipeline is fetching release data twice and hiding real API failures
by treating all ListReleases errors like “not found.” Update
WatchReleasePipeline and the printReleasePipeline path so releases are only
fetched once per loop, and distinguish expected empty/not-created cases from
unexpected errors. Use the existing Querier/ListReleases and
printReleasePipeline symbols to return non-expected errors immediately while
continuing to poll only for the missing-release case.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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 `@hack/tools/.golangci.yml`:
- Around line 1-46: The hack/tools/.golangci.yml config is currently unused
because the lint flow points at the root golangci config instead. Update the
lint setup so this file is actually invoked, either by adding a dedicated
hack/tools lint target or by wiring make lint to run golangci-lint with this
config; use the existing make lint entrypoint and the .golangci.yml file as the
locating symbols. If this config is not meant to be maintained separately,
remove it instead of leaving dead configuration behind.
🪄 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: c034d4c4-8d8e-4523-9443-f37f655ca623

📥 Commits

Reviewing files that changed from the base of the PR and between fd53cb3 and 9f27af0.

📒 Files selected for processing (6)
  • hack/tools/.golangci.yml
  • hack/tools/find-push-pipelinerun/format.go
  • hack/tools/find-push-pipelinerun/main.go
  • hack/tools/find-push-pipelinerun/pr.go
  • hack/tools/find-push-pipelinerun/query.go
  • hack/tools/find-push-pipelinerun/watch.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • hack/tools/find-push-pipelinerun/query.go
  • hack/tools/find-push-pipelinerun/pr.go
  • hack/tools/find-push-pipelinerun/main.go
  • hack/tools/find-push-pipelinerun/watch.go
  • hack/tools/find-push-pipelinerun/format.go

Comment thread hack/tools/.golangci.yml
Comment on lines +1 to +46
version: "2"
run:
allow-parallel-runners: true
linters:
enable:
- dupword
- durationcheck
- errorlint
- fatcontext
- gocyclo
- misspell
- nilerr
- noctx
- unparam
- usestdlibvars
settings:
gocyclo:
min-complexity: 30
misspell:
locale: US
exclusions:
warn-unused: true
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- unparam
path: '_test\.go$'
severity:
default: error
formatters:
enable:
- gci
settings:
gci:
sections:
- standard
- default
custom-order: true
exclusions:
warn-unused: true
generated: lax

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether the Makefile defines a target that runs golangci-lint against hack/tools
rg -n "hack/tools" Makefile
rg -n "golangci-lint run" Makefile

Repository: openshift/hypershift

Length of output: 1242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect lint-related Makefile targets and any CI entrypoints that call them.
rg -n "^(lint|.*lint.*):|golangci-lint|make lint|hack/tools" Makefile .github/workflows -g '!**/vendor/**' -g '!**/bin/**'

# Show the relevant Makefile section around lint targets.
line=$(rg -n "^(lint|.*lint.*):" Makefile | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-25))
  [ "$start" -lt 1 ] && start=1
  end=$((line+120))
  sed -n "${start},${end}p" Makefile
fi

Repository: openshift/hypershift

Length of output: 8795


Wire hack/tools/.golangci.yml into a lint target
make lint runs golangci-lint with the root ./.golangci.yml, so this config never gets applied. Add a hack/tools lint target or remove the file if it is unused.

🤖 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 `@hack/tools/.golangci.yml` around lines 1 - 46, The hack/tools/.golangci.yml
config is currently unused because the lint flow points at the root golangci
config instead. Update the lint setup so this file is actually invoked, either
by adding a dedicated hack/tools lint target or by wiring make lint to run
golangci-lint with this config; use the existing make lint entrypoint and the
.golangci.yml file as the locating symbols. If this config is not meant to be
maintained separately, remove it instead of leaving dead configuration behind.

- Add 30s timeout to GitHub and Kubernetes HTTP clients
- Validate WATCH_INTERVAL is positive before using it
- Consolidate ListReleases to one call per watch loop iteration
- Surface ListReleases errors instead of silently continuing
- Cache ReleasePlan mappings to avoid redundant API calls
- Use http.MethodGet instead of string literal
- Add golangci-lint config for hack/tools module

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@celebdor
celebdor force-pushed the feat/release-pipeline-tracking branch from 9f27af0 to 91f7e26 Compare July 8, 2026 07:09
@hypershift-jira-solve-ci

hypershift-jira-solve-ci Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

The repo is public. The 403 was a transient access issue. Here is the complete analysis:

Test Failure Analysis Complete

Job Information

  • Prow Job: Red Hat Konflux / hypershift-cli-mce-50-on-pull-request and Red Hat Konflux / hypershift-release-mce-50-on-pull-request
  • Build ID: PipelineRun hypershift-cli-mce-50-on-pull-request-krmtm and hypershift-release-mce-50-on-pull-request-xbncf
  • Namespace: crt-redhat-acm-tenant
  • PR: CNTRLPLANE-3773: Rewrite find-push-pipelinerun as Go CLI #8935 (CNTRLPLANE-3773: Rewrite find-push-pipelinerun as Go CLI)
  • Failure Time: 2026-07-08T07:09:40Z

Test Failure Analysis

Error

resolver failed to get Pipeline: error requesting remote resource: error getting "Git"
"crt-redhat-acm-tenant/git-cf61ca149fa5d103aab554fa1f36e671": error resolving repository:
git clone error: Cloning into '/tmp/konflux-build-catalog.git-3685898573'...
fatal: unable to access 'https://github.com/stolostron/konflux-build-catalog.git/':
The requested URL returned error: 403: exit status 128

Summary

Both Konflux pipeline runs failed before any build or test task could execute. The Tekton pipeline resolver in the Konflux build system was unable to clone stolostron/konflux-build-catalog.git from GitHub — a public repository that hosts the shared pipeline definitions. GitHub returned an HTTP 403 (Forbidden) during the git clone operation. This is a transient Konflux infrastructure issue, completely unrelated to the PR's code changes. The identical checks passed successfully on PR #8957 just ~3 hours earlier (completed at 04:17 UTC), confirming this was a temporary access disruption.

Root Cause

The root cause is a transient GitHub access failure from the Konflux build infrastructure. Specifically:

  1. The Konflux pipeline system uses a Tekton pipeline resolver to fetch pipeline definitions from https://github.com/stolostron/konflux-build-catalog.git at runtime.
  2. At ~07:09 UTC on 2026-07-08, the resolver received an HTTP 403 (Forbidden) response from GitHub when attempting to clone this repository.
  3. The repository stolostron/konflux-build-catalog is a public repository (confirmed via GitHub API), so this is not a permissions misconfiguration.
  4. The 403 likely resulted from one of: GitHub rate limiting on the Konflux build cluster's IP, a temporary GitHub service disruption, or an expired/revoked credential in the Konflux cluster's Git resolver configuration.
  5. Both pipeline runs (hypershift-cli-mce-50-on-pull-request-krmtm and hypershift-release-mce-50-on-pull-request-xbncf) failed at the pipeline resolution stage — no build tasks, compilation, or tests were ever attempted.
  6. The same two checks (hypershift-cli-mce-50-on-pull-request and hypershift-release-mce-50-on-pull-request) passed with SUCCESS on PR OCPBUGS-89689: (karpenter) use completed release image for unpinned NodeClaims during CP upgrade #8957 at 04:04–04:17 UTC the same day, confirming the issue is transient and not related to any code change.

This failure is not caused by PR #8935's code changes. The pipeline never reached the stage where it would examine the PR's source code.

Recommendations
  1. Re-trigger the checks: Push an empty commit or close/reopen the PR, or use the Konflux UI to rerun the pipeline. The transient 403 has likely resolved itself (PR OCPBUGS-89689: (karpenter) use completed release image for unpinned NodeClaims during CP upgrade #8957 passed the same checks earlier the same day).
  2. No code changes needed: This failure is entirely infrastructure-related and has zero connection to the PR's changes (rewriting find-push-pipelinerun as a Go CLI).
  3. If failures persist: Escalate to the Konflux/ACM build infrastructure team (crt-redhat-acm-tenant namespace owners) to investigate whether the Git resolver credentials or GitHub rate limits need attention for the stolostron/konflux-build-catalog repository.
Evidence
Evidence Detail
Error type Tekton pipeline resolver Git clone failure (HTTP 403)
Failed repository https://github.com/stolostron/konflux-build-catalog.git
Repository visibility Public (confirmed via gh api repos/stolostron/konflux-build-catalog)
Pipeline run 1 hypershift-cli-mce-50-on-pull-request-krmtm — failed at 07:09:40 UTC
Pipeline run 2 hypershift-release-mce-50-on-pull-request-xbncf — failed at 07:09:40 UTC
Same checks on PR #8957 Both passed (SUCCESS) at 04:04–04:17 UTC same day
Build/test execution None — pipeline failed during resolution before any task ran
Relation to PR code None — failure occurred before source code was ever accessed

@celebdor

celebdor commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

/override "ci/prow/e2e-azure-v2-self-managed"
/override "ci/prow/e2e-kubevirt-aws-ovn-reduced"
/override "ci/prow/e2e-v2-aws"
/override "ci/prow/e2e-v2-gke"

@openshift-ci

openshift-ci Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@celebdor: Overrode contexts on behalf of celebdor: ci/prow/e2e-azure-v2-self-managed, ci/prow/e2e-kubevirt-aws-ovn-reduced, ci/prow/e2e-v2-aws, ci/prow/e2e-v2-gke

Details

In response to this:

/override "ci/prow/e2e-azure-v2-self-managed"
/override "ci/prow/e2e-kubevirt-aws-ovn-reduced"
/override "ci/prow/e2e-v2-aws"
/override "ci/prow/e2e-v2-gke"

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.

@openshift-ci

openshift-ci Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Stale PRs are closed after 21d of inactivity.

If this PR is still relevant, comment to refresh it or remove the stale label.
Mark the PR as fresh by commenting /remove-lifecycle stale.

If this PR is safe to close now please do so with /close.

/lifecycle stale

@openshift-ci openshift-ci Bot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Aug 30, 2026
@openshift-ci

openshift-ci Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@celebdor: 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

area/ci-tooling Indicates the PR includes changes for CI or tooling area/documentation Indicates the PR includes changes for documentation jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants