Use Node.js script for Cronicle trigger to avoid shell dependency
Switches from curl (shell not available in Cronicle container) to a Node.js inline script using the built-in http module. Tries raggr-green first, falls back to raggr-blue automatically — no manual update needed on color swap. Delete the existing broken Cronicle event before redeploying. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+34
-16
@@ -47,7 +47,35 @@ async def _get_first_category_id() -> str:
|
||||
return rows[0]["id"]
|
||||
|
||||
|
||||
async def _create_event(title: str, url: str, headers: str, category_id: str) -> str:
|
||||
def _make_trigger_script(cron_secret: str) -> str:
|
||||
"""Node.js script that tries raggr-green then falls back to raggr-blue.
|
||||
|
||||
Uses Node's built-in http module — no curl/wget needed, and node is always
|
||||
present since Cronicle itself runs on Node.
|
||||
"""
|
||||
path = "/api/scheduled-messages/trigger"
|
||||
return f"""#!/usr/bin/env node
|
||||
const http = require('http');
|
||||
function post(host) {{
|
||||
return new Promise((resolve, reject) => {{
|
||||
const req = http.request(
|
||||
{{ hostname: host, port: 8080, path: '{path}', method: 'POST',
|
||||
headers: {{'X-Cron-Secret': '{cron_secret}'}} }},
|
||||
res => {{ res.resume(); resolve(res.statusCode); }}
|
||||
);
|
||||
req.setTimeout(10000, () => {{ req.destroy(); reject(new Error('timeout')); }});
|
||||
req.on('error', reject);
|
||||
req.end();
|
||||
}});
|
||||
}}
|
||||
post('raggr-green').catch(() => post('raggr-blue')).catch(err => {{
|
||||
console.error('trigger failed:', err.message);
|
||||
process.exitCode = 1;
|
||||
}});
|
||||
"""
|
||||
|
||||
|
||||
async def _create_event(title: str, script: str, category_id: str) -> str:
|
||||
async with httpx.AsyncClient() as client:
|
||||
resp = await client.post(
|
||||
f"{_base_url()}/api/app/create_event/v1",
|
||||
@@ -55,17 +83,12 @@ async def _create_event(title: str, url: str, headers: str, category_id: str) ->
|
||||
"api_key": _api_key(),
|
||||
"title": title,
|
||||
"enabled": 1,
|
||||
"plugin": "urlplug",
|
||||
"plugin": "shellplug",
|
||||
"target": "allgrp",
|
||||
"category": category_id,
|
||||
# Every minute: all 60 minutes explicitly (Cronicle {} defaults to hourly)
|
||||
# Every minute: list all 60 explicitly (Cronicle {} defaults to hourly)
|
||||
"timing": {"minutes": list(range(60))},
|
||||
"params": {
|
||||
"method": "post",
|
||||
"url": url,
|
||||
"headers": headers,
|
||||
"data": "",
|
||||
},
|
||||
"params": {"script": script},
|
||||
"notes": "Auto-registered by raggr on startup",
|
||||
},
|
||||
timeout=10,
|
||||
@@ -87,7 +110,6 @@ async def ensure_cronicle_events() -> None:
|
||||
return
|
||||
|
||||
cron_secret = os.environ.get("CRON_SECRET", "")
|
||||
raggr_url = os.environ.get("RAGGR_INTERNAL_URL", "http://raggr-green:8080")
|
||||
|
||||
try:
|
||||
events = await _get_events()
|
||||
@@ -96,12 +118,8 @@ async def ensure_cronicle_events() -> None:
|
||||
return
|
||||
|
||||
category_id = await _get_first_category_id()
|
||||
event_id = await _create_event(
|
||||
title=_SCHEDULED_MESSAGES_TITLE,
|
||||
url=f"{raggr_url}/api/scheduled-messages/trigger",
|
||||
headers=f"X-Cron-Secret: {cron_secret}",
|
||||
category_id=category_id,
|
||||
)
|
||||
script = _make_trigger_script(cron_secret)
|
||||
event_id = await _create_event(_SCHEDULED_MESSAGES_TITLE, script, category_id)
|
||||
logger.info(
|
||||
"Cronicle: created '%s' (id=%s)", _SCHEDULED_MESSAGES_TITLE, event_id
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user