New to Kestra?
Use blueprints to kickstart your first workflows.
Sweep a Miro team for boards untouched for N days with Kestra and delete them behind an explicit confirmation gate, with a Discord audit summary.
Old boards pile up until finding the current one means scrolling past two years of abandoned brainstorms, and every abandoned board is also an unwatched surface still sharing whatever was pasted onto it. This blueprint automates the cleanup with the caution deletion deserves. The flow lists a team's boards with io.kestra.plugin.miro.boards.List, compares each board's modifiedAt timestamp against a configurable staleness cutoff, and deletes the stale ones with io.kestra.plugin.miro.boards.Delete. Because Miro deletion is permanent and cannot be undone, an If guard fails the execution before anything is listed unless the confirm_delete input is explicitly true, and a Discord summary records every sweep.
confirm_gate (io.kestra.plugin.core.flow.If) checks the confirm_delete boolean first. When false, the nested io.kestra.plugin.core.execution.Fail task stops the execution with a clear message before any Miro call is made.list_boards (io.kestra.plugin.miro.boards.List) fetches up to 50 boards for the team, exposing the page as {{ outputs.list_boards.boards }} plus total and size scalars.sweep_stale (io.kestra.plugin.core.flow.ForEach) iterates the board objects; inside the loop each board arrives as a JSON string, decoded with fromJson(taskrun.value).check_stale compares modifiedAt against now() minus stale_days. Both sides are rendered as yyyy-MM-dd strings, which sort correctly under plain string comparison, so the date logic stays one readable line.delete_board runs only inside the If branch and reads the board ID with fromJson(parent.taskrun.value).id, since tasks nested under an If inside a ForEach reach the loop value through parent.notify posts a Discord audit summary with the scanned counts and threshold; the errors block reports stopped or failed sweeps, including unconfirmed runs.Schedule trigger is included; scheduled runs use input defaults, so confirm_delete defaulting to false keeps even an accidentally enabled schedule harmless.A cleanup script with a delete call in a loop is exactly the kind of automation that needs guardrails: typed inputs with safe defaults, a fail-fast confirmation gate, per-iteration visibility into what was deleted, and a permanent execution history. Kestra provides all of that declaratively, and the same flow serves as both the quarterly job and the documented, repeatable manual procedure.
boards:read and boards:write scopes.MIRO_ACCESS_TOKEN: Miro OAuth 2.0 access token.DISCORD_WEBHOOK_URL: Discord incoming webhook URL.confirm_delete left false and confirm it fails fast with the guard message.confirm_delete true and a high stale_days, and verify the Discord summary and per-board results.quarterly trigger.offset property across repeated runs.boards.Update renaming stale boards with an ARCHIVE prefix, keeping the same loop and gate.query property.