fix: use self-contained workflow images
Deploy / Deploy Staging (push) Failing after 25s
Deploy / Deploy Production (push) Has been skipped
Tests / lint (push) Has been cancelled
Tests / test (push) Has been cancelled

This commit is contained in:
Xiaoxia AI
2026-06-15 20:27:12 +08:00
parent 33fb16a75a
commit d3d90d3775
2 changed files with 167 additions and 136 deletions
+90 -100
View File
@@ -10,29 +10,24 @@ jobs:
deploy-staging:
name: Deploy Staging
runs-on: ubuntu-latest
container:
image: docker:27-cli
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout code
shell: bash
shell: sh
run: |
set -euo pipefail
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
auth_header="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0)"
git init .
git remote add origin "$repo_url"
git -c http.https://api.xiaoxiajianji.com/.extraheader="$auth_header" fetch --depth=1 origin "$GITHUB_SHA"
git checkout --force FETCH_HEAD
- name: Prepare deploy tooling
run: |
apt-get update
apt-get install -y docker.io curl
set -eu
archive_url="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/archive/${GITHUB_SHA}.tar.gz"
wget --header="Authorization: token ${GITHUB_TOKEN}" -O /tmp/repo.tar.gz "$archive_url"
tar -xzf /tmp/repo.tar.gz --strip-components=1 -C .
rm -f /tmp/repo.tar.gz
- name: Sync code to staging workspace
shell: bash
shell: sh
run: |
set -euo pipefail
set -eu
tar --exclude=.git -cf - . | docker run --rm -i \
-v /:/host \
alpine:3.20 \
@@ -45,82 +40,77 @@ jobs:
'
- name: Verify staging env file
shell: sh
run: |
set -eu
docker run --rm -v /:/host alpine:3.20 test -f /host/var/lib/xiaoxia-saas-staging/.env
- name: Prepare staging env
shell: sh
run: |
set -eu
docker run --rm -v /:/host alpine:3.20 sh -lc 'cp /host/var/lib/xiaoxia-saas-staging/.env /host/var/lib/xiaoxia-saas-staging/repo/.env'
- name: Build staging images
shell: sh
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host \
docker:27-cli sh -lc '
docker build \
-t xiaoxia-saas-api:${{ github.sha }} \
-t xiaoxia-saas-api:staging \
-f /host/var/lib/xiaoxia-saas-staging/repo/infra/docker/api.Dockerfile \
/host/var/lib/xiaoxia-saas-staging/repo && \
docker build \
-t xiaoxia-saas-worker:${{ github.sha }} \
-t xiaoxia-saas-worker:staging \
-f /host/var/lib/xiaoxia-saas-staging/repo/infra/docker/worker.Dockerfile \
/host/var/lib/xiaoxia-saas-staging/repo
'
set -eu
docker build \
-t xiaoxia-saas-api:${GITHUB_SHA} \
-t xiaoxia-saas-api:staging \
-f /var/lib/xiaoxia-saas-staging/repo/infra/docker/api.Dockerfile \
/var/lib/xiaoxia-saas-staging/repo
docker build \
-t xiaoxia-saas-worker:${GITHUB_SHA} \
-t xiaoxia-saas-worker:staging \
-f /var/lib/xiaoxia-saas-staging/repo/infra/docker/worker.Dockerfile \
/var/lib/xiaoxia-saas-staging/repo
- name: Deploy staging containers
shell: sh
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host \
-w /host/var/lib/xiaoxia-saas-staging/repo/infra/docker \
-e API_IMAGE=xiaoxia-saas-api:staging \
-e WORKER_IMAGE=xiaoxia-saas-worker:staging \
docker:27-cli sh -lc '
docker compose up -d postgres redis api worker && \
docker compose ps
'
set -eu
cd /var/lib/xiaoxia-saas-staging/repo/infra/docker
API_IMAGE=xiaoxia-saas-api:staging \
WORKER_IMAGE=xiaoxia-saas-worker:staging \
docker compose up -d postgres redis api worker
docker compose ps
- name: Verify staging health
shell: sh
run: |
docker run --rm --network host curlimages/curl:8.8.0 sh -lc '
for i in $(seq 1 30); do
if curl -fsS http://127.0.0.1:8000/api/v1/health; then
exit 0
fi
sleep 2
done
exit 1
'
set -eu
i=0
while [ "$i" -lt 30 ]; do
if wget -qO- http://127.0.0.1:8000/api/v1/health; then
exit 0
fi
i=$((i + 1))
sleep 2
done
exit 1
deploy-production:
name: Deploy Production
runs-on: ubuntu-latest
container:
image: docker:27-cli
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout code
shell: bash
shell: sh
run: |
set -euo pipefail
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
auth_header="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0)"
git init .
git remote add origin "$repo_url"
git -c http.https://api.xiaoxiajianji.com/.extraheader="$auth_header" fetch --depth=1 origin "$GITHUB_SHA"
git checkout --force FETCH_HEAD
- name: Prepare deploy tooling
run: |
apt-get update
apt-get install -y docker.io curl
set -eu
archive_url="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/archive/${GITHUB_SHA}.tar.gz"
wget --header="Authorization: token ${GITHUB_TOKEN}" -O /tmp/repo.tar.gz "$archive_url"
tar -xzf /tmp/repo.tar.gz --strip-components=1 -C .
rm -f /tmp/repo.tar.gz
- name: Sync code to production workspace
shell: bash
shell: sh
run: |
set -euo pipefail
set -eu
tar --exclude=.git -cf - . | docker run --rm -i \
-v /:/host \
alpine:3.20 \
@@ -133,54 +123,54 @@ jobs:
'
- name: Verify production env file
shell: sh
run: |
set -eu
docker run --rm -v /:/host alpine:3.20 test -f /host/var/lib/xiaoxia-saas-production/.env
- name: Prepare production env
shell: sh
run: |
set -eu
docker run --rm -v /:/host alpine:3.20 sh -lc 'cp /host/var/lib/xiaoxia-saas-production/.env /host/var/lib/xiaoxia-saas-production/repo/.env'
- name: Build production images
shell: sh
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host \
docker:27-cli sh -lc '
docker build \
-t xiaoxia-saas-api:${{ github.sha }} \
-t xiaoxia-saas-api:${{ github.ref_name }} \
-t xiaoxia-saas-api:latest \
-f /host/var/lib/xiaoxia-saas-production/repo/infra/docker/api.Dockerfile \
/host/var/lib/xiaoxia-saas-production/repo && \
docker build \
-t xiaoxia-saas-worker:${{ github.sha }} \
-t xiaoxia-saas-worker:${{ github.ref_name }} \
-t xiaoxia-saas-worker:latest \
-f /host/var/lib/xiaoxia-saas-production/repo/infra/docker/worker.Dockerfile \
/host/var/lib/xiaoxia-saas-production/repo
'
set -eu
docker build \
-t xiaoxia-saas-api:${GITHUB_SHA} \
-t xiaoxia-saas-api:${GITHUB_REF_NAME} \
-t xiaoxia-saas-api:latest \
-f /var/lib/xiaoxia-saas-production/repo/infra/docker/api.Dockerfile \
/var/lib/xiaoxia-saas-production/repo
docker build \
-t xiaoxia-saas-worker:${GITHUB_SHA} \
-t xiaoxia-saas-worker:${GITHUB_REF_NAME} \
-t xiaoxia-saas-worker:latest \
-f /var/lib/xiaoxia-saas-production/repo/infra/docker/worker.Dockerfile \
/var/lib/xiaoxia-saas-production/repo
- name: Deploy production containers
shell: sh
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host \
-w /host/var/lib/xiaoxia-saas-production/repo/infra/docker \
-e API_IMAGE=xiaoxia-saas-api:latest \
-e WORKER_IMAGE=xiaoxia-saas-worker:latest \
docker:27-cli sh -lc '
docker compose up -d postgres redis api worker && \
docker compose ps
'
set -eu
cd /var/lib/xiaoxia-saas-production/repo/infra/docker
API_IMAGE=xiaoxia-saas-api:latest \
WORKER_IMAGE=xiaoxia-saas-worker:latest \
docker compose up -d postgres redis api worker
docker compose ps
- name: Verify production health
shell: sh
run: |
docker run --rm --network host curlimages/curl:8.8.0 sh -lc '
for i in $(seq 1 30); do
if curl -fsS http://127.0.0.1:8000/api/v1/health; then
exit 0
fi
sleep 2
done
exit 1
'
set -eu
i=0
while [ "$i" -lt 30 ]; do
if wget -qO- http://127.0.0.1:8000/api/v1/health; then
exit 0
fi
i=$((i + 1))
sleep 2
done
exit 1
+77 -36
View File
@@ -9,70 +9,111 @@ on:
jobs:
test:
runs-on: ubuntu-latest
container:
image: python:3.12-slim
steps:
- name: Checkout code
shell: bash
shell: sh
run: |
set -euo pipefail
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
auth_header="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0)"
git init .
git remote add origin "$repo_url"
git -c http.https://api.xiaoxiajianji.com/.extraheader="$auth_header" fetch --depth=1 origin "$GITHUB_SHA"
git checkout --force FETCH_HEAD
set -eu
python - <<'PY'
import io
import os
import tarfile
import urllib.request
- name: Install Python tooling
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
with urllib.request.urlopen(request, timeout=120) as response:
archive = response.read()
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
for member in tar.getmembers():
name = member.name
if name == root_prefix[:-1]:
continue
if name.startswith(root_prefix):
member.name = name[len(root_prefix):]
if member.name:
tar.extract(member, '.')
PY
- name: Show Python version
shell: sh
run: |
apt-get update
apt-get install -y python3-pip python3-venv
python3 --version
python3 -m pip --version
set -eu
python --version
python -m pip --version
- name: Install dependencies
shell: sh
run: |
python3 -m pip install --break-system-packages --upgrade pip
python3 -m pip install --break-system-packages -r requirements.txt -r requirements-dev.txt
set -eu
python -m pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
python -m pip install -r requirements.txt -r requirements-dev.txt -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
- name: Run tests
shell: sh
run: |
python3 -m pytest tests/integration/ -v --cov=packages --cov=apps --cov-report=xml --cov-report=term
set -eu
python -m pytest tests/integration/ -v --cov=packages --cov=apps --cov-report=xml --cov-report=term
lint:
runs-on: ubuntu-latest
container:
image: python:3.12-slim
steps:
- name: Checkout code
shell: bash
shell: sh
run: |
set -euo pipefail
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
auth_header="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0)"
git init .
git remote add origin "$repo_url"
git -c http.https://api.xiaoxiajianji.com/.extraheader="$auth_header" fetch --depth=1 origin "$GITHUB_SHA"
git checkout --force FETCH_HEAD
set -eu
python - <<'PY'
import io
import os
import tarfile
import urllib.request
- name: Install Python tooling
run: |
apt-get update
apt-get install -y python3-pip python3-venv
python3 --version
python3 -m pip --version
url = f"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz"
request = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['GITHUB_TOKEN']}"})
with urllib.request.urlopen(request, timeout=120) as response:
archive = response.read()
- name: Install linting tools
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
for member in tar.getmembers():
name = member.name
if name == root_prefix[:-1]:
continue
if name.startswith(root_prefix):
member.name = name[len(root_prefix):]
if member.name:
tar.extract(member, '.')
PY
- name: Install dependencies
shell: sh
run: |
python3 -m pip install --break-system-packages --upgrade pip
python3 -m pip install --break-system-packages -r requirements.txt -r requirements-dev.txt
set -eu
python -m pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
python -m pip install -r requirements.txt -r requirements-dev.txt -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
- name: Run Black (check only)
shell: sh
run: |
python3 -m black --check packages/ apps/ tests/
set -eu
python -m black --check packages/ apps/ tests/
- name: Run Flake8
shell: sh
run: |
python3 -m flake8 packages/ apps/ tests/ --max-line-length=120 --extend-ignore=E203,W503
set -eu
python -m flake8 packages/ apps/ tests/ --max-line-length=120 --extend-ignore=E203,W503
- name: Run MyPy
shell: sh
run: |
python3 -m mypy packages/ apps/ --ignore-missing-imports
set -eu
python -m mypy packages/ apps/ --ignore-missing-imports