runner 出网对明文 HTTP(80 端口)持续返回 502,Playwright --with-deps 从 archive/security.ubuntu.com 拉包必然失败(run 1954/1956 三次重试全部 apt exit 100),而同环境 HTTPS 仓库均正常。安装依赖前先把 Ubuntu 源 整体改写为 HTTPS:官方源优先,失败依次切换阿里云、TUNA 镜像,全部 不可用才报错;microsoft/launchpad 等第三方源不受影响。
149 lines
6.7 KiB
YAML
149 lines
6.7 KiB
YAML
name: Verify
|
||
on: [push, pull_request]
|
||
permissions:
|
||
contents: read
|
||
jobs:
|
||
verify:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
postgres:
|
||
image: postgres:17
|
||
env:
|
||
POSTGRES_PASSWORD: ci-only-password
|
||
POSTGRES_DB: traceiq
|
||
options: >-
|
||
--label traceiq-ci-postgres=${{ github.repository }}:${{ github.run_id }}:${{ github.run_attempt }}
|
||
--health-cmd pg_isready --health-interval 5s
|
||
--health-timeout 5s --health-retries 10
|
||
env:
|
||
E2E_PASSWORD: CI-Test-Only-SecurePassword882!
|
||
PYTHONPATH: .
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: astral-sh/setup-uv@v6
|
||
with:
|
||
version: '0.10.12'
|
||
- uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: npm
|
||
- run: uv sync --frozen --python 3.12
|
||
# runner 使用共享 Docker 网络;按本次运行的标签找服务 IP,避免共用 postgres 别名。
|
||
# act_runner v0.6.1 尚未提供 job.services.postgres.id,现有 Docker socket 仅用于读取。
|
||
- name: Resolve isolated PostgreSQL service
|
||
env:
|
||
POSTGRES_SERVICE_LABEL: traceiq-ci-postgres=${{ github.repository }}:${{ github.run_id }}:${{ github.run_attempt }}
|
||
run: |
|
||
postgres_containers=$(curl --fail --silent --show-error \
|
||
--unix-socket /var/run/docker.sock \
|
||
--get --data-urlencode "filters={\"label\":[\"$POSTGRES_SERVICE_LABEL\"]}" \
|
||
http://localhost/containers/json)
|
||
POSTGRES_CONTAINERS="$postgres_containers" uv run python - <<'PY'
|
||
import ipaddress
|
||
import json
|
||
import os
|
||
|
||
containers = json.loads(os.environ["POSTGRES_CONTAINERS"])
|
||
if len(containers) != 1:
|
||
raise SystemExit("Expected exactly one PostgreSQL service for this run")
|
||
networks = list(containers[0]["NetworkSettings"]["Networks"].values())
|
||
if len(networks) != 1:
|
||
raise SystemExit("Expected PostgreSQL to use the runner's single Docker network")
|
||
address = ipaddress.IPv4Address(networks[0]["IPAddress"])
|
||
with open(os.environ["GITHUB_ENV"], "a") as env_file:
|
||
env_file.write(f"DATABASE_URL=postgresql://postgres:ci-only-password@{address}:5432/traceiq\n")
|
||
PY
|
||
- run: npm ci --registry=https://registry.npmjs.org
|
||
- run: uv run ruff check server finance tests scripts
|
||
- run: uv run ruff format --check server finance tests scripts
|
||
- run: uv run python manage.py makemigrations --check --dry-run
|
||
- run: uv run pytest --cov=finance --cov-report=term-missing --cov-fail-under=85
|
||
- run: npm run build
|
||
# 审计端点在 runner 网络下偶发 TLS 断开(npm error audit endpoint returned
|
||
# an error),重试区分网络抖动与真实漏洞:漏洞是确定性的,重试后照样红。
|
||
- name: npm audit (production deps)
|
||
run: |
|
||
for attempt in 1 2 3; do
|
||
npm audit --omit=dev --registry=https://registry.npmjs.org && exit 0
|
||
echo "::warning::npm audit 第 ${attempt} 次失败,15 秒后重试"
|
||
sleep 15
|
||
done
|
||
exit 1
|
||
- name: pip-audit
|
||
run: |
|
||
for attempt in 1 2 3; do
|
||
uv run pip-audit && exit 0
|
||
echo "::warning::pip-audit 第 ${attempt} 次失败,15 秒后重试"
|
||
sleep 15
|
||
done
|
||
exit 1
|
||
- run: uv run python manage.py migrate --noinput
|
||
- run: uv run python manage.py collectstatic --noinput
|
||
- run: uv run python manage.py bootstrap --username admin --organization CI
|
||
env:
|
||
BOOTSTRAP_PASSWORD: ${{ env.E2E_PASSWORD }}
|
||
# runner 出网对明文 HTTP(80 端口)一律 502,archive/security.ubuntu.com
|
||
# 的 Ubuntu 源拉不到包;HTTPS 仓库(microsoft、launchpad 等)均正常。
|
||
# 装 Playwright 系统依赖前把 Ubuntu 源整体切到 HTTPS,官方源优先、镜像兜底。
|
||
- name: Switch apt sources to HTTPS
|
||
run: |
|
||
set -euo pipefail
|
||
if [ "$(id -u)" -eq 0 ]; then S=""; else S="sudo"; fi
|
||
sources=$(ls /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources 2>/dev/null || true)
|
||
[ -n "$sources" ] || { echo "未找到 apt 源文件" >&2; exit 1; }
|
||
backup=/tmp/apt-sources-orig
|
||
rm -rf "$backup" && mkdir -p "$backup"
|
||
$S cp -a /etc/apt/sources.list "$backup/" 2>/dev/null || true
|
||
$S cp -a /etc/apt/sources.list.d "$backup/"
|
||
restore() {
|
||
$S rm -f /etc/apt/sources.list
|
||
$S find /etc/apt/sources.list.d -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
||
$S cp -a "$backup/sources.list" /etc/apt/sources.list 2>/dev/null || true
|
||
$S cp -a "$backup/sources.list.d/." /etc/apt/sources.list.d/
|
||
}
|
||
for mirror in \
|
||
"${CI_APT_MIRROR:-https://archive.ubuntu.com/ubuntu/}" \
|
||
https://mirrors.aliyun.com/ubuntu/ \
|
||
https://mirrors.tuna.tsinghua.edu.cn/ubuntu/; do
|
||
echo "::group::apt 源 -> $mirror"
|
||
restore
|
||
$S sed -E -i "s#https?://([a-z0-9-]+\.)*(archive|security)\.ubuntu\.com/ubuntu/?#$mirror#g" $sources
|
||
if $S apt-get update -o Acquire::Retries=3; then
|
||
echo "apt 源已使用 $mirror"
|
||
exit 0
|
||
fi
|
||
echo "::warning::apt 源 $mirror 更新失败,尝试下一个镜像"
|
||
done
|
||
echo "所有 apt 镜像均不可用" >&2
|
||
exit 1
|
||
- name: Install Playwright Chromium
|
||
run: |
|
||
for attempt in 1 2 3; do
|
||
npx playwright install --with-deps chromium && exit 0
|
||
if [ "$attempt" -lt 3 ]; then
|
||
echo "::warning::Playwright 安装第 ${attempt} 次失败,15 秒后重试"
|
||
sleep 15
|
||
fi
|
||
done
|
||
exit 1
|
||
- name: Browser regression
|
||
shell: bash
|
||
run: |
|
||
uv run python manage.py runserver 127.0.0.1:8000 --noreload > /tmp/web.log 2>&1 &
|
||
web=$!
|
||
uv run python manage.py import_worker > /tmp/worker.log 2>&1 &
|
||
worker=$!
|
||
trap 'kill "$web" "$worker"' EXIT
|
||
for i in {1..30}; do curl -fsS http://127.0.0.1:8000/api/health && break; sleep 1; done
|
||
npm run test:e2e
|
||
# Gitea 不支持 upload-artifact@v4 的 artifact 协议(GHESNotSupportedError),
|
||
# 上传失败不该把已经全绿的测试标红;迁到 GitHub 托管时此步骤自动生效。
|
||
- uses: actions/upload-artifact@v4
|
||
if: always()
|
||
continue-on-error: true
|
||
with:
|
||
name: browser-results
|
||
path: |
|
||
playwright-report
|
||
test-results
|