Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.0.0-beta.391 #5051

Merged
merged 48 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
1d4f057
feat(changelog): Add git cliff for automatic changelog generation
peaklabs-dev Jan 20, 2025
c4735f2
feat(workflows): improve changelog generation and workflows
peaklabs-dev Jan 22, 2025
1bdde5c
Merge branch 'next' into git-cliff
peaklabs-dev Jan 22, 2025
c037835
chore(workflows): make naming more clear and remove unused code
peaklabs-dev Jan 22, 2025
f554764
chore(version): bump Coolify version to 4.0.0-beta.391
andrasbacsai Jan 28, 2025
98a9985
feat(vite): add Cloudflare async script and style tag attributes
andrasbacsai Jan 28, 2025
a764a07
revert: remove Cloudflare async tag attributes
andrasbacsai Jan 28, 2025
dde6128
replace logo
andrasbacsai Jan 31, 2025
58c6e9c
change dev logo
andrasbacsai Jan 31, 2025
83f0f9f
fix(core): improve public repository URL parsing for branch and base …
andrasbacsai Jan 31, 2025
672a5d0
fix: Handle pullrequest:updated for reliable preview deployments
IARayan Feb 1, 2025
2c80595
Merge branch 'next' into IARayan-bitbucket-preview-deployment-fix-pul…
IARayan Feb 1, 2025
b1d6167
feat: add application api route
Vann-Dev Feb 1, 2025
e7988fc
feat: container logs
Vann-Dev Feb 1, 2025
a671dd4
fix(ui): align title and add button vertically in various views
angristan Feb 1, 2025
43e8d17
fix(api): domain check when updating domain
sistracia Feb 2, 2025
7b60d76
feat: remove ansi color from log
Vann-Dev Feb 2, 2025
8be536d
fix(core): increase HTTP/2 max concurrent streams to 250 (default)
andrasbacsai Feb 2, 2025
dea3b36
feat(meta): add comprehensive SEO and social media meta tags
andrasbacsai Feb 2, 2025
11a5ec7
feat: add lines query parameter
Vann-Dev Feb 2, 2025
85ad048
Adds bugsink template
jlengrand Feb 2, 2025
cd2ee25
fix(ui): update docker compose file helper text to clarify repository…
andrasbacsai Feb 3, 2025
0ff7c46
fix(ui): skip SERVICE_FQDN and SERVICE_URL variables during update
andrasbacsai Feb 3, 2025
d7885a3
docs(services): reword nitropage url and slogan
katywings Feb 3, 2025
2a03544
fix(core): stopping database is not disabling db proxy
andrasbacsai Feb 3, 2025
773caf7
feat(core): add name to default proxy configuration
andrasbacsai Feb 3, 2025
1e9a4aa
fix(core): remove --remove-orphans flag from proxy startup command to…
andrasbacsai Feb 3, 2025
035db67
Merge pull request #5036 from sistracia/next
andrasbacsai Feb 3, 2025
c45c64a
fix(ui): always redirect to dashboard after team switch
andrasbacsai Feb 3, 2025
f4575e5
fix(backup): escape special characters in database backup commands
andrasbacsai Feb 3, 2025
4c9aa24
Merge branch 'main' into next
peaklabs-dev Feb 3, 2025
2e65249
chore: add openapi response
Vann-Dev Feb 4, 2025
3da921e
fix(core): improve deployment failure Slack notification formatting
andrasbacsai Feb 4, 2025
df129b8
fix(core): update Slack notification formatting to use bold correctly
andrasbacsai Feb 4, 2025
fbb6ce3
fix(core): enhance Slack deployment success notification formatting
andrasbacsai Feb 4, 2025
5756873
chore(config): increase default PHP memory limit to 256M
andrasbacsai Feb 4, 2025
3d6eee4
Merge pull request #5049 from katywings/nitropage
andrasbacsai Feb 4, 2025
d8aae12
docs(readme): add Convex to special sponsors section
andrasbacsai Feb 4, 2025
8033a89
fix(ui): simplify service templates loading logic
andrasbacsai Feb 4, 2025
bd6674f
update service templates
andrasbacsai Feb 4, 2025
30fd26d
Merge pull request #5044 from jlengrand/feat/bugsink
andrasbacsai Feb 4, 2025
3824d88
update service template
andrasbacsai Feb 4, 2025
186a3fc
Merge pull request #5038 from Vann-Dev/main
andrasbacsai Feb 4, 2025
d87d3b8
Merge pull request #5033 from angristan/align-items-center
andrasbacsai Feb 4, 2025
65a7610
Merge pull request #5029 from IARayan/IARayan-bitbucket-preview-deplo…
andrasbacsai Feb 4, 2025
8b8ae17
Merge pull request #4929 from coollabsio/git-cliff
andrasbacsai Feb 4, 2025
d632eb2
refactor: simplify service start and restart workflows
andrasbacsai Feb 4, 2025
a5ca90c
feat(ui): add periodic status checking for services
andrasbacsai Feb 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/coolify-production-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
- docker/coolify-realtime/Dockerfile
- docker/testing-host/Dockerfile
- templates/**
- CHANGELOG.md

env:
GITHUB_REGISTRY: ghcr.io
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/coolify-staging-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
- docker/coolify-realtime/Dockerfile
- docker/testing-host/Dockerfile
- templates/**
- CHANGELOG.md

env:
GITHUB_REGISTRY: ghcr.io
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/generate-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Generate Changelog

on:
push:
branches: [ main ]
workflow_dispatch:

permissions:
contents: write

jobs:
changelog:
name: Generate changelog
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Generate changelog
uses: orhun/git-cliff-action@v4
with:
config: cliff.toml
args: --verbose
env:
OUTPUT: CHANGELOG.md
GITHUB_REPO: ${{ github.repository }}

- name: Commit
run: |
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add CHANGELOG.md
git commit -m "docs: update changelog"
git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git main
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ scripts/load-test/*
.env.dusk.local
docker/coolify-realtime/node_modules
.DS_Store
Changelog.md
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Special thanks to our biggest sponsors!
* [SupaGuide](https://supa.guide/?ref=coolify.io) - A comprehensive resource hub offering guides and tutorials for web development using Supabase.
* [GoldenVM](https://billing.goldenvm.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
* [Tigris](https://tigrisdata.com/?ref=coolify.io) - A fully managed serverless object storage service compatible with Amazon S3 API. Offers high performance, scalability, and built-in search capabilities for efficient data management.
* [Convex](https://convex.link/coolify.io) - Convex is the open-source reactive database for web app developers.
* [Cloudify.ro](https://cloudify.ro/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
* [Syntaxfm](https://syntax.fm/?ref=coolify.io) - Podcast for web developers.
* [PFGlabs](https://pfglabs.com/?ref=coolify.io) - Build real project with Golang.
Expand Down
1 change: 0 additions & 1 deletion app/Actions/Database/StopDatabaseProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
}
instant_remote_process(["docker rm -f {$uuid}-proxy"], $server);

$database->is_public = false;
$database->save();

DatabaseProxyStopped::dispatch();
Expand Down
2 changes: 1 addition & 1 deletion app/Actions/Proxy/StartProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function handle(Server $server, bool $async = true, bool $force = false):
" echo 'Successfully stopped and removed existing coolify-proxy.'",
'fi',
"echo 'Starting coolify-proxy.'",
'docker compose up -d --remove-orphans',
'docker compose up -d',
"echo 'Successfully started coolify-proxy.'",
]);
$commands = $commands->merge(connectProxyToNetworks($server));
Expand Down
13 changes: 9 additions & 4 deletions app/Actions/Service/StartService.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@ class StartService

public string $jobQueue = 'high';

public function handle(Service $service)
public function handle(Service $service, bool $pullLatestImages = false, bool $stopBeforeStart = false)
{
$service->parse();
if ($stopBeforeStart) {
StopService::run(service: $service, dockerCleanup: false);
}
$service->saveComposeConfigs();
$commands[] = 'cd '.$service->workdir();
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
if ($pullLatestImages) {
$commands[] = "echo 'Pulling images.'";
$commands[] = 'docker compose pull';
}
if ($service->networks()->count() > 0) {
$commands[] = "echo 'Creating Docker network.'";
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
}
$commands[] = 'echo Starting service.';
$commands[] = "echo 'Pulling images.'";
$commands[] = 'docker compose pull';
$commands[] = "echo 'Starting containers.'";
$commands[] = 'docker compose up -d --remove-orphans --force-recreate --build';
$commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true";
if (data_get($service, 'connect_to_docker_network')) {
Expand Down
28 changes: 0 additions & 28 deletions app/Actions/Shared/PullImage.php

This file was deleted.

107 changes: 105 additions & 2 deletions app/Http/Controllers/Api/ApplicationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,108 @@ public function application_by_uuid(Request $request)
return response()->json($this->removeSensitiveData($application));
}

#[OA\Get(
summary: 'Get application logs.',
description: 'Get application logs by UUID.',
path: '/applications/{uuid}/logs',
operationId: 'get-application-logs-by-uuid',
security: [
['bearerAuth' => []],
],
tags: ['Applications'],
parameters: [
new OA\Parameter(
name: 'uuid',
in: 'path',
description: 'UUID of the application.',
required: true,
schema: new OA\Schema(
type: 'string',
format: 'uuid',
)
),
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs.',
required: false,
schema: new OA\Schema(
type: 'integer',
format: 'int32',
default: 100,
)
),
],
responses: [
new OA\Response(
response: 200,
description: 'Get application logs by UUID.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'logs' => ['type' => 'string'],
]
)
),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
),
new OA\Response(
response: 400,
ref: '#/components/responses/400',
),
new OA\Response(
response: 404,
ref: '#/components/responses/404',
),
]
)]
public function logs_by_uuid(Request $request)
{
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
return invalidTokenResponse();
}
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['message' => 'UUID is required.'], 400);
}
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
if (! $application) {
return response()->json(['message' => 'Application not found.'], 404);
}

$containers = getCurrentApplicationContainerStatus($application->destination->server, $application->id);

if ($containers->count() == 0) {
return response()->json([
'message' => 'Application is not running.',
], 400);
}

$container = $containers->first();

$status = getContainerStatus($application->destination->server, $container['Names']);
if ($status !== 'running') {
return response()->json([
'message' => 'Application is not running.',
], 400);
}

$lines = $request->query->get('lines', 100) ?: 100;
$logs = getContainerLogs($application->destination->server, $container['ID'], $lines);

return response()->json([
'logs' => $logs,
]);
}

#[OA\Delete(
summary: 'Delete',
description: 'Delete application by UUID.',
Expand Down Expand Up @@ -1681,7 +1783,8 @@ public function update_by_uuid(Request $request)
], 422);
}
$domains = $request->domains;
if ($request->has('domains') && $server->isProxyShouldRun()) {
$requestHasDomains = $request->has('domains');
if ($requestHasDomains && $server->isProxyShouldRun()) {
$uuid = $request->uuid;
$fqdn = $request->domains;
$fqdn = str($fqdn)->replaceEnd(',', '')->trim();
Expand Down Expand Up @@ -1743,7 +1846,7 @@ public function update_by_uuid(Request $request)
removeUnnecessaryFieldsFromRequest($request);

$data = $request->all();
if ($request->has('domains') && $server->isProxyShouldRun()) {
if ($requestHasDomains && $server->isProxyShouldRun()) {
data_set($data, 'fqdn', $domains);
}

Expand Down
9 changes: 5 additions & 4 deletions app/Http/Controllers/Webhook/Bitbucket.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function manual(Request $request)
$headers = $request->headers->all();
$x_bitbucket_token = data_get($headers, 'x-hub-signature.0', '');
$x_bitbucket_event = data_get($headers, 'x-event-key.0', '');
$handled_events = collect(['repo:push', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
$handled_events = collect(['repo:push', 'pullrequest:updated', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
if (! $handled_events->contains($x_bitbucket_event)) {
return response([
'status' => 'failed',
Expand All @@ -48,14 +48,15 @@ public function manual(Request $request)
$branch = data_get($payload, 'push.changes.0.new.name');
$full_name = data_get($payload, 'repository.full_name');
$commit = data_get($payload, 'push.changes.0.new.target.hash');
if (! $branch) {

if (!$branch) {
return response([
'status' => 'failed',
'message' => 'Nothing to do. No branch found in the request.',
]);
}
}
if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') {
if ($x_bitbucket_event === 'pullrequest:updated' || $x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') {
$branch = data_get($payload, 'pullrequest.destination.branch.name');
$base_branch = data_get($payload, 'pullrequest.source.branch.name');
$full_name = data_get($payload, 'repository.full_name');
Expand Down Expand Up @@ -119,7 +120,7 @@ public function manual(Request $request)
]);
}
}
if ($x_bitbucket_event === 'pullrequest:created') {
if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:updated') {
if ($application->isPRDeployable()) {
$deployment_uuid = new Cuid2;
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
Expand Down
20 changes: 10 additions & 10 deletions app/Jobs/DatabaseBackupJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,9 @@ private function backup_standalone_mongodb(string $databaseWithCollections): voi
if ($databaseWithCollections === 'all') {
$commands[] = 'mkdir -p '.$this->backup_dir;
if (str($this->database->image)->startsWith('mongo:4')) {
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
$commands[] = "docker exec $this->container_name mongodump --uri=\"$url\" --gzip --archive > $this->backup_location";
} else {
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --gzip --archive > $this->backup_location";
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=\"$url\" --gzip --archive > $this->backup_location";
}
} else {
if (str($databaseWithCollections)->contains(':')) {
Expand All @@ -361,15 +361,15 @@ private function backup_standalone_mongodb(string $databaseWithCollections): voi
$commands[] = 'mkdir -p '.$this->backup_dir;
if ($collectionsToExclude->count() === 0) {
if (str($this->database->image)->startsWith('mongo:4')) {
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
$commands[] = "docker exec $this->container_name mongodump --uri=\"$url\" --gzip --archive > $this->backup_location";
} else {
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --archive > $this->backup_location";
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=\"$url\" --db $databaseName --gzip --archive > $this->backup_location";
}
} else {
if (str($this->database->image)->startsWith('mongo:4')) {
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --excludeCollection ".$collectionsToExclude->implode(' --excludeCollection ')." --archive > $this->backup_location";
} else {
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --excludeCollection ".$collectionsToExclude->implode(' --excludeCollection ')." --archive > $this->backup_location";
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=\"$url\" --db $databaseName --gzip --excludeCollection ".$collectionsToExclude->implode(' --excludeCollection ')." --archive > $this->backup_location";
}
}
}
Expand Down Expand Up @@ -415,9 +415,9 @@ private function backup_standalone_mysql(string $database): void
try {
$commands[] = 'mkdir -p '.$this->backup_dir;
if ($this->backup->dump_all) {
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} --all-databases --single-transaction --quick --lock-tables=false --compress | gzip > $this->backup_location";
$commands[] = "docker exec $this->container_name mysqldump -u root -p\"{$this->database->mysql_root_password}\" --all-databases --single-transaction --quick --lock-tables=false --compress | gzip > $this->backup_location";
} else {
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} $database > $this->backup_location";
$commands[] = "docker exec $this->container_name mysqldump -u root -p\"{$this->database->mysql_root_password}\" $database > $this->backup_location";
}
$this->backup_output = instant_remote_process($commands, $this->server);
$this->backup_output = trim($this->backup_output);
Expand All @@ -435,9 +435,9 @@ private function backup_standalone_mariadb(string $database): void
try {
$commands[] = 'mkdir -p '.$this->backup_dir;
if ($this->backup->dump_all) {
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} --all-databases --single-transaction --quick --lock-tables=false --compress > $this->backup_location";
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p\"{$this->database->mariadb_root_password}\" --all-databases --single-transaction --quick --lock-tables=false --compress > $this->backup_location";
} else {
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location";
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p\"{$this->database->mariadb_root_password}\" $database > $this->backup_location";
}
$this->backup_output = instant_remote_process($commands, $this->server);
$this->backup_output = trim($this->backup_output);
Expand Down Expand Up @@ -495,7 +495,7 @@ private function upload_to_s3(): void
} else {
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro {$fullImageName}";
}
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret";
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key \"$secret\"";
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/";
instant_remote_process($commands, $this->server);

Expand Down
13 changes: 12 additions & 1 deletion app/Livewire/Project/New/PublicGitRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,22 @@ public function loadBranch()

private function getGitSource()
{
$this->git_branch = 'main';
$this->base_directory = '/';

$this->repository_url_parsed = Url::fromString($this->repository_url);
$this->git_host = $this->repository_url_parsed->getHost();
$this->git_repository = $this->repository_url_parsed->getSegment(1).'/'.$this->repository_url_parsed->getSegment(2);

if ($this->repository_url_parsed->getSegment(3) === 'tree') {
$this->git_branch = str($this->repository_url_parsed->getPath())->after('tree/')->value();
$path = str($this->repository_url_parsed->getPath())->trim('/');
$this->git_branch = str($path)->after('tree/')->before('/')->value();
$this->base_directory = str($path)->after($this->git_branch)->after('/')->value();
if (filled($this->base_directory)) {
$this->base_directory = '/'.$this->base_directory;
} else {
$this->base_directory = '/';
}
} else {
$this->git_branch = 'main';
}
Expand Down
Loading