Repository navigation
330 lines (312 loc) · 15.3 KB
/
Copy pathshell-tests.yml
File metadata and controls
330 lines (312 loc) · 15.3 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
name: shell-tests
on:
pull_request:
branches:
- master
# Deliberately no push trigger. Every commit that reaches master was already
# parsed and tested by these same jobs on its pull request, so re-running them
# on the merge commit only re-proves what was just proven.
workflow_dispatch:
jobs:
# Same guard build.yml and gcc-compat.yml carry. These two jobs are cheap, but
# they are the last billed entry point a clone inherits: on a private mirror
# every master sync push and every internal PR runs them on that owner's bill.
# Upstream the first disjunct is true, so the condition is a tautology here.
load-hisilicon-parsing:
name: load_hisilicon os_mem_size derivation
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_load_hisilicon.sh
# load_goke runs under busybox sh and awk on the camera, and its zone
# arithmetic depends on busybox awk reading hex.
- name: Install busybox
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq busybox-static
- run: bash .github/scripts/test_load_goke.sh
- run: bash .github/scripts/test_load_hisilicon_layout.sh
sysupgrade-verify:
name: sysupgrade rootfs verification
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# The parse-check that used to live here now runs for every shipped script
# in the job below, against the busybox ash the device actually uses. This
# step was `sh -n` then `dash -n`, which on ubuntu-latest is the same
# check twice (/bin/sh is dash) and neither is the target shell.
- run: bash .github/scripts/test_sysupgrade.sh
# The copy in git is not the copy that ships: the build strips whole-line
# comments out of it. Run the same suite against that form, so the thing
# cameras actually execute is the thing under test. Without this, the
# stripper could quietly change behaviour and every check above would
# still pass, having tested a file no device ever runs.
- name: Re-run against the stripped form that actually ships
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/overlay/usr/sbin/sysupgrade > /tmp/sysupgrade.stripped
SRC=/tmp/sysupgrade.stripped bash .github/scripts/test_sysupgrade.sh
crashlog-capture:
name: crash log capture
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_crashlog.sh
# S98crashlog ships comment-stripped, like sysupgrade and extutils, and
# runs on the boot after every crash: the stripped form is what decides
# whether the evidence survives.
- name: Re-run against the stripped form that actually ships
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/package/openipc-failsafe/files/S98crashlog > /tmp/S98crashlog.stripped
SRC=/tmp/S98crashlog.stripped bash .github/scripts/test_crashlog.sh
majestic-supervise:
name: majestic restarted after a crash, never in a loop
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_majestic_supervise.sh
- name: Re-run against the comment-stripped form
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/package/majestic/files/S95majestic > /tmp/S95majestic.stripped
SRC=/tmp/S95majestic.stripped bash .github/scripts/test_majestic_supervise.sh
vigil-supervise:
name: vigil restarted after a crash, its arguments and recording path
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_vigil_supervise.sh
- name: Re-run against the comment-stripped form
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/package/vigil/files/S95vigil > /tmp/S95vigil.stripped
SRC=/tmp/S95vigil.stripped bash .github/scripts/test_vigil_supervise.sh
network-failover:
name: cable-primary networking and its carrier watcher
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_network_failover.sh
- name: Re-run against the comment-stripped forms
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/overlay/etc/init.d/S40network > /tmp/S40network.stripped
awk -f general/scripts/strip-shell-comments.awk \
general/overlay/usr/share/udhcpc/default.script > /tmp/default.script.stripped
S40=/tmp/S40network.stripped DS=/tmp/default.script.stripped \
bash .github/scripts/test_network_failover.sh
camera-mac:
name: the MAC the camera gives itself
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_check_mac.sh
# Same reason as sysupgrade above: the copy in git is not the copy that
# ships. extutils is comment-stripped into the image, and check_mac runs
# at S30 on every boot of every camera, so the stripped form is the one
# that has to make the right decision.
- name: Re-run against the stripped form that actually ships
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/overlay/usr/sbin/extutils > /tmp/extutils.stripped
SRC=/tmp/extutils.stripped bash .github/scripts/test_check_mac.sh
init-overlay:
name: init keeps an overlay it cannot mount
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash .github/scripts/test_init_overlay.sh
# /init is comment-stripped into every image and decides, on every boot
# of every camera, whether rootfs_data is erased. The stripped form is
# the one that has to get that right.
- name: Re-run against the stripped form that actually ships
run: |
awk -f general/scripts/strip-shell-comments.awk \
general/overlay/init > /tmp/init.stripped
SRC=/tmp/init.stripped bash .github/scripts/test_init_overlay.sh
# Only sysupgrade was ever parse-checked; every other script in the image --
# the init scripts, /etc/profile, /init on initramfs boards, the vendor load_*
# scripts that insert the SoC drivers -- reached cameras without anything
# confirming it even parses. Nothing else covers them: the overlay and the
# package install steps copy these files in verbatim, so a green build says
# nothing about their syntax.
#
# Checked against busybox ash only, since that is what executes on the device.
# dash would be the wrong bar: the shipped busybox sets ASH_BASH_COMPAT, so
# `function name()` is valid in the field, and four scripts that run on real
# hardware fail under dash. See the header of test_shell_parse.sh.
#
# Deliberately syntax-only. A bashism audit (checkbashisms) over the same set
# is a much larger change -- `local` alone is used throughout -- and is worth
# doing separately rather than smuggling into a coverage PR.
excludes-report:
name: excludes lists report what they no longer prune
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# rootfs_script.sh only reaches its excludes step during a board build,
# and a stale entry there is invisible by construction -- it removes
# nothing and says nothing. This drives the real script against a
# synthetic target instead, so the reporting is covered without paying
# for a build.
- run: bash .github/scripts/test_excludes_report.sh
ca-bundle-lite:
name: lite CA bundle keeps the roots it must
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# A lite bundle that lost GitHub's or Let's Encrypt's root builds green
# and is found only when sysupgrade cannot fetch. This runs the real
# rootfs_script.sh cut against the committed bundle, so a Mozilla refresh
# or a keep-list edit is checked without a build (#2508).
- run: bash .github/scripts/test_ca_bundle_lite.sh
build-request:
name: build request parser refuses what it must
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# build-one.yml feeds an issue body -- text anyone can write -- through
# build_request.sh into a defconfig. This pins that only
# `# BR2_<NAME> is not set` lines get through.
- run: bash .github/scripts/test_build_request.sh
shipped-shell-parse:
name: shipped shell scripts parse
if: >-
github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install busybox
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq busybox-static
- name: Parse every shipped shell script
# STRICT=1 so a busybox that failed to install fails the job instead of
# skipping every check and still reporting green.
env:
STRICT: 1
run: bash .github/scripts/test_shell_parse.sh
# The build strips whole-line comments from all of the above before they
# are flashed. Parsing only the tree copy would leave that transform --
# which rewrites 128 files nobody reads again -- entirely unchecked.
- name: Parse them again as the stripper leaves them
env:
STRICT: 1
run: bash .github/scripts/test_strip_shell_comments.sh
# Advisory until now, like lint.yml's jobs, and #2351 showed what that is
# worth: it merged with a red lint check and broke master. These four are the
# only thing standing between a syntax error in a shipped script and a camera
# that runs it, so being able to merge past them is worse here than there.
#
# One umbrella context, matching build.yml's CI Gate and lint.yml's Lint Gate,
# so branch protection names a stable check and a fifth job added below is
# covered without a settings change.
shell-tests-gate:
name: Shell Tests Gate
needs:
- load-hisilicon-parsing
- sysupgrade-verify
- camera-mac
- init-overlay
- crashlog-capture
- excludes-report
- ca-bundle-lite
- shipped-shell-parse
- build-request
- network-failover
- vigil-supervise
# always() so the gate reports when a needed job fails, but not on a run
# whose jobs the guard above deliberately skipped. Upstream the added
# disjunct is true, so this reduces to always().
if: >-
always() && (github.repository == 'OpenIPC/firmware' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && !github.event.repository.private))
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Require every shell test to succeed
run: |
echo "load-hisilicon=${{ needs.load-hisilicon-parsing.result }} sysupgrade=${{ needs.sysupgrade-verify.result }} camera-mac=${{ needs.camera-mac.result }} init-overlay=${{ needs.init-overlay.result }} crashlog=${{ needs.crashlog-capture.result }} excludes=${{ needs.excludes-report.result }} ca-bundle=${{ needs.ca-bundle-lite.result }} shell-parse=${{ needs.shipped-shell-parse.result }} build-request=${{ needs.build-request.result }} network-failover=${{ needs.network-failover.result }} vigil=${{ needs.vigil-supervise.result }}"
# 'skipped' is not accepted, for the reason given in lint.yml: a
# skipped job would take this context green having checked nothing.
if [ "${{ needs.load-hisilicon-parsing.result }}" != "success" ]; then
echo "::error::load_hisilicon os_mem_size derivation did not succeed"; exit 1
fi
if [ "${{ needs.sysupgrade-verify.result }}" != "success" ]; then
echo "::error::sysupgrade rootfs verification did not succeed"; exit 1
fi
if [ "${{ needs.build-request.result }}" != "success" ]; then
echo "::error::build request parser tests did not succeed"; exit 1
fi
if [ "${{ needs.network-failover.result }}" != "success" ]; then
echo "::error::network failover tests did not succeed"; exit 1
fi
if [ "${{ needs.vigil-supervise.result }}" != "success" ]; then
echo "::error::S95vigil supervisor tests did not succeed"; exit 1
fi
if [ "${{ needs.camera-mac.result }}" != "success" ]; then
echo "::error::the MAC the camera gives itself did not succeed"; exit 1
fi
if [ "${{ needs.init-overlay.result }}" != "success" ]; then
echo "::error::init keeping an overlay it cannot mount did not succeed"; exit 1
fi
if [ "${{ needs.crashlog-capture.result }}" != "success" ]; then
echo "::error::crash log capture did not succeed"; exit 1
fi
if [ "${{ needs.excludes-report.result }}" != "success" ]; then
echo "::error::excludes lists report did not succeed"; exit 1
fi
if [ "${{ needs.ca-bundle-lite.result }}" != "success" ]; then
echo "::error::lite CA bundle check did not succeed"; exit 1
fi
if [ "${{ needs.shipped-shell-parse.result }}" != "success" ]; then
echo "::error::shipped shell scripts parse did not succeed"; exit 1
fi