Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 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
2441d06
testsuite: sync with master
steadytao Nov 7, 2026
58b910e
testsuite: classify transfer failures
steadytao Nov 8, 2026
16adebf
testsuite: remove exit-status wrapper
steadytao Nov 8, 2026
b81dd42
testsuite: remove capability override
steadytao Nov 8, 2026
6a2bf3a
testsuite: fix long socket paths
steadytao Nov 8, 2026
660ecdb
testsuite: share native checks
steadytao Nov 8, 2026
49ab6a6
ci: use shared checks on Ubuntu
steadytao Nov 8, 2026
9fc6d1c
testsuite: fix permission fixtures
steadytao Nov 8, 2026
9cd28aa
ci: group workflows
steadytao Nov 8, 2026
e228b96
ci: flatten platform checks
steadytao Nov 8, 2026
a172d08
testsuite: check privilege profiles
steadytao Nov 8, 2026
7505a0e
testsuite: make search-only checks portable
steadytao Nov 8, 2026
74ef215
ci: run non-root checks
steadytao Nov 8, 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
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/rsync-web/ export-ignore

# old_versions/ holds static binaries of historical rsync releases, used by the
# version-mixing test suite (.github/workflows/ubuntu-version-mix.yml) to run
# version-mixing test suite (.github/workflows/versions.yml) to run
# the current code against a real old peer over the daemon / remote-shell.
# Mark the binaries as binary so the `text=auto eol=lf` rule above can't try to
# normalise line endings and corrupt them; export-ignore keeps them out of the
Expand Down
75 changes: 75 additions & 0 deletions .github/actions/cygwin/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Cygwin
description: Build and test rsync on Cygwin

runs:
using: composite
steps:
- name: Install Cygwin
shell: pwsh
run: |
$setup = Join-Path $Env:RUNNER_TEMP 'setup-x86_64.exe'
$sums = Join-Path $Env:RUNNER_TEMP 'cygwin-sha512.sum'
$packages = 'make,autoconf,automake,gcc-core,attr,libattr-devel,python39,python39-pip,libzstd-devel,liblz4-devel,libssl-devel,libxxhash0,libxxhash-devel,libidn2-devel'

Invoke-WebRequest https://cygwin.com/setup-x86_64.exe -OutFile $setup
Invoke-WebRequest https://cygwin.com/sha512.sum -OutFile $sums

$sum = Select-String -LiteralPath $sums -Pattern '^[0-9a-fA-F]{128}\s+\*?setup-x86_64\.exe$' | Select-Object -First 1
if (-not $sum) {
throw 'setup-x86_64.exe is missing from Cygwin sha512.sum'
}
$expected = ($sum.Line -split '\s+')[0]
$actual = (Get-FileHash -LiteralPath $setup -Algorithm SHA512).Hash
if ($actual -ine $expected) {
throw 'Cygwin setup SHA-512 mismatch'
}

$arguments = @(
'--quiet-mode',
'--no-desktop',
'--no-startmenu',
'--no-shortcuts',
'--root', 'C:\tools\cygwin',
'--local-package-dir', (Join-Path $Env:RUNNER_TEMP 'cygwin-packages'),
'--site', 'https://mirrors.kernel.org/sourceware/cygwin/',
'--packages', $packages
)
$install = Start-Process -FilePath $setup -ArgumentList $arguments -Wait -PassThru -NoNewWindow
if ($install.ExitCode -ne 0) {
exit $install.ExitCode
}

$bash = 'C:\tools\cygwin\bin\bash.exe'
if (-not (Test-Path -LiteralPath $bash)) {
throw 'Cygwin setup did not install bash'
}
& $bash -lc 'command -v make aclocal gcc python3 >/dev/null'
if ($LASTEXITCODE -ne 0) {
throw 'Cygwin setup did not install all required build tools'
}

echo 'C:/tools/cygwin/bin' >>$Env:GITHUB_PATH
- name: Install CommonMark
shell: pwsh
run: bash -c 'python3 -mpip install --user commonmark'
- name: Configure
shell: pwsh
run: bash -c './configure --with-rrsync'
- name: Build
shell: pwsh
run: bash -c 'make'
- name: Install
shell: pwsh
run: bash -c 'make install'
- name: Version
shell: pwsh
run: bash -c '/usr/local/bin/rsync --version'
- name: Tests (pipe)
shell: pwsh
run: bash -c 'RSYNC_TEST_PROFILES=pipe,non-asan,nonroot,self-peer,cygwin make check'
- name: Tests (TCP)
shell: pwsh
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: TLS listing (optional)
shell: pwsh
run: bash -c 'PATH="/usr/local/bin:$PATH" rsync-ssl --no-motd download.samba.org::rsyncftp/ || true'
38 changes: 38 additions & 0 deletions .github/actions/macos/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: macOS
description: Build and test rsync on macOS

runs:
using: composite
steps:
- name: Install dependencies
shell: bash -e {0}
run: |
brew install automake openssl xxhash zstd lz4 libidn2
pip3 install --user --break-system-packages commonmark
echo "$(brew --prefix)/bin" >>"$GITHUB_PATH"
- name: Configure
shell: bash -e {0}
run: |
BREW_PREFIX=$(brew --prefix)
OPENSSL_PREFIX=$(brew --prefix openssl)
CPPFLAGS="-I${BREW_PREFIX}/include -I${OPENSSL_PREFIX}/include" \
LDFLAGS="-L${BREW_PREFIX}/lib -L${OPENSSL_PREFIX}/lib" \
./configure --with-rrsync
- name: Build
shell: bash -e {0}
run: make
- name: Install
shell: bash -e {0}
run: sudo make install
- name: Version
shell: bash -e {0}
run: rsync --version
- name: Tests (pipe)
shell: bash -e {0}
run: sudo RSYNC_TEST_PROFILES=pipe,non-asan,root,self-peer,macos make check
- name: Tests (TCP)
shell: bash -e {0}
run: sudo RSYNC_TEST_PROFILES=non-asan,root,self-peer,macos ./testsuite/runtests.py --rsync-bin="$PWD/rsync" --use-tcp --daemon-tests-only -j 8
- name: TLS listing (optional)
shell: bash -e {0}
run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
40 changes: 40 additions & 0 deletions .github/check-results.jq
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
def require($condition; $message):
if $condition then . else error($message) end;

($ENV | with_entries(select(.key | startswith("CI_EXPECT_")))
| with_entries(.key |= (ltrimstr("CI_EXPECT_") | ascii_downcase))) as $expected
| ($ENV.CI_DIRECT_JOBS // "[]" | fromjson) as $direct
| require(type == "object" and keys == ($expected | keys); "Missing or unexpected job families")
| require(all($expected[]; . == "true" or . == "false") and any($expected[]; . == "true"); "No valid job selection")
| require(($direct | type) == "array" and all($direct[]; type == "string"); "Invalid direct jobs")
| require(($direct - ($expected | keys) | length) == 0; "Unknown direct job")
| to_entries[]
| .key as $family | .value as $group
| if $expected[$family] == "false" then
require($group.result == "skipped"; $family + ": expected skipped")
| "\($family): skipped"
else
require($group.result == "success"; $family + ": not successful")
| if ($direct | index($family)) != null then
require(($group.outputs | has("jobs") | not); $family + ": direct job exported workflow results")
| "\($family): \($group.result)"
else
($group.outputs.jobs | fromjson) as $jobs
| ($group.outputs.inputs // "{}" | fromjson) as $inputs
| $group.outputs.advisory as $advisory
| require(($jobs | type) == "object" and ($jobs | length) > 0; $family + ": missing job results")
| require(($inputs | type) == "object" and all($inputs[]; type == "boolean"); $family + ": invalid job selections")
| require((($inputs | keys) - ($jobs | keys) | length) == 0; $family + ": unknown job selection")
| require($advisory == null or ($jobs | has($advisory)); $family + ": unknown advisory job")
| require(any($jobs | keys[]; $inputs[.] != false); $family + ": no jobs selected")
| $jobs | to_entries[]
| .key as $job | .value.result as $result
| if $inputs[$job] == false then
require($result == "skipped"; $family + "/" + $job + ": expected skipped")
else
require($result == "success" or ($result == "failure" and $job == $advisory);
$family + "/" + $job + ": " + ($result // "missing result"))
end
| "\($family)/\($job): \($result)"
end
end
84 changes: 84 additions & 0 deletions .github/test-results.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/sh
set -eu

root=$(CDPATH= cd "$(dirname "$0")/.." && pwd -P)
if ! test -f "$root/.github/check-results.jq"; then
echo 'CI result checker is missing' >&2
exit 1
fi
scratch=$(mktemp -d)
trap 'rm -f "$scratch/out" "$scratch/err"; rmdir "$scratch"' 0
export CI_EXPECT_LINUX=true CI_EXPECT_DIAGNOSTICS=true CI_EXPECT_BSD=false CI_EXPECT_CYGWIN=true
export CI_DIRECT_JOBS='["cygwin"]'
data=$(jq -n '{
linux: {result: "success", outputs: {
jobs: ({ubuntu: {result: "success"}, almalinux: {result: "skipped"}} | tojson),
inputs: ({ubuntu: true, almalinux: false} | tojson)}},
diagnostics: {result: "success", outputs: {
jobs: ({scan_pinned: {result: "success"}, scan_latest: {result: "failure"}, asan: {result: "skipped"}} | tojson),
inputs: ({scan_pinned: true, scan_latest: true, asan: false} | tojson), advisory: "scan_latest"}},
bsd: {result: "skipped", outputs: {}},
cygwin: {result: "success", outputs: {}}
}')

check() {
expected=$1
edit=$2
payload=$(printf '%s\n' "$data" | jq "$edit")
actual=fail
if printf '%s\n' "$payload" | jq -er -f "$root/.github/check-results.jq" >"$scratch/out" 2>"$scratch/err"; then
actual=pass
fi
if test "$actual" != "$expected"; then
echo "Unexpected CI result for: $edit" >&2
cat "$scratch/out" "$scratch/err" >&2
exit 1
fi
}

check pass '.'
check pass '.diagnostics.outputs.jobs |= (fromjson | .scan_latest.result = "success" | tojson)'
CI_EXPECT_BSD=true check pass '.bsd = {result: "success", outputs: {jobs: ({test: {result: "success"}} | tojson)}}'
check fail 'del(.linux)'
check fail '.extra = {result: "success", outputs: {}}'
check fail '.linux.result = "failure"'
check fail '.linux.result = "cancelled"'
check fail '.linux.result = "skipped"'
check fail '.bsd.result = "success"'
check fail '.linux.outputs.jobs = "{}"'
check fail '.linux.outputs.jobs = "[]"'
check fail '.linux.outputs.jobs = "not JSON"'
check fail 'del(.linux.outputs.jobs)'
check fail '.linux.outputs.inputs = "[]"'
check fail '.linux.outputs.inputs = "not JSON"'
check fail 'del(.linux.outputs.inputs)'
check fail '.linux.outputs.inputs |= (fromjson | .unknown = true | tojson)'
check fail '.linux.outputs.inputs |= (fromjson | .ubuntu = "true" | tojson)'
check fail '.linux.outputs.inputs |= (fromjson | .ubuntu = false | tojson)'
check fail '.linux.outputs.inputs |= (fromjson | .ubuntu = false | tojson) | .linux.outputs.jobs |= (fromjson | .ubuntu.result = "skipped" | tojson)'
check fail '.linux.outputs.jobs |= (fromjson | .ubuntu.result = "failure" | tojson)'
check fail '.linux.outputs.jobs |= (fromjson | .ubuntu.result = "skipped" | tojson)'
check fail '.linux.outputs.jobs |= (fromjson | .ubuntu.result = "cancelled" | tojson)'
check fail '.linux.outputs.jobs |= (fromjson | del(.ubuntu) | tojson)'
check fail '.linux.outputs.jobs |= (fromjson | .almalinux.result = "success" | tojson)'
check fail '.diagnostics.outputs.advisory = ""'
check fail '.diagnostics.outputs.advisory = "unknown"'
check fail '.diagnostics.outputs.jobs |= (fromjson | .scan_latest.result = "cancelled" | tojson)'
check fail '.diagnostics.outputs.jobs |= (fromjson | .scan_latest.result = "skipped" | tojson)'
check fail '.bsd.result = "cancelled"'
check fail '.cygwin.result = "failure"'
check fail '.cygwin.result = "cancelled"'
check fail '.cygwin.result = "skipped"'
check fail '.cygwin.outputs.jobs = ({test: {result: "success"}} | tojson)'
CI_EXPECT_CYGWIN=false check pass '.cygwin.result = "skipped"'
CI_EXPECT_CYGWIN=false check fail '.'
check fail 'del(.linux.outputs.jobs) | .linux.outputs.kind = "direct"'
CI_DIRECT_JOBS='[]' check fail '.'
CI_DIRECT_JOBS='["missing"]' check fail '.'
CI_DIRECT_JOBS='["cygwin","linux"]' check fail '.'
CI_DIRECT_JOBS='{}' check fail '.'
CI_DIRECT_JOBS='not JSON' check fail '.'
check fail '{}'
export CI_EXPECT_LINUX=false CI_EXPECT_DIAGNOSTICS=false CI_EXPECT_CYGWIN=false
check fail 'with_entries(.value = {result: "skipped", outputs: {}})'
echo 'CI result checks passed'
47 changes: 0 additions & 47 deletions .github/workflows/actionlint.yml

This file was deleted.

88 changes: 0 additions & 88 deletions .github/workflows/almalinux-8-build.yml

This file was deleted.

Loading
Loading