diff --git a/.github/matrix.py b/.github/matrix.py new file mode 100644 index 000000000..6e5b9247e --- /dev/null +++ b/.github/matrix.py @@ -0,0 +1,165 @@ +# Copyright 2019 Ilya Shipitsin +# Copyright 2020 Tim Duesterhus +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. + +import json + + +def clean_os(os): + if os == "ubuntu-latest": + return "Ubuntu" + elif os == "macos-latest": + return "macOS" + return os.replace("-latest", "") + + +def clean_ssl(ssl): + return ssl.replace("_VERSION", "").lower() + + +def clean_compression(compression): + return compression.replace("USE_", "").lower() + + +def get_asan_flags(cc): + if cc == "clang": + return [ + "USE_OBSOLETE_LINKER=1", + 'DEBUG_CFLAGS="-g -fsanitize=address"', + 'LDFLAGS="-fsanitize=address"', + 'CPU_CFLAGS.generic="-O1"', + ] + + raise ValueError("ASAN is only supported for clang") + + +matrix = [] + +# Ubuntu + +os = "ubuntu-latest" +TARGET = "linux-glibc" +for CC in ["gcc", "clang"]: + matrix.append( + { + "name": "{}, {}, no features".format(clean_os(os), CC), + "os": os, + "TARGET": TARGET, + "CC": CC, + "FLAGS": [], + } + ) + + matrix.append( + { + "name": "{}, {}, all features".format(clean_os(os), CC), + "os": os, + "TARGET": TARGET, + "CC": CC, + "FLAGS": [ + "USE_ZLIB=1", + "USE_PCRE=1", + "USE_PCRE_JIT=1", + "USE_LUA=1", + "USE_OPENSSL=1", + "USE_SYSTEMD=1", + "USE_WURFL=1", + "WURFL_INC=contrib/wurfl", + "WURFL_LIB=contrib/wurfl", + "USE_DEVICEATLAS=1", + "DEVICEATLAS_SRC=contrib/deviceatlas", + # "USE_51DEGREES=1", + # "FIFTYONEDEGREES_SRC=contrib/51d/src/pattern", + ], + } + ) + + for compression in ["USE_SLZ=1", "USE_ZLIB=1"]: + matrix.append( + { + "name": "{}, {}, gz={}".format( + clean_os(os), CC, clean_compression(compression) + ), + "os": os, + "TARGET": TARGET, + "CC": CC, + "FLAGS": [compression], + } + ) + + for ssl in [ + "stock", + "OPENSSL_VERSION=1.0.2u", + "LIBRESSL_VERSION=2.9.2", + "LIBRESSL_VERSION=3.0.2", + "LIBRESSL_VERSION=3.1.1", + ]: + flags = ["USE_OPENSSL=1"] + if ssl != "stock": + flags.append("SSL_LIB=${HOME}/opt/lib") + flags.append("SSL_INC=${HOME}/opt/include") + matrix.append( + { + "name": "{}, {}, ssl={}".format(clean_os(os), CC, clean_ssl(ssl)), + "os": os, + "TARGET": TARGET, + "CC": CC, + "ssl": ssl, + "FLAGS": flags, + } + ) + +# ASAN + +os = "ubuntu-latest" +CC = "clang" +TARGET = "linux-glibc" +matrix.append( + { + "name": "{}, {}, ASAN, all features".format(clean_os(os), CC), + "os": os, + "TARGET": TARGET, + "CC": CC, + "FLAGS": get_asan_flags(CC) + + [ + "USE_ZLIB=1", + "USE_PCRE=1", + "USE_PCRE_JIT=1", + "USE_LUA=1", + "USE_OPENSSL=1", + "USE_SYSTEMD=1", + "USE_WURFL=1", + "WURFL_INC=contrib/wurfl", + "WURFL_LIB=contrib/wurfl", + "USE_DEVICEATLAS=1", + "DEVICEATLAS_SRC=contrib/deviceatlas", + # "USE_51DEGREES=1", + # "FIFTYONEDEGREES_SRC=contrib/51d/src/pattern", + ], + } +) + +# macOS + +os = "macos-latest" +TARGET = "osx" +for CC in ["clang"]: + matrix.append( + { + "name": "{}, {}, no features".format(clean_os(os), CC), + "os": os, + "TARGET": TARGET, + "CC": CC, + "FLAGS": [], + } + ) + +# Print matrix + +print(json.dumps(matrix, indent=4, sort_keys=True)) + +print("::set-output name=matrix::{}".format(json.dumps({"include": matrix}))) diff --git a/.github/vtest.json b/.github/vtest.json new file mode 100644 index 000000000..8e8165c24 --- /dev/null +++ b/.github/vtest.json @@ -0,0 +1,14 @@ +{ + "problemMatcher": [ + { + "owner": "vtest", + "pattern": [ + { + "regexp": "^#(\\s+top\\s+TEST\\s+(.*)\\s+FAILED.*)", + "file": 2, + "message": 1 + } + ] + } + ] +} diff --git a/.github/workflows/vtest.yml b/.github/workflows/vtest.yml new file mode 100644 index 000000000..c3571b876 --- /dev/null +++ b/.github/workflows/vtest.yml @@ -0,0 +1,133 @@ +# Copyright 2019 Ilya Shipitsin +# Copyright 2020 Tim Duesterhus +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. + +name: VTest + +on: + push: + +jobs: + # The generate-matrix job generates the build matrix using JSON output + # generated by .github/matrix.py. + generate-matrix: + name: Generate Build Matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + - name: Generate Build Matrix + id: set-matrix + run: python3 .github/matrix.py + + # The Test job actually runs the tests. + Test: + name: ${{ matrix.name }} + needs: generate-matrix + runs-on: ${{ matrix.os }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} + fail-fast: false + env: + # Configure a short TMPDIR to prevent failures due to long unix socket + # paths. + TMPDIR: /tmp + # Force ASAN output into asan.log to make the output more readable. + ASAN_OPTIONS: log_path=asan.log + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 100 + - name: Install apt dependencies + if: ${{ startsWith(matrix.os, 'ubuntu-') }} + run: | + sudo apt-get install -y \ + liblua5.3-dev \ + libpcre2-dev \ + libsystemd-dev \ + ninja-build \ + socat + - name: Install brew dependencies + if: ${{ startsWith(matrix.os, 'macos-') }} + run: | + brew install socat + brew install lua + - name: Install VTest + run: | + curl -fsSL https://github.com/vtest/VTest/archive/master.tar.gz -o VTest.tar.gz + mkdir VTest + tar xvf VTest.tar.gz -C VTest --strip-components=1 + make -C VTest -j$(nproc) FLAGS="-O2 -s -Wall" + sudo install -m755 VTest/vtest /usr/local/bin/vtest + - name: Install SLZ + if: ${{ contains(matrix.FLAGS, 'USE_SLZ=1') }} + run: | + curl -fsSL https://github.com/wtarreau/libslz/archive/master.tar.gz -o libslz.tar.gz + mkdir libslz + tar xvf libslz.tar.gz -C libslz --strip-components=1 + make -C libslz + sudo make -C libslz install + - name: Install SSL ${{ matrix.ssl }} + if: ${{ matrix.ssl && matrix.ssl != 'stock' }} + run: env ${{ matrix.ssl }} scripts/build-ssl.sh + - name: Build WURFL + if: ${{ contains(matrix.FLAGS, 'USE_WURFL=1') }} + run: make -C contrib/wurfl + - name: Compile HAProxy with ${{ matrix.CC }} + run: | + make -j$(nproc) all \ + ERR=1 \ + TARGET=${{ matrix.TARGET }} \ + CC=${{ matrix.CC }} \ + ${{ join(matrix.FLAGS, ' ') }} \ + ADDLIB="-Wl,-rpath,/usr/local/lib/ -Wl,-rpath,$HOME/opt/lib/" + sudo make install + - name: Show HAProxy version + id: show-version + run: | + echo "::group::Show dynamic libraries." + if command -v ldd > /dev/null; then + # Linux + ldd $(which haproxy) + else + # macOS + otool -L $(which haproxy) + fi + echo "::endgroup::" + haproxy -vv + echo "::set-output name=version::$(haproxy -v |awk 'NR==1{print $3}')" + - name: Adjust hosts file + # This step can be removed if https://github.com/vtest/VTest/pull/24 is + # fixed. + run: | + cat /etc/hosts + sudo sed -i.bak '/::1/s/^/#/' /etc/hosts + - name: Install problem matcher for VTest + # This allows one to more easily see which tests fail. + run: echo "::add-matcher::.github/vtest.json" + - name: Run VTest for HAProxy ${{ steps.show-version.outputs.version }} + id: vtest + # sudo is required, because macOS fails due to an open files limit. + run: sudo make reg-tests REGTESTS_TYPES=default,bug,devel + - name: Show results + if: ${{ failure() }} + # The chmod / sudo is necessary due to the `sudo` while running the tests. + run: | + sudo chmod a+rX ${TMPDIR}/haregtests-*/ + for folder in ${TMPDIR}/haregtests-*/vtc.*; do + printf "::group::" + cat $folder/INFO + cat $folder/LOG + echo "::endgroup::" + done + shopt -s nullglob + for asan in asan.log*; do + echo "::group::$asan" + sudo cat $asan + echo "::endgroup::" + done