CI: use explicit Debian release names.
[tinc] / .github / workflows / test.yml
index 21b3aba..0a53f4a 100644 (file)
-name: Build and test
+name: Test
 
 on:
   push:
-    branches:
-      - master
-      - "1.1"
-    tags:
-      - "release-*"
-
   pull_request:
     types:
       - opened
       - synchronize
 
 jobs:
-  test-linux:
+  cross:
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
     strategy:
-      matrix:
-        os: [ubuntu-18.04, ubuntu-20.04]
-        compiler: [clang, gcc]
-        legacy_protocol: ["", --disable-legacy-protocol]
       fail-fast: false
+      matrix:
+        arch:
+          - armhf
+          - mips
 
-    runs-on: ${{ matrix.os }}
-    env:
-      CC: ${{ matrix.compiler }}
+    container:
+      image: debian:bullseye
+      options: --privileged
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v2
-
-      - 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
-        run: >
-          ./configure 
-          --enable-{miniupnpc,uml,vde}
-          ${{ matrix.legacy_protocol }}
+        uses: actions/checkout@v1
 
-      - name: Check code formatting
-        run: make check-style
+      - name: Install deps
+        run: HOST=${{ matrix.arch }} sh .ci/deps.sh
 
-      - name: Compile project
-        run: make -j$(nproc)
+      - name: Prepare the system
+        run: |
+          sh .ci/test/prepare.sh
+          rm -f /dev/net/tun
 
-      - name: Run tests
-        # root is required for some tests
-        run: sudo make check-recursive
-        timeout-minutes: 20
+      - name: Run tests with default settings
+        run: sudo -u build CI=1 HOST=${{ matrix.arch }} sh .ci/test/run.sh default
+
+      - name: Run tests without legacy protocol
+        run: sudo -u build CI=1 HOST=${{ matrix.arch }} sh .ci/test/run.sh nolegacy
 
       - name: Upload test results
         uses: actions/upload-artifact@v2
         with:
-          name: tests_${{ matrix.os }}_${{ matrix.compiler }}
-          path: test/test-suite.log
-        if: failure()
-
-  build-windows:
-    runs-on: windows-latest
+          name: tests_cross_${{ env.ARTIFACT }}
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
 
+  static-analysis:
+    runs-on: ubuntu-latest
+    timeout-minutes: 10
     steps:
       - name: Checkout code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v1
 
-      - 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
+      - name: Install tools
+        run: |
+          sudo apt-get install -y astyle clang-tidy-$CLANG
+          sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-$CLANG 100
+          curl -OL "https://github.com/koalaman/shellcheck/releases/download/v$SHELLCHECK/shellcheck-v${SHELLCHECK}.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/v$SHFMT/shfmt_v${SHFMT}_linux_amd64"
+          chmod 755 ~/shfmt ~/shellcheck
+          pip3 install --user compiledb
+        env:
+          CLANG: 11
+          SHELLCHECK: 0.7.2
+          SHFMT: 3.3.0
 
-      - name: Build the project
-        shell: msys2 {0}
+      - name: Install deps
+        run: sudo sh .ci/deps.sh
+
+      - name: Configure and compile
         run: |
           autoreconf -fsi
-          ./configure --with-curses-include=/mingw64/include/ncurses --disable-readline
-          make -j$(nproc)
+          ./configure $(sh .ci/conf.sh)
 
-      - name: Check that tinc can be started
-        shell: msys2 {0}
-        run: ./src/tinc --version
+      - name: Run clang-tidy
+        run: sh .ci/tidy/run.sh
+        if: always()
 
-      - name: Check that tincd can be started
-        shell: msys2 {0}
-        run: ./src/tincd --version
+      - name: Check code formatting
+        run: "! astyle -r --options=.astylerc --dry-run --formatted '*.c' '*.h' | grep '^Formatted'"
+        if: always()
+
+      - 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: Run static analysis on tests
+        run: find -type f -name '*.test' -execdir shellcheck -x '{}' +
+        if: always()
 
-  release-deb:
-    if: startsWith(github.ref, 'refs/tags/release-')
-    needs: test-linux
+      - name: Check warnings (gcc)
+        run: bash .ci/warn/run.sh
+        env:
+          CC: gcc
+        if: always()
+
+      - name: Check warnings (clang)
+        run: bash .ci/warn/run.sh
+        env:
+          CC: clang
+        if: always()
 
+  sanitizer:
+    runs-on: ubuntu-latest
+    timeout-minutes: 20
     strategy:
+      fail-fast: false
       matrix:
-        os: ["ubuntu-18.04", ubuntu-20.04]
-
-    runs-on: ${{ matrix.os }}
+        sanitizer:
+          - address
+          - thread
+          - undefined
+    env:
+      SANITIZER: "${{ matrix.sanitizer }}"
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v1
 
-      - name: Install build deps
-        run: >
-          sudo apt-get install -y --no-install-{recommends,suggests}
-          dh-make
-          texinfo
-          libssl-dev
-          zlib1g-dev
-          liblzo2-dev
-          libncurses-dev
-          libreadline-dev
-
-      - name: Run autoreconf
-        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 }}"
+      - name: Install deps
+        run: sudo sh .ci/deps.sh
+
+      - name: Configure and compile
+        shell: bash
+        run: bash .ci/sanitizers/build.sh
         env:
-          DEBFULLNAME: Automated Builds
+          CC: clang-12
+
+      - name: Run tests
+        run: bash .ci/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_sanitizer_${{ matrix.sanitizer }}
+          path: test-results.tar.gz
+        if: always()
+
+  linux:
+    runs-on: ubuntu-latest
+    timeout-minutes: 20
+    strategy:
+      fail-fast: false
+      matrix:
+        os:
+          - alpine
+          - centos:7 # aka RHEL 7
+          - almalinux:8 # aka RHEL 8
+          - fedora
+          - debian:buster
+          - debian:bullseye
+          - debian:testing
+          - ubuntu # current LTS
+          - ubuntu:rolling # latest
+    container:
+      image: ${{ matrix.os }}
+      options: --privileged
+      env:
+        CI: 1
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Install deps
+        run: sh .ci/deps.sh
+
+      - name: Assign name for test results artifact
+        run: echo ARTIFACT="$(echo '${{ matrix.os }}' | sed 's|[:/]|_|g')" >>"$GITHUB_ENV"
+
+      - name: Create a non-privileged user
+        run: sh .ci/test/prepare.sh
+
+      - name: Run tests with default settings
+        run: sudo -u build CI=1 sh .ci/test/run.sh default
+
+      - name: Run tests without legacy protocol
+        run: sudo -u build CI=1 sh .ci/test/run.sh nolegacy
+
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_${{ env.ARTIFACT }}
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
 
-      - name: Build deb package
-        run: dpkg-buildpackage -d -us -uc
+      - name: Build package
+        run: sh .ci/package/build.sh
+        if: github.ref == 'refs/heads/1.1' || startsWith(github.ref, 'refs/tags/release-')
 
-      - name: Publish deb package
+      - name: Upload package
+        uses: actions/upload-artifact@v2
+        with:
+          name: pkg-${{ env.ARTIFACT }}
+          path: |
+            *.deb
+            ~/rpmbuild/RPMS/*/*.rpm
+
+  pkg-publish:
+    if: always() && (github.ref == 'refs/heads/1.1' || startsWith(github.ref, 'refs/tags/release-'))
+    runs-on: ubuntu-latest
+    needs:
+      - linux
+      - windows
+
+    steps:
+      - name: Create artifact directory
+        run: mkdir -p /tmp/artifacts
+
+      - name: Download packages
+        uses: actions/download-artifact@v2
+        with:
+          path: /tmp/artifacts
+
+      - name: Publish packages (dev)
+        uses: marvinpinto/action-automatic-releases@latest
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          automatic_release_tag: latest
+          title: Development release
+          prerelease: true
+          files: /tmp/artifacts/**/*.(deb|rpm|exe)
+        if: startsWith(github.ref, 'refs/heads/')
+
+      - name: Publish packages (release)
         uses: softprops/action-gh-release@v1
         with:
           files: |
-            ../*.deb
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+            /tmp/artifacts/**/*.deb
+            /tmp/artifacts/**/*.rpm
+            /tmp/artifacts/**/*.exe
+        if: startsWith(github.ref, 'refs/tags/')
 
-  test-macos:
-    runs-on: macos-10.15
+  macos:
+    runs-on: macos-latest
+    timeout-minutes: 15
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v1
 
-      - name: Install dependencies
-        run: brew install coreutils netcat automake lzo miniupnpc
+      - name: Install build deps
+        run: sh .ci/deps.sh
 
-      - name: Run autoreconf
-        run: autoreconf -fsi
+      - name: Run tests with default settings
+        run: sh .ci/test/run.sh default
 
-      - name: Run ./configure
-        run: >
-          ./configure
-          --with-openssl=/usr/local/opt/openssl@1.1
-          --enable-{tunemu,miniupnpc}
+      - name: Run clang-tidy
+        run: |
+          export PATH="$PATH:$(brew --prefix llvm)/bin:$HOME/Library/Python/3.9/bin"
+          sh .ci/tidy/run.sh
 
-      - name: Compile application
-        run: make -j$(sysctl -n hw.ncpu)
+      - name: Run tests without legacy protocol
+        run: sh .ci/test/run.sh nolegacy
 
-      - name: Run tests
-        run: make check-recursive
-        timeout-minutes: 20
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_macos
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
+
+  windows:
+    runs-on: windows-latest
+    timeout-minutes: 20
+
+    steps:
+      - 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
+            mingw-w64-x86_64-nsis
+            git
+            netcat
+            procps
+
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Run tests with default settings
+        shell: msys2 {0}
+        run: sh .ci/test/run.sh default
+
+      - name: Create installer
+        shell: msys2 {0}
+        run: sh .ci/package/build.sh
+        if: github.ref == 'refs/heads/1.1' || startsWith(github.ref, 'refs/tags/release-')
+
+      - name: Upload package
+        uses: actions/upload-artifact@v2
+        with:
+          name: pkg-windows
+          path: .ci/package/win/tinc-*.exe
+
+      - name: Run tests without legacy protocol
+        shell: msys2 {0}
+        run: sh .ci/test/run.sh nolegacy
 
       - name: Upload test results
         uses: actions/upload-artifact@v2
         with:
-          name: tests_${{ runner.os }}
-          path: test/test-suite.log
-        if: failure()
+          name: tests_windows
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()