Repository navigation
163 lines (152 loc) · 7.61 KB
/
Copy pathpull-request.yml
File metadata and controls
163 lines (152 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
name: Pull Request
on:
pull_request:
branches: [main, canary, AgentHits-Dev]
# deps-auto-update.yml starts the checks of its branch this way: a push with
# GITHUB_TOKEN creates no pull_request event.
workflow_dispatch:
permissions:
contents: read
concurrency:
group: pull-request-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
audit:
name: audit and typecheck
# 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-24.04' }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- run: bun audit --audit-level=moderate
- uses: actions/setup-node@v7
if: ${{ !cancelled() }}
with:
node-version-file: .nvmrc
- run: bun install --frozen-lockfile
if: ${{ !cancelled() }}
- run: bun run server:build
if: ${{ !cancelled() }}
- run: bun run typecheck
if: ${{ !cancelled() }}
pr-check:
name: pr-check (${{ matrix.part }})
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-24.04' }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
# The real-Docker tests wait on Swarm's own timers for minutes. In one job they
# held most of vitest's workers from the start, and most unit tests ran only in
# the last minutes, so each group of tests gets a runner of its own.
part: [build, unit, docker-1, docker-2]
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
- name: Install Nixpacks
if: matrix.part != 'build' && runner.environment == 'github-hosted'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
NIXPACKS_VERSION="$(sed -n "s/^ARG NIXPACKS_VERSION=//p" Dockerfile)"
scripts/github-release-asset.sh railwayapp/nixpacks "v$NIXPACKS_VERSION" "nixpacks-v$NIXPACKS_VERSION-$(uname -m)-unknown-linux-musl.tar.gz" "$RUNNER_TEMP/nixpacks.tar.gz"
sudo tar -xzf "$RUNNER_TEMP/nixpacks.tar.gz" -C /usr/local/bin nixpacks
echo "Nixpacks installed $NIXPACKS_VERSION"
- name: Install Railpack
if: matrix.part != 'build' && runner.environment == 'github-hosted'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
RAILPACK_VERSION="$(sed -n "s/^ARG RAILPACK_VERSION=//p" Dockerfile)"
scripts/github-release-asset.sh railwayapp/railpack "v$RAILPACK_VERSION" "railpack-v$RAILPACK_VERSION-$(uname -m | sed s/aarch64/arm64/)-unknown-linux-musl.tar.gz" "$RUNNER_TEMP/railpack.tar.gz"
sudo tar -xzf "$RUNNER_TEMP/railpack.tar.gz" -C /usr/local/bin railpack
# The mise Railpack pins, where Railpack looks for it (see Dockerfile).
MISE_VERSION="$(sed -n "s/^ARG MISE_VERSION=//p" Dockerfile)"
scripts/github-release-asset.sh jdx/mise "v$MISE_VERSION" "mise-v$MISE_VERSION-linux-$(uname -m | sed 's/x86_64/x64/; s/aarch64/arm64/')-musl.tar.gz" "$RUNNER_TEMP/mise.tar.gz"
mkdir -p /tmp/railpack/mise
tar -xzf "$RUNNER_TEMP/mise.tar.gz" -O mise/bin/mise > "/tmp/railpack/mise/mise-$MISE_VERSION"
chmod 0755 "/tmp/railpack/mise/mise-$MISE_VERSION"
echo "Railpack installed $RAILPACK_VERSION"
- name: Add build tools to PATH
if: matrix.part != 'build'
run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Initialize Docker Swarm
if: matrix.part != 'build'
run: |
# 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"
- run: bun install --frozen-lockfile
- run: bun run server:build
- run: bun run build
if: matrix.part == 'build'
env:
# The fork's db module throws without a password in production, and the Next build imports it.
POSTGRES_PASSWORD: build-time-postgres-password
# A table or column in the schema without a migration builds and passes
# every test, then fails on the panel's database: #201 shipped
# libsql_grpc_ca that way. drizzle-kit writes a migration for the gap.
- name: Check that the migrations match the schema
if: matrix.part == 'build'
working-directory: apps/dokploy
run: |
set -euo pipefail
./node_modules/.bin/drizzle-kit generate --name schema-drift --config ./server/db/drizzle.config.ts
if [ -n "$(git status --porcelain -- drizzle)" ]; then
git status --porcelain -- drizzle
echo "::error::The schema has changes without a migration: run 'bun run migration:generate' in apps/dokploy and commit the files."
exit 1
fi
- name: Run the ${{ matrix.part }} tests
if: matrix.part != 'build'
working-directory: apps/dokploy
env:
PART: ${{ matrix.part }}
POSTGRES_PASSWORD: ""
run: |
set -euo pipefail
# docker-2 takes every real-Docker file not listed here, so a new one runs without an edit.
docker_1=(
__test__/docker/swarm-convergence.real.test.ts
__test__/docker/swarm-convergence-failures.real.test.ts
__test__/deploy/application.real.test.ts
__test__/database/libsql-replica.real.test.ts
__test__/docker/compose-containers.real.test.ts
)
for file in "${docker_1[@]}"; do
[ -f "$file" ] || { echo "::error::$file is listed for docker-1 but does not exist"; exit 1; }
done
case "$PART" in
unit) files=(--exclude '**/*.real.test.ts') ;;
docker-1) files=("${docker_1[@]}") ;;
docker-2) mapfile -t files < <(git ls-files '*.real.test.ts' | grep -vxF -f <(printf '%s\n' "${docker_1[@]}")) ;;
esac
./node_modules/.bin/vitest run --config __test__/vitest.config.ts "${files[@]}"
# Tests remove their swarm services and compose projects, but a cancelled or
# timed-out run skips that. Docker is shared by all Mac mini runners, so only this checkout's
# apps go (see CHECKOUT_ID in application.real.test.ts).
- name: Remove leftover real-test services
if: always() && matrix.part != 'build'
working-directory: apps/dokploy
run: |
id="$(printf %s "$PWD" | shasum -a 256 | cut -c1-8)"
docker service ls --format '{{.Name}}' | grep -E "^real-[a-z]+-${id}" | xargs -r docker service rm
docker ps -a --format '{{.Names}}' | grep -E "^real-compose-${id}" | xargs -r docker rm -f
docker network ls --format '{{.Name}}' | grep -E "^real-compose-${id}" | xargs -r docker network rm
docker volume ls --format '{{.Name}}' | grep -E "^real-compose-${id}" | xargs -r docker volume rm