Skip to content

Fixes #39369 - Job Wizard should send bookmark_id#1037

Merged
adamlazik1 merged 2 commits into
theforeman:masterfrom
MariaAga:job-wizard-bookmarks
Jun 1, 2026
Merged

Fixes #39369 - Job Wizard should send bookmark_id#1037
adamlazik1 merged 2 commits into
theforeman:masterfrom
MariaAga:job-wizard-bookmarks

Conversation

@MariaAga
Copy link
Copy Markdown
Member

bookmark_id is always null in jobs created by the job wizard, it should be the actually value of the bookmark used

Is this issue a regression from the legacy page.

To test:

  1. got to new job wizard
  2. in the Target hosts and inputs step select search query -> then select a bookmark
  3. run job
  4. go to the job details page and expand the Target Hosts section

Expected behavior:
"Bookmark BOOKMARK_NAME using static query", and the search query is the bookmark.

Also rerun job should apply the bookmark search query.

@MariaAga
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Review Change Stack

Walkthrough

This pull request introduces bookmark support to JobWizard for host targeting. The changes establish Redux selectors and constants for host bookmarks, extend the autofill hook to detect and apply bookmarks from rerun data, refactor HostSearch to match search input against bookmark queries, wire bookmark selection through the component hierarchy, and update the submit action to include bookmark IDs in the payload. Test fixtures, fixtures setup, and test cases validate the bookmark flow across rerun and submission scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: enabling the Job Wizard to send bookmark_id when creating jobs, which directly addresses the issue being fixed.
Description check ✅ Passed The description is related to the changeset; it explains the problem (bookmark_id is always null), desired outcome, and provides testing steps that align with the implemented changes.
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.

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

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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
webpack/JobWizard/steps/HostsAndInputs/index.js (1)

168-193: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear bookmark selection when leaving search-query targeting mode.

A previously matched bookmark can remain selected after method switch, and then submission still sends bookmark_id, overriding current non-search targeting.

Suggested fix
                 setValue={val => {
                   setHostMethod(val);
+                  if (val !== hostMethods.searchQuery) {
+                    setSelectedBookmark(null);
+                  }
                   if (val === hostMethods.searchQuery) {
                     setErrorText(__('Please enter a search query'));
                   }
🤖 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 `@webpack/JobWizard/steps/HostsAndInputs/index.js` around lines 168 - 193, When
switching host targeting in the setValue handler for setHostMethod, clear any
previously matched bookmark so it doesn't persist when leaving search-query
mode; update the handler where setHostMethod(val) is called (the block that
checks val === hostMethods.searchQuery / hostMethods.hosts /
hostMethods.hostCollections / hostMethods.hostGroups) to call
setSelectedBookmark(null) (or an empty string per app convention) whenever val
!== hostMethods.searchQuery so bookmark_id is not sent for non-search targeting;
keep the existing errorText logic unchanged.
🧹 Nitpick comments (1)
webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js (1)

406-411: ⚡ Quick win

Avoid order-coupled assertion on the second dispatched action.

Using resourceSearchAction[1] makes this test fragile if dispatch order changes. Assert that at least one ForemanTasksTask action includes the encoded query instead.

Suggested test hardening
 const actions = newStore.getActions();
 const resourceSearchAction = actions.filter(
   action => action.key === 'ForemanTasksTask'
 );
 expect(resourceSearchAction).toHaveLength(2);
-expect(String(resourceSearchAction[1].url)).toContain('name=some+search');
+expect(
+  resourceSearchAction.some(action =>
+    String(action.url).includes('name=some+search')
+  )
+).toBe(true);
🤖 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 `@webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js`
around lines 406 - 411, The test is fragile because it indexes the second
dispatched ForemanTasksTask action (resourceSearchAction[1]); instead, filter
newStore.getActions() for actions with key === 'ForemanTasksTask' (as done into
resourceSearchAction) and assert that at least one of those actions' url
contains the encoded query (e.g., check that some(action =>
String(action.url).includes('name=some+search'))). Keep the existing expect for
total count if desired but remove the order-dependent indexing and use
Array.prototype.some on resourceSearchAction to verify the encoded query appears
in any matching action.
🤖 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 `@webpack/JobWizard/autofill.js`:
- Around line 88-103: The current branch only dispatches getBookmarks when
bookmarks.length === 0, so if bookmarks is non-empty but missing the requested
numericId the autofill never resolves; update the logic in autofill.js around
the bookmarks lookup (where bookmarks, numericId, setSelectedBookmark,
setHostsSearchQuery are used) to detect when no bookmark is found and in that
case call setPendingBookmarkId(numericId) and
dispatch(getBookmarks(hostsSearchProps.bookmarks.url, hostsController)) so the
missing bookmark is fetched and the pending id can be resolved when results
arrive.

---

Outside diff comments:
In `@webpack/JobWizard/steps/HostsAndInputs/index.js`:
- Around line 168-193: When switching host targeting in the setValue handler for
setHostMethod, clear any previously matched bookmark so it doesn't persist when
leaving search-query mode; update the handler where setHostMethod(val) is called
(the block that checks val === hostMethods.searchQuery / hostMethods.hosts /
hostMethods.hostCollections / hostMethods.hostGroups) to call
setSelectedBookmark(null) (or an empty string per app convention) whenever val
!== hostMethods.searchQuery so bookmark_id is not sent for non-search targeting;
keep the existing errorText logic unchanged.

---

Nitpick comments:
In `@webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js`:
- Around line 406-411: The test is fragile because it indexes the second
dispatched ForemanTasksTask action (resourceSearchAction[1]); instead, filter
newStore.getActions() for actions with key === 'ForemanTasksTask' (as done into
resourceSearchAction) and assert that at least one of those actions' url
contains the encoded query (e.g., check that some(action =>
String(action.url).includes('name=some+search'))). Keep the existing expect for
total count if desired but remove the order-dependent indexing and use
Array.prototype.some on resourceSearchAction to verify the encoded query appears
in any matching action.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 95a1cdb9-5450-4ecc-b7d7-37764726aa69

📥 Commits

Reviewing files that changed from the base of the PR and between dda4630 and 2657a9c.

⛔ Files ignored due to path filters (2)
  • webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap is excluded by !**/*.snap
  • webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (13)
  • webpack/JobWizard/JobWizard.js
  • webpack/JobWizard/JobWizardConstants.js
  • webpack/JobWizard/JobWizardSelectors.js
  • webpack/JobWizard/__tests__/JobWizardPageRerun.test.js
  • webpack/JobWizard/__tests__/fixtures.js
  • webpack/JobWizard/autofill.js
  • webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js
  • webpack/JobWizard/steps/HostsAndInputs/HostSearch.js
  • webpack/JobWizard/steps/HostsAndInputs/__tests__/HostsAndInputs.test.js
  • webpack/JobWizard/steps/HostsAndInputs/index.js
  • webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js
  • webpack/JobWizard/submit.js
  • webpack/__mocks__/foremanReact/components/SearchBar.js
💤 Files with no reviewable changes (1)
  • webpack/mocks/foremanReact/components/SearchBar.js

Comment on lines +88 to +103
if (bookmarks.length > 0) {
const bookmark = bookmarks.find(bm => bm.id === numericId);
if (bookmark) {
setSelectedBookmark({
id: bookmark.id,
name: bookmark.name,
query: bookmark.query,
});
setHostsSearchQuery(bookmark.query);
}
} else {
setPendingBookmarkId(numericId);
dispatch(
getBookmarks(hostsSearchProps.bookmarks.url, hostsController)
);
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 28, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fetch bookmarks when the requested bookmark ID is missing from cached results.

The current logic only dispatches getBookmarks when the cache is empty. If cache is non-empty but doesn’t contain the rerun bookmark_id, autofill never resolves the bookmark.

Suggested fix
       if (bookmarkId) {
         setSelectedTargets({
           hosts: [],
           hostCollections: [],
           hostGroups: [],
         });
         const numericId = Number(bookmarkId);
-        if (bookmarks.length > 0) {
-          const bookmark = bookmarks.find(bm => bm.id === numericId);
-          if (bookmark) {
-            setSelectedBookmark({
-              id: bookmark.id,
-              name: bookmark.name,
-              query: bookmark.query,
-            });
-            setHostsSearchQuery(bookmark.query);
-          }
-        } else {
+        const bookmark = bookmarks.find(bm => bm.id === numericId);
+        if (bookmark) {
+          setSelectedBookmark({
+            id: bookmark.id,
+            name: bookmark.name,
+            query: bookmark.query,
+          });
+          setHostsSearchQuery(bookmark.query);
+        } else {
           setPendingBookmarkId(numericId);
           dispatch(
             getBookmarks(hostsSearchProps.bookmarks.url, hostsController)
           );
         }
       } else if ((search || search === '') && !hostIds?.length) {
🤖 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 `@webpack/JobWizard/autofill.js` around lines 88 - 103, The current branch only
dispatches getBookmarks when bookmarks.length === 0, so if bookmarks is
non-empty but missing the requested numericId the autofill never resolves;
update the logic in autofill.js around the bookmarks lookup (where bookmarks,
numericId, setSelectedBookmark, setHostsSearchQuery are used) to detect when no
bookmark is found and in that case call setPendingBookmarkId(numericId) and
dispatch(getBookmarks(hostsSearchProps.bookmarks.url, hostsController)) so the
missing bookmark is fetched and the pending id can be resolved when results
arrive.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think this behaviour makes sense

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@MariaAga, understood — if bookmarks are already loaded in the store, a missing ID would indicate the bookmark no longer exists rather than being a cache miss, so skipping the fetch in that case is a reasonable assumption. I'll defer to your judgment here.

Copy link
Copy Markdown
Contributor

@adamlazik1 adamlazik1 left a comment

Choose a reason for hiding this comment

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

I have few notes and questions:

  1. When selecting a bookmark and then switching host method to something else, the bookmark search query is not cleared. For example, when the host method is switched to Hosts and a different host than the one the bookmark resolves to is selected, the job invocation is executed on both hosts - from bookmark search query and from Hosts. Then under target hosts it displays only the search query from bookmarks but not the other resolved host from Hosts. Is this intended behavior?

  2. Typing a query identical to a bookmark implicitly sends bookmark_id instead of search_query. This might potentially cause subtle rerun mismatches. If the query was originally dynamic, the rerun is triggered with the static query from the bookmark instead.

  3. The bookmark dropdown is being cut from the wizard view:

Image

@MariaAga
Copy link
Copy Markdown
Member Author

Thanks!

When selecting a bookmark and then switching host method to something else, the bookmark search query is not cleared. For example, when the host method is switched to Hosts and a different host than the one the bookmark resolves to is selected, the job invocation is executed on both hosts - from bookmark search query and from Hosts. Then under target hosts it displays only the search query from bookmarks but not the other resolved host from Hosts. Is this intended behavior?

No, fixed - so when other items are selected, it will not send the bookmark id.

Typing a query identical to a bookmark implicitly sends bookmark_id instead of search_query. This might potentially cause subtle rerun mismatches. If the query was originally dynamic, the rerun is triggered with the static query from the bookmark instead.

Right, fixed so if the search bar is typed, the bookmark id is not sent

The bookmark dropdown is being cut from the wizard view:

Changed the position of the dropdown so it will be visible within the wizard

@adamlazik1
Copy link
Copy Markdown
Contributor

I apologize for the noise, seems I don't know how to use the gh CLI feature. Can you please force push your branch in the current state once again to overwrite my mess?

Copy link
Copy Markdown
Contributor

@adamlazik1 adamlazik1 left a comment

Choose a reason for hiding this comment

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

LGTM. Tested on verified on packit build.

@adamlazik1 adamlazik1 merged commit 7c9fed6 into theforeman:master Jun 1, 2026
23 checks passed
@adamlazik1
Copy link
Copy Markdown
Contributor

Thanks @MariaAga !

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants