GitHub CI: check project for warnings with clang/gcc.
[tinc] / .github / workflows / test.yml
1 name: Test
2
3 on:
4   push:
5   pull_request:
6     types:
7       - opened
8       - synchronize
9
10 jobs:
11   static-analysis:
12     runs-on: ubuntu-latest
13     timeout-minutes: 10
14     steps:
15       - name: Checkout code
16         uses: actions/checkout@v2
17
18       - name: Install tools
19         run: |
20           sudo apt-get install -y astyle clang-tidy-$CLANG
21           sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-$CLANG 100
22           curl -OL "https://github.com/koalaman/shellcheck/releases/download/v$SHELLCHECK/shellcheck-v${SHELLCHECK}.linux.x86_64.tar.xz"
23           tar -C ~ --strip-components=1 --wildcards -xf ./shellcheck-*.tar.xz 'shellcheck-*/shellcheck'
24           curl -o ~/shfmt -L "https://github.com/mvdan/sh/releases/download/v$SHFMT/shfmt_v${SHFMT}_linux_amd64"
25           chmod 755 ~/shfmt ~/shellcheck
26           pip3 install --user compiledb
27         env:
28           CLANG: 11
29           SHELLCHECK: 0.7.2
30           SHFMT: 3.3.0
31
32       - name: Install deps
33         run: >
34           sudo apt-get install -y
35           git binutils make autoconf automake diffutils texinfo netcat
36           zlib1g-dev lib{ssl,lzo2,ncurses,readline,vdeplug,miniupnpc,gcrypt}-dev
37
38       - name: Configure and compile
39         run: |
40           autoreconf -fsi
41           ./configure --enable-{uml,vde,miniupnpc}
42           make -j$(nproc)
43           compiledb -n make check
44
45       - name: Check code formatting
46         run: "! astyle -r --options=.astylerc --dry-run --formatted '*.c' '*.h' | grep '^Formatted'"
47         if: always()
48
49       - name: Check scripts formatting
50         run: find -type f -regextype egrep -regex '.+\.(sh|sh\.in|test)$' -exec ~/shfmt -d -i 2 -s '{}' +
51         if: always()
52
53       - name: Run static analysis on scripts
54         run: find -type f -regextype egrep -regex '.+\.sh(\.in)?$' -exec shellcheck -x '{}' +
55         if: always()
56
57       - name: Run static analysis on tests
58         run: find -type f -name '*.test' -execdir shellcheck -x '{}' +
59         if: always()
60
61       - name: Run clang-tidy
62         run: |
63           find src \
64             ! '(' -path src/solaris -prune ')' \
65             ! '(' -path src/mingw   -prune ')' \
66             ! '(' -path src/bsd     -prune ')' \
67             -name '*.c' \
68             -exec clang-tidy --header-filter='.*' '{}' +
69         if: always()
70
71       - name: Check warnings (gcc)
72         run: bash .github/workflows/warn/run.sh
73         env:
74           CC: gcc
75         if: always()
76
77       - name: Check warnings (clang)
78         run: bash .github/workflows/warn/run.sh
79         env:
80           CC: clang
81         if: always()
82
83   sanitizer:
84     runs-on: ubuntu-latest
85     timeout-minutes: 10
86     strategy:
87       fail-fast: false
88       matrix:
89         sanitizer:
90           - address
91           - thread
92           - undefined
93     env:
94       SANITIZER: "${{ matrix.sanitizer }}"
95
96     steps:
97       - name: Checkout code
98         uses: actions/checkout@v2
99         with:
100           fetch-depth: 0
101
102       - name: Install deps
103         shell: bash
104         run: >
105           sudo apt-get install -y
106           git binutils make autoconf automake diffutils texinfo netcat
107           zlib1g-dev lib{ssl,lzo2,ncurses,readline,vdeplug,miniupnpc}-dev
108
109       - name: Configure and compile
110         shell: bash
111         run: bash .github/workflows/sanitizers/build.sh
112         env:
113           CC: clang-12
114
115       - name: Run tests
116         run: bash .github/workflows/sanitizers/run.sh
117
118       - name: Archive test results
119         run: sudo tar -c -z -f test-results.tar.gz test/ sanitizer/
120         if: always()
121
122       - name: Upload test results
123         uses: actions/upload-artifact@v2
124         with:
125           name: tests_sanitizer_${{ matrix.sanitizer }}
126           path: test-results.tar.gz
127         if: always()
128
129   linux:
130     runs-on: ubuntu-latest
131     timeout-minutes: 10
132     strategy:
133       fail-fast: false
134       matrix:
135         os:
136           - alpine:3.13
137           - centos:7 # aka RHEL 7
138           - almalinux:8 # aka RHEL 8
139           - debian:oldstable
140           - debian:stable
141           - debian:testing
142           - debian:unstable
143           - ubuntu:18.04 # previous LTS
144           - ubuntu:20.04 # current LTS
145           - opensuse/leap # aka SLES
146     container:
147       image: ${{ matrix.os }}
148       options: --privileged
149       env:
150         CI: 1
151     steps:
152       - name: Install deps (Alpine)
153         run: >
154           apk add git binutils make autoconf automake gcc linux-headers libtool
155           diffutils texinfo procps openssl-dev zlib-dev lzo-dev ncurses-dev
156           readline-dev musl-dev lz4-dev socat shadow sudo
157         if: startsWith(matrix.os, 'alpine')
158
159       - name: Install deps (Debian and Ubuntu)
160         shell: bash
161         run: |
162           apt-get update
163           apt-get install -y git binutils make autoconf automake gcc diffutils sudo \
164             texinfo netcat procps socat zlib1g-dev lib{ssl,lzo2,lz4,ncurses,readline}-dev
165         env:
166           DEBIAN_FRONTEND: noninteractive
167         if: startsWith(matrix.os, 'debian') || startsWith(matrix.os, 'ubuntu')
168
169       - name: Install deps (RHEL)
170         shell: bash
171         run: |
172           if type dnf 2>/dev/null; then
173             dnf install -y 'dnf-command(config-manager)'
174             dnf config-manager --enable powertools
175           fi
176           yum install -y epel-release
177           yum install -y git binutils make autoconf automake gcc diffutils sudo \
178             texinfo netcat procps socat {lzo,zlib,lz4,ncurses,readline}-devel
179           yum install -y openssl11-devel || yum install -y openssl-devel
180         if: startsWith(matrix.os, 'centos') || startsWith(matrix.os, 'alma')
181
182       - name: Install deps (SUSE)
183         shell: bash
184         run: >
185           zypper install -y tar git binutils make autoconf automake gcc procps sudo
186           makeinfo diffutils gzip socat {openssl,zlib,lzo,liblz4,ncurses,readline}-devel
187         if: startsWith(matrix.os, 'opensuse')
188
189       - name: Checkout code
190         uses: actions/checkout@v2
191         with:
192           fetch-depth: 0
193
194       - name: Assign name for test results artifact
195         run: echo TEST_ARTIFACT="$(echo '${{ matrix.os }}' | sed 's|[:/]|_|g')" >>"$GITHUB_ENV"
196
197       - name: Create a non-privileged user
198         run: |
199           useradd --user-group build
200           chown -R build:build .
201           echo 'build ALL=(ALL) NOPASSWD: ALL' >/etc/sudoers.d/build
202
203       - name: Run tests with default settings
204         run: sudo -u build CI=1 sh .github/workflows/test/run.sh default
205
206       - name: Run tests without legacy protocol
207         run: sudo -u build CI=1 sh .github/workflows/test/run.sh nolegacy
208
209       - name: Upload test results
210         uses: actions/upload-artifact@v2
211         with:
212           name: tests_${{ env.TEST_ARTIFACT }}
213           path: /tmp/tests.*.tar.gz
214         if: always()
215
216   deb-build:
217     if: startsWith(github.ref, 'refs/tags/release-')
218     needs: linux
219
220     strategy:
221       matrix:
222         os: [ubuntu-18.04, ubuntu-20.04]
223
224     runs-on: ${{ matrix.os }}
225     timeout-minutes: 5
226
227     steps:
228       - name: Checkout code
229         uses: actions/checkout@v2
230         with:
231           fetch-depth: 0
232
233       - name: Install build deps
234         run: >
235           sudo apt-get install -y --no-install-{recommends,suggests}
236           devscripts
237           git-buildpackage
238           dh-make
239           texinfo
240           libssl-dev
241           zlib1g-dev
242           liblzo2-dev
243           libncurses-dev
244           libreadline-dev
245           libminiupnpc-dev
246
247       - name: Configure project
248         run: autoreconf -fsi
249
250       - name: Prepare debian directory
251         run: bash .github/workflows/deb/prepare.sh
252         env:
253           JOB_DISTRIBUTION: ${{ matrix.os }}
254
255       - name: Build deb package
256         run: |
257           dpkg-buildpackage -d -us -uc
258           mv ../*.deb .
259
260       - name: Upload packages
261         uses: actions/upload-artifact@v2
262         with:
263           name: deb-${{ matrix.os }}
264           path: "*.deb"
265
266   deb-publish:
267     needs: deb-build
268
269     strategy:
270       matrix:
271         os: [ubuntu-18.04, ubuntu-20.04]
272
273     runs-on: ${{ matrix.os }}
274     timeout-minutes: 5
275
276     steps:
277       - name: Download built packages
278         uses: actions/download-artifact@v2
279         with:
280           name: deb-${{ matrix.os }}
281
282       - name: Install package
283         run: sudo apt-get install -y ./*.deb
284
285       - name: Prepare tinc configs
286         run: |
287           set -eu
288           sudo mkdir -p /etc/tinc/test/hosts
289           sudo tinc -b -n test generate-ed25519-keys
290           echo "Name test" | sudo tee /etc/tinc/test/tinc.conf
291
292       - name: Enable and start tincd
293         run: |
294           sudo systemctl start tinc@test
295           sudo tinc -n test dump reachable nodes
296
297       - name: Publish deb package
298         uses: softprops/action-gh-release@v1
299         with:
300           files: "*.deb"
301         env:
302           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
303
304   macos:
305     runs-on: macos-latest
306     timeout-minutes: 10
307
308     strategy:
309       fail-fast: false
310       matrix:
311         legacy_protocol: ["", --disable-legacy-protocol]
312
313     steps:
314       - name: Checkout code
315         uses: actions/checkout@v2
316         with:
317           fetch-depth: 0
318
319       - name: Install build deps
320         run: |
321           brew install coreutils netcat automake lzo lz4 miniupnpc
322           pip3 install --user compiledb
323
324       - name: Configure and compile
325         run: |
326           export CPPFLAGS="-I/usr/local/include"
327           export CPPFLAGS="$CPPFLAGS -I$(brew --prefix libgcrypt)/include"
328           export CPPFLAGS="$CPPFLAGS -I$(brew --prefix openssl)/include"
329           export CPPFLAGS="$CPPFLAGS -I$(brew --prefix libgcrypt)/include"
330
331           autoreconf -fsi
332           ./configure \
333             --with-openssl="$(brew --prefix openssl)" \
334             --with-miniupnpc="$(brew --prefix miniupnpc)" \
335             --enable-{tunemu,miniupnpc} \
336             ${{ matrix.legacy_protocol }}
337
338           make -j$(sysctl -n hw.ncpu)
339
340       - name: Run tests
341         run: |
342           export PATH="$PATH:$HOME/Library/Python/3.9/bin"
343           compiledb make -j$(sysctl -n hw.ncpu) check VERBOSE=1
344
345       - name: Run clang-tidy
346         run: |
347           export PATH="$PATH:$(brew --prefix llvm)/bin/"
348           find src \
349             ! '(' -path src/solaris -prune ')' \
350             ! '(' -path src/mingw   -prune ')' \
351             ! '(' -path src/linux   -prune ')' \
352             ! -name vde_device.c \
353             -name '*.c' \
354             -exec clang-tidy --header-filter='.*' '{}' +
355         if: ${{ matrix.legacy_protocol == '' }}
356
357       - name: Archive test results
358         run: sudo tar -c -z -f test-results.tar.gz test/
359         if: always()
360
361       - name: Upload test results
362         uses: actions/upload-artifact@v2
363         with:
364           name: tests_${{ runner.os }}_${{ matrix.legacy_protocol }}
365           path: test-results.tar.gz
366         if: always()
367
368   windows:
369     runs-on: windows-latest
370     timeout-minutes: 20
371
372     strategy:
373       fail-fast: false
374       matrix:
375         legacy_protocol: ["", --disable-legacy-protocol]
376
377     steps:
378       - name: Checkout code
379         uses: actions/checkout@v2
380         with:
381           fetch-depth: 0
382
383       - name: Install msys2
384         uses: msys2/setup-msys2@v2
385         with:
386           update: true
387           # https://packages.msys2.org/package/
388           install: >-
389             base-devel
390             mingw-w64-x86_64-gcc
391             mingw-w64-x86_64-openssl
392             mingw-w64-x86_64-zlib
393             mingw-w64-x86_64-lzo2
394             mingw-w64-x86_64-lz4
395             mingw-w64-x86_64-ncurses
396             mingw-w64-x86_64-miniupnpc
397             git
398             netcat
399             procps
400
401       - name: Configure project
402         shell: msys2 {0}
403         run: |
404           autoreconf -fsi
405           ./configure --enable-miniupnpc --disable-readline --with-curses-include=/mingw64/include/ncurses ${{ matrix.legacy_protocol }}
406
407       - name: Compile project
408         shell: msys2 {0}
409         run: make -j$(nproc)
410
411       - name: Run tests
412         shell: msys2 {0}
413         run: make check-recursive VERBOSE=1
414
415       - name: Archive test results
416         shell: msys2 {0}
417         run: tar -c -z -f test-results.tar.gz test/
418         if: always()
419
420       - name: Upload test results
421         uses: actions/upload-artifact@v2
422         with:
423           name: tests_${{ runner.os }}_${{ matrix.legacy_protocol }}
424           path: test-results.tar.gz
425         if: always()