-
Notifications
You must be signed in to change notification settings - Fork 12
153 lines (136 loc) · 5.54 KB
/
Copy pathuat-bypass.yml
File metadata and controls
153 lines (136 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
name: uat-bypass
# Phase 47 Plan 03 BYPASS-VERIFY-02/03/04:v3.5 白名单 fail-closed CI 守护。
#
# 工作流分两层:
#
# 1. lint — 永远跑:bash -n、--help、--dry-run 6 场景全过。
# 这一步在 ubuntu runner 不需要 nft/docker/sudo,只验证脚本本身。
#
# 2. uat — 真实 6 场景 × ubuntu-24.04 矩阵。
# fixture 脚本(scripts/uat-bypass-fixture-up.sh,需要起完整控制面
# + 颁发 admin token + 起带 sing-box gateway 的 bypass host)在
# Phase 47 verification 之后才会落地。本 job 通过 preflight step
# 检测 fixture 是否存在:
# - 存在 → 完整跑 6 场景断言 I1–I10。
# - 缺失 → 显式 SKIP(脚本 exit 2,被 continue-on-error 吞下),
# 仍记录为绿色,但 Summary 里能看到 "fixture missing"。
# 这样既能在 fixture 合入后 CI 立刻生效守护 ROADMAP SC#5,
# 又不会在 fixture 缺失阶段假阳性阻塞 PR。
#
# 通过这种分层,PR 阶段能立刻 catch 脚本回归(如 bash 语法、--dry-run 退出码),
# 也能在 fixture 合入后零配置切换到真实 CI 守护。
on:
pull_request:
paths:
- "internal/network/**"
- "internal/runtime/tasks/**"
- "internal/controlplane/http/admin_bypass*"
- "scripts/uat-bypass.sh"
- ".github/workflows/uat-bypass.yml"
push:
branches: [main]
permissions:
contents: read
concurrency:
group: uat-bypass-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: lint + dry-run 6 scenarios
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install minimal tools (jq / curl)
run: |
sudo apt-get update -y
sudo apt-get install -y jq curl
- name: bash -n (syntax)
run: bash -n scripts/uat-bypass.sh
- name: --help contains 6 scenarios + I1..I10
run: |
set -euo pipefail
OUT=$(bash scripts/uat-bypass.sh --help)
SCEN_COUNT=$(echo "$OUT" | grep -cE 'loopback-only|lan-only|loopback-lan|custom-ip|custom-domain|fail-closed-pkill')
INV_COUNT=$(echo "$OUT" | grep -cE 'I[0-9]')
echo "scenario references: $SCEN_COUNT"
echo "invariant references: $INV_COUNT"
test "$SCEN_COUNT" -ge 6
test "$INV_COUNT" -ge 10
- name: --dry-run all 6 scenarios
run: |
set -euo pipefail
for s in loopback-only lan-only loopback-lan custom-ip custom-domain fail-closed-pkill; do
echo "=== dry-run scenario=$s ==="
bash scripts/uat-bypass.sh \
--scenario="$s" \
--target-host-id=ci-dryrun \
--admin-token=ci-dryrun \
--dry-run
done
uat:
name: uat scenario=${{ matrix.scenario }}
runs-on: ubuntu-24.04
needs: lint
strategy:
fail-fast: false
matrix:
scenario:
- loopback-only
- lan-only
- loopback-lan
- custom-ip
- custom-domain
- fail-closed-pkill
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preflight — check fixture script availability
id: preflight
run: |
if [ -f scripts/uat-bypass-fixture-up.sh ]; then
echo "fixture_available=true" >> "$GITHUB_OUTPUT"
echo "[INFO] scripts/uat-bypass-fixture-up.sh 存在,将跑完整 uat 流程"
else
echo "fixture_available=false" >> "$GITHUB_OUTPUT"
echo "::warning::scripts/uat-bypass-fixture-up.sh 缺失,本次 uat job 仅 lint job 已守护脚本回归;完整 6 场景断言留待 fixture 落地"
fi
- name: Install prerequisites
if: steps.preflight.outputs.fixture_available == 'true'
run: |
sudo apt-get update -y
sudo apt-get install -y nftables tcpdump jq dnsutils curl
- name: Setup Go
if: steps.preflight.outputs.fixture_available == 'true'
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Build control plane
if: steps.preflight.outputs.fixture_available == 'true'
run: go build -o /tmp/cloud-cli-proxy ./cmd/control-plane
- name: Bring up bypass fixture
if: steps.preflight.outputs.fixture_available == 'true'
run: |
# scripts/uat-bypass-fixture-up.sh 必须输出 /tmp/uat-fixture.json
# 含 host_id + admin_token 两个字段(fixture 契约)。
bash scripts/uat-bypass-fixture-up.sh
echo "HOST_ID=$(jq -r '.host_id' /tmp/uat-fixture.json)" >> "$GITHUB_ENV"
echo "ADMIN_TOKEN=$(jq -r '.admin_token' /tmp/uat-fixture.json)" >> "$GITHUB_ENV"
- name: Run uat-bypass scenario=${{ matrix.scenario }}
if: steps.preflight.outputs.fixture_available == 'true'
env:
CLOUD_CLI_PROXY_ADMIN_TOKEN: ${{ env.ADMIN_TOKEN }}
CLOUD_CLI_PROXY_API_BASE: http://localhost:8080
run: |
bash scripts/uat-bypass.sh \
--scenario=${{ matrix.scenario }} \
--target-host-id="$HOST_ID"
- name: Teardown fixture
if: always() && steps.preflight.outputs.fixture_available == 'true'
run: |
if [ -f scripts/uat-bypass-fixture-down.sh ]; then
bash scripts/uat-bypass-fixture-down.sh
else
bash scripts/test-fixture-down.sh || true
fi