diff --git a/.env.example b/.env.example index f24762fab..dd4f03d08 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,7 @@ GROUPID= ############################################################################################################ APP_NAME=Laravel +APP_SERVICE=php APP_ENV=local APP_KEY= APP_DEBUG=true diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 77a715a14..1716e5c37 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -7,23 +7,34 @@ on: branches: [ "*" ] jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Build the Docker image - run: | - docker run --rm -u "$(id -u):$(id -g)" \ - -v "$(pwd):/app" \ - -w /app composer:2 \ - composer install --ignore-platform-reqs - TAG=$(date +%s) ./vendor/bin/sail build - TAG=$(date +%s) ./vendor/bin/sail up -d - sleep 1 - ./vendor/bin/sail ps - # Now to create .env - # Await database is created - # pest + - uses: actions/checkout@v3 + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: | + /usr/local/share/ca-certificates + /var/cache/apt/archives + /var/lib/apt/lists + ~/.cache + key: ${{ runner.os }}-docker-${{ hashFiles('**/Dockerfile') }} + restore-keys: | + ${{ runner.os }}-docker- + - name: Build the Docker image + run: | + cp .env.example .env + docker run --rm -u "$(id -u):$(id -g)" \ + -v "$(pwd):/app" \ + -w /app composer:2 \ + composer install --ignore-platform-reqs + ./vendor/bin/sail build + - name: Start the stack + run: | + ./vendor/bin/sail up -d + ./vendor/bin/sail artisan key:generate + ./vendor/bin/sail artisan migrate:fresh --seed + - name: Test (missing E2E tests) + run: | + ./vendor/bin/sail artisan test diff --git a/app/Models/User.php b/app/Models/User.php index 5ba3a299d..8c47df391 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -51,17 +51,21 @@ class User extends Authenticatable $model->uuid = (string) new Cuid2(7); }); } + public function teams() { return $this->belongsToMany(Team::class); } + public function currentTeam() { return $this->belongsTo(Team::class); } + public function otherTeams() { - $team_id = session('currentTeam')->id; + $team_id = data_get(session('currentTeam'), 'id'); + return auth()->user()->teams->filter(function ($team) use ($team_id) { return $team->id != $team_id; }); diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index a6ecc0af2..b0fc53227 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -19,6 +19,7 @@ class UserFactory extends Factory { return [ 'name' => fake()->name(), + 'uuid' => Str::uuid(), 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 63301e35c..70671dd98 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -10,13 +10,11 @@ class UserSeeder extends Seeder public function run(): void { User::factory()->create([ - 'id' => 1, 'name' => 'Root User', 'email' => 'test@example.com', 'is_root_user' => true, ]); User::factory()->create([ - 'id' => 2, 'name' => 'Normal User', 'email' => 'test2@example.com', ]); diff --git a/docker-compose.yaml b/docker-compose.yaml index 2b1379e2d..1e8869356 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,4 +1,16 @@ version: '3.8' + +x-testing-host: &testing-host-base + image: coolify-testing-host + build: + dockerfile: Dockerfile + context: ./docker/testing-host + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./docker/testing-host/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf + networks: + - coolify + services: php: image: "coolify:${TAG:-4}" @@ -19,6 +31,9 @@ services: - .:/var/www/html networks: - coolify + depends_on: + postgres: + condition: service_healthy postgres: image: postgres:15-alpine ports: @@ -36,34 +51,18 @@ services: test: [ "CMD-SHELL", - "pg_isready -U $$DB_USERNAME", + "pg_isready -U coolify", "-d", - "db_prod" + "coolify" ] - retries: 3 - timeout: 5s + retries: 5 + timeout: 10s testing-host: + <<: *testing-host-base container_name: coolify-testing-host - image: coolify-testing-host - build: - dockerfile: Dockerfile - context: ./docker/testing-host - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./docker/testing-host/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - networks: - - coolify testing-host2: + <<: *testing-host-base container_name: coolify-testing-host-2 - image: coolify-testing-host - build: - dockerfile: Dockerfile - context: ./docker/testing-host - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./docker/testing-host/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - networks: - - coolify volumes: db-coolify: diff --git a/docker/dev/supervisord.conf b/docker/dev/supervisord.conf index a50aad21c..b88d3ffa0 100644 --- a/docker/dev/supervisord.conf +++ b/docker/dev/supervisord.conf @@ -13,18 +13,20 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -[program:laravel-worker] -process_name=%(program_name)s_%(process_num)02d -command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan queue:listen -user=sail -autostart=true -autorestart=true -stopasgroup=true -killasgroup=true -numprocs=8 -redirect_stderr=true -stdout_logfile=/var/www/html/storage/logs/worker.log -stopwaitsecs=3600 +# Run workers by running manually `sail artisan queue:listen` +# +#[program:laravel-worker] +#process_name=%(program_name)s_%(process_num)02d +#command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan queue:listen +#user=sail +#autostart=true +#autorestart=true +#stopasgroup=true +#killasgroup=true +#numprocs=8 +#redirect_stderr=true +#stdout_logfile=/var/www/html/storage/logs/worker.log +#stopwaitsecs=3600 [program:laravel-schedule] process_name=%(program_name)s_%(process_num)02d diff --git a/run b/run new file mode 100755 index 000000000..81b90a608 --- /dev/null +++ b/run @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Inspired on https://github.com/adriancooney/Taskfile +# +# Install an alias, to be able to simply execute `run` +# echo 'alias run=./run' >> ~/.aliases +# + +# Define Docker Compose command prefix... +set -e + +docker compose &> /dev/null +if [ $? == 0 ]; then + DOCKER_COMPOSE="docker compose" +else + DOCKER_COMPOSE="docker-compose" +fi + +SAIL=./vendor/bin/sail +export WWWUSER=${WWWUSER:-$UID} +export WWWGROUP=${WWWGROUP:-$(id -g)} + +function help { + echo "$0 " + echo "Tasks:" + compgen -A function | cat -n +} + +function default { + help +} + +function wait_db { + TRIES=0 + MAX_TRIES=15 + WAIT=4 + + until $DOCKER_COMPOSE exec postgres bash -c "psql -U coolify -d coolify -t -q -c \"SELECT datname FROM pg_database;\" " | grep coolify + do + ((TRIES++)) + if [ $TRIES -gt $MAX_TRIES ]; then + echo "Database is not ready after $MAX_TRIES tries. Exiting." + exit 1 + fi + echo "Database is not ready yet. Attempt $TRIES/$MAX_TRIES. Waiting $WAIT seconds before next try..." + sleep $WAIT + done +} + +TIMEFORMAT="Task completed in %3lR" +time "${@:-default}" diff --git a/tests/Feature/DockerCommandsTest.php b/tests/Feature/DockerCommandsTest.php index 377777921..f7b88de6c 100644 --- a/tests/Feature/DockerCommandsTest.php +++ b/tests/Feature/DockerCommandsTest.php @@ -1,11 +1,29 @@ seed(DatabaseSeeder::class); +}); it('starts a docker container correctly', function () { + test()->actingAs(User::factory([ + 'uuid' => Str::uuid(), + 'email' => Str::uuid().'@example.com', + ])->create()); + $coolifyNamePrefix = 'coolify_test_'; + + $format = '{"ID":"{{ .ID }}", "Image": "{{ .Image }}", "Names":"{{ .Names }}"}'; $areThereCoolifyTestContainers = "docker ps --filter=\"name={$coolifyNamePrefix}*\" --format '{$format}' "; @@ -13,6 +31,19 @@ it('starts a docker container correctly', function () { $containerName = 'coolify_test_' . now()->format('Ymd_his'); $host = Server::where('name', 'testing-local-docker-container')->first(); + // Stop testing containers + $activity = remoteProcess([ + "docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + "docker rm $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + ], $host); + + throw_if( + $activity->getExtraProperty('exitCode') !== 0, + new RuntimeException($activity->description), + ); + + expect($activity->getExtraProperty('exitCode'))->toBe(0); + // Assert there's no containers start with coolify_test_* $activity = remoteProcess([$areThereCoolifyTestContainers], $host); $containers = formatDockerCmdOutputToJson($activity->getExtraProperty('stdout')); @@ -28,6 +59,9 @@ it('starts a docker container correctly', function () { expect($containers->where('Names', $containerName)->count())->toBe(1); // Stop testing containers - $activity = remoteProcess(["docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -q)"], $host); + $activity = remoteProcess([ + "docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + "docker rm $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + ], $host); expect($activity->getExtraProperty('exitCode'))->toBe(0); });