From e3de6420625744a210f4f7f8845f9a8329149030 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 19 Jan 2025 22:35:21 +0100 Subject: [PATCH] Revert "ci: remove code coverage jobs" This reverts commit ca92bff41bd713878fba25c8d4bc8b47f0d504c7. --- .github/workflows/CICD.yml | 126 +++++++++++++++++++++++++++++++++ .github/workflows/GnuTests.yml | 74 +++++++++++++++++++ 2 files changed, 200 insertions(+) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index c10ad18a21..815a4a87e1 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -952,6 +952,132 @@ jobs: name: toybox-result.json path: ${{ steps.vars.outputs.TEST_SUMMARY_FILE }} + coverage: + name: Code Coverage + runs-on: ${{ matrix.job.os }} + timeout-minutes: 90 + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + strategy: + fail-fast: false + matrix: + job: + - { os: ubuntu-latest , features: unix, toolchain: nightly } + - { os: macos-latest , features: macos, toolchain: nightly } + # FIXME: Re-enable Code Coverage on windows, which currently fails due to "profiler_builtins". See #6686. + # - { os: windows-latest , features: windows, toolchain: nightly-x86_64-pc-windows-gnu } + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.job.toolchain }} + components: rustfmt + - uses: taiki-e/install-action@nextest + - uses: taiki-e/install-action@grcov + - uses: Swatinem/rust-cache@v2 + - name: Run sccache-cache + uses: mozilla-actions/sccache-action@v0.0.6 + # - name: Reattach HEAD ## may be needed for accurate code coverage info + # run: git checkout ${{ github.head_ref }} + - name: Initialize workflow variables + id: vars + shell: bash + run: | + ## VARs setup + outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; } + # toolchain + TOOLCHAIN="nightly" ## default to "nightly" toolchain (required for certain required unstable compiler flags) ## !maint: refactor when stable channel has needed support + # * specify gnu-type TOOLCHAIN for windows; `grcov` requires gnu-style code coverage data files + case ${{ matrix.job.os }} in windows-*) TOOLCHAIN="$TOOLCHAIN-x86_64-pc-windows-gnu" ;; esac; + # * use requested TOOLCHAIN if specified + if [ -n "${{ matrix.job.toolchain }}" ]; then TOOLCHAIN="${{ matrix.job.toolchain }}" ; fi + outputs TOOLCHAIN + # target-specific options + # * CARGO_FEATURES_OPTION + CARGO_FEATURES_OPTION='--all-features' ; ## default to '--all-features' for code coverage + if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features=${{ matrix.job.features }}' ; fi + outputs CARGO_FEATURES_OPTION + # * CODECOV_FLAGS + CODECOV_FLAGS=$( echo "${{ matrix.job.os }}" | sed 's/[^[:alnum:]]/_/g' ) + outputs CODECOV_FLAGS + - name: Install/setup prerequisites + shell: bash + run: | + ## Install/setup prerequisites + case '${{ matrix.job.os }}' in + macos-latest) brew install coreutils ;; # needed for testing + esac + case '${{ matrix.job.os }}' in + ubuntu-latest) + # pinky is a tool to show logged-in users from utmp, and gecos fields from /etc/passwd. + # In GitHub Action *nix VMs, no accounts log in, even the "runner" account that runs the commands. The account also has empty gecos fields. + # To work around this for pinky tests, we create a fake login entry for the GH runner account... + FAKE_UTMP='[7] [999999] [tty2] [runner] [tty2] [] [0.0.0.0] [2022-02-22T22:22:22,222222+00:00]' + # ... by dumping the login records, adding our fake line, then reverse dumping ... + (utmpdump /var/run/utmp ; echo $FAKE_UTMP) | sudo utmpdump -r -o /var/run/utmp + # ... and add a full name to each account with a gecos field but no full name. + sudo sed -i 's/:,/:runner name,/' /etc/passwd + # We also create a couple optional files pinky looks for + touch /home/runner/.project + echo "foo" > /home/runner/.plan + ;; + esac + case '${{ matrix.job.os }}' in + # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368 + windows-latest) C:/msys64/usr/bin/pacman.exe -Sy --needed mingw-w64-x86_64-gcc --noconfirm ; echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH ;; + esac + - name: Initialize toolchain-dependent workflow variables + id: dep_vars + shell: bash + run: | + ## Dependent VARs setup + outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; } + # * determine sub-crate utility list + UTILITY_LIST="$(./util/show-utils.sh ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }})" + CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo -n "-puu_${u} "; done;)" + outputs CARGO_UTILITY_LIST_OPTIONS + - name: Test + run: cargo nextest run --profile ci --hide-progress-bar ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils + env: + RUSTC_WRAPPER: "" + RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" + RUSTDOCFLAGS: "-Cpanic=abort" + RUST_BACKTRACE: "1" + # RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }} + - name: Test individual utilities + run: cargo nextest run --profile ci --hide-progress-bar ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }} + env: + RUSTC_WRAPPER: "" + RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" + RUSTDOCFLAGS: "-Cpanic=abort" + RUST_BACKTRACE: "1" + # RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }} + - name: Generate coverage data (via `grcov`) + id: coverage + shell: bash + run: | + ## Generate coverage data + COVERAGE_REPORT_DIR="target/debug" + COVERAGE_REPORT_FILE="${COVERAGE_REPORT_DIR}/lcov.info" + # GRCOV_IGNORE_OPTION='--ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*"' ## `grcov` ignores these params when passed as an environment variable (why?) + # GRCOV_EXCLUDE_OPTION='--excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()"' ## `grcov` ignores these params when passed as an environment variable (why?) + mkdir -p "${COVERAGE_REPORT_DIR}" + # display coverage files + grcov . --output-type files --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" | sort --unique + # generate coverage report + grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" + echo "report=${COVERAGE_REPORT_FILE}" >> $GITHUB_OUTPUT + - name: Upload coverage results (to Codecov.io) + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ${{ steps.coverage.outputs.report }} + ## flags: IntegrationTests, UnitTests, ${{ steps.vars.outputs.CODECOV_FLAGS }} + flags: ${{ steps.vars.outputs.CODECOV_FLAGS }} + name: codecov-umbrella + fail_ci_if_error: false + test_separately: name: Separate Builds runs-on: ${{ matrix.os }} diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml index e4a2558fb9..4fcc332dfc 100644 --- a/.github/workflows/GnuTests.yml +++ b/.github/workflows/GnuTests.yml @@ -360,3 +360,77 @@ jobs: else echo "::warning ::Skipping test summary comparison; no prior reference summary is available." fi + + gnu_coverage: + name: Run GNU tests with coverage + runs-on: ubuntu-24.04 + steps: + - name: Checkout code uutil + uses: actions/checkout@v4 + with: + path: 'uutils' + - name: Checkout GNU coreutils + uses: actions/checkout@v4 + with: + repository: 'coreutils/coreutils' + path: 'gnu' + ref: 'v9.5' + submodules: recursive + - uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly + components: rustfmt + - uses: taiki-e/install-action@grcov + - uses: Swatinem/rust-cache@v2 + with: + workspaces: "./uutils -> target" + - name: Install dependencies + run: | + ## Install dependencies + sudo apt-get update + sudo apt-get install -y autoconf autopoint bison texinfo gperf gcc g++ gdb python3-pyinotify jq valgrind libexpect-perl libacl1-dev libattr1-dev libcap-dev libselinux1-dev attr + - name: Add various locales + run: | + ## Add various locales + echo "Before:" + locale -a + ## Some tests fail with 'cannot change locale (en_US.ISO-8859-1): No such file or directory' + ## Some others need a French locale + sudo locale-gen + sudo locale-gen --keep-existing fr_FR + sudo locale-gen --keep-existing fr_FR.UTF-8 + sudo update-locale + echo "After:" + locale -a + - name: Build binaries + env: + RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" + RUSTDOCFLAGS: "-Cpanic=abort" + run: | + ## Build binaries + cd uutils + bash util/build-gnu.sh + - name: Run GNU tests + run: bash uutils/util/run-gnu-test.sh + - name: Generate coverage data (via `grcov`) + id: coverage + run: | + ## Generate coverage data + cd uutils + COVERAGE_REPORT_DIR="target/debug" + COVERAGE_REPORT_FILE="${COVERAGE_REPORT_DIR}/lcov.info" + mkdir -p "${COVERAGE_REPORT_DIR}" + sudo chown -R "$(whoami)" "${COVERAGE_REPORT_DIR}" + # display coverage files + grcov . --output-type files --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" | sort --unique + # generate coverage report + grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" + echo "report=${COVERAGE_REPORT_FILE}" >> $GITHUB_OUTPUT + - name: Upload coverage results (to Codecov.io) + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ${{ steps.coverage.outputs.report }} + flags: gnutests + name: gnutests + working-directory: uutils