mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-26 04:59:31 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e39541c318 | ||
|
|
cf88885c94 | ||
|
|
1192346ce3 | ||
|
|
0e3bd85847 | ||
|
|
edeb6c6965 | ||
|
|
138fd5cb6d | ||
|
|
155410bd44 | ||
|
|
20bd829c2e | ||
|
|
7b7e222946 | ||
|
|
98d901d06c | ||
|
|
4e862cda6f | ||
|
|
4e940807ae | ||
|
|
b081743f54 | ||
|
|
34bb9f301f | ||
|
|
ed8a6daeea | ||
|
|
9e81ab43ac | ||
|
|
32d94cbe97 | ||
|
|
46a83aa457 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "coolify",
|
||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||
"version": "2.9.4",
|
||||
"version": "2.9.7",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
"dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev --host 0.0.0.0",
|
||||
|
||||
@@ -10,8 +10,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
Dockerfile.push('WORKDIR /app');
|
||||
Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
|
||||
if (isPnpm) {
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm');
|
||||
Dockerfile.push('RUN pnpm add -g pnpm');
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7');
|
||||
}
|
||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /app/${baseDirectory || ''} ./`);
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
});
|
||||
}
|
||||
if (isPnpm) {
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm');
|
||||
Dockerfile.push('RUN pnpm add -g pnpm');
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7');
|
||||
}
|
||||
Dockerfile.push(`COPY .${baseDirectory || ''} ./`);
|
||||
Dockerfile.push(`RUN ${installCommand}`);
|
||||
|
||||
@@ -36,8 +36,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
});
|
||||
}
|
||||
if (isPnpm) {
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm');
|
||||
Dockerfile.push('RUN pnpm add -g pnpm');
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7');
|
||||
}
|
||||
Dockerfile.push(`COPY .${baseDirectory || ''} ./`);
|
||||
Dockerfile.push(`RUN ${installCommand}`);
|
||||
|
||||
@@ -35,8 +35,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
});
|
||||
}
|
||||
if (isPnpm) {
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm');
|
||||
Dockerfile.push('RUN pnpm add -g pnpm');
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7');
|
||||
}
|
||||
Dockerfile.push(`COPY .${baseDirectory || ''} ./`);
|
||||
Dockerfile.push(`RUN ${installCommand}`);
|
||||
|
||||
@@ -66,8 +66,7 @@ export async function buildCacheImageWithNode(data, imageForBuild) {
|
||||
});
|
||||
}
|
||||
if (isPnpm) {
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm');
|
||||
Dockerfile.push('RUN pnpm add -g pnpm');
|
||||
Dockerfile.push('RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7');
|
||||
}
|
||||
if (installCommand) {
|
||||
Dockerfile.push(`COPY .${baseDirectory || ''}/package.json ./`);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
export let application;
|
||||
export let appId;
|
||||
import Select from 'svelte-select';
|
||||
import { page, session } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { errorNotification } from '$lib/form';
|
||||
@@ -33,6 +34,10 @@
|
||||
let showSave = false;
|
||||
let autodeploy = application.settings.autodeploy || true;
|
||||
|
||||
let search = {
|
||||
project: '',
|
||||
branch: ''
|
||||
};
|
||||
let selected = {
|
||||
group: undefined,
|
||||
project: undefined,
|
||||
@@ -84,16 +89,49 @@
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function selectGroup(event) {
|
||||
selected.group = event.detail;
|
||||
selected.project = null;
|
||||
selected.branch = null;
|
||||
showSave = false;
|
||||
loadProjects();
|
||||
}
|
||||
|
||||
async function searchProjects(searchText) {
|
||||
if (!selected.group) {
|
||||
return;
|
||||
}
|
||||
|
||||
search.project = searchText;
|
||||
await loadProjects();
|
||||
return projects;
|
||||
}
|
||||
|
||||
function selectProject(event) {
|
||||
selected.project = event.detail;
|
||||
selected.branch = null;
|
||||
showSave = false;
|
||||
loadBranches();
|
||||
}
|
||||
|
||||
async function loadProjects() {
|
||||
const params = new URLSearchParams({
|
||||
page: 1,
|
||||
per_page: 25,
|
||||
archived: false
|
||||
});
|
||||
|
||||
if (search.project) {
|
||||
params.append('search', search.project);
|
||||
}
|
||||
|
||||
loading.projects = true;
|
||||
if (username === selected.group.name) {
|
||||
try {
|
||||
projects = await get(
|
||||
`${apiUrl}/v4/users/${selected.group.name}/projects?min_access_level=40&page=1&per_page=25&archived=false`,
|
||||
{
|
||||
Authorization: `Bearer ${$gitTokens.gitlabToken}`
|
||||
}
|
||||
);
|
||||
params.append('min_access_level', 40);
|
||||
projects = await get(`${apiUrl}/v4/users/${selected.group.name}/projects?${params}`, {
|
||||
Authorization: `Bearer ${$gitTokens.gitlabToken}`
|
||||
});
|
||||
} catch (error) {
|
||||
errorNotification(error);
|
||||
throw new Error(error);
|
||||
@@ -102,12 +140,9 @@
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
projects = await get(
|
||||
`${apiUrl}/v4/groups/${selected.group.id}/projects?page=1&per_page=25&archived=false`,
|
||||
{
|
||||
Authorization: `Bearer ${$gitTokens.gitlabToken}`
|
||||
}
|
||||
);
|
||||
projects = await get(`${apiUrl}/v4/groups/${selected.group.id}/projects?${params}`, {
|
||||
Authorization: `Bearer ${$gitTokens.gitlabToken}`
|
||||
});
|
||||
} catch (error) {
|
||||
errorNotification(error);
|
||||
throw new Error(error);
|
||||
@@ -117,11 +152,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function searchBranches(searchText) {
|
||||
if (!selected.project) {
|
||||
return;
|
||||
}
|
||||
|
||||
search.branch = searchText;
|
||||
await loadBranches();
|
||||
return branches;
|
||||
}
|
||||
|
||||
function selectBranch(event) {
|
||||
selected.branch = event.detail;
|
||||
isBranchAlreadyUsed();
|
||||
}
|
||||
|
||||
async function loadBranches() {
|
||||
const params = new URLSearchParams({
|
||||
page: 1,
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
if (search.branch) {
|
||||
params.append('search', search.branch);
|
||||
}
|
||||
|
||||
loading.branches = true;
|
||||
try {
|
||||
branches = await get(
|
||||
`${apiUrl}/v4/projects/${selected.project.id}/repository/branches?per_page=100&page=1`,
|
||||
`${apiUrl}/v4/projects/${selected.project.id}/repository/branches?${params}`,
|
||||
{
|
||||
Authorization: `Bearer ${$gitTokens.gitlabToken}`
|
||||
}
|
||||
@@ -267,70 +326,79 @@
|
||||
|
||||
<form on:submit={handleSubmit}>
|
||||
<div class="flex flex-col space-y-2 px-4 xl:flex-row xl:space-y-0 xl:space-x-2 ">
|
||||
{#if loading.base}
|
||||
<select name="group" disabled class="w-96">
|
||||
<option selected value="">{$t('application.configuration.loading_groups')}</option>
|
||||
</select>
|
||||
{:else}
|
||||
<select name="group" class="w-96" bind:value={selected.group} on:change={loadProjects}>
|
||||
<option value="" disabled selected>{$t('application.configuration.select_a_group')}</option>
|
||||
{#each groups as group}
|
||||
<option value={group}>{group.full_name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{/if}
|
||||
{#if loading.projects}
|
||||
<select name="project" disabled class="w-96">
|
||||
<option selected value="">{$t('application.configuration.loading_projects')}</option>
|
||||
</select>
|
||||
{:else if !loading.projects && projects.length > 0}
|
||||
<select
|
||||
name="project"
|
||||
class="w-96"
|
||||
bind:value={selected.project}
|
||||
on:change={loadBranches}
|
||||
disabled={!selected.group}
|
||||
>
|
||||
<option value="" disabled selected
|
||||
>{$t('application.configuration.select_a_project')}</option
|
||||
>
|
||||
{#each projects as project}
|
||||
<option value={project}>{project.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<select name="project" disabled class="w-96">
|
||||
<option disabled selected value=""
|
||||
>{$t('application.configuration.no_projects_found')}</option
|
||||
>
|
||||
</select>
|
||||
{/if}
|
||||
|
||||
{#if loading.branches}
|
||||
<select name="branch" disabled class="w-96">
|
||||
<option selected value="">{$t('application.configuration.loading_branches')}</option>
|
||||
</select>
|
||||
{:else if !loading.branches && branches.length > 0}
|
||||
<select
|
||||
name="branch"
|
||||
class="w-96"
|
||||
bind:value={selected.branch}
|
||||
on:change={isBranchAlreadyUsed}
|
||||
disabled={!selected.project}
|
||||
>
|
||||
<option value="" disabled selected>{$t('application.configuration.select_a_branch')}</option
|
||||
>
|
||||
{#each branches as branch}
|
||||
<option value={branch}>{branch.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<select name="project" disabled class="w-96">
|
||||
<option disabled selected value=""
|
||||
>{$t('application.configuration.no_branches_found')}</option
|
||||
>
|
||||
</select>
|
||||
{/if}
|
||||
<div class="custom-select-wrapper">
|
||||
<Select
|
||||
placeholder={loading.base
|
||||
? $t('application.configuration.loading_groups')
|
||||
: $t('application.configuration.select_a_group')}
|
||||
id="group"
|
||||
showIndicator={!loading.base}
|
||||
isWaiting={loading.base}
|
||||
on:select={selectGroup}
|
||||
on:clear={() => {
|
||||
showSave = false;
|
||||
projects = [];
|
||||
branches = [];
|
||||
selected.group = null;
|
||||
selected.project = null;
|
||||
selected.branch = null;
|
||||
}}
|
||||
value={selected.group}
|
||||
isDisabled={loading.base}
|
||||
isClearable={false}
|
||||
items={groups}
|
||||
labelIdentifier="full_name"
|
||||
optionIdentifier="id"
|
||||
/>
|
||||
</div>
|
||||
<div class="custom-select-wrapper">
|
||||
<Select
|
||||
placeholder={loading.projects
|
||||
? $t('application.configuration.loading_projects')
|
||||
: $t('application.configuration.select_a_project')}
|
||||
noOptionsMessage={$t('application.configuration.no_projects_found')}
|
||||
id="project"
|
||||
showIndicator={!loading.projects}
|
||||
isWaiting={loading.projects}
|
||||
isDisabled={loading.projects || !selected.group}
|
||||
on:select={selectProject}
|
||||
on:clear={() => {
|
||||
showSave = false;
|
||||
branches = [];
|
||||
selected.project = null;
|
||||
selected.branch = null;
|
||||
}}
|
||||
value={selected.project}
|
||||
isClearable={false}
|
||||
items={projects}
|
||||
loadOptions={searchProjects}
|
||||
labelIdentifier="name"
|
||||
optionIdentifier="id"
|
||||
/>
|
||||
</div>
|
||||
<div class="custom-select-wrapper">
|
||||
<Select
|
||||
placeholder={loading.branches
|
||||
? $t('application.configuration.loading_branches')
|
||||
: $t('application.configuration.select_a_branch')}
|
||||
noOptionsMessage={$t('application.configuration.no_branches_found')}
|
||||
id="branch"
|
||||
showIndicator={!loading.branches}
|
||||
isWaiting={loading.branches}
|
||||
isDisabled={loading.branches || !selected.project}
|
||||
on:select={selectBranch}
|
||||
on:clear={() => {
|
||||
showSave = false;
|
||||
selected.branch = null;
|
||||
}}
|
||||
value={selected.branch}
|
||||
isClearable={false}
|
||||
items={branches}
|
||||
loadOptions={searchBranches}
|
||||
labelIdentifier="name"
|
||||
optionIdentifier="web_url"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center space-y-4 pt-5">
|
||||
<button
|
||||
|
||||
@@ -12,7 +12,7 @@ export const del: RequestHandler = async (event) => {
|
||||
const database = await db.getDatabase({ id, teamId });
|
||||
if (database.destinationDockerId) {
|
||||
const everStarted = await stopDatabase(database);
|
||||
if (everStarted) await stopTcpHttpProxy(database.destinationDocker, database.publicPort);
|
||||
if (everStarted) await stopTcpHttpProxy(id, database.destinationDocker, database.publicPort);
|
||||
}
|
||||
await db.removeDatabase({ id });
|
||||
return { status: 200 };
|
||||
|
||||
@@ -29,7 +29,7 @@ export const post: RequestHandler = async (event) => {
|
||||
}
|
||||
} else {
|
||||
await db.prisma.database.update({ where: { id }, data: { publicPort: null } });
|
||||
await stopTcpHttpProxy(destinationDocker, oldPublicPort);
|
||||
await stopTcpHttpProxy(id, destinationDocker, oldPublicPort);
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -13,7 +13,7 @@ export const post: RequestHandler = async (event) => {
|
||||
try {
|
||||
const database = await db.getDatabase({ id, teamId });
|
||||
const everStarted = await stopDatabase(database);
|
||||
if (everStarted) await stopTcpHttpProxy(database.destinationDocker, database.publicPort);
|
||||
if (everStarted) await stopTcpHttpProxy(id, database.destinationDocker, database.publicPort);
|
||||
await db.setDatabase({ id, isPublic: false });
|
||||
await db.prisma.database.update({ where: { id }, data: { publicPort: null } });
|
||||
|
||||
@@ -21,6 +21,7 @@ export const post: RequestHandler = async (event) => {
|
||||
status: 200
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return ErrorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ export const post: RequestHandler = async (event) => {
|
||||
fider: {
|
||||
image: `${image}:${version}`,
|
||||
environmentVariables: {
|
||||
HOST_DOMAIN: domain,
|
||||
BASE_URL: domain,
|
||||
DATABASE_URL: `postgresql://${postgresqlUser}:${postgresqlPassword}@${id}-postgresql:5432/${postgresqlDatabase}?sslmode=disable`,
|
||||
JWT_SECRET: `${jwtSecret.replace(/\$/g, '$$$')}`,
|
||||
EMAIL_NOREPLY: emailNoreply,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { checkContainer } from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
function configureMiddleware(
|
||||
{ id, container, port, domain, nakedDomain, isHttps, isWWW, isDualCerts },
|
||||
{ id, container, port, domain, nakedDomain, isHttps, isWWW, isDualCerts, scriptName, type },
|
||||
traefik
|
||||
) {
|
||||
if (isHttps) {
|
||||
@@ -125,6 +125,15 @@ function configureMiddleware(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'plausibleanalytics' && scriptName && scriptName !== 'plausible.js') {
|
||||
if (!traefik.http.routers[`${id}`].middlewares.includes(`${id}-redir`)) {
|
||||
traefik.http.routers[`${id}`].middlewares.push(`${id}-redir`);
|
||||
}
|
||||
if (!traefik.http.routers[`${id}-secure`].middlewares.includes(`${id}-redir`)) {
|
||||
traefik.http.routers[`${id}-secure`].middlewares.push(`${id}-redir`);
|
||||
}
|
||||
}
|
||||
}
|
||||
export const get: RequestHandler = async (event) => {
|
||||
const traefik = {
|
||||
@@ -176,7 +185,7 @@ export const get: RequestHandler = async (event) => {
|
||||
} = application;
|
||||
if (destinationDockerId) {
|
||||
const { engine, network } = destinationDocker;
|
||||
const isRunning = await checkContainer(engine, id);
|
||||
const isRunning = true;
|
||||
if (fqdn) {
|
||||
const domain = getDomain(fqdn);
|
||||
const nakedDomain = domain.replace(/^www\./, '');
|
||||
@@ -244,7 +253,7 @@ export const get: RequestHandler = async (event) => {
|
||||
if (found) {
|
||||
const port = found.ports.main;
|
||||
const publicPort = service[type]?.publicPort;
|
||||
const isRunning = await checkContainer(engine, id);
|
||||
const isRunning = true;
|
||||
if (fqdn) {
|
||||
const domain = getDomain(fqdn);
|
||||
const nakedDomain = domain.replace(/^www\./, '');
|
||||
@@ -335,11 +344,6 @@ export const get: RequestHandler = async (event) => {
|
||||
replacement: '/js/plausible.js'
|
||||
}
|
||||
};
|
||||
if (traefik.http.routers[id].middlewares.length > 0) {
|
||||
traefik.http.routers[id].middlewares.push(`${id}-redir`);
|
||||
} else {
|
||||
traefik.http.routers[id].middlewares = [`${id}-redir`];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const coolify of data.coolify) {
|
||||
|
||||
Reference in New Issue
Block a user