diff --git a/packages/server/registry.js b/packages/server/registry.js index 39a4182..9398bf5 100644 --- a/packages/server/registry.js +++ b/packages/server/registry.js @@ -690,7 +690,7 @@ export function createRegistry(server) { { workflow: opts.key, consecutiveFailures, - triggerWorkflow: failureConfig.workflowName, + onFailureWorkflow: failureConfig.workflowName, destination: destKey, }, "triggering failure alert workflow", diff --git a/packages/server/src/api/workflows.js b/packages/server/src/api/workflows.js index f017f58..b9adaef 100644 --- a/packages/server/src/api/workflows.js +++ b/packages/server/src/api/workflows.js @@ -28,7 +28,7 @@ function triggerSummary(owner, workflow) { path: isHttp && t?.path != null ? namespacedPath(owner, t.path) : t?.path ?? null, schedule: t?.schedule ?? null, onConsecutiveFailures: t?.onConsecutiveFailures ?? null, - triggerWorkflow: t?.triggerWorkflow ?? null, + onFailureWorkflow: t?.onFailureWorkflow ?? null, auth: isHttp ? authLabel(t?.auth) : null, }; }); diff --git a/packages/server/trigger-failure.js b/packages/server/trigger-failure.js index fa1dfbf..60d01e8 100644 --- a/packages/server/trigger-failure.js +++ b/packages/server/trigger-failure.js @@ -46,8 +46,7 @@ export function resolveFailureTriggerConfig(workflow, owner, runtimeTrigger) { if (!spec) continue; const threshold = Number(spec.onConsecutiveFailures); - const workflowName = - typeof spec.triggerWorkflow === "string" ? spec.triggerWorkflow.trim() : ""; + const workflowName = onFailureWorkflowName(spec); if (!Number.isFinite(threshold) || threshold < 1 || workflowName.length === 0) { return null; } @@ -59,6 +58,14 @@ export function resolveFailureTriggerConfig(workflow, owner, runtimeTrigger) { return null; } +/** + * @param {Record} trigger + */ +function onFailureWorkflowName(trigger) { + const value = trigger?.onFailureWorkflow; + return typeof value === "string" ? value.trim() : ""; +} + /** * @param {unknown} workflow */ @@ -73,14 +80,13 @@ export async function validateWorkflowFailureTriggers(workflow) { const hasThreshold = trigger.onConsecutiveFailures != null && trigger.onConsecutiveFailures !== ""; - const hasWorkflow = - typeof trigger.triggerWorkflow === "string" && trigger.triggerWorkflow.trim().length > 0; + const hasWorkflow = onFailureWorkflowName(trigger).length > 0; if (!hasThreshold && !hasWorkflow) continue; if (!hasThreshold || !hasWorkflow) { const err = new Error( - "onConsecutiveFailures and triggerWorkflow must both be set on a trigger", + "onConsecutiveFailures and onFailureWorkflow must both be set on a trigger", ); err.statusCode = 400; throw err; diff --git a/packages/server/workflows/default/detect-example-changes.yaml b/packages/server/workflows/default/detect-example-changes.yaml index dfaee2b..be96813 100644 --- a/packages/server/workflows/default/detect-example-changes.yaml +++ b/packages/server/workflows/default/detect-example-changes.yaml @@ -8,7 +8,7 @@ scripts: config: url: https://example.com/ outputVar: message - transform: > + transform: | data.hasChanges ? "example.com changed (fingerprint " & data.fingerprint & ")" : "example.com unchanged since " & data.fingerprintAt @@ -16,3 +16,7 @@ triggers: - type: HTTP method: POST path: /detect-example + - type: cron + schedule: "* * * * *" + onConsecutiveFailures: 3 + onFailureWorkflow: dev-zte-sms diff --git a/packages/server/workflows/default/jadwal-sholat-jakart.yaml b/packages/server/workflows/default/jadwal-sholat-jakart.yaml new file mode 100644 index 0000000..bbc1da7 --- /dev/null +++ b/packages/server/workflows/default/jadwal-sholat-jakart.yaml @@ -0,0 +1,50 @@ +name: Jadwal Solat Jakarta ntfy +scripts: + - id: fetch + script: fetch-http.js + config: + url: https://kemenag.go.id/api/prayer-times/1301 + method: GET + headers: + Content-Type: application/json + Accept: application/json + - id: transform + script: jsonata.js + config: + expression: |- + { + "title": data.httpResponse.data.date, + "message": "Imsak:" & data.httpResponse.data.imsak & "\n" & + "Subuh:" & data.httpResponse.data.subuh & "\n" & + "Dzuhur:" & data.httpResponse.data.dzuhur & "\n" & + "Ashar:" & data.httpResponse.data.ashar & "\n" & + "Maghrib:" & data.httpResponse.data.maghrib & "\n" & + "Isya:" & data.httpResponse.data.isya + } + needs: + - fetch + - id: ntfy + script: ntfy.js + config: + url: $VAR_ntfy_channel + fingerprint: true + needs: + - transform + - id: slack + script: ntfy.js + config: + url: $VAR_ntfy_channel2 + fingerprint: fingerprint:ntfy2 + needs: + - transform + - script: slack-webhook.js + config: + webhookUrlSecret: slack_deploy_webhook + fingerprint: true + fingerprintMaxAge: 1h + text: $INPUT_message + needs: + - transform +triggers: + - type: cron + schedule: 0 5 * * * diff --git a/packages/server/workflows/default/registers.yaml b/packages/server/workflows/default/registers.yaml index 7273056..f7a0693 100644 --- a/packages/server/workflows/default/registers.yaml +++ b/packages/server/workflows/default/registers.yaml @@ -10,3 +10,9 @@ scripts: - test-send-gmail.yaml - track.yaml - rss-devto-to-ntfy.yaml + - dev-joplin-sync.yaml + - dev-joplin-daily.yaml + - dev-joplin-get-note.yaml + - web-dave.yaml + - jadwal-sholat-jakart.yaml + - detect-example-changes.yaml diff --git a/packages/server/workflows/default/web-dave.yaml b/packages/server/workflows/default/web-dave.yaml new file mode 100644 index 0000000..73d560d --- /dev/null +++ b/packages/server/workflows/default/web-dave.yaml @@ -0,0 +1,14 @@ +name: Dab 0dev +scripts: + - script: list-webdav.js + config: + url: https://dav.0dev.web.id/books + path: / + includeDirectories: true + recursive: false + username: nsrb + passwordSecret: dav_0dev_password +triggers: + - type: HTTP + method: POST + path: /new diff --git a/packages/web/src/components/workflow/TriggerCard.jsx b/packages/web/src/components/workflow/TriggerCard.jsx index 27e604f..4e735d2 100644 --- a/packages/web/src/components/workflow/TriggerCard.jsx +++ b/packages/web/src/components/workflow/TriggerCard.jsx @@ -117,15 +117,15 @@ export function TriggerCard({ function triggerSummary(trigger, owner) { const type = trigger?.type; + const failure = + trigger.onConsecutiveFailures && trigger.onFailureWorkflow + ? ` · onFailure@${trigger.onFailureWorkflow}` + : ""; if (type === "HTTP") { - return `${trigger.method || "POST"} ${namespacedPath(owner || "owner", trigger.path || "/")}`; + return `${trigger.method || "POST"} ${namespacedPath(owner || "owner", trigger.path || "/")}${failure}`; } if (type === "cron") { - const extra = - trigger.onConsecutiveFailures && trigger.triggerWorkflow - ? ` · alert@${trigger.triggerWorkflow}` - : ""; - return `${trigger.schedule || ""}${extra}`; + return `${trigger.schedule || ""}${failure}`; } if (type === "workflow") return "callable"; return ""; @@ -320,12 +320,12 @@ function FailureAlertFields({ trigger, disabled, onChange, alertDestinations }) /> diff --git a/packages/web/src/lib/workflow-doc.js b/packages/web/src/lib/workflow-doc.js index 86e9dd8..647b48b 100644 --- a/packages/web/src/lib/workflow-doc.js +++ b/packages/web/src/lib/workflow-doc.js @@ -143,7 +143,7 @@ export function newHttpTrigger() { response: "", unauthorized: null, onConsecutiveFailures: "", - triggerWorkflow: "", + onFailureWorkflow: "", }; } @@ -158,7 +158,7 @@ export function newCronTrigger() { response: "", unauthorized: null, onConsecutiveFailures: "", - triggerWorkflow: "", + onFailureWorkflow: "", }; } @@ -173,7 +173,7 @@ export function newWorkflowTrigger() { response: "", unauthorized: null, onConsecutiveFailures: "", - triggerWorkflow: "", + onFailureWorkflow: "", }; } @@ -191,6 +191,10 @@ export function triggerDestinations(workflows, { owner, excludeFile } = {}) { export { HTTP_METHODS }; +function readOnFailureWorkflow(raw) { + return typeof raw?.onFailureWorkflow === "string" ? raw.onFailureWorkflow : ""; +} + function normalizeStep(step) { const uiId = nextUiId("step"); if (typeof step === "string") { @@ -266,10 +270,10 @@ function normalizeTrigger(raw) { "response", "unauthorized", "onConsecutiveFailures", - "triggerWorkflow", + "onFailureWorkflow", ]) : type === "cron" - ? new Set(["type", "schedule", "onConsecutiveFailures", "triggerWorkflow"]) + ? new Set(["type", "schedule", "onConsecutiveFailures", "onFailureWorkflow"]) : new Set(["type"]); /** @type {Record} */ const extra = {}; @@ -286,8 +290,7 @@ function normalizeTrigger(raw) { raw.onConsecutiveFailures == null || raw.onConsecutiveFailures === "" ? "" : String(raw.onConsecutiveFailures), - triggerWorkflow: - typeof raw.triggerWorkflow === "string" ? raw.triggerWorkflow : "", + onFailureWorkflow: readOnFailureWorkflow(raw), auth: raw.auth ?? null, response: typeof raw.response === "string" ? raw.response : "", unauthorized: raw.unauthorized ?? null, @@ -328,8 +331,8 @@ function dumpFailureTriggerFields(t, out) { out.onConsecutiveFailures = Math.floor(threshold); } } - if (typeof t.triggerWorkflow === "string" && t.triggerWorkflow.trim()) { - out.triggerWorkflow = t.triggerWorkflow.trim(); + if (typeof t.onFailureWorkflow === "string" && t.onFailureWorkflow.trim()) { + out.onFailureWorkflow = t.onFailureWorkflow.trim(); } }