mirror of
https://github.com/transmission/transmission.git
synced 2026-02-15 07:26:49 +00:00
ci: add run-tests composite action (#8159)
* ci: add run-tests composite action * fixup! ci: add run-tests composite action send sanitizer log messages to stderr otherwise, they will break transmission-show tests * fixup! ci: add run-tests composite action fix windows, alpine breakage * fixup! ci: add run-tests composite action fix: sanitizer logging to stderr * fixup! ci: add run-tests composite action disable asan leak detection on macOS: the feature is unsupported there * fixup! refactor: extract platform detection into its own composite action (#8158) ensure bash is installed on alpine linux
This commit is contained in:
@@ -29,8 +29,9 @@ runs:
|
||||
id: cache-key
|
||||
shell: pwsh
|
||||
run: |
|
||||
$RepoRoot = if (Test-Path (Join-Path . 'src/release/windows/main.ps1')) { Join-Path . 'src' } else { (Get-Item .).FullName }
|
||||
try {
|
||||
$DepsHash = & (Join-Path . src release windows main.ps1) -Mode DepsHash -BuildArch ${{ inputs.arch }} -BuildPart ${{ inputs.type }}
|
||||
$DepsHash = & (Join-Path $RepoRoot release windows main.ps1) -Mode DepsHash -BuildArch ${{ inputs.arch }} -BuildPart ${{ inputs.type }}
|
||||
"hash=${DepsHash}" | Out-File $Env:GITHUB_OUTPUT -Append
|
||||
} catch {
|
||||
Write-Error ("{1}{0}{2}{0}{3}" -f [Environment]::NewLine, $_.ToString(), $_.InvocationInfo.PositionMessage, $_.ScriptStackTrace) -ErrorAction Continue
|
||||
@@ -46,8 +47,9 @@ runs:
|
||||
if: steps.restore-cache.outputs.cache-hit != 'true'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$RepoRoot = if (Test-Path (Join-Path . 'src/release/windows/main.ps1')) { Join-Path . 'src' } else { (Get-Item .).FullName }
|
||||
try {
|
||||
& (Join-Path . src release windows main.ps1) -Mode Build -BuildArch ${{ inputs.arch }} -BuildPart ${{ inputs.type }}
|
||||
& (Join-Path $RepoRoot release windows main.ps1) -Mode Build -BuildArch ${{ inputs.arch }} -BuildPart ${{ inputs.type }}
|
||||
} catch {
|
||||
Write-Error ("{1}{0}{2}{0}{3}" -f [Environment]::NewLine, $_.ToString(), $_.InvocationInfo.PositionMessage, $_.ScriptStackTrace) -ErrorAction Continue
|
||||
exit 1
|
||||
|
||||
157
.github/actions/run-tests/action.yml
vendored
Normal file
157
.github/actions/run-tests/action.yml
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
name: Run tests
|
||||
description: Run ctest with crash-friendly settings and optional fallbacks
|
||||
inputs:
|
||||
setup-env:
|
||||
description: "Call set-test-env before running tests"
|
||||
required: false
|
||||
default: "true"
|
||||
build-dir:
|
||||
description: "CTest build directory"
|
||||
required: false
|
||||
default: "obj"
|
||||
build-config:
|
||||
description: "CTest build configuration"
|
||||
required: false
|
||||
default: ""
|
||||
parallel:
|
||||
description: "Number of parallel jobs (auto if empty)"
|
||||
required: false
|
||||
default: ""
|
||||
timeout:
|
||||
description: "CTest timeout in seconds"
|
||||
required: false
|
||||
default: ""
|
||||
extra-ctest-args:
|
||||
description: "Additional ctest arguments"
|
||||
required: false
|
||||
default: ""
|
||||
enable-sanitizers:
|
||||
description: "Whether sanitizer options are enabled (affects fallback choices)"
|
||||
required: false
|
||||
default: "false"
|
||||
enable-asan:
|
||||
description: "Explicitly enable ASan options"
|
||||
required: false
|
||||
default: ""
|
||||
enable-ubsan:
|
||||
description: "Explicitly enable UBSan options"
|
||||
required: false
|
||||
default: ""
|
||||
enable-lsan:
|
||||
description: "Explicitly enable LSan options"
|
||||
required: false
|
||||
default: ""
|
||||
extra-asan-options:
|
||||
description: "Additional ASan options to append"
|
||||
required: false
|
||||
default: ""
|
||||
extra-ubsan-options:
|
||||
description: "Additional UBSan options to append"
|
||||
required: false
|
||||
default: ""
|
||||
extra-lsan-options:
|
||||
description: "Additional LSan options to append"
|
||||
required: false
|
||||
default: ""
|
||||
use-catchsegv:
|
||||
description: "Use catchsegv on Linux if available"
|
||||
required: false
|
||||
default: "true"
|
||||
enable-macos-crash-reports:
|
||||
description: "Attempt to collect macOS crash reports on failure"
|
||||
required: false
|
||||
default: "true"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set test environment
|
||||
if: ${{ inputs.setup-env == 'true' }}
|
||||
uses: ./.github/actions/set-test-env
|
||||
with:
|
||||
enable-sanitizers: ${{ inputs.enable-sanitizers }}
|
||||
enable-asan: ${{ inputs.enable-asan }}
|
||||
enable-ubsan: ${{ inputs.enable-ubsan }}
|
||||
enable-lsan: ${{ inputs.enable-lsan }}
|
||||
extra-asan-options: ${{ inputs.extra-asan-options }}
|
||||
extra-ubsan-options: ${{ inputs.extra-ubsan-options }}
|
||||
extra-lsan-options: ${{ inputs.extra-lsan-options }}
|
||||
- name: Detect platform
|
||||
id: platform
|
||||
uses: ./.github/actions/detect-platform
|
||||
- name: Run ctest
|
||||
shell: bash
|
||||
env:
|
||||
OS_FAMILY: ${{ steps.platform.outputs.os-family }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
build_dir="${{ inputs.build-dir }}"
|
||||
build_config="${{ inputs.build-config }}"
|
||||
parallel="${{ inputs.parallel }}"
|
||||
timeout="${{ inputs.timeout }}"
|
||||
extra_args="${{ inputs.extra-ctest-args }}"
|
||||
enable_sanitizers="${{ inputs.enable-sanitizers }}"
|
||||
use_catchsegv="${{ inputs.use-catchsegv }}"
|
||||
enable_macos_crash_reports="${{ inputs.enable-macos-crash-reports }}"
|
||||
|
||||
if [[ -z "$parallel" ]]; then
|
||||
if command -v nproc >/dev/null 2>&1; then
|
||||
parallel=$(nproc)
|
||||
elif command -v sysctl >/dev/null 2>&1; then
|
||||
parallel=$(sysctl -n hw.logicalcpu)
|
||||
elif [[ -n "${NUMBER_OF_PROCESSORS:-}" ]]; then
|
||||
parallel="$NUMBER_OF_PROCESSORS"
|
||||
else
|
||||
parallel=1
|
||||
fi
|
||||
fi
|
||||
|
||||
args=("--test-dir" "$build_dir" "-j" "$parallel" "--output-on-failure")
|
||||
if [[ -n "$build_config" ]]; then
|
||||
args+=("--build-config" "$build_config")
|
||||
fi
|
||||
if [[ -n "$timeout" ]]; then
|
||||
args+=("--timeout" "$timeout")
|
||||
fi
|
||||
if [[ -n "$extra_args" ]]; then
|
||||
args+=($extra_args)
|
||||
fi
|
||||
|
||||
crash_marker=""
|
||||
if [[ "${OS_FAMILY:-}" == "macos" && "$enable_macos_crash_reports" == "true" ]]; then
|
||||
crash_marker="$RUNNER_TEMP/ctest-crash-marker"
|
||||
touch "$crash_marker"
|
||||
fi
|
||||
|
||||
run_ctest() {
|
||||
if [[ "${OS_FAMILY:-}" == "linux" && "$enable_sanitizers" != "true" && "$use_catchsegv" == "true" ]] && command -v catchsegv >/dev/null 2>&1; then
|
||||
catchsegv ctest "${args[@]}"
|
||||
else
|
||||
ctest "${args[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
set +e
|
||||
run_ctest
|
||||
status=$?
|
||||
set -e
|
||||
|
||||
if [[ $status -ne 0 && "${OS_FAMILY:-}" == "macos" && "$enable_macos_crash_reports" == "true" ]]; then
|
||||
echo "::group::macOS crash reports"
|
||||
reports_found=0
|
||||
for report_dir in "$HOME/Library/Logs/DiagnosticReports" "/Library/Logs/DiagnosticReports"; do
|
||||
if [[ -d "$report_dir" ]]; then
|
||||
while IFS= read -r report; do
|
||||
reports_found=1
|
||||
echo "--- $report ---"
|
||||
tail -n 200 "$report" || true
|
||||
done < <(find "$report_dir" -maxdepth 1 -type f \( -name "*.crash" -o -name "*.ips" \) -newer "$crash_marker" -print 2>/dev/null || true)
|
||||
fi
|
||||
done
|
||||
if [[ $reports_found -eq 0 ]]; then
|
||||
echo "No new crash reports found after test run."
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
exit $status
|
||||
98
.github/actions/set-test-env/action.yml
vendored
Normal file
98
.github/actions/set-test-env/action.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
name: Set test environment
|
||||
description: Configure environment variables for richer crash diagnostics in CI
|
||||
inputs:
|
||||
enable-sanitizers:
|
||||
description: "Enable sanitizer runtime options"
|
||||
required: false
|
||||
default: "false"
|
||||
enable-asan:
|
||||
description: "Explicitly enable ASan options"
|
||||
required: false
|
||||
default: ""
|
||||
enable-ubsan:
|
||||
description: "Explicitly enable UBSan options"
|
||||
required: false
|
||||
default: ""
|
||||
enable-lsan:
|
||||
description: "Explicitly enable LSan options"
|
||||
required: false
|
||||
default: ""
|
||||
extra-asan-options:
|
||||
description: "Additional ASan options to append"
|
||||
required: false
|
||||
default: ""
|
||||
extra-ubsan-options:
|
||||
description: "Additional UBSan options to append"
|
||||
required: false
|
||||
default: ""
|
||||
extra-lsan-options:
|
||||
description: "Additional LSan options to append"
|
||||
required: false
|
||||
default: ""
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Detect platform
|
||||
id: platform
|
||||
uses: ./.github/actions/detect-platform
|
||||
- name: Configure test environment
|
||||
shell: bash
|
||||
env:
|
||||
OS_FAMILY: ${{ steps.platform.outputs.os-family }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "CTEST_OUTPUT_ON_FAILURE=1" >> "$GITHUB_ENV"
|
||||
echo "QT_QPA_PLATFORM=offscreen" >> "$GITHUB_ENV"
|
||||
|
||||
enable_sanitizers="${{ inputs.enable-sanitizers }}"
|
||||
enable_asan="${{ inputs.enable-asan }}"
|
||||
enable_ubsan="${{ inputs.enable-ubsan }}"
|
||||
enable_lsan="${{ inputs.enable-lsan }}"
|
||||
|
||||
if [[ -z "$enable_asan" && -z "$enable_ubsan" && -z "$enable_lsan" ]]; then
|
||||
enable_asan="$enable_sanitizers"
|
||||
enable_ubsan="$enable_sanitizers"
|
||||
enable_lsan="$enable_sanitizers"
|
||||
fi
|
||||
|
||||
if command -v llvm-symbolizer >/dev/null 2>&1; then
|
||||
echo "ASAN_SYMBOLIZER_PATH=$(command -v llvm-symbolizer)" >> "$GITHUB_ENV"
|
||||
echo "LLVM_SYMBOLIZER_PATH=$(command -v llvm-symbolizer)" >> "$GITHUB_ENV"
|
||||
elif command -v llvm-symbolizer-20 >/dev/null 2>&1; then
|
||||
echo "ASAN_SYMBOLIZER_PATH=$(command -v llvm-symbolizer-20)" >> "$GITHUB_ENV"
|
||||
echo "LLVM_SYMBOLIZER_PATH=$(command -v llvm-symbolizer-20)" >> "$GITHUB_ENV"
|
||||
elif command -v llvm-symbolizer-19 >/dev/null 2>&1; then
|
||||
echo "ASAN_SYMBOLIZER_PATH=$(command -v llvm-symbolizer-19)" >> "$GITHUB_ENV"
|
||||
echo "LLVM_SYMBOLIZER_PATH=$(command -v llvm-symbolizer-19)" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
if [[ "$enable_asan" == "true" ]]; then
|
||||
os_family="${OS_FAMILY:-unknown}"
|
||||
detect_leaks_opt="detect_leaks=1"
|
||||
if [[ "$os_family" == "macos" ]]; then
|
||||
# don't run on unsupported platforms
|
||||
detect_leaks_opt="detect_leaks=0"
|
||||
fi
|
||||
asan_opts="abort_on_error=1:allocator_may_return_null=1:check_initialization_order=1:${detect_leaks_opt}:halt_on_error=1:print_stacktrace=1:strict_string_checks=1:symbolize=1:verbosity=0"
|
||||
if [[ -n "${{ inputs.extra-asan-options }}" ]]; then
|
||||
asan_opts+="${asan_opts:+:}${{ inputs.extra-asan-options }}"
|
||||
fi
|
||||
echo "ASAN_OPTIONS=$asan_opts" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
if [[ "$enable_ubsan" == "true" ]]; then
|
||||
ubsan_opts="halt_on_error=1:print_stacktrace=1:report_error_type=1:symbolize=1"
|
||||
if [[ -n "${{ inputs.extra-ubsan-options }}" ]]; then
|
||||
ubsan_opts+="${ubsan_opts:+:}${{ inputs.extra-ubsan-options }}"
|
||||
fi
|
||||
echo "UBSAN_OPTIONS=$ubsan_opts" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
if [[ "$enable_lsan" == "true" ]]; then
|
||||
lsan_opts="verbosity=0:log_threads=0:print_suppressions=1"
|
||||
if [[ -n "${{ inputs.extra-lsan-options }}" ]]; then
|
||||
lsan_opts+="${lsan_opts:+:}${{ inputs.extra-lsan-options }}"
|
||||
fi
|
||||
echo "LSAN_OPTIONS=$lsan_opts" >> "$GITHUB_ENV"
|
||||
fi
|
||||
70
.github/workflows/actions.yml
vendored
70
.github/workflows/actions.yml
vendored
@@ -166,7 +166,11 @@ jobs:
|
||||
- name: Make
|
||||
run: cmake --build obj --config Debug --target libtransmission-test transmission-show
|
||||
- name: Test with sanitizers
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config Debug --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: Debug
|
||||
enable-sanitizers: true
|
||||
|
||||
sanitizer-tests-macos:
|
||||
runs-on: macos-26
|
||||
@@ -208,7 +212,11 @@ jobs:
|
||||
- name: Make
|
||||
run: cmake --build obj --config Debug --target libtransmission-test transmission-show
|
||||
- name: Test with sanitizers
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config Debug --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: Debug
|
||||
enable-sanitizers: true
|
||||
|
||||
clang-tidy-libtransmission:
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -385,8 +393,10 @@ jobs:
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
env:
|
||||
TMPDIR: /private/tmp
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake -E chdir obj ctest -j $(sysctl -n hw.logicalcpu) --build-config RelWithDebInfo --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo --strip
|
||||
- uses: actions/upload-artifact@v6
|
||||
@@ -412,6 +422,7 @@ jobs:
|
||||
apk update
|
||||
apk add \
|
||||
ca-certificates \
|
||||
bash \
|
||||
clang \
|
||||
cmake \
|
||||
crc32c-dev \
|
||||
@@ -436,12 +447,11 @@ jobs:
|
||||
- name: Get Source
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: src
|
||||
submodules: recursive
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake \
|
||||
-S src \
|
||||
-S . \
|
||||
-B obj \
|
||||
-G Ninja \
|
||||
-DCMAKE_C_COMPILER='clang' \
|
||||
@@ -465,8 +475,10 @@ jobs:
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
env:
|
||||
TMPDIR: /private/tmp
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config RelWithDebInfo --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo --strip
|
||||
- uses: actions/upload-artifact@v6
|
||||
@@ -496,10 +508,9 @@ jobs:
|
||||
- name: Get Source
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: src
|
||||
submodules: recursive
|
||||
- name: Prepare Build Deps
|
||||
uses: ./src/.github/actions/prepare-deps-win32
|
||||
uses: ./.github/actions/prepare-deps-win32
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
type: Deps
|
||||
@@ -507,7 +518,7 @@ jobs:
|
||||
run: |
|
||||
Import-VisualStudioVars -VisualStudioVersion 2022 -Architecture ${{ matrix.arch }}
|
||||
cmake `
|
||||
-S src `
|
||||
-S . `
|
||||
-B obj `
|
||||
-G Ninja `
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
||||
@@ -529,7 +540,11 @@ jobs:
|
||||
cmake --build obj --config RelWithDebInfo
|
||||
- name: Test
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config RelWithDebInfo --output-on-failure --timeout 600
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
timeout: 600
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo
|
||||
- name: Package
|
||||
@@ -620,6 +635,12 @@ jobs:
|
||||
- name: Get Dependencies (Qt)
|
||||
if: ${{ needs.what-to-make.outputs.make-qt == 'true' }}
|
||||
run: brew install --formula qt
|
||||
- name: Get Composite Actions
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github/actions
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Get Source
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
@@ -659,8 +680,10 @@ jobs:
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
env:
|
||||
TMPDIR: /private/tmp
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake -E chdir obj ctest -j $(sysctl -n hw.logicalcpu) --build-config RelWithDebInfo --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo --strip
|
||||
- uses: actions/upload-artifact@v6
|
||||
@@ -726,9 +749,10 @@ jobs:
|
||||
run: cmake --build obj --config RelWithDebInfo
|
||||
- name: Test
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config RelWithDebInfo --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo --strip
|
||||
- uses: actions/upload-artifact@v6
|
||||
@@ -800,9 +824,10 @@ jobs:
|
||||
run: cmake --build obj --config RelWithDebInfo
|
||||
- name: Test
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config RelWithDebInfo --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo --strip
|
||||
- uses: actions/upload-artifact@v6
|
||||
@@ -870,7 +895,10 @@ jobs:
|
||||
if: ${{ needs.what-to-make.outputs.make-tests == 'true' }}
|
||||
env:
|
||||
TMPDIR: /private/tmp
|
||||
run: cmake -E chdir obj ctest -j $(nproc) --build-config RelWithDebInfo --output-on-failure
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
build-dir: obj
|
||||
build-config: RelWithDebInfo
|
||||
- name: Install
|
||||
run: cmake --install obj --config RelWithDebInfo --strip
|
||||
- uses: actions/upload-artifact@v6
|
||||
|
||||
Reference in New Issue
Block a user