feat: Autodeploy pause
This commit is contained in:
19
prisma/migrations/20220311213422_autodeploy/migration.sql
Normal file
19
prisma/migrations/20220311213422_autodeploy/migration.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-- RedefineTables
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_ApplicationSettings" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"applicationId" TEXT NOT NULL,
|
||||||
|
"dualCerts" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"debug" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"previews" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"autodeploy" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
CONSTRAINT "ApplicationSettings_applicationId_fkey" FOREIGN KEY ("applicationId") REFERENCES "Application" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
INSERT INTO "new_ApplicationSettings" ("applicationId", "createdAt", "debug", "dualCerts", "id", "previews", "updatedAt") SELECT "applicationId", "createdAt", "debug", "dualCerts", "id", "previews", "updatedAt" FROM "ApplicationSettings";
|
||||||
|
DROP TABLE "ApplicationSettings";
|
||||||
|
ALTER TABLE "new_ApplicationSettings" RENAME TO "ApplicationSettings";
|
||||||
|
CREATE UNIQUE INDEX "ApplicationSettings_applicationId_key" ON "ApplicationSettings"("applicationId");
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
PRAGMA foreign_keys=ON;
|
@@ -104,6 +104,7 @@ model ApplicationSettings {
|
|||||||
dualCerts Boolean @default(false)
|
dualCerts Boolean @default(false)
|
||||||
debug Boolean @default(false)
|
debug Boolean @default(false)
|
||||||
previews Boolean @default(false)
|
previews Boolean @default(false)
|
||||||
|
autodeploy Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
@@ -71,7 +71,7 @@ export async function removeApplication({ id, teamId }) {
|
|||||||
export async function getApplicationWebhook({ projectId, branch }) {
|
export async function getApplicationWebhook({ projectId, branch }) {
|
||||||
try {
|
try {
|
||||||
let applications = await prisma.application.findMany({
|
let applications = await prisma.application.findMany({
|
||||||
where: { projectId, branch },
|
where: { projectId, branch, settings: { autodeploy: true } },
|
||||||
include: {
|
include: {
|
||||||
destinationDocker: true,
|
destinationDocker: true,
|
||||||
settings: true,
|
settings: true,
|
||||||
@@ -158,24 +158,41 @@ export async function getApplication({ id, teamId }) {
|
|||||||
return { ...body };
|
return { ...body };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureGitRepository({ id, repository, branch, projectId, webhookToken }) {
|
export async function configureGitRepository({
|
||||||
|
id,
|
||||||
|
repository,
|
||||||
|
branch,
|
||||||
|
projectId,
|
||||||
|
webhookToken,
|
||||||
|
autodeploy
|
||||||
|
}) {
|
||||||
if (webhookToken) {
|
if (webhookToken) {
|
||||||
const encryptedWebhookToken = encrypt(webhookToken);
|
const encryptedWebhookToken = encrypt(webhookToken);
|
||||||
return await prisma.application.update({
|
await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
repository,
|
repository,
|
||||||
branch,
|
branch,
|
||||||
projectId,
|
projectId,
|
||||||
gitSource: { update: { gitlabApp: { update: { webhookToken: encryptedWebhookToken } } } }
|
gitSource: { update: { gitlabApp: { update: { webhookToken: encryptedWebhookToken } } } },
|
||||||
|
settings: { update: { autodeploy } }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return await prisma.application.update({
|
await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { repository, branch, projectId }
|
data: { repository, branch, projectId, settings: { update: { autodeploy } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!autodeploy) {
|
||||||
|
const applications = await prisma.application.findMany({ where: { branch, projectId } });
|
||||||
|
for (const application of applications) {
|
||||||
|
await prisma.applicationSettings.updateMany({
|
||||||
|
where: { applicationId: application.id },
|
||||||
|
data: { autodeploy: false }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureBuildPack({ id, buildPack }) {
|
export async function configureBuildPack({ id, buildPack }) {
|
||||||
@@ -210,10 +227,14 @@ export async function configureApplication({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setApplicationSettings({ id, debug, previews, dualCerts }) {
|
export async function checkDoubleBranch(branch, projectId) {
|
||||||
|
const applications = await prisma.application.findMany({ where: { branch, projectId } });
|
||||||
|
return applications.length > 1;
|
||||||
|
}
|
||||||
|
export async function setApplicationSettings({ id, debug, previews, dualCerts, autodeploy }) {
|
||||||
return await prisma.application.update({
|
return await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { settings: { update: { debug, previews, dualCerts } } },
|
data: { settings: { update: { debug, previews, dualCerts, autodeploy } } },
|
||||||
include: { destinationDocker: true }
|
include: { destinationDocker: true }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
branch: undefined
|
branch: undefined
|
||||||
};
|
};
|
||||||
let showSave = false;
|
let showSave = false;
|
||||||
|
let autodeploy = application.settings.autodeploy || true;
|
||||||
|
|
||||||
async function loadRepositoriesByPage(page = 0) {
|
async function loadRepositoriesByPage(page = 0) {
|
||||||
return await get(`${apiUrl}/installation/repositories?per_page=100&page=${page}`, {
|
return await get(`${apiUrl}/installation/repositories?per_page=100&page=${page}`, {
|
||||||
Authorization: `token ${$gitTokens.githubToken}`
|
Authorization: `token ${$gitTokens.githubToken}`
|
||||||
@@ -69,7 +71,14 @@
|
|||||||
`/applications/${id}/configuration/repository.json?repository=${selected.repository}&branch=${selected.branch}`
|
`/applications/${id}/configuration/repository.json?repository=${selected.repository}&branch=${selected.branch}`
|
||||||
);
|
);
|
||||||
if (data.used) {
|
if (data.used) {
|
||||||
errorNotification('This branch is already used by another application.');
|
const sure = confirm(
|
||||||
|
`This branch is already used by another application. Webhooks won't work in this case for both applications. Are you sure you want to use it?`
|
||||||
|
);
|
||||||
|
if (sure) {
|
||||||
|
autodeploy = false;
|
||||||
|
showSave = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
showSave = false;
|
showSave = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -172,7 +181,7 @@
|
|||||||
class="w-96"
|
class="w-96"
|
||||||
disabled={!selected.repository}
|
disabled={!selected.repository}
|
||||||
bind:value={selected.branch}
|
bind:value={selected.branch}
|
||||||
on:change={() => (showSave = true)}
|
on:change={isBranchAlreadyUsed}
|
||||||
>
|
>
|
||||||
{#if !selected.repository}
|
{#if !selected.repository}
|
||||||
<option value="" disabled selected>Select a repository first</option>
|
<option value="" disabled selected>Select a repository first</option>
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
let projects = [];
|
let projects = [];
|
||||||
let branches = [];
|
let branches = [];
|
||||||
let showSave = false;
|
let showSave = false;
|
||||||
|
let autodeploy = application.settings.autodeploy || true;
|
||||||
|
|
||||||
let selected = {
|
let selected = {
|
||||||
group: undefined,
|
group: undefined,
|
||||||
@@ -138,7 +139,14 @@
|
|||||||
`/applications/${id}/configuration/repository.json?repository=${selected.project.path_with_namespace}&branch=${selected.branch.name}`
|
`/applications/${id}/configuration/repository.json?repository=${selected.project.path_with_namespace}&branch=${selected.branch.name}`
|
||||||
);
|
);
|
||||||
if (data.used) {
|
if (data.used) {
|
||||||
errorNotification('This branch is already used by another application.');
|
const sure = confirm(
|
||||||
|
`This branch is already used by another application. Webhooks won't work in this case for both applications. Are you sure you want to use it?`
|
||||||
|
);
|
||||||
|
if (sure) {
|
||||||
|
autodeploy = false;
|
||||||
|
showSave = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
showSave = false;
|
showSave = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -242,6 +250,7 @@
|
|||||||
repository,
|
repository,
|
||||||
branch: selected.branch.name,
|
branch: selected.branch.name,
|
||||||
projectId: selected.project.id,
|
projectId: selected.project.id,
|
||||||
|
autodeploy,
|
||||||
webhookToken
|
webhookToken
|
||||||
});
|
});
|
||||||
return await goto(from || `/applications/${id}/configuration/buildpack`);
|
return await goto(from || `/applications/${id}/configuration/buildpack`);
|
||||||
@@ -305,7 +314,7 @@
|
|||||||
name="branch"
|
name="branch"
|
||||||
class="w-96"
|
class="w-96"
|
||||||
bind:value={selected.branch}
|
bind:value={selected.branch}
|
||||||
on:change={() => (showSave = true)}
|
on:change={isBranchAlreadyUsed}
|
||||||
disabled={!selected.project}
|
disabled={!selected.project}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected>Please select a branch</option>
|
<option value="" disabled selected>Please select a branch</option>
|
||||||
|
@@ -30,14 +30,21 @@ export const post: RequestHandler = async (event) => {
|
|||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
let { repository, branch, projectId, webhookToken } = await event.request.json();
|
let { repository, branch, projectId, webhookToken, autodeploy } = await event.request.json();
|
||||||
|
|
||||||
repository = repository.toLowerCase();
|
repository = repository.toLowerCase();
|
||||||
branch = branch.toLowerCase();
|
branch = branch.toLowerCase();
|
||||||
projectId = Number(projectId);
|
projectId = Number(projectId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.configureGitRepository({ id, repository, branch, projectId, webhookToken });
|
await db.configureGitRepository({
|
||||||
|
id,
|
||||||
|
repository,
|
||||||
|
branch,
|
||||||
|
projectId,
|
||||||
|
webhookToken,
|
||||||
|
autodeploy
|
||||||
|
});
|
||||||
return { status: 201 };
|
return { status: 201 };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
|
@@ -56,6 +56,7 @@
|
|||||||
let debug = application.settings.debug;
|
let debug = application.settings.debug;
|
||||||
let previews = application.settings.previews;
|
let previews = application.settings.previews;
|
||||||
let dualCerts = application.settings.dualCerts;
|
let dualCerts = application.settings.dualCerts;
|
||||||
|
let autodeploy = application.settings.autodeploy;
|
||||||
|
|
||||||
if (browser && window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
|
if (browser && window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
|
||||||
application.fqdn = `http://${cuid()}.demo.coolify.io`;
|
application.fqdn = `http://${cuid()}.demo.coolify.io`;
|
||||||
@@ -75,10 +76,32 @@
|
|||||||
if (name === 'dualCerts') {
|
if (name === 'dualCerts') {
|
||||||
dualCerts = !dualCerts;
|
dualCerts = !dualCerts;
|
||||||
}
|
}
|
||||||
|
if (name === 'autodeploy') {
|
||||||
|
autodeploy = !autodeploy;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await post(`/applications/${id}/settings.json`, { previews, debug, dualCerts });
|
await post(`/applications/${id}/settings.json`, {
|
||||||
|
previews,
|
||||||
|
debug,
|
||||||
|
dualCerts,
|
||||||
|
autodeploy,
|
||||||
|
branch: application.branch,
|
||||||
|
projectId: application.projectId
|
||||||
|
});
|
||||||
return toast.push('Settings saved.');
|
return toast.push('Settings saved.');
|
||||||
} catch ({ error }) {
|
} catch ({ error }) {
|
||||||
|
if (name === 'debug') {
|
||||||
|
debug = !debug;
|
||||||
|
}
|
||||||
|
if (name === 'previews') {
|
||||||
|
previews = !previews;
|
||||||
|
}
|
||||||
|
if (name === 'dualCerts') {
|
||||||
|
dualCerts = !dualCerts;
|
||||||
|
}
|
||||||
|
if (name === 'autodeploy') {
|
||||||
|
autodeploy = !autodeploy;
|
||||||
|
}
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,22 +406,23 @@
|
|||||||
<div class="flex space-x-1 pb-5 font-bold">
|
<div class="flex space-x-1 pb-5 font-bold">
|
||||||
<div class="title">Features</div>
|
<div class="title">Features</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <ul class="mt-2 divide-y divide-stone-800">
|
|
||||||
<Setting
|
|
||||||
bind:setting={forceSSL}
|
|
||||||
on:click={() => changeSettings('forceSSL')}
|
|
||||||
title="Force https"
|
|
||||||
description="Creates a https redirect for all requests from http and also generates a https certificate for the domain through Let's Encrypt."
|
|
||||||
/>
|
|
||||||
</ul> -->
|
|
||||||
<div class="px-10 pb-10">
|
<div class="px-10 pb-10">
|
||||||
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
<Setting
|
||||||
|
isCenter={false}
|
||||||
|
bind:setting={autodeploy}
|
||||||
|
on:click={() => changeSettings('autodeploy')}
|
||||||
|
title="Enable Automatic Deployment"
|
||||||
|
description="Enable automatic deployment through webhooks."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="grid grid-cols-2 items-center">
|
<div class="grid grid-cols-2 items-center">
|
||||||
<Setting
|
<Setting
|
||||||
isCenter={false}
|
isCenter={false}
|
||||||
bind:setting={previews}
|
bind:setting={previews}
|
||||||
on:click={() => changeSettings('previews')}
|
on:click={() => changeSettings('previews')}
|
||||||
title="Enable MR/PR Previews"
|
title="Enable MR/PR Previews"
|
||||||
description="Creates previews from pull and merge requests."
|
description="Enable preview deployments from pull or merge requests."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 items-center">
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
@@ -8,10 +8,17 @@ export const post: RequestHandler = async (event) => {
|
|||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
const { debug, previews, dualCerts } = await event.request.json();
|
const { debug, previews, dualCerts, autodeploy, branch, projectId } = await event.request.json();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.setApplicationSettings({ id, debug, previews, dualCerts });
|
const isDouble = await db.checkDoubleBranch(branch, projectId);
|
||||||
|
if (isDouble && autodeploy) {
|
||||||
|
throw {
|
||||||
|
message:
|
||||||
|
'Cannot activate automatic deployments until only one application is defined for this repository / branch.'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
await db.setApplicationSettings({ id, debug, previews, dualCerts, autodeploy });
|
||||||
return { status: 201 };
|
return { status: 201 };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
|
@@ -81,8 +81,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.digest('hex');
|
.digest('hex');
|
||||||
await db.prisma.application.updateMany({
|
await db.prisma.application.update({
|
||||||
where: { branch, projectId },
|
where: { id: application.id },
|
||||||
data: { configHash }
|
data: { configHash }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -45,8 +45,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.digest('hex');
|
.digest('hex');
|
||||||
await db.prisma.application.updateMany({
|
await db.prisma.application.update({
|
||||||
where: { branch, projectId },
|
where: { id: application.id },
|
||||||
data: { configHash }
|
data: { configHash }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user