|
|
|
@@ -1,186 +0,0 @@
|
|
|
|
|
name: Deploy Now
|
|
|
|
|
run-name: 🚀 Deploy Now by @${{ gitea.actor }}
|
|
|
|
|
|
|
|
|
|
on:
|
|
|
|
|
workflow_dispatch:
|
|
|
|
|
|
|
|
|
|
jobs:
|
|
|
|
|
deploy:
|
|
|
|
|
name: Deploy Nexus
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
env:
|
|
|
|
|
DEPLOY_PATH: /home/projekte_bao/openclaw/data/openclaw/workspace/nexus
|
|
|
|
|
ENV_TMPFILE: /tmp/nexus-deploy-env
|
|
|
|
|
ENV_POSTGRES_PASSWORD: ${{ secrets.ENV_POSTGRES_PASSWORD }}
|
|
|
|
|
ENV_JWT_KEY: ${{ secrets.ENV_JWT_KEY }}
|
|
|
|
|
ENV_OPENCLAW_TOKEN: ${{ secrets.ENV_OPENCLAW_TOKEN }}
|
|
|
|
|
|
|
|
|
|
steps:
|
|
|
|
|
- name: Checkout
|
|
|
|
|
uses: actions/checkout@v4
|
|
|
|
|
with:
|
|
|
|
|
ref: main
|
|
|
|
|
fetch-depth: 0
|
|
|
|
|
fetch-tags: true
|
|
|
|
|
|
|
|
|
|
- name: Resolve Version
|
|
|
|
|
id: version
|
|
|
|
|
run: |
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
if [ ! -f VERSION ]; then
|
|
|
|
|
echo "ERROR: VERSION file not found"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
VERSION=$(cat VERSION | tr -d '[:space:]')
|
|
|
|
|
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
|
|
|
echo "ERROR: Invalid semver in VERSION: $VERSION"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
GIT_REF=$(git rev-parse --short HEAD)
|
|
|
|
|
echo "Deploy version: v${VERSION} git:${GIT_REF}"
|
|
|
|
|
echo "version=${VERSION}" >> "$GITEA_OUTPUT"
|
|
|
|
|
|
|
|
|
|
- name: Prepare .env
|
|
|
|
|
run: |
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
printf 'POSTGRES_DB=nexus\n' > "${ENV_TMPFILE}"
|
|
|
|
|
printf 'POSTGRES_USER=nexus\n' >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'POSTGRES_PASSWORD=%s\n' "${ENV_POSTGRES_PASSWORD}" >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'JWT_KEY=%s\n' "${ENV_JWT_KEY}" >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'JWT_ISSUER=nexus\n' >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'JWT_AUDIENCE=nexus-web\n' >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de\n' >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'OPENCLAW_BASE_URL=http://host.docker.internal:18789\n' >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'OPENCLAW_GATEWAY_TOKEN=%s\n' "${ENV_OPENCLAW_TOKEN}" >> "${ENV_TMPFILE}"
|
|
|
|
|
printf 'OPENCLAW_GATEWAY_PASSWORD=\n' >> "${ENV_TMPFILE}"
|
|
|
|
|
chmod 600 "${ENV_TMPFILE}"
|
|
|
|
|
echo "OK .env written to ${ENV_TMPFILE}"
|
|
|
|
|
|
|
|
|
|
- name: Sync code to host
|
|
|
|
|
run: |
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
docker run --rm \
|
|
|
|
|
-v "${{ gitea.workspace }}:/src:ro" \
|
|
|
|
|
-v "${DEPLOY_PATH}:/dest" \
|
|
|
|
|
alpine:latest \
|
|
|
|
|
sh -c "cd /src && find . -mindepth 1 -maxdepth 1 ! -name .git -exec cp -r {} /dest/ \; && DEST_OWNER=\$(stat -c '%u:%g' /dest) && chown -R \"\$DEST_OWNER\" /dest"
|
|
|
|
|
echo "OK synced to ${DEPLOY_PATH}"
|
|
|
|
|
|
|
|
|
|
- name: Build and Deploy
|
|
|
|
|
run: |
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
SCRIPT=/tmp/nexus-deploy-script.sh
|
|
|
|
|
printf '#!/bin/sh\n' > "$SCRIPT"
|
|
|
|
|
printf 'set -e\n' >> "$SCRIPT"
|
|
|
|
|
printf 'trap "rm -f /tmp/nexus-deploy-env" EXIT\n' >> "$SCRIPT"
|
|
|
|
|
printf 'cat > /tmp/nexus-deploy-env\n' >> "$SCRIPT"
|
|
|
|
|
printf '\n' >> "$SCRIPT"
|
|
|
|
|
printf '# ── Graceful shutdown (preserves DB volume integrity) ──\n' >> "$SCRIPT"
|
|
|
|
|
printf 'docker compose --env-file /tmp/nexus-deploy-env stop postgres 2>/dev/null || true\n' >> "$SCRIPT"
|
|
|
|
|
printf 'docker compose --env-file /tmp/nexus-deploy-env down --remove-orphans 2>/dev/null || true\n' >> "$SCRIPT"
|
|
|
|
|
printf 'echo "Postgres volume preserved (nexus-postgres) — no WAL reset"\n' >> "$SCRIPT"
|
|
|
|
|
printf '\n' >> "$SCRIPT"
|
|
|
|
|
printf 'echo "Deploying all services"\n' >> "$SCRIPT"
|
|
|
|
|
printf 'docker compose --env-file /tmp/nexus-deploy-env build --no-cache\n' >> "$SCRIPT"
|
|
|
|
|
printf 'docker compose --env-file /tmp/nexus-deploy-env up -d --force-recreate\n' >> "$SCRIPT"
|
|
|
|
|
printf '\n' >> "$SCRIPT"
|
|
|
|
|
printf 'echo "Waiting for services to become healthy (up to 180s)..."\n' >> "$SCRIPT"
|
|
|
|
|
printf 'for i in $(seq 1 36); do\n' >> "$SCRIPT"
|
|
|
|
|
printf ' STATUS=$(docker compose --env-file /tmp/nexus-deploy-env ps -a 2>/dev/null | tail -n +2)\n' >> "$SCRIPT"
|
|
|
|
|
printf ' if echo "$STATUS" | grep -q unhealthy; then\n' >> "$SCRIPT"
|
|
|
|
|
printf ' echo " [$i/36] Unhealthy containers - failing fast"\n' >> "$SCRIPT"
|
|
|
|
|
printf ' docker compose --env-file /tmp/nexus-deploy-env ps -a\n' >> "$SCRIPT"
|
|
|
|
|
printf ' docker compose --env-file /tmp/nexus-deploy-env logs --tail=30\n' >> "$SCRIPT"
|
|
|
|
|
printf ' exit 1\n' >> "$SCRIPT"
|
|
|
|
|
printf ' elif echo "$STATUS" | grep -q starting; then\n' >> "$SCRIPT"
|
|
|
|
|
printf ' echo " [$i/36] Still starting..."\n' >> "$SCRIPT"
|
|
|
|
|
printf ' sleep 5\n' >> "$SCRIPT"
|
|
|
|
|
printf ' else\n' >> "$SCRIPT"
|
|
|
|
|
printf ' echo "All containers healthy"\n' >> "$SCRIPT"
|
|
|
|
|
printf ' docker compose --env-file /tmp/nexus-deploy-env ps -a\n' >> "$SCRIPT"
|
|
|
|
|
printf ' exit 0\n' >> "$SCRIPT"
|
|
|
|
|
printf ' fi\n' >> "$SCRIPT"
|
|
|
|
|
printf 'done\n' >> "$SCRIPT"
|
|
|
|
|
printf 'echo "Timeout waiting for services"\n' >> "$SCRIPT"
|
|
|
|
|
printf 'docker compose --env-file /tmp/nexus-deploy-env ps -a\n' >> "$SCRIPT"
|
|
|
|
|
printf 'docker compose --env-file /tmp/nexus-deploy-env logs --tail=20\n' >> "$SCRIPT"
|
|
|
|
|
printf 'exit 1\n' >> "$SCRIPT"
|
|
|
|
|
chmod +x "$SCRIPT"
|
|
|
|
|
|
|
|
|
|
docker run --rm \
|
|
|
|
|
-v "${DEPLOY_PATH}:/workspace/nexus" \
|
|
|
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
|
|
|
-v "${SCRIPT}:/deploy.sh:ro" \
|
|
|
|
|
-w /workspace/nexus \
|
|
|
|
|
-i \
|
|
|
|
|
docker:cli \
|
|
|
|
|
sh /deploy.sh < "${ENV_TMPFILE}"
|
|
|
|
|
|
|
|
|
|
rm -f "$SCRIPT"
|
|
|
|
|
echo "OK deployed"
|
|
|
|
|
|
|
|
|
|
- name: Clean up temp .env
|
|
|
|
|
if: always()
|
|
|
|
|
run: |
|
|
|
|
|
if [ -f "${ENV_TMPFILE}" ]; then
|
|
|
|
|
shred -u "${ENV_TMPFILE}" 2>/dev/null || rm -f "${ENV_TMPFILE}"
|
|
|
|
|
echo "OK cleaned"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
- name: Health Check
|
|
|
|
|
run: |
|
|
|
|
|
echo "Health check..."
|
|
|
|
|
RETRY=0; MAX=6; WAIT=1
|
|
|
|
|
while [ $RETRY -lt $MAX ]; do
|
|
|
|
|
RETRY=$((RETRY + 1))
|
|
|
|
|
if curl -sf --max-time 10 https://nexus.noveria.net/health; then
|
|
|
|
|
echo ""
|
|
|
|
|
echo "OK Health check passed (attempt $RETRY/$MAX)"
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
echo "Attempt $RETRY/$MAX failed, waiting ${WAIT}s..."
|
|
|
|
|
sleep $WAIT
|
|
|
|
|
NEXT=$((WAIT + RETRY))
|
|
|
|
|
[ $NEXT -le 15 ] && WAIT=$NEXT || WAIT=15
|
|
|
|
|
done
|
|
|
|
|
echo "ERROR Health check failed after $MAX attempts"
|
|
|
|
|
exit 1
|
|
|
|
|
|
|
|
|
|
- name: Smoke Test
|
|
|
|
|
run: |
|
|
|
|
|
PASS=0; FAIL=0; BASE="https://nexus.noveria.net"
|
|
|
|
|
check() {
|
|
|
|
|
local path="$1" label="$2" expected="${3:-200}"
|
|
|
|
|
local code
|
|
|
|
|
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "${BASE}${path}")
|
|
|
|
|
printf " %-25s HTTP %s" "${label}:" "${code}"
|
|
|
|
|
if [ "$code" = "$expected" ]; then
|
|
|
|
|
echo " OK"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo " FAIL (expected $expected)"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
check "/dashboard" "Dashboard" 200
|
|
|
|
|
check "/health" "Health API" 200
|
|
|
|
|
check "/api/v1/operations/snapshot" "Operations API (auth)" 401
|
|
|
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
|
|
|
if [ "$FAIL" -gt 0 ]; then
|
|
|
|
|
echo "ERROR Smoke test failed"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
echo "OK Smoke test passed"
|
|
|
|
|
|
|
|
|
|
- name: Summary
|
|
|
|
|
if: always()
|
|
|
|
|
run: |
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo " Deploy Summary"
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo " Version: v${{ steps.version.outputs.version }}"
|
|
|
|
|
echo " Git ref: main"
|
|
|
|
|
echo " Service: all"
|
|
|
|
|
echo " Trigger: Manual"
|
|
|
|
|
echo " Status: ${{ job.status }}"
|
|
|
|
|
echo "========================================"
|