forked from markfasheh/duperemove
-
Notifications
You must be signed in to change notification settings - Fork 1
180 lines (157 loc) · 6.59 KB
/
Copy pathci.yml
File metadata and controls
180 lines (157 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
name: CI
# A PR branch would otherwise match both triggers and run the whole matrix
# twice for one commit: double the CI spend, and double the exposure to a
# wedged runner. Restrict push to the branches that have no PR to cover them --
# in practice just master, for post-merge validation. (This has to be an
# allowlist: GitHub rejects `branches` and `branches-ignore` on the same event,
# and a denylist cannot express "every branch that has an open PR".)
on:
push:
branches:
- master
pull_request:
# Read-only by default; no job here needs to write back to the repo.
permissions:
contents: read
# Every job builds with WERROR=1 so a new compiler warning fails CI rather than
# scrolling past in the log (scripts/verify.sh greps the build output locally,
# but CI never runs it - without this a warning could land unnoticed).
env:
WERROR: 1
# Every job carries a timeout-minutes. GitHub's default is 360, so a hung test
# holds a runner (and blocks the PR) for six hours before anything notices -- a
# TSAN leg once wedged in the integration suite with oans and llvm-symbolizer
# both live, and looked simply "in progress" the whole time. The bounds below
# are ~8x the observed medians (build ~1 min, sanitizers ~1-2.6 min, valgrind
# ~6.6 min): loose enough not to police normal runner variance, tight enough
# that a wedge fails fast and visibly.
jobs:
build-and-test:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
# Both compilers: they disagree on plenty (clang's -Wcast-align fires on
# the container_of idiom, gcc has no -Wgnu-* checks), so building each at
# -O2 catches warnings and codegen the other misses. The sanitizer jobs
# below only cover clang at -O1.
scratch_fs: [btrfs, xfs]
cc: [gcc, clang]
env:
CC: ${{ matrix.cc }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/apt-deps
with:
leg: build
# Guards the long-path invariant (#117): a syscall taking a scanned
# file's path silently ENAMETOOLONGs and drops the file, exit 0.
- name: Lint (long-path invariant)
run: make lint
- name: Build
run: make
- name: Unit tests
run: make test
# Dedupe integration tests need a reflink-capable filesystem, which the
# runner's ext4 root is not. Back a small btrfs/XFS with a loopback image
# and point the suite's scratch dir at it. The XFS leg runs unprivileged,
# so it also proves the unprivileged FS_IOC_GETFSUUID path (Linux 6.4+);
# the harness auto-skips the few btrfs-only (fragmentation) tests on XFS.
- name: Set up a scratch ${{ matrix.scratch_fs }}
run: |
sudo modprobe ${{ matrix.scratch_fs }} || true
IMG="$RUNNER_TEMP/oans-scratch.img"
truncate -s 2G "$IMG"
if [ "${{ matrix.scratch_fs }}" = btrfs ]; then
mkfs.btrfs -q "$IMG"
else
mkfs.xfs -q -m reflink=1 "$IMG"
fi
sudo mkdir -p /mnt/oans-scratch
sudo mount -o loop "$IMG" /mnt/oans-scratch
sudo chmod 1777 /mnt/oans-scratch
- name: Integration tests
run: make integration
env:
DUPEREMOVE_TEST_DIR: /mnt/oans-scratch
# Same build + suites, but under valgrind's memcheck. Kept as its own job so
# the fast legs above still give quick feedback; this one is ~7x slower but
# catches use-after-free / leaks the plain suite reads straight past (it found
# the dbfile recreate-path UAF fixed in #105). One filesystem is enough -
# memory behaviour is fs-independent - so it runs on btrfs only.
valgrind:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/apt-deps
with:
leg: valgrind
- name: Build
run: make
- name: Unit tests under valgrind
run: |
make test # builds ./test (and runs it natively - fast)
valgrind -q --leak-check=full --error-exitcode=42 \
--suppressions=tests/valgrind.supp ./test
- name: Set up a scratch btrfs
run: |
sudo modprobe btrfs || true
IMG="$RUNNER_TEMP/oans-scratch.img"
truncate -s 2G "$IMG"
mkfs.btrfs -q "$IMG"
sudo mkdir -p /mnt/oans-scratch
sudo mount -o loop "$IMG" /mnt/oans-scratch
sudo chmod 1777 /mnt/oans-scratch
- name: Integration tests under valgrind
run: make integration-valgrind
env:
DUPEREMOVE_TEST_DIR: /mnt/oans-scratch
# Clang AddressSanitizer and UndefinedBehaviorSanitizer builds. These run the
# same unit + integration suites but compiled with -fsanitize; the Makefile's
# SANITIZE=... path also disables release hardening and exports the ASAN/UBSAN/
# LSAN run options that make any finding abort the process (so a suite fails on
# it). ASAN and UBSAN are separate legs for a clean per-sanitizer signal.
# Complements valgrind: ASAN's LeakSanitizer and use-after-scope plus UBSAN's
# integer/alignment/UB checks catch classes memcheck doesn't. Like valgrind,
# one filesystem is enough (the checks are fs-independent), so btrfs only.
sanitizers:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
# thread additionally needs src/tsan.h's GLib annotations to say
# anything useful; the Makefile wires those up for SANITIZE=thread.
sanitize: [address, undefined, thread]
env:
CC: clang
SANITIZE: ${{ matrix.sanitize }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/apt-deps
with:
leg: sanitizers
# Newer runners default vm.mmap_rnd_bits to 32, which clang's ASAN shadow
# mapping can't accommodate ("Shadow memory range interleaves..."). 28 is
# the value ASAN expects. Harmless for the UBSAN leg.
- name: Widen ASLR entropy for ASAN
run: sudo sysctl -w vm.mmap_rnd_bits=28
- name: Build (${{ matrix.sanitize }})
run: make
- name: Unit tests (${{ matrix.sanitize }})
run: make test
- name: Set up a scratch btrfs
run: |
sudo modprobe btrfs || true
IMG="$RUNNER_TEMP/oans-scratch.img"
truncate -s 2G "$IMG"
mkfs.btrfs -q "$IMG"
sudo mkdir -p /mnt/oans-scratch
sudo mount -o loop "$IMG" /mnt/oans-scratch
sudo chmod 1777 /mnt/oans-scratch
- name: Integration tests (${{ matrix.sanitize }})
run: make integration
env:
DUPEREMOVE_TEST_DIR: /mnt/oans-scratch