diff --git a/agent/internal/build/build.go b/agent/internal/build/build.go
index b8e31c4..ff64287 100644
--- a/agent/internal/build/build.go
+++ b/agent/internal/build/build.go
@@ -90,6 +90,14 @@ func truncateStr(s string, maxLen int) string {
return s[:maxLen]
}
+func tailLines(output string, n int) string {
+ lines := strings.Split(strings.TrimSpace(output), "\n")
+ if len(lines) <= n {
+ return strings.TrimSpace(output)
+ }
+ return strings.Join(lines[len(lines)-n:], "\n")
+}
+
func computeSecretsHash(secrets map[string]string) string {
if len(secrets) == 0 {
return ""
@@ -220,7 +228,7 @@ func (b *Builder) buildAndPush(ctx context.Context, config *Config, buildDir str
if err != nil {
log.Printf("[build:%s] buildctl failed with output: %s", truncateStr(config.BuildID, 8), output)
b.sendLog(config, fmt.Sprintf("Build error: %s", output))
- return fmt.Errorf("buildctl build failed: %w", err)
+ return fmt.Errorf("buildctl build failed:\n%s", tailLines(output, 20))
}
} else {
log.Printf("[build:%s] building with Railpack via buildctl for %s", truncateStr(config.BuildID, 8), platform)
@@ -238,7 +246,7 @@ func (b *Builder) buildAndPush(ctx context.Context, config *Config, buildDir str
if err != nil {
log.Printf("[build:%s] railpack prepare failed with output: %s", truncateStr(config.BuildID, 8), output)
b.sendLog(config, fmt.Sprintf("Railpack prepare error: %s", output))
- return fmt.Errorf("railpack prepare failed: %w", err)
+ return fmt.Errorf("railpack prepare failed:\n%s", tailLines(output, 20))
}
b.sendLog(config, fmt.Sprintf("Building for %s...", platform))
@@ -268,7 +276,7 @@ func (b *Builder) buildAndPush(ctx context.Context, config *Config, buildDir str
if err != nil {
log.Printf("[build:%s] buildctl failed for %s: %s", truncateStr(config.BuildID, 8), platform, output)
b.sendLog(config, fmt.Sprintf("Build error (%s): %s", platform, output))
- return fmt.Errorf("buildctl build failed for %s: %w", platform, err)
+ return fmt.Errorf("buildctl build failed for %s:\n%s", platform, tailLines(output, 20))
}
}
diff --git a/web/actions/projects.ts b/web/actions/projects.ts
index 19f52a8..9d2aa1e 100644
--- a/web/actions/projects.ts
+++ b/web/actions/projects.ts
@@ -47,9 +47,11 @@ function isValidImageReferencePart(reference: string): boolean {
const tagPattern = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
const digestPattern = /^[A-Za-z0-9_+.-]+:[0-9a-fA-F]{32,256}$/;
- return reference === "latest" ||
+ return (
+ reference === "latest" ||
tagPattern.test(reference) ||
- digestPattern.test(reference);
+ digestPattern.test(reference)
+ );
}
function parseImageReference(image: string): {
@@ -604,27 +606,6 @@ export async function deployService(serviceId: string) {
}
}
- const existingDeployments = await db
- .select()
- .from(deployments)
- .where(eq(deployments.serviceId, serviceId));
-
- const inProgressStatuses = [
- "pending",
- "pulling",
- "starting",
- "healthy",
- "stopping",
- ];
-
- const hasInProgressDeployment = existingDeployments.some((d) =>
- inProgressStatuses.includes(d.status),
- );
-
- if (hasInProgressDeployment) {
- throw new Error("A deployment is already in progress");
- }
-
const rolloutId = randomUUID();
await db.insert(rollouts).values({
diff --git a/web/app/(dashboard)/dashboard/projects/[slug]/[env]/services/[serviceId]/page.tsx b/web/app/(dashboard)/dashboard/projects/[slug]/[env]/services/[serviceId]/page.tsx
index e9d674f..0314f07 100644
--- a/web/app/(dashboard)/dashboard/projects/[slug]/[env]/services/[serviceId]/page.tsx
+++ b/web/app/(dashboard)/dashboard/projects/[slug]/[env]/services/[serviceId]/page.tsx
@@ -132,7 +132,7 @@ export default function DeploymentsPage() {
(service.configuredReplicas || []).length > 0;
return (
-
+
-
0 ? (
- hasRunningDeployments ? (
-
- setConfirmAction("redeploy")}
- >
-
- {isLoading === "redeploy" ? "Redeploying..." : "Redeploy"}
-
-
-
- }
+
+
0 ? (
+ hasRunningDeployments ? (
+
+ setConfirmAction("redeploy")}
>
-
-
-
-
- handleAction(
- "restart",
- () => restartService(service.id),
- "Restart queued",
- )
+
+ {isLoading === "redeploy" ? "Redeploying..." : "Redeploy"}
+
+
+
}
>
-
- Restart
-
-
- setConfirmAction("stop")}
- className="text-orange-600 dark:text-orange-500"
- >
-
- Stop All
-
- setConfirmAction("delete")}
- >
-
- Delete All
-
-
-
-
- ) : canStartAll ? (
-
-
- handleAction("start", () => deployService(service.id))
- }
- >
-
- {isLoading === "start" ? "Starting..." : "Start All"}
-
-
-
+
+
+
+ onClick={() =>
+ handleAction(
+ "restart",
+ () => restartService(service.id),
+ "Restart queued",
+ )
+ }
+ >
+
+ Restart
+
+
+ setConfirmAction("stop")}
+ className="text-orange-600 dark:text-orange-500"
+ >
+
+ Stop All
+
+ setConfirmAction("delete")}
+ >
+
+ Delete All
+
+
+
+
+ ) : canStartAll ? (
+
+
+ handleAction("start", () => deployService(service.id))
}
>
-
-
-
- setConfirmAction("delete")}
+
+ {isLoading === "start" ? "Starting..." : "Start All"}
+
+
+
+ }
>
-
- Delete All
-
-
-
-
+
+
+
+ setConfirmAction("delete")}
+ >
+
+ Delete All
+
+
+
+
+ ) : undefined
) : undefined
- ) : undefined
- }
- />
+ }
+ />
+
r[0]);
if (githubRepo) {
- const baseUrl =
- process.env.APP_URL || "https://cloud.techulus.com";
+ const baseUrl = process.env.APP_URL || "https://cloud.techulus.com";
const logUrl = `${baseUrl}/builds/${buildId}/logs`;
if (
diff --git a/web/components/builds/build-details.tsx b/web/components/builds/build-details.tsx
index e942a0a..0f0b27f 100644
--- a/web/components/builds/build-details.tsx
+++ b/web/components/builds/build-details.tsx
@@ -309,7 +309,11 @@ export function BuildDetails({
Build Failed
- {build.error}
+
+
+ {build.error}
+
+
)}
diff --git a/web/components/builds/builds-viewer.tsx b/web/components/builds/builds-viewer.tsx
index 9d724f3..8d53766 100644
--- a/web/components/builds/builds-viewer.tsx
+++ b/web/components/builds/builds-viewer.tsx
@@ -285,9 +285,9 @@ export function BuildsViewer({
)}
{build.error && (
-
+
)}
e.stopPropagation()}>
diff --git a/web/components/service/create-service-dialog.tsx b/web/components/service/create-service-dialog.tsx
index 685a454..dc74668 100644
--- a/web/components/service/create-service-dialog.tsx
+++ b/web/components/service/create-service-dialog.tsx
@@ -188,8 +188,8 @@ export function CreateDockerServiceDialog({
/>
{error && {error}
}
- Supported: Docker Hub, GitHub Container Registry (ghcr.io), or
- any public registry
+ Supported: Docker Hub, GitHub Container Registry (ghcr.io), or any
+ public registry
diff --git a/web/components/service/details/deployment-progress.tsx b/web/components/service/details/deployment-progress.tsx
index fe073c8..a561cbf 100644
--- a/web/components/service/details/deployment-progress.tsx
+++ b/web/components/service/details/deployment-progress.tsx
@@ -129,9 +129,7 @@ export function getBarState(
const maxStageIndex = Math.max(
...service.deployments
.filter((d) => inProgressStatuses.includes(d.status))
- .map((d) =>
- getStageIndex(mapDeploymentStatusToStage(d.status)),
- ),
+ .map((d) => getStageIndex(mapDeploymentStatusToStage(d.status))),
);
return {
mode: "deploying",
@@ -252,9 +250,7 @@ export const DeploymentProgress = memo(function DeploymentProgress({
-
- Building
-
+
Building
{BUILD_STATUS_LABELS[barState.buildStatus] || "Building"}
@@ -306,9 +302,7 @@ export const DeploymentProgress = memo(function DeploymentProgress({
{isMigrating ? "Migrating" : "Deploying"}
-
- {status}
-
+
{status}
{isMigrating ? (
@@ -343,7 +337,7 @@ export const DeploymentProgress = memo(function DeploymentProgress({
opacity: isVisible ? 1 : 0,
}}
>
- {content}
+ {content}
);
});
diff --git a/web/components/service/details/pending-changes-banner.tsx b/web/components/service/details/pending-changes-banner.tsx
index 6a3b010..6d2e09e 100644
--- a/web/components/service/details/pending-changes-banner.tsx
+++ b/web/components/service/details/pending-changes-banner.tsx
@@ -39,7 +39,8 @@ export const PendingChangesBanner = memo(function PendingChangesBanner({
const hasChanges = changes.length > 0;
const showBanner =
- barMode === "ready" && (hasChanges || (hasNoDeployments && totalReplicas > 0));
+ barMode === "ready" &&
+ (hasChanges || (hasNoDeployments && totalReplicas > 0));
const handleDeploy = async () => {
setIsDeploying(true);
@@ -66,7 +67,7 @@ export const PendingChangesBanner = memo(function PendingChangesBanner({
opacity: showBanner ? 1 : 0,
}}
>
-
+
@@ -93,7 +94,9 @@ export const PendingChangesBanner = memo(function PendingChangesBanner({
{change.from}
-
{change.to}
+
+ {change.to}
+
))}
diff --git a/web/components/service/details/rollout-details.tsx b/web/components/service/details/rollout-details.tsx
index 2c518f3..ef7eb90 100644
--- a/web/components/service/details/rollout-details.tsx
+++ b/web/components/service/details/rollout-details.tsx
@@ -123,9 +123,7 @@ export function RolloutDetails({
-
+
{config.label}
{rollout.currentStage && isLive && (
diff --git a/web/components/service/details/rollout-history.tsx b/web/components/service/details/rollout-history.tsx
index ab58a76..1c39224 100644
--- a/web/components/service/details/rollout-history.tsx
+++ b/web/components/service/details/rollout-history.tsx
@@ -1,12 +1,7 @@
"use client";
-import {
- CheckCircle2,
- Clock,
- Loader2,
- RotateCcw,
- XCircle,
-} from "lucide-react";
+import { useState } from "react";
+import { CheckCircle2, Clock, Loader2, RotateCcw, XCircle } from "lucide-react";
import Link from "next/link";
import useSWR from "swr";
import {
@@ -118,11 +113,19 @@ export function RolloutHistory({
envName: string;
actions?: React.ReactNode;
}) {
+ const [hasInProgress, setHasInProgress] = useState(false);
+
const { data, isLoading } = useSWR<{ rollouts: RolloutListItem[] }>(
`/api/services/${serviceId}/rollouts`,
fetcher,
{
- refreshInterval: 10000,
+ refreshInterval: hasInProgress ? 3000 : 30000,
+ revalidateOnFocus: true,
+ onSuccess: (data) => {
+ setHasInProgress(
+ data?.rollouts?.some((r) => r.status === "in_progress") ?? false,
+ );
+ },
},
);
@@ -174,10 +177,7 @@ export function RolloutHistory({
{formatRelativeTime(rollout.createdAt)}
Duration:{" "}
- {formatDuration(
- rollout.createdAt,
- rollout.completedAt,
- )}
+ {formatDuration(rollout.createdAt, rollout.completedAt)}
diff --git a/web/components/service/details/source-section.tsx b/web/components/service/details/source-section.tsx
index 6c0ef04..cf0c2d6 100644
--- a/web/components/service/details/source-section.tsx
+++ b/web/components/service/details/source-section.tsx
@@ -144,11 +144,7 @@ export const SourceSection = memo(function SourceSection({
{!isEditing && (
-
+
Edit
@@ -188,7 +184,11 @@ export const SourceSection = memo(function SourceSection({
-
+
{isSaving && (
)}
@@ -254,18 +254,10 @@ export const SourceSection = memo(function SourceSection({
{!isEditing && (
-
+
Edit
-
+
Connect GitHub
@@ -299,9 +291,7 @@ export const SourceSection = memo(function SourceSection({
disabled={isSaving || !image.trim()}
size="sm"
>
- {isSaving && (
-
- )}
+ {isSaving && }
Save
(`/api/projects/${projectId}/services`, fetcher, {
- refreshInterval: 5000,
+ refreshInterval: hasActiveActivity ? 3000 : 10000,
revalidateOnFocus: true,
+ onSuccess: (data) => {
+ const svc = data?.find((s) => s.id === serviceId);
+ if (!svc) return;
+ const isActive =
+ (svc.latestBuild != null &&
+ ACTIVE_BUILD_STATUSES.includes(svc.latestBuild.status)) ||
+ svc.rollouts?.[0]?.status === "in_progress" ||
+ !!svc.migrationStatus ||
+ svc.deployments.some((d) =>
+ IN_PROGRESS_DEPLOY_STATUSES.includes(d.status),
+ );
+ setHasActiveActivity(isActive);
+ },
});
const service = services?.find((s) => s.id === serviceId);
@@ -69,6 +104,7 @@ export function ServiceLayoutClient({
}, [service]);
const handleActionComplete = useCallback(() => {
+ setHasActiveActivity(true);
mutate();
}, [mutate]);
diff --git a/web/lib/agent-status.ts b/web/lib/agent-status.ts
index 7431054..f8e0f10 100644
--- a/web/lib/agent-status.ts
+++ b/web/lib/agent-status.ts
@@ -247,7 +247,12 @@ export async function applyStatusReport(
);
if (deployment.rolloutId) {
- await ingestRolloutLog(deployment.rolloutId, deployment.serviceId, "deploying", `Deployment ${deployment.id} starting on server ${serverId}`);
+ await ingestRolloutLog(
+ deployment.rolloutId,
+ deployment.serviceId,
+ "deploying",
+ `Deployment ${deployment.id} starting on server ${serverId}`,
+ );
}
if (!hasHealthCheck) {
@@ -313,7 +318,12 @@ export async function applyStatusReport(
.where(eq(deployments.id, deployment.id));
if (deployment.rolloutId) {
- await ingestRolloutLog(deployment.rolloutId, deployment.serviceId, "health_check", `Deployment ${deployment.id} is healthy`);
+ await ingestRolloutLog(
+ deployment.rolloutId,
+ deployment.serviceId,
+ "health_check",
+ `Deployment ${deployment.id} is healthy`,
+ );
await inngest.send({
name: "deployment/healthy",
data: {
@@ -353,7 +363,12 @@ export async function applyStatusReport(
.where(eq(deployments.id, deployment.id));
if (deployment.rolloutId) {
- await ingestRolloutLog(deployment.rolloutId, deployment.serviceId, "health_check", `Deployment ${deployment.id} failed health check`);
+ await ingestRolloutLog(
+ deployment.rolloutId,
+ deployment.serviceId,
+ "health_check",
+ `Deployment ${deployment.id} failed health check`,
+ );
await inngest.send({
name: "deployment/failed",
data: {
@@ -379,7 +394,12 @@ export async function applyStatusReport(
);
for (const rollout of rolloutsInDnsSync) {
- await ingestRolloutLog(rollout.id, "", "dns_sync", `DNS synced on server ${serverId}`);
+ await ingestRolloutLog(
+ rollout.id,
+ "",
+ "dns_sync",
+ `DNS synced on server ${serverId}`,
+ );
await inngest.send({
name: "server/dns-synced",
data: {
diff --git a/web/lib/fetcher.ts b/web/lib/fetcher.ts
index a2b2a63..c34abd8 100644
--- a/web/lib/fetcher.ts
+++ b/web/lib/fetcher.ts
@@ -1,2 +1,2 @@
export const fetcher = (url: string): Promise =>
- fetch(url).then((res) => res.json());
+ fetch(url, { cache: "no-store" }).then((res) => res.json());
diff --git a/web/lib/inngest/functions/build-trigger-workflow.ts b/web/lib/inngest/functions/build-trigger-workflow.ts
index a19cb19..43fe37f 100644
--- a/web/lib/inngest/functions/build-trigger-workflow.ts
+++ b/web/lib/inngest/functions/build-trigger-workflow.ts
@@ -1,5 +1,4 @@
import { randomUUID } from "node:crypto";
-import { eq, and } from "drizzle-orm";
import { db } from "@/db";
import { builds } from "@/db/schema";
import { inngest } from "../client";
@@ -12,6 +11,7 @@ import { enqueueWork } from "@/lib/work-queue";
export const buildTriggerWorkflow = inngest.createFunction(
{
id: "build-trigger-workflow",
+ concurrency: [{ limit: 1, key: "event.data.serviceId" }],
},
{ event: "build/trigger" },
async ({ event, step }) => {
@@ -25,22 +25,6 @@ export const buildTriggerWorkflow = inngest.createFunction(
githubDeploymentId,
} = event.data;
- const pendingBuild = await step.run("check-pending-build", async () => {
- const existing = await db
- .select()
- .from(builds)
- .where(
- and(eq(builds.serviceId, serviceId), eq(builds.status, "pending")),
- )
- .then((r) => r[0]);
-
- return !!existing;
- });
-
- if (pendingBuild) {
- return { status: "skipped", reason: "build_already_pending" };
- }
-
const { buildIds, buildGroupId } = await step.run(
"create-builds",
async () => {
diff --git a/web/lib/inngest/functions/on-deployment-failed.ts b/web/lib/inngest/functions/on-deployment-failed.ts
index 620cf17..f7c18bd 100644
--- a/web/lib/inngest/functions/on-deployment-failed.ts
+++ b/web/lib/inngest/functions/on-deployment-failed.ts
@@ -21,7 +21,12 @@ export const onDeploymentFailed = inngest.createFunction(
if (!rollout || rollout.status !== "in_progress") return;
- await ingestRolloutLog(rolloutId, serviceId, reason, `Rollout failed: ${reason}`);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ reason,
+ `Rollout failed: ${reason}`,
+ );
await step.sendEvent("cancel-rollout", {
name: "rollout/cancelled",
diff --git a/web/lib/inngest/functions/rollout-helpers.ts b/web/lib/inngest/functions/rollout-helpers.ts
index 51538aa..cfbd4d7 100644
--- a/web/lib/inngest/functions/rollout-helpers.ts
+++ b/web/lib/inngest/functions/rollout-helpers.ts
@@ -78,42 +78,6 @@ export async function allocateHostPorts(
return allocated;
}
-export async function validateDeploymentPreconditions(
- serviceId: string,
-): Promise<{
- valid: boolean;
- error?: string;
- migrationNeeded?: { targetServerId: string };
-}> {
- const service = await getService(serviceId);
- if (!service) {
- return { valid: false, error: "Service not found" };
- }
-
- const existingDeployments = await db
- .select()
- .from(deployments)
- .where(eq(deployments.serviceId, serviceId));
-
- const inProgressStatuses = [
- "pending",
- "pulling",
- "starting",
- "healthy",
- "stopping",
- ];
-
- const hasInProgressDeployment = existingDeployments.some((d) =>
- inProgressStatuses.includes(d.status),
- );
-
- if (hasInProgressDeployment) {
- return { valid: false, error: "A deployment is already in progress" };
- }
-
- return { valid: true };
-}
-
export async function calculateServicePlacements(
service: NonNullable>>,
): Promise<{
@@ -285,6 +249,8 @@ export async function issueCertificatesForService(
.filter((p) => p.isPublic && p.domain)
.map((p) => p.domain as string);
+ const failedDomains: string[] = [];
+
for (const domain of domainsNeedingCerts) {
const existingCert = await getCertificate(domain);
if (!existingCert) {
@@ -296,9 +262,16 @@ export async function issueCertificatesForService(
`[deploy] failed to issue certificate for ${domain}:`,
error,
);
+ failedDomains.push(domain);
}
}
}
+
+ if (failedDomains.length > 0) {
+ throw new Error(
+ `Certificate provisioning failed for: ${failedDomains.join(", ")}`,
+ );
+ }
}
export async function createDeploymentRecords(
diff --git a/web/lib/inngest/functions/rollout-workflow.ts b/web/lib/inngest/functions/rollout-workflow.ts
index 4695b4f..5cc51ee 100644
--- a/web/lib/inngest/functions/rollout-workflow.ts
+++ b/web/lib/inngest/functions/rollout-workflow.ts
@@ -19,6 +19,7 @@ import {
export const rolloutWorkflow = inngest.createFunction(
{
id: "rollout-workflow",
+ concurrency: [{ limit: 1, key: "event.data.serviceId" }],
cancelOn: [{ event: "rollout/cancelled", match: "data.rolloutId" }],
},
{ event: "rollout/created" },
@@ -37,7 +38,12 @@ export const rolloutWorkflow = inngest.createFunction(
.update(rollouts)
.set({ status: "in_progress", currentStage: "preparing" })
.where(eq(rollouts.id, rolloutId));
- await ingestRolloutLog(rolloutId, serviceId, "preparing", "Rollout started");
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "preparing",
+ "Rollout started",
+ );
});
const { placements, totalReplicas } = await step.run(
@@ -48,7 +54,12 @@ export const rolloutWorkflow = inngest.createFunction(
throw new Error("Service not found");
}
const result = await calculateServicePlacements(service);
- await ingestRolloutLog(rolloutId, serviceId, "preparing", `Calculated placements: ${result.totalReplicas} replica(s)`);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "preparing",
+ `Calculated placements: ${result.totalReplicas} replica(s)`,
+ );
return result;
},
);
@@ -56,7 +67,12 @@ export const rolloutWorkflow = inngest.createFunction(
const serverIds = await step.run("validate-servers", async () => {
const serverMap = await validateServers(placements);
const ids = [...serverMap.keys()];
- await ingestRolloutLog(rolloutId, serviceId, "preparing", `Validated ${ids.length} server(s)`);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "preparing",
+ `Validated ${ids.length} server(s)`,
+ );
return ids;
});
@@ -67,24 +83,64 @@ export const rolloutWorkflow = inngest.createFunction(
if (isRollingUpdate) {
await step.run("prepare-rolling-update", async () => {
await prepareRollingUpdate(serviceId);
- await ingestRolloutLog(rolloutId, serviceId, "preparing", "Prepared rolling update");
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "preparing",
+ "Prepared rolling update",
+ );
});
} else {
await step.run("cleanup-existing", async () => {
await cleanupExistingDeployments(serviceId);
- await ingestRolloutLog(rolloutId, serviceId, "preparing", "Cleaned up existing deployments");
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "preparing",
+ "Cleaned up existing deployments",
+ );
});
}
- await step.run("issue-certificates", async () => {
+ const certResult = await step.run("issue-certificates", async () => {
await db
.update(rollouts)
.set({ currentStage: "certificates" })
.where(eq(rollouts.id, rolloutId));
- await issueCertificatesForService(serviceId);
- await ingestRolloutLog(rolloutId, serviceId, "certificates", "Certificates issued");
+ try {
+ await issueCertificatesForService(serviceId);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "certificates",
+ "Certificates issued",
+ );
+ return { success: true as const };
+ } catch (error) {
+ const message =
+ error instanceof Error
+ ? error.message
+ : "Certificate provisioning failed";
+ await ingestRolloutLog(rolloutId, serviceId, "certificates", message);
+ return { success: false as const, reason: message };
+ }
});
+ if (!certResult.success) {
+ await step.run("handle-certificate-failure", async () => {
+ await handleRolloutFailure(
+ rolloutId,
+ serviceId,
+ "certificate_provisioning_failed",
+ isRollingUpdate,
+ );
+ });
+ return {
+ status: "failed",
+ reason: certResult.reason,
+ };
+ }
+
const { deploymentIds } = await step.run("create-deployments", async () => {
await db
.update(rollouts)
@@ -106,7 +162,12 @@ export const rolloutWorkflow = inngest.createFunction(
isRollingUpdate,
});
- await ingestRolloutLog(rolloutId, serviceId, "deploying", `Created ${result.deploymentIds.length} deployment(s)`);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "deploying",
+ `Created ${result.deploymentIds.length} deployment(s)`,
+ );
return result;
});
@@ -133,7 +194,12 @@ export const rolloutWorkflow = inngest.createFunction(
.update(rollouts)
.set({ currentStage: "health_check" })
.where(eq(rollouts.id, rolloutId));
- await ingestRolloutLog(rolloutId, serviceId, "health_check", "Waiting for health checks");
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "health_check",
+ "Waiting for health checks",
+ );
});
const healthResults = await Promise.all(
@@ -150,7 +216,12 @@ export const rolloutWorkflow = inngest.createFunction(
if (timedOutIndex !== -1) {
const failedDeploymentId = deploymentIds[timedOutIndex];
await step.run("log-health-timeout", async () => {
- await ingestRolloutLog(rolloutId, serviceId, "health_check", `Health check timed out for deployment ${failedDeploymentId}`);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "health_check",
+ `Health check timed out for deployment ${failedDeploymentId}`,
+ );
});
await step.run("handle-health-timeout", async () => {
await handleRolloutFailure(
@@ -193,7 +264,12 @@ export const rolloutWorkflow = inngest.createFunction(
),
);
- await ingestRolloutLog(rolloutId, serviceId, "dns_sync", "Routing traffic to new deployments");
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "dns_sync",
+ "Routing traffic to new deployments",
+ );
});
const dnsResults = await Promise.all(
@@ -212,7 +288,12 @@ export const rolloutWorkflow = inngest.createFunction(
`[rollout:${rolloutId}] DNS sync timeout for server ${serverIds[i]}`,
);
await step.run(`log-dns-timeout-${serverIds[i]}`, async () => {
- await ingestRolloutLog(rolloutId, serviceId, "dns_sync", `DNS sync timed out for server ${serverIds[i]}`);
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "dns_sync",
+ `DNS sync timed out for server ${serverIds[i]}`,
+ );
});
}
}
@@ -226,7 +307,12 @@ export const rolloutWorkflow = inngest.createFunction(
completedAt: new Date(),
})
.where(eq(rollouts.id, rolloutId));
- await ingestRolloutLog(rolloutId, serviceId, "completed", "Rollout completed successfully");
+ await ingestRolloutLog(
+ rolloutId,
+ serviceId,
+ "completed",
+ "Rollout completed successfully",
+ );
});
return { status: "completed", rolloutId };