c22ab58ff2
Deploy / Deploy Staging (push) Failing after 209h0m7s
CI/CD Pipeline / Frontend Lint (push) Failing after 209h0m36s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 209h0m45s
Deploy / Production Browser E2E (push) Failing after 1867h15m39s
Deploy / Deploy Production (push) Failing after 1867h15m41s
Deploy / Build Production Runtime Images (push) Failing after 1867h16m27s
- Add 'Build and push staging API/Worker images' step in deploy.yml - Update inline deploy script to pass REGISTRY/API_IMAGE/WORKER_IMAGE - Update deploy-staging.sh to default to registry-prefixed image names - Fix infra container checks to use -staging suffix
334 lines
17 KiB
YAML
334 lines
17 KiB
YAML
name: Deploy
|
|
|
|
on:
|
|
push:
|
|
branches: [ main, develop, "feature/**" ]
|
|
tags:
|
|
- 'v*'
|
|
|
|
jobs:
|
|
deploy-staging:
|
|
name: Deploy Staging
|
|
runs-on: ubuntu-22.04
|
|
if: github.ref_name == 'main' || github.ref_name == 'develop' || startsWith(github.ref_name, 'feature/')
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
shell: sh
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
run: |
|
|
set -eu
|
|
python3 - <<'PY'
|
|
import io, os, tarfile, urllib.request
|
|
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: Install SSH client
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
apt-get update -qq && apt-get install -y -qq openssh-client >/dev/null 2>&1
|
|
echo "openssh-client installed"
|
|
|
|
- name: Build staging web artifact
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
docker run --rm \
|
|
--pull=never \
|
|
-v "$PWD:/workspace" \
|
|
-w /workspace/apps/web \
|
|
docker.m.daocloud.io/library/node:20 \
|
|
sh -lc 'npm ci && npm run build'
|
|
docker build --pull=false \
|
|
-f infra/docker/web-artifact.Dockerfile \
|
|
-t "xiaoxia-saas-web:staging-${GITHUB_SHA}" \
|
|
.
|
|
test -f apps/web/dist/index.html
|
|
|
|
|
|
- name: Build and push staging API/Worker images
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
REGISTRY="172.30.18.198:5000"
|
|
docker build --pull=false \
|
|
-f infra/docker/api.Dockerfile \
|
|
-t "${REGISTRY}/xiaoxia-saas-api:dev" \
|
|
.
|
|
docker build --pull=false \
|
|
-f infra/docker/worker.Dockerfile \
|
|
-t "${REGISTRY}/xiaoxia-saas-worker:dev" \
|
|
.
|
|
docker push "${REGISTRY}/xiaoxia-saas-api:dev"
|
|
docker push "${REGISTRY}/xiaoxia-saas-worker:dev"
|
|
|
|
- name: Package staging release artifact
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
rm -rf dist/staging-artifacts
|
|
mkdir -p dist/staging-artifacts
|
|
tar --exclude=.git --exclude=apps/web/node_modules --exclude=./dist \
|
|
-czf dist/staging-artifacts/xiaoxia-staging-${GITHUB_SHA}.tar.gz .
|
|
docker save -o "dist/staging-artifacts/xiaoxia-web-staging-${GITHUB_SHA}.tar" "xiaoxia-saas-web:staging-${GITHUB_SHA}"
|
|
|
|
- name: Upload staging artifact to business host
|
|
shell: sh
|
|
env:
|
|
STAGING_SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
|
|
STAGING_SSH_USER: ${{ secrets.STAGING_SSH_USER }}
|
|
STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
|
|
run: |
|
|
set -eu
|
|
staging_host="${STAGING_SSH_HOST:-47.98.113.167}"
|
|
staging_user="${STAGING_SSH_USER:-root}"
|
|
mkdir -p ~/.ssh
|
|
# Prefer host key if available (more reliable), fallback to secrets
|
|
if [ -f /root/.ssh/xiaoxia_runtime_builder ]; then
|
|
key_path="/root/.ssh/xiaoxia_runtime_builder"
|
|
echo "Using host SSH key: $key_path"
|
|
elif [ -n "${STAGING_SSH_KEY:-}" ]; then
|
|
key_path="$HOME/.ssh/id_ed25519"
|
|
printf '%s\n' "$STAGING_SSH_KEY" > "$key_path"
|
|
chmod 600 "$key_path"
|
|
echo "Using secret SSH key: $key_path"
|
|
else
|
|
echo "ERROR: No SSH key available"
|
|
exit 1
|
|
fi
|
|
ssh-keyscan -H "$staging_host" >> ~/.ssh/known_hosts
|
|
ssh -i "$key_path" "$staging_user@$staging_host" "mkdir -p /var/lib/xiaoxia-saas-staging/artifacts"
|
|
scp -i "$key_path" "dist/staging-artifacts/xiaoxia-staging-${GITHUB_SHA}.tar.gz" \
|
|
"$staging_user@$staging_host:/var/lib/xiaoxia-saas-staging/artifacts/xiaoxia-staging-${GITHUB_SHA}.tar.gz"
|
|
scp -i "$key_path" "dist/staging-artifacts/xiaoxia-web-staging-${GITHUB_SHA}.tar" \
|
|
"$staging_user@$staging_host:/var/lib/xiaoxia-saas-staging/artifacts/xiaoxia-web-staging-${GITHUB_SHA}.tar"
|
|
|
|
- name: Deploy staging stack on business host
|
|
shell: sh
|
|
env:
|
|
STAGING_SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
|
|
STAGING_SSH_USER: ${{ secrets.STAGING_SSH_USER }}
|
|
STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
|
|
run: |
|
|
set -eu
|
|
staging_host="${STAGING_SSH_HOST:-47.98.113.167}"
|
|
staging_user="${STAGING_SSH_USER:-root}"
|
|
if [ -f /root/.ssh/xiaoxia_runtime_builder ]; then
|
|
key_path="/root/.ssh/xiaoxia_runtime_builder"
|
|
elif [ -n "${STAGING_SSH_KEY:-}" ]; then
|
|
key_path="$HOME/.ssh/id_ed25519"
|
|
else
|
|
echo "ERROR: No SSH key available"
|
|
exit 1
|
|
fi
|
|
echo 'c2V0IC1ldQphcnRpZmFjdD0iL3Zhci9saWIveGlhb3hpYS1zYWFzLXN0YWdpbmcvYXJ0aWZhY3RzL3hpYW94aWEtc3RhZ2luZy0ke0dJVEhVQl9TSEF9LnRhci5neiIKaW1hZ2VfdGFyPSIvdmFyL2xpYi94aWFveGlhLXNhYXMtc3RhZ2luZy9hcnRpZmFjdHMveGlhb3hpYS13ZWItc3RhZ2luZy0ke0dJVEhVQl9TSEF9LnRhciIKdGVzdCAtZiAiJGFydGlmYWN0Igp0ZXN0IC1mICIkaW1hZ2VfdGFyIgp0ZXN0IC1mIC92YXIvbGliL3hpYW94aWEtc2Fhcy1zdGFnaW5nLy5lbnYKZG9ja2VyIGxvYWQgLWkgIiRpbWFnZV90YXIiCnJtIC1yZiAvdmFyL2xpYi94aWFveGlhLXNhYXMtc3RhZ2luZy9yZXBvCm1rZGlyIC1wIC92YXIvbGliL3hpYW94aWEtc2Fhcy1zdGFnaW5nL3JlcG8KdGFyIC14emYgIiRhcnRpZmFjdCIgLUMgL3Zhci9saWIveGlhb3hpYS1zYWFzLXN0YWdpbmcvcmVwbwp0ZXN0IC1mIC92YXIvbGliL3hpYW94aWEtc2Fhcy1zdGFnaW5nL3JlcG8vYXBwcy93ZWIvZGlzdC9pbmRleC5odG1sCmNwIC92YXIvbGliL3hpYW94aWEtc2Fhcy1zdGFnaW5nLy5lbnYgL3Zhci9saWIveGlhb3hpYS1zYWFzLXN0YWdpbmcvcmVwby8uZW52CmNobW9kICt4IC92YXIvbGliL3hpYW94aWEtc2Fhcy1zdGFnaW5nL3JlcG8vaW5mcmEvZG9ja2VyL2RlcGxveS1zdGFnaW5nLnNoClJFR0lTVFJZPSIxNzIuMzAuMTguMTk4OjUwMDAiIEFQSV9JTUFHRT0iJHtSRUdJU1RSWX0veGlhb3hpYS1zYWFzLWFwaTpkZXYiIFdPUktFUl9JTUFHRT0iJHtSRUdJU1RSWX0veGlhb3hpYS1zYWFzLXdvcmtlcjpkZXYiIFdFQl9JTUFHRT0ieGlhb3hpYS1zYWFzLXdlYjpzdGFnaW5nLSR7R0lUSFVCX1NIQX0iIEhPU1RfUFJFRklYPSBXRUJfUE9SVD0zMDAxIFJFQlVJTERfQkFDS0VORD0wIEJVSUxEX1dFQj0wIFJVTl9NSUdSQVRJT05TPTAgL3Zhci9saWIveGlhb3hpYS1zYWFzLXN0YWdpbmcvcmVwby9pbmZyYS9kb2NrZXIvZGVwbG95LXN0YWdpbmcuc2gKaT0wCndoaWxlIFsgIiRpIiAtbHQgMzAgXTsgZG8KICBpZiB3Z2V0IC1xTy0gaHR0cDovLzEyNy4wLjAuMTo4MDAwL2hlYWx0aDsgdGhlbgogICAgZXhpdCAwCiAgZmkKICBpPSQoKGkgKyAxKSkKICBzbGVlcCAyCmRvbmUKZXhpdCAxCg==' | base64 -d | ssh -i "$key_path" "$staging_user@$staging_host" "GITHUB_SHA='${GITHUB_SHA}' sh"
|
|
|
|
build-production-runtime-images:
|
|
name: Build Production Runtime Images
|
|
runs-on: ubuntu-22.04
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
shell: sh
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
run: |
|
|
set -eu
|
|
python3 - <<'PY'
|
|
import io, os, tarfile, urllib.request
|
|
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: Build runtime image artifact
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
chmod +x scripts/build_release_images.sh
|
|
scripts/build_release_images.sh "${GITHUB_REF_NAME}"
|
|
|
|
- name: Build production web artifact
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
docker run --rm \
|
|
--pull=never \
|
|
-v "$PWD:/workspace" \
|
|
-w /workspace/apps/web \
|
|
docker.m.daocloud.io/library/node:20 \
|
|
sh -lc 'npm ci && npm run build'
|
|
docker build --pull=false \
|
|
-f infra/docker/web-artifact.Dockerfile \
|
|
-t "xiaoxia-saas-web:${GITHUB_REF_NAME}" \
|
|
.
|
|
test -f apps/web/dist/index.html
|
|
|
|
- name: Package release source artifact
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
mkdir -p dist/release-artifacts
|
|
tar --exclude=.git --exclude=apps/web/node_modules --exclude=./dist \
|
|
-czf "dist/release-artifacts/xiaoxia-release-${GITHUB_REF_NAME}.tar.gz" .
|
|
docker save -o "dist/release-artifacts/xiaoxia-web-${GITHUB_REF_NAME}.tar" "xiaoxia-saas-web:${GITHUB_REF_NAME}"
|
|
|
|
- name: Upload runtime image and release artifacts
|
|
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
|
|
production_host="${PRODUCTION_SSH_HOST:-47.98.113.167}"
|
|
production_user="${PRODUCTION_SSH_USER:-root}"
|
|
mkdir -p ~/.ssh
|
|
# Prefer host key if available (more reliable), fallback to secrets
|
|
if [ -f /root/.ssh/xiaoxia_runtime_builder ]; then
|
|
key_path="/root/.ssh/xiaoxia_runtime_builder"
|
|
echo "Using host SSH key: $key_path"
|
|
elif [ -n "${PRODUCTION_SSH_KEY:-}" ]; then
|
|
key_path="$HOME/.ssh/id_ed25519"
|
|
printf '%s\n' "$PRODUCTION_SSH_KEY" > "$key_path"
|
|
chmod 600 "$key_path"
|
|
echo "Using secret SSH key: $key_path"
|
|
else
|
|
echo "ERROR: No SSH key available"
|
|
exit 1
|
|
fi
|
|
ssh-keyscan -H "$production_host" >> ~/.ssh/known_hosts
|
|
scp -i "$key_path" "dist/release-images/xiaoxia-runtime-images-${GITHUB_REF_NAME}.tar" \
|
|
"$production_user@$production_host:/var/lib/xiaoxia-saas-production/runtime-images-${GITHUB_REF_NAME}.tar"
|
|
scp -i "$key_path" "dist/release-artifacts/xiaoxia-release-${GITHUB_REF_NAME}.tar.gz" \
|
|
"$production_user@$production_host:/var/lib/xiaoxia-saas-production/release-${GITHUB_REF_NAME}.tar.gz"
|
|
scp -i "$key_path" "dist/release-artifacts/xiaoxia-web-${GITHUB_REF_NAME}.tar" \
|
|
"$production_user@$production_host:/var/lib/xiaoxia-saas-production/web-${GITHUB_REF_NAME}.tar"
|
|
|
|
- name: Cleanup old Docker images
|
|
if: always()
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
if [ -f scripts/cleanup_old_images.sh ]; then
|
|
chmod +x scripts/cleanup_old_images.sh
|
|
scripts/cleanup_old_images.sh
|
|
else
|
|
echo "Cleanup script not found, doing basic prune..."
|
|
docker image prune -f 2>/dev/null || true
|
|
fi
|
|
echo "Disk usage after cleanup:"
|
|
df -h / | tail -1
|
|
|
|
deploy-production:
|
|
name: Deploy Production
|
|
runs-on: ubuntu-22.04
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
needs: build-production-runtime-images
|
|
|
|
steps:
|
|
- name: Install SSH client
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
apt-get update -qq && apt-get install -y -qq openssh-client >/dev/null 2>&1
|
|
echo "openssh-client installed"
|
|
|
|
- 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
|
|
production_host="${PRODUCTION_SSH_HOST:-47.98.113.167}"
|
|
production_user="${PRODUCTION_SSH_USER:-root}"
|
|
mkdir -p ~/.ssh
|
|
# Prefer host key if available (more reliable), fallback to secrets
|
|
if [ -f /root/.ssh/xiaoxia_runtime_builder ]; then
|
|
key_path="/root/.ssh/xiaoxia_runtime_builder"
|
|
echo "Using host SSH key: $key_path"
|
|
elif [ -n "${PRODUCTION_SSH_KEY:-}" ]; then
|
|
key_path="$HOME/.ssh/id_ed25519"
|
|
printf '%s\n' "$PRODUCTION_SSH_KEY" > "$key_path"
|
|
chmod 600 "$key_path"
|
|
echo "Using secret SSH key: $key_path"
|
|
else
|
|
echo "ERROR: No SSH key available"
|
|
exit 1
|
|
fi
|
|
ssh-keyscan -H "$production_host" >> ~/.ssh/known_hosts
|
|
echo 'c2V0IC1ldQpyZWxlYXNlX3Rhcj0iL3Zhci9saWIveGlhb3hpYS1zYWFzLXByb2R1Y3Rpb24vcmVsZWFzZS0ke1JFTEVBU0VfVkVSU0lPTn0udGFyLmd6Igp0ZXN0IC1mICIkcmVsZWFzZV90YXIiCnRlc3QgLWYgIi92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3J1bnRpbWUtaW1hZ2VzLSR7UkVMRUFTRV9WRVJTSU9OfS50YXIiCnRlc3QgLWYgIi92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3dlYi0ke1JFTEVBU0VfVkVSU0lPTn0udGFyIgpta2RpciAtcCAvdmFyL2xpYi94aWFveGlhLXNhYXMtcHJvZHVjdGlvbgpvbGRfYXNzZXRzX2Rpcj0iL3RtcC94aWFveGlhLXByZXZpb3VzLXdlYi1hc3NldHMtJHtSRUxFQVNFX1ZFUlNJT059IgpybSAtcmYgIiRvbGRfYXNzZXRzX2RpciIKbWtkaXIgLXAgIiRvbGRfYXNzZXRzX2RpciIKaWYgZG9ja2VyIGluc3BlY3QgeGlhb3hpYS13ZWItcHJvZHVjdGlvbiA+L2Rldi9udWxsIDI+JjE7IHRoZW4KICBkb2NrZXIgY3AgeGlhb3hpYS13ZWItcHJvZHVjdGlvbjovdXNyL3NoYXJlL25naW54L2h0bWwvYXNzZXRzLy4gIiRvbGRfYXNzZXRzX2RpciIvIDI+L2Rldi9udWxsIHx8IHRydWUKZmkKaWYgWyAtZCAvdmFyL2xpYi94aWFveGlhLXNhYXMtcHJvZHVjdGlvbi9yZXBvL2FwcHMvd2ViL2Rpc3QvYXNzZXRzIF07IHRoZW4KICBjcCAtYSAvdmFyL2xpYi94aWFveGlhLXNhYXMtcHJvZHVjdGlvbi9yZXBvL2FwcHMvd2ViL2Rpc3QvYXNzZXRzLy4gIiRvbGRfYXNzZXRzX2RpciIvCmZpCnJtIC1yZiAvdmFyL2xpYi94aWFveGlhLXNhYXMtcHJvZHVjdGlvbi9yZXBvCm1rZGlyIC1wIC92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3JlcG8KdGFyIC14emYgIiRyZWxlYXNlX3RhciIgLUMgL3Zhci9saWIveGlhb3hpYS1zYWFzLXByb2R1Y3Rpb24vcmVwbwp0ZXN0IC1mIC92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3JlcG8vYXBwcy93ZWIvZGlzdC9pbmRleC5odG1sCmlmIFsgLWQgIiRvbGRfYXNzZXRzX2RpciIgXTsgdGhlbgogIG1rZGlyIC1wIC92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3JlcG8vYXBwcy93ZWIvZGlzdC9hc3NldHMKICBmb3IgYXNzZXQgaW4gIiRvbGRfYXNzZXRzX2RpciIvKjsgZG8KICAgIFsgLWUgIiRhc3NldCIgXSB8fCBjb250aW51ZQogICAgbmFtZT0iJChiYXNlbmFtZSAiJGFzc2V0IikiCiAgICBpZiBbICEgLWUgIi92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3JlcG8vYXBwcy93ZWIvZGlzdC9hc3NldHMvJG5hbWUiIF07IHRoZW4KICAgICAgY3AgLWEgIiRhc3NldCIgIi92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uL3JlcG8vYXBwcy93ZWIvZGlzdC9hc3NldHMvJG5hbWUiCiAgICBmaQogIGRvbmUKICBybSAtcmYgIiRvbGRfYXNzZXRzX2RpciIKZmkKdGVzdCAtZiAvdmFyL2xpYi94aWFveGlhLXNhYXMtcHJvZHVjdGlvbi8uZW52CmNwIC92YXIvbGliL3hpYW94aWEtc2Fhcy1wcm9kdWN0aW9uLy5lbnYgL3Zhci9saWIveGlhb3hpYS1zYWFzLXByb2R1Y3Rpb24vcmVwby8uZW52CkhPU1RfUFJFRklYPSBXRUJfSU1BR0U9InhpYW94aWEtc2Fhcy13ZWI6JHtSRUxFQVNFX1ZFUlNJT059IiBXRUJfSU1BR0VfVEFSPSIvdmFyL2xpYi94aWFveGlhLXNhYXMtcHJvZHVjdGlvbi93ZWItJHtSRUxFQVNFX1ZFUlNJT059LnRhciIgc2ggL3Zhci9saWIveGlhb3hpYS1zYWFzLXByb2R1Y3Rpb24vcmVwby9pbmZyYS9kb2NrZXIvZGVwbG95LXByb2R1Y3Rpb24uc2gKaT0wCndoaWxlIFsgIiRpIiAtbHQgMzAgXTsgZG8KICBpZiB3Z2V0IC1xTy0gaHR0cDovLzEyNy4wLjAuMTo4MDAxL2hlYWx0aDsgdGhlbgogICAgZXhpdCAwCiAgZmkKICBpPSQoKGkgKyAxKSkKICBzbGVlcCAyCmRvbmUKZXhpdCAxCg==' | base64 -d | ssh -i "$key_path" "$production_user@$production_host" "RELEASE_VERSION='${GITHUB_REF_NAME}' sh"
|
|
|
|
production-e2e:
|
|
name: Production Browser E2E
|
|
runs-on: ubuntu-22.04
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
needs: deploy-production
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
shell: sh
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
run: |
|
|
set -eu
|
|
python3 - <<'PY'
|
|
import io, os, tarfile, urllib.request
|
|
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: Run production browser E2E
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
docker run --rm \
|
|
-e E2E_BASE_URL=https://saas.xiaoxiajianji.com \
|
|
-e E2E_API_BASE=https://api.xiaoxiajianji.com/api/v1 \
|
|
-e E2E_BROWSER_CHANNEL=chromium \
|
|
-v "$PWD:/workspace" \
|
|
-w /workspace/apps/web \
|
|
mcr.microsoft.com/playwright:v1.45.0-jammy \
|
|
sh -lc 'npm ci && npx playwright test --reporter=line --project=chromium e2e/core-upload.spec.ts e2e/core-generation.spec.ts e2e/core-titles.spec.ts'
|