Files
hi-server/.github/workflows/release-acceptance.yml
T
2026-06-12 02:03:43 -07:00

267 lines
10 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: 发布验收测试
on:
workflow_run:
workflows:
- 测试环境部署
types:
- completed
branches:
- internal
- main
workflow_dispatch:
permissions:
contents: read
actions: read
concurrency:
group: release-acceptance
cancel-in-progress: false
env:
ACCEPTANCE_ARTIFACT_NAME: release-acceptance-${{ github.run_id }}-${{ github.run_attempt }}
ACCEPTANCE_REPORT_DIR: ${{ github.workspace }}/acceptance-artifacts
ACCEPTANCE_REPORT_PATH: ${{ github.workspace }}/acceptance-artifacts/acceptance-report.json
ACCEPTANCE_TEST_JSON: ${{ github.workspace }}/acceptance-artifacts/go-test.json
ACCEPTANCE_FAILURE_LOG: ${{ github.workspace }}/acceptance-artifacts/failure.log
ACCEPTANCE_NODE_SERVER_ID: ${{ vars.ACCEPTANCE_NODE_SERVER_ID || '31' }}
ACCEPTANCE_NODE_PROTOCOL: ${{ vars.ACCEPTANCE_NODE_PROTOCOL || 'trojan' }}
jobs:
acceptance:
name: Staging acceptance
runs-on: ubuntu-latest
timeout-minutes: 20
env:
STAGING_BASE_URL: ${{ secrets.STAGING_BASE_URL || vars.STAGING_BASE_URL || 'https://tapi.hifast.biz' }}
if: >-
${{
github.event_name == 'workflow_dispatch' ||
(
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push'
)
}}
steps:
- name: 检出代码
uses: actions/checkout@v6
with:
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
- name: 配置 Go 环境
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache: true
- name: 准备报告目录
run: mkdir -p "$ACCEPTANCE_REPORT_DIR"
- name: 校验必需配置
env:
ACCEPTANCE_ADMIN_EMAIL: ${{ secrets.ACCEPTANCE_ADMIN_EMAIL }}
ACCEPTANCE_ADMIN_PASSWORD: ${{ secrets.ACCEPTANCE_ADMIN_PASSWORD }}
ACCEPTANCE_USER_EMAIL: ${{ secrets.ACCEPTANCE_USER_EMAIL }}
ACCEPTANCE_USER_PASSWORD: ${{ secrets.ACCEPTANCE_USER_PASSWORD }}
STAGING_BASE_URL: ${{ secrets.STAGING_BASE_URL || vars.STAGING_BASE_URL || 'https://tapi.hifast.biz' }}
STAGING_DB_HOST: ${{ secrets.STAGING_DB_HOST }}
STAGING_DB_USER: ${{ secrets.STAGING_DB_USER }}
STAGING_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
STAGING_DB_NAME: ${{ secrets.STAGING_DB_NAME }}
STAGING_REDIS_ADDR: ${{ secrets.STAGING_REDIS_ADDR }}
STAGING_REDIS_PASSWORD: ${{ secrets.STAGING_REDIS_PASSWORD }}
run: |
set -euo pipefail
if [ -z "${STAGING_BASE_URL:-}" ]; then
echo "STAGING_BASE_URL 未配置且默认值不可用" | tee "$ACCEPTANCE_FAILURE_LOG"
{
echo "## 发布验收测试"
echo
echo "状态:配置错误"
echo
echo "- `STAGING_BASE_URL` 不能为空。"
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
missing_optional=()
optional=(
ACCEPTANCE_ADMIN_EMAIL
ACCEPTANCE_ADMIN_PASSWORD
ACCEPTANCE_USER_EMAIL
ACCEPTANCE_USER_PASSWORD
STAGING_DB_HOST
STAGING_DB_USER
STAGING_DB_PASSWORD
STAGING_DB_NAME
STAGING_REDIS_ADDR
STAGING_REDIS_PASSWORD
)
for key in "${optional[@]}"; do
if [ -z "${!key:-}" ]; then
missing_optional+=("$key")
fi
done
: > "$ACCEPTANCE_FAILURE_LOG"
if [ "${#missing_optional[@]}" -gt 0 ]; then
printf '缺少可选 GitHub Actions secrets/vars,部分验收用例将被跳过:\n' | tee -a "$ACCEPTANCE_FAILURE_LOG"
printf -- '- %s\n' "${missing_optional[@]}" | tee -a "$ACCEPTANCE_FAILURE_LOG"
{
echo "## 发布验收测试"
echo
echo "状态:部分配置缺失"
echo
echo "缺少以下可选 secrets/vars,对应验收用例会在测试阶段自动跳过:"
printf -- '- `%s`\n' "${missing_optional[@]}"
echo
echo "- `STAGING_BASE_URL`${STAGING_BASE_URL}"
} >> "$GITHUB_STEP_SUMMARY"
else
{
echo "## 发布验收测试"
echo
echo "状态:配置检查通过"
echo
echo "- `STAGING_BASE_URL`${STAGING_BASE_URL}"
} >> "$GITHUB_STEP_SUMMARY"
fi
- name: 下载依赖模块
run: go mod download
- name: 运行 acceptance 测试
env:
ACCEPTANCE_ADMIN_EMAIL: ${{ secrets.ACCEPTANCE_ADMIN_EMAIL }}
ACCEPTANCE_ADMIN_PASSWORD: ${{ secrets.ACCEPTANCE_ADMIN_PASSWORD }}
ACCEPTANCE_USER_EMAIL: ${{ secrets.ACCEPTANCE_USER_EMAIL }}
ACCEPTANCE_USER_PASSWORD: ${{ secrets.ACCEPTANCE_USER_PASSWORD }}
ACCEPTANCE_NODE_SECRET: ${{ secrets.ACCEPTANCE_NODE_SECRET }}
ACCEPTANCE_RUN_ID: qa_${{ github.run_id }}_${{ github.run_attempt }}
STAGING_DB_HOST: ${{ secrets.STAGING_DB_HOST }}
STAGING_DB_USER: ${{ secrets.STAGING_DB_USER }}
STAGING_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
STAGING_DB_NAME: ${{ secrets.STAGING_DB_NAME }}
STAGING_REDIS_ADDR: ${{ secrets.STAGING_REDIS_ADDR }}
STAGING_REDIS_PASSWORD: ${{ secrets.STAGING_REDIS_PASSWORD }}
STAGING_REDIS_DB: ${{ vars.STAGING_REDIS_DB || '0' }}
run: |
set -o pipefail
go test -json ./tests/acceptance/... \
-staging-url="$STAGING_BASE_URL" \
-report-path="$ACCEPTANCE_REPORT_PATH" \
> >(tee "$ACCEPTANCE_TEST_JSON") \
2> >(tee "$ACCEPTANCE_FAILURE_LOG" >&2)
- name: 生成测试摘要
if: always()
run: |
set -euo pipefail
{
echo "## 发布验收测试"
echo
echo "- 状态:${{ job.status }}"
echo "- Staging URL${STAGING_BASE_URL}"
echo "- Artifact${ACCEPTANCE_ARTIFACT_NAME}"
echo "- Run URL${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
if [ "${{ github.event_name }}" = "workflow_run" ]; then
echo "- Deploy run${{ github.event.workflow_run.html_url }}"
echo "- Deploy SHA${{ github.event.workflow_run.head_sha }}"
else
echo "- 手动触发 SHA${{ github.sha }}"
fi
echo
} | tee "$ACCEPTANCE_REPORT_DIR/summary.md" >> "$GITHUB_STEP_SUMMARY"
if [ "${{ job.status }}" = "failure" ]; then
if [ -s "$ACCEPTANCE_FAILURE_LOG" ]; then
{
echo
echo "Run URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
echo "Artifact: ${ACCEPTANCE_ARTIFACT_NAME}"
} >> "$ACCEPTANCE_FAILURE_LOG"
else
{
echo "Acceptance 测试失败。"
echo "Run URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
echo "Artifact: ${ACCEPTANCE_ARTIFACT_NAME}"
echo
tail -100 "$ACCEPTANCE_TEST_JSON" 2>/dev/null || true
} > "$ACCEPTANCE_FAILURE_LOG"
fi
elif [ ! -f "$ACCEPTANCE_FAILURE_LOG" ]; then
: > "$ACCEPTANCE_FAILURE_LOG"
fi
- name: 上传 acceptance artifact
if: always()
uses: actions/upload-artifact@v6
with:
name: ${{ env.ACCEPTANCE_ARTIFACT_NAME }}
path: |
${{ env.ACCEPTANCE_REPORT_PATH }}
${{ env.ACCEPTANCE_TEST_JSON }}
${{ env.ACCEPTANCE_FAILURE_LOG }}
${{ env.ACCEPTANCE_REPORT_DIR }}/summary.md
if-no-files-found: warn
retention-days: 14
- name: Telegram 成功通知
if: success()
env:
TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }}
TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }}
run: |
if [ -z "${TG_BOT_TOKEN:-}" ] || [ -z "${TG_CHAT_ID:-}" ]; then
echo "Telegram 密钥未配置,跳过通知。"
exit 0
fi
MESSAGE="$(cat <<'EOF'
✅ 发布验收测试通过
仓库:${{ github.repository }}
分支:${{ github.event.workflow_run.head_branch || github.ref_name }}
提交:${{ github.event.workflow_run.head_sha || github.sha }}
Staging${{ env.STAGING_BASE_URL }}
Artifact${{ env.ACCEPTANCE_ARTIFACT_NAME }}
运行记录:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
EOF
)"
curl -fsS -X POST "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage" \
--data-urlencode "chat_id=${TG_CHAT_ID}" \
--data-urlencode "text=${MESSAGE}" || echo "Telegram 通知发送失败,但验收结果不受影响。"
- name: Telegram 失败通知
if: failure()
env:
TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }}
TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }}
run: |
if [ -z "${TG_BOT_TOKEN:-}" ] || [ -z "${TG_CHAT_ID:-}" ]; then
echo "Telegram 密钥未配置,跳过通知。"
exit 0
fi
MESSAGE="$(cat <<'EOF'
❌ 发布验收测试失败
仓库:${{ github.repository }}
分支:${{ github.event.workflow_run.head_branch || github.ref_name }}
提交:${{ github.event.workflow_run.head_sha || github.sha }}
Staging${{ env.STAGING_BASE_URL }}
Artifact${{ env.ACCEPTANCE_ARTIFACT_NAME }}
运行记录:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
EOF
)"
curl -fsS -X POST "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage" \
--data-urlencode "chat_id=${TG_CHAT_ID}" \
--data-urlencode "text=${MESSAGE}" || echo "Telegram 通知发送失败,工作流失败状态已记录。"