mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-25 04:59:32 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca705bbf89 | ||
|
|
b70fe09d17 | ||
|
|
d7d570393f | ||
|
|
41ca265e5a | ||
|
|
03cde08d67 | ||
|
|
5684674bd7 | ||
|
|
4fe919f2ea | ||
|
|
c8c23c53ef | ||
|
|
b1c25e98d7 | ||
|
|
7ab5a4bfcf | ||
|
|
a3ee57995c | ||
|
|
32020fd336 | ||
|
|
3ef093c7e6 | ||
|
|
f5dfaa81d3 | ||
|
|
fcf206a081 | ||
|
|
9790d2b613 | ||
|
|
201fa82efc | ||
|
|
d28433ee64 | ||
|
|
cc348bf0f5 | ||
|
|
b023d65fcf |
@@ -11,7 +11,7 @@ WORKDIR /app
|
|||||||
|
|
||||||
LABEL coolify.managed true
|
LABEL coolify.managed true
|
||||||
|
|
||||||
RUN apk add --no-cache git openssh-client curl jq cmake sqlite
|
RUN apk add --no-cache git git-lfs openssh-client curl jq cmake sqlite
|
||||||
|
|
||||||
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@6
|
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@6
|
||||||
RUN pnpm add -g pnpm
|
RUN pnpm add -g pnpm
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "coolify",
|
"name": "coolify",
|
||||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||||
"version": "2.3.0",
|
"version": "2.3.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev",
|
"dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev",
|
||||||
|
|||||||
@@ -102,12 +102,9 @@ export const setDefaultConfiguration = async (data) => {
|
|||||||
else if (buildPack === 'php') port = 80;
|
else if (buildPack === 'php') port = 80;
|
||||||
else if (buildPack === 'python') port = 8000;
|
else if (buildPack === 'python') port = 8000;
|
||||||
}
|
}
|
||||||
if (template) {
|
if (!installCommand) installCommand = template?.installCommand || 'yarn install';
|
||||||
if (!installCommand) installCommand = template?.installCommand || 'yarn install';
|
if (!startCommand) startCommand = template?.startCommand || 'yarn start';
|
||||||
if (!startCommand) startCommand = template?.startCommand || 'yarn start';
|
if (!buildCommand) buildCommand = template?.buildCommand || null;
|
||||||
if (!buildCommand) buildCommand = template?.buildCommand || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!publishDirectory) publishDirectory = template?.publishDirectory || null;
|
if (!publishDirectory) publishDirectory = template?.publishDirectory || null;
|
||||||
if (baseDirectory) {
|
if (baseDirectory) {
|
||||||
if (!baseDirectory.startsWith('/')) baseDirectory = `/${baseDirectory}`;
|
if (!baseDirectory.startsWith('/')) baseDirectory = `/${baseDirectory}`;
|
||||||
@@ -127,18 +124,7 @@ export const setDefaultConfiguration = async (data) => {
|
|||||||
|
|
||||||
export async function copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId) {
|
export async function copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId) {
|
||||||
try {
|
try {
|
||||||
// TODO: Write full .dockerignore for all deployments!!
|
|
||||||
if (buildPack === 'php') {
|
if (buildPack === 'php') {
|
||||||
await fs.writeFile(
|
|
||||||
`${workdir}/.htaccess`,
|
|
||||||
`
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteBase /
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
|
||||||
RewriteRule ^(.+)$ index.php [QSA,L]
|
|
||||||
`
|
|
||||||
);
|
|
||||||
await fs.writeFile(`${workdir}/entrypoint.sh`, `chown -R 1000 /app`);
|
await fs.writeFile(`${workdir}/entrypoint.sh`, `chown -R 1000 /app`);
|
||||||
await saveBuildLog({
|
await saveBuildLog({
|
||||||
line: 'Copied default configuration file for PHP.',
|
line: 'Copied default configuration file for PHP.',
|
||||||
|
|||||||
@@ -1,23 +1,33 @@
|
|||||||
import { buildImage } from '$lib/docker';
|
import { buildImage } from '$lib/docker';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|
||||||
const createDockerfile = async (data, image): Promise<void> => {
|
const createDockerfile = async (data, image, htaccessFound): Promise<void> => {
|
||||||
const { workdir, baseDirectory } = data;
|
const { workdir, baseDirectory } = data;
|
||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push(`LABEL coolify.image=true`);
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push('WORKDIR /app');
|
Dockerfile.push('WORKDIR /app');
|
||||||
Dockerfile.push(`COPY .${baseDirectory || ''} /app`);
|
Dockerfile.push(`COPY .${baseDirectory || ''} /app`);
|
||||||
Dockerfile.push(`COPY /.htaccess .`);
|
if (htaccessFound) {
|
||||||
|
Dockerfile.push(`COPY .${baseDirectory || ''}/.htaccess ./`);
|
||||||
|
}
|
||||||
Dockerfile.push(`COPY /entrypoint.sh /opt/docker/provision/entrypoint.d/30-entrypoint.sh`);
|
Dockerfile.push(`COPY /entrypoint.sh /opt/docker/provision/entrypoint.d/30-entrypoint.sh`);
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function (data) {
|
export default async function (data) {
|
||||||
|
const { workdir, baseDirectory } = data;
|
||||||
try {
|
try {
|
||||||
const image = 'webdevops/php-nginx';
|
let htaccessFound = false;
|
||||||
await createDockerfile(data, image);
|
try {
|
||||||
|
const d = await fs.readFile(`${workdir}${baseDirectory || ''}/.htaccess`);
|
||||||
|
htaccessFound = true;
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
const image = htaccessFound ? 'webdevops/php-apache' : 'webdevops/php-nginx';
|
||||||
|
await createDockerfile(data, image, htaccessFound);
|
||||||
await buildImage(data);
|
await buildImage(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -46,11 +46,16 @@ const customConfig: Config = {
|
|||||||
export const version = currentVersion;
|
export const version = currentVersion;
|
||||||
export const asyncExecShell = util.promisify(child.exec);
|
export const asyncExecShell = util.promisify(child.exec);
|
||||||
export const asyncSleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
|
export const asyncSleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
|
||||||
|
|
||||||
export const sentry = Sentry;
|
export const sentry = Sentry;
|
||||||
|
|
||||||
export const uniqueName = () => uniqueNamesGenerator(customConfig);
|
export const uniqueName = () => uniqueNamesGenerator(customConfig);
|
||||||
|
|
||||||
export const saveBuildLog = async ({ line, buildId, applicationId }) => {
|
export const saveBuildLog = async ({ line, buildId, applicationId }) => {
|
||||||
|
if (line.includes('ghs_')) {
|
||||||
|
const regex = /ghs_.*@/g;
|
||||||
|
line = line.replace(regex, '<SENSITIVE_DATA_DELETED>@');
|
||||||
|
}
|
||||||
const addTimestamp = `${generateTimestamp()} ${line}`;
|
const addTimestamp = `${generateTimestamp()} ${line}`;
|
||||||
return await buildLogQueue.add(buildId, { buildId, line: addTimestamp, applicationId });
|
return await buildLogQueue.add(buildId, { buildId, line: addTimestamp, applicationId });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,40 +15,35 @@ export default async function ({
|
|||||||
branch,
|
branch,
|
||||||
buildId
|
buildId
|
||||||
}): Promise<any> {
|
}): Promise<any> {
|
||||||
try {
|
const url = htmlUrl.replace('https://', '').replace('http://', '');
|
||||||
const url = htmlUrl.replace('https://', '').replace('http://', '');
|
await saveBuildLog({ line: 'GitHub importer started.', buildId, applicationId });
|
||||||
await saveBuildLog({ line: 'GitHub importer started.', buildId, applicationId });
|
const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId });
|
||||||
const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId });
|
const githubPrivateKey = privateKey.replace(/\\n/g, '\n').replace(/"/g, '');
|
||||||
const githubPrivateKey = privateKey.replace(/\\n/g, '\n').replace(/"/g, '');
|
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
iat: Math.round(new Date().getTime() / 1000),
|
iat: Math.round(new Date().getTime() / 1000),
|
||||||
exp: Math.round(new Date().getTime() / 1000 + 60),
|
exp: Math.round(new Date().getTime() / 1000 + 60),
|
||||||
iss: appId
|
iss: appId
|
||||||
};
|
};
|
||||||
const jwtToken = jsonwebtoken.sign(payload, githubPrivateKey, {
|
const jwtToken = jsonwebtoken.sign(payload, githubPrivateKey, {
|
||||||
algorithm: 'RS256'
|
algorithm: 'RS256'
|
||||||
});
|
});
|
||||||
const { token } = await got
|
const { token } = await got
|
||||||
.post(`${apiUrl}/app/installations/${installationId}/access_tokens`, {
|
.post(`${apiUrl}/app/installations/${installationId}/access_tokens`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${jwtToken}`,
|
Authorization: `Bearer ${jwtToken}`,
|
||||||
Accept: 'application/vnd.github.machine-man-preview+json'
|
Accept: 'application/vnd.github.machine-man-preview+json'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.json();
|
.json();
|
||||||
await saveBuildLog({
|
await saveBuildLog({
|
||||||
line: `Cloning ${repository}:${branch} branch.`,
|
line: `Cloning ${repository}:${branch} branch.`,
|
||||||
buildId,
|
buildId,
|
||||||
applicationId
|
applicationId
|
||||||
});
|
});
|
||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`git clone -q -b ${branch} https://x-access-token:${token}@${url}/${repository}.git ${workdir}/ && cd ${workdir} && git submodule update --init --recursive && cd ..`
|
`git clone -q -b ${branch} https://x-access-token:${token}@${url}/${repository}.git ${workdir}/ && cd ${workdir} && git submodule update --init --recursive && git lfs pull && cd .. `
|
||||||
);
|
);
|
||||||
const { stdout: commit } = await asyncExecShell(`cd ${workdir}/ && git rev-parse HEAD`);
|
const { stdout: commit } = await asyncExecShell(`cd ${workdir}/ && git rev-parse HEAD`);
|
||||||
return commit.replace('\n', '');
|
return commit.replace('\n', '');
|
||||||
} catch (error) {
|
|
||||||
console.log({ error });
|
|
||||||
return ErrorHandler(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default async function ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -q -i ${repodir}id.rsa -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && cd ..`
|
`git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -q -i ${repodir}id.rsa -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && git lfs pull && cd .. `
|
||||||
);
|
);
|
||||||
const { stdout: commit } = await asyncExecShell(`cd ${workdir}/ && git rev-parse HEAD`);
|
const { stdout: commit } = await asyncExecShell(`cd ${workdir}/ && git rev-parse HEAD`);
|
||||||
return commit.replace('\n', '');
|
return commit.replace('\n', '');
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default async function (job) {
|
|||||||
await asyncSleep(500);
|
await asyncSleep(500);
|
||||||
await db.prisma.build.updateMany({
|
await db.prisma.build.updateMany({
|
||||||
where: {
|
where: {
|
||||||
status: 'queued',
|
status: { in: ['queued', 'running'] },
|
||||||
id: { not: buildId },
|
id: { not: buildId },
|
||||||
applicationId,
|
applicationId,
|
||||||
createdAt: { lt: new Date(new Date().getTime() - 60 * 60 * 1000) }
|
createdAt: { lt: new Date(new Date().getTime() - 60 * 60 * 1000) }
|
||||||
|
|||||||
@@ -118,10 +118,14 @@ buildWorker.on('completed', async (job: Bullmq.Job) => {
|
|||||||
try {
|
try {
|
||||||
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'success' } });
|
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'success' } });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setTimeout(async () => {
|
||||||
|
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'success' } });
|
||||||
|
}, 1234);
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
const workdir = `/tmp/build-sources/${job.data.repository}/${job.data.build_id}`;
|
const workdir = `/tmp/build-sources/${job.data.repository}/${job.data.build_id}`;
|
||||||
if (!dev) await asyncExecShell(`rm -fr ${workdir}`);
|
if (!dev) await asyncExecShell(`rm -fr ${workdir}`);
|
||||||
|
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'success' } });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
@@ -130,10 +134,14 @@ buildWorker.on('failed', async (job: Bullmq.Job, failedReason) => {
|
|||||||
try {
|
try {
|
||||||
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'failed' } });
|
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'failed' } });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setTimeout(async () => {
|
||||||
|
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'failed' } });
|
||||||
|
}, 1234);
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
const workdir = `/tmp/build-sources/${job.data.repository}`;
|
const workdir = `/tmp/build-sources/${job.data.repository}`;
|
||||||
if (!dev) await asyncExecShell(`rm -fr ${workdir}`);
|
if (!dev) await asyncExecShell(`rm -fr ${workdir}`);
|
||||||
|
await prisma.build.update({ where: { id: job.data.build_id }, data: { status: 'failed' } });
|
||||||
}
|
}
|
||||||
await saveBuildLog({
|
await saveBuildLog({
|
||||||
line: 'Failed to deploy!',
|
line: 'Failed to deploy!',
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
batchSecretsPairs.map(({ name, value, isNew }) =>
|
batchSecretsPairs.map(({ name, value, isNew }) =>
|
||||||
limit(() => saveSecret({ name, value, applicationId: id, isNew, dispatch }))
|
limit(() => saveSecret({ name, value, applicationId: id, isNew }))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
batchSecrets = '';
|
batchSecrets = '';
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h2 class="title my-6 font-bold">Paste .env file</h2>
|
<h2 class="title my-6 font-bold">Paste .env file</h2>
|
||||||
<form on:submit={getValues} class="mb-12 w-full">
|
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
|
||||||
<textarea value={batchSecrets} on:change={setBatchValue} class="mb-2 min-h-[200px] w-full" />
|
<textarea bind:value={batchSecrets} class="mb-2 min-h-[200px] w-full" />
|
||||||
<button
|
<button
|
||||||
class="bg-green-600 hover:bg-green-500 disabled:text-white disabled:opacity-40"
|
class="bg-green-600 hover:bg-green-500 disabled:text-white disabled:opacity-40"
|
||||||
type="submit">Batch add secrets</button
|
type="submit">Batch add secrets</button
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import { del } from '$lib/api';
|
import { del } from '$lib/api';
|
||||||
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||||
import { errorNotification } from '$lib/form';
|
import { errorNotification } from '$lib/form';
|
||||||
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { saveSecret } from './utils';
|
import { saveSecret } from './utils';
|
||||||
|
|
||||||
@@ -32,21 +33,39 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createSecret(isNew) {
|
async function createSecret(isNew) {
|
||||||
saveSecret({
|
await saveSecret({
|
||||||
isNew,
|
isNew,
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
isBuildSecret,
|
isBuildSecret,
|
||||||
isPRMRSecret,
|
isPRMRSecret,
|
||||||
isNewSecret,
|
isNewSecret,
|
||||||
applicationId: id,
|
applicationId: id
|
||||||
dispatch
|
|
||||||
});
|
});
|
||||||
|
if (isNewSecret) {
|
||||||
|
name = '';
|
||||||
|
value = '';
|
||||||
|
isBuildSecret = false;
|
||||||
|
}
|
||||||
|
dispatch('refresh');
|
||||||
|
toast.push('Secret saved');
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSecretValue() {
|
async function setSecretValue() {
|
||||||
if (isNewSecret) {
|
if (!isPRMRSecret) {
|
||||||
isBuildSecret = !isBuildSecret;
|
isBuildSecret = !isBuildSecret;
|
||||||
|
if (!isNewSecret) {
|
||||||
|
await saveSecret({
|
||||||
|
isNew: isNewSecret,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret,
|
||||||
|
isNewSecret,
|
||||||
|
applicationId: id
|
||||||
|
});
|
||||||
|
toast.push('Secret saved');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -81,9 +100,9 @@
|
|||||||
class="relative inline-flex h-6 w-11 flex-shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out"
|
class="relative inline-flex h-6 w-11 flex-shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out"
|
||||||
class:bg-green-600={isBuildSecret}
|
class:bg-green-600={isBuildSecret}
|
||||||
class:bg-stone-700={!isBuildSecret}
|
class:bg-stone-700={!isBuildSecret}
|
||||||
class:opacity-50={!isNewSecret}
|
class:opacity-50={isPRMRSecret}
|
||||||
class:cursor-not-allowed={!isNewSecret}
|
class:cursor-not-allowed={isPRMRSecret}
|
||||||
class:cursor-pointer={isNewSecret}
|
class:cursor-pointer={!isPRMRSecret}
|
||||||
>
|
>
|
||||||
<span class="sr-only">Use isBuildSecret</span>
|
<span class="sr-only">Use isBuildSecret</span>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -22,18 +22,48 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let secrets;
|
export let secrets;
|
||||||
export let application;
|
export let application;
|
||||||
|
import pLimit from 'p-limit';
|
||||||
import Secret from './_Secret.svelte';
|
import Secret from './_Secret.svelte';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { get } from '$lib/api';
|
import { get } from '$lib/api';
|
||||||
import BatchSecrets from './_BatchSecrets.svelte';
|
import { saveSecret } from './utils';
|
||||||
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
|
|
||||||
|
const limit = pLimit(1);
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
|
|
||||||
|
let batchSecrets = '';
|
||||||
async function refreshSecrets() {
|
async function refreshSecrets() {
|
||||||
const data = await get(`/applications/${id}/secrets.json`);
|
const data = await get(`/applications/${id}/secrets.json`);
|
||||||
secrets = [...data.secrets];
|
secrets = [...data.secrets];
|
||||||
}
|
}
|
||||||
|
async function getValues(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const eachValuePair = batchSecrets.split('\n');
|
||||||
|
const batchSecretsPairs = eachValuePair
|
||||||
|
.filter((secret) => !secret.startsWith('#') && secret)
|
||||||
|
.map((secret) => {
|
||||||
|
const [name, value] = secret.split('=');
|
||||||
|
const cleanValue = value?.replaceAll('"', '') || '';
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
value: cleanValue,
|
||||||
|
isNew: !secrets.find((secret) => name === secret.name)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
batchSecretsPairs.map(({ name, value, isNew }) =>
|
||||||
|
limit(() => saveSecret({ name, value, applicationId: id, isNew }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
batchSecrets = '';
|
||||||
|
await refreshSecrets();
|
||||||
|
toast.push('Secrets saved');
|
||||||
|
}
|
||||||
|
function asd() {
|
||||||
|
console.log(secrets);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex items-center space-x-2 p-5 px-6 font-bold">
|
<div class="flex items-center space-x-2 p-5 px-6 font-bold">
|
||||||
@@ -134,6 +164,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<button on:click={asd}>Save</button>
|
||||||
<BatchSecrets {secrets} {id} {refreshSecrets} />
|
<h2 class="title my-6 font-bold">Paste .env file</h2>
|
||||||
|
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
|
||||||
|
<textarea bind:value={batchSecrets} class="mb-2 min-h-[200px] w-full" />
|
||||||
|
<button
|
||||||
|
class="bg-green-600 hover:bg-green-500 disabled:text-white disabled:opacity-40"
|
||||||
|
type="submit">Batch add secrets</button
|
||||||
|
>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ type Props = {
|
|||||||
isPRMRSecret?: boolean;
|
isPRMRSecret?: boolean;
|
||||||
isNewSecret?: boolean;
|
isNewSecret?: boolean;
|
||||||
applicationId: string;
|
applicationId: string;
|
||||||
dispatch: (name: string) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function saveSecret({
|
export async function saveSecret({
|
||||||
@@ -20,8 +19,7 @@ export async function saveSecret({
|
|||||||
isBuildSecret,
|
isBuildSecret,
|
||||||
isPRMRSecret,
|
isPRMRSecret,
|
||||||
isNewSecret,
|
isNewSecret,
|
||||||
applicationId,
|
applicationId
|
||||||
dispatch
|
|
||||||
}: Props): Promise<void> {
|
}: Props): Promise<void> {
|
||||||
if (!name) return errorNotification('Name is required.');
|
if (!name) return errorNotification('Name is required.');
|
||||||
if (!value) return errorNotification('Value is required.');
|
if (!value) return errorNotification('Value is required.');
|
||||||
@@ -33,13 +31,11 @@ export async function saveSecret({
|
|||||||
isPRMRSecret,
|
isPRMRSecret,
|
||||||
isNew: isNew || false
|
isNew: isNew || false
|
||||||
});
|
});
|
||||||
dispatch('refresh');
|
|
||||||
if (isNewSecret) {
|
if (isNewSecret) {
|
||||||
name = '';
|
name = '';
|
||||||
value = '';
|
value = '';
|
||||||
isBuildSecret = false;
|
isBuildSecret = false;
|
||||||
}
|
}
|
||||||
toast.push('Secret saved.');
|
|
||||||
} catch ({ error }) {
|
} catch ({ error }) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const config = {
|
const config = {
|
||||||
image: `${image}:${version}`,
|
image: `${image}:${version}`,
|
||||||
volume: `${id}-n8n:/root/.n8n`,
|
volume: `${id}-n8n:/root/.n8n`,
|
||||||
environmentVariables: {}
|
environmentVariables: {
|
||||||
|
WEBHOOK_URL: `${service.fqdn}`
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (serviceSecret.length > 0) {
|
if (serviceSecret.length > 0) {
|
||||||
serviceSecret.forEach((secret) => {
|
serviceSecret.forEach((secret) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user