Add Markdown reformat to lint.py
[tinc] / .github / workflows / test.yml
index 214dd1d..ad86e0f 100644 (file)
@@ -1,4 +1,8 @@
-name: Build and test
+name: Test
+
+concurrency:
+  group: test-${{ github.head_ref }}
+  cancel-in-progress: true
 
 on:
   push:
@@ -8,72 +12,318 @@ on:
       - synchronize
 
 jobs:
-  test-linux:
+  cross:
+    runs-on: ubuntu-22.04
+    timeout-minutes: 30
     strategy:
-      matrix:
-        os: [ubuntu-18.04, ubuntu-20.04]
-        compiler: [clang, gcc]
-        legacy_protocol: ["", --disable-legacy-protocol]
       fail-fast: false
+      matrix:
+        arch:
+          - armhf
+          - mipsel
+          - mingw
+
+    container:
+      image: debian:bullseye
+      options: --privileged
+
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Install deps
+        run: HOST=${{ matrix.arch }} sh .ci/deps.sh
+
+      - name: Prepare the system
+        run: HOST=${{ matrix.arch }} sh .ci/test/prepare.sh
+
+      - 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
+        if: always()
+
+      - name: Run tests with libgcrypt
+        run: sudo -u build CI=1 HOST=${{ matrix.arch }} sh .ci/test/run.sh gcrypt
+        if: always()
+
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_cross_${{ matrix.arch }}
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
+
+  muon:
+    runs-on: ubuntu-22.04
+    timeout-minutes: 20
+    container:
+      image: debian:bullseye-slim
+      env:
+        CI: 1
+
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Install dependencies
+        run: SKIP_OPENSSL3=1 SKIP_MESON=1 .ci/deps.sh libpkgconf-dev
+
+      - name: Compatibility with muon
+        run: ./.ci/muon/run.sh
+
+  analysis:
+    runs-on: ubuntu-22.04
+    timeout-minutes: 30
+    steps:
+      - name: Checkout tinc
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Install dependencies
+        run: sudo SKIP_OPENSSL3=1 .ci/deps.sh autoconf automake iperf3
+
+      - name: Compatibility with older versions of tinc
+        run: sudo ./.ci/compat/run.sh
+        if: always()
+
+      - 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
+          sudo update-alternatives --install /usr/bin/run-clang-tidy run-clang-tidy /usr/bin/run-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
+          python3 -m venv /tmp/venv
+          . /tmp/venv/bin/activate
+          pip3 install black pylint mypy markflow
+        env:
+          CLANG: 11
+          SHELLCHECK: 0.8.0
+          SHFMT: 3.5.0
+        if: always()
+
+      - name: Lint/typecheck/check formatting on C/shell/Python code
+        run: |
+          . /tmp/venv/bin/activate
+          PATH=$PATH:$HOME ./lint.py
+        if: always()
+
+      - name: Check warnings (clang)
+        run: bash .ci/warn/run.sh
+        env:
+          CC: clang-12
+        if: always()
+
+      - name: Check warnings (gcc)
+        run: bash .ci/warn/run.sh
+        env:
+          CC: gcc-11
+        if: always()
+
+      - name: Archive test results
+        run: sudo tar -caf tests.tar.gz /usr/local/etc
+        continue-on-error: true
+        if: always()
+
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_compat
+          path: tests.tar.gz
+        if: always()
 
-    runs-on: ${{ matrix.os }}
+  sanitizer:
+    runs-on: ubuntu-22.04
+    timeout-minutes: 30
+    strategy:
+      fail-fast: false
+      matrix:
+        sanitizer:
+          - address
+          - thread
+          - undefined
     env:
-      CC: ${{ matrix.compiler }}
+      SANITIZER: "${{ matrix.sanitizer }}"
 
     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 }}
-
-      - name: Check code formatting
-        run: make check-style
-
-      - name: Compile project
-        run: make -j$(nproc)
-
-      - name: Run tests
-        # root is required for some tests
-        run: sudo make check-recursive
-        timeout-minutes: 20
+        uses: actions/checkout@v1
+
+      - name: Install deps
+        run: |
+          sudo sh .ci/deps.sh
+          sudo pip3 install --upgrade cryptography
+
+      - name: Run tests with OpenSSL 3
+        run: bash .ci/sanitizers/run.sh openssl3
+        if: always()
+
+      - name: Sanitize tests with default settings
+        run: bash .ci/sanitizers/run.sh default
+        if: always()
+
+      - name: Sanitize tests without legacy protocol
+        run: bash .ci/sanitizers/run.sh nolegacy
+        if: always()
+
+      - name: Run tests with libgcrypt
+        run: bash .ci/sanitizers/run.sh gcrypt
+        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: /tmp/logs/tests.*.tar.gz
+        if: always()
 
-  build-windows:
-    runs-on: windows-latest
+  linux:
+    runs-on: ubuntu-22.04
+    timeout-minutes: 30
+    strategy:
+      fail-fast: false
+      matrix:
+        os:
+          - alpine
+          - alpine:edge
+          - centos:7 # aka RHEL 7
+          - almalinux:8 # aka RHEL 8
+          - almalinux:9 # aka RHEL 9
+          - 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 OpenSSL 3
+        run: sudo -u build CI=1 sh .ci/test/run.sh openssl3
+
+      - name: Run tests with default settings
+        run: sudo -u build CI=1 sh .ci/test/run.sh default
+        if: always()
+
+      - name: Run tests without legacy protocol
+        run: sudo -u build CI=1 sh .ci/test/run.sh nolegacy
+        if: always()
+
+      - name: Run tests with libgcrypt
+        run: sudo -u build CI=1 sh .ci/test/run.sh gcrypt
+        if: always()
+
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_${{ env.ARTIFACT }}
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
+
+      - name: Build package
+        run: sh .ci/package/build.sh
+        if: github.ref == 'refs/heads/1.1' || startsWith(github.ref, 'refs/tags/release-')
+        continue-on-error: true
+
+      - name: Upload package
+        uses: actions/upload-artifact@v2
+        with:
+          name: pkg-${{ env.ARTIFACT }}
+          path: |
+            *.deb
+            ~/rpmbuild/RPMS/*/*.rpm
+        continue-on-error: true
+
+  pkg-publish:
+    if: always() && (github.ref == 'refs/heads/1.1' || startsWith(github.ref, 'refs/tags/release-'))
+    runs-on: ubuntu-22.04
+    continue-on-error: true
+    needs:
+      - linux
+      - mingw
+
+    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: |
+            /tmp/artifacts/**/*.deb
+            /tmp/artifacts/**/*.rpm
+            /tmp/artifacts/**/*.exe
+        if: startsWith(github.ref, 'refs/tags/')
+
+  macos:
+    runs-on: macos-12
+    timeout-minutes: 20
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v1
+
+      - name: Install build deps
+        run: sh .ci/deps.sh
+
+      - name: Run tests with default settings
+        run: sh .ci/test/run.sh default
+
+      - name: Run tests without legacy protocol
+        run: sh .ci/test/run.sh nolegacy
+        if: always()
+
+      - name: Run tests with libgcrypt
+        run: sh .ci/test/run.sh gcrypt
+        if: always()
+
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_macos
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
+
+  mingw:
+    runs-on: windows-latest
+    timeout-minutes: 30
 
+    steps:
       - name: Install msys2
         uses: msys2/setup-msys2@v2
         with:
@@ -81,117 +331,97 @@ jobs:
           # https://packages.msys2.org/package/
           install: >-
             base-devel
+            mingw-w64-x86_64-meson
+            mingw-w64-x86_64-pkgconf
             mingw-w64-x86_64-gcc
             mingw-w64-x86_64-openssl
+            mingw-w64-x86_64-libgcrypt
             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
+            openbsd-netcat
+            procps
 
-      - name: Build the project
-        shell: msys2 {0}
-        run: |
-          autoreconf -fsi
-          ./configure --with-curses-include=/mingw64/include/ncurses --disable-readline
-          make -j$(nproc)
+      - name: Checkout code
+        uses: actions/checkout@v1
 
-      - name: Check that tinc can be started
+      - name: Run tests with default settings
         shell: msys2 {0}
-        run: ./src/tinc --version
+        run: sh .ci/test/run.sh default
 
-      - name: Check that tincd can be started
+      - name: Create installer
         shell: msys2 {0}
-        run: ./src/tincd --version
-
-  release-deb:
-    if: startsWith(github.ref, 'refs/tags/release-')
-    needs: test-linux
+        run: sh .ci/package/build.sh
+        if: github.ref == 'refs/heads/1.1' || startsWith(github.ref, 'refs/tags/release-')
+        continue-on-error: true
 
-    strategy:
-      matrix:
-        os: ["ubuntu-18.04", ubuntu-20.04]
+      - name: Upload package
+        uses: actions/upload-artifact@v2
+        with:
+          name: pkg-windows
+          path: .ci/package/win/tinc-*.exe
+        continue-on-error: true
 
-    runs-on: ${{ matrix.os }}
+      - name: Run tests without legacy protocol
+        shell: msys2 {0}
+        run: sh .ci/test/run.sh nolegacy
+        if: always()
 
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v2
+      - name: Run tests with libgcrypt
+        shell: msys2 {0}
+        run: sh .ci/test/run.sh gcrypt
+        if: always()
 
-      - 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 }}"
-        env:
-          DEBFULLNAME: Automated Builds
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        with:
+          name: tests_windows
+          path: /tmp/logs/tests.*.tar.gz
+        if: always()
 
-      - name: Build deb package
-        run: dpkg-buildpackage -d -us -uc
+  msvc:
+    runs-on: windows-latest
+    timeout-minutes: 30
 
-      - name: Publish deb package
-        uses: softprops/action-gh-release@v1
-        with:
-          files: |
-            ../*.deb
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    strategy:
+      fail-fast: false
+      matrix:
+        target:
+          - { build: amd64, host: amd64, test: test }
+          - { build: amd64, host: x86, test: test }
+          - { build: amd64, host: arm64, test: notest }
 
-  test-macos:
-    runs-on: macos-10.15
+    env:
+      HOST_ARCH: ${{ matrix.target.host }}
+      BUILD_ARCH: ${{ matrix.target.build }}
 
     steps:
-      - name: Checkout code
-        uses: actions/checkout@v2
+      - name: Install meson
+        run: pip3 install meson
 
-      - name: Install dependencies
-        run: brew install coreutils netcat automake lzo miniupnpc
+      - name: Checkout code
+        uses: actions/checkout@v1
 
-      - name: Run autoreconf
-        run: autoreconf -fsi
+      - name: Activate dev environment
+        uses: ilammy/msvc-dev-cmd@v1
+        with:
+          arch: ${{ matrix.target.build == matrix.target.host && matrix.target.host || format('{0}_{1}', matrix.target.build, matrix.target.host) }}
 
-      - name: Run ./configure
-        run: >
-          ./configure
-          --with-openssl=/usr/local/opt/openssl@1.1
-          --enable-{tunemu,miniupnpc}
+      - name: Build (nolegacy)
+        run: .ci\windows\build.cmd nolegacy
 
-      - name: Compile application
-        run: make -j$(sysctl -n hw.ncpu)
+      - name: Test (nolegacy)
+        run: .ci\windows\test.cmd nolegacy
+        if: always() && matrix.target.test == 'test'
 
-      - name: Run tests
-        run: make check-recursive
-        timeout-minutes: 20
+      - name: Build (OpenSSL)
+        run: .ci\windows\build.cmd openssl
+        if: always()
 
-      - name: Upload test results
-        uses: actions/upload-artifact@v2
-        with:
-          name: tests_${{ runner.os }}
-          path: test/test-suite.log
-        if: failure()
+      - name: Test (OpenSSL)
+        run: .ci\windows\test.cmd openssl
+        if: always() && matrix.target.test == 'test'