-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathaction.yml
More file actions
223 lines (216 loc) · 11.4 KB
/
Copy pathaction.yml
File metadata and controls
223 lines (216 loc) · 11.4 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
name: bootstrap-mcpp
description: >
Restore the shared CI cache lineage (mcpp sandbox + xlings + target/) and
bootstrap a released mcpp via xlings. Exports MCPP and XLINGS_BIN.
Extracted so the split CI jobs (build / toolchain legs / e2e shards /
integration) share ONE definition instead of copy-pasting a 40-line
preamble per job. Every job that uses it lands on the same cache keys,
which is what makes splitting cheap: each job restores a warm sandbox
and only pays one incremental `mcpp build`.
inputs:
xlings-version:
description: xlings release to bootstrap from
required: false
# Must equal `pinned::kXlingsVersion` in src/xlings/xlings.cppm — enforced by
# .github/tools/check_version_pins.sh, not by this comment. (The previous
# comment here listed the files to keep in lock-step, and that list was
# already incomplete; that is why the check exists.)
#
# Hard floor: 0.4.69. The index's SPEC-001 short-name migration put two
# packages named `lua` in one repo (`compat:lua` and `mcpplibs.capi:lua`,
# both pulled in transitively by mcpplibs.xpkg). Before 0.4.69
# (openxlings/xlings#381) a repo keyed its table by the bare
# `package.name`, so one of the two was simply unreachable — and which one
# depended on the machine, which is why CI failed on `compat:lua` on
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
default: '2026.8.30.2'
cache-target:
description: also restore/save target/ (build artifacts + BMIs)
required: false
default: 'true'
runs:
using: composite
steps:
# NOTE: the "-ci-" segment keeps this lineage disjoint from release.yml's
# "-release-" caches. A bare "mcpp-sandbox-<os>-" restore prefix used to
# match the release sandbox too, silently swapping in a differently
# populated registry (issue #120).
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.mcpp
# ⚠️⚠️ `runner.arch` IS PART OF EVERY KEY, AND WAS NOT.
#
# These caches hold INSTALLED BINARIES — `~/.xlings`, `~/.mcpp`, and
# `target/`. Keyed on `runner.os` alone, `Linux` names two machines, and
# `ubuntu-24.04-arm` restored what `ubuntu-24.04` had stored. Measured
# the first time this repo scheduled an arm Linux runner:
#
# Cache hit for: xlings-Linux-v2-xl2026.8.17.2-…
# …/bin/xlings: cannot execute binary file: Exec format error
#
# ⭐ AND IT SURVIVED THE FIX ONE LAYER DOWN. Reading `uname -m` to pick
# the right tarball is correct and was not enough: the download never
# happened, because a cache from the other architecture was already
# there. A key that does not name the machine is a key that lets one
# machine answer for another.
#
# The xlings version is part of the LINEAGE, not just the key: mcpp
# vendors xlings into ~/.mcpp/registry/bin once at `self init` and
# never revisits it (acquire_xlings_binary returns early when the file
# exists). With the version only in the key, restore-keys would hand a
# sandbox built by an OLDER xlings to a newer bootstrap, and the
# sandbox — which is what actually resolves dependencies — would
# silently stay behind (observed: a 0.4.30 sandbox surviving under a
# 0.4.69 bootstrap for weeks).
key: mcpp-sandbox-${{ runner.os }}-${{ runner.arch }}-ci-xl${{ inputs.xlings-version }}-${{ hashFiles('mcpp.toml', '.xlings.json') }}
restore-keys: |
mcpp-sandbox-${{ runner.os }}-${{ runner.arch }}-ci-xl${{ inputs.xlings-version }}-
- name: Cache xlings
uses: actions/cache@v4
with:
path: ~/.xlings
key: xlings-${{ runner.os }}-${{ runner.arch }}-v2-xl${{ inputs.xlings-version }}-${{ hashFiles('.xlings.json') }}
restore-keys: |
xlings-${{ runner.os }}-${{ runner.arch }}-v2-xl${{ inputs.xlings-version }}-
- name: Bootstrap mcpp via xlings (unix)
if: runner.os != 'Windows'
shell: bash
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: ${{ inputs.xlings-version }}
run: |
REPO_DIR="$(pwd)"
# Always install the pinned version — the cache may hold an older
# xlings whose sysroot/packages are incompatible.
# ⚠️⚠️ THE ARCHITECTURE IS READ, NOT ASSUMED. This branched on the OS
# alone and named `linux-x86_64` for every non-Darwin host, which is
# invisible until a Linux runner is not x86_64. Measured on
# `ubuntu-24.04-arm`, the first time this repo scheduled one:
#
# .../xlings-2026.8.17.2-linux-x86_64/subos/default/bin/xlings:
# cannot execute binary file: Exec format error
# Process completed with exit code 126
#
# xlings has published `linux-aarch64` all along; nothing here asked
# for it. `ci-aarch64-fresh-install.yml` never hit this because it
# bootstraps through `quick_install.sh`, which does read the arch.
case "$(uname -s)" in
Darwin) tarball="xlings-${XLINGS_VERSION}-macosx-arm64.tar.gz" ;;
*)
case "$(uname -m)" in
aarch64|arm64) xa=aarch64 ;;
*) xa=x86_64 ;;
esac
tarball="xlings-${XLINGS_VERSION}-linux-${xa}.tar.gz" ;;
esac
WORK=$(mktemp -d)
# Retried and verified — see .github/tools/fetch_release.sh. A bare curl
# here was the single largest source of unexplained CI red on this repo
# (`curl: (52) Empty reply from server`).
bash "$REPO_DIR/.github/tools/fetch_release.sh" \
"https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${tarball}" \
"${WORK}/${tarball}"
tar -xzf "${WORK}/${tarball}" -C "${WORK}"
# ⚠️⚠️ THE TWO LINUX TARBALLS DO NOT HAVE THE SAME SHAPE, and this line
# named one of them. Measured on the 2026.8.17.2 assets:
#
# linux-x86_64 → subos/default/bin/xlings (513 entries)
# linux-aarch64 → bin/xlings (494 entries)
#
# so fetching the right architecture — the fix immediately above — got
# as far as `No such file or directory`, exit 127.
#
# ⭐ FOUND RATHER THAN ASSUMED, AND THE SEARCH IS BOUNDED. `-maxdepth 5`
# keeps it from wandering into the payload tree, and an empty result is
# a hard error: a bootstrap that silently continues without xlings fails
# forty lines later on something that reads like a different problem.
#
# ⚠️ CHECKED BEFORE CHANGING THE THREE HOSTS THAT ALREADY WORKED. On
# x86_64 this now resolves `bin/xlings` where the line before named
# `subos/default/bin/xlings` — and those are the same file:
#
# subos/default/bin/xlings -> ../../../bin/xlings (symlink)
# md5 94b8e2f2… for both
#
# A find that quietly moved macOS and Windows onto a different binary
# would have been a worse defect than the one being fixed.
XL_BOOT="$(find "${WORK}/${tarball%.tar.gz}" -maxdepth 5 -type f \
-name xlings -perm -u+x | head -1)"
[ -n "$XL_BOOT" ] || {
echo "::error::no xlings executable inside ${tarball}"
find "${WORK}/${tarball%.tar.gz}" -maxdepth 3 | head -20
exit 1
}
echo "bootstrap xlings: ${XL_BOOT#${WORK}/}"
"$XL_BOOT" self install
export PATH="$HOME/.xlings/subos/default/bin:$PATH"
echo "$HOME/.xlings/subos/default/bin" >> "$GITHUB_PATH"
xlings --version
# xim:mcpp — pinned, NOT bare `xlings install mcpp`. One shared
# implementation for every bootstrap point in the repo; see
# .github/tools/install_pinned_mcpp.sh for why.
MCPP=$(bash "$REPO_DIR/.github/tools/install_pinned_mcpp.sh" "$REPO_DIR")
# The SANDBOX xlings is a separate copy: mcpp vendors it into
# ~/.mcpp/registry/bin at `self init` and never revisits it
# (acquire_xlings_binary returns early when the file exists), while
# ~/.mcpp is restored from cache by prefix. So it can lag the system
# one by a lot, and it — not the system binary — is what resolves
# dependencies. Print both; a mismatch is worth seeing in the log.
echo "system xlings: $(xlings --version 2>/dev/null | head -1)"
if [ -x "$HOME/.mcpp/registry/bin/xlings" ]; then
echo "sandbox xlings: $("$HOME/.mcpp/registry/bin/xlings" --version 2>/dev/null | head -1)"
else
echo "sandbox xlings: (not initialised yet)"
fi
echo "MCPP=$MCPP" >> "$GITHUB_ENV"
echo "XLINGS_BIN=$HOME/.xlings/subos/default/bin/xlings" >> "$GITHUB_ENV"
- name: Bootstrap mcpp via xlings (windows)
if: runner.os == 'Windows'
shell: bash
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: ${{ inputs.xlings-version }}
run: |
REPO_DIR="$(pwd)"
WORK=$(mktemp -d)
zipfile="xlings-${XLINGS_VERSION}-windows-x86_64.zip"
# Same helper as the unix leg. This is the leg that kept failing, and a
# fix applied to only one of them is a fix half the CI does not get.
bash "$REPO_DIR/.github/tools/fetch_release.sh" \
"https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${zipfile}" \
"${WORK}/${zipfile}"
cd "${WORK}"
unzip -q "${zipfile}"
"$WORK/xlings-${XLINGS_VERSION}-windows-x86_64/subos/default/bin/xlings.exe" self install
export PATH="$USERPROFILE/.xlings/subos/default/bin:$PATH"
echo "$USERPROFILE/.xlings/subos/default/bin" >> "$GITHUB_PATH"
xlings.exe --version
# Pinned install — shared implementation, see the unix leg.
MCPP=$(bash "$REPO_DIR/.github/tools/install_pinned_mcpp.sh" "$REPO_DIR")
# See the unix leg: the sandbox keeps its own vendored xlings copy.
echo "system xlings: $(xlings.exe --version 2>/dev/null | head -1)"
if [ -x "$USERPROFILE/.mcpp/registry/bin/xlings.exe" ]; then
echo "sandbox xlings: $("$USERPROFILE/.mcpp/registry/bin/xlings.exe" --version 2>/dev/null | head -1)"
else
echo "sandbox xlings: (not initialised yet)"
fi
echo "MCPP=$MCPP" >> "$GITHUB_ENV"
echo "XLINGS_BIN=$(cygpath -w "$USERPROFILE/.xlings/subos/default/bin/xlings.exe")" >> "$GITHUB_ENV"
# Precise key on src/ + manifest so a no-source-change run lands on a full
# hit; layered restore-keys let partial hits keep BMI/dyndep state for a
# proper incremental build.
- name: Cache target/ (build artifacts + BMIs)
if: inputs.cache-target == 'true'
uses: actions/cache@v4
with:
path: target
# ⚠️ `modules/**` belongs here as much as `src/**` does. mcpp's own
# source lives in both since the subsystem split, and a key that hashed
# only one of them would restore a target/ built from different sources
# and report success — the failure mode a cache key exists to prevent,
# arriving silently.
key: mcpp-target-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('src/**', 'modules/**', 'tests/**', 'mcpp.toml', 'mcpp.lock') }}
restore-keys: |
mcpp-target-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
mcpp-target-${{ runner.os }}-${{ runner.arch }}-