Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
89f2393
ci: consolidate Ubuntu workflows
steadytao Aug 15, 2026
8b818e0
ci: restrict workflow permissions
steadytao Aug 15, 2026
c60276d
ci: bound workflow runtimes
steadytao Aug 15, 2026
bf25c07
ci: pin workflows
steadytao Oct 8, 2026
52cf566
testsuite: stabilise daemon argv rejection
steadytao Oct 8, 2026
1c3bddf
testsuite: stabilise legacy peer symlink times
steadytao Oct 8, 2026
96155ab
testsuite: make timestamp fixtures deterministic
steadytao Oct 8, 2026
172ea5b
testsuite: wait for observable process state
steadytao Oct 8, 2026
9d078e3
testsuite: cover inetd socket detection
steadytao Oct 8, 2026
78421e3
testsuite: cover daemon address families
steadytao Oct 8, 2026
ae0bcba
testsuite: cover daemon connection limits
steadytao Oct 8, 2026
9d893bd
testsuite: refresh coverage matrix
steadytao Oct 8, 2026
9b1a3f2
testsuite: cover ignore-missing-args
steadytao Oct 8, 2026
0a667a7
testsuite: cover old-dirs
steadytao Oct 8, 2026
1cfbbe8
testsuite: cover iconv
steadytao Oct 8, 2026
ac08178
testsuite: cover output and logging controls
steadytao Oct 8, 2026
e74ff0d
testsuite: cover ignore-errors
steadytao Oct 8, 2026
b6e5ccc
testsuite: narrow stderr routing checks
steadytao Oct 8, 2026
5f33a0f
ci: cache prepared virtual machines
steadytao Oct 8, 2026
5715253
testsuite: rework Python test harness
steadytao Oct 9, 2026
1ee9bc7
docs: refresh testsuite documentation
steadytao Oct 9, 2026
f1559c5
ci: bound NetBSD VM host setup
steadytao Oct 9, 2026
9d5432d
ci: bound remaining VM host setup
steadytao Oct 9, 2026
7d97929
testsuite: read xattrs across platforms
steadytao Oct 9, 2026
a5d28c4
testsuite: classify Zstandard thread support
steadytao Oct 9, 2026
7c2a62c
testsuite: support matrix profiles
steadytao Oct 9, 2026
1e341c6
testsuite: classify platform requirements
steadytao Oct 9, 2026
6daf18f
testsuite: retire expected-skip policy
steadytao Oct 9, 2026
6e45b4a
testsuite: profile BSD and Solaris
steadytao Oct 9, 2026
15e7c04
ci: enforce BSD and Solaris profiles
steadytao Oct 9, 2026
eb29317
testsuite: complete capability profiles
steadytao Oct 9, 2026
5c05482
testsuite: support wrapped diagnostic runs
steadytao Oct 9, 2026
10cb7b9
ci: profile diagnostic workflows
steadytao Oct 9, 2026
6e59c3b
ci: fix Valgrind matrix
steadytao Oct 10, 2026
5caf3e8
testsuite: classify files-from race skips
steadytao Oct 10, 2026
b1d9a0a
ci: preserve root Valgrind evidence
steadytao Oct 10, 2026
07c2384
ci: avoid duplicate ASan TCP tests
steadytao Oct 10, 2026
a36ade8
ci: avoid duplicate TCP tests
steadytao Oct 10, 2026
0a8db75
ci: pass Valgrind options safely
steadytao Oct 10, 2026
d534085
testsuite: organise tests and helpers
steadytao Oct 10, 2026
92e4ce2
testsuite: stage harness for user namespace test
steadytao Oct 10, 2026
2b63116
testsuite: split process helpers
steadytao Oct 10, 2026
c070255
testsuite: simplify test layout
steadytao Oct 10, 2026
1e61584
ci: trim workflow commentary
steadytao Oct 10, 2026
0b17f5f
docs: refine wording/layout
steadytao Oct 10, 2026
008898f
testsuite: fix renamed test symlink targets
steadytao Oct 10, 2026
074e67c
testsuite: compose overlapping capabilities
steadytao Oct 10, 2026
58f3e5c
testsuite: move mutation helpers
steadytao Oct 10, 2026
9806803
testsuite: separate daemon configuration
steadytao Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
22 changes: 10 additions & 12 deletions .github/workflows/actionlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

# Static-check the workflow YAML with rhysd/actionlint. Catches missing
# secrets, bad expressions, expression-type errors, unsupported runner
# images, and (via embedded shellcheck) common pitfalls in `run:` scripts.
# Trigger only on changes under .github/workflows/ so the rest of the
# matrix isn't billed when nothing here moves.

on:
push:
branches: [ master ]
Expand All @@ -30,16 +24,20 @@ permissions:
jobs:
actionlint:
runs-on: ubuntu-latest
timeout-minutes: 15
name: actionlint
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: install actionlint
# Pin a version so this job is reproducible; bump deliberately.
# The download script verifies a SHA256 of the release tarball.
run: |
bash <(curl --proto '=https' --tlsv1.2 -fsSL \
https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) \
1.7.12
archive=actionlint_1.7.12_linux_amd64.tar.gz
curl --proto '=https' --tlsv1.2 -fsSLO \
"https://github.com/rhysd/actionlint/releases/download/v1.7.12/$archive"
echo "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 $archive" \
| sha256sum --check --strict
tar -xzf "$archive" actionlint
echo "$PWD" >>"$GITHUB_PATH"
- name: actionlint --version
run: actionlint -version
Expand Down
31 changes: 10 additions & 21 deletions .github/workflows/almalinux-8-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

# Older-LTS coverage on the Fedora/RHEL family to help with backporting
# security fixes. AlmaLinux 8 is the RHEL 8 rebuild and is the oldest
# active LTS in this family (RHEL 8 full support runs to 2029).
# GitHub Actions has no native runner for this family, so the job runs
# inside an almalinux:8 container hosted on ubuntu-latest.

on:
push:
branches: [ master ]
Expand All @@ -24,26 +18,26 @@ on:
schedule:
- cron: '42 8 * * *'

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 45
container:
image: almalinux:8
name: Test rsync on AlmaLinux 8
steps:
- name: install git
# actions/checkout needs git in the container before the checkout step.
run: dnf -y install git
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
- name: prep
# PowerTools is needed for libzstd-devel etc; xxhash and lz4 dev
# headers live in EPEL on RHEL 8. The default python3 on RHEL 8
# is 3.6, which is too old for runtests.py (uses capture_output=
# / text= introduced in 3.7), so install python39 and point
# /usr/bin/python3 at it.
run: |
# RHEL 8's default Python is too old for the test runner
dnf -y install epel-release
dnf config-manager --set-enabled powertools
dnf -y install gcc gcc-c++ make autoconf automake m4 \
Expand All @@ -63,18 +57,13 @@ jobs:
- name: info
run: ./rsync --version
- name: check
# In the container we already run as root, so no sudo. The
# crtimes-not-supported skip matches the other Linux jobs;
# daemon-chroot-acl and proxy-response-line-too-long skip because
# the default (secure) transport opens no listening socket.
run: RSYNC_EXPECT_SKIPPED=@testsuite/skiplist/common.txt,@testsuite/skiplist/linux.txt make check
run: RSYNC_TEST_PROFILES=pipe,non-asan,root,self-peer,linux,no-zstd-threads make check
- name: check (TCP daemon transport)
# Second run exercising the real loopback-TCP daemon path.
run: ./runtests.py --rsync-bin="$PWD/rsync" --use-tcp -j 8
run: RSYNC_TEST_PROFILES=non-asan,root,self-peer,linux,no-zstd-threads ./testsuite/runtests.py --rsync-bin="$PWD/rsync" --use-tcp --daemon-tests-only -j 8
- name: ssl file list
run: ./rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
- name: save artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
retention-days: 45
name: almalinux-8-bin
Expand Down
34 changes: 9 additions & 25 deletions .github/workflows/android-static-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

# Cross-compiles statically-linked rsync binaries with the Android NDK,
# suitable for dropping onto a phone (adb push / Termux) with no shared
# libraries. arm64-v8a covers all modern phones; armeabi-v7a covers older
# 32-bit devices. The binaries are uploaded as workflow artifacts.
#
# These are cross-compiled, so the test suite can't run here; we sanity
# check that each binary is the right architecture, is static, and that
# it executes (`--version`) under qemu-user.

on:
push:
branches: [ master ]
Expand All @@ -28,14 +19,16 @@ on:
- cron: '42 8 * * 1'
workflow_dispatch:

permissions:
contents: read

env:
# Minimum supported API level. 24 (Android 7.0) runs on every modern
# phone while keeping broad reach; bump if you need newer Bionic APIs.
ANDROID_API: 24

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 45
name: ${{ matrix.abi }}
strategy:
fail-fast: false
Expand All @@ -48,9 +41,10 @@ jobs:
triple: armv7a-linux-androideabi
qemu: qemu-arm-static
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false

- name: Install build prerequisites
run: sudo apt-get update && sudo apt-get install -y autoconf automake gawk qemu-user-static
Expand All @@ -65,19 +59,12 @@ jobs:
export AR="$TC/llvm-ar" RANLIB="$TC/llvm-ranlib" STRIP="$TC/llvm-strip"
export CFLAGS="-O2" LDFLAGS="-static"

# Bionic doesn't declare lchmod()/lutimes() until API 36, but the
# symbols link, so configure mis-detects them -- force them off so
# rsync uses its fallbacks. The other cache vars restore values
# that configure can't probe when cross-compiling (Android runs a
# normal Linux kernel, so these match the native Linux result).
# Bionic hides lchmod and lutimes before API 36; cross-builds cannot run probes
export ac_cv_func_lchmod=no ac_cv_func_lutimes=no \
rsync_cv_HAVE_SOCKETPAIR=yes \
rsync_cv_MKNOD_CREATES_FIFOS=yes \
rsync_cv_MKNOD_CREATES_SOCKETS=yes

# Self-contained build: drop optional external libraries so the
# static binary needs nothing at runtime. rsync keeps md5/md4
# checksums and its bundled zlib.
./configure --host=${{ matrix.triple }} --build=x86_64-pc-linux-gnu \
--enable-ipv6 \
--disable-zstd --disable-lz4 --disable-xxhash --disable-openssl --disable-idn \
Expand All @@ -86,8 +73,7 @@ jobs:
--disable-md2man --disable-roll-simd \
--with-included-popt --with-included-zlib

# Generate the awk-built headers serially first so the parallel
# build can't race on proto.h <- daemon-parm.h.
# Generate shared headers before the parallel build
make proto.h
make -j"$(nproc)" rsync
"$STRIP" rsync
Expand All @@ -97,12 +83,10 @@ jobs:
run: |
set -euo pipefail
file rsync
# Gate: must be a statically-linked executable (no interpreter).
file rsync | grep -q "statically linked"
if file rsync | grep -q "dynamically linked"; then
echo "ERROR: binary is not static" >&2; exit 1
fi
# Best-effort: confirm it actually runs under qemu-user.
${{ matrix.qemu }} ./rsync --version | head -3 || \
echo "WARNING: qemu smoke test did not run cleanly (check on a real device)"

Expand All @@ -118,7 +102,7 @@ jobs:
echo "ARTIFACT_NAME=rsync-android-${{ matrix.abi }}" >>"$GITHUB_ENV"

- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
retention-days: 45
name: ${{ env.ARTIFACT_NAME }}
Expand Down
45 changes: 17 additions & 28 deletions .github/workflows/asan-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,50 @@ on:
- '.github/workflows/*.yml'
- '!.github/workflows/asan-build.yml'
schedule:
# Weekly (Mon 09:42 UTC): catch breakage from a moving ubuntu-latest/clang
# toolchain (a new clang can add a UBSan check, or change ASan behaviour)
# that no code push would otherwise trigger. Push/PR already gate every
# code change, so daily would just re-run an unchanged tree.
- cron: '42 9 * * 1'
workflow_dispatch:

permissions:
contents: read

jobs:
asan:
runs-on: ubuntu-latest
timeout-minutes: 45
name: rsync ASan+UBSan (clang)
env:
# rsync intentionally leaks small allocations at process exit, so leak
# detection would be all noise; chase only memory-safety errors.
# Process-exit leaks are intentional; memory errors remain fatal
ASAN_OPTIONS: detect_leaks=0:abort_on_error=1
# UBSan is a gate: -fno-sanitize-recover=undefined (below) aborts on the
# first finding and halt_on_error=1 makes that fatal, so any undefined
# behaviour fails the run. This needs the tree to be UBSan-clean: the
# remaining findings are fixed in code (hashtable/mdfour shifts, xattrs,
# and log.c's file_struct, kept aligned via rounding.h); only byteorder.h's
# intentional unaligned accessors are suppressed, with no_sanitize.
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
steps:
- uses: actions/checkout@v4
- 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 clang acl libacl1-dev attr libattr1-dev liblz4-dev libzstd-dev libxxhash-dev libidn2-dev openssl
echo "/usr/local/bin" >>"$GITHUB_PATH"
- name: configure
# -DNDEBUG builds as a shipped release does (assert() compiled out), so
# AddressSanitizer catches the over-reads/over-writes that an "assert()
# instead of a real bounds check" bug would cause in a production build.
# UBSan rides along on the same build; -fno-sanitize-recover=undefined
# makes any undefined behaviour abort (and thus fail the run) instead of
# merely printing it.
# Exercise release behaviour with assertions disabled
run: |
CC=clang \
CFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer -g -O1 -DNDEBUG" \
LDFLAGS="-fsanitize=address,undefined" \
./configure --with-rrsync --disable-md2man
- name: make
# check-progs builds rsync plus the test helper programs (tls, trimslash,
# t_unsafe, ...) that runtests.py requires; plain "make" builds only rsync
# and runtests aborts on the missing helpers.
run: make check-progs
- name: info
run: ./rsync --version
- name: check (stdio-pipe transport)
# ASan+UBSan-instrumented coverage of the transfer, daemon, sender,
# receiver and metadata paths over the default stdio-pipe transport.
run: ./runtests.py --rsync-bin="$PWD/rsync" -j8
run: RSYNC_TEST_PROFILES=pipe,nonroot,self-peer,linux ./testsuite/runtests.py --rsync-bin="$PWD/rsync" --receipt=test-results/asan-pipe.json -j8
- name: check (TCP daemon transport)
# --use-tcp also exercises the loopback rsyncd listener and the client's
# TCP connection path.
run: ./runtests.py --rsync-bin="$PWD/rsync" --use-tcp -j8
run: RSYNC_TEST_PROFILES=nonroot,self-peer,linux ./testsuite/runtests.py --rsync-bin="$PWD/rsync" --use-tcp --daemon-tests-only --receipt=test-results/asan-tcp.json -j8
- name: upload receipts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
retention-days: 45
name: asan-receipts
path: test-results/*.json
14 changes: 7 additions & 7 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,19 @@ on:
- cron: '42 9 * * 1'
workflow_dispatch:

permissions:
contents: read

jobs:
coverage:
runs-on: ubuntu-latest
timeout-minutes: 45
name: gcov coverage
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
- name: prep
run: |
sudo apt-get update
Expand All @@ -38,11 +43,6 @@ jobs:
run: make
- name: info
run: rsync --version
# Two coverage runs: the default pipe transport, then a second pass over a
# real loopback rsyncd (--use-tcp) which also exercises the require_tcp-only
# tests. gcovr's --print-summary line/branch/decision totals go to the step
# log (and the job summary below), so the numbers are visible in CI.
# `make coverage` exits with the suite's status, so a regression fails CI.
- name: coverage (pipe transport)
run: |
set -o pipefail
Expand All @@ -67,7 +67,7 @@ jobs:
} >> "$GITHUB_STEP_SUMMARY"
- name: upload HTML reports
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
retention-days: 45
name: coverage-html
Expand Down
21 changes: 9 additions & 12 deletions .github/workflows/cygwin-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,19 @@ on:
schedule:
- cron: '42 8 * * *'

permissions:
contents: read

jobs:
test:
runs-on: windows-2022
timeout-minutes: 60
name: Test rsync on Cygwin
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
- name: cygwin
run: |
$setup = Join-Path $Env:RUNNER_TEMP 'setup-x86_64.exe'
Expand Down Expand Up @@ -81,21 +86,13 @@ jobs:
- name: info
run: bash -c '/usr/local/bin/rsync --version'
- name: check
# chown-fake / devices-fake / xattrs / xattrs-hlink now RUN on Cygwin
# (rsyncfns.py drives xattrs via getfattr/setfattr from the `attr`
# package installed above), verified on a real Cygwin host. The real
# chown/devices tests still skip (need root/mknod), as do the
# RESOLVE_BENEATH symlink-race tests. Cygwin runs non-root, so the
# namecvt empty-response regression can run despite its common root skip.
run: bash -c 'RSYNC_EXPECT_SKIPPED=@testsuite/skiplist/common.txt,@testsuite/skiplist/cygwin.txt,-daemon-namecvt-empty-response make check'
run: bash -c 'RSYNC_TEST_PROFILES=pipe,non-asan,nonroot,self-peer,cygwin make check'
- name: check (TCP daemon transport)
# Second run with daemon tests over a real loopback rsyncd; the default
# 'make check' above uses the secure stdio-pipe transport.
run: bash -c './runtests.py --rsync-bin=`pwd`/rsync.exe --use-tcp -j 8'
run: bash -c 'RSYNC_TEST_PROFILES=non-asan,nonroot,self-peer,cygwin ./testsuite/runtests.py --rsync-bin=`pwd`/rsync.exe --use-tcp --daemon-tests-only -j 8'
- name: ssl file list
run: bash -c 'PATH="/usr/local/bin:$PATH" rsync-ssl --no-motd download.samba.org::rsyncftp/ || true'
- name: save artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
retention-days: 45
name: cygwin-bin
Expand Down
Loading
Loading