89 lines
4.3 KiB
YAML
89 lines
4.3 KiB
YAML
name: Verify and deploy API
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: pk-lab-server-production
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
verify-deploy:
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
image: docker:27-cli
|
|
timeout-minutes: 30
|
|
env:
|
|
SOURCE_SERVER: ${{ gitea.server_url }}
|
|
SOURCE_REPOSITORY: ${{ gitea.repository }}
|
|
SOURCE_REVISION: ${{ gitea.sha }}
|
|
DEPLOY_PORT: ${{ vars.DEPLOY_PORT || '18082' }}
|
|
PUBLIC_BASE_URL: ${{ vars.PUBLIC_BASE_URL || '' }}
|
|
CORS_ORIGINS: ${{ vars.CORS_ORIGINS || 'http://47.76.92.159:3000,http://47.76.92.159:3002,http://localhost:3000,http://localhost:3002' }}
|
|
TEST_AUTH_ENABLED: ${{ vars.TEST_AUTH_ENABLED || 'true' }}
|
|
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
|
TOKEN_SECRET: ${{ secrets.TOKEN_SECRET }}
|
|
XHS_HUB_APP_ID: ${{ secrets.XHS_HUB_APP_ID }}
|
|
XHS_HUB_APP_SECRET: ${{ secrets.XHS_HUB_APP_SECRET }}
|
|
XHS_RICE_APP_ID: ${{ secrets.XHS_RICE_APP_ID }}
|
|
XHS_RICE_APP_SECRET: ${{ secrets.XHS_RICE_APP_SECRET }}
|
|
steps:
|
|
- name: Prepare runner and fetch exact revision
|
|
env:
|
|
SOURCE_TOKEN: ${{ secrets.GITEA_TOKEN || gitea.token }}
|
|
run: |
|
|
set -eu
|
|
apk add --no-cache python3 curl
|
|
docker info >/dev/null
|
|
python3 - <<'PY'
|
|
import io, os, shutil, tarfile, tempfile, urllib.request
|
|
from pathlib import Path
|
|
url = f"{os.environ['SOURCE_SERVER'].rstrip('/')}/api/v1/repos/{os.environ['SOURCE_REPOSITORY']}/archive/{os.environ['SOURCE_REVISION']}.tar.gz"
|
|
request = urllib.request.Request(url, headers={'Authorization': 'token ' + os.environ['SOURCE_TOKEN']})
|
|
with urllib.request.urlopen(request, timeout=60) as response:
|
|
data = response.read()
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
with tarfile.open(fileobj=io.BytesIO(data), mode='r:gz') as archive:
|
|
archive.extractall(directory, filter='data')
|
|
roots = list(Path(directory).iterdir())
|
|
if len(roots) != 1:
|
|
raise RuntimeError('Unexpected archive structure')
|
|
shutil.copytree(roots[0], Path.cwd(), dirs_exist_ok=True)
|
|
PY
|
|
- name: Run checks in image build
|
|
run: docker build --target test --tag "pk-lab-server:$SOURCE_REVISION-test" .
|
|
- name: Build runtime image
|
|
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
|
|
run: docker build --target runtime --tag "pk-lab-server:$SOURCE_REVISION" .
|
|
- name: Update permanent stack without deleting data
|
|
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
|
|
run: |
|
|
set -eu
|
|
secret_volume=pk-lab-production-secrets
|
|
docker volume create "$secret_volume" >/dev/null
|
|
docker run --rm \
|
|
-e INITIAL_POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
|
|
-e INITIAL_TOKEN_SECRET="$TOKEN_SECRET" \
|
|
-v "$secret_volume:/secrets" \
|
|
alpine:3.20 sh -eu -c '
|
|
umask 077
|
|
if [ ! -s /secrets/postgres-password ]; then
|
|
if [ -n "$INITIAL_POSTGRES_PASSWORD" ]; then printf %s "$INITIAL_POSTGRES_PASSWORD" > /secrets/postgres-password; else head -c 48 /dev/urandom | base64 > /secrets/postgres-password; fi
|
|
fi
|
|
if [ ! -s /secrets/token-secret ]; then
|
|
if [ -n "$INITIAL_TOKEN_SECRET" ]; then printf %s "$INITIAL_TOKEN_SECRET" > /secrets/token-secret; else head -c 64 /dev/urandom | base64 > /secrets/token-secret; fi
|
|
fi
|
|
'
|
|
POSTGRES_PASSWORD="$(docker run --rm -v "$secret_volume:/secrets:ro" alpine:3.20 cat /secrets/postgres-password)"
|
|
TOKEN_SECRET="$(docker run --rm -v "$secret_volume:/secrets:ro" alpine:3.20 cat /secrets/token-secret)"
|
|
export POSTGRES_PASSWORD TOKEN_SECRET
|
|
export DEPLOY_IMAGE="pk-lab-server:$SOURCE_REVISION"
|
|
sh scripts/deploy.sh
|
|
curl --fail --silent --show-error "http://127.0.0.1:$DEPLOY_PORT/health"
|
|
- name: Probe public endpoint
|
|
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main' && env.PUBLIC_BASE_URL != ''
|
|
run: curl --fail --silent --show-error --connect-timeout 10 --max-time 20 "${PUBLIC_BASE_URL%/}/health"
|