Compare commits

..

16 Commits

Author SHA1 Message Date
Andras Bacsai
ca705bbf89 Merge pull request #290 from coollabsio/v2.3.3
v2.3.3
2022-04-05 11:19:07 +02:00
Andras Bacsai
b70fe09d17 fix: Remove asyncUntil 2022-04-05 11:13:13 +02:00
Andras Bacsai
d7d570393f Revert try 2022-04-05 11:09:17 +02:00
Andras Bacsai
41ca265e5a Try to not restart redis? 2022-04-05 11:00:36 +02:00
Andras Bacsai
03cde08d67 fix: Lame fixing 2022-04-05 10:58:47 +02:00
Andras Bacsai
5684674bd7 fix: revert seed 2022-04-05 10:36:28 +02:00
Andras Bacsai
4fe919f2ea Merge branch 'v2.3.3' of github.com:coollabsio/coolify into v2.3.3 2022-04-05 10:36:12 +02:00
Andras Bacsai
c8c23c53ef fix: Update stucked builds 2022-04-05 10:36:09 +02:00
Andras Bacsai
b1c25e98d7 fix: Update stucked builds on startup 2022-04-05 10:34:31 +02:00
Andras Bacsai
7ab5a4bfcf fix: Try to update build status several times 2022-04-05 10:30:18 +02:00
Andras Bacsai
a3ee57995c chore: Version++ 2022-04-05 10:21:46 +02:00
Andras Bacsai
32020fd336 fix: Add git lfs while deploying 2022-04-05 10:21:40 +02:00
Andras Bacsai
3ef093c7e6 Merge pull request #286 from coollabsio/v2.3.2
v2.3.2
2022-04-04 19:40:39 +02:00
Andras Bacsai
f5dfaa81d3 chore:version++ 2022-04-04 19:35:17 +02:00
Andras Bacsai
fcf206a081 fix: Add default webhook domain for n8n 2022-04-04 19:18:06 +02:00
Andras Bacsai
9790d2b613 fix(php): If .htaccess file found use apache 2022-04-04 18:47:22 +02:00
10 changed files with 64 additions and 55 deletions

View File

@@ -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

View File

@@ -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.1", "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",

View File

@@ -124,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.',

View File

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

View File

@@ -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 });
}; };

View File

@@ -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);
}
} }

View File

@@ -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', '');

View File

@@ -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) }

View File

@@ -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!',

View File

@@ -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) => {