-
Notifications
You must be signed in to change notification settings - Fork 0
233 lines (230 loc) · 9.93 KB
/
Copy pathbootstrapping_ci.yml
File metadata and controls
233 lines (230 loc) · 9.93 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
name: Bootstrapping CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- 'vlib/v3/**'
- '**.yml'
- '**.md'
- '**.vv'
- '**.out'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
- '!cmd/tools/vup.v'
- '!**/bootstrapping_ci.yml'
pull_request:
paths-ignore:
- 'vlib/v3/**'
- '**.yml'
- '**.md'
- '**.vv'
- '**.out'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
- '!cmd/tools/vup.v'
- '!**/bootstrapping_ci.yml'
concurrency:
group: bootstrapping-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
bootstrap-v:
strategy:
matrix:
os: [ubuntu-latest, macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 20
env:
VFLAGS: -no-parallel
B_LFLAGS: -lm -lpthread
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Build V
run: make -j4
- name: Test bootstrapping (v.c can be compiled and run with -os cross)
run: |
ls -la v vc/v.c
./v -os cross -o vc/v.c cmd/v
# shellcheck disable=SC2086
cc -o v_from_vc vc/v.c $B_LFLAGS
ls -lart v_from_vc
./v_from_vc version
./v_from_vc run examples/hello_world.v
./v_from_vc -o v_from_vc_produced_native_v cmd/v
./v_from_vc_produced_native_v run examples/hello_world.v
### the next make invocation will simulate building V from scratch
make local=1
ls -la v vc/v.c v_from_vc v_from_vc_produced_native_v
./v_from_vc_produced_native_v -os cross -o vc/v.c cmd/v
### do it a second time, just in case:
# shellcheck disable=SC2086
clang -o v_from_vc2 vc/v.c $B_LFLAGS
ls -lart v_from_vc2
./v_from_vc2 version
./v_from_vc2 run examples/hello_world.v
./v_from_vc2 -o v_from_vc_produced_native_v2 cmd/v
./v_from_vc_produced_native_v2 run examples/hello_world.v
make local=1
ls -la v vc/v.c
ls -la v_from_vc v_from_vc_produced_native_v
ls -la v_from_vc2 v_from_vc_produced_native_v2
- name: Ensure V master is available
if: github.ref_name != 'master'
run: git branch master remotes/origin/master
- name: Test `v up`
run: |
tested_sha=$(git rev-parse 'HEAD^{commit}')
if [ "$tested_sha" != "$GITHUB_SHA" ]; then
echo "::error::checked out commit $tested_sha does not match GITHUB_SHA $GITHUB_SHA"
exit 1
fi
# Derive a commit sha from an older successful fast workflow on master that was able to build V.
# The workflow used below is `Path Testing CI` (18477644).
# Fetch several successful runs and pick the first commit that is actually reachable on master.
# Some runs may reference commits from force-pushed branches that are no longer on master.
fetch_page() {
local page="$1"
local body=""
for attempt in 1 2 3; do
body=$(curl -sL --max-time 30 \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/vlang/v/actions/workflows/18477644/runs?branch=master&status=success&event=push&per_page=10&page=$page")
if [ -n "$body" ] && echo "$body" | jq -e '.workflow_runs' >/dev/null 2>&1; then
echo "$body" | jq -r '.workflow_runs[].head_sha'
return 0
fi
echo "::warning::page $page attempt $attempt failed, retrying..." >&2
sleep 5
done
return 1
}
recent_good_commit=""
valid_count=0
for page in 1 2 3; do
commits=$(fetch_page "$page" || true)
commit_count=$(printf '%s\n' "$commits" | grep -c . || true)
echo "page $page: fetched $commit_count commits"
for sha in $commits; do
if git merge-base --is-ancestor "$sha" master 2>/dev/null &&
git merge-base --is-ancestor "$sha" "$tested_sha" 2>/dev/null; then
valid_count=$((valid_count + 1))
echo " valid #$valid_count: $sha"
# Skip the first few valid commits to get an older one for testing upgrades.
if [ "$valid_count" -ge 5 ]; then
recent_good_commit="$sha"
break 2
fi
fi
done
done
if [ -z "$recent_good_commit" ]; then
echo "Path Testing CI lookup yielded only $valid_count valid commits; falling back to git log."
common_ancestor=$(git merge-base master "$tested_sha" || true)
if [ -n "$common_ancestor" ]; then
fallback_start=$(git rev-parse "${common_ancestor}^" 2>/dev/null || true)
if [ -n "$fallback_start" ]; then
recent_good_commit=$(git log "$fallback_start" --first-parent --format=%H --before='14 days ago' -n 1)
fi
fi
fi
if [ -z "$recent_good_commit" ]; then
echo "Could not find a valid recent good commit on master"
exit 1
fi
echo "recent_good_commit=$recent_good_commit"
if [ "$recent_good_commit" = "$tested_sha" ]; then
echo "::error::the v up seed must differ from the tested commit"
exit 1
fi
if ! git merge-base --is-ancestor "$recent_good_commit" "$tested_sha"; then
echo "::error::v up seed $recent_good_commit is not an ancestor of $tested_sha"
exit 1
fi
vup_remote="$RUNNER_TEMP/v-up-tested-$tested_sha.git"
if [ -e "$vup_remote" ]; then
echo "::error::temporary v up remote already exists: $vup_remote"
exit 1
fi
git init --bare "$vup_remote"
GIT_ALLOW_PROTOCOL=file git push "$vup_remote" "$tested_sha:refs/heads/master"
git -C "$vup_remote" symbolic-ref HEAD refs/heads/master
bare_sha=$(git -C "$vup_remote" rev-parse 'HEAD^{commit}')
if [ "$bare_sha" != "$tested_sha" ]; then
echo "::error::temporary v up remote has $bare_sha instead of $tested_sha"
exit 1
fi
# Build oldv at recent_good_commit.
./v run cmd/tools/oldv.v -v "$recent_good_commit"
cd "$HOME/.cache/oldv/v_at_$recent_good_commit"
seed_sha=$(git rev-parse 'HEAD^{commit}')
if [ "$seed_sha" != "$recent_good_commit" ]; then
echo "::error::oldv checkout has $seed_sha instead of $recent_good_commit"
exit 1
fi
if [ ! -f thirdparty/tcc/.git/config ]; then
echo "::error::oldv must have a repository-local tcc dependency before v up"
exit 1
fi
rm -f -- cv
if [ -n "$(git status --porcelain=v1)" ]; then
echo "::error::oldv left unexpected changes in the tested checkout"
git status --short
exit 1
fi
git config --local protocol.file.allow always
git config --local url."https://github.com/vlang/vc".insteadOf https://github.com/vlang/vc
git config --local url."file://$vup_remote".insteadOf https://github.com/vlang/v
git remote add ci-tested-v-up https://github.com/vlang/v
git remote add ci-vc-upstream https://github.com/vlang/vc
resolved_vup_url=$(git remote get-url ci-tested-v-up)
expected_vup_url="file://$vup_remote"
if [ "$resolved_vup_url" != "$expected_vup_url" ]; then
echo "::error::v up URL resolved to $resolved_vup_url instead of $expected_vup_url"
exit 1
fi
resolved_vc_url=$(git remote get-url ci-vc-upstream)
expected_vc_url="https://github.com/vlang/vc"
if [ "$resolved_vc_url" != "$expected_vc_url" ]; then
echo "::error::vc URL resolved to $resolved_vc_url instead of $expected_vc_url"
exit 1
fi
remote_master=$(git ls-remote https://github.com/vlang/v refs/heads/master)
expected_remote_master=$(printf '%s\trefs/heads/master' "$tested_sha")
if [ "$remote_master" != "$expected_remote_master" ]; then
echo "::error::v up remote master is not exactly $tested_sha"
exit 1
fi
# Test updating
./v version
./v -v up
./v version
updated_sha=$(git rev-parse 'HEAD^{commit}')
if [ "$updated_sha" != "$tested_sha" ]; then
echo "::error::v up ended at $updated_sha instead of $tested_sha"
exit 1
fi
configured_file_protocol=$(git config --local --get protocol.file.allow)
configured_vup_url=$(git remote get-url ci-tested-v-up)
configured_vc_url=$(git remote get-url ci-vc-upstream)
configured_instead_of=$(git config --local --get-all url."file://$vup_remote".insteadOf)
configured_vc_instead_of=$(git config --local --get-all url."https://github.com/vlang/vc".insteadOf)
if [ "$configured_file_protocol" != "always" ] ||
[ "$configured_vup_url" != "$expected_vup_url" ] ||
[ "$configured_vc_url" != "$expected_vc_url" ] ||
[ "$configured_instead_of" != "https://github.com/vlang/v" ] ||
[ "$configured_vc_instead_of" != "$expected_vc_url" ]; then
echo "::error::v up changed its repository-local Git routing"
exit 1
fi
if [ -n "$(git status --porcelain=v1)" ]; then
echo "::error::v up left the tested checkout dirty"
git status --short
exit 1
fi
./v -o v2 cmd/v && ./v2 -o v3 cmd/v