|
| 1 | +name: CI Linux libretro-common samples |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: |
| 6 | + - master |
| 7 | + paths: |
| 8 | + - 'libretro-common/**' |
| 9 | + - '.github/workflows/Linux-libretro-common-samples.yml' |
| 10 | + pull_request: |
| 11 | + branches: |
| 12 | + - master |
| 13 | + paths: |
| 14 | + - 'libretro-common/**' |
| 15 | + - '.github/workflows/Linux-libretro-common-samples.yml' |
| 16 | + workflow_dispatch: |
| 17 | + |
| 18 | +permissions: |
| 19 | + contents: read |
| 20 | + |
| 21 | +env: |
| 22 | + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true |
| 23 | + |
| 24 | +jobs: |
| 25 | + samples: |
| 26 | + name: Build and run libretro-common/samples |
| 27 | + runs-on: ubuntu-latest |
| 28 | + timeout-minutes: 15 |
| 29 | + |
| 30 | + steps: |
| 31 | + - name: Install dependencies |
| 32 | + run: | |
| 33 | + sudo apt-get update -y |
| 34 | + sudo apt-get install -y build-essential zlib1g-dev |
| 35 | +
|
| 36 | + - name: Checkout |
| 37 | + uses: actions/checkout@v3 |
| 38 | + |
| 39 | + - name: Build and run samples |
| 40 | + shell: bash |
| 41 | + working-directory: libretro-common/samples |
| 42 | + run: | |
| 43 | + set -u |
| 44 | + set -o pipefail |
| 45 | +
|
| 46 | + # Samples whose binary, when invoked with no arguments, runs a |
| 47 | + # self-contained test and exits 0 on success / non-zero on |
| 48 | + # failure. These are built AND executed. |
| 49 | + declare -a RUN_TARGETS=( |
| 50 | + compat_fnmatch_test |
| 51 | + snprintf |
| 52 | + unbase64_test |
| 53 | + archive_zip_test |
| 54 | + config_file_test |
| 55 | + path_resolve_realpath_test |
| 56 | + nbio_test |
| 57 | + rpng |
| 58 | + ) |
| 59 | +
|
| 60 | + # Per-binary run command (overrides ./<binary> if present). |
| 61 | + # config_file_test has pre-existing sample leaks unrelated to |
| 62 | + # any regression so we disable the ASan leak detector -- if a |
| 63 | + # real leak shows up elsewhere it will be flagged during build |
| 64 | + # of ASan-enabled configurations, not here. |
| 65 | + declare -A RUN_ENV=( |
| 66 | + [config_file_test]="ASAN_OPTIONS=detect_leaks=0" |
| 67 | + ) |
| 68 | +
|
| 69 | + # Samples that are build-only (either they require command-line |
| 70 | + # arguments, open network sockets, need extra fixtures, or are |
| 71 | + # interactive demos). They are compiled to catch build-time |
| 72 | + # regressions but not executed. |
| 73 | + declare -a BUILD_ONLY_DIRS=( |
| 74 | + formats/xml |
| 75 | + streams/rzip |
| 76 | + ) |
| 77 | +
|
| 78 | + # Samples that are currently broken at build time on a stock |
| 79 | + # Ubuntu host and are therefore neither built nor run. The |
| 80 | + # net/ Makefile references symbols (fill_pathname_resolve_relative, |
| 81 | + # cpu_features_get_time_usec) without adding the corresponding |
| 82 | + # source files to its SOURCES list; fixing that is out of |
| 83 | + # scope for this workflow. Remove from this list once the |
| 84 | + # Makefile is corrected. |
| 85 | + declare -a SKIP_DIRS=( |
| 86 | + net |
| 87 | + ) |
| 88 | +
|
| 89 | + is_in() { |
| 90 | + local needle=$1; shift |
| 91 | + local h |
| 92 | + for h in "$@"; do [[ "$h" == "$needle" ]] && return 0; done |
| 93 | + return 1 |
| 94 | + } |
| 95 | +
|
| 96 | + fails=0 |
| 97 | + builds=0 |
| 98 | + runs=0 |
| 99 | +
|
| 100 | + # Collect all Makefile directories (one or two levels deep). |
| 101 | + mapfile -t MKDIRS < <(find . -name Makefile -printf '%h\n' | sort) |
| 102 | +
|
| 103 | + printf '\n==> %d sample directories found\n' "${#MKDIRS[@]}" |
| 104 | + for d in "${MKDIRS[@]}"; do printf ' %s\n' "${d#./}"; done |
| 105 | + printf '\n' |
| 106 | +
|
| 107 | + for d in "${MKDIRS[@]}"; do |
| 108 | + rel=${d#./} |
| 109 | + printf '========================================\n' |
| 110 | + printf '[%s] %s\n' "$(is_in "$rel" "${SKIP_DIRS[@]}" && echo skip || echo build)" "$rel" |
| 111 | + printf '========================================\n' |
| 112 | +
|
| 113 | + if is_in "$rel" "${SKIP_DIRS[@]}"; then |
| 114 | + printf '[skip] %s is on the skip list\n\n' "$rel" |
| 115 | + continue |
| 116 | + fi |
| 117 | +
|
| 118 | + # Build |
| 119 | + if ! ( cd "$d" && make clean all ); then |
| 120 | + printf '\n::error title=Build failed::%s failed to build\n' "$rel" |
| 121 | + fails=$((fails+1)) |
| 122 | + continue |
| 123 | + fi |
| 124 | + builds=$((builds+1)) |
| 125 | +
|
| 126 | + # Skip run for build-only dirs |
| 127 | + if is_in "$rel" "${BUILD_ONLY_DIRS[@]}"; then |
| 128 | + printf '[skip-run] %s (build-only list)\n\n' "$rel" |
| 129 | + continue |
| 130 | + fi |
| 131 | +
|
| 132 | + # Extract targets from Makefile (handles both TARGET := foo |
| 133 | + # and TARGETS = a b c). |
| 134 | + mapfile -t targets < <( |
| 135 | + grep -hE '^(TARGET|TARGETS)[[:space:]]*[:?]?=' "$d/Makefile" \ |
| 136 | + | head -1 \ |
| 137 | + | sed -E 's/^[^=]*=[[:space:]]*//' \ |
| 138 | + | tr -s ' \t' '\n' \ |
| 139 | + | grep -v '^$' |
| 140 | + ) |
| 141 | +
|
| 142 | + for t in "${targets[@]}"; do |
| 143 | + if ! is_in "$t" "${RUN_TARGETS[@]}"; then |
| 144 | + printf '[skip-run] %s/%s (not in run allowlist)\n' "$rel" "$t" |
| 145 | + continue |
| 146 | + fi |
| 147 | +
|
| 148 | + bin="$d/$t" |
| 149 | + if [[ ! -x "$bin" ]]; then |
| 150 | + printf '::error title=Missing binary::%s was in the run allowlist but %s does not exist after build\n' "$t" "$bin" |
| 151 | + fails=$((fails+1)) |
| 152 | + continue |
| 153 | + fi |
| 154 | +
|
| 155 | + extra_env=${RUN_ENV[$t]:-} |
| 156 | +
|
| 157 | + printf '\n[run] %s\n' "$bin" |
| 158 | + if ( cd "$d" && env $extra_env timeout 60 "./$t" ); then |
| 159 | + printf '[pass] %s\n\n' "$t" |
| 160 | + runs=$((runs+1)) |
| 161 | + else |
| 162 | + rc=$? |
| 163 | + printf '\n::error title=Test failed::%s exited with status %d\n' "$t" "$rc" |
| 164 | + fails=$((fails+1)) |
| 165 | + fi |
| 166 | + done |
| 167 | + done |
| 168 | +
|
| 169 | + printf '========================================\n' |
| 170 | + printf 'Summary\n' |
| 171 | + printf '========================================\n' |
| 172 | + printf ' Built: %d\n' "$builds" |
| 173 | + printf ' Ran: %d\n' "$runs" |
| 174 | + printf ' Failed: %d\n' "$fails" |
| 175 | +
|
| 176 | + if [[ $fails -gt 0 ]]; then |
| 177 | + exit 1 |
| 178 | + fi |
0 commit comments