Skip to content

Commit acd0b89

Browse files
committed
.github: CI workflow for samples/tasks
Separate workflow from Linux-libretro-common-samples, since the two test suites have different build shapes: * libretro-common/samples/ binaries are self-contained: each Makefile produces a single test binary that needs no arguments and exits on its own. The existing workflow walks every Makefile under that tree with a generic build+run loop. * samples/tasks/ pulls in ~60 source files from across the retroarch tree -- core_info, playlist, msg_hash, libretro-db, the task queue, archivers -- and links the two demos with hand-written stubs for retroarch-core-only symbols. The two binaries also have different runtime shapes (one is a demo that needs a real directory tree, the other a self-contained predicate test), so a generic loop is a poor fit. Triggers paths the existing workflow doesn't cover: * samples/tasks/** (obvious) * tasks/task_decompress.c (the predicate under test in archive_name_safety_test keeps a verbatim copy; if the upstream predicate is edited the copy must follow) * tasks/task_database{,_cue}.c (compiled into database_task) * this workflow file itself Behaviour: * database_task is built (catches compile/link regressions, which is most of what rots between releases), then invoked with no args to verify it prints usage and exits non-zero. The full dbscan loop is NOT exercised in CI: task_push_dbscan ignores the caller's completion callback and delegates to task_push_manual_content_scan, which has no public way to plumb a completion signal back out. The loop can only be terminated externally, which makes it a poor CI fit. An honest note explaining this is in the workflow step's inline comment. * archive_name_safety_test is built and run with a 60s timeout. This is the true regression test -- it enumerates 23 safe and unsafe paths (including ".." traversal, absolute Unix and Windows paths, drive-letter prefixes, and backslash-separated attacks) and fails if archive_name_is_safe() ever regresses. Local dry-run of every step on the current master: [pass] database_task builds and links [pass] database_task no-args exit=1 (expected non-zero) [pass] archive_name_safety_test all 23 cases pass
1 parent 509c0ea commit acd0b89

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: CI Linux samples/tasks
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
paths:
8+
- 'samples/tasks/**'
9+
- 'tasks/task_decompress.c'
10+
- 'tasks/task_database.c'
11+
- 'tasks/task_database_cue.c'
12+
- '.github/workflows/Linux-samples-tasks.yml'
13+
pull_request:
14+
branches:
15+
- master
16+
paths:
17+
- 'samples/tasks/**'
18+
- 'tasks/task_decompress.c'
19+
- 'tasks/task_database.c'
20+
- 'tasks/task_database_cue.c'
21+
- '.github/workflows/Linux-samples-tasks.yml'
22+
workflow_dispatch:
23+
24+
permissions:
25+
contents: read
26+
27+
env:
28+
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
29+
30+
jobs:
31+
samples-tasks:
32+
name: Build and run samples/tasks
33+
runs-on: ubuntu-latest
34+
timeout-minutes: 10
35+
36+
steps:
37+
- name: Install dependencies
38+
run: |
39+
sudo apt-get update -y
40+
sudo apt-get install -y build-essential zlib1g-dev
41+
42+
- name: Checkout
43+
uses: actions/checkout@v3
44+
45+
- name: Build database_task
46+
shell: bash
47+
working-directory: samples/tasks/database
48+
run: |
49+
set -eu
50+
make clean all
51+
test -x database_task
52+
53+
- name: Smoke-test database_task argv parsing
54+
shell: bash
55+
working-directory: samples/tasks/database
56+
run: |
57+
set -u
58+
# database_task with no args should print the usage line and
59+
# exit non-zero. This catches build regressions in the argv
60+
# parsing / main() entry path without depending on the task
61+
# queue actually running to completion -- task_push_dbscan
62+
# delegates to task_push_manual_content_scan which does not
63+
# plumb through the caller's completion callback, so the
64+
# loop can only be terminated externally (by timeout or
65+
# signal). The full loop is exercised in local testing; in
66+
# CI we settle for the argv smoke.
67+
./database_task > /dev/null 2>&1
68+
rc=$?
69+
if [[ $rc -eq 0 ]]; then
70+
echo "::error title=Test failed::database_task with no args exited 0; expected non-zero (usage)"
71+
exit 1
72+
fi
73+
echo "[pass] database_task no-args exit=$rc (expected non-zero)"
74+
75+
- name: Build and run archive_name_safety_test
76+
shell: bash
77+
working-directory: samples/tasks/decompress
78+
run: |
79+
set -eu
80+
make clean all
81+
test -x archive_name_safety_test
82+
# Regression test for the Zip Slip / absolute-path defences
83+
# in tasks/task_decompress.c::archive_name_is_safe(). The
84+
# test keeps a verbatim copy of the predicate and runs it
85+
# against 23 safe and unsafe inputs. If task_decompress.c
86+
# ever amends the predicate, the copy here must follow.
87+
timeout 60 ./archive_name_safety_test
88+
echo "[pass] archive_name_safety_test"

0 commit comments

Comments
 (0)