feat: Autodeploy pause

This commit is contained in:
Andras Bacsai 2022-03-11 22:36:21 +01:00
parent 7c273a3a48
commit fa6cf068c7
10 changed files with 127 additions and 30 deletions

View 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;

View File

@ -104,6 +104,7 @@ model ApplicationSettings {
dualCerts Boolean @default(false)
debug Boolean @default(false)
previews Boolean @default(false)
autodeploy Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

View File

@ -71,7 +71,7 @@ export async function removeApplication({ id, teamId }) {
export async function getApplicationWebhook({ projectId, branch }) {
try {
let applications = await prisma.application.findMany({
where: { projectId, branch },
where: { projectId, branch, settings: { autodeploy: true } },
include: {
destinationDocker: true,
settings: true,
@ -158,24 +158,41 @@ export async function getApplication({ id, teamId }) {
return { ...body };
}
export async function configureGitRepository({ id, repository, branch, projectId, webhookToken }) {
export async function configureGitRepository({
id,
repository,
branch,
projectId,
webhookToken,
autodeploy
}) {
if (webhookToken) {
const encryptedWebhookToken = encrypt(webhookToken);
return await prisma.application.update({
await prisma.application.update({
where: { id },
data: {
repository,
branch,
projectId,
gitSource: { update: { gitlabApp: { update: { webhookToken: encryptedWebhookToken } } } }
gitSource: { update: { gitlabApp: { update: { webhookToken: encryptedWebhookToken } } } },
settings: { update: { autodeploy } }
}
});
} else {
return await prisma.application.update({
await prisma.application.update({
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 }) {
@ -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({
where: { id },
data: { settings: { update: { debug, previews, dualCerts } } },
data: { settings: { update: { debug, previews, dualCerts, autodeploy } } },
include: { destinationDocker: true }
});
}

View File

@ -28,6 +28,8 @@
branch: undefined
};
let showSave = false;
let autodeploy = application.settings.autodeploy || true;
async function loadRepositoriesByPage(page = 0) {
return await get(`${apiUrl}/installation/repositories?per_page=100&page=${page}`, {
Authorization: `token ${$gitTokens.githubToken}`
@ -69,7 +71,14 @@
`/applications/${id}/configuration/repository.json?repository=${selected.repository}&branch=${selected.branch}`
);
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;
return true;
}
@ -172,7 +181,7 @@
class="w-96"
disabled={!selected.repository}
bind:value={selected.branch}
on:change={() => (showSave = true)}
on:change={isBranchAlreadyUsed}
>
{#if !selected.repository}
<option value="" disabled selected>Select a repository first</option>

View File

@ -30,6 +30,7 @@
let projects = [];
let branches = [];
let showSave = false;
let autodeploy = application.settings.autodeploy || true;
let selected = {
group: undefined,
@ -138,7 +139,14 @@
`/applications/${id}/configuration/repository.json?repository=${selected.project.path_with_namespace}&branch=${selected.branch.name}`
);
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;
return true;
}
@ -242,6 +250,7 @@
repository,
branch: selected.branch.name,
projectId: selected.project.id,
autodeploy,
webhookToken
});
return await goto(from || `/applications/${id}/configuration/buildpack`);
@ -305,7 +314,7 @@
name="branch"
class="w-96"
bind:value={selected.branch}
on:change={() => (showSave = true)}
on:change={isBranchAlreadyUsed}
disabled={!selected.project}
>
<option value="" disabled selected>Please select a branch</option>

View File

@ -30,14 +30,21 @@ export const post: RequestHandler = async (event) => {
if (status === 401) return { status, body };
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();
branch = branch.toLowerCase();
projectId = Number(projectId);
try {
await db.configureGitRepository({ id, repository, branch, projectId, webhookToken });
await db.configureGitRepository({
id,
repository,
branch,
projectId,
webhookToken,
autodeploy
});
return { status: 201 };
} catch (error) {
return ErrorHandler(error);

View File

@ -56,6 +56,7 @@
let debug = application.settings.debug;
let previews = application.settings.previews;
let dualCerts = application.settings.dualCerts;
let autodeploy = application.settings.autodeploy;
if (browser && window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
application.fqdn = `http://${cuid()}.demo.coolify.io`;
@ -75,10 +76,32 @@
if (name === 'dualCerts') {
dualCerts = !dualCerts;
}
if (name === 'autodeploy') {
autodeploy = !autodeploy;
}
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.');
} 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);
}
}
@ -383,22 +406,23 @@
<div class="flex space-x-1 pb-5 font-bold">
<div class="title">Features</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="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">
<Setting
isCenter={false}
bind:setting={previews}
on:click={() => changeSettings('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 class="grid grid-cols-2 items-center">

View File

@ -8,10 +8,17 @@ export const post: RequestHandler = async (event) => {
if (status === 401) return { status, body };
const { id } = event.params;
const { debug, previews, dualCerts } = await event.request.json();
const { debug, previews, dualCerts, autodeploy, branch, projectId } = await event.request.json();
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 };
} catch (error) {
return ErrorHandler(error);

View File

@ -81,8 +81,8 @@ export const post: RequestHandler = async (event) => {
})
)
.digest('hex');
await db.prisma.application.updateMany({
where: { branch, projectId },
await db.prisma.application.update({
where: { id: application.id },
data: { configHash }
});
}

View File

@ -45,8 +45,8 @@ export const post: RequestHandler = async (event) => {
})
)
.digest('hex');
await db.prisma.application.updateMany({
where: { branch, projectId },
await db.prisma.application.update({
where: { id: application.id },
data: { configHash }
});
}