summaryrefslogtreecommitdiffstats
path: root/.github/workflows/ci.yml
diff options
context:
space:
mode:
Diffstat (limited to '.github/workflows/ci.yml')
-rw-r--r--.github/workflows/ci.yml483
1 files changed, 483 insertions, 0 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..de5e7ed
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,483 @@
+name: CI
+
+on:
+ push:
+ branches-ignore:
+ - coverity_scan
+ pull_request:
+
+env:
+ PANIC_ACTION: "gdb -batch -x raddb/panic.gdb %e %p 1>&0 2>&0"
+ ALT_OPENSSL: "3.0.8"
+ CI: 1
+ GH_ACTIONS: 1
+ DEBIAN_FRONTEND: noninteractive
+ APT_OPTS: "-y --no-install-recommends"
+ LDAP_TEST_SERVER: 127.0.0.1
+ LDAP_TEST_SERVER_PORT: 3890
+ REST_TEST_SERVER: 127.0.0.1
+ REST_TEST_SERVER_PORT: 8080
+ REST_TEST_SERVER_SSL_PORT: 8443
+ SQL_MYSQL_TEST_SERVER: mariadb
+ SQL_POSTGRESQL_TEST_SERVER: postgres
+ ASAN_OPTIONS: symbolize=1 detect_leaks=1 detect_stack_use_after_return=1
+ LSAN_OPTIONS: fast_unwind_on_malloc=0:malloc_context_size=50
+ UBSAN_OPTIONS: print_stacktrace=1
+
+jobs:
+ pre-ci:
+ runs-on: ubuntu-latest
+ outputs:
+ should_skip: ${{ steps.skip_check.outputs.should_skip }}
+ selfhosted: ${{ github.repository_owner == 'FreeRADIUS' && '1' || '0' }}
+ docker_prefix: ${{ github.repository_owner == 'FreeRADIUS' && 'docker.internal.networkradius.com/' || '' }}
+ steps:
+ - id: skip_check
+ uses: fkirc/skip-duplicate-actions@master
+
+ ci:
+ needs: pre-ci
+ if: ${{ needs.pre-ci.outputs.should_skip != 'true' }}
+
+ runs-on: ${{ matrix.os.runs_on }}
+
+ container:
+ image: ${{ matrix.os.docker }}
+
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+#
+# runs_on - where GitHub will spin up the runner, either
+# "self-hosted", or the name of a GitHub VM image.
+# code - the name/version of the OS (for step evaluations below)
+# docker - the docker image name, if containers are being used
+# name - used in the job name only
+#
+ - runs_on: "${{ needs.pre-ci.outputs.selfhosted == '1' && 'self-hosted' || 'ubuntu-20.04' }}"
+ docker: "${{ needs.pre-ci.outputs.selfhosted == '1' && 'docker.internal.networkradius.com/self-hosted' || 'ubuntu:20.04' }}"
+ name: "${{ needs.pre-ci.outputs.selfhosted == '1' && 'self' || 'gh' }}-ubuntu20"
+ code: "ubuntu2004"
+
+ env:
+ - { CC: gcc, DO_BUILD: yes, LIBS_OPTIONAL: no, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-gcc-lean }
+ - { CC: gcc, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-gcc }
+ - { CC: gcc, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: yes, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-gcc-reproducible }
+ - { CC: gcc, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG -O2 -g3", NAME: linux-gcc-O2-g3 }
+ - { CC: clang, DO_BUILD: yes, LIBS_OPTIONAL: no, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-clang-lean }
+ - { CC: clang, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-clang }
+ - { CC: clang, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: yes, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-clang-altlibs }
+ - { CC: clang, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: yes, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-clang-reproducible }
+ - { CC: clang, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: yes, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG", NAME: linux-clang-sanitizer }
+ - { CC: clang, DO_BUILD: yes, LIBS_OPTIONAL: yes, LIBS_ALT: no, REPRODUCIBLE: no, SANITIZER: no, BUILD_CFLAGS: "-DWITH_EVAL_DEBUG -O2 -g3", NAME: linux-clang-O2-g3 }
+
+ env: ${{ matrix.env }}
+
+ # Test names are used in the branch protection rules in GitHub
+ # If you change the names here, or add additional matrix entries, you
+ # must also amend the branch protection fules.
+ name: "v3.2.x-${{ matrix.os.name }}-${{ matrix.env.NAME }}"
+
+ # The standard GitHub environment contains PostgreSQL and
+ # MySQL already. However when running on hosted GitHub runners
+ # we need to run separate database containers to provide these.
+ services:
+ mariadb:
+ image: ${{ needs.pre-ci.outputs.docker_prefix }}mariadb
+ env:
+ MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: yes
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 10
+
+ postgres:
+ image: ${{ needs.pre-ci.outputs.docker_prefix }}postgres
+ env:
+ POSTGRES_HOST_AUTH_METHOD: trust
+ ports:
+ - 5432:5432
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
+
+ steps:
+
+ - name: Self-hosted runner container fixes
+ run: |
+ ln -fs /usr/bin/env /usr/local/bin/sudo
+ rm -rf "$HOME"/*
+
+ - name: Package manager performance improvements
+ run: |
+ sudo sh -c 'echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02speedup'
+ if command -v mandb >/dev/null; then
+ echo 'man-db man-db/auto-update boolean false' | sudo debconf-set-selections
+ sudo dpkg-reconfigure man-db
+ fi
+
+ - name: Freshen APT repo metadata
+ run: |
+ sudo apt-get update
+
+ - name: Install common build dependencies
+ run: |
+ sudo apt-get install ${APT_OPTS} \
+ autoconf \
+ build-essential \
+ debhelper \
+ devscripts \
+ dh-make \
+ fakeroot \
+ firebird-dev \
+ freetds-dev \
+ gawk \
+ git \
+ git-lfs \
+ gnupg \
+ libcap-dev \
+ libcollectdclient-dev \
+ libcurl4-openssl-dev \
+ libgdbm-dev \
+ libhiredis-dev \
+ libidn11-dev \
+ libiodbc2 \
+ libiodbc2-dev \
+ libjson-c-dev \
+ libkqueue-dev \
+ libkrb5-dev \
+ libldap2-dev \
+ libmemcached-dev \
+ libmysqlclient-dev \
+ libnl-3-dev \
+ libnl-genl-3-dev \
+ libpam0g-dev \
+ libpcap-dev \
+ libpcre3-dev \
+ libperl-dev \
+ libpq-dev \
+ libreadline-dev \
+ libruby \
+ libsnmp-dev \
+ libsqlite3-dev \
+ libssl-dev \
+ libtalloc-dev \
+ libunbound-dev \
+ libwbclient-dev \
+ libykclient-dev \
+ libyubikey-dev \
+ lintian \
+ pbuilder \
+ python-dev \
+ python3-dev \
+ ruby-dev \
+ snmp \
+ software-properties-common \
+ quilt
+
+ - name: Install LLVM 15 for 20.04
+ if: ${{ matrix.os.code == 'ubuntu2004' && matrix.env.CC == 'clang' }}
+ run: |
+ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add
+ sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main"
+ sudo apt-get install ${APT_OPTS} clang-15 llvm-15 gdb libclang-rt-15-dev
+ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 60 && sudo update-alternatives --set clang /usr/bin/clang-15
+ sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-15 60 && sudo update-alternatives --set llvm-symbolizer /usr/bin/llvm-symbolizer-15
+
+ - name: Install GCC
+ if: ${{ matrix.env.CC == 'gcc' }}
+ run: |
+ sudo apt-get install ${APT_OPTS} gcc gdb
+
+ #
+ # Build using some alternative libraries
+ #
+ # MIT Kerberos -> HEIMDAL Kerberos
+ # OpenSSL 1.0 -> OpenSSL 3.0
+ #
+ - name: 'Fetch OpenSSL 3.0 SHA'
+ id: opensslshasum
+ if: ${{ matrix.env.LIBS_ALT == 'yes' }}
+ run: |
+ wget -qO- http://www.openssl.org/source/openssl-$ALT_OPENSSL.tar.gz.sha256 | sed -ne 's/^\s\+/shasum=/p' >> $GITHUB_OUTPUT
+
+ - name: 'Restore OpenSSL 3.0 from the cache'
+ if: ${{ matrix.env.LIBS_ALT == 'yes' }}
+ uses: actions/cache@v3
+ id: openssl-cache
+ with:
+ path: /opt/openssl/
+ key: openssl3-${{ steps.opensslshasum.outputs.shasum }}
+
+ - name: 'Build OpenSSL 3.0 (if cache stale)'
+ if: ${{ matrix.env.LIBS_ALT == 'yes' && steps.openssl-cache.outputs.cache-hit != 'true' }}
+ run: |
+ cd ~
+ wget https://www.openssl.org/source/openssl-$ALT_OPENSSL.tar.gz
+ tar xzf openssl-$ALT_OPENSSL.tar.gz
+ cd openssl-$ALT_OPENSSL
+ ./Configure --prefix=/opt/openssl --openssldir=.
+ make -j `nproc`
+ make install
+
+ - name: Use alternative libraries
+ if: ${{ matrix.env.LIBS_ALT == 'yes' }}
+ run: |
+ echo /opt/openssl/lib64 | sudo tee /etc/ld.so.conf.d/openssl3.conf >/dev/null
+ sudo ldconfig
+ sudo apt-get install ${APT_OPTS} heimdal-dev
+
+ - name: Show versions
+ run: |
+ printf "$CC: " ; $CC --version
+ printf "\nmake: " ; make --version
+ printf "\nkrb5: " ; krb5-config --all || :
+ [ -d /opt/openssl ] && export PATH=/opt/openssl/bin:$PATH
+ printf "\nopenssl: " ; openssl version
+
+ - uses: actions/checkout@v3
+
+ - name: Build eapol_test
+ run: |
+ if [ -d /opt/openssl ]; then
+ # Used by scripts/ci/eapol_test-build.sh
+ export PATH=/opt/openssl/bin:$PATH
+ export EAPOL_TEST_CFLAGS="-I/opt/openssl/include"
+ export EAPOL_TEST_LDFLAGS="-L/opt/openssl/lib64"
+ fi
+ ./scripts/ci/eapol_test-build.sh
+
+ - name: Build FreeRADIUS
+ run: |
+ export PATH=$(echo "$PATH" | sed -e 's#:/home/linuxbrew/[^:]\+##g')
+ if [ -d /opt/openssl ]; then
+ export PATH=/opt/openssl/bin:$PATH
+ CONFIG_OPENSSL="--with-openssl-lib-dir=/opt/openssl/lib64 --with-openssl-include-dir=/opt/openssl/include"
+ fi
+
+ if [ $SANITIZER = "yes" ]; then
+ echo "Enabling sanitizers"
+ enable_sanitizers="--enable-address-sanitizer --enable-undefined-behaviour-sanitizer"
+ if [ "`uname`" != "Darwin" ]; then
+ enable_sanitizers="$enable_sanitizers --enable-leak-sanitizer"
+ fi
+ # TODO: libunbound is broken when built with LSAN/ASAN, let's disable it for now.
+ extra_cflags="--without-rlm_unbound"
+
+ # Temporary hack just to skip and see the result.
+ # memory leak in rlm_{ldap,rest} and problems in perl+llvm
+ rm -rf src/tests/modules/ldap/
+ rm -rf src/tests/modules/rest/
+ else
+ enable_sanitizers=""
+ extra_cflags=""
+ fi
+ CFLAGS="${BUILD_CFLAGS}" ./configure -C \
+ --enable-developer \
+ ${enable_sanitizers} \
+ $CONFIG_OPENSSL \
+ $extra_cflags \
+ --enable-werror \
+ --prefix=$HOME/freeradius \
+ --with-threads=$LIBS_OPTIONAL \
+ --with-udpfromto=$LIBS_OPTIONAL \
+ --with-openssl=$LIBS_OPTIONAL \
+ --with-pcre=$LIBS_OPTIONAL \
+ --enable-reproducible-builds=${REPRODUCIBLE}
+ make -j $(($(nproc) + 1))
+
+ - name: clang scan
+ run: |
+ make -j $(($(nproc) + 1)) scan && [ "$(find build/plist/ -name *.html)" = '' ]
+ if: ${{ matrix.env.CC == 'clang' }}
+
+ - name: "Clang Static Analyzer: Store assets on failure"
+ uses: actions/upload-artifact@v3
+ with:
+ name: clang-scan.tgz
+ path: build/plist/**/*.html
+ if: ${{ matrix.env.CC == 'clang' && failure() }}
+
+ - name: Add OpenResty repository
+ shell: bash
+ run: |
+ wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
+ echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list
+
+ sudo apt-get update
+
+ - name: Setup git
+ shell: bash
+ run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
+
+ - name: Install test requisites
+ run: |
+ # Temporarily replace ucf (for config merge) with cp since it's
+ # terribly slow!
+ sudo mv /usr/bin/ucf /usr/bin/ucf.disabled
+ sudo sh -c 'echo "#!/bin/sh" > /usr/bin/ucf'
+ sudo sh -c 'echo "shift && cp -v \$@" >> /usr/bin/ucf'
+ sudo chmod +x /usr/bin/ucf
+
+ sudo apt-get install ${APT_OPTS} \
+ apparmor-utils \
+ ldap-utils \
+ openresty \
+ slapd
+
+ sudo mv -f /usr/bin/ucf.disabled /usr/bin/ucf
+
+ - name: Database dependencies
+ run: |
+ sudo apt-get install ${APT_OPTS} \
+ mariadb-client \
+ postgresql-client
+
+ slapd
+
+ - name: Build certificates for REST tests
+ run: |
+ cp -r raddb/certs raddb/restcerts
+ cd ./raddb/restcerts && make ca && make server
+
+ - name: Setup test databases
+ run: |
+ for i in \
+ postgresql-setup.sh \
+ mysql-setup.sh \
+ openresty-setup.sh \
+ ldap-setup.sh \
+ ldap2-setup.sh; do
+
+ script="./scripts/ci/$i"
+ echo "Calling $i"
+ $script
+ done
+
+ - name: Configure test database access
+ run: |
+ mysql -h mariadb -uroot -e "CREATE USER 'radius'@'%' IDENTIFIED BY 'radpass';"
+ mysql -u root -h mariadb -e "GRANT ALL ON radius.* TO 'radius'; FLUSH PRIVILEGES;"
+
+ - name: Run tests
+ run: |
+ [ -d /opt/openssl ] && export PATH=/opt/openssl/bin:$PATH
+
+ openssl dhparam -out ./raddb/certs/dh -2 128 || \
+ openssl dhparam -out ./raddb/certs/dh -2 512 || \
+ true
+
+ make ci-test
+
+ - name: Show debug logs on failure
+ if: ${{ failure() }}
+ run: |
+ cat src/tests/radius.log || :
+
+ #
+ # If the CI has failed and the branch is ci-debug then start a tmate
+ # session. SSH rendezvous point is emited continuously in the job output.
+ #
+ - name: "Debug: Start tmate"
+ uses: mxschmitt/action-tmate@v3
+ with:
+ limit-access-to-actor: true
+ if: ${{ github.ref == 'refs/heads/ci-debug' && failure() }}
+
+##########################################################################################
+# FREERADIUS CORE DEVELOPERS ONLY
+##########################################################################################
+#
+# Direct push access to the main freeradius-server repo has been disabled in an attempt
+# to keep CI passing reliably.
+#
+# The code below will automatically push to the main repository if a commit passes CI in
+# your fork on a branch that exists in the main repository.
+#
+# The code below will only run if PERSONAL_ACCESS_TOKEN is defined in the repository
+# secrets for your fork of the freeradius-server repo.
+#
+# If the above CI checks pass then we auto-merge into the same branch in the
+# main FR repo (only on push) if the PERSONAL_ACCESS_TOKEN secret is defined, i.e. when
+# the actor claims to be a FreeRADIUS developer with push access.
+#
+# Personal access tokens can be generated via the GitHub website:
+#
+# - Click on the Profile menu (top right)
+# > Settings
+# > Developer settings
+# > Personal access tokens
+# > Generate New Token
+# - Next, add the following settings and scopes:
+# Note: FreeRADIUS CI Push
+# public_repo (checked)
+#
+# This will allow any git operations using this PERSONAL_ACCESS_TOKEN to commit code to any
+# public repository you have access to.
+#
+# As this PERSONAL_ACCESS_TOKEN will only ever be accessible from GitHub actions when they are
+# running from your fork of the FreeRADIUS repo, this shouldn't be a security issue.
+#
+# After generating your PERSONAL_ACCESS_TOKEN you will need to add it as a secret to your
+# repository.
+#
+# - Copy your new token
+# - Click on the Profile menu (top right)
+# > Your repositories
+# - Search for freeradius-server
+# > Click freeradius-server
+# - Click settings in the tabs on the left
+# - Click secrets in the menu items on the left
+# - Click New repository secret
+# - Name: PERSONAL_ACCESS_TOKEN
+# Value: <value you copied>
+# - Click Add secret
+ #
+ # Needed because secrets are not available for evaluation in if conditions
+ # at the job level, so we evaluate the existence of the PERSONAL_ACCESS_TOKEN secret
+ # within a step and export the result instead. We also extract the short
+ # branch name here because it's convenient to do so.
+ #
+ merge-preflight:
+ needs:
+ - ci
+ if: ( github.event_name == 'push' ) && ( github.repository_owner != 'FreeRADIUS' ) && ( github.ref == 'refs/heads/master' || github.ref == 'refs/heads/v3.2.x' )
+ name: "Merge preflight"
+ runs-on: ubuntu-latest
+ steps:
+ - name: "Report whether PERSONAL_ACCESS_TOKEN secret exists"
+ id: merge-preflight
+ run: |
+ [ -z "$PERSONAL_ACCESS_TOKEN" ] || echo "::set-output name=PERSONAL_ACCESS_TOKEN_EXISTS::1"
+ env:
+ PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
+ outputs:
+ PERSONAL_ACCESS_TOKEN_EXISTS: ${{ steps.merge-preflight.outputs.PERSONAL_ACCESS_TOKEN_EXISTS }}
+
+ merge-upstream:
+ needs:
+ - ci
+ - merge-preflight
+ if: needs.merge-preflight.outputs.PERSONAL_ACCESS_TOKEN_EXISTS == '1'
+ runs-on: ubuntu-latest
+ name: "Merge into upstream"
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ lfs: false
+ persist-credentials: false
+ # Note: This also opportunistically updates the developer's branch with commits from
+ # the main repository.
+ # This update may fail if the developer has pushed additional commits since the
+ # workflow started. This is normal, and we ignore the failure.
+ - name: "Merge into upstream dev branch and update local branch"
+ run: |
+ BRANCH=${GITHUB_REF#refs/heads/}
+ git remote add upstream https://$USERNAME:$REPO_KEY@github.com/FreeRADIUS/freeradius-server.git
+ git fetch --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/upstream/*
+ git checkout --progress --force -B upstream-branch "refs/remotes/upstream/$BRANCH"
+ git merge "$BRANCH" --ff-only
+ git push upstream "upstream-branch:$BRANCH"
+ git push origin "$BRANCH" || true
+ env:
+ USERNAME: ${{ github.actor }}
+ REPO_KEY: ${{ secrets.PERSONAL_ACCESS_TOKEN }}