-
Notifications
You must be signed in to change notification settings - Fork 16.4k
Add support for opening trigger modal via URL pre-populated #55277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for opening trigger modal via URL pre-populated #55277
Conversation
jscheffl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR. Some comments as general code review. Did not test myself (yet) as I assume it will need a bit of adjustments. Code is mainly looking good.
Regarding your questions:
- I (personally, other opinions welcome) would favor using
/triggerand not a URL parameter for this. Also themodecould be directly encoded as part of the URL like/trigger/single(and would propose to have single as default because this would be for 90% of calls I assume).
General feedback to the PR:
- In PR #54783 we also had a discussion about passing form values as JSON dict. In my view this makes it complex because a user who constructs a URL must make a proper JSON and encode the data in the URL properly. Finally we came to the point in passing individual key/vale pairs and not a JSON dict. See also #54783 (comment) - I'd wish to make it consistent here as well.
- Please also add documentation back to airflow-core/docs/core-concepts/params.rst as it was removed in #54799 and describe how users can use it (would be bad if users need to read source to discover such cool features!)
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGButton.tsx
Outdated
Show resolved
Hide resolved
airflow-core/src/airflow/ui/src/constants/reprocessBehaviourParams.ts
Outdated
Show resolved
Hide resolved
airflow-core/src/airflow/ui/src/constants/reprocessBehaviourParams.ts
Outdated
Show resolved
Hide resolved
|
Hello @jscheffl @guan404ming, @RoyLee1224 since last time of your review, colud you also help me to review with this PR, thx! |
2b8bc23 to
827c6c3
Compare
Added support for `?trigger=true` or `?trigger=1` query parameter to automatically open TriggerDAGModal
- Added `decodeParam` for safe URL decoding - Added `parseJsonSafe` for safe JSON.parse with fallback - Added `getUrlParam` to unify parameter extraction and optional JSON parsing
- Pre-populate fields (conf, dag_run_id, logical_date, note) from URL parameters - URL conf is validated and pretty-printed if valid JSON - add openAdvanced that supports open automatically
- Added parsing of backfill-specific parameters (start_date, end_date, reset_dagruns, rerun_failed_tasks, etc.) - Connected URL param values into Backfill form default state - add mapped helper function with ReprocessBehavior
1. add `/trigger/single` and `/trigger/backfill` pathname to fit the correct mode. 2. add trigger.ts: encapsulate params getter function to new file 3. refactor TriggerDAGModal, TrggerDAGForm, TrggerDAGButton, RunBackfillForm * RunBackfillForm is almost closed to the maximum line, we may need to refactor it.
827c6c3 to
969a418
Compare
I see no change in regards to - was this missed-out? Or do you have a strong preperence to the proposed PR solution with a JSON? Then I'd need some arguments to convince me.
|
Didn't the PR description solve the problem? 🤔 After I read all the PRs you mentioned, I realized we need to add Now If I still misunderstood the meaning, sorry for my poor understanding... 🤡 |
guan404ming
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
I think the implementation could be simpler by just get search param via hook and preload them in FlexiableForm
| - ``conf`` – JSON configuration. | ||
| - ``run_id`` – run identifier. | ||
| - ``logical_date`` – execution date in ``YYYY-MM-DDTHH:mm:ss.SSS`` format. Defaults to the current timestamp if not provided. | ||
| - ``note`` – note attached to the DAG run. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fields in the form would dynamically change based on user's config. Thus, we may not only need to handle these specific fields but we should handle all fields passed. The implementation is quite like #54783
pierrejeambrun
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, a few suggestion in addition to @guan404ming comments.
| const params = new URLSearchParams(search); | ||
| const { | ||
| conf: urlConf, | ||
| from_date: urlFromDate, | ||
| max_active_runs: urlMaxActiveRuns, | ||
| reprocess_behavior: urlReprocessBehavior, | ||
| run_backwards: urlRunBackwards, | ||
| to_date: urlToDate, | ||
| } = getPreloadBackfillFormData(params); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use the searchParam hook there.
| // Only sync URL when already within trigger route to avoid interfering with close navigation | ||
| if (!open || !/\/trigger(\/(single|backfill))?$/u.test(pathname)) { | ||
| return; | ||
| } | ||
|
|
||
| const targetPath = normalizeTriggerPath(pathname, runMode); | ||
|
|
||
| if (pathname !== targetPath) { | ||
| navigate({ pathname: targetPath, search }, { replace: true }); | ||
| } | ||
| }, [runMode, pathname, search, navigate, open]); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably add router entries on ..../trigger/{mode} that also maps to the same page, and handle the path param mode if in the URL.
| from_date: searchParams.get("start_date") ?? "", | ||
| max_active_runs: parseInt(searchParams.get("max_active_runs") ?? "1", 10), | ||
| reprocess_behavior: (searchParams.get("reprocess_behavior") ?? "none") as ReprocessBehavior, | ||
| run_backwards: ["1", "true"].includes(searchParams.get("run_backwards") ?? ""), | ||
| to_date: searchParams.get("end_date") ?? "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you change the url name of the param vs the one used for the form?
| from_date: searchParams.get("start_date") ?? "", | |
| max_active_runs: parseInt(searchParams.get("max_active_runs") ?? "1", 10), | |
| reprocess_behavior: (searchParams.get("reprocess_behavior") ?? "none") as ReprocessBehavior, | |
| run_backwards: ["1", "true"].includes(searchParams.get("run_backwards") ?? ""), | |
| to_date: searchParams.get("end_date") ?? "", | |
| from_date: searchParams.get("from_date") ?? "", | |
| max_active_runs: parseInt(searchParams.get("max_active_runs") ?? "1", 10), | |
| reprocess_behavior: (searchParams.get("reprocess_behavior") ?? "none") as ReprocessBehavior, | |
| run_backwards: ["1", "true"].includes(searchParams.get("run_backwards") ?? ""), | |
| to_date: searchParams.get("to_date") ?? "", |
Also you should probably use the PARAMS constants from SearchParamsKeys and update that enum if some keys are missing.
| { element: <Overview />, path: "single" }, | ||
| { element: <Overview />, path: "backfill" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should pass trigger={"single" | "backfill" | undefined} as props from here instead of trying to manually parse the url string?
| </Dialog.Header> | ||
|
|
||
| <Dialog.CloseTrigger /> | ||
| <Dialog.CloseTrigger onClick={onClose} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this change
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions. |
Description
This PR introduces a new feature that allows calling DAG trigger modals with Single/Backfill mode to be opened directly via URL using the query string parameter.
The feature also supports pre-populating form fields from URL parameters, improving automation and integration with external tools.
Changes
1. Trigger Modal Opening/Closing
/dags/{dag_id}/trigger/singleor/dags/{dag_id}/trigger/backfill, the Trigger Modal automatically opens with correspond mode./dags/{dag_id}automatically.2. URL Parameter Pre-Population
Trigger form supports (you can check its functionality on UI):
confrun_idlogical_datenoteBackfill form supports (you can check its functionality on UI):
start_dateend_daterun_backwardsreprocess_behaviormax_active_runsconfconfsupports 2 type:Has higher priority if present.
/dags/{dag_id}/trigger/single?conf={"foo":"bar","x":123}confis not specified, any query parameter that is not a reserved keyword will be collected intoconf./dags/{dag_id}/trigger/single?run_id=myrun&foo=bar&x=123→conf={"foo":"bar","x":"123"}3. Utilities Added
New helper file in
src/utils/trigger.ts:getPreloadTriggerFormData,getPreloadBackfillFormData)getRunModeFromPathnamenormalizeTriggerPath, i.e. (/trigger/single,/trigger/backfill)4. Advanced Options
Examples
1. Single mode
/trigger/single&mode=single?conf={"environment":"production","debug":true,"user":"admin"}&run_id=test_run_001&logical_date=2024-01-15T10:30:00.000¬e=testing note2. Backfill mode
/trigger/backfill?start_date=2024-01-01&end_date=2024-01-31&run_backwards=true&reprocess_behavior=missing_runs&max_active_runs=3&conf={"environment":"staging","batch_size":1000}Snapshot
/dag/{dag_id}/trigger/single?run_id=run%20dag&logical_date=2025-09-06T12:34:56.789&conf={%22foo%22:%22bar%22,%22ping%22:%22pong%22}¬e=Nothing%20beats%20a%20jet2%20holidaysingle.mode.mov
/dags/{dag_id}/trigger/backfill?start_date=2025-09-01T12:34:56&end_date=2025-09-02T12:34:56&conf={%22foo%22:%22bar%22,%22ping%22:%22pong%22}&reprocess_behavior=completed&max_active_runs=3&run_backwards=1backfill.mode.mov
key=valuetype of conf with/dags/{dag_id}/trigger/single?run_id=run%20dag&logical_date=2025-09-06T12:34:56.789&foo=bar&ping=pong¬e=Nothing%20beats%20a%20jet2%20holidaykey.value.type.of.conf.mov
Documentation
I edited the
/core-concepts/params.htmlfile for this change, I addedtrigger params,conf usage table,examples for 2 mode.Related Issue
resolves #54800