-
Notifications
You must be signed in to change notification settings - Fork 40
339 lines (300 loc) · 12.7 KB
/
Copy pathci.yaml
File metadata and controls
339 lines (300 loc) · 12.7 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# CI - Lint, test, and build for all modules
#
# Runs on PRs and pushes to main/release branches.
# Covers the AuthProxy Go module and Python tests.
#
name: CI
on:
pull_request:
branches:
- main
- "release-*"
push:
branches:
- main
permissions:
contents: read
jobs:
pre-commit:
name: Pre-commit Checks
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: core/go.mod
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.12'
- name: Run pre-commit
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
# TODO: Remove continue-on-error after fixing pre-existing style issues repo-wide
continue-on-error: true
env:
SKIP: ai-assisted-by-trailer
go-ci-core:
name: Go CI (core)
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: core
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: core/go.mod
cache-dependency-path: core/go.sum
- name: Lint
run: |
go fmt ./...
go vet ./...
- name: Build
run: go build -v ./...
- name: Test
run: go test -v -race -cover ./...
# The plugin-profile guards live in their own module, so no other job runs
# them. They have to run on every PR: plugins are all opt-in, and a plugin
# missing from every profile produces no build error — it just silently
# disappears from every image. TestEveryPluginIsAccountedFor is the only thing
# between that and a shipped artifact.
go-ci-profile-tags:
name: Go CI (plugin profiles)
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: scripts/profile-tags
env:
GOWORK: "off"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: scripts/profile-tags/go.mod
- name: Lint
run: |
go fmt ./...
go vet ./...
# The guards read sibling trees through relative paths (../../cmd, the repo
# root), so they need the full checkout, not just this module. -count=1 is
# required, not cosmetic: Go's test cache keys on this package's own inputs
# and knows nothing about those sibling files, so a cached PASS can outlive
# the change that should have broken it.
- name: Test
run: go test -count=1 -v -cover ./...
# Every profile must resolve to a non-empty tag list. A profile that
# silently yields nothing would flow into `go build -tags ""`.
- name: Every profile resolves
run: |
for profile in local full lite envoy cpex; do
tags=$(go run . "${profile}")
[ -n "${tags}" ] || { echo "profile ${profile} resolved to no tags"; exit 1; }
echo "${profile}: ${tags}"
done
go-ci-readme-demo:
name: Go CI (README demo)
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: scripts/readme-demo
env:
GOWORK: "off"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: scripts/readme-demo/go.mod
- name: Lint
run: |
go fmt ./...
go vet ./...
# The generator drives the real abctl TUI and compares its output against the
# committed docs/assets/cortex-demo.svg, so it reads sibling trees through
# relative paths and needs the full checkout. -count=1 is required, not
# cosmetic: Go's test cache keys on this package's own inputs and knows
# nothing about abctl's sources or the committed asset, so a cached PASS can
# outlive exactly the UI change this job exists to catch.
- name: Test (includes the asset staleness check)
run: go test -count=1 -v ./...
go-ci-authbridge-cmd:
name: Go CI (authbridge ${{ matrix.binary }})
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
binary:
- authbridge-proxy
- authbridge-envoy
# abctl is published by release-binaries.yaml, so it has to build
# under GOWORK=off here too. Omitting it let a missing go.sum entry
# for a core transitive dep reach main: the workspace build used
# everywhere else resolved it, and the per-module release build did
# not — surfacing only when a tag was cut.
- abctl
# authbridge-praxis was in no workflow at all, which is how it ended
# up broken under GOWORK=off by the same missing go.sum entry. Any
# cmd/* module absent from every workflow will drift this way — the
# workspace hides exactly this class of breakage. (authbridge-cpex is
# deliberately not here: it needs CGO and libcpex_ffi.a from a pinned
# release, so build.yaml covers it via its image build instead.)
- authbridge-praxis
defaults:
run:
working-directory: cmd/${{ matrix.binary }}
env:
# Disable go.work so each cmd/* module resolves core via its own
# `replace` directive in go.mod (the workspace would otherwise pull
# all sibling modules in and slow down CI).
GOWORK: "off"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: cmd/${{ matrix.binary }}/go.mod
cache-dependency-path: cmd/${{ matrix.binary }}/go.sum
- name: Lint
run: |
go fmt ./...
go vet ./...
- name: Build
run: go build -v ./...
# Every plugin is opt-in, so the Build and Test steps above exercise a
# binary with NO plugins linked. That is worth compiling on its own — it is
# what a caller who forgets -tags gets — but the shipped artifacts are the
# profiles, so build AND test each one here. build.yaml only exercises them
# on tag/main pushes; this catches a profile-only regression on the PR.
- name: Build + test each shipped profile
if: matrix.binary == 'authbridge-proxy' || matrix.binary == 'authbridge-envoy'
run: |
case "${{ matrix.binary }}" in
authbridge-proxy) profiles="local full lite" ;;
authbridge-envoy) profiles="envoy" ;;
esac
for profile in ${profiles}; do
echo "::group::profile ${profile}"
TAGS=$(go -C ../../scripts/profile-tags run . "${profile}")
go build -v -tags "${TAGS}" ./...
go test -race -cover -tags "${TAGS}" ./...
echo "::endgroup::"
done
# Gives the abctl leg a real systemd --user session for
# cmd_service_systemd_integration_test.go. The runner has no interactive login, so
# nothing has started one yet; enable-linger asks logind to start and keep one
# running. Either way a real problem here is loud, not silent: a hard failure (e.g.
# enable-linger itself failing) fails this step outright under bash -e, so Test
# never runs; a soft one (session unreachable after enable-linger) only warns here,
# and ABCTL_SYSTEMD_TESTS=required (below) is what turns THAT case into a failed
# test instead of a silent skip.
- name: Enable a systemd --user session (abctl leg only)
if: matrix.binary == 'abctl'
run: |
sudo loginctl enable-linger "$(whoami)"
rt="/run/user/$(id -u)"
for i in $(seq 1 30); do
[ -S "${rt}/bus" ] && break
sleep 1
done
echo "XDG_RUNTIME_DIR=${rt}" >> "$GITHUB_ENV"
XDG_RUNTIME_DIR="${rt}" systemctl --user show-environment || \
echo "::warning::systemd --user session not reachable after enable-linger; the real-systemd tests will report why"
- name: Test
env:
ABCTL_SYSTEMD_TESTS: ${{ matrix.binary == 'abctl' && 'required' || '' }}
run: go test -v -race -cover ./...
proxy-init-iptables:
name: proxy-init iptables rules
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# This job runs a repo script as root via `sudo -E` and needs no git
# access afterwards, so don't leave the job token in .git/config.
persist-credentials: false
# The harness builds its rules inside `unshare --net`, so it never touches
# the runner's own networking. It needs root for unshare + iptables, the
# dummy module to generate a routable external packet, and both iptables
# backends so the legacy-detection case is exercised rather than skipped.
- name: Install iptables backends
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq iptables iproute2 kmod
sudo modprobe dummy || echo "dummy module unavailable; capture packet may not be generated"
# Gates the interception rules themselves: chain placement and ordering,
# the DNS carve-out, the non-TCP drop, the fail-closed guards, and — for
# transparent inbound — that the ambient DNAT precedes AB_REDIRECT's
# ztunnel-mark RETURN. That ordering decides whether mesh-delivered traffic
# is validated or waved through, and nothing else in CI covers it.
- name: Test enforce-redirect + transparent inbound rules
run: sudo -E deploy/proxy-init/test-enforce-redirect.sh
python-test:
name: Python Tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install pytest==8.* python-keycloak==5.3.1 pyjwt==2.10.1 pyyaml==6.*
- name: Run tests
run: pytest tests/ -v -x --ignore=tests/e2e
# install.sh is a curl|sh entry point, so a regression there is a
# stranger's first experience of Cortex. shellcheck in
# security-scans.yaml catches syntax, not behaviour — the tag parser
# returning the OLDEST release shipped past it.
install-script:
name: install.sh tests
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Run install.sh tests
run: sh scripts/install_test.sh
# `go mod tidy -diff` on every module in the repo. GOWORK=off so
# replace directives resolve as they do in build.yaml and
# release-binaries.yaml.
go-tidy-check:
name: Verify module graph is tidy
runs-on: ubuntu-latest
timeout-minutes: 5
env:
GOWORK: "off"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: core/go.mod
- name: Run go mod tidy -diff in every module
run: |
set -euo pipefail
# Percent-encode %, CR, LF for use in workflow commands
# (both metadata and message halves — CR/LF in the message
# would end the command and let the next line be interpreted
# as a new one).
esc() { printf '%s' "$1" | sed -e 's/%/%25/g' -e 's/\r/%0D/g' -e ':a' -e '$!N' -e 's/\n/%0A/g' -e 'ta'; }
fail=0
found=0
while IFS= read -r -d '' go_mod; do
found=$((found + 1))
mod=$(dirname "$go_mod")
mod_esc=$(esc "$mod")
go_mod_esc=$(esc "$go_mod")
echo "::group::${mod_esc}"
if ! (cd "$mod" && go mod tidy -diff); then
echo "::error file=${go_mod_esc}::go mod tidy would change ${go_mod_esc}; run 'go mod tidy' in ${mod_esc} and commit"
fail=1
fi
echo "::endgroup::"
done < <(find . -name go.mod -print0 | sort -z)
if [ "$found" -eq 0 ]; then
echo "::error::no go.mod found in the repository"
exit 1
fi
exit $fail