On 08/04/2025 20:09, Ihor Solodrai wrote: > On 4/1/25 2:24 AM, Alan Maguire wrote: >> Borrowing heavily from libbpf github actions, add workflows to >> >> - build dwarves for gcc, LLVM >> >> - build dwarves for x86_64/aarch64 and use it to build a Linux >> kernel including BTF generation; then run dwarves selftests >> using generated vmlinux >> >> These workflows trigger on all pushes. This will allow both >> developers working on dwarves to push a branch to their github >> repo and test, and also for maintainer pushes from git.kernel.org >> pahole repo to trigger tests. >> >> The build/test workflows can also be run as bash scripts locally, >> as is described in the toplevel README. >> >> Similar to libbpf, additional workflows for coverity etc >> are triggered for pushes to master/next. >> >> Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx> > > Hi Alan. Thanks for addressing my comments. > > Acked-by: Ihor Solodrai <ihor.solodrai@xxxxxxxxx> > > Some nits and questions below. > thanks for the feedback! replies below.. >> --- >> .github/scripts/build-debian.sh | 92 ++++++++++++++++++++++++++++++++ >> .github/scripts/build-kernel.sh | 35 ++++++++++++ >> .github/scripts/build-pahole.sh | 17 ++++++ >> .github/scripts/run-selftests.sh | 15 ++++++ >> .github/scripts/travis_wait.bash | 61 +++++++++++++++++++++ >> .github/workflows/build.yml | 34 ++++++++++++ >> .github/workflows/codeql.yml | 53 ++++++++++++++++++ >> .github/workflows/coverity.yml | 33 ++++++++++++ >> .github/workflows/lint.yml | 20 +++++++ >> .github/workflows/ondemand.yml | 31 +++++++++++ >> .github/workflows/test.yml | 36 +++++++++++++ >> .github/workflows/vmtest.yml | 62 +++++++++++++++++++++ >> README | 18 +++++++ >> 13 files changed, 507 insertions(+) >> create mode 100755 .github/scripts/build-debian.sh >> create mode 100755 .github/scripts/build-kernel.sh >> create mode 100755 .github/scripts/build-pahole.sh >> create mode 100755 .github/scripts/run-selftests.sh >> create mode 100755 .github/scripts/travis_wait.bash >> create mode 100644 .github/workflows/build.yml >> create mode 100644 .github/workflows/codeql.yml >> create mode 100644 .github/workflows/coverity.yml >> create mode 100644 .github/workflows/lint.yml >> create mode 100644 .github/workflows/ondemand.yml >> create mode 100644 .github/workflows/test.yml >> create mode 100644 .github/workflows/vmtest.yml >> >> diff --git a/.github/scripts/build-debian.sh b/.github/scripts/build-debian.sh >> new file mode 100755 >> index 0000000..5a0789a >> --- /dev/null >> +++ b/.github/scripts/build-debian.sh >> @@ -0,0 +1,92 @@ >> +#!/bin/bash >> +# SPDX-License-Identifier: GPL-2.0-only >> +# >> +# Copyright (c) 2025, Oracle and/or its affiliates. >> +# >> + >> +PHASES=(${@:-SETUP RUN CLEANUP}) >> +DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}" >> +CONT_NAME="${CONT_NAME:-dwarves-debian-$DEBIAN_RELEASE}" >> +ENV_VARS="${ENV_VARS:-}" >> +DOCKER_RUN="${DOCKER_RUN:-docker run}" >> +REPO_ROOT="${REPO_ROOT:-$PWD}" >> +ADDITIONAL_DEPS=(pkgconf) >> +EXTRA_CFLAGS="" >> +EXTRA_LDFLAGS="" >> + >> +function info() { >> + echo -e "\033[33;1m$1\033[0m" >> +} >> + >> +function error() { >> + echo -e "\033[31;1m$1\033[0m" >> +} >> + >> +function docker_exec() { >> + docker exec $ENV_VARS $CONT_NAME "$@" >> +} >> + >> +set -eu >> + >> +source "$(dirname $0)/travis_wait.bash" >> + >> +for phase in "${PHASES[@]}"; do >> + case $phase in >> + SETUP) >> + info "Setup phase" >> + info "Using Debian $DEBIAN_RELEASE" >> + >> + docker --version >> + >> + docker pull debian:$DEBIAN_RELEASE >> + info "Starting container $CONT_NAME" >> + $DOCKER_RUN -v $REPO_ROOT:/build:rw \ >> + -w /build --privileged=true --name $CONT_NAME \ >> + -dit --net=host debian:$DEBIAN_RELEASE /bin/bash >> + echo -e "::group::Build Env Setup" >> + >> + docker_exec apt-get -y update >> + docker_exec apt-get -y install aptitude >> + docker_exec aptitude -y install make cmake libz-dev libelf-dev libdw-dev git >> + docker_exec aptitude -y install "${ADDITIONAL_DEPS[@]}" >> + echo -e "::endgroup::" >> + ;; >> + RUN|RUN_CLANG|RUN_CLANG16|RUN_GCC12) >> + CC="cc" >> + if [[ "$phase" =~ "RUN_CLANG(\d+)(_ASAN)?" ]]; then >> + ENV_VARS="-e CC=clang-${BASH_REMATCH[1]} -e CXX=clang++-${BASH_REMATCH[1]}" >> + CC="clang-${BASH_REMATCH[1]}" >> + elif [[ "$phase" = *"CLANG"* ]]; then >> + ENV_VARS="-e CC=clang -e CXX=clang++" >> + CC="clang" >> + elif [[ "$phase" =~ "RUN_GCC(\d+)(_ASAN)?" ]]; then >> + ENV_VARS="-e CC=gcc-${BASH_REMATCH[1]} -e CXX=g++-${BASH_REMATCH[1]}" >> + CC="gcc-${BASH_REMATCH[1]}" >> + fi >> + if [[ "$CC" != "cc" ]]; then >> + docker_exec aptitude -y install "$CC" >> + else >> + docker_exec aptitude -y install gcc >> + fi >> + git config --global --add safe.directory $REPO_ROOT >> + pushd $REPO_ROOT >> + git submodule update --init >> + popd >> + docker_exec mkdir build install >> + docker_exec ${CC} --version >> + info "build" >> + docker_exec cmake -DGIT_SUBMODULE=OFF . >> + docker_exec make -j$((4*$(nproc))) >> + info "install" >> + docker_exec make DESTDIR=../install install >> + ;; >> + CLEANUP) >> + info "Cleanup phase" >> + docker stop $CONT_NAME >> + docker rm -f $CONT_NAME >> + ;; >> + *) >> + echo >&2 "Unknown phase '$phase'" >> + exit 1 >> + esac >> +done >> diff --git a/.github/scripts/build-kernel.sh b/.github/scripts/build-kernel.sh >> new file mode 100755 >> index 0000000..41a3cf8 >> --- /dev/null >> +++ b/.github/scripts/build-kernel.sh >> @@ -0,0 +1,35 @@ >> +#!/usr/bin/bash >> +# SPDX-License-Identifier: GPL-2.0-only >> +# >> +# Copyright (c) 2025, Oracle and/or its affiliates. >> +# >> + >> +GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$(dirname $0)/../..} >> +INPUTS_ARCH=${INPUTS_ARCH:-$(uname -m)} >> +REPO=${REPO:-https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git} >> +REPO_BRANCH=${REPO_BRANCH:-master} >> +REPO_TARGET=${GITHUB_WORKSPACE}/.kernel >> + >> +export PATH=${GITHUB_WORKSPACE}/install/usr/local/bin:${PATH} >> +export PAHOLE=${GITHUB_WORKSPACE}/install/usr/local/bin/pahole >> + >> +which pahole >> +$PAHOLE --version >> + >> +if [[ ! -d $REPO_TARGET ]]; then >> + git clone $REPO $REPO_TARGET >> +fi >> +cd $REPO_TARGET >> +git checkout $REPO_BRANCH >> + >> +cat tools/testing/selftests/bpf/config \ >> + tools/testing/selftests/bpf/config.${INPUTS_ARCH} > .config >> +# this file might or might not exist depending on kernel version >> +if [[ -f tools/testing/selftests/bpf/config.vm ]]; then >> + cat tools/testing/selftests/bpf/config.vm >> .config >> +fi >> +make olddefconfig && make prepare >> +grep PAHOLE .config >> +grep _BTF .config > > This looks like debugging code, but instead of removing it I think it > is useful to dump entire config to the output (hence job log) in case > something goes wrong. How about `cat .config` before make > olddefconfig? > Sounds good, but would doing it after "make olddefconfig" be more informative maybe since some additional values may be set? >> +make -j $((4*$(nproc))) all >> + >> diff --git a/.github/scripts/build-pahole.sh b/.github/scripts/build-pahole.sh >> new file mode 100755 >> index 0000000..64f9eea >> --- /dev/null >> +++ b/.github/scripts/build-pahole.sh >> @@ -0,0 +1,17 @@ >> +#!/usr/bin/bash >> +# SPDX-License-Identifier: GPL-2.0-only >> +# >> +# Copyright (c) 2025, Oracle and/or its affiliates. >> +# >> + >> +GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$(dirname $0)/../..} >> +cd $GITHUB_WORKSPACE >> +git config --global --add safe.directory $GITHUB_WORKSPACE >> +git submodule update --init >> +mkdir -p build >> +cd build >> +pwd >> +cmake -DGIT_SUBMODULE=OFF -DBUILD_SHARED_LIBS=OFF .. > > With these cmake options, what version of libbpf is used? > > On CI a build/test of both static and shared variants should be > tested, ideally. But that doesn't have to be a part of this patchset. > Good idea; I think we'll follow up with that as it is somewhat dependent on what shared library versions of libbpf we have available. >> +make -j$((4*$(nproc))) all >> +make DESTDIR=../install install >> + >> diff --git a/.github/scripts/run-selftests.sh b/.github/scripts/run-selftests.sh >> new file mode 100755 >> index 0000000..f9ba24e >> --- /dev/null >> +++ b/.github/scripts/run-selftests.sh >> @@ -0,0 +1,15 @@ >> +#!/usr/bin/bash >> +# SPDX-License-Identifier: GPL-2.0-only >> +# >> +# Copyright (c) 2025, Oracle and/or its affiliates. >> +# >> + >> +GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$(pwd)} >> +VMLINUX=${GITHUB_WORKSPACE}/.kernel/vmlinux >> +SELFTESTS=${GITHUB_WORKSPACE}/tests >> +cd $SELFTESTS >> +export PATH=${GITHUB_WORKSPACE}/install/usr/local/bin:${PATH} >> +which pahole >> +pahole --version >> +vmlinux=$VMLINUX ./tests >> + >> diff --git a/.github/scripts/travis_wait.bash b/.github/scripts/travis_wait.bash >> new file mode 100755 >> index 0000000..acf6ad1 >> --- /dev/null >> +++ b/.github/scripts/travis_wait.bash >> @@ -0,0 +1,61 @@ >> +# This was borrowed from https://github.com/travis-ci/travis-build/tree/master/lib/travis/build/bash >> +# to get around https://github.com/travis-ci/travis-ci/issues/9979. It should probably be removed >> +# as soon as Travis CI has started to provide an easy way to export the functions to bash scripts. > > This comment makes me think travis_wait.bash could be removed. > Do you know if it's actually necessary (for build-debian.sh)? > I tried removing it, and if I recall the github action fell over without a pause between setup and build, so I think it's still needed. >> + >> +travis_jigger() { >> + local cmd_pid="${1}" >> + shift >> + local timeout="${1}" >> + shift >> + local count=0 >> + >> + echo -e "\\n" >> + >> + while [[ "${count}" -lt "${timeout}" ]]; do >> + count="$((count + 1))" >> + echo -ne "Still running (${count} of ${timeout}): ${*}\\r" >> + sleep 60 >> + done >> + >> + echo -e "\\n${ANSI_RED}Timeout (${timeout} minutes) reached. Terminating \"${*}\"${ANSI_RESET}\\n" >> + kill -9 "${cmd_pid}" >> +} >> + >> +travis_wait() { >> + local timeout="${1}" >> + >> + if [[ "${timeout}" =~ ^[0-9]+$ ]]; then >> + shift >> + else >> + timeout=20 >> + fi >> + >> + local cmd=("${@}") >> + local log_file="travis_wait_${$}.log" >> + >> + "${cmd[@]}" &>"${log_file}" & >> + local cmd_pid="${!}" >> + >> + travis_jigger "${!}" "${timeout}" "${cmd[@]}" & >> + local jigger_pid="${!}" >> + local result >> + >> + { >> + set +e >> + wait "${cmd_pid}" 2>/dev/null >> + result="${?}" >> + ps -p"${jigger_pid}" &>/dev/null && kill "${jigger_pid}" >> + set -e >> + } >> + >> + if [[ "${result}" -eq 0 ]]; then >> + echo -e "\\n${ANSI_GREEN}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}" >> + else >> + echo -e "\\n${ANSI_RED}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}" >> + fi >> + >> + echo -e "\\n${ANSI_GREEN}Log:${ANSI_RESET}\\n" >> + cat "${log_file}" >> + >> + return "${result}" >> +} >> diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml >> new file mode 100644 >> index 0000000..25a395f >> --- /dev/null >> +++ b/.github/workflows/build.yml >> @@ -0,0 +1,34 @@ >> +name: dwarves-build >> + >> +on: >> + pull_request: >> + push: >> + schedule: >> + - cron: '0 18 * * *' >> + >> +concurrency: >> + group: ci-build-${{ github.head_ref }} >> + cancel-in-progress: true >> + >> +jobs: >> + >> + debian: >> + runs-on: ubuntu-latest >> + name: Debian Build (${{ matrix.name }}) >> + strategy: >> + fail-fast: false >> + matrix: >> + include: >> + - name: default >> + target: RUN >> + - name: gcc-12 >> + target: RUN_GCC12 >> + - name: clang >> + target: RUN_CLANG >> + steps: >> + - uses: actions/checkout@v4 >> + name: Checkout >> + - name: setup >> + shell: bash >> + run: ./.github/scripts/build-debian.sh SETUP ${{ matrix.target }} >> + >> diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml >> new file mode 100644 >> index 0000000..a140be1 >> --- /dev/null >> +++ b/.github/workflows/codeql.yml >> @@ -0,0 +1,53 @@ >> +--- >> +# vi: ts=2 sw=2 et: >> + >> +name: "CodeQL" >> + >> +on: >> + push: >> + branches: >> + - master >> + pull_request: >> + branches: >> + - master >> + - next >> + >> +permissions: >> + contents: read >> + >> +jobs: >> + analyze: >> + name: Analyze >> + runs-on: ubuntu-latest >> + concurrency: >> + group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }} >> + cancel-in-progress: true >> + permissions: >> + actions: read >> + security-events: write >> + >> + strategy: >> + fail-fast: false >> + matrix: >> + language: ['cpp', 'python'] >> + >> + steps: >> + - name: Checkout repository >> + uses: actions/checkout@v4 >> + >> + - name: Initialize CodeQL >> + uses: github/codeql-action/init@v2 >> + with: >> + languages: ${{ matrix.language }} >> + queries: +security-extended,security-and-quality >> + >> + - name: Setup >> + uses: ./.github/actions/setup >> + >> + - name: Build >> + run: | >> + source /tmp/ci_setup >> + make -C ./src >> + >> + - name: Perform CodeQL Analysis >> + uses: github/codeql-action/analyze@v2 >> diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml >> new file mode 100644 >> index 0000000..97a04d4 >> --- /dev/null >> +++ b/.github/workflows/coverity.yml >> @@ -0,0 +1,33 @@ >> +name: dwarves-ci-coverity >> + >> +on: >> + push: >> + branches: >> + - master >> + - next >> + schedule: >> + - cron: '0 18 * * *' >> + >> +jobs: >> + coverity: >> + runs-on: ubuntu-latest >> + name: Coverity >> + env: >> + COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} >> + steps: >> + - uses: actions/checkout@v4 >> + - uses: ./.github/actions/setup >> + - name: Run coverity >> + if: ${{ env.COVERITY_SCAN_TOKEN }} >> + run: | >> + source /tmp/ci_setup >> + export COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}" >> + export COVERITY_SCAN_BRANCH_PATTERN=${GITHUB_REF##refs/*/} >> + export TRAVIS_BRANCH=${COVERITY_SCAN_BRANCH_PATTERN} >> + scripts/coverity.sh >> + env: >> + COVERITY_SCAN_PROJECT_NAME: dwarves >> + COVERITY_SCAN_BUILD_COMMAND_PREPEND: 'cmake .' >> + COVERITY_SCAN_BUILD_COMMAND: 'make' >> + - name: SCM log >> + run: cat /home/runner/work/dwarves/cov-int/scm_log.txt >> diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml >> new file mode 100644 >> index 0000000..ca13052 >> --- /dev/null >> +++ b/.github/workflows/lint.yml >> @@ -0,0 +1,20 @@ >> +name: "lint" >> + >> +on: >> + pull_request: >> + push: >> + branches: >> + - master >> + - next >> + >> +jobs: >> + shellcheck: >> + name: ShellCheck >> + runs-on: ubuntu-latest >> + steps: >> + - name: Checkout repository >> + uses: actions/checkout@v4 >> + - name: Run ShellCheck >> + uses: ludeeus/action-shellcheck@master >> + env: >> + SHELLCHECK_OPTS: --severity=error >> diff --git a/.github/workflows/ondemand.yml b/.github/workflows/ondemand.yml >> new file mode 100644 >> index 0000000..5f3034f >> --- /dev/null >> +++ b/.github/workflows/ondemand.yml >> @@ -0,0 +1,31 @@ >> +name: ondemand >> + >> +on: >> + workflow_dispatch: >> + inputs: >> + arch: >> + default: 'x86_64' >> + required: true >> + llvm-version: >> + default: '18' >> + required: true >> + kernel: >> + default: 'LATEST' >> + required: true >> + pahole: >> + default: "master" >> + required: true >> + runs-on: >> + default: 'ubuntu-24.04' >> + required: true >> + >> +jobs: >> + vmtest: >> + name: ${{ inputs.kernel }} kernel llvm-${{ inputs.llvm-version }} pahole@${{ inputs.pahole }} >> + uses: ./.github/workflows/vmtest.yml >> + with: >> + runs_on: ${{ inputs.runs-on }} >> + kernel: ${{ inputs.kernel }} >> + arch: ${{ inputs.arch }} >> + llvm-version: ${{ inputs.llvm-version }} >> + pahole: ${{ inputs.pahole }} >> diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml >> new file mode 100644 >> index 0000000..f11ebfe >> --- /dev/null >> +++ b/.github/workflows/test.yml >> @@ -0,0 +1,36 @@ >> +name: dwarves-ci >> + >> +on: >> + pull_request: >> + push: >> + schedule: >> + - cron: '0 18 * * *' >> + >> +concurrency: >> + group: ci-test-${{ github.head_ref }} >> + cancel-in-progress: true >> + >> +jobs: >> + vmtest: >> + strategy: >> + fail-fast: false >> + matrix: >> + include: >> + - kernel: 'LATEST' >> + runs_on: 'ubuntu-24.04' >> + arch: 'x86_64' >> + llvm-version: '18' >> + pahole: 'master' >> + - kernel: 'LATEST' >> + runs_on: 'ubuntu-24.04-arm' >> + arch: 'aarch64' >> + llvm-version: '18' >> + pahole: 'tmp.master' >> + name: Linux ${{ matrix.kernel }} >> + uses: ./.github/workflows/vmtest.yml >> + with: >> + runs_on: ${{ matrix.runs_on }} >> + kernel: ${{ matrix.kernel }} >> + arch: ${{ matrix.arch }} >> + llvm-version: ${{ matrix.llvm-version }} >> + pahole: ${{ matrix.pahole }} >> diff --git a/.github/workflows/vmtest.yml b/.github/workflows/vmtest.yml >> new file mode 100644 >> index 0000000..0f66eed >> --- /dev/null >> +++ b/.github/workflows/vmtest.yml >> @@ -0,0 +1,62 @@ >> +name: 'Build kernel run selftests via vmtest' >> + >> +on: >> + workflow_call: >> + inputs: >> + runs_on: >> + required: true >> + default: 'ubuntu-24.04' >> + type: string >> + arch: >> + description: 'what arch to test' >> + required: true >> + default: 'x86_64' >> + type: string >> + kernel: >> + description: 'kernel version or LATEST' >> + required: true >> + default: 'LATEST' >> + type: string >> + pahole: >> + description: 'pahole rev or branch' >> + required: false >> + default: 'master' >> + type: string >> + llvm-version: >> + description: 'llvm version' >> + required: false >> + default: '18' >> + type: string >> +jobs: >> + vmtest: >> + name: pahole@${{ inputs.arch }} >> + runs-on: ${{ inputs.runs_on }} >> + steps: >> + >> + - uses: actions/checkout@v4 >> + >> + - name: Setup environment >> + uses: libbpf/ci/setup-build-env@v3 >> + with: >> + pahole: ${{ inputs.pahole }} >> + arch: ${{ inputs.arch }} >> + llvm-version: ${{ inputs.llvm-version }} > > I think I mentioned it before, but libbpf/ci/setup-build-env checks > out and installs pahole too, which is unnecessary here. Have you tried > removing this step from the job? > > You should be able to reuse a piece of SETUP logic from > build-debian.sh to install pahole's dependencies. Although you kernel > build deps are needed too. > Yeah it's the latter that are needed I think. > I could make a change in libbpf/ci/setup-build-env to accept a special > `pahole` input value or check for env variable to NOT build pahole. > What do you think? That would be great! Something like "pahole: none"? I'll probably try and land this more or less as-is as we're hoping to get 1.30 out the door this week, but definitely will follow up with builds with shared library libbpf etc. Thanks for taking a look! Alan