feat: simpleDockerfile deployment

This commit is contained in:
Andras Bacsai
2022-12-01 12:58:45 +01:00
parent a129be0dbd
commit 2e56086661
21 changed files with 459 additions and 184 deletions

View File

@@ -42,4 +42,6 @@
<Icons.Heroku {isAbsolute} />
{:else if application.buildPack?.toLowerCase() === 'compose'}
<Icons.Compose {isAbsolute} />
{:else if application.simpleDockerfile}
<Icons.Docker {isAbsolute} />
{/if}

View File

@@ -19,14 +19,14 @@ export async function refreshStatus(list: Array<any>) {
}
export async function getStatus(resource: any, force: boolean = false) {
const { id, buildPack, dualCerts, engine } = resource;
const { id, buildPack, dualCerts, engine, simpleDockerfile } = resource;
let newStatus = 'stopped';
// Already set and we're not forcing
if (getStore(containerStatus)[id] && !force) return getStore(containerStatus)[id];
try {
if (buildPack) { // Application
if (buildPack || simpleDockerfile) { // Application
const response = await get(`/applications/${id}/status`);
newStatus = parseApplicationsResponse(response);
} else if (typeof dualCerts !== 'undefined') { // Service

View File

@@ -57,14 +57,15 @@ export const appSession: Writable<AppSession> = writable({
export const disabledButton: Writable<boolean> = writable(false);
export const isDeploymentEnabled: Writable<boolean> = writable(false);
export function checkIfDeploymentEnabledApplications(isAdmin: boolean, application: any) {
return (
return !!(
isAdmin &&
(application.buildPack === 'compose') ||
(application.fqdn || application.settings.isBot) &&
application.gitSource &&
((application.gitSource &&
application.repository &&
application.destinationDocker &&
application.buildPack
application.buildPack) || application.simpleDockerfile) &&
application.destinationDocker
);
}
export function checkIfDeploymentEnabledServices(isAdmin: boolean, service: any) {

View File

@@ -218,28 +218,30 @@
<li class="menu-title">
<span>Advanced</span>
</li>
<li
class="rounded"
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/revert`}
>
<a href={`/applications/${$page.params.id}/revert`} class="no-underline w-full">
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M20 5v14l-12 -7z" />
<line x1="4" y1="5" x2="4" y2="19" />
</svg>
Revert</a
{#if !application.simpleDockerfile}
<li
class="rounded"
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/revert`}
>
</li>
<a href={`/applications/${$page.params.id}/revert`} class="no-underline w-full">
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M20 5v14l-12 -7z" />
<line x1="4" y1="5" x2="4" y2="19" />
</svg>
Revert</a
>
</li>
{/if}
<li
class="rounded"
class:text-stone-600={$status.application.overallStatus !== 'healthy'}
@@ -265,7 +267,7 @@
</svg>Monitoring</a
>
</li>
{#if !application.settings.isBot}
{#if !application.settings.isBot && !application.simpleDockerfile}
<li
class="rounded"
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/previews`}

View File

@@ -2,8 +2,14 @@
import type { Load } from '@sveltejs/kit';
function checkConfiguration(application: any): string | null {
let configurationPhase = null;
if (!application.gitSourceId) {
configurationPhase = 'source';
if (!application.gitSourceId && !application.simpleDockerfile) {
return (configurationPhase = 'source');
}
if (application.simpleDockerfile) {
if (!application.destinationDockerId) {
configurationPhase = 'destination';
}
return configurationPhase;
} else if (!application.repository && !application.branch) {
configurationPhase = 'repository';
} else if (!application.destinationDockerId) {

View File

@@ -9,6 +9,12 @@
redirect: `/applications/${params.id}`
};
}
if (application.simpleDockerfile) {
return {
status: 302,
redirect: `/applications/${params.id}`
};
}
const response = await get(`/applications/${params.id}/configuration/buildpack`);
return {
props: {
@@ -47,7 +53,7 @@
const { id } = $page.params;
let htmlUrl = application.gitSource.htmlUrl;
let htmlUrl = application.gitSource?.htmlUrl || null;
let scanning: boolean = true;
let foundConfig: any = null;

View File

@@ -25,6 +25,8 @@
</script>
<script lang="ts">
export let sources: any;
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { get, post } from '$lib/api';
@@ -33,11 +35,12 @@
import { appSession } from '$lib/store';
import PublicRepository from './_PublicRepository.svelte';
import DocLink from '$lib/components/DocLink.svelte';
import Beta from '$lib/components/Beta.svelte';
const { id } = $page.params;
const from = $page.url.searchParams.get('from');
let simpleDockerfile: any = null;
export let sources: any;
const filteredSources = sources.filter(
(source: any) =>
(source.type === 'github' && source.githubAppId && source.githubApp.installationId) ||
@@ -61,18 +64,20 @@
return errorNotification(error);
}
}
async function newSource() {
const { id } = await post('/sources/new', {});
return await goto(`/sources/${id}`, { replaceState: true });
async function handleDockerImage() {
try {
await post(`/applications/${id}/configuration/source`, { simpleDockerfile });
return await goto(from || `/applications/${id}/configuration/destination`);
} catch (error) {
return errorNotification(error);
}
}
</script>
<div class="max-w-screen-2xl mx-auto px-9">
{#if !filteredSources}
<div class="title pb-8">Git App</div>
{/if}
<div class="flex flex-wrap justify-center">
{#if !filteredSources}
<div class="flex flex-wrap justify-center">
<div class="flex-col">
<div class="pb-2 text-center font-bold">
{$t('application.configuration.no_configurable_git')}
@@ -95,7 +100,13 @@
</a>
</div>
</div>
{:else}
</div>
{/if}
{#if ownSources.length > 0 || otherSources.length > 0}
<div class="title pb-8">Integrated with Git App</div>
{/if}
{#if ownSources.length > 0}
<div class="flex flex-wrap justify-center">
<div class="flex flex-col lg:flex-row lg:flex-wrap justify-center">
{#each ownSources as source}
<div class="p-2 relative">
@@ -240,11 +251,25 @@
</div>
{/each}
</div>
{/if}
</div>
</div>
{/if}
<div class="flex flex-row items-center">
<div class="title py-4 pr-4">Public Repository</div>
<div class="title py-4 pr-4">Public Repository from Git</div>
<DocLink url="https://docs.coollabs.io/coolify/applications/#public-repository" />
</div>
<PublicRepository />
<div class="flex flex-row items-center pt-10">
<div class="title py-4 pr-4">Simple Dockerfile <Beta /></div>
<DocLink url="https://docs.coollabs.io/coolify/applications/#dockerfile" />
</div>
<div class="mx-auto max-w-screen-2xl">
<form class="flex flex-col" on:submit|preventDefault={handleDockerImage}>
<div class="flex flex-col space-y-2 w-full">
<div class="flex flex-row space-x-2">
<textarea required class="w-full" rows="10" bind:value={simpleDockerfile} />
<button class="btn btn-primary" type="submit">Deploy Dockerfile</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -124,7 +124,7 @@
description={$t('application.enable_auto_deploy_webhooks')}
/>
</div>
{#if !application.settings.isBot}
{#if !application.settings.isBot && !application.simpleDockerfile}
<div class="grid grid-cols-2 items-center">
<Setting
id="previews"

View File

@@ -66,6 +66,7 @@
save: false,
reloadCompose: false
};
let isSimpleDockerfile = !!application.simpleDockerfile;
let fqdnEl: any = null;
let forceSave = false;
let isPublicRepository = application.settings?.isPublicRepository;
@@ -268,7 +269,7 @@
}
}
}
await saveForm(id, application,baseDatabaseBranch, dockerComposeConfiguration);
await saveForm(id, application, baseDatabaseBranch, dockerComposeConfiguration);
setLocation(application, settings);
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
@@ -492,79 +493,84 @@
<label for="name">{$t('forms.name')}</label>
<input name="name" id="name" class="w-full" bind:value={application.name} required />
</div>
<div class="grid grid-cols-2 items-center">
<label for="gitSource">{$t('application.git_source')}</label>
{#if isDisabled || application.settings.isPublicRepository}
<input
disabled={isDisabled || application.settings.isPublicRepository}
class="w-full"
value={application.gitSource?.name}
/>
{:else}
<a
href={`/applications/${id}/configuration/source?from=/applications/${id}`}
class="no-underline"
><input
{#if !isSimpleDockerfile}
<div class="grid grid-cols-2 items-center">
<label for="gitSource">{$t('application.git_source')}</label>
{#if isDisabled || application.settings.isPublicRepository}
<input
disabled={isDisabled || application.settings.isPublicRepository}
class="w-full"
value={application.gitSource?.name}
id="gitSource"
class="cursor-pointer hover:bg-coolgray-500 w-full"
/></a
>
{/if}
</div>
<div class="grid grid-cols-2 items-center">
<label for="repository">Git commit</label>
<div class="flex gap-2">
<input
id="commit"
name="commit"
class="w-full"
disabled={isDisabled}
placeholder="default: latest commit"
bind:value={application.gitCommitHash}
/>
<a
href="{application.gitSource
.htmlUrl}/{application.repository}/commits/{application.branch}"
target="_blank noreferrer"
class="btn btn-primary text-xs"
>Commits<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="3"
stroke="currentColor"
class="w-3 h-3 text-white ml-2"
/>
{:else}
<a
href={`/applications/${id}/configuration/source?from=/applications/${id}`}
class="no-underline"
><input
value={application.gitSource?.name}
id="gitSource"
class="cursor-pointer hover:bg-coolgray-500 w-full"
/></a
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25"
/>
</svg></a
>
{/if}
</div>
</div>
<div class="grid grid-cols-2 items-center">
<label for="repository">{$t('application.git_repository')}</label>
{#if isDisabled || application.settings.isPublicRepository}
<input
class="w-full"
disabled={isDisabled || application.settings.isPublicRepository}
value="{application.repository}/{application.branch}"
/>
{:else}
<a
href={`/applications/${id}/configuration/repository?from=/applications/${id}&to=/applications/${id}/configuration/buildpack`}
class="no-underline"
><input
<div class="grid grid-cols-2 items-center">
<label for="repository">Git commit</label>
<div class="flex gap-2">
<input
id="commit"
name="commit"
class="w-full"
disabled={isDisabled}
placeholder="default: latest commit"
bind:value={application.gitCommitHash}
/>
<a
href="{application.gitSource
.htmlUrl}/{application.repository}/commits/{application.branch}"
target="_blank noreferrer"
class="btn btn-primary text-xs"
>Commits<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="3"
stroke="currentColor"
class="w-3 h-3 text-white ml-2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25"
/>
</svg></a
>
</div>
</div>
<div class="grid grid-cols-2 items-center">
<label for="repository">{$t('application.git_repository')}</label>
{#if isDisabled || application.settings.isPublicRepository}
<input
class="w-full"
disabled={isDisabled || application.settings.isPublicRepository}
value="{application.repository}/{application.branch}"
id="repository"
class="cursor-pointer hover:bg-coolgray-500 w-full"
/></a
>
{/if}
</div>
/>
{:else}
<a
href={`/applications/${id}/configuration/repository?from=/applications/${id}&to=/applications/${id}/configuration/buildpack`}
class="no-underline"
><input
value="{application.repository}/{application.branch}"
id="repository"
class="cursor-pointer hover:bg-coolgray-500 w-full"
/></a
>
{/if}
</div>
{:else}
{/if}
<div class="grid grid-cols-2 items-center">
<label for="registry">Docker Registry</label>
{#if isDisabled}
@@ -586,23 +592,29 @@
>
{/if}
</div>
<div class="grid grid-cols-2 items-center">
<label for="buildPack">{$t('application.build_pack')} </label>
{#if isDisabled}
<input class="capitalize w-full" disabled={isDisabled} value={application.buildPack} />
{:else}
<a
href={`/applications/${id}/configuration/buildpack?from=/applications/${id}`}
class="no-underline"
>
{#if !isSimpleDockerfile}
<div class="grid grid-cols-2 items-center">
<label for="buildPack">{$t('application.build_pack')} </label>
{#if isDisabled}
<input
class="capitalize w-full"
disabled={isDisabled}
value={application.buildPack}
id="buildPack"
class="cursor-pointer hover:bg-coolgray-500 capitalize w-full"
/></a
>
{/if}
</div>
/>
{:else}
<a
href={`/applications/${id}/configuration/buildpack?from=/applications/${id}`}
class="no-underline"
>
<input
value={application.buildPack}
id="buildPack"
class="cursor-pointer hover:bg-coolgray-500 capitalize w-full"
/></a
>
{/if}
</div>
{/if}
<div class="grid grid-cols-2 items-center">
<label for="destination">{$t('application.destination')}</label>
<div class="no-underline">
@@ -712,7 +724,44 @@
{/if}
{/if}
</div>
{#if application.buildPack !== 'compose'}
{#if isSimpleDockerfile}
<div class="title font-bold pb-3 pt-10 border-b border-coolgray-500 mb-6">
Configuration
</div>
<div class="grid grid-flow-row gap-2 px-4 pr-5">
<div class="grid grid-cols-2 items-center pt-4">
<label for="simpleDockerfile">Dockerfile</label>
<div class="flex gap-2">
<textarea
rows=10
id="simpleDockerfile"
name="simpleDockerfile"
class="w-full"
disabled={isDisabled}
bind:value={application.simpleDockerfile}
/>
</div>
</div>
<div class="grid grid-cols-2 items-center">
<label for="port"
>{$t('forms.port')}
<Explainer
explanation={'The port your application listens inside the docker container.'}
/></label
>
<input
class="w-full"
disabled={isDisabled}
readonly={!$appSession.isAdmin}
name="port"
id="port"
bind:value={application.port}
placeholder="{$t('forms.default')}: 3000"
/>
</div>
</div>
{:else if application.buildPack !== 'compose'}
<div class="title font-bold pb-3 pt-10 border-b border-coolgray-500 mb-6">
Configuration
</div>

View File

@@ -20,6 +20,7 @@
<script lang="ts">
export let secrets: any;
export let application: any;
export let previewSecrets: any;
import pLimit from 'p-limit';
import { page } from '$app/stores';
@@ -28,7 +29,6 @@
import Secret from './_Secret.svelte';
import PreviewSecret from './_PreviewSecret.svelte';
import { errorNotification } from '$lib/common';
import { t } from '$lib/translations';
import Explainer from '$lib/components/Explainer.svelte';
const limit = pLimit(1);
@@ -110,6 +110,7 @@
<div class="lg:pt-0 pt-10">
<Secret on:refresh={refreshSecrets} length={secrets.length} isNewSecret />
</div>
{#if !application.settings.isBot && !application.simpleDockerfile}
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2">
<div class="title font-bold pb-3 pt-8">
Preview Secrets <Explainer
@@ -133,6 +134,7 @@
{:else}
Add secrets first to see Preview Secrets.
{/if}
{/if}
</div>
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2 pt-10">

View File

@@ -86,7 +86,7 @@
<Storage on:refresh={refreshStorage} {storage} />
{/key}
{/each}
<div class="title pt-10">
<div class="Preview Secrets" class:pt-10={predefinedVolumes.length > 0}>
Add New Volume <Explainer
position="dropdown-bottom"
explanation={$t('application.storage.persistent_storage_explainer')}

View File

@@ -29,7 +29,7 @@
export let settings: any;
export let gitSources: any;
export let destinations: any;
let filtered: any = setInitials();
import { get, post } from '$lib/api';
import { t } from '$lib/translations';
@@ -151,7 +151,7 @@
}
async function getStatus(resources: any, force: boolean = false) {
const { id, buildPack, dualCerts, type } = resources;
const { id, buildPack, dualCerts, type, simpleDockerfile } = resources;
if (buildPack && applications.length + filtered.otherApplications.length > 10 && !force) {
noInitialStatus.applications = true;
return;
@@ -172,7 +172,7 @@
numberOfGetStatus++;
let isRunning = false;
let isDegraded = false;
if (buildPack) {
if (buildPack || simpleDockerfile) {
const response = await get(`/applications/${id}/status`);
if (response.length === 0) {
isRunning = false;