ci(release): deploy production from runtime builder

This commit is contained in:
Xiaoxia AI
2026-06-22 18:36:56 +08:00
parent f73b87314d
commit 59e4c9d418
3 changed files with 41 additions and 49 deletions
+32 -43
View File
@@ -148,57 +148,45 @@ jobs:
deploy-production:
name: Deploy Production
runs-on: ubuntu-latest
container:
image: docker:27-cli
runs-on: runtime-builder
if: startsWith(github.ref, 'refs/tags/v')
needs: build-production-runtime-images
steps:
- name: Sync release artifact to production workspace
- name: Deploy production over SSH
shell: sh
env:
PRODUCTION_SSH_HOST: ${{ secrets.PRODUCTION_SSH_HOST }}
PRODUCTION_SSH_USER: ${{ secrets.PRODUCTION_SSH_USER }}
PRODUCTION_SSH_KEY: ${{ secrets.PRODUCTION_SSH_KEY }}
run: |
set -eu
docker run --rm -e GITHUB_REF_NAME="${GITHUB_REF_NAME}" -v /:/host docker:27-cli sh -lc '
set -eu
release_tar="/host/var/lib/xiaoxia-saas-production/release-${GITHUB_REF_NAME}.tar.gz"
test -f "$release_tar"
mkdir -p /host/var/lib/xiaoxia-saas-production
rm -rf /host/var/lib/xiaoxia-saas-production/repo
mkdir -p /host/var/lib/xiaoxia-saas-production/repo
tar -xzf "$release_tar" -C /host/var/lib/xiaoxia-saas-production/repo
test -f /host/var/lib/xiaoxia-saas-production/repo/apps/web/dist/index.html
'
- name: Verify production env file
shell: sh
run: |
set -eu
docker run --rm -v /:/host docker:27-cli sh -lc 'test -f /host/var/lib/xiaoxia-saas-production/.env'
- name: Prepare production env
shell: sh
run: |
set -eu
docker run --rm -v /:/host docker:27-cli sh -lc 'cp /host/var/lib/xiaoxia-saas-production/.env /host/var/lib/xiaoxia-saas-production/repo/.env'
- name: Deploy production stack
shell: sh
run: |
set -eu
docker run --rm \
-e GITHUB_REF_NAME="${GITHUB_REF_NAME}" \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host \
docker:27-cli sh -lc '
chmod +x /host/var/lib/xiaoxia-saas-production/repo/infra/docker/deploy-production.sh && \
RELEASE_VERSION="${GITHUB_REF_NAME}" /host/var/lib/xiaoxia-saas-production/repo/infra/docker/deploy-production.sh
'
- name: Verify production health
shell: sh
run: |
production_host="${PRODUCTION_SSH_HOST:-47.98.113.167}"
production_user="${PRODUCTION_SSH_USER:-root}"
mkdir -p ~/.ssh
if [ -n "${PRODUCTION_SSH_KEY:-}" ]; then
key_path="$HOME/.ssh/id_ed25519"
printf '%s\n' "$PRODUCTION_SSH_KEY" > "$key_path"
chmod 600 "$key_path"
else
key_path="/root/.ssh/xiaoxia_runtime_builder"
test -f "$key_path"
fi
ssh-keyscan -H "$production_host" >> ~/.ssh/known_hosts
ssh -i "$key_path" "$production_user@$production_host" \
"RELEASE_VERSION='${GITHUB_REF_NAME}' sh -s" <<'REMOTE_DEPLOY'
set -eu
release_tar="/var/lib/xiaoxia-saas-production/release-${RELEASE_VERSION}.tar.gz"
test -f "$release_tar"
test -f "/var/lib/xiaoxia-saas-production/runtime-images-${RELEASE_VERSION}.tar"
mkdir -p /var/lib/xiaoxia-saas-production
rm -rf /var/lib/xiaoxia-saas-production/repo
mkdir -p /var/lib/xiaoxia-saas-production/repo
tar -xzf "$release_tar" -C /var/lib/xiaoxia-saas-production/repo
test -f /var/lib/xiaoxia-saas-production/repo/apps/web/dist/index.html
test -f /var/lib/xiaoxia-saas-production/.env
cp /var/lib/xiaoxia-saas-production/.env /var/lib/xiaoxia-saas-production/repo/.env
sh /var/lib/xiaoxia-saas-production/repo/infra/docker/deploy-production.sh
i=0
while [ "$i" -lt 30 ]; do
if wget -qO- http://127.0.0.1:8001/health; then
@@ -208,3 +196,4 @@ jobs:
sleep 2
done
exit 1
REMOTE_DEPLOY
+3 -3
View File
@@ -58,10 +58,10 @@ On `v*` tag push:
4. It builds `apps/web/dist` in a Node Docker container, not on production.
5. It packages `release-<tag>.tar.gz` with the prebuilt Web dist.
6. It uploads both `runtime-images-<tag>.tar` and `release-<tag>.tar.gz` to production.
7. `deploy-production` runs after the build job succeeds.
8. `deploy-production` extracts the prebuilt release artifact, loads `/var/lib/xiaoxia-saas-production/runtime-images-<tag>.tar`, and restarts API/Worker/Web.
7. `deploy-production` runs after the build job succeeds, on `runtime-builder`, and drives production over SSH.
8. `deploy-production` extracts the prebuilt release artifact on production, loads `/var/lib/xiaoxia-saas-production/runtime-images-<tag>.tar`, and restarts API/Worker/Web.
If either the release tar or runtime image tar is missing, production deploy must fail.
If either the release tar or runtime image tar is missing, production deploy must fail. The production deploy job intentionally also runs on `runtime-builder` because Gitea `needs` scheduling previously skipped the downstream `ubuntu-latest` deploy job after a successful cross-runner build.
## Preflight checks on runner
+6 -3
View File
@@ -17,7 +17,7 @@ def test_gitea_production_deploy_uses_production_ports():
assert "GITHUB_TOKEN: ${{ github.token }}" in workflow
assert "WEB_PORT=3001" not in production_section
assert "http://127.0.0.1:8001/health" in production_section
assert "RELEASE_VERSION=\"${GITHUB_REF_NAME}\"" in production_section
assert "RELEASE_VERSION='${GITHUB_REF_NAME}' sh -s" in production_section
assert "http://127.0.0.1:8000/health" not in production_section
@@ -173,9 +173,12 @@ def test_gitea_production_deploy_requires_runtime_builder_job():
assert "runtime-images-${GITHUB_REF_NAME}.tar" in build_section
assert "release-${GITHUB_REF_NAME}.tar.gz" in build_section
assert "needs: build-production-runtime-images" in production_section
assert "Sync release artifact to production workspace" in production_section
assert "release_tar=\"/host/var/lib/xiaoxia-saas-production/release-${GITHUB_REF_NAME}.tar.gz\"" in production_section
assert "runs-on: runtime-builder" in production_section
assert "Deploy production over SSH" in production_section
assert "release_tar=\"/var/lib/xiaoxia-saas-production/release-${RELEASE_VERSION}.tar.gz\"" in production_section
assert "runtime-images-${RELEASE_VERSION}.tar" in production_section
assert "apps/web/dist/index.html" in production_section
assert "sh /var/lib/xiaoxia-saas-production/repo/infra/docker/deploy-production.sh" in production_section
def test_build_host_runbook_requires_off_production_runtime_builds():