mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(github): add triggerType field to GitHub provider and handle tag creation events
This commit is contained in:
parent
0bdaa81263
commit
fcb8a2bded
@ -57,6 +57,7 @@ const GithubProviderSchema = z.object({
|
|||||||
branch: z.string().min(1, "Branch is required"),
|
branch: z.string().min(1, "Branch is required"),
|
||||||
githubId: z.string().min(1, "Github Provider is required"),
|
githubId: z.string().min(1, "Github Provider is required"),
|
||||||
watchPaths: z.array(z.string()).optional(),
|
watchPaths: z.array(z.string()).optional(),
|
||||||
|
triggerType: z.enum(["push", "tag"]).default("push"),
|
||||||
});
|
});
|
||||||
|
|
||||||
type GithubProvider = z.infer<typeof GithubProviderSchema>;
|
type GithubProvider = z.infer<typeof GithubProviderSchema>;
|
||||||
@ -124,6 +125,7 @@ export const SaveGithubProvider = ({ applicationId }: Props) => {
|
|||||||
buildPath: data.buildPath || "/",
|
buildPath: data.buildPath || "/",
|
||||||
githubId: data.githubId || "",
|
githubId: data.githubId || "",
|
||||||
watchPaths: data.watchPaths || [],
|
watchPaths: data.watchPaths || [],
|
||||||
|
triggerType: data.triggerType || "push",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [form.reset, data, form]);
|
}, [form.reset, data, form]);
|
||||||
@ -137,6 +139,7 @@ export const SaveGithubProvider = ({ applicationId }: Props) => {
|
|||||||
buildPath: data.buildPath,
|
buildPath: data.buildPath,
|
||||||
githubId: data.githubId,
|
githubId: data.githubId,
|
||||||
watchPaths: data.watchPaths || [],
|
watchPaths: data.watchPaths || [],
|
||||||
|
triggerType: data.triggerType,
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
toast.success("Service Provided Saved");
|
toast.success("Service Provided Saved");
|
||||||
@ -379,6 +382,45 @@ export const SaveGithubProvider = ({ applicationId }: Props) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="triggerType"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<FormLabel>Trigger Type</FormLabel>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>
|
||||||
|
Choose when to trigger deployments: on push to the selected branch or when a new tag is created.
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
defaultValue={field.value}
|
||||||
|
value={field.value}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a trigger type" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="push">On Push</SelectItem>
|
||||||
|
<SelectItem value="tag">On Tag</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="watchPaths"
|
name="watchPaths"
|
||||||
|
5
apps/dokploy/drizzle/0084_add_trigger_type.sql
Normal file
5
apps/dokploy/drizzle/0084_add_trigger_type.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
-- Add triggerType column to application table
|
||||||
|
ALTER TABLE "application" ADD COLUMN IF NOT EXISTS "triggerType" text DEFAULT 'push';
|
||||||
|
|
||||||
|
-- Add triggerType column to compose table
|
||||||
|
ALTER TABLE "compose" ADD COLUMN IF NOT EXISTS "triggerType" text DEFAULT 'push';
|
@ -62,11 +62,12 @@ export default async function handler(
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
req.headers["x-github-event"] !== "push" &&
|
req.headers["x-github-event"] !== "push" &&
|
||||||
req.headers["x-github-event"] !== "pull_request"
|
req.headers["x-github-event"] !== "pull_request" &&
|
||||||
|
req.headers["x-github-event"] !== "create"
|
||||||
) {
|
) {
|
||||||
res
|
res
|
||||||
.status(400)
|
.status(400)
|
||||||
.json({ message: "We only accept push events or pull_request events" });
|
.json({ message: "We only accept push, pull_request, or create events" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +90,106 @@ export default async function handler(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle tag creation event
|
||||||
|
if (req.headers["x-github-event"] === "create" && githubBody?.ref_type === "tag") {
|
||||||
|
try {
|
||||||
|
const tagName = githubBody?.ref;
|
||||||
|
const repository = githubBody?.repository?.name;
|
||||||
|
const owner = githubBody?.repository?.owner?.name || githubBody?.repository?.owner?.login;
|
||||||
|
const deploymentTitle = `Tag created: ${tagName}`;
|
||||||
|
const deploymentHash = githubBody?.master_branch || "";
|
||||||
|
|
||||||
|
// Find applications configured to deploy on tag
|
||||||
|
const apps = await db.query.applications.findMany({
|
||||||
|
where: and(
|
||||||
|
eq(applications.sourceType, "github"),
|
||||||
|
eq(applications.autoDeploy, true),
|
||||||
|
eq(applications.triggerType, "tag"),
|
||||||
|
eq(applications.repository, repository),
|
||||||
|
eq(applications.owner, owner),
|
||||||
|
eq(applications.githubId, githubResult.githubId),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const app of apps) {
|
||||||
|
const jobData: DeploymentJob = {
|
||||||
|
applicationId: app.applicationId as string,
|
||||||
|
titleLog: deploymentTitle,
|
||||||
|
descriptionLog: `Tag: ${tagName}`,
|
||||||
|
type: "deploy",
|
||||||
|
applicationType: "application",
|
||||||
|
server: !!app.serverId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (IS_CLOUD && app.serverId) {
|
||||||
|
jobData.serverId = app.serverId;
|
||||||
|
await deploy(jobData);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
await myQueue.add(
|
||||||
|
"deployments",
|
||||||
|
{ ...jobData },
|
||||||
|
{
|
||||||
|
removeOnComplete: true,
|
||||||
|
removeOnFail: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find compose apps configured to deploy on tag
|
||||||
|
const composeApps = await db.query.compose.findMany({
|
||||||
|
where: and(
|
||||||
|
eq(compose.sourceType, "github"),
|
||||||
|
eq(compose.autoDeploy, true),
|
||||||
|
eq(compose.triggerType, "tag"),
|
||||||
|
eq(compose.repository, repository),
|
||||||
|
eq(compose.owner, owner),
|
||||||
|
eq(compose.githubId, githubResult.githubId),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const composeApp of composeApps) {
|
||||||
|
const jobData: DeploymentJob = {
|
||||||
|
composeId: composeApp.composeId as string,
|
||||||
|
titleLog: deploymentTitle,
|
||||||
|
type: "deploy",
|
||||||
|
applicationType: "compose",
|
||||||
|
descriptionLog: `Tag: ${tagName}`,
|
||||||
|
server: !!composeApp.serverId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (IS_CLOUD && composeApp.serverId) {
|
||||||
|
jobData.serverId = composeApp.serverId;
|
||||||
|
await deploy(jobData);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await myQueue.add(
|
||||||
|
"deployments",
|
||||||
|
{ ...jobData },
|
||||||
|
{
|
||||||
|
removeOnComplete: true,
|
||||||
|
removeOnFail: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalApps = apps.length + composeApps.length;
|
||||||
|
|
||||||
|
if (totalApps === 0) {
|
||||||
|
res.status(200).json({ message: "No apps configured to deploy on tag" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({ message: `Deployed ${totalApps} apps based on tag ${tagName}` });
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deploying applications on tag:", error);
|
||||||
|
res.status(400).json({ message: "Error deploying applications on tag", error });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (req.headers["x-github-event"] === "push") {
|
if (req.headers["x-github-event"] === "push") {
|
||||||
try {
|
try {
|
||||||
const branchName = githubBody?.ref?.replace("refs/heads/", "");
|
const branchName = githubBody?.ref?.replace("refs/heads/", "");
|
||||||
@ -105,6 +206,7 @@ export default async function handler(
|
|||||||
where: and(
|
where: and(
|
||||||
eq(applications.sourceType, "github"),
|
eq(applications.sourceType, "github"),
|
||||||
eq(applications.autoDeploy, true),
|
eq(applications.autoDeploy, true),
|
||||||
|
eq(applications.triggerType, "push"),
|
||||||
eq(applications.branch, branchName),
|
eq(applications.branch, branchName),
|
||||||
eq(applications.repository, repository),
|
eq(applications.repository, repository),
|
||||||
eq(applications.owner, owner),
|
eq(applications.owner, owner),
|
||||||
@ -150,6 +252,7 @@ export default async function handler(
|
|||||||
where: and(
|
where: and(
|
||||||
eq(compose.sourceType, "github"),
|
eq(compose.sourceType, "github"),
|
||||||
eq(compose.autoDeploy, true),
|
eq(compose.autoDeploy, true),
|
||||||
|
eq(compose.triggerType, "push"),
|
||||||
eq(compose.branch, branchName),
|
eq(compose.branch, branchName),
|
||||||
eq(compose.repository, repository),
|
eq(compose.repository, repository),
|
||||||
eq(compose.owner, owner),
|
eq(compose.owner, owner),
|
||||||
|
@ -346,6 +346,7 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
applicationStatus: "idle",
|
applicationStatus: "idle",
|
||||||
githubId: input.githubId,
|
githubId: input.githubId,
|
||||||
watchPaths: input.watchPaths,
|
watchPaths: input.watchPaths,
|
||||||
|
triggerType: input.triggerType,
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -149,6 +149,7 @@ export const applications = pgTable("application", {
|
|||||||
owner: text("owner"),
|
owner: text("owner"),
|
||||||
branch: text("branch"),
|
branch: text("branch"),
|
||||||
buildPath: text("buildPath").default("/"),
|
buildPath: text("buildPath").default("/"),
|
||||||
|
triggerType: text("triggerType").default("push"),
|
||||||
autoDeploy: boolean("autoDeploy").$defaultFn(() => true),
|
autoDeploy: boolean("autoDeploy").$defaultFn(() => true),
|
||||||
// Gitlab
|
// Gitlab
|
||||||
gitlabProjectId: integer("gitlabProjectId"),
|
gitlabProjectId: integer("gitlabProjectId"),
|
||||||
@ -471,7 +472,10 @@ export const apiSaveGithubProvider = createSchema
|
|||||||
githubId: true,
|
githubId: true,
|
||||||
watchPaths: true,
|
watchPaths: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required()
|
||||||
|
.extend({
|
||||||
|
triggerType: z.enum(["push", "tag"]).default("push"),
|
||||||
|
});
|
||||||
|
|
||||||
export const apiSaveGitlabProvider = createSchema
|
export const apiSaveGitlabProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
|
@ -76,6 +76,7 @@ export const compose = pgTable("compose", {
|
|||||||
suffix: text("suffix").notNull().default(""),
|
suffix: text("suffix").notNull().default(""),
|
||||||
randomize: boolean("randomize").notNull().default(false),
|
randomize: boolean("randomize").notNull().default(false),
|
||||||
isolatedDeployment: boolean("isolatedDeployment").notNull().default(false),
|
isolatedDeployment: boolean("isolatedDeployment").notNull().default(false),
|
||||||
|
triggerType: text("triggerType").default("push"),
|
||||||
composeStatus: applicationStatus("composeStatus").notNull().default("idle"),
|
composeStatus: applicationStatus("composeStatus").notNull().default("idle"),
|
||||||
projectId: text("projectId")
|
projectId: text("projectId")
|
||||||
.notNull()
|
.notNull()
|
||||||
|
Loading…
Reference in New Issue
Block a user