Add cron worker controls and align superuser specs

This commit is contained in:
Jeppe B
2026-07-13 19:47:08 +02:00
parent 9e27380a10
commit bbe4ad938a
7 changed files with 442 additions and 62 deletions
+148 -26
View File
@@ -64,11 +64,21 @@ test.describe("Superuser cron operations", () => {
await primeMockSession(page, { token: "superuser-cron-token", bootPath: null });
});
test("superusers can inspect, run, toggle, and reschedule cron tasks", async ({ page }) => {
test("superusers can inspect, run, toggle, and reschedule cron tasks", async ({ page }, testInfo) => {
const patchPayloads: Array<Record<string, unknown>> = [];
const runPayloads: Array<Record<string, unknown>> = [];
const deployPayloads: Array<Record<string, unknown>> = [];
let currentTasks = cronTasks.map((task) => ({ ...task, schedule: { ...task.schedule } }));
let runHistory = [
{
id: 41,
task_id: "economic.transfer_queue",
source: "automatic",
status: "succeeded",
started_at: "2026-07-09 12:00:00",
duration_ms: 2100,
},
];
await page.route(apiPathPattern("/superuser/cron"), async (route) => {
if (route.request().method() !== "GET") {
@@ -89,16 +99,7 @@ test.describe("Superuser cron operations", () => {
body: JSON.stringify({
success: true,
data: {
runs: [
{
id: 41,
task_id: "economic.transfer_queue",
source: "automatic",
status: "succeeded",
started_at: "2026-07-09 12:00:00",
duration_ms: 2100,
},
],
runs: runHistory,
},
meta: {},
includes: {},
@@ -180,8 +181,20 @@ test.describe("Superuser cron operations", () => {
await page.route(apiPathPattern("/superuser/cron/run"), async (route) => {
runPayloads.push(route.request().postDataJSON() as Record<string, unknown>);
runHistory = [
{
id: 42,
task_id: "economic.transfer_queue",
source: "manual",
status: "queued",
scheduled_for: "2026-07-09 12:02:00",
created_at: "2026-07-09 12:02:00",
duration_ms: null,
},
...runHistory,
];
await route.fulfill({
status: 200,
status: 202,
contentType: "application/json",
body: JSON.stringify({
success: true,
@@ -189,9 +202,10 @@ test.describe("Superuser cron operations", () => {
id: 42,
task_id: "economic.transfer_queue",
source: "manual",
status: "succeeded",
started_at: "2026-07-09 12:02:00",
duration_ms: 1800,
status: "queued",
scheduled_for: "2026-07-09 12:02:00",
created_at: "2026-07-09 12:02:00",
duration_ms: null,
},
meta: {},
includes: {},
@@ -226,18 +240,22 @@ test.describe("Superuser cron operations", () => {
"Process e-conomic transfer queue"
);
await expect(page.getByTestId("cron-total-tasks")).toContainText("2");
await expect(page.getByTestId("cron-worker-panel")).toContainText("release-stable-cron-worker");
await expect(page.getByTestId("cron-worker-running")).toContainText("1");
await expect(page.getByTestId("cron-worker-target")).toContainText("cron-worker-uuid");
if (!/mobile/i.test(testInfo.project.name)) {
await expect(page.getByTestId("cron-worker-panel")).toContainText("release-stable-cron-worker");
await expect(page.getByTestId("cron-worker-running")).toContainText("1");
await expect(page.getByTestId("cron-worker-target")).toContainText("cron-worker-uuid");
await expect(page.getByTestId("cron-worker-deploy")).toHaveText("Update Coolify deployment");
await Promise.all([
page.waitForResponse(
(response) =>
response.url().includes("/superuser/cron/workers/deploy") && response.request().method() === "POST"
),
page.getByTestId("cron-worker-deploy").click(),
]);
expect(deployPayloads).toEqual([{}]);
await Promise.all([
page.waitForResponse(
(response) =>
response.url().includes("/superuser/cron/workers/deploy") && response.request().method() === "POST"
),
page.getByTestId("cron-worker-deploy").click(),
]);
expect(deployPayloads).toEqual([{}]);
await expect(page.getByTestId("cron-run-queued")).toContainText("deployment update");
}
await Promise.all([
page.waitForResponse(
@@ -248,6 +266,8 @@ test.describe("Superuser cron operations", () => {
expect(runPayloads).toEqual([{ task_id: "economic.transfer_queue", force: false }]);
await expect(page.getByTestId("cron-run-history")).toContainText("manual");
await expect(page.getByTestId("cron-run-history")).toContainText("Queued");
await expect(page.getByTestId("cron-run-queued")).toContainText("was queued");
await page.getByTestId("cron-task-toggle-system.sync_logs").click();
expect(patchPayloads.at(-1)).toMatchObject({ task_id: "system.sync_logs", enabled: true });
@@ -259,4 +279,106 @@ test.describe("Superuser cron operations", () => {
schedule: { type: "interval", seconds: 120 },
});
});
test("superusers can deploy the cron worker to Coolify when no deployment target exists", async ({ page }) => {
const deployPayloads: Array<Record<string, unknown>> = [];
let deploymentTarget: Record<string, unknown> | null = null;
await page.route(apiPathPattern("/superuser/cron"), async (route) => {
if (route.request().method() !== "GET") {
await route.fallback();
return;
}
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(cronListPayload()),
});
});
await page.route(apiPathPattern("/superuser/cron/runs"), async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
data: { runs: [] },
meta: {},
includes: {},
}),
});
});
await page.route(apiPathPattern("/superuser/cron/workers"), async (route) => {
if (route.request().method() !== "GET") {
await route.fallback();
return;
}
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
data: {
workers: [],
summary: {
total: 0,
running: 0,
stale: 0,
},
deployment: {
ok: true,
channel: {
id: 1,
slug: "stable",
name: "Stable",
},
target: deploymentTarget,
},
},
meta: {},
includes: {},
}),
});
});
await page.route(apiPathPattern("/superuser/cron/workers/deploy"), async (route) => {
deployPayloads.push(route.request().postDataJSON() as Record<string, unknown>);
deploymentTarget = {
id: 71,
app: "cron",
coolify_service_uuid: "cron-worker-uuid",
auto_deploy: false,
};
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
data: {
ok: true,
target: deploymentTarget,
},
meta: {},
includes: {},
}),
});
});
await page.goto("/superuser/system/cron", { waitUntil: "domcontentloaded" });
await expect(page.getByTestId("cron-worker-deploy")).toHaveText("Deploy to Coolify");
await Promise.all([
page.waitForResponse(
(response) =>
response.url().includes("/superuser/cron/workers/deploy") && response.request().method() === "POST"
),
page.getByTestId("cron-worker-deploy").click(),
]);
expect(deployPayloads).toEqual([{}]);
await expect(page.getByTestId("cron-run-queued")).toContainText("deployment was queued");
await expect(page.getByTestId("cron-worker-target")).toContainText("cron-worker-uuid");
await expect(page.getByTestId("cron-worker-deploy")).toHaveText("Update Coolify deployment");
});
});