From b1ad1480af1c6e8a3d3dd95a6f8372d1ed63a5ea Mon Sep 17 00:00:00 2001 From: merge-check <140916359+agentHits@users.noreply.github.com> Date: Wed, 7 Oct 2026 08:35:00 -0400 Subject: [PATCH 1/3] ci: run owner pull request checks on the self-hosted mac mini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Что: - Проверки PR (audit, build, test, typecheck) для PR владельца из этого репозитория идут на self-hosted раннерах с меткой dokploy-ci. - PR из форков и от других авторов остаются на ubuntu-latest. - Nixpacks/Railpack ставятся только на GitHub-раннерах; swarm init пропускается, если swarm уже активен. - Добавлены concurrency по номеру PR и timeout-minutes: 30. Зачем: - На раннерах GitHub проверки идут около 5 минут; на Mac mini install/typecheck/build/test быстрее за счёт тёплого кэша. Риски: - Репозиторий публичный: PR из форка может переписать runs-on, поэтому в настройках включено одобрение запусков для всех внешних участников. - Тесты делят Docker (OrbStack) на Mac mini с другими нагрузками. Проверки: - Команды и результаты: на Mac mini bun install (тёплый кэш) 15 с, typecheck 12 с, build 82 с, unit-тесты 69 с; итоговый прогон - в этом PR. - Ограничения: сборка Docker-образа остаётся на GitHub (amd64 под эмуляцией на Mac mini медленнее: 18 мин с нуля). What: - PR checks (audit, build, test, typecheck) for the owner's PRs from this repository run on self-hosted runners labelled dokploy-ci. - Fork PRs and PRs by other authors stay on ubuntu-latest. - Nixpacks/Railpack are installed only on GitHub runners; swarm init is skipped when the swarm is already active. - Added per-PR concurrency and timeout-minutes: 30. Why: - On GitHub runners the checks take about 5 minutes; on the Mac mini install/typecheck/build/test are faster with a warm cache. Risks: - The repository is public: a fork PR can rewrite runs-on, so the repo now requires approval for runs from every outside contributor. - Tests share Docker (OrbStack) on the Mac mini with other workloads. Checks: - Commands and results: on the Mac mini bun install (warm cache) 15 s, typecheck 12 s, build 82 s, unit tests 69 s; full run happens in this PR. - Limitations: the Docker image build stays on GitHub (amd64 under emulation on the Mac mini is slower: 18 min from scratch). Co-Authored-By: Claude Opus 5.5 --- .github/workflows/pull-request.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 2a514b4046f..7a1da6a124c 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -7,9 +7,16 @@ on: permissions: contents: read +concurrency: + group: pull-request-${{ github.event.pull_request.number }} + cancel-in-progress: true + jobs: audit: - runs-on: ubuntu-latest + # Only the owner's own PRs reach the Mac mini runners. A fork PR could rewrite + # this line, so the repo also requires approval for every outside contributor. + runs-on: ${{ (github.event.pull_request.user.login == github.repository_owner && github.event.pull_request.head.repo.full_name == github.repository) && fromJSON('["self-hosted", "dokploy-ci"]') || 'ubuntu-latest' }} + timeout-minutes: 30 steps: - uses: actions/checkout@v7 with: @@ -21,7 +28,8 @@ jobs: - run: bun audit --audit-level=moderate --ignore GHSA-vfj7-8cjw-p6xm pr-check: - runs-on: ubuntu-latest + runs-on: ${{ (github.event.pull_request.user.login == github.repository_owner && github.event.pull_request.head.repo.full_name == github.repository) && fromJSON('["self-hosted", "dokploy-ci"]') || 'ubuntu-latest' }} + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -38,14 +46,14 @@ jobs: node-version: 24.4.0 - name: Install Nixpacks - if: matrix.job == 'test' + if: matrix.job == 'test' && runner.environment == 'github-hosted' run: | export NIXPACKS_VERSION=1.41.0 curl -sSL https://nixpacks.com/install.sh | bash echo "Nixpacks installed $NIXPACKS_VERSION" - name: Install Railpack - if: matrix.job == 'test' + if: matrix.job == 'test' && runner.environment == 'github-hosted' run: | export RAILPACK_VERSION=0.15.4 curl -sSL https://railpack.com/install.sh | bash @@ -58,7 +66,10 @@ jobs: - name: Initialize Docker Swarm if: matrix.job == 'test' run: | - docker swarm init + # The Mac mini keeps its swarm between runs. + if [ "$(docker info --format '{{.Swarm.LocalNodeState}}')" != "active" ]; then + docker swarm init + fi docker network create --driver overlay dokploy-network || true echo "✅ Docker Swarm initialized" From db78c6a49667885aeb4df8f92d27b6e0ec1b256f Mon Sep 17 00:00:00 2001 From: merge-check <140916359+agentHits@users.noreply.github.com> Date: Wed, 7 Oct 2026 08:53:40 -0400 Subject: [PATCH 2/3] test: give the super password alert sweep a 30 s timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Что: - Тесту "covers every super password event with no secrets in the payloads" дан таймаут 30 с вместо стандартных 5 с. Зачем: - В тесте около 20 вызовов bcrypt; на Mac mini, когда все ядра заняты воркерами vitest и next build, он стабильно не укладывался в 5 с, а следующий тест падал каскадом с "duplicate key in super_password". Риски: - Не выявлены: меняется только таймаут теста. Проверки: - Команды и результаты: bun run test -- --run __test__/security/super-password-alerts.test.ts - 10/10; biome check - ок. - Ограничения: полный прогон - в CI этого PR. What: - The test "covers every super password event with no secrets in the payloads" gets a 30 s timeout instead of the default 5 s. Why: - It runs about 20 bcrypt calls; on the Mac mini, with every core busy with vitest workers and next build, it kept missing 5 s, and the next test then failed in cascade with "duplicate key in super_password". Risks: - None identified: only the test timeout changes. Checks: - Commands and results: bun run test -- --run __test__/security/super-password-alerts.test.ts - 10/10; biome check - ok. - Limitations: the full run happens in this PR's CI. Co-Authored-By: Claude Opus 5.5 --- apps/dokploy/__test__/security/super-password-alerts.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/__test__/security/super-password-alerts.test.ts b/apps/dokploy/__test__/security/super-password-alerts.test.ts index 07f04fb6218..30bb9ce0134 100644 --- a/apps/dokploy/__test__/security/super-password-alerts.test.ts +++ b/apps/dokploy/__test__/security/super-password-alerts.test.ts @@ -318,6 +318,7 @@ describe("super password alerts", () => { ]); }); + // About 20 bcrypt hashes run here; with every CPU core busy they exceed 5 s. it("covers every super password event with no secrets in the payloads", async () => { seedTelegram("alerts", { messageThreadId: "42" }); seedDiscord("backup"); @@ -428,7 +429,7 @@ describe("super password alerts", () => { telegramCalls().map(([, text, buttons]) => ({ text, buttons })), ); expect(telegramOnly).not.toContain("super-password-reset?token="); - }); + }, 30_000); it("puts the one-time lock link on opened and extended alerts as a Telegram button", async () => { seedTelegram("alerts"); From 82bd28c65915fe553a3136e909fc9f04eaac3371 Mon Sep 17 00:00:00 2001 From: merge-check <140916359+agentHits@users.noreply.github.com> Date: Wed, 7 Oct 2026 09:08:03 -0400 Subject: [PATCH 3/3] ci: run docker-backed tests as a separate pull request job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Что: - Тесты *.real.test.ts (настоящий Docker, ~3 мин) вынесены в отдельную задачу матрицы test-real; задача test запускает остальные тесты. - Установка Nixpacks/Railpack и инициализация swarm теперь только в test-real. - Имена проверок остаются вида pr-check (). Зачем: - test-real идёт параллельно с build, test и typecheck на третьем раннере Mac mini, общая длительность проверок PR сокращается. Риски: - Проверка pr-check (test-real) новая; если её когда-нибудь сделают обязательной, это надо учесть. Проверки: - Команды и результаты: локально bun run test -- real.test.ts выбирает ровно 2 файла; --exclude "**/*.real.test.ts" доходит до vitest. - Ограничения: полный прогон - в CI этого PR. What: - *.real.test.ts (real Docker, ~3 min) moved into a separate test-real matrix job; the test job runs the remaining tests. - Nixpacks/Railpack install and swarm init now run only in test-real. - Check names stay pr-check (). Why: - test-real runs in parallel with build, test and typecheck on a third Mac mini runner, so PR checks finish sooner. Risks: - pr-check (test-real) is a new check name; keep that in mind if checks ever become required. Checks: - Commands and results: locally bun run test -- real.test.ts selects exactly 2 files; --exclude "**/*.real.test.ts" reaches vitest. - Limitations: the full run happens in this PR's CI. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/pull-request.yml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 7a1da6a124c..3a38f964c34 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -28,12 +28,22 @@ jobs: - run: bun audit --audit-level=moderate --ignore GHSA-vfj7-8cjw-p6xm pr-check: + name: pr-check (${{ matrix.job }}) runs-on: ${{ (github.event.pull_request.user.login == github.repository_owner && github.event.pull_request.head.repo.full_name == github.repository) && fromJSON('["self-hosted", "dokploy-ci"]') || 'ubuntu-latest' }} timeout-minutes: 30 strategy: fail-fast: false matrix: - job: [build, test, typecheck] + include: + - job: build + command: bun run build + - job: test + command: bun run test -- --exclude "**/*.real.test.ts" + # Docker-backed tests take ~3 minutes, so they get their own runner. + - job: test-real + command: bun run test -- real.test.ts + - job: typecheck + command: bun run typecheck steps: - uses: actions/checkout@v7 with: @@ -46,25 +56,25 @@ jobs: node-version: 24.4.0 - name: Install Nixpacks - if: matrix.job == 'test' && runner.environment == 'github-hosted' + if: matrix.job == 'test-real' && runner.environment == 'github-hosted' run: | export NIXPACKS_VERSION=1.41.0 curl -sSL https://nixpacks.com/install.sh | bash echo "Nixpacks installed $NIXPACKS_VERSION" - name: Install Railpack - if: matrix.job == 'test' && runner.environment == 'github-hosted' + if: matrix.job == 'test-real' && runner.environment == 'github-hosted' run: | export RAILPACK_VERSION=0.15.4 curl -sSL https://railpack.com/install.sh | bash echo "Railpack installed $RAILPACK_VERSION" - name: Add build tools to PATH - if: matrix.job == 'test' + if: matrix.job == 'test-real' run: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Initialize Docker Swarm - if: matrix.job == 'test' + if: matrix.job == 'test-real' run: | # The Mac mini keeps its swarm between runs. if [ "$(docker info --format '{{.Swarm.LocalNodeState}}')" != "active" ]; then @@ -75,7 +85,7 @@ jobs: - run: bun install --frozen-lockfile - run: bun run server:build - - run: bun run ${{ matrix.job }} + - run: ${{ matrix.command }} env: # The fork's db module throws without a password in production, and the Next build imports it. POSTGRES_PASSWORD: ${{ matrix.job == 'build' && 'build-time-postgres-password' || '' }}