Repository navigation
Expand file tree
/
Copy pathTaskfile.dist.yml
More file actions
344 lines (312 loc) · 11.4 KB
/
Copy pathTaskfile.dist.yml
File metadata and controls
344 lines (312 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
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
version: "3"
env:
GOTOOLCHAIN: auto
GOPROXY: https://proxy.golang.org,direct
APP_VERSION:
sh: echo -n "${APP_VERSION:-$(git rev-parse --short HEAD)-dev}"
UID:
sh: '{{if ne OS "windows"}}id -u{{end}}'
GID:
sh: '{{if ne OS "windows"}}id -g{{end}}'
dotenv: [".env"]
includes:
docker: ./scripts/tasks/docker.yml
batocera: ./scripts/tasks/batocera.yml
bazzite: ./scripts/tasks/bazzite.yml
chimeraos: ./scripts/tasks/chimeraos.yml
libreelec: ./scripts/tasks/libreelec.yml
linux: ./scripts/tasks/linux.yml
mac: ./scripts/tasks/mac.yml
mister: ./scripts/tasks/mister.yml
mistex: ./scripts/tasks/mistex.yml
recalbox: ./scripts/tasks/recalbox.yml
replayos: ./scripts/tasks/replayos.yml
retropie: ./scripts/tasks/retropie.yml
steamos: ./scripts/tasks/steamos.yml
windows: ./scripts/tasks/windows.yml
zapos: ./scripts/tasks/zapos.yml
cross-lint: ./scripts/tasks/cross-lint.yml
zigcc: ./scripts/tasks/zigcc.yml
tasks:
build:
vars:
APP_BIN: '{{default "zaparoo" .APP_BIN}}'
BUILD_OS: "{{default OS .BUILD_OS}}"
BUILD_ARCH: "{{default ARCH .BUILD_ARCH}}"
PLATFORM: '{{default (OS | replace "darwin" "mac") .PLATFORM}}'
BUILD_DIR: "_build/{{.PLATFORM}}_{{.BUILD_ARCH}}"
EXTRA_LDFLAGS: "{{.EXTRA_LDFLAGS}}"
EXTRA_TAGS: "{{.EXTRA_TAGS}}"
env:
GO111MODULE: on
CGO_ENABLED: 1
GOARCH: "{{.BUILD_ARCH}}"
GOOS: "{{.BUILD_OS}}"
CGO_LDFLAGS: "{{if not .NO_LIBNFC}}-lnfc -lusb{{end}}"
PLATFORM: "{{.PLATFORM}}"
CC: "{{.CC}}"
CXX: "{{.CXX}}"
cmds:
- task: expr:check-profile
- task: credits:check
- task: app:compress
- >-
go build -trimpath
-ldflags "-X 'github.com/ZaparooProject/zaparoo-core/v2/pkg/config.AppVersion=${APP_VERSION}'
-linkmode external -extldflags
'{{if not .NO_LIBNFC}}${CGO_LDFLAGS}{{end}}
{{if not .NO_STATIC}}-static{{end}}'
-s -w {{.EXTRA_LDFLAGS}}"
-tags "netgo,osusergo,sqlite_omit_load_extension,validator_novalidatefn,expr_static_methods{{if .EXTRA_TAGS}},{{.EXTRA_TAGS}}{{end}}"
-o "{{.BUILD_DIR}}/{{.APP_BIN}}"
"./cmd/${PLATFORM}"
expr:check-profile:
desc: Verify Expr method profile matches dependencies and Core environments
env:
GOOS: '{{OS}}'
GOARCH: '{{ARCH}}'
CGO_ENABLED: 0
cmds:
- go run ./scripts/expr-method-profile
credits:
desc: Regenerate the embedded contributor list and third-party software notices
env:
GOOS: '{{OS}}'
GOARCH: '{{ARCH}}'
CGO_ENABLED: 0
cmds:
- go run ./scripts/credits -check=false
credits:check:
desc: Verify the embedded third-party software notices match the dependencies
env:
GOOS: '{{OS}}'
GOARCH: '{{ARCH}}'
CGO_ENABLED: 0
cmds:
- go run ./scripts/credits
app:compress:
desc: Prepare compressed embedded app assets
env:
GOOS: '{{OS}}'
GOARCH: '{{ARCH}}'
CGO_ENABLED: 0
cmds:
- go run ./scripts/compress-app
clean:
desc: Clean build artifacts (optionally specific platform/arch)
vars:
PLATFORM: '{{default "" .PLATFORM}}'
ARCH: '{{default "" .ARCH}}'
TARGET_DIR: "{{if and .PLATFORM .ARCH}}_build/{{.PLATFORM}}_{{.ARCH}}{{else if .PLATFORM}}_build/{{.PLATFORM}}_*{{else}}_build{{end}}"
cmds:
- '{{if eq OS "windows"}}powershell rm -Recurse -Force{{else}}rm -rf{{end}} {{.TARGET_DIR}}'
hooks:install:
desc: Install local pre-push validation hook
cmds:
- mkdir -p .git/hooks
- |
cat > .git/hooks/pre-push <<'HOOK'
#!/usr/bin/env bash
set -euo pipefail
if [[ -n "$(git status --short)" ]]; then
cat >&2 <<'MSG'
pre-push: working tree has uncommitted changes before validation.
Commit or stash them, then push again.
MSG
git status --short >&2
exit 1
fi
printf 'pre-push: running task lint-fix\n'
task lint-fix
printf 'pre-push: running task test\n'
task test
printf 'pre-push: running task cross-lint:all\n'
task cross-lint:all
if [[ -n "$(git status --short)" ]]; then
cat >&2 <<'MSG'
pre-push: validation changed working tree.
Review changes, commit them, then push again.
MSG
git status --short >&2
exit 1
fi
printf 'pre-push: validation passed\n'
HOOK
- chmod +x .git/hooks/pre-push
- echo "Installed .git/hooks/pre-push"
test:c-sanitizer-canary:
desc: Verify the C compiler flags make undefined behavior fail the job
cmds:
- |
set -eu
: "${CC:?C compiler required}" "${CGO_CFLAGS:?Sanitizer flags required}"
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
$CC $CGO_CFLAGS scripts/testing/c-sanitizer-canary.c -o "$work/probe"
if "$work/probe" >"$work/result" 2>&1; then
echo 'C sanitizer canary unexpectedly succeeded' >&2
exit 1
fi
if ! grep -q 'signed integer overflow' "$work/result"; then
cat "$work/result" >&2
exit 1
fi
echo 'C sanitizer canary correctly rejected signed integer overflow'
test:native-sanitized:
desc: Verify instrumented native archives and exercise hardware-free C APIs
cmds:
- |
set -eu
: "${CC:?C compiler required}" "${CGO_CFLAGS:?Sanitizer flags required}"
: "${CGO_LDFLAGS:?Native archive paths required}"
for archive in /opt/deps/x86_64-linux-gnu/lib/libusb.a /opt/deps/x86_64-linux-gnu/lib/libusb-1.0.a /opt/libnfc/x86_64-linux-gnu/lib/libnfc.a; do
if ! nm -u "$archive" | grep -q '__ubsan_handle_'; then
echo "Native archive lacks UBSan instrumentation: $archive" >&2
exit 1
fi
done
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
$CC $CGO_CFLAGS -I/opt/deps/x86_64-linux-gnu/include -I/opt/deps/x86_64-linux-gnu/include/libusb-1.0 \
scripts/testing/native-library-smoke.c $CGO_LDFLAGS -lpthread -o "$work/smoke"
"$work/smoke"
test:linux-release:
desc: Race-test Core packages reachable from the Linux release entry point
vars:
RELEASE_TAGS: netgo,osusergo,sqlite_omit_load_extension,validator_novalidatefn,expr_static_methods,nopkgconfig
preconditions:
- sh: test '{{OS}}' = linux
msg: Linux release tests must run in a Linux environment.
cmds:
- task: expr:check-profile
# The release image lacks PC/SC development files. Test the shipping
# graph rather than unrelated reader packages excluded by nopkgconfig.
- |
set -eu
deps=$(go list -deps -tags={{.RELEASE_TAGS}} ./cmd/linux)
packages=$(printf '%s\n' "$deps" | grep '^github.com/ZaparooProject/zaparoo-core/v2/')
go test -race -count=1 -tags={{.RELEASE_TAGS}} $packages
test:
desc: Run all tests
vars:
TEST_ARGS: '{{default "./..." .CLI_ARGS}}'
cmds:
- task: expr:check-profile
- task: credits:check
- go test -race -tags=validator_novalidatefn,expr_static_methods {{.TEST_ARGS}}
- |
if [ '{{.TEST_ARGS}}' = './...' ]; then
(cd mister && go test -race ./...)
fi
fuzz:
desc: Run fuzz tests (default 30s per test, use FUZZ_TIME to override)
vars:
FUZZ_TIME: '{{default "30s" .FUZZ_TIME}}'
cmds:
- |
exit_code=0
targets=()
while IFS= read -r pkg; do
if ! listing="$(go test -list '^Fuzz' "./${pkg}")"; then
echo "FAIL: listing fuzz targets in ${pkg}"
exit_code=1
continue
fi
found=0
while IFS= read -r func; do
targets+=("${func} ${pkg}")
found=$((found + 1))
done < <(grep '^Fuzz' <<< "${listing}" || true)
if [ "${found}" -eq 0 ]; then
echo "FAIL: no fuzz targets listed in ${pkg}"
exit_code=1
fi
done < <(grep -rl --include='*_test.go' '^func Fuzz' pkg | xargs -n1 dirname | sort -u)
if [ "${#targets[@]}" -eq 0 ]; then
echo "FAIL: no fuzz targets discovered"
exit 1
fi
for target in "${targets[@]}"; do
func="${target%% *}"
pkg="${target#* }"
echo "=== ${func} (${pkg}) ==="
if go test -run "^$" -fuzz="${func}" -fuzztime={{.FUZZ_TIME}} "./${pkg}"; then
echo "PASS: ${func}"
else
echo "FAIL: ${func} in ${pkg}"
exit_code=1
fi
done
exit $exit_code
lint:
desc: Run golangci-lint
cmds:
- golangci-lint run ./...
- cd mister && golangci-lint run ./...
lint-fix:
desc: Run golangci-lint with auto-fixes
cmds:
- golangci-lint run --fix ./...
- cd mister && golangci-lint run --fix ./...
vulncheck:
desc: Run govulncheck for security vulnerabilities
cmds:
- govulncheck ./...
nilcheck:
desc: Run nilaway for nil-pointer analysis
cmds:
# Run through go vet so each package is analysed in its own process.
# Standalone nilaway loads the whole dependency graph into one process
# and needs well over 10 GB for this repo.
- >-
go vet -p 4 -vettool="$(command -v nilaway)"
-include-pkgs=github.com/ZaparooProject/zaparoo-core ./...
deadlock:
desc: Run tests with go-deadlock to detect lock ordering violations
cmds:
- go test -tags=deadlock,validator_novalidatefn,expr_static_methods -race -count=1 ./...
mutesting:
desc: Run mutation testing on a package
cmds:
- go-mutesting {{.CLI_ARGS}}
# Benchmark workflow:
# 1. task bench-baseline (generates testdata/benchmarks/baseline.txt, commit this)
# 2. make changes
# 3. task bench-compare (compares current vs committed baseline via benchstat)
# Quick runs: task bench (count=3) or task bench-db (database only)
bench:
desc: Run all benchmarks
cmds:
- go test -run='^$' -bench=. -benchmem -count=3 -timeout=30m ./...
bench-db:
desc: Run database benchmarks only
cmds:
- go test -run='^$' -bench=. -benchmem -count=3 -timeout=20m ./pkg/database/...
bench-baseline:
desc: Generate benchmark baseline (commit the output)
cmds:
- bash -o pipefail -c 'go test -run="^$$" -bench=. -benchmem -count=6 -timeout=45m ./... | grep -E "^(Benchmark|goos:|goarch:|pkg:|cpu:)" | tee testdata/benchmarks/baseline.txt'
bench-compare:
desc: Compare current benchmarks against baseline (requires benchstat, install with go install golang.org/x/perf/cmd/benchstat@latest)
vars:
BENCH_PKGS: '{{default "./..." .BENCH_PKGS}}'
BENCH_PATTERN: '{{default "." .BENCH_PATTERN}}'
cmds:
- bash -o pipefail -c 'go test -run="^$$" -bench="{{.BENCH_PATTERN}}" -benchmem -count=6 -timeout=45m {{.BENCH_PKGS}} | grep -E "^(Benchmark|goos:|goarch:|pkg:|cpu:)" > /tmp/zaparoo-bench-current.txt'
- benchstat testdata/benchmarks/baseline.txt /tmp/zaparoo-bench-current.txt
get-logs:
desc: Download and decode logs from Zaparoo API
vars:
ENDPOINT: '{{default "localhost:7497" .CLI_ARGS}}'
UUID:
sh: uuidgen
cmds:
- >-
curl -X POST http://{{.ENDPOINT}}/api/v0.1
-H "Content-Type: application/json"
-d '{
"jsonrpc": "2.0",
"method": "settings.logs.download",
"params": {},
"id": "{{.UUID}}"
}' | jq -r '.result.content' | base64 -d