Skip to content

image-detector: support /image commit directive to force image builds#5105

Merged
openshift-merge-robot merged 1 commit into
openshift:mainfrom
jmguzik:image-detector
Apr 24, 2026
Merged

image-detector: support /image commit directive to force image builds#5105
openshift-merge-robot merged 1 commit into
openshift:mainfrom
jmguzik:image-detector

Conversation

@jmguzik

@jmguzik jmguzik commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

When build_if_affected is enabled, users can now add /image directives in commit messages to force-build specific images regardless of code change detection. The directive must start at the beginning of a line.

Supported syntax:

  • /image ... - force specific images
  • /image all - force all configured images

Image names are validated against images.items[].to in ci-operator config. Unknown names are warned and ignored. Forced images are unioned with auto-detected affected images.

Summary by CodeRabbit

Release Notes

  • New Features
    • Commit messages now support /image directives to control which tools and images are selected for builds
    • Use /image <name> to force a specific tool, or /image all to include all configured images
    • System validates image names against your configuration; warnings are logged for unsupported directives
    • Forced images are properly incorporated across all detection logic paths

@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

@coderabbitai

coderabbitai Bot commented Apr 14, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The changes extend AffectedTools() to precompute forced tool images by parsing /image directives from commit messages between the base and head references. When /image all is found, it returns the full configured image set. Otherwise, parsed image names are incorporated throughout the detection logic, including early-exit branches and the normal path. Helper functions are added for listing configured images, running git log with NUL-delimited output, and line-by-line parsing of directives with validation against allowed names.

Changes

Cohort / File(s) Summary
Core Implementation
pkg/tool-detector/detector.go
Adds precomputation of forced images from commit message /image directives. Parses directives with support for all keyword and individual image names. Incorporates forced images into detection logic across all code paths, with helper functions for git log operations and directive parsing. Includes warning logging for invalid directives.
Test Coverage
pkg/tool-detector/detector_test.go
Adds comprehensive table-driven test TestParseForcedImagesFromCommitMessages that validates directive parsing behavior, including handling of valid/invalid image names, all keyword, line position requirements, whitespace variations, and line ending formats (CRLF).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 11 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding support for a /image commit directive to force image builds in the image-detector tool, which is the primary functionality added in the pull request.
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 The PR does not contain any Ginkgo tests. All test code uses Go's standard testing package with table-driven test patterns via t.Run(). Since the custom check specifically requires assessment of Ginkgo test names (using It(), Describe(), Context(), etc.), and this PR contains only conventional Go unit tests with static, descriptive names containing no dynamic information, the check is not applicable to this PR.
Test Structure And Quality ✅ Passed Custom check for Ginkgo tests not applicable; pull request contains only standard Go testing package code.
Microshift Test Compatibility ✅ Passed This PR does not add any Ginkgo e2e tests, only unit tests for the tool-detector package. No MicroShift compatibility assessment required.
Single Node Openshift (Sno) Test Compatibility ✅ Passed This PR does not add Ginkgo e2e tests. Changes are limited to unit tests in pkg/tool-detector/detector_test.go using standard Go testing package, not Ginkgo.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only CI utility functions in pkg/tool-detector/ for image rebuild detection; contains no deployment manifests, scheduling constraints, or topology-aware configuration.
Ote Binary Stdout Contract ✅ Passed Modified code uses logrus for all logging, which writes to stderr by default, with no stdout redirections or direct stdout writes in process-level code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PR does not add any Ginkgo e2e tests. Changes consist only of Go unit tests for tool detection logic.

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

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

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

@openshift-ci openshift-ci Bot requested review from Prucek and bear-redhat April 14, 2026 14:12
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 14, 2026

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/tool-detector/detector_test.go (1)

865-875: Add one AffectedTools()-level test for the new control flow.

Lines 867-873 only exercise the parser. They won't catch regressions in the AffectedTools() branches that merge forced images, short-circuit on /image all, or hit the empty-diff path. A small git-backed test there would lock down the behavior that actually drives image skipping.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/tool-detector/detector_test.go` around lines 865 - 875, Add a new test in
detector_test.go that exercises the higher-level AffectedTools() control flow
(not just parseForcedImagesFromCommitMessages) by creating a small git-backed
repo state and commits that include the forced-image patterns; call
AffectedTools() (the function under test) and assert the three important
branches: (1) merging of forced images into the result, (2) short-circuit
behavior when a commit contains "/image all", and (3) the empty-diff path when
no changes should affect tools. Use the existing tests table style and reference
parseForcedImagesFromCommitMessages and AffectedTools by name so the test fails
if those branches regress. Ensure the test sets up commits/messages and allowed
list to trigger each branch and validates the returned forced-images map and the
all-flag or empty result accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/tool-detector/detector.go`:
- Around line 142-151: The git range in
Detector.getForcedImagesFromCommitMessages uses the symmetric difference range
"baseRef...HEAD" which can include commits from base when it's not an ancestor;
change the git log invocation to use a HEAD-only range such as "baseRef..HEAD"
(or compute merge-base(baseRef, HEAD) and use "mergeBase..HEAD") so only commits
reachable from HEAD are scanned for /image directives; update the exec.Command
call that builds the "git log" args in getForcedImagesFromCommitMessages
accordingly and audit any other uses of "...HEAD" in this package (e.g., other
functions that call git log or git diff) to the same pattern.

---

Nitpick comments:
In `@pkg/tool-detector/detector_test.go`:
- Around line 865-875: Add a new test in detector_test.go that exercises the
higher-level AffectedTools() control flow (not just
parseForcedImagesFromCommitMessages) by creating a small git-backed repo state
and commits that include the forced-image patterns; call AffectedTools() (the
function under test) and assert the three important branches: (1) merging of
forced images into the result, (2) short-circuit behavior when a commit contains
"/image all", and (3) the empty-diff path when no changes should affect tools.
Use the existing tests table style and reference
parseForcedImagesFromCommitMessages and AffectedTools by name so the test fails
if those branches regress. Ensure the test sets up commits/messages and allowed
list to trigger each branch and validates the returned forced-images map and the
all-flag or empty result accordingly.
🪄 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: Pro Plus

Run ID: 9acfe622-7b48-4518-8562-0abb52a2f7f4

📥 Commits

Reviewing files that changed from the base of the PR and between 40f5b15 and 4e14a75.

📒 Files selected for processing (2)
  • pkg/tool-detector/detector.go
  • pkg/tool-detector/detector_test.go

Comment thread pkg/tool-detector/detector.go Outdated
Comment thread pkg/tool-detector/detector.go
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

1 similar comment
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/tool-detector/detector.go`:
- Around line 89-91: The early returns fail to include forcedImages when
expanding binary-inputs; ensure the binary-input expansion call
getAffectedToolsByBinaryInputs is seeded with forcedImages so images forced via
"/image <tool>" propagate through inputs["bin"]. Specifically, where
affectedByImageChanges.Union(getAffectedToolsByBinaryInputs(affectedByImageChanges))
is computed (and in the other two similar return paths), call
getAffectedToolsByBinaryInputs with the union of affectedByImageChanges and
forcedImages (e.g.,
getAffectedToolsByBinaryInputs(affectedByImageChanges.Union(forcedImages))) and
then union the result with forcedImages before returning so forcedImages are
part of the binary-input expansion in all three return branches.
🪄 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: Pro Plus

Run ID: 72b03a4f-df69-46e0-9fc0-09a8fb5aca72

📥 Commits

Reviewing files that changed from the base of the PR and between 4e14a75 and eb4d47d.

📒 Files selected for processing (2)
  • pkg/tool-detector/detector.go
  • pkg/tool-detector/detector_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/tool-detector/detector_test.go

Comment thread pkg/tool-detector/detector.go
@jmguzik

jmguzik commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

1 similar comment
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

@danilo-gemoli

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Apr 20, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 4be58f4 and 2 for PR HEAD c12c68a in total

@jmguzik

jmguzik commented Apr 20, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD fb45e8f and 1 for PR HEAD c12c68a in total

@droslean

Copy link
Copy Markdown
Member

/retest

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD fc0afd3 and 0 for PR HEAD c12c68a in total

@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Apr 21, 2026

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
pkg/jira/fake.go (1)

45-50: Expose setup hooks for the new fake behaviors.

NewFake still only lets callers seed FileIssue expectations. Because closeBehavior and statusBehavior are unexported, packages outside pkg/jira can't reuse this fake for the expanded IssueFiler surface; the new pkg/slack/events/supportrequest/handler_test.go had to define another filer instead. Consider constructor options or helper setters for the new behaviors.

Also applies to: 125-130

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/jira/fake.go` around lines 45 - 50, NewFake currently only seeds
FileIssue expectations and leaves closeBehavior, statusBehavior,
unwantedCloseCalls and unwantedStatusCalls unexported so external tests can't
reuse this fake for the full IssueFiler surface; expose hooks by adding
constructor options or helper setters on the fake (e.g., NewFake(...opts) that
accept closeBehavior map[CloseIssueRequest]CloseIssueResponse and statusBehavior
map[SetIssueStatusRequest]SetIssueStatusResponse, or methods SetCloseBehavior
and SetStatusBehavior) and provide getters or exported slices for
unwantedCloseCalls/unwantedStatusCalls so tests can inspect calls; update the
fake's NewFake and the fake type to accept or set these behaviors and ensure the
names referenced (NewFake, closeBehavior, statusBehavior, unwantedCloseCalls,
unwantedStatusCalls, IssueRequest, CloseIssueRequest, SetIssueStatusRequest) are
used to locate the changes.
pkg/slack/events/supportrequest/lock.go (1)

40-73: Consider accepting context.Context parameter instead of using context.TODO().

Using context.TODO() throughout the lock operations prevents proper cancellation and timeout propagation from callers. This could cause the handler to hang indefinitely if the Kubernetes API is slow or unresponsive.

♻️ Suggested signature change
-func (c *configMapLockClient) Acquire(threadTS string) (bool, error) {
+func (c *configMapLockClient) Acquire(ctx context.Context, threadTS string) (bool, error) {
 	key := lockNameForThread(threadTS)
 	for i := 0; i < maxLockRetries; i++ {
-		lockMap, err := c.getOrCreateLockMap()
+		lockMap, err := c.getOrCreateLockMap(ctx)

Apply the same pattern to MarkProcessed, Release, and getOrCreateLockMap.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/slack/events/supportrequest/lock.go` around lines 40 - 73, Change the
locking methods to accept a context.Context parameter and propagate it instead
of using context.TODO(): update the signatures of Acquire, MarkProcessed,
Release and getOrCreateLockMap to accept ctx context.Context, replace any
context.TODO() calls (e.g., in c.client.Update and any other k8s client calls)
with the passed ctx, and update all call sites to forward the caller's context;
ensure error handling and retry logic remain the same and that
timeout/cancellation from the caller now properly cancels k8s API requests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/slack/events/supportrequest/lock.go`:
- Around line 75-98: The ConfigMap growth issue stems from MarkProcessed
(configMapLockClient) writing perpetual entries (lockStateProcessed) under keys
from lockNameForThread into threadLockMapName; change the stored value to
include a timestamp (e.g., "processed|<unix_ts>") or a separate timestamp map so
each entry can be aged, and implement a cleanup mechanism: add a
CleanProcessedOlderThan(threshold time.Duration) method that reads
threadLockMapName, removes entries whose timestamp is older than threshold, and
updates the ConfigMap with the same retry/conflict handling used in
MarkProcessed; schedule that cleanup via a periodic goroutine or external
CronJob and ensure all updates handle apierrors.IsConflict with retries.

---

Nitpick comments:
In `@pkg/jira/fake.go`:
- Around line 45-50: NewFake currently only seeds FileIssue expectations and
leaves closeBehavior, statusBehavior, unwantedCloseCalls and unwantedStatusCalls
unexported so external tests can't reuse this fake for the full IssueFiler
surface; expose hooks by adding constructor options or helper setters on the
fake (e.g., NewFake(...opts) that accept closeBehavior
map[CloseIssueRequest]CloseIssueResponse and statusBehavior
map[SetIssueStatusRequest]SetIssueStatusResponse, or methods SetCloseBehavior
and SetStatusBehavior) and provide getters or exported slices for
unwantedCloseCalls/unwantedStatusCalls so tests can inspect calls; update the
fake's NewFake and the fake type to accept or set these behaviors and ensure the
names referenced (NewFake, closeBehavior, statusBehavior, unwantedCloseCalls,
unwantedStatusCalls, IssueRequest, CloseIssueRequest, SetIssueStatusRequest) are
used to locate the changes.

In `@pkg/slack/events/supportrequest/lock.go`:
- Around line 40-73: Change the locking methods to accept a context.Context
parameter and propagate it instead of using context.TODO(): update the
signatures of Acquire, MarkProcessed, Release and getOrCreateLockMap to accept
ctx context.Context, replace any context.TODO() calls (e.g., in c.client.Update
and any other k8s client calls) with the passed ctx, and update all call sites
to forward the caller's context; ensure error handling and retry logic remain
the same and that timeout/cancellation from the caller now properly cancels k8s
API requests.
🪄 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: Pro Plus

Run ID: 2028b837-2743-452f-a66e-2b7ae404bd82

📥 Commits

Reviewing files that changed from the base of the PR and between c12c68a and 883ed89.

📒 Files selected for processing (12)
  • cmd/slack-bot/README.md
  • cmd/slack-bot/main.go
  • pkg/jira/fake.go
  • pkg/jira/issues.go
  • pkg/jira/issues_test.go
  • pkg/slack/events/router/router.go
  • pkg/slack/events/supportrequest/handler.go
  • pkg/slack/events/supportrequest/handler_test.go
  • pkg/slack/events/supportrequest/lock.go
  • pkg/slack/events/supportrequest/lock_test.go
  • pkg/tool-detector/detector.go
  • pkg/tool-detector/detector_test.go
✅ Files skipped from review due to trivial changes (1)
  • cmd/slack-bot/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/tool-detector/detector.go

Comment on lines +154 to +174
// Jira issue is created, so keep this thread lock permanently by
// converting it to a durable "processed" marker.
shouldReleaseLock = false
if err := locker.MarkProcessed(event.ThreadTimeStamp); err != nil {
return true, err
}
if err := filer.SetIssueStatus(issue.Key, jira.StatusInProgress, logger); err != nil {
logger.WithError(err).WithField("issue", issue.Key).Warn("Failed to transition support request to In Progress")
}

issueURL := fmt.Sprintf("%s%s", issuesRedHatBrowseBase, issue.Key)
_, _, postErr := postMessageWithRetry(client, channelID, slack.MsgOptionText(
fmt.Sprintf(
"%s <%s|%s>\nThis ticket was created automatically after this thread exceeded the threshold of %d messages. No user action is needed and conversation can continue in this forum thread.",
supportRequestPrefix, issueURL, issue.Key, threadMessageThreshold,
),
false,
), slack.MsgOptionTS(event.ThreadTimeStamp))
if postErr != nil {
logger.WithError(postErr).Warn("Failed to post support request Jira link in Slack thread")
}

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

Make the thread→issue mapping durable before exiting this critical section.

After FileIssue() succeeds, there are two failure windows here with bad recovery behavior. If MarkProcessed() fails, the handler returns before posting the Slack marker, so the thread only has a TTL-bound processing lock; once that expires, a later reply can reacquire and file a second Jira. If the Slack post fails after MarkProcessed(), the thread is permanently marked processed but handleReactionAdded() has no reply to scrape for the issue key, so the Slack close flow is orphaned. Persist the issue key atomically with the lock, or otherwise ensure one durable duplicate-suppression/discovery marker exists before returning.

Comment thread pkg/slack/events/supportrequest/lock.go Outdated
Comment on lines +75 to +98
func (c *configMapLockClient) MarkProcessed(threadTS string) error {
key := lockNameForThread(threadTS)
for i := 0; i < maxLockRetries; i++ {
lockMap := &corev1.ConfigMap{}
if err := c.client.Get(context.TODO(), ctrlruntimeclient.ObjectKey{Namespace: c.namespace, Name: threadLockMapName}, lockMap); err != nil {
if apierrors.IsNotFound(err) {
return nil
}
return err
}
if lockMap.Data == nil {
lockMap.Data = map[string]string{}
}
lockMap.Data[key] = lockStateProcessed
if err := c.client.Update(context.TODO(), lockMap); err != nil {
if apierrors.IsConflict(err) {
continue
}
return err
}
return nil
}
return fmt.Errorf("failed to mark lock for %s as processed after retries", threadTS)
}

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 | 🟡 Minor

ConfigMap can grow unbounded with "processed" entries.

The MarkProcessed method adds entries that are never cleaned up. Over time, the ConfigMap will accumulate stale "processed" entries, potentially approaching the 1MB etcd limit for ConfigMap data. Consider implementing periodic cleanup of old processed entries or adding a TTL-based eviction mechanism.

Would you like me to help design a cleanup strategy, such as:

  • Storing a timestamp with "processed" state and purging entries older than N days
  • Running a periodic goroutine that cleans old entries
  • Using a separate cleanup job/CronJob
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/slack/events/supportrequest/lock.go` around lines 75 - 98, The ConfigMap
growth issue stems from MarkProcessed (configMapLockClient) writing perpetual
entries (lockStateProcessed) under keys from lockNameForThread into
threadLockMapName; change the stored value to include a timestamp (e.g.,
"processed|<unix_ts>") or a separate timestamp map so each entry can be aged,
and implement a cleanup mechanism: add a CleanProcessedOlderThan(threshold
time.Duration) method that reads threadLockMapName, removes entries whose
timestamp is older than threshold, and updates the ConfigMap with the same
retry/conflict handling used in MarkProcessed; schedule that cleanup via a
periodic goroutine or external CronJob and ensure all updates handle
apierrors.IsConflict with retries.

@droslean

Copy link
Copy Markdown
Member

/retest

@Prucek

Prucek commented Apr 23, 2026

Copy link
Copy Markdown
Member

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Apr 23, 2026
@openshift-ci

openshift-ci Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: danilo-gemoli, jmguzik, 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:
  • OWNERS [Prucek,danilo-gemoli,jmguzik]

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

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 37cda1a and 2 for PR HEAD 4924fd2 in total

When build_if_affected is enabled, users can now add /image directives
in commit messages to force-build specific images regardless of code
change detection. The directive must start at the beginning of a line.

Supported syntax:
- /image <name1> <name2> ... - force specific images
- /image all - force all configured images

Image names are validated against images.items[].to in ci-operator
config. Unknown names are warned and ignored. Forced images are unioned
with auto-detected affected images.

Signed-off-by: Jakub Guzik <jguzik@redhat.com>
@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Apr 23, 2026
@openshift-ci

openshift-ci Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

New changes are detected. LGTM label has been removed.

@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 (1)
pkg/tool-detector/detector.go (1)

153-182: Optional: dedupe unknown-image warnings to reduce log noise.

If multiple commits repeat the same unknown image token, this currently logs repeatedly. Consider warning once per unique unknown token per parse run.

Possible small refactor
 func parseForcedImagesFromCommitMessages(messages []string, allowedImageNames sets.Set[string]) (sets.Set[string], bool) {
 	forced := sets.New[string]()
+	unknownWarned := sets.New[string]()
 	for _, message := range messages {
 		scanner := bufio.NewScanner(strings.NewReader(message))
 		for scanner.Scan() {
 			line := scanner.Text()
@@
 				if allowedImageNames.Has(imageName) {
 					forced.Insert(imageName)
 					continue
 				}
-				logrus.WithField("image", imageName).Warn("Ignoring unknown forced image requested via /image commit directive")
+				if !unknownWarned.Has(imageName) {
+					logrus.WithField("image", imageName).Warn("Ignoring unknown forced image requested via /image commit directive")
+					unknownWarned.Insert(imageName)
+				}
 			}
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/tool-detector/detector.go` around lines 153 - 182, In
parseForcedImagesFromCommitMessages, duplicate "unknown forced image" warnings
are noisy; add a local set (e.g., unknownWarned := sets.New[string]()) at the
top of the function and, when encountering an imageName that's not in
allowedImageNames and not "all", only call logrus.WithField(...).Warn(...) if
unknownWarned.Has(imageName) is false, then insert imageName into unknownWarned
to suppress further warnings for that token during this parse run; keep existing
behavior for inserting allowed names into forced and returning allowedImageNames
on "all".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/tool-detector/detector.go`:
- Around line 153-182: In parseForcedImagesFromCommitMessages, duplicate
"unknown forced image" warnings are noisy; add a local set (e.g., unknownWarned
:= sets.New[string]()) at the top of the function and, when encountering an
imageName that's not in allowedImageNames and not "all", only call
logrus.WithField(...).Warn(...) if unknownWarned.Has(imageName) is false, then
insert imageName into unknownWarned to suppress further warnings for that token
during this parse run; keep existing behavior for inserting allowed names into
forced and returning allowedImageNames on "all".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1fa3d157-4a8e-427d-873b-1b3b6595cc93

📥 Commits

Reviewing files that changed from the base of the PR and between 883ed89 and ece2da2.

📒 Files selected for processing (2)
  • pkg/tool-detector/detector.go
  • pkg/tool-detector/detector_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/tool-detector/detector_test.go

@jmguzik

jmguzik commented Apr 24, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@openshift-ci

openshift-ci Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

@jmguzik: The following tests 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/breaking-changes ece2da2 link false /test breaking-changes
ci/prow/images ece2da2 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.

@openshift-merge-robot openshift-merge-robot merged commit 751ad93 into openshift:main Apr 24, 2026
13 of 17 checks passed
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants