-
Notifications
You must be signed in to change notification settings - Fork 3
407 lines (363 loc) · 14.6 KB
/
Copy pathcondukt.yml
File metadata and controls
407 lines (363 loc) · 14.6 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
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
name: Condukt
on:
pull_request:
push:
permissions:
contents: read
jobs:
compile:
name: Compile without warnings
runs-on: ubuntu-latest
env:
MIX_ENV: test
# Compile native modules as plain stubs in the broad Elixir jobs.
# The tagged NIF tests are excluded from the default suite, and
# loading these shared libraries on Linux runners can segfault BEAM
# during process teardown even when the tagged tests do not run.
# Native coverage lives in dedicated jobs below.
CONDUKT_BASHKIT_DISABLE: "1"
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Install BEAM tooling with mise
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db
with:
cache: true
# Only what this job builds with. mise.toml also pins deployment
# tooling for the chart, and installing all of it here means a broken
# download for helm or kubectl fails the library's build, which is
# exactly how this job went red.
install_args: "erlang elixir rust"
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Install Linux native dependencies
run: |
sudo apt-get update
sudo apt-get install -y libcap-ng-dev
- name: Fetch dependencies
run: mix deps.get
- name: Compile dependencies
run: mix deps.compile
- name: Compile without warnings
run: mix compile --warnings-as-errors
- name: Upload Mix dependencies
uses: actions/upload-artifact@v4
with:
name: mix-test-build
path: |
deps
_build/test
if-no-files-found: error
test:
name: Run tests
runs-on: ubuntu-latest
needs: compile
env:
MIX_ENV: test
CONDUKT_BASHKIT_DISABLE: "1"
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Install BEAM tooling with mise
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db
with:
cache: true
# Only what this job builds with. mise.toml also pins deployment
# tooling for the chart, and installing all of it here means a broken
# download for helm or kubectl fails the library's build, which is
# exactly how this job went red.
install_args: "erlang elixir rust"
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Install Linux native dependencies
run: |
sudo apt-get update
sudo apt-get install -y libcap-ng-dev gdb
- name: Enable core dumps
run: |
sudo mkdir -p /tmp/cores
sudo chmod 1777 /tmp/cores
sudo sh -c 'echo "/tmp/cores/core.%e.%p" > /proc/sys/kernel/core_pattern'
echo "core_pattern: $(cat /proc/sys/kernel/core_pattern)"
- name: Download Mix dependencies
uses: actions/download-artifact@v4
with:
name: mix-test-build
path: .
- name: Fetch dependencies
run: mix deps.get
- name: Prepare NIF and patch out exit-time destructors
run: |
# The downloaded mix-test-build artifact has the NIF .so but
# also needs `mix compile` to restore file modes on test
# fixtures (artifacts strip exec bits) and re-run the rustler
# copy step. `mix compile` itself segfaults at exit on Linux
# because loading the project modules triggers the NIF
# on_load -> dlopen -> _dl_fini -> aws-lc-sys destructor
# crash. The .so is fully built / copied before BEAM tears
# down, so we tolerate exit 139 here, then patch
# DT_FINI_ARRAYSZ to 0. The follow-up `mix test --no-compile`
# runs against the patched .so and exits cleanly. See
# scripts/patch_nif_fini_array.py for the full diagnosis.
set +e
mix compile
status=$?
set -e
if [ "$status" -ne 0 ] && [ "$status" -ne 139 ]; then
echo "mix compile failed with unexpected status $status"
exit "$status"
fi
so=_build/test/lib/condukt/priv/native/condukt_microsandbox.so
if [ -e "$so" ]; then
python3 scripts/patch_nif_fini_array.py "$so"
else
echo "warning: $so not found after mix compile"
fi
- name: Run test suite
run: |
ulimit -c unlimited
set +e
mix test --no-compile
status=$?
set -e
if [ "$status" -ne 0 ]; then
echo "::group::NIF binary inspection"
so=_build/test/lib/condukt/priv/native/condukt_microsandbox.so
if [ -e "$so" ]; then
echo "--- file $so ---"
file "$so" || true
echo "--- readelf -d $so ---"
readelf -d "$so" || true
echo "--- nodelete present? ---"
readelf -d "$so" | grep -i nodelete || echo "NODELETE NOT SET"
echo "--- section headers (fini/init) ---"
readelf -SW "$so" | grep -E "fini|init" || true
echo "--- .fini_array contents ---"
readelf --hex-dump=.fini_array "$so" || true
echo "--- .init_array contents ---"
readelf --hex-dump=.init_array "$so" || true
echo "--- objdump -R (first 80 lines) ---"
objdump -R "$so" 2>&1 | head -80 || true
echo "--- readelf -rW (first 80 lines) ---"
readelf -rW "$so" 2>&1 | head -80 || true
echo "--- .fini_array destructor symbols (via addr2line + nm) ---"
# Pull the three function offsets from the dynamic relocations
# targeting .fini_array, then resolve each back to source.
# Use `objdump -R` format which is unambiguous:
# <off> R_X86_64_RELATIVE *ABS*+<addr>
fini_addr_hex=$(readelf -SW "$so" | awk '/\.fini_array/ {print $4; exit}')
fini_size_hex=$(readelf -SW "$so" | awk '/\.fini_array/ {print $6; exit}')
if [ -n "$fini_addr_hex" ] && [ -n "$fini_size_hex" ]; then
fini_start=$((16#$fini_addr_hex))
fini_end=$((fini_start + 16#$fini_size_hex))
objdump -R "$so" 2>/dev/null | awk '$2 ~ /RELATIVE/ {print $1, $3}' | \
while read -r off_hex addend_field; do
off_dec=$((16#$off_hex)) 2>/dev/null || continue
if [ "$off_dec" -ge "$fini_start" ] && [ "$off_dec" -lt "$fini_end" ]; then
# addend_field looks like "*ABS*+0xABCDEF"
target=${addend_field##*+}
echo "--- destructor target $target (.fini_array slot 0x$off_hex) ---"
echo "addr2line:"
addr2line -e "$so" -f -C "$target" 2>&1 || true
echo "nearest symbol:"
nm -C --defined-only --numeric-sort "$so" 2>/dev/null | \
awk -v tdec=$((16#${target#0x})) '
{
ad = strtonum("0x" $1)
if (ad <= tdec) { prev_sym = $0 }
if (ad > tdec) { print prev_sym; exit }
}
' || true
echo "disassembly:"
stop=$(printf '0x%x' $((16#${target#0x} + 0x80)))
objdump -d --start-address="$target" --stop-address="$stop" "$so" 2>&1 | tail -30 || true
fi
done
fi
echo "--- Relocations targeting .fini_array address range ---"
# readelf -SW columns when section name is short: [N] NAME TYPE ADDR OFF SIZE ES FLG ...
fini_addr_hex=$(readelf -SW "$so" | awk '/\.fini_array/ {print $4; exit}')
fini_size_hex=$(readelf -SW "$so" | awk '/\.fini_array/ {print $6; exit}')
if [ -n "$fini_addr_hex" ] && [ -n "$fini_size_hex" ]; then
fini_start=$((16#$fini_addr_hex))
fini_end=$((fini_start + 16#$fini_size_hex))
printf 'fini_array vaddr=0x%s size=0x%s (dec %d..%d)\n' "$fini_addr_hex" "$fini_size_hex" "$fini_start" "$fini_end"
readelf -rW "$so" | while IFS= read -r line; do
off_hex=$(printf '%s' "$line" | awk '$1 ~ /^[0-9a-f]+$/ {print $1; exit}')
[ -z "$off_hex" ] && continue
off_dec=$((16#$off_hex)) 2>/dev/null || continue
if [ "$off_dec" -ge "$fini_start" ] && [ "$off_dec" -lt "$fini_end" ]; then
echo "$line"
fi
done
fi
else
echo "$so not found"
fi
echo "::endgroup::"
echo "::group::Core dumps"
ls -la /tmp/cores/ || true
for core in /tmp/cores/core.*; do
[ -e "$core" ] || continue
echo "--- $core ---"
file_out=$(file "$core")
echo "$file_out"
exe=$(printf '%s' "$file_out" | sed -n "s/.*execfn: '\\([^']*\\)'.*/\\1/p")
if [ -z "$exe" ]; then
exe=$(ls /home/runner/.local/share/mise/installs/erlang/*/erts-*/bin/beam.smp 2>/dev/null | head -1)
fi
echo "executable: $exe"
gdb -batch \
-ex 'set pagination off' \
-ex 'info sharedlibrary' \
-ex 'info proc mappings' \
-ex 'thread apply all bt full' \
-ex 'info registers' \
-ex 'x/16gx $rsp' \
-ex 'x/16i $rip-32' \
-ex 'x/16i $rip' \
-ex quit \
"$exe" "$core" 2>&1 || true
done
echo "::endgroup::"
fi
exit $status
- name: Upload core dumps and NIF binary
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-core-dumps
path: |
/tmp/cores/
_build/test/lib/condukt/priv/native/condukt_microsandbox.so
if-no-files-found: ignore
retention-days: 7
format:
name: Check formatting
runs-on: ubuntu-latest
needs: compile
env:
MIX_ENV: test
CONDUKT_BASHKIT_DISABLE: "1"
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Install BEAM tooling with mise
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db
with:
cache: true
# Only what this job builds with. mise.toml also pins deployment
# tooling for the chart, and installing all of it here means a broken
# download for helm or kubectl fails the library's build, which is
# exactly how this job went red.
install_args: "erlang elixir rust"
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Download Mix dependencies
uses: actions/download-artifact@v4
with:
name: mix-test-build
path: .
- name: Fetch dependencies
run: mix deps.get
- name: Check formatting
run: mix format --check-formatted
credo:
name: Run Credo
runs-on: ubuntu-latest
needs: compile
env:
MIX_ENV: test
CONDUKT_BASHKIT_DISABLE: "1"
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Install BEAM tooling with mise
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db
with:
cache: true
# Only what this job builds with. mise.toml also pins deployment
# tooling for the chart, and installing all of it here means a broken
# download for helm or kubectl fails the library's build, which is
# exactly how this job went red.
install_args: "erlang elixir rust"
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Download Mix dependencies
uses: actions/download-artifact@v4
with:
name: mix-test-build
path: .
- name: Fetch dependencies
run: mix deps.get
- name: Run Credo
run: mix credo --strict
k8s_sandbox:
name: K8s sandbox smoke tests (kind)
runs-on: ubuntu-latest
needs: compile
env:
MIX_ENV: test
CONDUKT_BASHKIT_DISABLE: "1"
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Install BEAM tooling with mise
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db
with:
cache: true
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Install Linux native dependencies
run: |
sudo apt-get update
sudo apt-get install -y libcap-ng-dev
- name: Download Mix dependencies
uses: actions/download-artifact@v4
with:
name: mix-test-build
path: .
- name: Fetch dependencies
run: mix deps.get
- name: Create kind cluster
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc
with:
cluster_name: condukt-smoke
wait: 60s
- name: Wait for kind control plane
run: |
kubectl wait --for=condition=Ready node --all --timeout=120s
kubectl -n kube-system rollout status deployment/coredns --timeout=120s
- name: Pre-pull pod image into the kind cluster
run: |
docker pull debian:bookworm-slim
kind load docker-image debian:bookworm-slim --name condukt-smoke
- name: Prepare NIF and patch out exit-time destructors
run: |
# Same dance as the test job. See scripts/patch_nif_fini_array.py.
set +e
mix compile
status=$?
set -e
if [ "$status" -ne 0 ] && [ "$status" -ne 139 ]; then
echo "mix compile failed with unexpected status $status"
exit "$status"
fi
so=_build/test/lib/condukt/priv/native/condukt_microsandbox.so
if [ -e "$so" ]; then
python3 scripts/patch_nif_fini_array.py "$so"
else
echo "warning: $so not found after mix compile"
fi
- name: Run K8s sandbox smoke tests
run: mix test --no-compile --only k8s_sandbox test/condukt/sandbox/kubernetes_test.exs