Some cleanups in GitHub Actions CI
[tinc] / .github / workflows / test.yml
index 214dd1d..1b819a6 100644 (file)
@@ -1,4 +1,4 @@
-name: Build and test
+name: Test
 
 on:
   push:
@@ -8,119 +8,181 @@ on:
       - synchronize
 
 jobs:
-  test-linux:
+  code-style:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v2
+
+      - name: Install code formatting tools
+        run: |
+          sudo apt-get install -y astyle
+          curl -OL 'https://github.com/koalaman/shellcheck/releases/download/v0.7.2/shellcheck-v0.7.2.linux.x86_64.tar.xz'
+          tar -C ~ --strip-components=1 --wildcards -xf ./shellcheck-*.tar.xz 'shellcheck-*/shellcheck'
+          curl -o ~/shfmt -L 'https://github.com/mvdan/sh/releases/download/v3.3.0/shfmt_v3.3.0_linux_amd64'
+          chmod 755 ~/shfmt ~/shellcheck
+
+      - name: Check code formatting
+        run: "! astyle -r --options=.astylerc --dry-run --formatted '*.c' '*.h' | grep '^Formatted'"
+
+      - name: Check scripts formatting
+        run: find -type f -regextype egrep -regex '.+\.(sh|sh\.in|test)$' -exec ~/shfmt -d -i 2 -s '{}' +
+        if: always()
+
+      - name: Run static analysis on scripts
+        run: find -type f -regextype egrep -regex '.+\.sh(\.in)?$' -exec shellcheck -x '{}' +
+        if: always()
+
+      - name: Prepare test library and run static analysis on tests
+        run: |
+          autoreconf -fsi
+          ./configure --disable-{lzo,readline,zlib,curses}
+          find -type f -name '*.test' -execdir shellcheck -x '{}' +
+        if: always()
+
+  sanitizer:
+    runs-on: ubuntu-latest
     strategy:
-      matrix:
-        os: [ubuntu-18.04, ubuntu-20.04]
-        compiler: [clang, gcc]
-        legacy_protocol: ["", --disable-legacy-protocol]
       fail-fast: false
-
-    runs-on: ${{ matrix.os }}
+      matrix:
+        sanitizer:
+          - thread
+          - undefined
     env:
-      CC: ${{ matrix.compiler }}
+      SANITIZER: "${{ matrix.sanitizer }}"
 
     steps:
       - name: Checkout code
         uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
 
-      - name: Install Artistic Style and build deps
-        run: >
-          sudo apt-get install -y --no-install-{recommends,suggests}
-          zlib1g-dev
-          liblzo2-dev
-          libncurses-dev
-          libreadline-dev
-          libminiupnpc-dev
-          libvdeplug-dev
-          astyle
-          socket
-
-      - name: Install OpenSSL
-        run: sudo apt-get install -y libssl-dev
-        if: ${{ matrix.legacy_protocol == '' }}
-
-      - name: Run autoreconf
-        run: autoreconf -fsi
-
-      - name: Run ./configure
+      - name: Install deps
+        shell: bash
         run: >
-          ./configure 
-          --enable-{miniupnpc,uml,vde}
-          ${{ matrix.legacy_protocol }}
-
-      - name: Check code formatting
-        run: make check-style
+          sudo apt-get install -y
+          git binutils make autoconf automake diffutils texinfo netcat
+          zlib1g-dev lib{ssl,lzo2,ncurses,readline,vdeplug,miniupnpc}-dev
 
-      - name: Compile project
-        run: make -j$(nproc)
+      - name: Configure and compile
+        shell: bash
+        run: bash .github/workflows/sanitizers/build.sh
+        env:
+          CC: clang-12
 
       - name: Run tests
-        # root is required for some tests
-        run: sudo make check-recursive
-        timeout-minutes: 20
+        run: bash .github/workflows/sanitizers/run.sh
+
+      - name: Archive test results
+        run: sudo tar -c -z -f test-results.tar.gz test/ sanitizer/
+        if: always()
 
       - name: Upload test results
         uses: actions/upload-artifact@v2
         with:
-          name: tests_${{ matrix.os }}_${{ matrix.compiler }}
-          path: test/test-suite.log
-        if: failure()
+          name: tests_sanitizer_${{ matrix.sanitizer }}
+          path: test-results.tar.gz
+        if: always()
 
-  build-windows:
-    runs-on: windows-latest
+  linux:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        os:
+          - alpine:3.13
+          - centos:7 # aka RHEL 7
+          - almalinux:8 # aka RHEL 8
+          - debian:oldstable
+          - debian:stable
+          - debian:testing
+          - debian:unstable
+          - ubuntu:18.04 # previous LTS
+          - ubuntu:20.04 # current LTS
+          - opensuse/leap # aka SLES
+    container:
+      image: ${{ matrix.os }}
+      options: --privileged
 
     steps:
+      - name: Install deps (Alpine)
+        run: >
+          apk add git binutils make autoconf automake gcc linux-headers libtool
+          diffutils texinfo procps openssl-dev zlib-dev lzo-dev ncurses-dev
+          readline-dev musl-dev lz4-dev socat
+        if: startsWith(matrix.os, 'alpine')
+
+      - name: Install deps (Debian and Ubuntu)
+        shell: bash
+        run: |
+          apt-get update
+          apt-get install -y git binutils make autoconf automake gcc diffutils \
+            texinfo netcat procps socat zlib1g-dev lib{ssl,lzo2,lz4,ncurses,readline}-dev
+        env:
+          DEBIAN_FRONTEND: noninteractive
+        if: startsWith(matrix.os, 'debian') || startsWith(matrix.os, 'ubuntu')
+
+      - name: Install deps (RHEL)
+        shell: bash
+        run: |
+          if type dnf 2>/dev/null; then
+            dnf install -y 'dnf-command(config-manager)'
+            dnf config-manager --enable powertools
+          fi
+          yum install -y epel-release
+          yum install -y git binutils make autoconf automake gcc diffutils \
+            texinfo netcat procps socat {lzo,zlib,lz4,openssl,ncurses,readline}-devel
+        if: startsWith(matrix.os, 'centos') || startsWith(matrix.os, 'alma')
+
+      - name: Install deps (SUSE)
+        shell: bash
+        run: >
+          zypper install -y tar git binutils make autoconf automake gcc procps
+          makeinfo diffutils gzip socat {openssl,zlib,lzo,liblz4,ncurses,readline}-devel
+        if: startsWith(matrix.os, 'opensuse')
+
       - name: Checkout code
         uses: actions/checkout@v2
-
-      - name: Install msys2
-        uses: msys2/setup-msys2@v2
         with:
-          update: true
-          # https://packages.msys2.org/package/
-          install: >-
-            base-devel
-            mingw-w64-x86_64-gcc
-            mingw-w64-x86_64-openssl
-            mingw-w64-x86_64-zlib
-            mingw-w64-x86_64-lzo2
-            mingw-w64-x86_64-ncurses
-            mingw-w64-x86_64-miniupnpc
-            git
+          fetch-depth: 0
 
-      - name: Build the project
-        shell: msys2 {0}
-        run: |
-          autoreconf -fsi
-          ./configure --with-curses-include=/mingw64/include/ncurses --disable-readline
-          make -j$(nproc)
+      - name: Assign name for test results artifact
+        run: echo TEST_ARTIFACT="$(echo '${{ matrix.os }}' | sed 's|[:/]|_|g')" >>"$GITHUB_ENV"
 
-      - name: Check that tinc can be started
-        shell: msys2 {0}
-        run: ./src/tinc --version
+      - name: Run tests with default settings
+        run: sh .github/workflows/test/run.sh default
 
-      - name: Check that tincd can be started
-        shell: msys2 {0}
-        run: ./src/tincd --version
+      - name: Run tests without legacy protocol
+        run: sh .github/workflows/test/run.sh nolegacy
 
-  release-deb:
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_${{ env.TEST_ARTIFACT }}
+          path: /tmp/tests.*.tar.gz
+        if: always()
+
+  deb-build:
     if: startsWith(github.ref, 'refs/tags/release-')
-    needs: test-linux
+    needs: linux
 
     strategy:
       matrix:
-        os: ["ubuntu-18.04", ubuntu-20.04]
+        os: [ubuntu-18.04, ubuntu-20.04]
 
     runs-on: ${{ matrix.os }}
 
     steps:
       - name: Checkout code
         uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
 
       - name: Install build deps
         run: >
           sudo apt-get install -y --no-install-{recommends,suggests}
+          devscripts
+          git-buildpackage
           dh-make
           texinfo
           libssl-dev
@@ -128,70 +190,157 @@ jobs:
           liblzo2-dev
           libncurses-dev
           libreadline-dev
+          libminiupnpc-dev
 
-      - name: Run autoreconf
+      - name: Configure project
         run: autoreconf -fsi
 
-      - name: Run ./configure
-        run: >
-          ./configure 
-          --prefix=/usr
-          --sbindir=/usr/sbin
-          --sysconfdir=/etc
-          --localstatedir=/var
-          --with-systemd=/usr/lib/systemd/system
-
       - name: Prepare debian directory
-        run: >
-          dh_make
-          --yes
-          --single
-          --createorig
-          --copyright gpl2
-          --packagename "tinc_$(git describe --tags --always | sed 's/release-//')-${{ matrix.os }}"
+        run: bash .github/workflows/deb/prepare.sh
         env:
-          DEBFULLNAME: Automated Builds
+          JOB_DISTRIBUTION: ${{ matrix.os }}
 
       - name: Build deb package
-        run: dpkg-buildpackage -d -us -uc
+        run: |
+          dpkg-buildpackage -d -us -uc
+          mv ../*.deb .
+
+      - name: Upload packages
+        uses: actions/upload-artifact@v2
+        with:
+          name: deb-${{ matrix.os }}
+          path: "*.deb"
+
+  deb-publish:
+    needs: deb-build
+
+    strategy:
+      matrix:
+        os: [ubuntu-18.04, ubuntu-20.04]
+
+    runs-on: ${{ matrix.os }}
+
+    steps:
+      - name: Download built packages
+        uses: actions/download-artifact@v2
+        with:
+          name: deb-${{ matrix.os }}
+
+      - name: Install package
+        run: sudo apt-get install -y ./*.deb
+
+      - name: Prepare tinc configs
+        run: |
+          set -eu
+          sudo mkdir -p /etc/tinc/test/hosts
+          sudo tinc -b -n test generate-ed25519-keys
+          echo "Name test" | sudo tee /etc/tinc/test/tinc.conf
+
+      - name: Enable and start tincd
+        run: |
+          sudo systemctl start tinc@test
+          sudo tinc -n test dump reachable nodes
 
       - name: Publish deb package
         uses: softprops/action-gh-release@v1
         with:
-          files: |
-            ../*.deb
+          files: "*.deb"
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
-  test-macos:
-    runs-on: macos-10.15
+  macos:
+    runs-on: macos-latest
+
+    strategy:
+      fail-fast: false
+      matrix:
+        legacy_protocol: ["", --disable-legacy-protocol]
 
     steps:
       - name: Checkout code
         uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
 
-      - name: Install dependencies
-        run: brew install coreutils netcat automake lzo miniupnpc
-
-      - name: Run autoreconf
-        run: autoreconf -fsi
+      - name: Install build deps
+        run: brew install coreutils netcat automake lzo lz4 miniupnpc
 
-      - name: Run ./configure
-        run: >
-          ./configure
-          --with-openssl=/usr/local/opt/openssl@1.1
-          --enable-{tunemu,miniupnpc}
+      - name: Configure project
+        run: |
+          autoreconf -fsi
+          ./configure --with-openssl=/usr/local/opt/openssl@1.1 --enable-{tunemu,miniupnpc} ${{ matrix.legacy_protocol }}
 
-      - name: Compile application
+      - name: Compile project
         run: make -j$(sysctl -n hw.ncpu)
 
       - name: Run tests
-        run: make check-recursive
-        timeout-minutes: 20
+        run: make check-recursive VERBOSE=1
+
+      - name: Archive test results
+        run: sudo tar -c -z -f test-results.tar.gz test/
+        if: always()
+
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_${{ runner.os }}_${{ matrix.legacy_protocol }}
+          path: test-results.tar.gz
+        if: always()
+
+  windows:
+    runs-on: windows-latest
+
+    strategy:
+      fail-fast: false
+      matrix:
+        legacy_protocol: ["", --disable-legacy-protocol]
+
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+
+      - name: Install msys2
+        uses: msys2/setup-msys2@v2
+        with:
+          update: true
+          # https://packages.msys2.org/package/
+          install: >-
+            base-devel
+            mingw-w64-x86_64-gcc
+            mingw-w64-x86_64-openssl
+            mingw-w64-x86_64-zlib
+            mingw-w64-x86_64-lzo2
+            mingw-w64-x86_64-lz4
+            mingw-w64-x86_64-ncurses
+            mingw-w64-x86_64-miniupnpc
+            git
+            netcat
+            procps
+
+      - name: Configure project
+        shell: msys2 {0}
+        run: |
+          autoreconf -fsi
+          ./configure --enable-miniupnpc --disable-readline --with-curses-include=/mingw64/include/ncurses ${{ matrix.legacy_protocol }}
+
+      - name: Compile project
+        shell: msys2 {0}
+        run: make -j$(nproc)
+
+      - name: Run tests
+        shell: msys2 {0}
+        run: make check-recursive VERBOSE=1
+
+      - name: Archive test results
+        shell: msys2 {0}
+        run: tar -c -z -f test-results.tar.gz test/
+        if: always()
 
       - name: Upload test results
         uses: actions/upload-artifact@v2
         with:
-          name: tests_${{ runner.os }}
-          path: test/test-suite.log
-        if: failure()
+          name: tests_${{ runner.os }}_${{ matrix.legacy_protocol }}
+          path: test-results.tar.gz
+        if: always()