feat(automations): moteur de regles if-this-then-that (v5.1.0 roadmap, bump v5.2.0)
Moteur d'automatisation complet : declencheurs (evenement / cron / bouton),
conditions combinables (eq, neq, contains, is_empty, is_not_empty, changed)
et actions (webhook, set_property, create_page, notify).
- Migration v5 : tables `automations` + `automation_runs` (avec index).
- Service `app/services/automations.py` : fire_event, cron_due (`*/N`,
minute fixe, @hourly/@daily), scheduler de fond dans le lifespan.
- Router `app/routers/automations.py` : CRUD `/workspace/automations`,
historique des executions, run manuel + run bouton `/api/automations/{id}/run`
(exempt CSRF, comme `/api/agent`).
- Hooks d'evenements dans collections.py / board.py / workspace.py
(collection.* et page.* : created/updated/deleted/moved).
- Bloc `button` dans l'editeur (menu slash) : declenche une regle au clic,
picker d'automation inline, serialisation automations_id/name.
- Panneau Automations dans le Settings (creer/editer/activer/desactiver/
lancer/supprimer + historique), collection scope + JSON conditions/actions.
- 11 tests `tests/test_automations.py` ; suite complete pytest 289 verte.
- Version bump 5.2.0 (VERSION, app/main.py, CHANGELOG).
This commit is contained in:
@@ -172,6 +172,58 @@ def _migration_fts5(conn: sqlite3.Connection) -> None:
|
||||
)
|
||||
|
||||
|
||||
@register(5, "automations (v5.1.0 rules engine)")
|
||||
def _migration_automations(conn: sqlite3.Connection) -> None:
|
||||
"""v5.1.0: database automations — if-this-then-that rule engine (trigger +
|
||||
condition + action) and clickable buttons that trigger actions.
|
||||
|
||||
``automations`` — the rules (event/cron/button trigger, optional
|
||||
condition JSON, actions JSON, run counters).
|
||||
``automation_runs`` — execution history for auditing and the Settings UI.
|
||||
"""
|
||||
conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS automations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
workspace TEXT NOT NULL DEFAULT '',
|
||||
name TEXT NOT NULL,
|
||||
trigger_type TEXT NOT NULL DEFAULT 'event', -- event | cron | button
|
||||
event TEXT NOT NULL DEFAULT 'page.created', -- for trigger_type='event'
|
||||
cron_expression TEXT NOT NULL DEFAULT '', -- for trigger_type='cron'
|
||||
collection_id INTEGER, -- optional scope (event triggers)
|
||||
condition_json TEXT NOT NULL DEFAULT '[]', -- list of condition clauses
|
||||
actions_json TEXT NOT NULL DEFAULT '[]', -- list of action descriptors
|
||||
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||
created_by INTEGER,
|
||||
last_run_at TIMESTAMP,
|
||||
run_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""
|
||||
)
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_automations_trigger ON automations(trigger_type, event, enabled)"
|
||||
)
|
||||
conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS automation_runs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
automation_id INTEGER NOT NULL REFERENCES automations(id) ON DELETE CASCADE,
|
||||
trigger_source TEXT NOT NULL DEFAULT 'event',
|
||||
status TEXT NOT NULL DEFAULT 'fired', -- fired | skipped | error
|
||||
detail TEXT NOT NULL DEFAULT '',
|
||||
collection_id INTEGER,
|
||||
page_id INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""
|
||||
)
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_automation_runs_auto ON automation_runs(automation_id, created_at)"
|
||||
)
|
||||
|
||||
|
||||
@register(4, "database templates (icon) + property validation")
|
||||
def _migration_db_templates_validation(conn: sqlite3.Connection) -> None:
|
||||
"""v5.3.0: database templates get an icon, properties a validation config,
|
||||
|
||||
Reference in New Issue
Block a user