From cfab8ef00c096839996abecd147fea2922f50ea8 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 9 Jul 2026 18:05:03 +0100 Subject: [PATCH 1/3] ci: improve coverage --- .github/workflows/test.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ef406396..045438f6f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -318,17 +318,15 @@ jobs: with: use_oidc: true flags: rs-e2e - files: ${{ github.workspace }}/cache/llvm-cov-target.json + files: | + ${{ github.workspace }}/cache/llvm-cov-target.json + ${{ github.workspace }}/cache/rs-e2e-coverage.lcov - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v5 if: ${{ always() }} with: use_oidc: true flags: rs-e2e - files: ${{ github.workspace }}/cache/llvm-cov-target.json + files: | + ${{ github.workspace }}/cache/llvm-cov-target.json + ${{ github.workspace }}/cache/rs-e2e-coverage.lcov report_type: test_results - - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v5 - if: ${{ always() }} - with: - use_oidc: true - flags: rs-e2e - files: ${{ github.workspace }}/cache/rs-e2e-coverage.lcov From f9165340367b0dcf6cc672b1cc779b6e6082222d Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 9 Jul 2026 21:35:22 +0100 Subject: [PATCH 2/3] build cov --- .github/workflows/_build-rs.yml | 9 +++++++++ Makefile | 3 +++ common.mk | 13 +++++++++++++ hack/rs-build-coverage-convert.sh | 23 +++++++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100755 hack/rs-build-coverage-convert.sh diff --git a/.github/workflows/_build-rs.yml b/.github/workflows/_build-rs.yml index 8f1bec88b..adcab1443 100644 --- a/.github/workflows/_build-rs.yml +++ b/.github/workflows/_build-rs.yml @@ -48,6 +48,7 @@ jobs: CARGO_TERM_COLOR: always permissions: contents: read + id-token: write outputs: artifact-id: ${{ steps.artifact.outputs.artifact-id }} steps: @@ -107,6 +108,14 @@ jobs: with: name: authentik_${{ matrix.platform }}_${{ matrix.target }}${{ inputs.artifact_suffix }} path: bin/ + - if: ${{ contains(inputs.rust_build_flags, 'instrument-coverage') }} + run: make rs-build-coverage-convert + - if: ${{ contains(inputs.rust_build_flags, 'instrument-coverage') }} + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v5 + with: + use_oidc: true + flags: rs-e2e-build-${{ matrix.target }} + files: ${{ github.workspace }}/cache/rs-build-coverage.lcov - uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4 if: always() with: diff --git a/Makefile b/Makefile index 447925062..90f89c9e3 100644 --- a/Makefile +++ b/Makefile @@ -112,6 +112,9 @@ test-e2e-convert: find ${PWD}/ak-platform-e2e/coverage $(call rs_e2e_coverage_convert) +rs-build-coverage-convert: + $(call rs_build_coverage_convert) + test-setup: go run -v ./cmd/cli setup -v http://authentik:9000 diff --git a/common.mk b/common.mk index dccc08d10..9584ae7be 100644 --- a/common.mk +++ b/common.mk @@ -57,6 +57,8 @@ endef ifeq ($(PLATFORM),gnu/linux) define cargo_build + rm -rf "$(CONTAINER_TOP)cache/build-profraw" + mkdir -p "$(CONTAINER_TOP)cache/build-profraw" docker run --rm \ -i \ --volume "$(CONTAINER_TOP):/workspace" \ @@ -65,6 +67,7 @@ define cargo_build --env AK_VERSION="${VERSION}" \ --env AK_BUILDHASH="${VERSION_HASH}" \ --env AK_TAG="${VERSION_TAG}" \ + --env LLVM_PROFILE_FILE="/workspace/cache/build-profraw/%m_%p.profraw" \ $(DOCKER_BUILDER_IMAGE) \ cargo build \ --target-dir /workspace/cache/shared \ @@ -134,6 +137,16 @@ define rs_e2e_coverage_convert fi endef +define rs_build_coverage_convert + mkdir -p "${PWD}/cache" + docker run --rm \ + -i \ + --volume "$(CONTAINER_TOP):/workspace" \ + --workdir /workspace \ + $(DOCKER_BUILDER_IMAGE) \ + bash hack/rs-build-coverage-convert.sh +endef + TME := docker exec authentik-platform_devcontainer-test-machine-1 define lint_shellcheck diff --git a/hack/rs-build-coverage-convert.sh b/hack/rs-build-coverage-convert.sh new file mode 100755 index 000000000..f281d917c --- /dev/null +++ b/hack/rs-build-coverage-convert.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail + +PROFRAW_FILES=$(find cache/build-profraw -name '*.profraw' 2>/dev/null | tr '\n' ' ') +BUILD_SCRIPT=$(find cache/shared/release/build -path '*/ak-cli-*/build-script-build' -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-) + +if [ -z "$PROFRAW_FILES" ] || [ -z "$BUILD_SCRIPT" ]; then + echo "No Rust build-time profraw/build-script binary found, creating empty coverage file" >&2 + touch cache/rs-build-coverage.lcov + exit 0 +fi + +HOST=$(rustc -vV | awk '/^host:/{print $2}') +TOOLCHAIN=$(rustup show active-toolchain | awk '{print $1}') +LLVM_DIR="$(rustup show home)/toolchains/${TOOLCHAIN}/lib/rustlib/${HOST}/bin" + +"${LLVM_DIR}/llvm-profdata" merge -sparse ${PROFRAW_FILES} -o cache/rs-build.profdata +"${LLVM_DIR}/llvm-cov" export \ + -format=lcov \ + -instr-profile=cache/rs-build.profdata \ + -object "${BUILD_SCRIPT}" \ + -ignore-filename-regex='generated|\.cargo' \ + > cache/rs-build-coverage.lcov From 1d32ad5ee81f5baea1a5e44986b1910e99ba0ef0 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 9 Jul 2026 21:41:58 +0100 Subject: [PATCH 3/3] cleanup --- Makefile | 4 ++- common.mk | 34 ++---------------- hack/rs-build-coverage-convert.sh | 23 ------------ hack/rs-coverage-convert.sh | 59 +++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 56 deletions(-) delete mode 100755 hack/rs-build-coverage-convert.sh create mode 100755 hack/rs-coverage-convert.sh diff --git a/Makefile b/Makefile index 90f89c9e3..e68056d57 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,9 @@ test-e2e-convert: echo "No Go in-container coverage found, skipping Go coverage conversion"; \ fi find ${PWD}/ak-platform-e2e/coverage - $(call rs_e2e_coverage_convert) + bash hack/rs-coverage-convert.sh "${PWD}/ak-platform-e2e/coverage/rs" rs-e2e \ + "${PWD}/bin/cli/ak" "${PWD}/bin/agent/ak-agent" \ + "${PWD}/bin/nss/libnss_authentik.so" "${PWD}/bin/pam/libpam_authentik.so" rs-build-coverage-convert: $(call rs_build_coverage_convert) diff --git a/common.mk b/common.mk index 9584ae7be..f571be1a8 100644 --- a/common.mk +++ b/common.mk @@ -106,37 +106,6 @@ define cargo_test --output-dir "${PWD}/cache/llvm-cov-html/" endef -define rs_e2e_coverage_convert - mkdir -p "${PWD}/cache" - PROFRAW_FILES=$$(find "${PWD}/ak-platform-e2e/coverage/rs" -name '*.profraw' 2>/dev/null | tr '\n' ' '); \ - if [ -z "$$PROFRAW_FILES" ]; then \ - echo "No Rust profraw files found in ak-platform-e2e/coverage/rs, creating empty coverage file"; \ - touch "${PWD}/cache/rs-e2e-coverage.lcov"; \ - else \ - HOST=$$(rustc -vV 2>/dev/null | awk '/^host:/{print $$2}'); \ - TOOLCHAIN=$$(rustup show active-toolchain 2>/dev/null | awk '{print $$1}'); \ - LLVM_DIR=$$(rustup show home 2>/dev/null)/toolchains/$$TOOLCHAIN/lib/rustlib/$$HOST/bin; \ - $$LLVM_DIR/llvm-profdata merge -sparse $$PROFRAW_FILES \ - -o "${PWD}/cache/rs-e2e-merged.profdata"; \ - OBJECTS=""; \ - for bin in "${PWD}/bin/cli/ak" "${PWD}/bin/agent/ak-agent" \ - "${PWD}/bin/nss/libnss_authentik.so" "${PWD}/bin/pam/libpam_authentik.so"; do \ - if [ -f "$$bin" ]; then OBJECTS="$$OBJECTS -object $$bin"; fi; \ - done; \ - if [ -z "$$OBJECTS" ]; then \ - echo "No instrumented Rust binaries found in bin/, creating empty coverage file"; \ - touch "${PWD}/cache/rs-e2e-coverage.lcov"; \ - else \ - $$LLVM_DIR/llvm-cov export \ - -format=lcov \ - -instr-profile="${PWD}/cache/rs-e2e-merged.profdata" \ - $$OBJECTS \ - -ignore-filename-regex='generated|\.cargo' \ - > "${PWD}/cache/rs-e2e-coverage.lcov"; \ - fi; \ - fi -endef - define rs_build_coverage_convert mkdir -p "${PWD}/cache" docker run --rm \ @@ -144,7 +113,8 @@ define rs_build_coverage_convert --volume "$(CONTAINER_TOP):/workspace" \ --workdir /workspace \ $(DOCKER_BUILDER_IMAGE) \ - bash hack/rs-build-coverage-convert.sh + bash hack/rs-coverage-convert.sh cache/build-profraw rs-build \ + "newest:cache/shared/release/build:*/ak-cli-*/build-script-build" endef TME := docker exec authentik-platform_devcontainer-test-machine-1 diff --git a/hack/rs-build-coverage-convert.sh b/hack/rs-build-coverage-convert.sh deleted file mode 100755 index f281d917c..000000000 --- a/hack/rs-build-coverage-convert.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -set -euo pipefail - -PROFRAW_FILES=$(find cache/build-profraw -name '*.profraw' 2>/dev/null | tr '\n' ' ') -BUILD_SCRIPT=$(find cache/shared/release/build -path '*/ak-cli-*/build-script-build' -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-) - -if [ -z "$PROFRAW_FILES" ] || [ -z "$BUILD_SCRIPT" ]; then - echo "No Rust build-time profraw/build-script binary found, creating empty coverage file" >&2 - touch cache/rs-build-coverage.lcov - exit 0 -fi - -HOST=$(rustc -vV | awk '/^host:/{print $2}') -TOOLCHAIN=$(rustup show active-toolchain | awk '{print $1}') -LLVM_DIR="$(rustup show home)/toolchains/${TOOLCHAIN}/lib/rustlib/${HOST}/bin" - -"${LLVM_DIR}/llvm-profdata" merge -sparse ${PROFRAW_FILES} -o cache/rs-build.profdata -"${LLVM_DIR}/llvm-cov" export \ - -format=lcov \ - -instr-profile=cache/rs-build.profdata \ - -object "${BUILD_SCRIPT}" \ - -ignore-filename-regex='generated|\.cargo' \ - > cache/rs-build-coverage.lcov diff --git a/hack/rs-coverage-convert.sh b/hack/rs-coverage-convert.sh new file mode 100755 index 000000000..d16fa2a16 --- /dev/null +++ b/hack/rs-coverage-convert.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -euo pipefail + +# Usage: rs-coverage-convert.sh [object ...] +# +# Each trailing "object" is either a plain path to an instrumented binary/library +# (included if it exists), or "newest::" to resolve to +# the most-recently-modified file under matching +# (used to find Cargo's hashed build-script-build output). + +PROFRAW_DIR="$1" +OUTPUT_BASENAME="$2" +shift 2 + +mkdir -p "${PWD}/cache" + +PROFRAW_FILES=$(find "$PROFRAW_DIR" -name '*.profraw' 2>/dev/null | tr '\n' ' ') + +if [ -z "$PROFRAW_FILES" ]; then + echo "No Rust profraw files found in ${PROFRAW_DIR}, creating empty coverage file" + touch "${PWD}/cache/${OUTPUT_BASENAME}-coverage.lcov" + exit 0 +fi + +OBJECTS="" +for arg in "$@"; do + case "$arg" in + newest:*) + spec="${arg#newest:}" + search_dir="${spec%%:*}" + path_pattern="${spec#*:}" + resolved=$(find "$search_dir" -path "$path_pattern" -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-) + if [ -n "$resolved" ]; then OBJECTS="$OBJECTS -object $resolved"; fi + ;; + *) + if [ -f "$arg" ]; then OBJECTS="$OBJECTS -object $arg"; fi + ;; + esac +done + +if [ -z "$OBJECTS" ]; then + echo "No instrumented Rust binaries found, creating empty coverage file" + touch "${PWD}/cache/${OUTPUT_BASENAME}-coverage.lcov" + exit 0 +fi + +HOST=$(rustc -vV 2>/dev/null | awk '/^host:/{print $2}') +TOOLCHAIN=$(rustup show active-toolchain 2>/dev/null | awk '{print $1}') +LLVM_DIR="$(rustup show home 2>/dev/null)/toolchains/${TOOLCHAIN}/lib/rustlib/${HOST}/bin" + +"${LLVM_DIR}/llvm-profdata" merge -sparse ${PROFRAW_FILES} \ + -o "${PWD}/cache/${OUTPUT_BASENAME}-merged.profdata" + +"${LLVM_DIR}/llvm-cov" export \ + -format=lcov \ + -instr-profile="${PWD}/cache/${OUTPUT_BASENAME}-merged.profdata" \ + ${OBJECTS} \ + -ignore-filename-regex='generated|\.cargo' \ + > "${PWD}/cache/${OUTPUT_BASENAME}-coverage.lcov"