From 464d58daaa68843b6b612f750e69d63219fc91d0 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Wed, 17 Sep 2025 18:23:21 +0200 Subject: [PATCH 1/2] feat(deployment): add support for Soft Serve webhooks --- .../pages/api/deploy/[refreshToken].ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/dokploy/pages/api/deploy/[refreshToken].ts b/apps/dokploy/pages/api/deploy/[refreshToken].ts index 2ab607736..0ce50cae2 100644 --- a/apps/dokploy/pages/api/deploy/[refreshToken].ts +++ b/apps/dokploy/pages/api/deploy/[refreshToken].ts @@ -159,6 +159,10 @@ export default async function handler( normalizedCommits = req.body?.commits?.flatMap( (commit: any) => commit.modified, ); + } else if (provider === "soft-serve") { + normalizedCommits = req.body?.commits?.flatMap( + (commit: any) => commit.modified, + ); } const shouldDeployPaths = shouldDeploy( @@ -442,6 +446,13 @@ export const extractCommitMessage = (headers: any, body: any) => { : "NEW COMMIT"; } + // Soft Serve + if (headers["x-softserve-event"]) { + return body.commits && body.commits.length > 0 + ? body.commits[0].message + : "NEW COMMIT"; + } + if (headers["user-agent"]?.includes("Go-http-client")) { if (body.push_data && body.repository) { return `DockerHub image pushed: ${body.repository.repo_name}:${body.push_data.tag} by ${body.push_data.pusher}`; @@ -479,6 +490,11 @@ export const extractHash = (headers: any, body: any) => { return body.after || "NEW COMMIT"; } + // Soft Serve + if (headers["x-softserve-event"]) { + return body.after || "NEW COMMIT"; + } + return ""; }; @@ -495,6 +511,10 @@ export const extractBranchName = (headers: any, body: any) => { return body?.push?.changes[0]?.new?.name; } + if (headers["x-softserve-event"]?.includes("push")) { + return body?.ref ? body?.ref.replace("refs/heads/", "") : null; + } + return null; }; @@ -515,6 +535,10 @@ export const getProviderByHeader = (headers: any) => { return "bitbucket"; } + if (headers["x-softserve-event"]) { + return "soft-serve"; + } + return null; }; From f5f21ef195fd98aabbf50492fa7a21242bc8b5c9 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Fri, 19 Sep 2025 18:27:53 +0200 Subject: [PATCH 2/2] test(deployment): add Soft Serve tests --- apps/dokploy/__test__/deploy/github.test.ts | 11 +++++ .../__test__/deploy/soft-serve.test.ts | 49 +++++++++++++++++++ .../pages/api/deploy/[refreshToken].ts | 9 ++-- 3 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 apps/dokploy/__test__/deploy/soft-serve.test.ts diff --git a/apps/dokploy/__test__/deploy/github.test.ts b/apps/dokploy/__test__/deploy/github.test.ts index 46be44883..d2e773dfc 100644 --- a/apps/dokploy/__test__/deploy/github.test.ts +++ b/apps/dokploy/__test__/deploy/github.test.ts @@ -83,6 +83,14 @@ describe("GitHub Webhook Skip CI", () => { { commits: [{ message: "[skip ci] test" }] }, ), ).toBe("[skip ci] test"); + + // Soft Serve + expect( + extractCommitMessage( + { "x-softserve-event": "push" }, + { commits: [{ message: "[skip ci] test" }] }, + ), + ).toBe("[skip ci] test"); }); it("should handle missing commit message", () => { @@ -99,6 +107,9 @@ describe("GitHub Webhook Skip CI", () => { expect(extractCommitMessage({ "x-gitea-event": "push" }, {})).toBe( "NEW COMMIT", ); + expect(extractCommitMessage({ "x-softserve-event": "push" }, {})).toBe( + "NEW COMMIT", + ); }); }); diff --git a/apps/dokploy/__test__/deploy/soft-serve.test.ts b/apps/dokploy/__test__/deploy/soft-serve.test.ts new file mode 100644 index 000000000..609f15dee --- /dev/null +++ b/apps/dokploy/__test__/deploy/soft-serve.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from "vitest"; +import { + extractBranchName, + extractCommitMessage, + extractHash, + getProviderByHeader, +} from "@/pages/api/deploy/[refreshToken]"; + +describe("Soft Serve Webhook", () => { + const mockSoftServeHeaders = { + "x-softserve-event": "push", + }; + + const createMockBody = (message: string, hash: string, branch: string) => ({ + event: "push", + ref: `refs/heads/${branch}`, + after: hash, + commits: [{ message: message }], + }); + const message: string = "feat: add new feature"; + const hash: string = "3c91c24ef9560bddc695bce138bf8a7094ec3df5"; + const branch: string = "feat/add-new"; + const goodWebhook = createMockBody(message, hash, branch); + + it("should properly extract the provider name", () => { + expect(getProviderByHeader(mockSoftServeHeaders)).toBe("soft-serve"); + }); + + it("should properly extract the commit message", () => { + expect(extractCommitMessage(mockSoftServeHeaders, goodWebhook)).toBe( + message, + ); + }); + + it("should properly extract hash", () => { + expect(extractHash(mockSoftServeHeaders, goodWebhook)).toBe(hash); + }); + + it("should properly extract branch name", () => { + expect(extractBranchName(mockSoftServeHeaders, goodWebhook)).toBe(branch); + }); + + it("should gracefully handle invalid webhook", () => { + expect(getProviderByHeader({})).toBeNull(); + expect(extractCommitMessage(mockSoftServeHeaders, {})).toBe("NEW COMMIT"); + expect(extractHash(mockSoftServeHeaders, {})).toBe("NEW COMMIT"); + expect(extractBranchName(mockSoftServeHeaders, {})).toBeNull(); + }); +}); diff --git a/apps/dokploy/pages/api/deploy/[refreshToken].ts b/apps/dokploy/pages/api/deploy/[refreshToken].ts index 0ce50cae2..32ffe63ec 100644 --- a/apps/dokploy/pages/api/deploy/[refreshToken].ts +++ b/apps/dokploy/pages/api/deploy/[refreshToken].ts @@ -503,7 +503,10 @@ export const extractBranchName = (headers: any, body: any) => { return body?.ref?.replace("refs/heads/", ""); } - if (headers["x-gitlab-event"]) { + if ( + headers["x-gitlab-event"] || + headers["x-softserve-event"]?.includes("push") + ) { return body?.ref ? body?.ref.replace("refs/heads/", "") : null; } @@ -511,10 +514,6 @@ export const extractBranchName = (headers: any, body: any) => { return body?.push?.changes[0]?.new?.name; } - if (headers["x-softserve-event"]?.includes("push")) { - return body?.ref ? body?.ref.replace("refs/heads/", "") : null; - } - return null; };