Files
rsync/.github/workflows/valgrind.yml
2026-10-10 19:25:04 +10:00

123 lines
4.3 KiB
YAML

name: Valgrind memcheck
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
on:
push:
branches: [ master ]
paths-ignore:
- '.github/workflows/*.yml'
- '!.github/workflows/valgrind.yml'
pull_request:
types: [opened, synchronize, reopened]
paths-ignore:
- '.github/workflows/*.yml'
- '!.github/workflows/valgrind.yml'
schedule:
- cron: '17 4 * * *'
workflow_dispatch:
permissions:
contents: read
jobs:
memcheck:
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- privilege: user
transport: pipe
profiles: pipe,non-asan,nonroot,self-peer,linux,valgrind
- privilege: user
transport: tcp
profiles: non-asan,nonroot,self-peer,linux,valgrind
- privilege: root
transport: pipe
profiles: pipe,non-asan,root,self-peer,linux,valgrind
- privilege: root
transport: tcp
profiles: non-asan,root,self-peer,linux,valgrind
name: memcheck (${{ matrix.privilege }}, ${{ matrix.transport }})
env:
VALGRIND_SCRATCH: /tmp/rsync-valgrind-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.privilege }}-${{ matrix.transport }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
- name: prep
run: |
sudo apt-get update
sudo apt-get install -y valgrind acl libacl1-dev attr libattr1-dev \
liblz4-dev libzstd-dev libxxhash-dev libidn2-dev python3-cmarkgfm openssl
echo "/usr/local/bin" >>"$GITHUB_PATH"
- name: configure
run: ./configure --with-rrsync --enable-debug
- name: make
run: make check-progs # builds rsync + the test helper programs runtests.py needs
- name: info
run: ./rsync --version
# Gate memory errors rather than intentional process-exit leaks
- name: run testsuite under valgrind
run: |
mkdir -p test-results/valgrind-logs
SUDO=()
[ "${{ matrix.privilege }}" = root ] && SUDO=(sudo -E)
TCP=()
[ "${{ matrix.transport }}" = tcp ] && TCP=(--use-tcp --daemon-tests-only)
"${SUDO[@]}" env RSYNC_TEST_PROFILES=${{ matrix.profiles }} scratchbase="$VALGRIND_SCRATCH" \
./testsuite/runtests.py --valgrind \
--valgrind-opts="--leak-check=no --error-exitcode=0" \
"${TCP[@]}" -j2 --timeout=600 --preserve-scratch \
--receipt=test-results/valgrind-${{ matrix.privilege }}-${{ matrix.transport }}.json
- name: scan for unsuppressed valgrind errors
if: always()
run: |
log_dir="$VALGRIND_SCRATCH/testtmp/valgrind-logs"
if [ -d "$log_dir" ]; then
sudo chown -R "$USER" "$log_dir"
fi
shopt -s nullglob
logs=("$log_dir"/valgrind.*.log)
if [ "${#logs[@]}" -eq 0 ]; then
echo "::error::no valgrind logs were produced -- the suite did not run"
exit 1
fi
evidence_dir=test-results/valgrind-logs
mkdir -p "$evidence_dir"
cp -- "${logs[@]}" "$evidence_dir/"
echo "scanned ${#logs[@]} valgrind log(s)"
bad=()
for f in "${logs[@]}"; do
grep -qE 'ERROR SUMMARY: [1-9][0-9]* errors' "$f" && bad+=("$f")
done
if [ "${#bad[@]}" -ne 0 ]; then
echo "::error::valgrind reported unsuppressed errors in ${#bad[@]} run(s)"
for f in "${bad[@]}"; do
echo "===== $f ====="
sed 's/==[0-9]*== //' "$f" | grep -A18 \
-E 'depends on uninitialised|points to uninitialised|Invalid (read|write|free)|lost in loss record|Mismatched free' \
| head -60
done
exit 1
fi
echo "valgrind clean: no unsuppressed errors"
- name: upload valgrind evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: valgrind-logs-${{ matrix.privilege }}-${{ matrix.transport }}
path: |
test-results/valgrind-logs/*.log
test-results/*.json
if-no-files-found: ignore
retention-days: 45