Skip to content

Commit 1d0ad0e

Browse files
authored
ci: add macos-arm64 automation baseline (#91)
1 parent 274abd2 commit 1d0ad0e

3 files changed

Lines changed: 1473 additions & 36 deletions

File tree

.github/workflows/build-and-test.yml

Lines changed: 137 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,31 @@ on:
55
branches: [thirdparty-macos-arm64]
66
pull_request:
77
branches: [thirdparty-macos-arm64]
8-
workflow_dispatch: {}
8+
9+
permissions:
10+
contents: read
11+
12+
env:
13+
CONTRACT_REPOSITORY: vlang/v
14+
CONTRACT_SHA: 7545e515b434cd399333d43659238427d72e22e7
15+
VC_SHA: dfc458a13ba8923ebc249e262c331f8169aa728b
16+
PUBLISH: 'false'
17+
TCCBIN_PUBLISH: 'false'
918

1019
concurrency:
1120
group: build-and-test-macos-arm64-${{ github.ref }}
1221
cancel-in-progress: true
1322

1423
jobs:
1524
build:
25+
if: >-
26+
github.repository == 'vlang/tccbin' &&
27+
(
28+
(github.event_name == 'pull_request' &&
29+
github.base_ref == 'thirdparty-macos-arm64') ||
30+
(github.event_name == 'push' &&
31+
github.ref == 'refs/heads/thirdparty-macos-arm64')
32+
)
1633
runs-on: macos-15
1734
timeout-minutes: 30
1835
steps:
@@ -26,23 +43,59 @@ jobs:
2643
# this branch reuses its own prebuilt libgc.a/libgc.dylib rather
2744
# than compiling thirdparty/libgc/gc.c from source.
2845
- name: checkout v (for thirdparty/libgc and thirdparty/tccbin_tests)
29-
uses: actions/checkout@v4
46+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
3047
with:
3148
repository: vlang/v
32-
ref: c82d3f08271e9324d6fb8de3c251e9c0e1a9154b
33-
sparse-checkout: |
34-
thirdparty/libgc/include
35-
thirdparty/tccbin_tests
36-
vlib/v/compiler_errors_test.v
37-
sparse-checkout-cone-mode: false
49+
ref: ${{ env.CONTRACT_SHA }}
3850
path: work
51+
fetch-depth: 0
52+
persist-credentials: false
53+
54+
- name: checkout immutable VC bootstrap snapshot
55+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
56+
with:
57+
repository: vlang/vc
58+
ref: ${{ env.VC_SHA }}
59+
path: .tccbin-bootstrap-vc
60+
fetch-depth: 0
61+
persist-credentials: false
62+
63+
- name: bootstrap contract-bound validator
64+
shell: bash
65+
run: |
66+
set -euo pipefail
67+
validator_work="$RUNNER_TEMP/tccbin-validator-work"
68+
test ! -e "$validator_work"
69+
git -C work config --local core.autocrlf false
70+
git -C .tccbin-bootstrap-vc config --local core.autocrlf false
71+
work/thirdparty/tccbin_automation/bootstrap/bootstrap.sh \
72+
"$GITHUB_WORKSPACE/work" "$CONTRACT_REPOSITORY" "$CONTRACT_SHA" \
73+
"$GITHUB_WORKSPACE/.tccbin-bootstrap-vc" "$validator_work"
74+
{
75+
echo "TCCBIN_VALIDATOR_CLI=$validator_work/tccbin-automation"
76+
echo "TCCBIN_VALIDATOR_CONTRACT_ROOT=$validator_work/contract-source"
77+
} >> "$GITHUB_ENV"
3978
4079
# this branch, checked out where build.sh expects to find itself
4180
# (work/thirdparty/tcc), matching a normal local checkout layout.
4281
- name: checkout this branch
43-
uses: actions/checkout@v4
82+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
4483
with:
84+
ref: ${{ github.sha }}
4585
path: work/thirdparty/tcc
86+
fetch-depth: 0
87+
persist-credentials: false
88+
89+
- name: validate baseline manifest and immutable contract binding
90+
shell: bash
91+
run: |
92+
set -euo pipefail
93+
git -C work/thirdparty/tcc config --local core.autocrlf false
94+
bash work/thirdparty/tcc/automation/probes/baseline-contract.sh \
95+
"$TCCBIN_VALIDATOR_CLI" "$TCCBIN_VALIDATOR_CONTRACT_ROOT" \
96+
"$GITHUB_WORKSPACE/work/thirdparty/tcc" macos-arm64 \
97+
thirdparty-macos-arm64 "$CONTRACT_SHA" "$GITHUB_SHA" \
98+
"$GITHUB_WORKSPACE/.tccbin-bootstrap-vc"
4699
47100
# This branch DISTRIBUTES the checked-in tcc.exe/libgc.a/libgc.dylib
48101
# directly - that's what V's own builder and anyone else using this
@@ -195,40 +248,88 @@ jobs:
195248
if [ "$code" -eq 0 ]; then
196249
echo "::error::Static libgc.a linking now succeeds on macOS arm64 - this lane's special-casing should be removed and folded back into a single blocking lane, this workaround is no longer needed."
197250
exit 1
251+
elif [ "$code" -ne 1 ]; then
252+
echo "::error::Static libgc.a XFAIL returned exit $code; expected TCC compile-error exit 1 exactly."
253+
exit 1
198254
fi
199255
256+
set +e
257+
direct_err_gc_alloc=$(thirdparty/tcc/tcc.exe thirdparty/tccbin_tests/shared/gc_alloc.c \
258+
-DGC_BUILTIN_ATOMIC=1 \
259+
-DGC_THREADS=1 \
260+
-DMPROTECT_VDB=1 \
261+
-I thirdparty/libgc/include \
262+
"$PWD/thirdparty/tcc/lib/libgc.a" \
263+
-ldl -lpthread \
264+
-o /tmp/gc_alloc_arm64_xfail_probe 2>&1)
265+
direct_code_gc_alloc=$?
266+
direct_err_hello=$(thirdparty/tcc/tcc.exe thirdparty/tccbin_tests/shared/hello.c \
267+
-DGC_BUILTIN_ATOMIC=1 \
268+
-DGC_THREADS=1 \
269+
-DMPROTECT_VDB=1 \
270+
-I thirdparty/libgc/include \
271+
"$PWD/thirdparty/tcc/lib/libgc.a" \
272+
-ldl -lpthread \
273+
-o /tmp/hello_arm64_xfail_probe 2>&1)
274+
direct_code_hello=$?
275+
set -e
276+
277+
is_known_gc_init() {
278+
# TCC's compile-error exit is exactly 1. Every nonempty stderr
279+
# line must be one complete unresolved GC_* diagnostic; require
280+
# GC_init specifically so an unrelated missing symbol cannot
281+
# masquerade as the known archive-parsing limitation.
282+
if [ "$2" -ne 1 ]; then
283+
return 1
284+
fi
285+
stderr_lines=$(printf '%s\n' "$1" | sed '/^$/d')
286+
[ -n "$stderr_lines" ] || return 1
287+
unexpected=$(printf '%s\n' "$stderr_lines" | grep -Ev "^tcc: error: unresolved reference to '_?GC_[A-Za-z0-9_]+'$" || true)
288+
[ -z "$unexpected" ] || return 1
289+
printf '%s\n' "$stderr_lines" | grep -E "^tcc: error: unresolved reference to '_?GC_init'$" >/dev/null
290+
}
291+
292+
pass_count=$(printf '%s\n' "$output" | grep -Ec '^PASS ' || true)
293+
fail_count=$(printf '%s\n' "$output" | grep -Ec '^FAIL ' || true)
294+
final_summary=$(printf '%s\n' "$output" | sed '/^$/d' | tail -n 1)
200295
case "$output" in
201-
*"PASS crash"*"FAIL gc_alloc (compile error)"*"FAIL hello (compile error)"*)
202-
echo "known XFAIL: static libgc.a still can't link gc_alloc/hello, as expected - not blocking CI"
296+
*"PASS crash"*"FAIL gc_alloc (compile error:"*"FAIL hello (compile error:"*)
297+
if [ "$pass_count" -ne 1 ] || [ "$fail_count" -ne 2 ] || [ "$final_summary" != '1 passed, 2 failed' ]; then
298+
echo "::error::Static libgc.a summary counts/final line differ from the exact known XFAIL (PASS=1, FAIL=2, final='1 passed, 2 failed')."
299+
exit 1
300+
fi
301+
if is_known_gc_init "$direct_err_gc_alloc" "$direct_code_gc_alloc" && is_known_gc_init "$direct_err_hello" "$direct_code_hello"; then
302+
echo "known XFAIL: static libgc.a still can't link gc_alloc/hello (unresolved GC_init, the known tcc archive-parsing bug), as expected - not blocking CI"
303+
else
304+
echo "::error::libgc.a lane failed with the known summary shape, but at least one of gc_alloc.c/hello.c's direct compile errors does NOT mention an unresolved GC_init reference (or exited abnormally) - this looks like a different, unexpected regression:"
305+
echo "gc_alloc.c: exit=$direct_code_gc_alloc: $direct_err_gc_alloc"
306+
echo "hello.c: exit=$direct_code_hello: $direct_err_hello"
307+
exit 1
308+
fi
203309
;;
204310
*)
205311
echo "::error::Static libgc.a lane failed, but NOT with the known/expected signature (PASS crash, FAIL gc_alloc/hello with compile error) - this looks like a different, unexpected problem and should not be silently treated as the known XFAIL."
206312
exit 1
207313
;;
208314
esac
209315
210-
# actions/upload-artifact doesn't preserve executable bits on raw
211-
# files (tcc.exe would come back chmod 644 after download), and
212-
# hand-listing individual paths already missed lib/libtcc1.a -
213-
# which tcc.exe needs at link time just as much as libgc. Archive
214-
# the whole rebuilt thirdparty/tcc output instead: tar preserves
215-
# modes, and keeping the thirdparty/tcc/ prefix inside the
216-
# archive means extracting it anywhere reproduces the exact
217-
# relative layout tcc.exe's own baked-in library path expects
218-
# (see the comment on the "run shared conformance tests" step
219-
# above) - a raw multi-path upload-artifact list would instead
220-
# flatten that prefix away.
221-
- name: package built tcc for upload
222-
# Run even after an earlier failure, so a maintainer debugging
223-
# a red run still gets a downloadable build to reproduce
224-
# against instead of just a log transcript.
225-
if: ${{ !cancelled() }}
226-
working-directory: work
227-
run: tar --exclude=.git -czf tccbin-macos-arm64-current.tar.gz thirdparty/tcc
228-
229-
- name: upload built binaries
230-
if: ${{ !cancelled() }}
231-
uses: actions/upload-artifact@v4
232-
with:
233-
name: tccbin-macos-arm64-current
234-
path: work/tccbin-macos-arm64-current.tar.gz
316+
tccbin-branch-gate:
317+
name: tccbin-branch-gate
318+
if: >-
319+
always() &&
320+
github.repository == 'vlang/tccbin' &&
321+
(
322+
(github.event_name == 'pull_request' &&
323+
github.base_ref == 'thirdparty-macos-arm64') ||
324+
(github.event_name == 'push' &&
325+
github.ref == 'refs/heads/thirdparty-macos-arm64')
326+
)
327+
needs: [build]
328+
runs-on: ubuntu-latest
329+
timeout-minutes: 5
330+
steps:
331+
- name: require successful baseline validation
332+
shell: bash
333+
env:
334+
BUILD_RESULT: ${{ needs.build.result }}
335+
run: test "$BUILD_RESULT" = success

0 commit comments

Comments
 (0)