Skip to content

Trigger a single automation run on demand, via CLI, API and UI - #2460

Merged
Flix6x merged 8 commits into
mainfrom
feat/2459-trigger-automation-run
Sep 3, 2026
Merged

Trigger a single automation run on demand, via CLI, API and UI#2460
Flix6x merged 8 commits into
mainfrom
feat/2459-trigger-automation-run

Conversation

@Flix6x

@Flix6x Flix6x commented Sep 2, 2026

Copy link
Copy Markdown
Member

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:

  • CLI: flexmeasures jobs run-automation --automation 4
  • API: POST /api/v3_0/assets/<id>/automations/<automation_id>/trigger
  • UI: a Run now button per automation on the asset's Automations page

All 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

  • The cursor is not touched. An on-demand run is extra work, not a claim on a scheduled occurrence, so the next recurring run still happens as scheduled, and a run missed while the runner was down is still caught up. A CLI test asserts exactly this: it triggers a run by hand, then lets the recurring runner run and checks that it still queues the scheduled run.
  • No duplicate guard. The recurring path holds a Redis guard on 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.
  • Inactive automations can be triggered, since an inactive automation is exactly the one you want to try out before switching it on.
  • Permission: create-children on 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.
  • The endpoint falls under the stricter trigger rate limit the other triggering endpoints share (visible in the regenerated OpenAPI spec).
  • The API path stays nested under the asset, matching the two merged automation endpoints, the CRUD endpoints under review in CRUD for automations in the API and UI #2294, and the UI route.

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

  • CLI, end to end (real queueing): jobs are queued and recorded as the automation's own, an audit-log record is written, the cursor stays put and the next scheduled run still happens, an inactive automation runs, and an unknown ID is reported cleanly.
  • API: permissions (401/403/202), the response (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.
  • Each new assertion was verified to fail when the behaviour it covers is broken (cursor advanced on an on-demand run; the asset/automation consistency check dropped; n_jobs left out).

🤖 Generated with Claude Code

https://claude.ai/code/session_01G9NpBEcXs6MbCAzzm1sLxG

Flix6x and others added 6 commits September 2, 2026 12:29
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>
@read-the-docs-community

read-the-docs-community Bot commented Sep 2, 2026

Copy link
Copy Markdown

Copilot AI 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.

🟡 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-children permission, 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.

Comment thread flexmeasures/cli/jobs.py Outdated
Comment thread flexmeasures/api/v3_0/assets.py Outdated
Comment thread flexmeasures/ui/templates/assets/asset_automations.html Outdated
Comment thread flexmeasures/ui/templates/assets/asset_automations.html
Flix6x and others added 2 commits September 2, 2026 12:39
…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>

Copilot AI 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.

🟢 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

@Flix6x
Flix6x requested a review from BelhsanHmida September 2, 2026 12:08
@Flix6x Flix6x self-assigned this Sep 2, 2026

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

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.

@Flix6x Flix6x added this to the 1.1.0 milestone Sep 3, 2026
@Flix6x
Flix6x merged commit 48705b5 into main Sep 3, 2026
14 checks passed
@Flix6x
Flix6x deleted the feat/2459-trigger-automation-run branch September 3, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trigger a single automation run on demand, via CLI, API and UI

3 participants