@cloud-cli/on 1.9.0 โ 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/on.js +243 -184
- package/dist/plugins/github-status.plugin.d.ts +13 -3
- package/dist/plugins/github-status.plugin.d.ts.map +1 -1
- package/dist/plugins/manager.d.ts +3 -2
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/run-view.d.ts +16 -0
- package/dist/run-view.d.ts.map +1 -0
- package/dist/server.d.ts +0 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/types.d.ts +6 -27
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/reporters/html.reporter.d.ts +0 -11
- package/dist/reporters/html.reporter.d.ts.map +0 -1
- package/dist/reporters/json-file.reporter.d.ts +0 -10
- package/dist/reporters/json-file.reporter.d.ts.map +0 -1
- package/dist/reporters/slack.reporter.d.ts +0 -16
- package/dist/reporters/slack.reporter.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -179,7 +179,7 @@ You can customize engine behavior using `runner.config.mjs` in your project root
|
|
|
179
179
|
|
|
180
180
|
```javascript
|
|
181
181
|
// runner.config.mjs
|
|
182
|
-
import {
|
|
182
|
+
import { GitHubStatusPlugin } from '@cloud-cli/on';
|
|
183
183
|
|
|
184
184
|
export default {
|
|
185
185
|
port: 3000,
|
|
@@ -195,18 +195,19 @@ export default {
|
|
|
195
195
|
NODE_ENV: 'production',
|
|
196
196
|
},
|
|
197
197
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
new SlackReporter({
|
|
203
|
-
webhookUrl: process.env.SLACK_WEBHOOK_URL,
|
|
204
|
-
channel: '#ci-deployments',
|
|
198
|
+
plugins: [
|
|
199
|
+
new GitHubStatusPlugin({
|
|
200
|
+
token: process.env.SECRET_GITHUB_TOKEN,
|
|
201
|
+
context: 'on',
|
|
205
202
|
}),
|
|
206
203
|
],
|
|
207
204
|
};
|
|
208
205
|
```
|
|
209
206
|
|
|
207
|
+
The GitHub status plugin publishes commit states when a workflow starts and finishes. Its token needs permission to write commit statuses for the target repository.
|
|
208
|
+
|
|
209
|
+
Run details are available as HTML at `/runs/:id` and as sanitized JSON at `/api/runs/:id`. The HTML view refreshes reactively through job-specific SSE events while a run is active. Both representations omit raw webhook bodies, sensitive input fields, execution environment values, and internal rerun state.
|
|
210
|
+
|
|
210
211
|
---
|
|
211
212
|
|
|
212
213
|
## ๐ Deterministic Evaluation Rules
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {
|
|
3
|
-
export { JsonFileReporter } from './reporters/json-file.reporter.js';
|
|
4
|
-
export { SlackReporter } from './reporters/slack.reporter.js';
|
|
2
|
+
export { GitHubStatusPlugin } from './plugins/github-status.plugin.js';
|
|
5
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAYA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAYA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC"}
|
package/dist/on.js
CHANGED
|
@@ -74,7 +74,7 @@ function ue(e, t) {
|
|
|
74
74
|
tags: i.map((e) => e.trim()).filter(Boolean),
|
|
75
75
|
storagePath: e.storagePath ?? n.RUNNER_TMP ?? "/tmp/workspaces",
|
|
76
76
|
env: e.env ?? {},
|
|
77
|
-
|
|
77
|
+
plugins: e.plugins ?? []
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
function de() {
|
|
@@ -7954,7 +7954,7 @@ var Mo = class {
|
|
|
7954
7954
|
owner: c,
|
|
7955
7955
|
repo: l,
|
|
7956
7956
|
clone_url: n.repository?.clone_url,
|
|
7957
|
-
commit_sha: n.after || n.head_commit?.id,
|
|
7957
|
+
commit_sha: n.after || n.head_commit?.id || n.pull_request?.head?.sha,
|
|
7958
7958
|
author: n.pusher?.name || n.sender?.login,
|
|
7959
7959
|
action: n.action,
|
|
7960
7960
|
raw: n,
|
|
@@ -7982,29 +7982,7 @@ var Mo = class {
|
|
|
7982
7982
|
inputs: e
|
|
7983
7983
|
};
|
|
7984
7984
|
}
|
|
7985
|
-
}
|
|
7986
|
-
//#endregion
|
|
7987
|
-
//#region src/html-state.ts
|
|
7988
|
-
function No(e) {
|
|
7989
|
-
return JSON.stringify(e).replace(/[<>&\u2028\u2029]/g, (e) => `\\u${e.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
7990
|
-
}
|
|
7991
|
-
//#endregion
|
|
7992
|
-
//#region src/reporters/html.reporter.html?raw
|
|
7993
|
-
var Po = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Run</title>\n <script type=\"importmap\">\n {\n \"imports\": {\n \"@li3/\": \"https://cdn.li3.dev/@li3/\",\n \"ansi_up\": \"https://esm.sh/ansi_up@6.0.6\"\n }\n }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <div class=\"max-w-5xl mx-auto space-y-4\">\n <header class=\"flex flex-col md:flex-row md:items-center justify-between border-b border-gray-800 pb-6 gap-4\">\n <div class=\"min-w-0\">\n <a href=\"/runs\" class=\"text-xs text-indigo-400 hover:underline mb-1 inline-block\">Back to Dashboard</a>\n <h1 class=\"text-2xl font-bold text-white flex flex-wrap items-center gap-3\">\n {{ report.workflowName }}\n <span class=\"text-sm font-mono text-gray-500\">#{{ report.jobId }}</span>\n <template if=\"report.parentId\">\n <a attr-href=\"'/runs/' + report.parentId\" class=\"text-sm font-mono text-indigo-400 hover:underline\">\n from #{{ report.parentId }}\n </a>\n </template>\n </h1>\n <p class=\"text-xs text-gray-400 mt-1\">Started {{ report.startedAt }} ยท {{ timing }}</p>\n </div>\n <div class=\"flex items-center gap-2 shrink-0\">\n <span\n class=\"px-4 py-1.5 rounded-full text-sm font-semibold border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': report.status === 'success',\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': report.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.border-indigo-500/20': report.status === 'running',\n 'bg-amber-500/10.text-amber-400.border-amber-500/20': !['success', 'failed', 'running'].includes(report.status)\n }\"\n >\n {{ upper(report.status) }}\n </span>\n <button\n class=\"text-sm text-white px-4 py-1.5 border border-gray-600 hover:border-gray-400 rounded-full\"\n on-click=\"restartJob()\"\n >\n Restart\n </button>\n </div>\n </header>\n\n <section class=\"rounded overflow-hidden border-b border-gray-800\">\n <h2 class=\"sr-only\">Execution Steps</h2>\n <template for=\"[step, index] of report.steps\">\n <details class=\"border border-b-0 border-gray-800 bg-gray-900/50 text-sm\">\n <summary class=\"flex flex-col md:flex-row md:items-center justify-between gap-2 p-3 bg-gray-800/40 border-b border-gray-800 cursor-pointer\">\n <div class=\"flex flex-wrap items-center gap-3 min-w-0\">\n <span class=\"font-mono text-gray-500\">\n #{{ index + 1 }}<template if=\"step.exitCode !== undefined && step.exitCode !== 0\"> ({{ step.exitCode }})</template>\n </span>\n <h3 class=\"font-semibold text-gray-200 break-words\">{{ step.name }}</h3>\n <span\n class=\"px-2.5 py-0.5 rounded-full font-medium\"\n bind-class=\"{\n 'text-emerald-400.bg-emerald-500/10': step.status === 'success',\n 'text-rose-400.bg-rose-500/10': step.status === 'failed',\n 'text-indigo-400.bg-indigo-500/10': step.status === 'running',\n 'text-gray-400.bg-gray-500/10': !['success', 'failed', 'running'].includes(step.status)\n }\"\n >\n {{ upper(step.status) }}\n </span>\n </div>\n <div class=\"font-mono text-gray-400 shrink-0\">{{ step.durationMs }}ms</div>\n </summary>\n <div class=\"p-4 bg-gray-950 font-mono text-gray-300 leading-relaxed overflow-auto w-full\">\n <pre class=\"whitespace-pre-wrap\" bind-innerhtml=\"stepLog(step)\"></pre>\n </div>\n </details>\n </template>\n </section>\n\n <details class=\"bg-gray-900 border border-gray-800 rounded-xl p-4 overflow-auto max-h-[400px]\">\n <summary class=\"cursor-pointer\">\n <h2 class=\"inline text-xs font-semibold text-gray-400 uppercase tracking-wider\">Trigger Inputs</h2>\n </summary>\n <pre class=\"font-mono text-xs text-gray-200 bg-gray-950 p-3 mt-3 rounded-lg overflow-x-auto\">{{ inputsJson }}</pre>\n </details>\n </div>\n\n <script setup>\n import { computed, onInit, ref } from '@li3/web';\n import { AnsiUp } from 'ansi_up';\n\n export default function setup() {\n const report = ref({});\n const ansiUp = new AnsiUp();\n ansiUp.use_classes = false;\n\n const active = computed(() => ['pending', 'running'].includes(report.value.status));\n const inputsJson = computed(() => JSON.stringify(report.value.inputs || {}, null, 2));\n const timing = computed(() => {\n if (report.value.status === 'pending') return 'Waiting for a worker';\n if (report.value.status === 'running') return `Running for ${report.value.durationMs}ms`;\n return `Finished in ${report.value.durationMs}ms`;\n });\n\n const upper = (value) => String(value || '').toUpperCase();\n const stepLog = (step) => {\n if (step.status === 'skipped') return '';\n if (step.status === 'running') return '<span class=\"text-indigo-400\">Step is running. Logs will appear after it finishes.</span>';\n if (step.status === 'pending') return '<span class=\"text-gray-500\">Waiting to run.</span>';\n if (step.logContent) return ansiUp.ansi_to_html(step.logContent);\n return '<span class=\"text-gray-500\">(No terminal log output recorded for this step)</span>';\n };\n const restartJob = async () => {\n const response = await fetch(`/restart/${report.value.jobId}`, { method: 'POST' });\n if (response.ok) {\n const { id } = await response.json();\n location.href = `/runs/${id}`;\n }\n };\n\n onInit(() => {\n document.title = `Run #${report.value.jobId} - ${report.value.workflowName}`;\n if (active.value) setTimeout(() => location.reload(), 3000);\n });\n\n return { report, inputsJson, timing, upper, stepLog, restartJob };\n }\n <\/script>\n <script state>__REPORT_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n", Fo = "__REPORT_STATE__", Io = class {
|
|
7994
|
-
name = "html";
|
|
7995
|
-
outputDir;
|
|
7996
|
-
constructor(e) {
|
|
7997
|
-
this.outputDir = e.outputDir;
|
|
7998
|
-
}
|
|
7999
|
-
async report(t) {
|
|
8000
|
-
e.mkdirSync(this.outputDir, { recursive: !0 });
|
|
8001
|
-
let n = this.generateHtml(t), r = a.join(this.outputDir, `run-${t.jobId}.html`);
|
|
8002
|
-
e.writeFileSync(r, n, "utf-8"), console.log(`๐ HTML Execution Report generated: ${r}`);
|
|
8003
|
-
}
|
|
8004
|
-
generateHtml(e) {
|
|
8005
|
-
return Po.replace(Fo, () => No({ report: e }));
|
|
8006
|
-
}
|
|
8007
|
-
}, Lo = class e {
|
|
7985
|
+
}, No = class e {
|
|
8008
7986
|
static async from(t) {
|
|
8009
7987
|
let n = o(t) ? c("/", t) : s(process.cwd(), c("/", t)), r = (await _(n, { withFileTypes: !0 })).filter((e) => e.isFile() && (e.name.endsWith(".yml") || e.name.endsWith(".yaml"))).map((e) => s(n, e.name)), i = [], a = new di(t);
|
|
8010
7988
|
for (let t of r) i.push(...await e.loadFile(t, a));
|
|
@@ -8038,10 +8016,15 @@ var Po = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta ch
|
|
|
8038
8016
|
}
|
|
8039
8017
|
return n;
|
|
8040
8018
|
}
|
|
8041
|
-
},
|
|
8019
|
+
}, Po = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Engine Dashboard</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <main class=\"max-w-6xl mx-auto space-y-6\">\n <header class=\"flex flex-col sm:flex-row sm:items-center justify-between gap-3 border-b border-gray-800 pb-4\">\n <div>\n <h1 class=\"text-2xl font-bold text-white\">Runner Engine Status</h1>\n <p class=\"text-xs text-gray-400\">Live Job Queue & Execution Traces</p>\n </div>\n <div class=\"flex items-center gap-3 text-xs font-mono\">\n <span class=\"text-gray-500\">Updated {{ lastUpdated }}</span>\n <span\n class=\"px-3 py-1 rounded-full border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': !refreshError,\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': refreshError\n }\"\n >\n {{ refreshError ? 'Refresh failed' : 'System operational' }}\n </span>\n </div>\n </header>\n\n <section class=\"bg-gray-900 border border-gray-800 rounded-xl overflow-hidden hidden md:block\">\n <table class=\"w-full text-left text-sm\">\n <thead class=\"bg-gray-800/50 text-gray-400 text-xs uppercase font-mono border-b border-gray-800\">\n <tr>\n <th class=\"py-3 px-4\">Job ID</th>\n <th class=\"py-3 px-4\">Workflow</th>\n <th class=\"py-3 px-4\">Status</th>\n <th class=\"py-3 px-4 hidden xl:table-cell\">Worker</th>\n <th class=\"py-3 px-4 hidden lg:table-cell\">Created At</th>\n <th class=\"py-3 px-4 text-right\">Action</th>\n </tr>\n </thead>\n <tbody>\n <template for=\"job of jobs\">\n <tr class=\"border-b border-gray-800 hover:bg-gray-800/40 transition\">\n <td class=\"py-3 px-4 font-mono text-indigo-400\">\n <a attr-href=\"'/runs/' + job.id\" class=\"hover:underline\">#{{ job.id }}</a>\n </td>\n <td class=\"py-3 px-4 font-medium text-white\">{{ job.workflowId }}</td>\n <td class=\"py-3 px-4\">\n <span\n class=\"px-2.5 py-0.5 rounded-full text-xs font-semibold\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400': job.status === 'success',\n 'bg-rose-500/10.text-rose-400': job.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.animate-pulse': job.status === 'running',\n 'bg-gray-500/10.text-gray-400': !['success', 'failed', 'running'].includes(job.status)\n }\"\n >\n {{ upper(job.status) }}\n </span>\n </td>\n <td class=\"py-3 px-4 hidden xl:table-cell text-xs font-mono text-gray-400\">{{ job.workerId || '-' }}</td>\n <td class=\"py-3 px-4 hidden lg:table-cell text-xs text-gray-400\">{{ job.createdAt }}</td>\n <td class=\"py-3 px-4 text-right whitespace-nowrap\">\n <a attr-href=\"'/runs/' + job.id\" class=\"text-xs bg-gray-800 hover:bg-gray-700 text-gray-200 px-3 py-1 rounded border border-gray-700\">View Trace</a>\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n <template if=\"!jobs.length\">\n <div class=\"p-8 text-center text-gray-500\">No jobs recorded yet.</div>\n </template>\n </section>\n\n <section class=\"md:hidden bg-gray-900 border border-gray-800 rounded-xl divide-y divide-gray-800 overflow-hidden\">\n <template for=\"job of jobs\">\n <article class=\"p-4 bg-gray-900/60\">\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <div class=\"flex items-center gap-2\">\n <span\n class=\"w-2.5 h-2.5 rounded-full shrink-0\"\n bind-class=\"{\n 'bg-emerald-400': job.status === 'success',\n 'bg-rose-400': job.status === 'failed',\n 'bg-indigo-400.animate-pulse': job.status === 'running',\n 'bg-gray-500': !['success', 'failed', 'running'].includes(job.status)\n }\"\n ></span>\n <h2 class=\"font-medium text-white truncate\">{{ job.workflowId }}</h2>\n </div>\n <p class=\"mt-1 pl-[18px] text-xs font-mono text-gray-400\">#{{ job.id }} ยท {{ upper(job.status) }}</p>\n </div>\n <a attr-href=\"'/runs/' + job.id\" class=\"shrink-0 text-xs bg-gray-800 hover:bg-gray-700 text-gray-300 px-2.5 py-1 rounded border border-gray-700\">Trace</a>\n </div>\n </article>\n </template>\n <template if=\"!jobs.length\">\n <div class=\"p-8 text-center text-gray-500\">No jobs recorded yet.</div>\n </template>\n </section>\n\n <template if=\"hasMore\">\n <div class=\"flex justify-center\">\n <button\n class=\"px-4 py-2 text-sm text-gray-200 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded-lg\"\n on-click=\"loadMore()\"\n >\n {{ loadingMore ? 'Loading...' : 'Load more' }}\n </button>\n </div>\n </template>\n </main>\n\n <script setup>\n import { onDestroy, onInit, ref } from '@li3/web';\n\n export default function setup() {\n const jobs = ref([]);\n const lastUpdated = ref('now');\n const refreshError = ref(false);\n const hasMore = ref(false);\n const loadingMore = ref(false);\n let refreshTimer;\n let eventSource;\n let refreshing = false;\n let refreshPending = false;\n\n const upper = (value) => String(value || '').toUpperCase();\n const terminalStatuses = new Set(['success', 'failed', 'cancelled']);\n const refreshJobs = async () => {\n if (refreshing) {\n refreshPending = true;\n return;\n }\n refreshing = true;\n\n try {\n const activeIds = jobs.value\n .filter((job) => !terminalStatuses.has(job.status))\n .map((job) => Number(job.id));\n const knownIds = jobs.value.map((job) => Number(job.id));\n const afterId = activeIds.length\n ? Math.max(0, Math.min(...activeIds) - 1)\n : knownIds.length\n ? Math.max(...knownIds)\n : null;\n const url = afterId === null ? '/api/jobs?limit=500' : `/api/jobs?afterId=${afterId}&limit=500`;\n const response = await fetch(url, { headers: { accept: 'application/json' } });\n if (!response.ok) throw new Error(`Dashboard refresh failed: ${response.status}`);\n\n const data = await response.json();\n const merged = new Map(jobs.value.map((job) => [job.id, job]));\n for (const job of data.jobs) merged.set(job.id, job);\n jobs.value = Array.from(merged.values()).sort((a, b) => Number(b.id) - Number(a.id));\n lastUpdated.value = new Date().toLocaleTimeString();\n refreshError.value = false;\n } catch (error) {\n console.error(error);\n refreshError.value = true;\n } finally {\n refreshing = false;\n if (refreshPending) {\n refreshPending = false;\n void refreshJobs();\n }\n }\n };\n\n const loadMore = async () => {\n if (loadingMore.value || !hasMore.value || !jobs.value.length) return;\n loadingMore.value = true;\n\n try {\n const beforeId = Math.min(...jobs.value.map((job) => Number(job.id)));\n const response = await fetch(`/api/jobs?beforeId=${beforeId}`, {\n headers: { accept: 'application/json' },\n });\n if (!response.ok) throw new Error(`Loading older jobs failed: ${response.status}`);\n\n const data = await response.json();\n const merged = new Map(jobs.value.map((job) => [job.id, job]));\n for (const job of data.jobs) merged.set(job.id, job);\n jobs.value = Array.from(merged.values()).sort((a, b) => Number(b.id) - Number(a.id));\n hasMore.value = data.hasMore;\n } catch (error) {\n console.error(error);\n refreshError.value = true;\n } finally {\n loadingMore.value = false;\n }\n };\n\n onInit(() => {\n eventSource = new EventSource('/api/events');\n eventSource.addEventListener('jobs.available', refreshJobs);\n eventSource.addEventListener('jobs.changed', refreshJobs);\n eventSource.onerror = () => {\n refreshError.value = true;\n };\n refreshTimer = setInterval(refreshJobs, 60000);\n });\n onDestroy(() => {\n eventSource?.close();\n clearInterval(refreshTimer);\n });\n\n return { jobs, lastUpdated, refreshError, hasMore, loadingMore, loadMore, upper };\n }\n <\/script>\n <script state>__DASHBOARD_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n";
|
|
8020
|
+
//#endregion
|
|
8021
|
+
//#region src/html-state.ts
|
|
8022
|
+
function Fo(e) {
|
|
8023
|
+
return JSON.stringify(e).replace(/[<>&\u2028\u2029]/g, (e) => `\\u${e.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
8024
|
+
}
|
|
8042
8025
|
//#endregion
|
|
8043
8026
|
//#region src/dashboard.ts
|
|
8044
|
-
function
|
|
8027
|
+
function Io(e) {
|
|
8045
8028
|
return e.map((e) => ({
|
|
8046
8029
|
id: e.id,
|
|
8047
8030
|
workflowId: e.workflow_id,
|
|
@@ -8051,15 +8034,15 @@ function zo(e) {
|
|
|
8051
8034
|
updatedAt: e.updated_at
|
|
8052
8035
|
}));
|
|
8053
8036
|
}
|
|
8054
|
-
function
|
|
8055
|
-
return
|
|
8037
|
+
function Lo(e, t = !1) {
|
|
8038
|
+
return Po.replace("__DASHBOARD_STATE__", () => Fo({
|
|
8056
8039
|
jobs: e,
|
|
8057
8040
|
hasMore: t
|
|
8058
8041
|
}));
|
|
8059
8042
|
}
|
|
8060
8043
|
//#endregion
|
|
8061
8044
|
//#region src/events.ts
|
|
8062
|
-
var
|
|
8045
|
+
var Ro = class {
|
|
8063
8046
|
clients = /* @__PURE__ */ new Map();
|
|
8064
8047
|
nextId = 1;
|
|
8065
8048
|
maxClients = 1e3;
|
|
@@ -8091,7 +8074,7 @@ var Vo = class {
|
|
|
8091
8074
|
this.clients.clear();
|
|
8092
8075
|
}
|
|
8093
8076
|
};
|
|
8094
|
-
async function
|
|
8077
|
+
async function zo(e, t, n, r) {
|
|
8095
8078
|
let i = await fetch(new URL("/api/events", e), {
|
|
8096
8079
|
headers: { Accept: "text/event-stream" },
|
|
8097
8080
|
signal: t
|
|
@@ -8113,22 +8096,83 @@ async function Ho(e, t, n, r) {
|
|
|
8113
8096
|
}
|
|
8114
8097
|
}
|
|
8115
8098
|
//#endregion
|
|
8099
|
+
//#region src/run.html?raw
|
|
8100
|
+
var Bo = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Run</title>\n <script type=\"importmap\">\n {\n \"imports\": {\n \"@li3/\": \"https://cdn.li3.dev/@li3/\",\n \"ansi_up\": \"https://esm.sh/ansi_up@6.0.6\"\n }\n }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <div class=\"max-w-5xl mx-auto space-y-4\">\n <header class=\"flex flex-col md:flex-row md:items-center justify-between border-b border-gray-800 pb-6 gap-4\">\n <div class=\"min-w-0\">\n <a href=\"/runs\" class=\"text-xs text-indigo-400 hover:underline mb-1 inline-block\">Back to Dashboard</a>\n <h1 class=\"text-2xl font-bold text-white flex flex-wrap items-center gap-3\">\n {{ report.workflowName }}\n <span class=\"text-sm font-mono text-gray-500\">#{{ report.jobId }}</span>\n <template if=\"report.parentId\">\n <a attr-href=\"'/runs/' + report.parentId\" class=\"text-sm font-mono text-indigo-400 hover:underline\">\n from #{{ report.parentId }}\n </a>\n </template>\n </h1>\n <p class=\"text-xs text-gray-400 mt-1\">Started {{ report.startedAt }} ยท {{ timing }}</p>\n </div>\n <div class=\"flex items-center gap-2 shrink-0\">\n <span\n class=\"px-4 py-1.5 rounded-full text-sm font-semibold border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': report.status === 'success',\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': report.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.border-indigo-500/20': report.status === 'running',\n 'bg-amber-500/10.text-amber-400.border-amber-500/20': !['success', 'failed', 'running'].includes(report.status)\n }\"\n >\n {{ upper(report.status) }}\n </span>\n <button\n class=\"text-sm text-white px-4 py-1.5 border border-gray-600 hover:border-gray-400 rounded-full\"\n on-click=\"restartJob()\"\n >\n Restart\n </button>\n </div>\n </header>\n\n <section class=\"rounded overflow-hidden border-b border-gray-800\">\n <h2 class=\"sr-only\">Execution Steps</h2>\n <template for=\"[step, index] of report.steps\">\n <details class=\"border border-b-0 border-gray-800 bg-gray-900/50 text-sm\">\n <summary class=\"flex flex-col md:flex-row md:items-center justify-between gap-2 p-3 bg-gray-800/40 border-b border-gray-800 cursor-pointer\">\n <div class=\"flex flex-wrap items-center gap-3 min-w-0\">\n <span class=\"font-mono text-gray-500\">\n #{{ index + 1 }}<template if=\"step.exitCode !== undefined && step.exitCode !== 0\"> ({{ step.exitCode }})</template>\n </span>\n <h3 class=\"font-semibold text-gray-200 break-words\">{{ step.name }}</h3>\n <span\n class=\"px-2.5 py-0.5 rounded-full font-medium\"\n bind-class=\"{\n 'text-emerald-400.bg-emerald-500/10': step.status === 'success',\n 'text-rose-400.bg-rose-500/10': step.status === 'failed',\n 'text-indigo-400.bg-indigo-500/10': step.status === 'running',\n 'text-gray-400.bg-gray-500/10': !['success', 'failed', 'running'].includes(step.status)\n }\"\n >\n {{ upper(step.status) }}\n </span>\n </div>\n <div class=\"font-mono text-gray-400 shrink-0\">{{ step.durationMs }}ms</div>\n </summary>\n <div class=\"p-4 bg-gray-950 font-mono text-gray-300 leading-relaxed overflow-auto w-full\">\n <pre class=\"whitespace-pre-wrap\" bind-innerhtml=\"stepLog(step)\"></pre>\n </div>\n </details>\n </template>\n </section>\n\n <details class=\"bg-gray-900 border border-gray-800 rounded-xl p-4 overflow-auto max-h-[400px]\">\n <summary class=\"cursor-pointer\">\n <h2 class=\"inline text-xs font-semibold text-gray-400 uppercase tracking-wider\">Trigger Inputs</h2>\n </summary>\n <pre class=\"font-mono text-xs text-gray-200 bg-gray-950 p-3 mt-3 rounded-lg overflow-x-auto\">{{ inputsJson }}</pre>\n </details>\n </div>\n\n <script setup>\n import { computed, onDestroy, onInit, ref } from '@li3/web';\n import { AnsiUp } from 'ansi_up';\n\n export default function setup() {\n const report = ref({});\n const now = ref(Date.now());\n const ansiUp = new AnsiUp();\n ansiUp.use_classes = false;\n let eventSource;\n let refreshTimer;\n let clockTimer;\n let refreshing = false;\n let refreshPending = false;\n\n const active = computed(() => ['pending', 'running'].includes(report.value.status));\n const inputsJson = computed(() => JSON.stringify(report.value.inputs || {}, null, 2));\n const timing = computed(() => {\n if (report.value.status === 'pending') return 'Waiting for a worker';\n if (report.value.status === 'running') {\n return `Running for ${Math.max(0, now.value - Date.parse(report.value.startedAt))}ms`;\n }\n return `Finished in ${report.value.durationMs}ms`;\n });\n\n const upper = (value) => String(value || '').toUpperCase();\n const stepLog = (step) => {\n if (step.status === 'skipped') return '';\n if (step.status === 'running') return '<span class=\"text-indigo-400\">Step is running. Logs will appear after it finishes.</span>';\n if (step.status === 'pending') return '<span class=\"text-gray-500\">Waiting to run.</span>';\n if (step.logContent) return ansiUp.ansi_to_html(step.logContent);\n return '<span class=\"text-gray-500\">(No terminal log output recorded for this step)</span>';\n };\n const restartJob = async () => {\n const response = await fetch(`/restart/${report.value.jobId}`, { method: 'POST' });\n if (response.ok) {\n const { id } = await response.json();\n location.href = `/runs/${id}`;\n }\n };\n const refreshRun = async () => {\n if (refreshing) {\n refreshPending = true;\n return;\n }\n refreshing = true;\n\n try {\n const response = await fetch(`/api/runs/${report.value.jobId}`, {\n headers: { accept: 'application/json' },\n });\n if (!response.ok) throw new Error(`Run refresh failed: ${response.status}`);\n report.value = await response.json();\n } catch (error) {\n console.error(error);\n } finally {\n refreshing = false;\n if (refreshPending) {\n refreshPending = false;\n void refreshRun();\n }\n }\n };\n const handleJobChange = (event) => {\n const data = JSON.parse(event.data || '{}');\n if (!data.jobId || String(data.jobId) === String(report.value.jobId)) void refreshRun();\n };\n\n onInit(() => {\n document.title = `Run #${report.value.jobId} - ${report.value.workflowName}`;\n eventSource = new EventSource('/api/events');\n eventSource.addEventListener('jobs.changed', handleJobChange);\n refreshTimer = setInterval(() => {\n if (active.value) void refreshRun();\n }, 60000);\n clockTimer = setInterval(() => {\n now.value = Date.now();\n }, 1000);\n });\n onDestroy(() => {\n eventSource?.close();\n clearInterval(refreshTimer);\n clearInterval(clockTimer);\n });\n\n return { report, inputsJson, timing, upper, stepLog, restartJob };\n }\n <\/script>\n <script state>__REPORT_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n", Vo = /(?:^|[_-])auth(?:entication)?(?:$|[_-])|access[_-]?key|api[_-]?key|authorization|cookie|credential|passphrase|password|private[_-]?key|secret|session(?:id)?|signing[_-]?key|token/i;
|
|
8101
|
+
function Ho(e, t, n) {
|
|
8102
|
+
let r = JSON.parse(e.payload), i = e.report ? JSON.parse(e.report) : Wo(e, r), a = e.status;
|
|
8103
|
+
return {
|
|
8104
|
+
jobId: String(e.id),
|
|
8105
|
+
parentId: String(i.parentId || e.parentId || ""),
|
|
8106
|
+
workflowName: n(i.workflowName),
|
|
8107
|
+
status: a,
|
|
8108
|
+
durationMs: a === "running" ? Math.max(0, Date.now() - Date.parse(i.startedAt)) : i.durationMs,
|
|
8109
|
+
startedAt: i.startedAt,
|
|
8110
|
+
finishedAt: i.finishedAt,
|
|
8111
|
+
inputs: Go(i.inputs || {}, n),
|
|
8112
|
+
steps: (i.steps || []).map((e) => {
|
|
8113
|
+
let r = Object.hasOwn(t, e.id) && typeof t[e.id] == "string" ? t[e.id] : "";
|
|
8114
|
+
return {
|
|
8115
|
+
id: e.id,
|
|
8116
|
+
name: n(e.name),
|
|
8117
|
+
status: e.status,
|
|
8118
|
+
durationMs: e.durationMs,
|
|
8119
|
+
exitCode: e.exitCode,
|
|
8120
|
+
startedAt: e.startedAt,
|
|
8121
|
+
finishedAt: e.finishedAt,
|
|
8122
|
+
error: e.error ? n(e.error) : void 0,
|
|
8123
|
+
outputs: Go(e.outputs || {}, n),
|
|
8124
|
+
logContent: e.status === "running" || e.status === "pending" ? "" : n(r || e.logContent || "")
|
|
8125
|
+
};
|
|
8126
|
+
}),
|
|
8127
|
+
artifacts: (i.artifacts || []).map(n)
|
|
8128
|
+
};
|
|
8129
|
+
}
|
|
8130
|
+
function Uo(e) {
|
|
8131
|
+
return Bo.replace("__REPORT_STATE__", () => Fo({ report: e }));
|
|
8132
|
+
}
|
|
8133
|
+
function Wo(e, t) {
|
|
8134
|
+
let n = e.started_at || e.created_at;
|
|
8135
|
+
return {
|
|
8136
|
+
jobId: String(e.id),
|
|
8137
|
+
parentId: String(e.parentId || ""),
|
|
8138
|
+
workflowName: e.workflow_id,
|
|
8139
|
+
status: e.status,
|
|
8140
|
+
durationMs: e.status === "running" ? Math.max(0, Date.now() - Date.parse(n)) : 0,
|
|
8141
|
+
startedAt: n,
|
|
8142
|
+
inputs: t.inputs || {},
|
|
8143
|
+
environment: {},
|
|
8144
|
+
steps: (t.steps || []).map((e, t) => ({
|
|
8145
|
+
id: e.id || `step-${t}`,
|
|
8146
|
+
name: e.name || e.id || `step-${t}`,
|
|
8147
|
+
status: "pending",
|
|
8148
|
+
durationMs: 0,
|
|
8149
|
+
outputs: {},
|
|
8150
|
+
logContent: ""
|
|
8151
|
+
})),
|
|
8152
|
+
artifacts: [],
|
|
8153
|
+
rerunToken: ""
|
|
8154
|
+
};
|
|
8155
|
+
}
|
|
8156
|
+
function Go(e, t) {
|
|
8157
|
+
return typeof e == "string" ? t(e) : Array.isArray(e) ? e.map((e) => Go(e, t)) : !e || typeof e != "object" ? e : Object.fromEntries(Object.entries(e).filter(([e]) => e.toLowerCase() !== "raw" && !Vo.test(e)).map(([e, n]) => [e, Go(n, t)]));
|
|
8158
|
+
}
|
|
8159
|
+
//#endregion
|
|
8116
8160
|
//#region src/server.ts
|
|
8117
|
-
var
|
|
8161
|
+
var Ko = 50, qo = 500, Jo = class e {
|
|
8118
8162
|
server;
|
|
8119
8163
|
preprocessors = /* @__PURE__ */ new Map();
|
|
8120
8164
|
workflows = [];
|
|
8121
8165
|
queue;
|
|
8122
8166
|
secrets;
|
|
8123
8167
|
adminToken;
|
|
8124
|
-
events = new
|
|
8168
|
+
events = new Ro();
|
|
8125
8169
|
workflowsLoaded;
|
|
8126
8170
|
static async withPort(t) {
|
|
8127
8171
|
let { port: n, ...r } = t;
|
|
8128
8172
|
return new e(r).listen(n);
|
|
8129
8173
|
}
|
|
8130
8174
|
constructor(e) {
|
|
8131
|
-
this.queue = e.queue, this.secrets = e.secrets, this.adminToken = e.adminToken, this.workflowsLoaded =
|
|
8175
|
+
this.queue = e.queue, this.secrets = e.secrets, this.adminToken = e.adminToken, this.workflowsLoaded = No.from(e.config.workflows).then((t) => {
|
|
8132
8176
|
this.workflows = t, console.log(`โ
Loaded ${t.length} workflow(s) from ${e.config.workflows}`);
|
|
8133
8177
|
}), this.registerPreprocessor(new Mo()), this.server = f.createServer((e, t) => this.handleRequest(e, t));
|
|
8134
8178
|
}
|
|
@@ -8139,14 +8183,18 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8139
8183
|
let n = new p(e.url || "/", `${e.headers["x-forwarded-proto"] || "http"}://${e.headers["x-forwarded-host"] || e.headers.host}`);
|
|
8140
8184
|
if (e.method === "GET" && (n.pathname === "/runs" || n.pathname === "/")) return this.renderDashboard(t);
|
|
8141
8185
|
if (e.method === "GET" && n.pathname === "/api/jobs") {
|
|
8142
|
-
let e = n.searchParams.get("afterId"), r = n.searchParams.get("beforeId"), i = n.searchParams.get("limit"), a = e === null ? void 0 : Number(e), o = r === null ? void 0 : Number(r), s = i === null ?
|
|
8143
|
-
return a !== void 0 && (!Number.isSafeInteger(a) || a < 0) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "afterId must be a non-negative integer" }))) : o !== void 0 && (!Number.isSafeInteger(o) || o < 1) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "beforeId must be a positive integer" }))) : !Number.isSafeInteger(s) || s < 1 || s >
|
|
8186
|
+
let e = n.searchParams.get("afterId"), r = n.searchParams.get("beforeId"), i = n.searchParams.get("limit"), a = e === null ? void 0 : Number(e), o = r === null ? void 0 : Number(r), s = i === null ? Ko : Number(i);
|
|
8187
|
+
return a !== void 0 && (!Number.isSafeInteger(a) || a < 0) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "afterId must be a non-negative integer" }))) : o !== void 0 && (!Number.isSafeInteger(o) || o < 1) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "beforeId must be a positive integer" }))) : !Number.isSafeInteger(s) || s < 1 || s > qo ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: `limit must be an integer from 1 to ${qo}` }))) : this.renderDashboardJobs(t, s, a, o);
|
|
8144
8188
|
}
|
|
8145
8189
|
if (e.method === "GET" && n.pathname === "/api/events") return this.events.subscribe(e, t);
|
|
8146
8190
|
if (e.method === "POST" && n.pathname === "/api/events") return this.handleWorkerEvent(e, t);
|
|
8147
8191
|
if (e.method === "GET" && n.pathname.startsWith("/runs/")) {
|
|
8148
8192
|
let e = n.pathname.replace("/runs/", "");
|
|
8149
|
-
return this.renderRunDetails(e, t);
|
|
8193
|
+
return this.renderRunDetails(e, t, "html");
|
|
8194
|
+
}
|
|
8195
|
+
if (e.method === "GET" && n.pathname.startsWith("/api/runs/")) {
|
|
8196
|
+
let e = n.pathname.replace("/api/runs/", "");
|
|
8197
|
+
return this.renderRunDetails(e, t, "json");
|
|
8150
8198
|
}
|
|
8151
8199
|
if (e.method === "POST" && n.pathname.startsWith("/restart/")) {
|
|
8152
8200
|
let e = n.pathname.replace("/restart/", "");
|
|
@@ -8246,14 +8294,23 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8246
8294
|
}
|
|
8247
8295
|
async handleWorkerEvent(e, t) {
|
|
8248
8296
|
if (!this.adminToken || e.headers.authorization !== `Bearer ${this.adminToken}`) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
|
|
8249
|
-
this.
|
|
8297
|
+
let { rawBuffer: n } = await this.readRequest(e, t);
|
|
8298
|
+
if (!n || t.headersSent) return;
|
|
8299
|
+
let r;
|
|
8300
|
+
try {
|
|
8301
|
+
let e = n.length ? JSON.parse(n.toString("utf8")) : {}, t = Number(e.jobId);
|
|
8302
|
+
Number.isSafeInteger(t) && t > 0 && (r = t);
|
|
8303
|
+
} catch {
|
|
8304
|
+
return t.writeHead(400, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Invalid event payload" }));
|
|
8305
|
+
}
|
|
8306
|
+
this.events.publish("jobs.changed", r ? { jobId: r } : {}), t.writeHead(202).end();
|
|
8250
8307
|
}
|
|
8251
8308
|
async renderDashboard(e) {
|
|
8252
|
-
let t = await this.queue.listJobs(51), n =
|
|
8309
|
+
let t = await this.queue.listJobs(51), n = Io(t.slice(0, Ko)), r = this.secrets.redactText(Lo(n, t.length > Ko));
|
|
8253
8310
|
e.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), e.end(r);
|
|
8254
8311
|
}
|
|
8255
8312
|
async renderDashboardJobs(e, t, n, r) {
|
|
8256
|
-
let i = await this.queue.listJobs(t + 1, n, r), a =
|
|
8313
|
+
let i = await this.queue.listJobs(t + 1, n, r), a = Io(i.slice(0, t)), o = this.secrets.redactText(JSON.stringify({
|
|
8257
8314
|
jobs: a,
|
|
8258
8315
|
hasMore: i.length > t
|
|
8259
8316
|
}));
|
|
@@ -8262,44 +8319,18 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8262
8319
|
"Content-Type": "application/json; charset=utf-8"
|
|
8263
8320
|
}), e.end(o);
|
|
8264
8321
|
}
|
|
8265
|
-
async renderRunDetails(e, t) {
|
|
8266
|
-
let
|
|
8267
|
-
if (!
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
t.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), t.end(
|
|
8277
|
-
}
|
|
8278
|
-
buildPendingReport(e) {
|
|
8279
|
-
let t = JSON.parse(e.payload), n = e.started_at || e.created_at;
|
|
8280
|
-
return {
|
|
8281
|
-
jobId: String(e.id),
|
|
8282
|
-
parentId: String(e.parentId || ""),
|
|
8283
|
-
workflowName: e.workflow_id,
|
|
8284
|
-
status: e.status,
|
|
8285
|
-
durationMs: e.status === "running" ? Math.max(0, Date.now() - Date.parse(n)) : 0,
|
|
8286
|
-
startedAt: n,
|
|
8287
|
-
inputs: t.inputs || {},
|
|
8288
|
-
environment: t.env || {},
|
|
8289
|
-
steps: (t.steps || []).map((e, t) => ({
|
|
8290
|
-
id: e.id || `step-${t}`,
|
|
8291
|
-
name: e.name || e.id || `step-${t}`,
|
|
8292
|
-
status: "pending",
|
|
8293
|
-
durationMs: 0,
|
|
8294
|
-
outputs: {},
|
|
8295
|
-
logContent: ""
|
|
8296
|
-
})),
|
|
8297
|
-
artifacts: [],
|
|
8298
|
-
rerunToken: JSON.stringify({
|
|
8299
|
-
jobId: e.id,
|
|
8300
|
-
payload: t
|
|
8301
|
-
})
|
|
8302
|
-
};
|
|
8322
|
+
async renderRunDetails(e, t, n) {
|
|
8323
|
+
let r = await this.queue.getJob(e);
|
|
8324
|
+
if (!r) {
|
|
8325
|
+
let e = n === "json" ? "application/json; charset=utf-8" : "text/html; charset=utf-8";
|
|
8326
|
+
return t.writeHead(404, { "Content-Type": e }), t.end(n === "json" ? JSON.stringify({ error: "Run not found" }) : "<h1>404 - Run Not Found</h1>");
|
|
8327
|
+
}
|
|
8328
|
+
let i = Ho(r, await this.queue.getJobLogs(e), (e) => this.secrets.redactText(e));
|
|
8329
|
+
if (n === "json") return t.writeHead(200, {
|
|
8330
|
+
"Cache-Control": "no-store",
|
|
8331
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
8332
|
+
}), t.end(JSON.stringify(i));
|
|
8333
|
+
t.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), t.end(Uo(i));
|
|
8303
8334
|
}
|
|
8304
8335
|
async handleRestartJob(e, t) {
|
|
8305
8336
|
let n = await this.queue.restartJob(e);
|
|
@@ -8323,7 +8354,7 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8323
8354
|
});
|
|
8324
8355
|
});
|
|
8325
8356
|
}
|
|
8326
|
-
},
|
|
8357
|
+
}, Yo = d(v), Xo = class {
|
|
8327
8358
|
name = "systemd";
|
|
8328
8359
|
async isSupported() {
|
|
8329
8360
|
try {
|
|
@@ -8446,7 +8477,7 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8446
8477
|
cancel: async () => {
|
|
8447
8478
|
d = !0;
|
|
8448
8479
|
try {
|
|
8449
|
-
t.image && await
|
|
8480
|
+
t.image && await Yo(`docker stop -t 2 ${o}`).catch(() => {}), await Yo(`systemctl stop ${o}.service`).catch(() => {});
|
|
8450
8481
|
} catch {}
|
|
8451
8482
|
},
|
|
8452
8483
|
logFilePath: i
|
|
@@ -8456,7 +8487,7 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8456
8487
|
let t = await g(e, "utf-8"), n = t.includes("Running as unit: ") ? t.indexOf("\n") + 1 : 0, r = t.includes("Finished with result: ") ? t.lastIndexOf("Finished with result: ") : t.length;
|
|
8457
8488
|
return t.slice(n, r);
|
|
8458
8489
|
}
|
|
8459
|
-
},
|
|
8490
|
+
}, Zo = class {
|
|
8460
8491
|
name = "standard-process";
|
|
8461
8492
|
async isSupported() {
|
|
8462
8493
|
return !0;
|
|
@@ -8571,13 +8602,13 @@ var Uo = 50, Wo = 500, Go = class e {
|
|
|
8571
8602
|
};
|
|
8572
8603
|
//#endregion
|
|
8573
8604
|
//#region src/drivers/index.ts
|
|
8574
|
-
async function
|
|
8575
|
-
let e = new
|
|
8576
|
-
return await e.isSupported() ? (console.log("โก Selected Execution Driver: Systemd (cgroups enabled)"), e) : (console.log("๐ฆ Selected Execution Driver: Standard Process (Fallback)"), new
|
|
8605
|
+
async function Qo() {
|
|
8606
|
+
let e = new Xo();
|
|
8607
|
+
return await e.isSupported() ? (console.log("โก Selected Execution Driver: Systemd (cgroups enabled)"), e) : (console.log("๐ฆ Selected Execution Driver: Standard Process (Fallback)"), new Zo());
|
|
8577
8608
|
}
|
|
8578
8609
|
//#endregion
|
|
8579
8610
|
//#region src/signals.ts
|
|
8580
|
-
async function
|
|
8611
|
+
async function $o(e) {
|
|
8581
8612
|
let t = !1;
|
|
8582
8613
|
async function n(n) {
|
|
8583
8614
|
if (!t) {
|
|
@@ -8585,7 +8616,7 @@ async function Xo(e) {
|
|
|
8585
8616
|
console.error("โ ๏ธ Graceful shutdown timed out after 10s. Forcing exit!"), process.exit(1);
|
|
8586
8617
|
}, 1e4).unref();
|
|
8587
8618
|
try {
|
|
8588
|
-
|
|
8619
|
+
os(), e.length > 0 && (console.log("โ๏ธ Waiting for active worker jobs to drain..."), await Promise.allSettled(e)), console.log("โจ Engine stopped cleanly. Goodbye!"), process.exit(0);
|
|
8589
8620
|
} catch (e) {
|
|
8590
8621
|
console.error("โ Error during graceful shutdown:", e.message), process.exit(1);
|
|
8591
8622
|
}
|
|
@@ -8594,35 +8625,57 @@ async function Xo(e) {
|
|
|
8594
8625
|
process.on("SIGINT", () => n("SIGINT")), process.on("SIGTERM", () => n("SIGTERM"));
|
|
8595
8626
|
}
|
|
8596
8627
|
//#endregion
|
|
8597
|
-
//#region src/
|
|
8598
|
-
var
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8628
|
+
//#region src/plugins/manager.ts
|
|
8629
|
+
var es = class {
|
|
8630
|
+
plugins;
|
|
8631
|
+
constructor(e = []) {
|
|
8632
|
+
this.plugins = e;
|
|
8633
|
+
}
|
|
8634
|
+
register(e) {
|
|
8635
|
+
console.log(`๐ Registered Plugin: ${e.name}`), this.plugins.push(e);
|
|
8636
|
+
}
|
|
8637
|
+
async triggerWorkflowStart(e) {
|
|
8638
|
+
for (let t of this.plugins) if (t.onWorkflowStart) try {
|
|
8639
|
+
await t.onWorkflowStart(e);
|
|
8640
|
+
} catch (e) {
|
|
8641
|
+
console.error(`[Plugin Error] ${t.name}.onWorkflowStart:`, e);
|
|
8642
|
+
}
|
|
8643
|
+
}
|
|
8644
|
+
async triggerWorkflowFinish(e, t) {
|
|
8645
|
+
for (let n of this.plugins) if (n.onWorkflowFinish) try {
|
|
8646
|
+
await n.onWorkflowFinish(e, t);
|
|
8647
|
+
} catch (e) {
|
|
8648
|
+
console.error(`[Plugin Error] ${n.name}.onWorkflowFinish:`, e);
|
|
8649
|
+
}
|
|
8650
|
+
}
|
|
8651
|
+
}, ts = !!process.env.DEBUG, ns = { isStopping: !1 }, rs = /* @__PURE__ */ new Set(), is = null, as = null;
|
|
8652
|
+
function os() {
|
|
8653
|
+
ns.isStopping = !0, is?.abort(), as?.();
|
|
8654
|
+
}
|
|
8655
|
+
function ss(e, t, n, r) {
|
|
8656
|
+
ns.isStopping = !1;
|
|
8657
|
+
let i = [cs(e, t, n, r)];
|
|
8658
|
+
return $o(i), i;
|
|
8659
|
+
}
|
|
8660
|
+
async function cs(e, t, n, r) {
|
|
8661
|
+
let i = await Qo(), a = /* @__PURE__ */ new Set(), o = 0, s = null, c = () => {
|
|
8609
8662
|
o++, s?.();
|
|
8610
8663
|
};
|
|
8611
|
-
|
|
8612
|
-
let l =
|
|
8613
|
-
for (console.log(`๐ Worker scheduler started. Driver: ${i.name}. Concurrency: ${e}. Tags: ${r.tags.join(", ") || "(none)"}`); !
|
|
8664
|
+
as = c, is = new AbortController();
|
|
8665
|
+
let l = ls(r, is.signal, c);
|
|
8666
|
+
for (console.log(`๐ Worker scheduler started. Driver: ${i.name}. Concurrency: ${e}. Tags: ${r.tags.join(", ") || "(none)"}`); !ns.isStopping;) {
|
|
8614
8667
|
let l = o;
|
|
8615
8668
|
try {
|
|
8616
|
-
for (; a.size < e && !
|
|
8669
|
+
for (; a.size < e && !ns.isStopping;) {
|
|
8617
8670
|
let e = await t.claimNextJob(r.tags);
|
|
8618
8671
|
if (!e) break;
|
|
8619
|
-
if (
|
|
8672
|
+
if (ns.isStopping) {
|
|
8620
8673
|
await t.releaseJob(e.id);
|
|
8621
8674
|
break;
|
|
8622
8675
|
}
|
|
8623
8676
|
let o = `worker-${e.id}`, s;
|
|
8624
8677
|
s = (async () => {
|
|
8625
|
-
|
|
8678
|
+
fs(r, e.id), await ps({
|
|
8626
8679
|
workerId: o,
|
|
8627
8680
|
job: e,
|
|
8628
8681
|
queue: t,
|
|
@@ -8631,31 +8684,31 @@ async function is(e, t, n, r) {
|
|
|
8631
8684
|
driver: i
|
|
8632
8685
|
});
|
|
8633
8686
|
})().catch((e) => console.error(`[${o}] โ ๏ธ Worker execution error:`, e)).finally(() => {
|
|
8634
|
-
a.delete(s),
|
|
8687
|
+
a.delete(s), fs(r, e.id), c();
|
|
8635
8688
|
}), a.add(s);
|
|
8636
8689
|
}
|
|
8637
8690
|
} catch (e) {
|
|
8638
8691
|
console.error("โ ๏ธ Worker scheduler claim error:", e), setTimeout(c, 5e3).unref();
|
|
8639
8692
|
}
|
|
8640
|
-
!
|
|
8693
|
+
!ns.isStopping && o === l && (await us(l, () => o, (e) => s = e), s = null);
|
|
8641
8694
|
}
|
|
8642
|
-
|
|
8695
|
+
is.abort(), await Promise.allSettled(a), await l, as = null, console.log("๐ Worker scheduler stopped cleanly.");
|
|
8643
8696
|
}
|
|
8644
|
-
async function
|
|
8697
|
+
async function ls(e, t, n) {
|
|
8645
8698
|
let r = 1e3;
|
|
8646
8699
|
for (; !t.aborted;) {
|
|
8647
8700
|
try {
|
|
8648
|
-
await
|
|
8701
|
+
await zo(e.serverUrl, t, (t, r) => {
|
|
8649
8702
|
t === "jobs.available" && (Array.isArray(r.tags) ? r.tags.filter((e) => typeof e == "string") : []).every((t) => e.tags.includes(t)) && n();
|
|
8650
8703
|
}, n), r = 1e3;
|
|
8651
8704
|
} catch (e) {
|
|
8652
8705
|
if (t.aborted || e?.name === "AbortError") break;
|
|
8653
8706
|
console.error(`โ ๏ธ Worker event stream disconnected: ${e.message}`);
|
|
8654
8707
|
}
|
|
8655
|
-
await
|
|
8708
|
+
await ds(r, t), r = Math.min(r * 2, 3e4);
|
|
8656
8709
|
}
|
|
8657
8710
|
}
|
|
8658
|
-
function
|
|
8711
|
+
function us(e, t, n) {
|
|
8659
8712
|
return new Promise((r) => {
|
|
8660
8713
|
if (t() !== e) return r();
|
|
8661
8714
|
let i = setTimeout(r, 6e4);
|
|
@@ -8664,7 +8717,7 @@ function os(e, t, n) {
|
|
|
8664
8717
|
});
|
|
8665
8718
|
});
|
|
8666
8719
|
}
|
|
8667
|
-
function
|
|
8720
|
+
function ds(e, t) {
|
|
8668
8721
|
return new Promise((n) => {
|
|
8669
8722
|
if (t.aborted) return n();
|
|
8670
8723
|
let r = () => {
|
|
@@ -8675,19 +8728,23 @@ function ss(e, t) {
|
|
|
8675
8728
|
t.addEventListener("abort", r, { once: !0 });
|
|
8676
8729
|
});
|
|
8677
8730
|
}
|
|
8678
|
-
async function
|
|
8731
|
+
async function fs(e, t) {
|
|
8679
8732
|
if (e.adminToken) try {
|
|
8680
|
-
let
|
|
8733
|
+
let n = await fetch(new URL("/api/events", e.serverUrl), {
|
|
8681
8734
|
method: "POST",
|
|
8682
|
-
headers: {
|
|
8735
|
+
headers: {
|
|
8736
|
+
Authorization: `Bearer ${e.adminToken}`,
|
|
8737
|
+
"Content-Type": "application/json"
|
|
8738
|
+
},
|
|
8739
|
+
body: JSON.stringify({ jobId: t }),
|
|
8683
8740
|
signal: AbortSignal.timeout(5e3)
|
|
8684
8741
|
});
|
|
8685
|
-
!
|
|
8742
|
+
!n.ok && ts && console.error(`Failed to publish job status event: HTTP ${n.status}`);
|
|
8686
8743
|
} catch (e) {
|
|
8687
|
-
|
|
8744
|
+
ts && console.error("Failed to publish job status event:", e);
|
|
8688
8745
|
}
|
|
8689
8746
|
}
|
|
8690
|
-
async function
|
|
8747
|
+
async function ps(e) {
|
|
8691
8748
|
let { workerId: t, job: n, config: r, secrets: i, queue: o } = e;
|
|
8692
8749
|
console.log(`\n[${t}] ๐ฆ Claimed Job #${n.id} (Workflow: ${n.workflow_id})`);
|
|
8693
8750
|
let s = typeof n.payload == "string" ? JSON.parse(n.payload) : n.payload, c = s.steps || [], l = s.inputs || {}, u = Date.now(), d = a.join(r.storagePath, `job-${n.id}`), f = a.join(d, "logs"), p = a.join(d, "wd"), m = {
|
|
@@ -8704,20 +8761,27 @@ async function ls(e) {
|
|
|
8704
8761
|
durationMs: 0,
|
|
8705
8762
|
outputs: {},
|
|
8706
8763
|
logContent: ""
|
|
8707
|
-
})), g =
|
|
8708
|
-
await o.saveReport(n.id, g);
|
|
8709
|
-
let
|
|
8764
|
+
})), g = bs(n, "running", u, l, m.env, h, s);
|
|
8765
|
+
await o.saveReport(n.id, g), fs(r, n.id);
|
|
8766
|
+
let _ = new es(r.plugins), v = {
|
|
8767
|
+
jobId: String(n.id),
|
|
8768
|
+
workflowName: n.workflow_id,
|
|
8769
|
+
inputs: l,
|
|
8770
|
+
runUrl: new URL(`/runs/${n.id}`, r.serverUrl).toString()
|
|
8771
|
+
};
|
|
8772
|
+
await _.triggerWorkflowStart(v);
|
|
8773
|
+
let { cancelled: y, failed: ee } = await ms({
|
|
8710
8774
|
payload: s,
|
|
8711
8775
|
steps: c,
|
|
8712
8776
|
executionContext: m,
|
|
8713
8777
|
...e
|
|
8714
|
-
}, g),
|
|
8715
|
-
g.status =
|
|
8778
|
+
}, g), b = y ? "cancelled" : ee ? "failed" : "success";
|
|
8779
|
+
g.status = b, g.durationMs = Date.now() - u, g.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), await o.completeJob(n.id, b, g), fs(r, n.id), console.log(`[${t}] โ
Job #${n.id} completed as: ${b}`), await _.triggerWorkflowFinish(v, b);
|
|
8716
8780
|
}
|
|
8717
|
-
async function
|
|
8781
|
+
async function ms(e, t) {
|
|
8718
8782
|
let { driver: n, workerId: r, queue: i, config: a, job: o, payload: s, steps: c, executionContext: l } = e, u = t.steps, d = !1, f = !1, p = 0;
|
|
8719
8783
|
try {
|
|
8720
|
-
s.env && Object.assign(l.env, await
|
|
8784
|
+
s.env && Object.assign(l.env, await _s(s.env, l));
|
|
8721
8785
|
for (let e = 0; e < c.length; e++) {
|
|
8722
8786
|
let s = c[e], m = (/* @__PURE__ */ new Date()).toISOString();
|
|
8723
8787
|
u[e] = {
|
|
@@ -8730,8 +8794,8 @@ async function us(e, t) {
|
|
|
8730
8794
|
logContent: "",
|
|
8731
8795
|
startedAt: m,
|
|
8732
8796
|
finishedAt: void 0
|
|
8733
|
-
}, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t);
|
|
8734
|
-
let h = await
|
|
8797
|
+
}, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), fs(a, o.id);
|
|
8798
|
+
let h = await hs({
|
|
8735
8799
|
workerId: r,
|
|
8736
8800
|
jobId: o.id,
|
|
8737
8801
|
step: s,
|
|
@@ -8758,7 +8822,7 @@ async function us(e, t) {
|
|
|
8758
8822
|
exitCode: 1,
|
|
8759
8823
|
error: "Step failed before execution started",
|
|
8760
8824
|
finishedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8761
|
-
}, p = e + 1, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), h.skipped) break;
|
|
8825
|
+
}, p = e + 1, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), fs(a, o.id), h.skipped) break;
|
|
8762
8826
|
if (h.cancelled) {
|
|
8763
8827
|
f = !0, d = !0;
|
|
8764
8828
|
break;
|
|
@@ -8771,22 +8835,22 @@ async function us(e, t) {
|
|
|
8771
8835
|
} catch (e) {
|
|
8772
8836
|
console.log("๐ Step failed", e), d = !0;
|
|
8773
8837
|
}
|
|
8774
|
-
return p < c.length && (
|
|
8838
|
+
return p < c.length && (ys(c, p, u), t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), fs(a, o.id)), {
|
|
8775
8839
|
failed: d,
|
|
8776
8840
|
cancelled: f,
|
|
8777
8841
|
stepReports: u
|
|
8778
8842
|
};
|
|
8779
8843
|
}
|
|
8780
|
-
async function
|
|
8844
|
+
async function hs(e) {
|
|
8781
8845
|
let { step: t, stepIndex: n, executionContext: r } = e;
|
|
8782
|
-
if (t.id ||= `step-${n}`, t.name ||= t.id, t.if && !await ko.evaluateConditions(t.if, r)) return
|
|
8846
|
+
if (t.id ||= `step-${n}`, t.name ||= t.id, t.if && !await ko.evaluateConditions(t.if, r)) return ts && console.log(`โฉ Skipped step ${t.id} based on condition: ${t.if}`, r), {
|
|
8783
8847
|
failed: !1,
|
|
8784
8848
|
cancelled: !1,
|
|
8785
8849
|
skipped: !0,
|
|
8786
8850
|
report: null
|
|
8787
8851
|
};
|
|
8788
8852
|
try {
|
|
8789
|
-
let n = await
|
|
8853
|
+
let n = await _s(t.env, r), i = {
|
|
8790
8854
|
jobId: String(e.jobId),
|
|
8791
8855
|
step: t,
|
|
8792
8856
|
command: t.run,
|
|
@@ -8800,15 +8864,15 @@ async function ds(e) {
|
|
|
8800
8864
|
WORKING_DIR: r.workingDir
|
|
8801
8865
|
}
|
|
8802
8866
|
};
|
|
8803
|
-
return t.eval ?
|
|
8867
|
+
return t.eval ? gs({
|
|
8804
8868
|
...e,
|
|
8805
8869
|
stepContext: i
|
|
8806
|
-
}) :
|
|
8870
|
+
}) : vs({
|
|
8807
8871
|
...e,
|
|
8808
8872
|
stepContext: i
|
|
8809
8873
|
});
|
|
8810
8874
|
} catch (e) {
|
|
8811
|
-
return
|
|
8875
|
+
return ts && console.error(`โฉ Failed to run step ${t.id}`, r, e), {
|
|
8812
8876
|
failed: !0,
|
|
8813
8877
|
cancelled: !1,
|
|
8814
8878
|
skipped: !1,
|
|
@@ -8816,7 +8880,7 @@ async function ds(e) {
|
|
|
8816
8880
|
};
|
|
8817
8881
|
}
|
|
8818
8882
|
}
|
|
8819
|
-
async function
|
|
8883
|
+
async function gs(e) {
|
|
8820
8884
|
let { queue: t, stepContext: n, executionContext: r } = e, { jobId: i, step: a } = n, o = Date.now(), s = a.id, c = a.name;
|
|
8821
8885
|
try {
|
|
8822
8886
|
let e = await ko.evaluateExpression(a.eval, r);
|
|
@@ -8862,12 +8926,12 @@ async function fs(e) {
|
|
|
8862
8926
|
};
|
|
8863
8927
|
}
|
|
8864
8928
|
}
|
|
8865
|
-
async function
|
|
8929
|
+
async function _s(e, t) {
|
|
8866
8930
|
let n = {};
|
|
8867
8931
|
if (e) for (let [r, i] of Object.entries(e)) n[r] = String(await ko.evaluateValue(i, t));
|
|
8868
8932
|
return n;
|
|
8869
8933
|
}
|
|
8870
|
-
async function
|
|
8934
|
+
async function vs(t) {
|
|
8871
8935
|
let { workerId: n, jobId: r, stepContext: i, executionContext: a, driver: o, queue: s } = t, { step: c } = i, l = c.id, u = c.name, d;
|
|
8872
8936
|
try {
|
|
8873
8937
|
d = o.execute(i);
|
|
@@ -8882,11 +8946,11 @@ async function ms(t) {
|
|
|
8882
8946
|
logFilePath: ""
|
|
8883
8947
|
};
|
|
8884
8948
|
}
|
|
8885
|
-
|
|
8949
|
+
rs.add(d);
|
|
8886
8950
|
let f = !1, p = setInterval(async () => {
|
|
8887
8951
|
await s.isCancelled(r) && (console.log(`[${n}] ๐ Job #${r} was cancelled! Halting execution.`), f = !0, clearInterval(p), await d.cancel());
|
|
8888
8952
|
}, 3e3), m = await d.done;
|
|
8889
|
-
if (clearInterval(p),
|
|
8953
|
+
if (clearInterval(p), rs.delete(d), d.logFilePath && e.existsSync(d.logFilePath)) try {
|
|
8890
8954
|
let e = await o.readLog(d.logFilePath);
|
|
8891
8955
|
await s.saveStepLog(r, l, e);
|
|
8892
8956
|
} catch (e) {
|
|
@@ -8913,7 +8977,7 @@ async function ms(t) {
|
|
|
8913
8977
|
}
|
|
8914
8978
|
};
|
|
8915
8979
|
}
|
|
8916
|
-
function
|
|
8980
|
+
function ys(e, t, n) {
|
|
8917
8981
|
for (let r = t; r < e.length; r++) {
|
|
8918
8982
|
let t = e[r], i = t.id || `step-${r}`;
|
|
8919
8983
|
n[r] = {
|
|
@@ -8927,7 +8991,7 @@ function hs(e, t, n) {
|
|
|
8927
8991
|
};
|
|
8928
8992
|
}
|
|
8929
8993
|
}
|
|
8930
|
-
function
|
|
8994
|
+
function bs(e, t, n, r, i, a, o) {
|
|
8931
8995
|
return {
|
|
8932
8996
|
jobId: String(e.id),
|
|
8933
8997
|
parentId: String(e.parentId || ""),
|
|
@@ -8946,56 +9010,51 @@ function gs(e, t, n, r, i, a, o) {
|
|
|
8946
9010
|
})
|
|
8947
9011
|
};
|
|
8948
9012
|
}
|
|
8949
|
-
async function _s(e, t = [], n) {
|
|
8950
|
-
!Array.isArray(t) || t.length === 0 || (console.log(`[${e}] ๐ข Dispatching execution report to ${t.length} reporter(s)...`), await Promise.allSettled(t.map(async (t) => {
|
|
8951
|
-
try {
|
|
8952
|
-
await t.report(n);
|
|
8953
|
-
} catch (n) {
|
|
8954
|
-
console.error(`[${e}] โ ๏ธ Reporter '${t.name || "unknown"}' failed:`, n.message);
|
|
8955
|
-
}
|
|
8956
|
-
})));
|
|
8957
|
-
}
|
|
8958
9013
|
//#endregion
|
|
8959
|
-
//#region src/
|
|
8960
|
-
var
|
|
8961
|
-
name = "
|
|
8962
|
-
|
|
9014
|
+
//#region src/plugins/github-status.plugin.ts
|
|
9015
|
+
var xs = class {
|
|
9016
|
+
name = "github-commit-status";
|
|
9017
|
+
token;
|
|
9018
|
+
apiUrl;
|
|
9019
|
+
context;
|
|
8963
9020
|
constructor(e) {
|
|
8964
|
-
this.
|
|
8965
|
-
}
|
|
8966
|
-
async
|
|
8967
|
-
|
|
8968
|
-
let n = a.join(this.outputDir, `run-${t.jobId}.json`);
|
|
8969
|
-
e.writeFileSync(n, JSON.stringify(t, null, 2), "utf-8"), console.log(`๐ Execution report saved to: ${n}`);
|
|
8970
|
-
}
|
|
8971
|
-
}, ys = class {
|
|
8972
|
-
name = "slack";
|
|
8973
|
-
webhookUrl = "";
|
|
8974
|
-
token = "";
|
|
8975
|
-
channel = "";
|
|
8976
|
-
notifyOn = ["failed"];
|
|
8977
|
-
constructor(e) {
|
|
8978
|
-
Object.assign(this, e);
|
|
9021
|
+
this.token = e.token, this.apiUrl = e.apiUrl || "https://api.github.com/", this.context = e.context || "on";
|
|
9022
|
+
}
|
|
9023
|
+
async onWorkflowStart(e) {
|
|
9024
|
+
this.hasCoordinates(e) && await this.updateStatus(e, "pending", "Workflow build has started.");
|
|
8979
9025
|
}
|
|
8980
|
-
async
|
|
8981
|
-
if (!this.
|
|
8982
|
-
let
|
|
8983
|
-
await
|
|
9026
|
+
async onWorkflowFinish(e, t) {
|
|
9027
|
+
if (!this.hasCoordinates(e)) return;
|
|
9028
|
+
let n = t === "success" ? "success" : t === "failed" ? "failure" : "error", r = t === "success" ? "Workflow completed successfully." : `Workflow ${t}.`;
|
|
9029
|
+
await this.updateStatus(e, n, r);
|
|
9030
|
+
}
|
|
9031
|
+
async updateStatus(e, t, n) {
|
|
9032
|
+
let r = encodeURIComponent(String(e.inputs.owner)), i = encodeURIComponent(String(e.inputs.repo)), a = encodeURIComponent(String(e.inputs.commit_sha)), o = this.apiUrl.endsWith("/") ? this.apiUrl : `${this.apiUrl}/`, s = await fetch(new URL(`repos/${r}/${i}/statuses/${a}`, o), {
|
|
8984
9033
|
method: "POST",
|
|
8985
9034
|
headers: {
|
|
9035
|
+
Accept: "application/vnd.github+json",
|
|
8986
9036
|
Authorization: `Bearer ${this.token}`,
|
|
8987
|
-
"Content-Type": "application/json"
|
|
9037
|
+
"Content-Type": "application/json",
|
|
9038
|
+
"User-Agent": "@cloud-cli/on",
|
|
9039
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
8988
9040
|
},
|
|
9041
|
+
signal: AbortSignal.timeout(1e4),
|
|
8989
9042
|
body: JSON.stringify({
|
|
8990
|
-
|
|
8991
|
-
|
|
9043
|
+
state: t,
|
|
9044
|
+
target_url: e.runUrl,
|
|
9045
|
+
description: n.slice(0, 140),
|
|
9046
|
+
context: `${this.context}/${e.workflowName}`.slice(0, 100)
|
|
8992
9047
|
})
|
|
8993
9048
|
});
|
|
9049
|
+
if (!s.ok) throw Error(`GitHub status update failed with HTTP ${s.status}: ${await s.text()}`);
|
|
9050
|
+
}
|
|
9051
|
+
hasCoordinates(e) {
|
|
9052
|
+
return !!(this.token && e.inputs.owner && e.inputs.repo && e.inputs.commit_sha);
|
|
8994
9053
|
}
|
|
8995
9054
|
};
|
|
8996
9055
|
//#endregion
|
|
8997
9056
|
//#region src/index.ts
|
|
8998
|
-
function
|
|
9057
|
+
function Ss(e) {
|
|
8999
9058
|
console.log("๐ Validating Workflows in:", e.workflows);
|
|
9000
9059
|
let t = new di(e.workflows), n = r(e.workflows).filter((e) => e.endsWith(".yml") || e.endsWith(".yaml"));
|
|
9001
9060
|
for (let e of n) {
|
|
@@ -9003,13 +9062,13 @@ function bs(e) {
|
|
|
9003
9062
|
console.log(` โ
${e} -> Valid! (${n.length} job matrix variant(s) generated)`);
|
|
9004
9063
|
}
|
|
9005
9064
|
}
|
|
9006
|
-
async function
|
|
9065
|
+
async function Cs() {
|
|
9007
9066
|
let { config: e, command: t } = await fe();
|
|
9008
|
-
if (e || process.exit(1), t === "validate") return
|
|
9067
|
+
if (e || process.exit(1), t === "validate") return Ss(e);
|
|
9009
9068
|
let n = new mi("./.env"), r = new pi(process.env.WORKER_NAME || "cli");
|
|
9010
9069
|
switch (t) {
|
|
9011
9070
|
case "start-server":
|
|
9012
|
-
console.log("๐ Starting Ingress Gateway..."), await r.init(), await
|
|
9071
|
+
console.log("๐ Starting Ingress Gateway..."), await r.init(), await Jo.withPort({
|
|
9013
9072
|
config: e,
|
|
9014
9073
|
queue: r,
|
|
9015
9074
|
secrets: n,
|
|
@@ -9018,11 +9077,11 @@ async function xs() {
|
|
|
9018
9077
|
});
|
|
9019
9078
|
break;
|
|
9020
9079
|
case "start-workers":
|
|
9021
|
-
console.log(`โ๏ธ Starting worker scheduler with ${e.workers} concurrent slot(s)...`), await r.init(),
|
|
9080
|
+
console.log(`โ๏ธ Starting worker scheduler with ${e.workers} concurrent slot(s)...`), await r.init(), ss(e.workers, r, n, e);
|
|
9022
9081
|
break;
|
|
9023
9082
|
default: console.error(`โ Unknown command: '${t}'`), de(), process.exit(1);
|
|
9024
9083
|
}
|
|
9025
9084
|
}
|
|
9026
|
-
|
|
9085
|
+
Cs().catch(console.error);
|
|
9027
9086
|
//#endregion
|
|
9028
|
-
export {
|
|
9087
|
+
export { xs as GitHubStatusPlugin };
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FinalJobStatus, WorkflowContext, WorkflowPlugin } from '../types.js';
|
|
2
|
+
export interface GitHubStatusPluginOptions {
|
|
3
|
+
token: string;
|
|
4
|
+
apiUrl?: string;
|
|
5
|
+
context?: string;
|
|
6
|
+
}
|
|
2
7
|
export declare class GitHubStatusPlugin implements WorkflowPlugin {
|
|
3
|
-
name
|
|
8
|
+
readonly name = "github-commit-status";
|
|
9
|
+
private readonly token;
|
|
10
|
+
private readonly apiUrl;
|
|
11
|
+
private readonly context;
|
|
12
|
+
constructor(options: GitHubStatusPluginOptions);
|
|
4
13
|
onWorkflowStart(wf: WorkflowContext): Promise<void>;
|
|
5
|
-
onWorkflowFinish(wf: WorkflowContext, status:
|
|
14
|
+
onWorkflowFinish(wf: WorkflowContext, status: FinalJobStatus): Promise<void>;
|
|
6
15
|
private updateStatus;
|
|
16
|
+
private hasCoordinates;
|
|
7
17
|
}
|
|
8
18
|
//# sourceMappingURL=github-status.plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-status.plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/github-status.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"github-status.plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/github-status.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,IAAI,0BAA0B;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,yBAAyB;IAMxC,eAAe,CAAC,EAAE,EAAE,eAAe;IAMnC,gBAAgB,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc;YASpD,YAAY;IA4B1B,OAAO,CAAC,cAAc;CAGvB"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FinalJobStatus, WorkflowContext, WorkflowPlugin } from '../types.js';
|
|
2
2
|
export declare class PluginManager {
|
|
3
3
|
private plugins;
|
|
4
|
+
constructor(plugins?: WorkflowPlugin[]);
|
|
4
5
|
register(plugin: WorkflowPlugin): void;
|
|
5
6
|
triggerWorkflowStart(wf: WorkflowContext): Promise<void>;
|
|
6
|
-
triggerWorkflowFinish(wf: WorkflowContext, status:
|
|
7
|
+
triggerWorkflowFinish(wf: WorkflowContext, status: FinalJobStatus): Promise<void>;
|
|
7
8
|
}
|
|
8
9
|
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnF,qBAAa,aAAa;IACZ,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE,cAAc,EAAO;IAElD,QAAQ,CAAC,MAAM,EAAE,cAAc;IAKzB,oBAAoB,CAAC,EAAE,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxD,qBAAqB,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAWxF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JobRecord, StepReport, WorkflowExecutionReport } from './types.js';
|
|
2
|
+
export interface RunView {
|
|
3
|
+
jobId: string;
|
|
4
|
+
parentId: string;
|
|
5
|
+
workflowName: string;
|
|
6
|
+
status: WorkflowExecutionReport['status'];
|
|
7
|
+
durationMs: number;
|
|
8
|
+
startedAt: string;
|
|
9
|
+
finishedAt?: string;
|
|
10
|
+
inputs: Record<string, unknown>;
|
|
11
|
+
steps: StepReport[];
|
|
12
|
+
artifacts: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function buildRunView(job: JobRecord & Record<string, any>, logs: Record<string, string>, redact: (value: string) => string): RunView;
|
|
15
|
+
export declare function renderRunHtml(report: RunView): string;
|
|
16
|
+
//# sourceMappingURL=run-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-view.d.ts","sourceRoot":"","sources":["../src/run-view.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,SAAS,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAK7F,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAChC,OAAO,CAgCT;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAErD"}
|
package/dist/server.d.ts
CHANGED
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,mBAAmB,EACnB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAQpB,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,eAAe,CAAgB;WAE1B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;gBAK1D,OAAO,EAAE,oBAAoB;IAczC,oBAAoB,CAAC,YAAY,EAAE,mBAAmB;YAIxC,aAAa;IAuE3B;;OAEG;YACW,aAAa;YA0Bb,WAAW;IAwBzB,OAAO,CAAC,UAAU;YAiBJ,cAAc;IA2C5B;;OAEG;YACW,kBAAkB;YAelB,iBAAiB;IAuB/B;;OAEG;YACW,eAAe;YAQf,mBAAmB;IAWjC;;OAEG;YACW,gBAAgB;YAqBhB,gBAAgB;IAc9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAStC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { QueueManager } from './queue.js';
|
|
2
2
|
import { SecretStore } from './secrets.js';
|
|
3
|
-
export interface Reporter {
|
|
4
|
-
name: string;
|
|
5
|
-
report(execReport: WorkflowExecutionReport): Promise<void>;
|
|
6
|
-
}
|
|
7
3
|
export interface RunnerConfig {
|
|
8
4
|
/** Ingress HTTP Gateway Port */
|
|
9
5
|
port: number;
|
|
@@ -13,7 +9,7 @@ export interface RunnerConfig {
|
|
|
13
9
|
database: string;
|
|
14
10
|
/** Directory where workflow YAML files live */
|
|
15
11
|
workflows: string;
|
|
16
|
-
/**
|
|
12
|
+
/** Maximum number of jobs executed concurrently on this node */
|
|
17
13
|
workers: number;
|
|
18
14
|
/** Webhook server URL used for worker event notifications */
|
|
19
15
|
serverUrl: string;
|
|
@@ -23,8 +19,8 @@ export interface RunnerConfig {
|
|
|
23
19
|
storagePath: string;
|
|
24
20
|
/** Global environment variables injected into all step runs */
|
|
25
21
|
env: Record<string, string>;
|
|
26
|
-
/**
|
|
27
|
-
|
|
22
|
+
/** External integrations notified about workflow lifecycle changes */
|
|
23
|
+
plugins: WorkflowPlugin[];
|
|
28
24
|
}
|
|
29
25
|
export type UserRunnerConfig = Partial<RunnerConfig>;
|
|
30
26
|
export interface StepContext {
|
|
@@ -149,35 +145,18 @@ export interface ParsedWorkflow {
|
|
|
149
145
|
steps: WorkflowStep[];
|
|
150
146
|
[key: string]: any;
|
|
151
147
|
}
|
|
152
|
-
export interface IngressContext {
|
|
153
|
-
provider: string;
|
|
154
|
-
headers: Record<string, string>;
|
|
155
|
-
body: any;
|
|
156
|
-
rawBuffer: Buffer;
|
|
157
|
-
}
|
|
158
148
|
export interface WorkflowContext {
|
|
159
149
|
jobId: string;
|
|
160
150
|
workflowName: string;
|
|
161
151
|
inputs: WorkflowInputs;
|
|
162
|
-
|
|
152
|
+
runUrl: string;
|
|
163
153
|
}
|
|
164
154
|
export interface WorkflowPlugin {
|
|
165
155
|
name: string;
|
|
166
|
-
/** Verify HMAC or signatures */
|
|
167
|
-
onAuthenticate?: (ctx: IngressContext) => Promise<boolean> | boolean;
|
|
168
|
-
/** Convert raw body/headers into normalized inputs */
|
|
169
|
-
onTransform?: (ctx: IngressContext) => Promise<Record<string, any>> | Record<string, any>;
|
|
170
|
-
/** Final gatekeeper check (return false to drop job before enqueueing) */
|
|
171
|
-
onFilter?: (inputs: Record<string, any>, ctx: IngressContext) => Promise<boolean> | boolean;
|
|
172
|
-
/** Runs before any steps execute (e.g. notify Slack, update GitHub status to "Pending") */
|
|
173
156
|
onWorkflowStart?: (wf: WorkflowContext) => Promise<void>;
|
|
174
|
-
|
|
175
|
-
onStepBefore?: (step: StepContext, wf: WorkflowContext) => Promise<void>;
|
|
176
|
-
/** Runs after a step finishes (e.g. parse outputs, stream step metrics) */
|
|
177
|
-
onStepAfter?: (step: StepContext, result: StepResult, wf: WorkflowContext) => Promise<void>;
|
|
178
|
-
/** Runs when workflow succeeds or fails (e.g. update GitHub status to "Success/Failure", wipe layers) */
|
|
179
|
-
onWorkflowFinish?: (wf: WorkflowContext, status: 'success' | 'failed', error?: Error) => Promise<void>;
|
|
157
|
+
onWorkflowFinish?: (wf: WorkflowContext, status: FinalJobStatus) => Promise<void>;
|
|
180
158
|
}
|
|
159
|
+
export type FinalJobStatus = Exclude<JobStatus, 'pending' | 'running'>;
|
|
181
160
|
export interface StepReport {
|
|
182
161
|
id: string;
|
|
183
162
|
name: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAQ3C,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/worker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAGL,YAAY,EAOZ,WAAW,EAIZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAGL,YAAY,EAOZ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAOpB,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAMF;;GAEG;AACH,wBAAsB,qBAAqB,kBAK1C;AAED,wBAAgB,qBAAqB,SAIpC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,mBAK1G;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,YAAY,iBA4DrB;AAgFD;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,WAAW,iBAoE9C"}
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Reporter, WorkflowExecutionReport } from '../types.js';
|
|
2
|
-
export declare class HtmlReporter implements Reporter {
|
|
3
|
-
name: string;
|
|
4
|
-
private outputDir;
|
|
5
|
-
constructor(options: {
|
|
6
|
-
outputDir: string;
|
|
7
|
-
});
|
|
8
|
-
report(execReport: WorkflowExecutionReport): Promise<void>;
|
|
9
|
-
generateHtml(execReport: WorkflowExecutionReport): string;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=html.reporter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"html.reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/html.reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAMhE,qBAAa,YAAa,YAAW,QAAQ;IAC3C,IAAI,SAAU;IACd,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAIpC,MAAM,CAAC,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAShE,YAAY,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM;CAG1D"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Reporter, WorkflowExecutionReport } from '../types.js';
|
|
2
|
-
export declare class JsonFileReporter implements Reporter {
|
|
3
|
-
name: string;
|
|
4
|
-
private outputDir;
|
|
5
|
-
constructor(options: {
|
|
6
|
-
outputDir: string;
|
|
7
|
-
});
|
|
8
|
-
report(execReport: WorkflowExecutionReport): Promise<void>;
|
|
9
|
-
}
|
|
10
|
-
//# sourceMappingURL=json-file.reporter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"json-file.reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/json-file.reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEhE,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,IAAI,SAAe;IACnB,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAIpC,MAAM,CAAC,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;CAQjE"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Reporter, WorkflowExecutionReport } from '../types.js';
|
|
2
|
-
export declare class SlackReporter implements Reporter {
|
|
3
|
-
readonly name = "slack";
|
|
4
|
-
private webhookUrl;
|
|
5
|
-
private token;
|
|
6
|
-
private channel;
|
|
7
|
-
private notifyOn;
|
|
8
|
-
constructor(options: {
|
|
9
|
-
webhookUrl: string;
|
|
10
|
-
token: string;
|
|
11
|
-
channel: string;
|
|
12
|
-
notifyOn?: ('success' | 'failed')[];
|
|
13
|
-
});
|
|
14
|
-
report(execReport: WorkflowExecutionReport): Promise<void>;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=slack.reporter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"slack.reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/slack.reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEhE,qBAAa,aAAc,YAAW,QAAQ;IAC5C,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,QAAQ,CAAwC;gBAE5C,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAA;KAAE;IAI1G,MAAM,CAAC,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;CAejE"}
|