mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-04 19:22:16 +00:00
fix(ci): run dokploy install.sh as root, install version A directly via DOKPLOY_VERSION
Previous run failed with 'This script must be run as root'. install.sh also respects DOKPLOY_VERSION and ADVERTISE_ADDR env vars, so we can install version A directly instead of installing latest and downgrading (which would risk B's migrations running on A's expected schema).
This commit is contained in:
@@ -123,41 +123,39 @@ jobs:
|
|||||||
docker system prune -af --volumes
|
docker system prune -af --volumes
|
||||||
df -h
|
df -h
|
||||||
|
|
||||||
- name: Pre-init Docker Swarm (so install.sh skips its own swarm init)
|
# ── Install Dokploy directly at VERSION A ──────────────────────────────
|
||||||
|
# install.sh:
|
||||||
|
# • requires root (run via sudo bash)
|
||||||
|
# • respects DOKPLOY_VERSION → installs that tag directly
|
||||||
|
# (so we don't need a separate "downgrade" step that would risk
|
||||||
|
# running B's migrations on A's expected schema)
|
||||||
|
# • respects ADVERTISE_ADDR → skip the external IP lookup
|
||||||
|
# • initializes Docker Swarm + dokploy-network itself
|
||||||
|
- name: Install Dokploy at VERSION A (${{ matrix.pair.from }})
|
||||||
run: |
|
run: |
|
||||||
docker swarm init --advertise-addr 127.0.0.1
|
curl -fsSL https://dokploy.com/install.sh -o /tmp/install.sh
|
||||||
docker network create --driver overlay --attachable dokploy-network || true
|
chmod +x /tmp/install.sh
|
||||||
|
sudo -E env \
|
||||||
|
DOKPLOY_VERSION="${{ matrix.pair.from }}" \
|
||||||
|
ADVERTISE_ADDR="127.0.0.1" \
|
||||||
|
bash /tmp/install.sh
|
||||||
|
|
||||||
# ── Install Dokploy infrastructure ─────────────────────────────────────
|
- name: Wait for dokploy service to converge on ${{ matrix.pair.from }}
|
||||||
- name: Run Dokploy install.sh (sets up Traefik, Redis, Postgres, service)
|
|
||||||
run: curl -sSL https://dokploy.com/install.sh | bash
|
|
||||||
|
|
||||||
# ── Pin to version A before any data is written ────────────────────────
|
|
||||||
- name: Pin Dokploy to VERSION A (${{ matrix.pair.from }})
|
|
||||||
run: |
|
run: |
|
||||||
docker service update \
|
echo "Waiting for 'dokploy' Swarm service to reach 1/1..."
|
||||||
--image "${{ env.DOKPLOY_IMAGE }}:${{ matrix.pair.from }}" \
|
timeout 240 bash -c '
|
||||||
--force \
|
|
||||||
"${{ env.DOKPLOY_SERVICE }}"
|
|
||||||
|
|
||||||
echo "Waiting for service to converge on ${{ matrix.pair.from }}..."
|
|
||||||
timeout 180 bash -c '
|
|
||||||
until ! docker service inspect dokploy \
|
|
||||||
--format "{{.UpdateStatus.State}}" 2>/dev/null \
|
|
||||||
| grep -q "^updating$"; do
|
|
||||||
sleep 4
|
|
||||||
done
|
|
||||||
until docker service ls --filter name=dokploy \
|
until docker service ls --filter name=dokploy \
|
||||||
--format "{{.Name}} {{.Replicas}}" \
|
--format "{{.Name}} {{.Replicas}}" \
|
||||||
| grep "^dokploy " | grep -q " 1/1"; do
|
| grep "^dokploy " | grep -q " 1/1"; do
|
||||||
sleep 4
|
sleep 4
|
||||||
done
|
done
|
||||||
'
|
'
|
||||||
|
docker service ls
|
||||||
echo "✅ Service running on ${{ matrix.pair.from }}"
|
echo "✅ Service running on ${{ matrix.pair.from }}"
|
||||||
|
|
||||||
- name: Wait for Dokploy API to accept requests
|
- name: Wait for Dokploy API to accept requests
|
||||||
run: |
|
run: |
|
||||||
timeout 120 bash -c '
|
timeout 180 bash -c '
|
||||||
until curl -sf -o /dev/null \
|
until curl -sf -o /dev/null \
|
||||||
"http://localhost:${{ env.DOKPLOY_PORT }}"; do
|
"http://localhost:${{ env.DOKPLOY_PORT }}"; do
|
||||||
sleep 3
|
sleep 3
|
||||||
@@ -169,23 +167,25 @@ jobs:
|
|||||||
- name: Register first admin user
|
- name: Register first admin user
|
||||||
id: auth
|
id: auth
|
||||||
run: |
|
run: |
|
||||||
COOKIE_JAR=$(mktemp /tmp/dokploy-cookies-XXXXXX)
|
COOKIE_JAR="$RUNNER_TEMP/dokploy-cookies.txt"
|
||||||
|
: > "$COOKIE_JAR"
|
||||||
|
chmod 600 "$COOKIE_JAR"
|
||||||
echo "cookie_jar=$COOKIE_JAR" >> "$GITHUB_OUTPUT"
|
echo "cookie_jar=$COOKIE_JAR" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# better-auth: sign-up/email (allowed only before any owner exists)
|
# better-auth: sign-up/email (allowed only before any owner exists)
|
||||||
RESP=$(curl -sf -X POST \
|
set -x
|
||||||
|
curl -sS -i -X POST \
|
||||||
"http://localhost:${{ env.DOKPLOY_PORT }}/api/auth/sign-up/email" \
|
"http://localhost:${{ env.DOKPLOY_PORT }}/api/auth/sign-up/email" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-c "$COOKIE_JAR" -b "$COOKIE_JAR" \
|
-c "$COOKIE_JAR" -b "$COOKIE_JAR" \
|
||||||
-d '{"name":"CI Admin","email":"[email protected]","password":"CiTest1234!"}')
|
-d '{"name":"CI Admin","email":"[email protected]","password":"CiTest1234!"}' \
|
||||||
|
| tee /tmp/signup.out
|
||||||
|
set +x
|
||||||
|
|
||||||
echo "Sign-up response: $RESP"
|
# Verify we got a session cookie
|
||||||
# Session cookie is stored in the jar; also capture token if present
|
if ! grep -qE '(better-auth|auth)\.session' "$COOKIE_JAR"; then
|
||||||
TOKEN=$(echo "$RESP" | jq -r '.token // empty' 2>/dev/null || true)
|
echo "⚠️ No session cookie matched expected name; jar contents:"
|
||||||
if [ -n "$TOKEN" ]; then
|
cat "$COOKIE_JAR"
|
||||||
echo "::add-mask::$TOKEN"
|
|
||||||
# Inject token as a cookie for older versions that don't use cookie jar
|
|
||||||
echo "dokploy.com FALSE / FALSE 0 auth_token $TOKEN" >> "$COOKIE_JAR"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Create test resources ──────────────────────────────────────────────
|
# ── Create test resources ──────────────────────────────────────────────
|
||||||
@@ -195,12 +195,13 @@ jobs:
|
|||||||
BASE: "http://localhost:${{ env.DOKPLOY_PORT }}"
|
BASE: "http://localhost:${{ env.DOKPLOY_PORT }}"
|
||||||
COOKIE: ${{ steps.auth.outputs.cookie_jar }}
|
COOKIE: ${{ steps.auth.outputs.cookie_jar }}
|
||||||
run: |
|
run: |
|
||||||
# --- tRPC helpers ---
|
set -euo pipefail
|
||||||
# Mutation (POST)
|
|
||||||
|
# --- tRPC POST helper ---
|
||||||
trpc_mut() {
|
trpc_mut() {
|
||||||
curl -sf -X POST "$BASE/api/trpc/$1" \
|
curl -sf -X POST "$BASE/api/trpc/$1" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-b "$COOKIE" \
|
-b "$COOKIE" -c "$COOKIE" \
|
||||||
-d "{\"json\":$2}"
|
-d "{\"json\":$2}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +219,7 @@ jobs:
|
|||||||
PG=$(trpc_mut postgres.create \
|
PG=$(trpc_mut postgres.create \
|
||||||
"{\"name\":\"ci-pg\",\"appName\":\"ci-pg-db\",\
|
"{\"name\":\"ci-pg\",\"appName\":\"ci-pg-db\",\
|
||||||
\"databaseName\":\"cidb\",\"databaseUser\":\"ciuser\",\
|
\"databaseName\":\"cidb\",\"databaseUser\":\"ciuser\",\
|
||||||
\"databasePassword\":\"CiPg1!\",\
|
\"databasePassword\":\"CiPg1pass\",\
|
||||||
\"dockerImage\":\"postgres:15\",\"environmentId\":\"$ENV_ID\"}")
|
\"dockerImage\":\"postgres:15\",\"environmentId\":\"$ENV_ID\"}")
|
||||||
PG_ID=$(echo "$PG" | jq -r '.result.data.json.postgresId')
|
PG_ID=$(echo "$PG" | jq -r '.result.data.json.postgresId')
|
||||||
trpc_mut postgres.start "{\"postgresId\":\"$PG_ID\"}" > /dev/null
|
trpc_mut postgres.start "{\"postgresId\":\"$PG_ID\"}" > /dev/null
|
||||||
@@ -228,14 +229,13 @@ jobs:
|
|||||||
MG=$(trpc_mut mongo.create \
|
MG=$(trpc_mut mongo.create \
|
||||||
"{\"name\":\"ci-mongo\",\"appName\":\"ci-mongo-db\",\
|
"{\"name\":\"ci-mongo\",\"appName\":\"ci-mongo-db\",\
|
||||||
\"databaseName\":\"cidb\",\"databaseUser\":\"ciuser\",\
|
\"databaseName\":\"cidb\",\"databaseUser\":\"ciuser\",\
|
||||||
\"databasePassword\":\"CiMg1!\",\
|
\"databasePassword\":\"CiMg1pass\",\
|
||||||
\"dockerImage\":\"mongo:7.0\",\"environmentId\":\"$ENV_ID\"}")
|
\"dockerImage\":\"mongo:7.0\",\"environmentId\":\"$ENV_ID\"}")
|
||||||
MG_ID=$(echo "$MG" | jq -r '.result.data.json.mongoId')
|
MG_ID=$(echo "$MG" | jq -r '.result.data.json.mongoId')
|
||||||
trpc_mut mongo.start "{\"mongoId\":\"$MG_ID\"}" > /dev/null
|
trpc_mut mongo.start "{\"mongoId\":\"$MG_ID\"}" > /dev/null
|
||||||
echo "mg_id=$MG_ID" >> "$GITHUB_OUTPUT"
|
echo "mg_id=$MG_ID" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# --- Docker-image application helper ---
|
# --- Docker-image application helper ---
|
||||||
# Creates an application, sets Docker image provider, triggers deploy.
|
|
||||||
make_app() {
|
make_app() {
|
||||||
local DISP_NAME=$1 APP_NAME=$2 IMAGE=$3
|
local DISP_NAME=$1 APP_NAME=$2 IMAGE=$3
|
||||||
APP=$(trpc_mut application.create \
|
APP=$(trpc_mut application.create \
|
||||||
@@ -276,11 +276,10 @@ jobs:
|
|||||||
APP_NODE_ID: ${{ steps.create.outputs.app_node_id }}
|
APP_NODE_ID: ${{ steps.create.outputs.app_node_id }}
|
||||||
APP_GO_ID: ${{ steps.create.outputs.app_go_id }}
|
APP_GO_ID: ${{ steps.create.outputs.app_go_id }}
|
||||||
run: |
|
run: |
|
||||||
# Poll a tRPC query endpoint until the service status field == "done"
|
|
||||||
wait_done() {
|
wait_done() {
|
||||||
local NAME=$1 ENDPOINT=$2 ID_KEY=$3 ID=$4 STATUS_KEY=$5
|
local NAME=$1 ENDPOINT=$2 ID_KEY=$3 ID=$4 STATUS_KEY=$5
|
||||||
echo "Waiting for $NAME to reach 'done'..."
|
echo "Waiting for $NAME to reach 'done'..."
|
||||||
timeout 300 bash -c "
|
timeout 360 bash -c "
|
||||||
until [ \"\$(curl -sf -G '$BASE/api/trpc/$ENDPOINT' \
|
until [ \"\$(curl -sf -G '$BASE/api/trpc/$ENDPOINT' \
|
||||||
--data-urlencode 'input={\"json\":{\"$ID_KEY\":\"$ID\"}}' \
|
--data-urlencode 'input={\"json\":{\"$ID_KEY\":\"$ID\"}}' \
|
||||||
-b '$COOKIE' | \
|
-b '$COOKIE' | \
|
||||||
@@ -303,7 +302,6 @@ jobs:
|
|||||||
echo "=== docker service ls ==="
|
echo "=== docker service ls ==="
|
||||||
docker service ls
|
docker service ls
|
||||||
|
|
||||||
# User services should all be 1/1; check none are 0/1
|
|
||||||
FAIL=$(docker service ls --format '{{.Name}} {{.Replicas}}' | \
|
FAIL=$(docker service ls --format '{{.Name}} {{.Replicas}}' | \
|
||||||
grep -E '^ci-' | grep -v ' 1/1' || true)
|
grep -E '^ci-' | grep -v ' 1/1' || true)
|
||||||
if [ -n "$FAIL" ]; then
|
if [ -n "$FAIL" ]; then
|
||||||
@@ -322,7 +320,7 @@ jobs:
|
|||||||
"${{ env.DOKPLOY_SERVICE }}"
|
"${{ env.DOKPLOY_SERVICE }}"
|
||||||
|
|
||||||
echo "Waiting for service to converge on ${{ matrix.pair.to }}..."
|
echo "Waiting for service to converge on ${{ matrix.pair.to }}..."
|
||||||
timeout 180 bash -c '
|
timeout 240 bash -c '
|
||||||
until ! docker service inspect dokploy \
|
until ! docker service inspect dokploy \
|
||||||
--format "{{.UpdateStatus.State}}" 2>/dev/null \
|
--format "{{.UpdateStatus.State}}" 2>/dev/null \
|
||||||
| grep -q "^updating$"; do
|
| grep -q "^updating$"; do
|
||||||
@@ -338,7 +336,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Wait for Dokploy API to respond post-upgrade
|
- name: Wait for Dokploy API to respond post-upgrade
|
||||||
run: |
|
run: |
|
||||||
timeout 120 bash -c '
|
timeout 180 bash -c '
|
||||||
until curl -sf -o /dev/null \
|
until curl -sf -o /dev/null \
|
||||||
"http://localhost:${{ env.DOKPLOY_PORT }}"; do
|
"http://localhost:${{ env.DOKPLOY_PORT }}"; do
|
||||||
sleep 3
|
sleep 3
|
||||||
@@ -395,8 +393,12 @@ jobs:
|
|||||||
echo "=== docker service ls ===" && docker service ls || true
|
echo "=== docker service ls ===" && docker service ls || true
|
||||||
echo "=== dokploy service tasks ===" && \
|
echo "=== dokploy service tasks ===" && \
|
||||||
docker service ps "${{ env.DOKPLOY_SERVICE }}" --no-trunc || true
|
docker service ps "${{ env.DOKPLOY_SERVICE }}" --no-trunc || true
|
||||||
echo "=== dokploy logs (last 100) ===" && \
|
echo "=== dokploy logs (last 200) ===" && \
|
||||||
docker service logs "${{ env.DOKPLOY_SERVICE }}" --tail 100 2>&1 || true
|
docker service logs "${{ env.DOKPLOY_SERVICE }}" --tail 200 2>&1 || true
|
||||||
|
echo "=== install.sh tail ===" && \
|
||||||
|
tail -100 /tmp/install.sh 2>&1 || true
|
||||||
|
echo "=== signup response ===" && \
|
||||||
|
cat /tmp/signup.out 2>&1 || true
|
||||||
echo "=== disk usage ===" && df -h
|
echo "=== disk usage ===" && df -h
|
||||||
|
|
||||||
# ── Job summary ────────────────────────────────────────────────────────
|
# ── Job summary ────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user