Trigger a single automation run on demand, via CLI, API and UI - #2460
Conversation
Context: - Issue #2459: automations could only run on their own cron cadence, so trying one out, re-running it after a failure, or refreshing its results after late data arrived meant rewriting its cron string or bypassing the automation entirely. Change: - Add POST /assets/<id>/automations/<automation_id>/trigger, which runs one automation once, on top of its recurring runs. - It wraps the same run_automation() the recurring runner calls, so the jobs it queues are recorded as the automation's jobs, and it leaves the cursor alone, so the recurrence is unaffected. - Triggering requires create-children on the asset, which is what writing data under the asset means, and is what the other triggering endpoints require; it also falls under their stricter rate limit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Context: - Issue #2459: the CLI could only run all due automations (jobs run-automations), not a single one now. Change: - Add 'flexmeasures jobs run-automation --automation <id>', which queues the jobs for one run of one automation. - Like the API endpoint, it leaves the automation's cursor alone, so its next recurring run still happens as scheduled, and it can run an inactive automation, which is how one is tried out before activating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Context: - Issue #2459: the automations page could only show automations, not run one. Change: - Add a 'Run now' button per automation, which triggers a single run and refreshes that automation's job stats. - The button is shown to users who may create children on the asset, which is the permission the endpoint behind it requires. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Context: - Issue #2459: an on-demand run must queue the automation's jobs without disturbing its recurrence. Change: - Cover the CLI command end to end: it queues jobs recorded as the automation's own, writes an audit-log record, leaves the cursor where it was (so the next scheduled run still happens), and runs an inactive automation. - Cover the API endpoint's permissions, its response, that an automation of another asset or an unknown one is a 404, and that a run which cannot be set up is a 422 rather than a queued job. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Context: - Issue #2459 adds a way to run a single automation now, via CLI, API and UI. Change: - Describe when to use it, and how it relates to the recurring runs: the cursor is untouched, inactive automations can be run, and, unlike a recurring run, an on-demand run is not guarded against being started twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Context: - Issue #2459 adds the CLI command, API endpoint and UI button for it. Change: - Add entries to the main, CLI and API change logs; the new endpoint opens API revision v3.0-34. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Documentation build overview
8 files changed ·
|
There was a problem hiding this comment.
🟡 Changes recommended
There are a few correctness/convention issues in newly added code (CLI success on missing job info, and repo-enforced comment/doc wrapping conventions) that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds an on-demand “run once now” trigger for existing automations across CLI, API, and UI, reusing the existing run_automation() service so the queued jobs keep the same automation trigger metadata as scheduled runs.
Changes:
- CLI: introduce
flexmeasures jobs run-automation --automation <id>plus end-to-end tests asserting cursor is unchanged and scheduled runs still occur. - API: add
POST /api/v3_0/assets/<id>/automations/<automation_id>/trigger(rate-limited like other trigger endpoints) with tests for auth, 404/422 behavior, and response shape. - UI: add a per-automation “Run now” button gated by
create-childrenpermission, and wire it to the new API endpoint.
File summaries
| File | Description |
|---|---|
| flexmeasures/ui/views/assets/views.py | Passes user_can_create_children into the Automations page template for permission-gated UI actions |
| flexmeasures/ui/templates/assets/asset_automations.html | Adds “Run now” button and AJAX trigger call plus success/error messaging |
| flexmeasures/ui/static/openapi-specs.json | Regenerated OpenAPI spec including the new automation trigger endpoint |
| flexmeasures/cli/tests/test_automations.py | Adds CLI integration tests for on-demand runs, including cursor semantics and inactive automations |
| flexmeasures/cli/jobs.py | Adds run-automation CLI command that queues a single automation run and writes an audit-log entry |
| flexmeasures/api/v3_0/tests/test_automations_api.py | Adds API tests for the new trigger endpoint (auth, 202 payload, 404/422 cases) |
| flexmeasures/api/v3_0/assets.py | Implements the new trigger endpoint with permission checks and audit logging |
| documentation/features/automations.rst | Documents on-demand automation runs and their semantics |
| documentation/cli/change_log.rst | Records the new CLI command in the CLI changelog |
| documentation/changelog.rst | Adds a user-facing changelog entry for the new on-demand trigger feature |
| documentation/api/change_log.rst | Records the new API endpoint and its semantics in the API changelog |
Review details
Suppressed comments (1)
flexmeasures/ui/templates/assets/asset_automations.html:95
- This inline JavaScript comment should end with punctuation to follow the repo’s comment line-break convention (each physical line ends with a comma/semicolon/colon/period).
// Run this automation once, now, on top of its recurring runs
- Files reviewed: 11/11 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…LI, too Context: - Copilot review on PR #2460: the CLI wrote an audit-log record, committed and reported success with 0 jobs when a run reported no job, while the API endpoint treats that as an error. Change: - Roll back and abort in the CLI as well, so no run is recorded which did not queue work. - Keep the UI's success message grammatical when the response carries no job count. - Break the endpoint docstring after punctuation, and end the comments this PR adds at punctuation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
Context: - Copilot review on PR #2460 pointed out the CLI reported success in this case. Change: - Assert the CLI aborts, says so, and records nothing in the audit log when a run reports no job. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG Signed-off-by: F.N. Claessen <claessen@seita.nl>
There was a problem hiding this comment.
🟢 Approval recommended
The CLI/API/UI implementations are consistent with the stated semantics (not touching the cursor, shared run_automation() path, correct permission gating and rate limiting) and are covered by targeted tests and documentation updates.
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 0 new
- Review effort level: Lite
BelhsanHmida
left a comment
There was a problem hiding this comment.
Approving.
I tested, Everything passed. The endpoint shows up correctly in Swagger under Assets with both path parameters
and the 202/401/403/404/422/429 responses, and the documented example matches the actual response
field for field. Triggering an active automation returns 202 with the job id and n_jobs, queues the
job with {"origin": "automation", "automation_id": 1} in its metadata, writes the audit record, and
leaves the cursor alone. Inactive automations trigger fine and stay inactive. Unknown ids and
automations requested through the wrong asset both return 404 without reaching run_automation, a
user from another account gets 403 with nothing queued, and an automation whose output sensor sits
outside the asset returns 422 with the real reason, no job and no audit record. The rate limit kicks
in exactly at 10 and does share its budget with /schedules/trigger, as described.
The CLI behaves the same way. run-automation queues and records the run, an unknown id exits 2
cleanly, and a run that cannot be set up aborts without queueing anything. The cursor semantics hold
end to end: I triggered a run by hand, saw the cursor stay put, then ran run-automations and it
still queued the scheduled run and advanced the cursor. Job stats counted the manually triggered jobs
as the automation's own, so they do show up like any other run.
Closes #2459.
Automations could only ever run on their own cron cadence, so trying one out after creating it, re-running it once the cause of a failure was fixed, or refreshing its results after late input data arrived meant temporarily rewriting its cron string, or bypassing the automation and triggering a forecast by hand with the same parameters (which loses the link to the automation).
This adds a way to run one automation now, once, through all three interfaces:
flexmeasures jobs run-automation --automation 4POST /api/v3_0/assets/<id>/automations/<automation_id>/triggerAll three are thin wrappers around the same
run_automation()that the recurring runner calls, so an on-demand run is the same run, and the jobs it queues carry the same automation trigger metadata — they show up in the automation's job stats like any other run.Semantics
automation-run:<id>:<scheduled_at>, which has no counterpart here: the operator asked for the run. Asking twice queues two runs, which the docs say plainly. The UI disables its button while a request is in flight.create-childrenon the asset, i.e. what writing data under the asset means, and what the other triggering endpoints (/assets/<id>/schedules/trigger,/sensors/<id>/forecasts/trigger) require. This is a deliberate change from the "require update" suggestion in Trigger a single automation run on demand, via CLI, API and UI #2459: an automation's output sensors were checked against this same permission when it was created, and its output scope is re-checked on every run, so requiring account-admin here would be stricter than triggering the very same forecast by hand. Say the word if you would rather have it the other way round.When #2393 (durable automation-run records) lands, an on-demand run should get its own run record, marked as manually triggered; that is noted in #2459 rather than done here.
Testing
job,n_jobs), a 404 for an unknown automation and for one requested through an asset it does not belong to, and a 422 (rather than a queued job) when the run cannot be set up.n_jobsleft out).🤖 Generated with Claude Code
https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG