diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml deleted file mode 100644 index df1fba73c54..00000000000 --- a/.github/workflows/CICD.yml +++ /dev/null @@ -1,1202 +0,0 @@ -name: CICD - -# spell-checker:ignore (abbrev/names) CICD CodeCOV MacOS MinGW MSVC musl taiki -# spell-checker:ignore (env/flags) Awarnings Ccodegen Coverflow Cpanic Dwarnings RUSTDOCFLAGS RUSTFLAGS Zpanic CARGOFLAGS -# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain fuzzers dedupe devel profdata -# spell-checker:ignore (people) Peltoche rivy dtolnay Anson dawidd -# spell-checker:ignore (shell/tools) binutils choco clippy dmake dpkg esac fakeroot fdesc fdescfs gmake grcov halium lcov libclang libfuse libssl limactl mkdir nextest nocross pacman popd printf pushd redoxer rsync rustc rustfmt rustup shopt sccache utmpdump xargs -# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils defconfig DESTDIR gecos getenforce gnueabihf issuecomment maint manpages msys multisize noconfirm nullglob onexitbegin onexitend pell runtest Swatinem tempfile testsuite toybox uutils - -env: - PROJECT_NAME: coreutils - PROJECT_DESC: "Core universal (cross-platform) utilities" - PROJECT_AUTH: "uutils" - RUST_MIN_SRV: "1.85.0" - # * style job configuration - STYLE_FAIL_ON_FAULT: true ## (bool) fail the build if a style job contains a fault (error or warning); may be overridden on a per-job basis - -on: - pull_request: - push: - tags: - - '*' - branches: - - '*' - -permissions: - contents: read # to fetch code (actions/checkout) - -# End the current execution if there is a new changeset in the PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -jobs: - cargo-deny: - name: Style/cargo-deny - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: EmbarkStudios/cargo-deny-action@v2 - - style_deps: - ## ToDO: [2021-11-10; rivy] 'Style/deps' needs more informative output and better integration of results into the GHA dashboard - name: Style/deps - runs-on: ${{ matrix.job.os }} - strategy: - fail-fast: false - matrix: - job: - # note: `cargo-udeps` panics when processing stdbuf/libstdbuf ("uu_stdbuf_libstdbuf"); either b/c of the 'cpp' crate or 'libstdbuf' itself - # ... b/c of the panic, a more limited feature set is tested (though only excluding `stdbuf`) - - { os: ubuntu-latest , features: "feat_Tier1,feat_require_unix,feat_require_unix_utmpx" } - - { os: macos-latest , features: "feat_Tier1,feat_require_unix,feat_require_unix_utmpx" } - - { os: windows-latest , features: feat_os_windows } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly - ## note: requires 'nightly' toolchain b/c `cargo-udeps` uses the `rustc` '-Z save-analysis' option - ## * ... ref: - - uses: taiki-e/install-action@cargo-udeps - - uses: Swatinem/rust-cache@v2 - - 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; } - # failure mode - unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in - ''|0|f|false|n|no|off) FAULT_TYPE=warning ;; - *) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;; - esac; - outputs FAIL_ON_FAULT FAULT_TYPE - # target-specific options - # * CARGO_FEATURES_OPTION - CARGO_FEATURES_OPTION='' ; - if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi - outputs CARGO_FEATURES_OPTION - - name: Detect unused dependencies - shell: bash - run: | - ## Detect unused dependencies - unset fault - fault_type="${{ steps.vars.outputs.FAULT_TYPE }}" - fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]') - # - cargo +nightly udeps ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --all-targets &> udeps.log || cat udeps.log - grep --ignore-case "all deps seem to have been used" udeps.log || { printf "%s\n" "::${fault_type} ::${fault_prefix}: \`cargo udeps\`: style violation (unused dependency found)" ; fault=true ; } - if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi - - doc_warnings: - name: Documentation/warnings - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } -# for now, don't build it on mac & windows because the doc is only published from linux -# + it needs a bunch of duplication for build -# and I don't want to add a doc step in the regular build to avoid long builds -# - { os: macos-latest , features: feat_os_macos } -# - { os: windows-latest , features: feat_os_windows } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: clippy - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install/setup prerequisites - shell: bash - run: | - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev - - 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; } - # failure mode - unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in - ''|0|f|false|n|no|off) FAULT_TYPE=warning ;; - *) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;; - esac; - outputs FAIL_ON_FAULT FAULT_TYPE - # target-specific options - # * CARGO_FEATURES_OPTION - CARGO_FEATURES_OPTION='--all-features' ; - if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features ${{ matrix.job.features }}' ; fi - outputs CARGO_FEATURES_OPTION - # * determine sub-crate utility list - UTILITY_LIST="$(./util/show-utils.sh ${CARGO_FEATURES_OPTION})" - echo UTILITY_LIST=${UTILITY_LIST} - CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo -n "-puu_${u} "; done;)" - outputs CARGO_UTILITY_LIST_OPTIONS - - name: "`cargo doc` with warnings" - shell: bash - run: | - RUSTDOCFLAGS="-Dwarnings" cargo doc ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-deps --workspace --document-private-items - - uses: DavidAnson/markdownlint-cli2-action@v19 - with: - fix: "true" - globs: | - *.md - docs/src/*.md - src/uu/*/*.md - - min_version: - name: MinRustV # Minimum supported rust version (aka, MinSRV or MSRV) - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.RUST_MIN_SRV }} - components: rustfmt - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - 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; } - # target-specific options - # * CARGO_FEATURES_OPTION - unset CARGO_FEATURES_OPTION - if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi - outputs CARGO_FEATURES_OPTION - - name: Confirm MinSRV compatible '*/Cargo.lock' - shell: bash - run: | - ## Confirm MinSRV compatible '*/Cargo.lock' - # * '*/Cargo.lock' is required to be in a format that `cargo` of MinSRV can interpret (eg, v1-format for MinSRV < v1.38) - for dir in "." "fuzz"; do - ( cd "$dir" && cargo fetch --locked --quiet ) || { echo "::error file=$dir/Cargo.lock::Incompatible (or out-of-date) '$dir/Cargo.lock' file; update using \`cd '$dir' && cargo +${{ env.RUST_MIN_SRV }} update\`" ; exit 1 ; } - done - - name: Install/setup prerequisites - shell: bash - run: | - # Install a package for one of the tests - sudo apt-get -y update ; sudo apt-get -y install attr - - name: Info - shell: bash - run: | - ## Info - # environment - echo "## environment" - echo "CI='${CI}'" - # tooling info display - echo "## tooling" - which gcc >/dev/null 2>&1 && (gcc --version | head -1) || true - rustup -V 2>/dev/null - rustup show active-toolchain - cargo -V - rustc -V - cargo tree -V - # dependencies - echo "## dependency list" - ## * using the 'stable' toolchain is necessary to avoid "unexpected '--filter-platform'" errors - RUSTUP_TOOLCHAIN=stable cargo fetch --locked --quiet - RUSTUP_TOOLCHAIN=stable cargo tree --no-dedupe --locked -e=no-dev --prefix=none ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} | grep -vE "$PWD" | sort --unique - - name: Test - run: cargo nextest run --hide-progress-bar --profile ci ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils - env: - RUSTFLAGS: "-Awarnings" - RUST_BACKTRACE: "1" - - deps: - name: Dependencies - runs-on: ${{ matrix.job.os }} - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - name: "`cargo update` testing" - shell: bash - run: | - ## `cargo update` testing - # * convert any errors/warnings to GHA UI annotations; ref: - for dir in "." "fuzz"; do - ( cd "$dir" && cargo fetch --locked --quiet ) || { echo "::error file=$dir/Cargo.lock::'$dir/Cargo.lock' file requires update (use \`cd '$dir' && cargo +${{ env.RUST_MIN_SRV }} update\`)" ; exit 1 ; } - done - - build_makefile: - name: Build/Makefile - needs: [ min_version, deps ] - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 - - name: Install/setup prerequisites - shell: bash - run: | - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: "`make build`" - shell: bash - run: | - make build - - name: "`make nextest`" - shell: bash - run: make nextest CARGOFLAGS="--profile ci --hide-progress-bar" - env: - RUST_BACKTRACE: "1" - - name: "`make install COMPLETIONS=n MANPAGES=n`" - shell: bash - run: | - DESTDIR=/tmp/ make PROFILE=release COMPLETIONS=n MANPAGES=n install - # Check that the utils are present - test -f /tmp/usr/local/bin/tty - # Check that the manpage is not present - ! test -f /tmp/usr/local/share/man/man1/whoami.1 - # Check that the completion is not present - ! test -f /tmp/usr/local/share/zsh/site-functions/_install - ! test -f /tmp/usr/local/share/bash-completion/completions/head - ! test -f /tmp/usr/local/share/fish/vendor_completions.d/cat.fish - env: - RUST_BACKTRACE: "1" - - name: "`make install`" - shell: bash - run: | - DESTDIR=/tmp/ make PROFILE=release install - # Check that the utils are present - test -f /tmp/usr/local/bin/tty - # Check that the manpage is present - test -f /tmp/usr/local/share/man/man1/whoami.1 - # Check that the completion is present - test -f /tmp/usr/local/share/zsh/site-functions/_install - test -f /tmp/usr/local/share/bash-completion/completions/head - test -f /tmp/usr/local/share/fish/vendor_completions.d/cat.fish - env: - RUST_BACKTRACE: "1" - - name: "`make uninstall`" - shell: bash - run: | - DESTDIR=/tmp/ make uninstall - # Check that the utils are not present - ! test -f /tmp/usr/local/bin/tty - # Check that the manpage is not present - ! test -f /tmp/usr/local/share/man/man1/whoami.1 - # Check that the completion is not present - ! test -f /tmp/usr/local/share/zsh/site-functions/_install - ! test -f /tmp/usr/local/share/bash-completion/completions/head - ! test -f /tmp/usr/local/share/fish/vendor_completions.d/cat.fish - - build_rust_stable: - name: Build/stable - needs: [ min_version, deps ] - 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: feat_os_unix } - - { os: macos-latest , features: feat_os_macos } - - { os: windows-latest , features: feat_os_windows } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Test - run: cargo nextest run --hide-progress-bar --profile ci --features ${{ matrix.job.features }} - env: - RUST_BACKTRACE: "1" - - build_rust_nightly: - name: Build/nightly - needs: [ min_version, deps ] - 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: feat_os_unix } - - { os: macos-latest , features: feat_os_macos } - - { os: windows-latest , features: feat_os_windows } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Test - run: cargo nextest run --hide-progress-bar --profile ci --features ${{ matrix.job.features }} - env: - RUST_BACKTRACE: "1" - - compute_size: - name: Binary sizes - needs: [ min_version, deps ] - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install dependencies - shell: bash - run: | - ## Install dependencies - sudo apt-get update - sudo apt-get install jq libselinux1-dev - - name: "`make install`" - shell: bash - run: | - ## `make install` - make install DESTDIR=target/size-release/ - make install MULTICALL=y DESTDIR=target/size-multi-release/ - # strip the results - strip target/size*/usr/local/bin/* - - name: Compute uutil release sizes - shell: bash - run: | - ## Compute uutil release sizes - DATE=$(date --rfc-email) - find target/size-release/usr/local/bin -type f -printf '%f\0' | sort -z | - while IFS= read -r -d '' name; do - size=$(du -s target/size-release/usr/local/bin/$name | awk '{print $1}') - echo "\"$name\"" - echo "$size" - done | \ - jq -n \ - --arg date "$DATE" \ - --arg sha "$GITHUB_SHA" \ - 'reduce inputs as $name ({}; . + { ($name): input }) | { ($date): {sha: $sha, sizes: map_values(.)} }' > individual-size-result.json - SIZE=$(cat individual-size-result.json | jq '[.[] | .sizes | .[]] | reduce .[] as $num (0; . + $num)') - SIZE_MULTI=$(du -s target/size-multi-release/usr/local/bin/coreutils | awk '{print $1}') - jq -n \ - --arg date "$DATE" \ - --arg sha "$GITHUB_SHA" \ - --arg size "$SIZE" \ - --arg multisize "$SIZE_MULTI" \ - '{($date): { sha: $sha, size: $size, multisize: $multisize, }}' > size-result.json - - name: Download the previous individual size result - uses: dawidd6/action-download-artifact@v9 - with: - workflow: CICD.yml - name: individual-size-result - repo: uutils/coreutils - path: dl - - name: Download the previous size result - uses: dawidd6/action-download-artifact@v9 - with: - workflow: CICD.yml - name: size-result - repo: uutils/coreutils - path: dl - - name: Check uutil release sizes - shell: bash - run: | - check() { - # Warn if the size increases by more than 5% - threshold='1.05' - - if [[ "$2" -eq 0 || "$3" -eq 0 ]]; then - echo "::warning file=$4::Invalid size for $1. Sizes cannot be 0." - return - fi - - ratio=$(jq -n "$2 / $3") - echo "$1: size=$2, previous_size=$3, ratio=$ratio, threshold=$threshold" - if [[ "$(jq -n "$ratio > $threshold")" == 'true' ]]; then - echo "::warning file=$4::Size of $1 increases by more than 5%" - fi - } - ## Check individual size result - while read -r name previous_size; do - size=$(cat individual-size-result.json | jq -r ".[] | .sizes | .\"$name\"") - check "\`$name\` binary" "$size" "$previous_size" 'individual-size-result.json' - done < <(cat dl/individual-size-result.json | jq -r '.[] | .sizes | to_entries[] | "\(.key) \(.value)"') - ## Check size result - size=$(cat size-result.json | jq -r '.[] | .size') - previous_size=$(cat dl/size-result.json | jq -r '.[] | .size') - check 'multiple binaries' "$size" "$previous_size" 'size-result.json' - multisize=$(cat size-result.json | jq -r '.[] | .multisize') - previous_multisize=$(cat dl/size-result.json | jq -r '.[] | .multisize') - check 'multicall binary' "$multisize" "$previous_multisize" 'size-result.json' - - name: Upload the individual size result - uses: actions/upload-artifact@v4 - with: - name: individual-size-result - path: individual-size-result.json - - name: Upload the size result - uses: actions/upload-artifact@v4 - with: - name: size-result - path: size-result.json - - build: - permissions: - contents: write # to create GitHub release (softprops/action-gh-release) - - name: Build - needs: [ min_version, deps ] - runs-on: ${{ matrix.job.os }} - timeout-minutes: 90 - env: - DOCKER_OPTS: '--volume /etc/passwd:/etc/passwd --volume /etc/group:/etc/group' - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - # - { os , target , cargo-options , features , use-cross , toolchain, skip-tests, workspace-tests } - - { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , features: feat_os_unix_gnueabihf , use-cross: use-cross , skip-tests: true } - - { os: ubuntu-24.04-arm , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf } - - { os: ubuntu-latest , target: aarch64-unknown-linux-musl , features: feat_os_unix , use-cross: use-cross , skip-tests: true } - # - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross } - - { os: ubuntu-latest , target: i686-unknown-linux-gnu , features: "feat_os_unix,test_risky_names", use-cross: use-cross } - - { os: ubuntu-latest , target: i686-unknown-linux-musl , features: feat_os_unix , use-cross: use-cross } - - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: "feat_os_unix,test_risky_names", use-cross: use-cross } - - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: "feat_os_unix,uudoc" , use-cross: no, workspace-tests: true } - - { os: ubuntu-latest , target: x86_64-unknown-linux-musl , features: feat_os_unix , use-cross: use-cross } - - { os: ubuntu-latest , target: x86_64-unknown-redox , features: feat_os_unix_redox , use-cross: redoxer , skip-tests: true } - - { os: macos-latest , target: aarch64-apple-darwin , features: feat_os_macos, workspace-tests: true } # M1 CPU - - { os: macos-13 , target: x86_64-apple-darwin , features: feat_os_macos, workspace-tests: true } - - { os: windows-latest , target: i686-pc-windows-msvc , features: feat_os_windows } - - { os: windows-latest , target: x86_64-pc-windows-gnu , features: feat_os_windows } - - { os: windows-latest , target: x86_64-pc-windows-msvc , features: feat_os_windows } - - { os: windows-latest , target: aarch64-pc-windows-msvc , features: feat_os_windows, use-cross: use-cross , skip-tests: true } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.RUST_MIN_SRV }} - targets: ${{ matrix.job.target }} - - uses: Swatinem/rust-cache@v2 - with: - key: "${{ matrix.job.os }}_${{ matrix.job.target }}" - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - 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="stable" ## default to "stable" toolchain - # * specify alternate/non-default TOOLCHAIN for *-pc-windows-gnu targets; gnu targets on Windows are broken for the standard *-pc-windows-msvc toolchain (refs: GH:rust-lang/rust#47048, GH:rust-lang/rust#53454, GH:rust-lang/cargo#6754) - case ${{ matrix.job.target }} in *-pc-windows-gnu) TOOLCHAIN="stable-${{ matrix.job.target }}" ;; esac; - # * use requested TOOLCHAIN if specified - if [ -n "${{ matrix.job.toolchain }}" ]; then TOOLCHAIN="${{ matrix.job.toolchain }}" ; fi - outputs TOOLCHAIN - # staging directory - STAGING='_staging' - outputs STAGING - # determine EXE suffix - EXE_suffix="" ; case '${{ matrix.job.target }}' in *-pc-windows-*) EXE_suffix=".exe" ;; esac; - outputs EXE_suffix - # parse commit reference info - echo GITHUB_REF=${GITHUB_REF} - echo GITHUB_SHA=${GITHUB_SHA} - REF_NAME=${GITHUB_REF#refs/*/} - unset REF_BRANCH ; case "${GITHUB_REF}" in refs/heads/*) REF_BRANCH=${GITHUB_REF#refs/heads/} ;; esac; - unset REF_TAG ; case "${GITHUB_REF}" in refs/tags/*) REF_TAG=${GITHUB_REF#refs/tags/} ;; esac; - REF_SHAS=${GITHUB_SHA:0:10} - outputs REF_NAME REF_BRANCH REF_TAG REF_SHAS - # parse target - unset TARGET_ARCH - case '${{ matrix.job.target }}' in - aarch64-*) TARGET_ARCH=arm64 ;; - arm-*-*hf) TARGET_ARCH=armhf ;; - i586-*) TARGET_ARCH=i586 ;; - i686-*) TARGET_ARCH=i686 ;; - x86_64-*) TARGET_ARCH=x86_64 ;; - esac; - unset TARGET_OS - case '${{ matrix.job.target }}' in - *-linux-*) TARGET_OS=linux ;; - *-apple-*) TARGET_OS=macos ;; - *-windows-*) TARGET_OS=windows ;; - *-redox*) TARGET_OS=redox ;; - esac - outputs TARGET_ARCH TARGET_OS - # package name - PKG_suffix=".tar.gz" ; case '${{ matrix.job.target }}' in *-pc-windows-*) PKG_suffix=".zip" ;; esac; - PKG_BASENAME=${PROJECT_NAME}-${REF_TAG:-$REF_SHAS}-${{ matrix.job.target }} - PKG_NAME=${PKG_BASENAME}${PKG_suffix} - outputs PKG_suffix PKG_BASENAME PKG_NAME - # deployable tag? (ie, leading "vM" or "M"; M == version number) - unset DEPLOY ; if [[ $REF_TAG =~ ^[vV]?[0-9].* ]]; then DEPLOY='true' ; fi - outputs DEPLOY - # DPKG architecture? - unset DPKG_ARCH - case ${{ matrix.job.target }} in - x86_64-*-linux-*) DPKG_ARCH=amd64 ;; - *-linux-*) DPKG_ARCH=${TARGET_ARCH} ;; - esac - outputs DPKG_ARCH - # DPKG version? - unset DPKG_VERSION ; if [[ $REF_TAG =~ ^[vV]?[0-9].* ]]; then DPKG_VERSION=${REF_TAG/#[vV]/} ; fi - outputs DPKG_VERSION - # DPKG base name/conflicts? - DPKG_BASENAME=${PROJECT_NAME} - DPKG_CONFLICTS=${PROJECT_NAME}-musl - case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${PROJECT_NAME}-musl ; DPKG_CONFLICTS=${PROJECT_NAME} ;; esac; - outputs DPKG_BASENAME DPKG_CONFLICTS - # DPKG name - unset DPKG_NAME; - if [[ -n $DPKG_ARCH && -n $DPKG_VERSION ]]; then DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb" ; fi - outputs DPKG_NAME - # target-specific options - # * CARGO_FEATURES_OPTION - CARGO_FEATURES_OPTION='' ; - if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features=${{ matrix.job.features }}' ; fi - outputs CARGO_FEATURES_OPTION - # * CARGO_CMD - CARGO_CMD='cross' - CARGO_CMD_OPTIONS='+${{ env.RUST_MIN_SRV }}' - # Added suffix for artifacts, needed when multiple jobs use the same target. - ARTIFACTS_SUFFIX='' - case '${{ matrix.job.use-cross }}' in - ''|0|f|false|n|no) - CARGO_CMD='cargo' - ARTIFACTS_SUFFIX='-nocross' - ;; - redoxer) - CARGO_CMD='redoxer' - CARGO_CMD_OPTIONS='' - ;; - esac - outputs CARGO_CMD - outputs CARGO_CMD_OPTIONS - outputs ARTIFACTS_SUFFIX - CARGO_TEST_OPTIONS='' - case '${{ matrix.job.workspace-tests }}' in - 1|t|true|y|yes) - # This also runs tests in other packages in the source directory (e.g. uucore). - # We cannot enable this everywhere as some platforms are currently broken, and - # we cannot use `cross` as its Docker image is ancient (Ubuntu 16.04) and is - # missing required system dependencies (e.g. recent libclang-dev). - CARGO_TEST_OPTIONS='--workspace' - ;; - esac - outputs CARGO_TEST_OPTIONS - # ** pass needed environment into `cross` container (iff `cross` not already configured via "Cross.toml") - if [ "${CARGO_CMD}" = 'cross' ] && [ ! -e "Cross.toml" ] ; then - printf "[build.env]\npassthrough = [\"CI\", \"RUST_BACKTRACE\", \"CARGO_TERM_COLOR\"]\n" > Cross.toml - fi - # * executable for `strip`? - STRIP="strip" - case ${{ matrix.job.target }} in - aarch64-*-linux-*) STRIP="aarch64-linux-gnu-strip" ;; - arm-*-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;; - *-pc-windows-msvc) STRIP="" ;; - esac; - outputs STRIP - - uses: taiki-e/install-action@v2 - if: steps.vars.outputs.CARGO_CMD == 'cross' - with: - tool: cross@0.2.5 - - name: Create all needed build/work directories - shell: bash - run: | - ## Create build/work space - mkdir -p '${{ steps.vars.outputs.STAGING }}' - mkdir -p '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}' - mkdir -p '${{ steps.vars.outputs.STAGING }}/dpkg' - - name: Install/setup prerequisites - shell: bash - run: | - ## Install/setup prerequisites - case '${{ matrix.job.target }}' in - arm-unknown-linux-gnueabihf) - sudo apt-get -y update - sudo apt-get -y install gcc-arm-linux-gnueabihf - ;; - aarch64-unknown-linux-*) - sudo apt-get -y update - sudo apt-get -y install gcc-aarch64-linux-gnu - ;; - *-redox*) - sudo apt-get -y update - sudo apt-get -y install fuse3 libfuse-dev - ;; - # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368 - x86_64-pc-windows-gnu) - C:/msys64/usr/bin/pacman.exe -Sy --needed mingw-w64-x86_64-gcc --noconfirm - echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH - ;; - esac - case '${{ matrix.job.os }}' in - macos-latest) brew install coreutils ;; # needed for testing - esac - case '${{ matrix.job.os }}' in - ubuntu-*) - # selinux headers needed to build tests - sudo apt-get -y update - sudo apt-get -y install libselinux1-dev - # 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 - - uses: taiki-e/install-action@v2 - if: steps.vars.outputs.CARGO_CMD == 'redoxer' - with: - tool: redoxer@0.2.37 - - 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 }})" - echo UTILITY_LIST=${UTILITY_LIST} - CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo -n "-puu_${u} "; done;)" - outputs CARGO_UTILITY_LIST_OPTIONS - - name: Info - shell: bash - run: | - ## Info - # commit info - echo "## commit" - echo GITHUB_REF=${GITHUB_REF} - echo GITHUB_SHA=${GITHUB_SHA} - # environment - echo "## environment" - echo "CI='${CI}'" - # tooling info display - echo "## tooling" - which gcc >/dev/null 2>&1 && (gcc --version | head -1) || true - rustup -V 2>/dev/null - rustup show active-toolchain - cargo -V - rustc -V - cargo tree -V - # dependencies - echo "## dependency list" - cargo fetch --locked --quiet - cargo tree --locked --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-dedupe -e=no-dev --prefix=none | grep -vE "$PWD" | sort --unique - - name: Build - shell: bash - run: | - ## Build - ${{ steps.vars.outputs.CARGO_CMD }} ${{ steps.vars.outputs.CARGO_CMD_OPTIONS }} build --release \ - --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} - - name: Test - if: matrix.job.skip-tests != true - shell: bash - run: | - ## Test - ${{ steps.vars.outputs.CARGO_CMD }} ${{ steps.vars.outputs.CARGO_CMD_OPTIONS }} test --target=${{ matrix.job.target }} \ - ${{ steps.vars.outputs.CARGO_TEST_OPTIONS}} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} - env: - RUST_BACKTRACE: "1" - - name: Test individual utilities - if: matrix.job.skip-tests != true - shell: bash - run: | - ## Test individual utilities - ${{ steps.vars.outputs.CARGO_CMD }} ${{ steps.vars.outputs.CARGO_CMD_OPTIONS }} test --target=${{ matrix.job.target }} \ - ${{ matrix.job.cargo-options }} ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }} - env: - RUST_BACKTRACE: "1" - - name: Archive executable artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ env.PROJECT_NAME }}-${{ matrix.job.target }}${{ steps.vars.outputs.ARTIFACTS_SUFFIX }} - path: target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }} - - name: Package - shell: bash - run: | - ## Package artifact(s) - # binary - cp 'target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }}' '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}/' - # `strip` binary (if needed) - if [ -n "${{ steps.vars.outputs.STRIP }}" ]; then "${{ steps.vars.outputs.STRIP }}" '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }}' ; fi - # README and LICENSE - # * spell-checker:ignore EADME ICENSE - (shopt -s nullglob; for f in [R]"EADME"{,.*}; do cp $f '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}/' ; done) - (shopt -s nullglob; for f in [L]"ICENSE"{-*,}{,.*}; do cp $f '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}/' ; done) - # core compressed package - pushd '${{ steps.vars.outputs.STAGING }}/' >/dev/null - case '${{ matrix.job.target }}' in - *-pc-windows-*) 7z -y a '${{ steps.vars.outputs.PKG_NAME }}' '${{ steps.vars.outputs.PKG_BASENAME }}'/* | tail -2 ;; - *) tar czf '${{ steps.vars.outputs.PKG_NAME }}' '${{ steps.vars.outputs.PKG_BASENAME }}'/* ;; - esac - popd >/dev/null - # dpkg - if [ -n "${{ steps.vars.outputs.DPKG_NAME }}" ]; then - DPKG_DIR="${{ steps.vars.outputs.STAGING }}/dpkg" - # binary - install -Dm755 'target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }}' "${DPKG_DIR}/usr/bin/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }}" - if [ -n "${{ steps.vars.outputs.STRIP }}" ]; then "${{ steps.vars.outputs.STRIP }}" "${DPKG_DIR}/usr/bin/${{ env.PROJECT_NAME }}${{ steps.vars.outputs.EXE_suffix }}" ; fi - # README and LICENSE - (shopt -s nullglob; for f in [R]"EADME"{,.*}; do install -Dm644 "$f" "${DPKG_DIR}/usr/share/doc/${{ env.PROJECT_NAME }}/$f" ; done) - (shopt -s nullglob; for f in [L]"ICENSE"{-*,}{,.*}; do install -Dm644 "$f" "${DPKG_DIR}/usr/share/doc/${{ env.PROJECT_NAME }}/$f" ; done) - # control file - mkdir -p "${DPKG_DIR}/DEBIAN" - printf "Package: ${{ steps.vars.outputs.DPKG_BASENAME }}\nVersion: ${{ steps.vars.outputs.DPKG_VERSION }}\nSection: utils\nPriority: optional\nMaintainer: ${{ env.PROJECT_AUTH }}\nArchitecture: ${{ steps.vars.outputs.DPKG_ARCH }}\nProvides: ${{ env.PROJECT_NAME }}\nConflicts: ${{ steps.vars.outputs.DPKG_CONFLICTS }}\nDescription: ${{ env.PROJECT_DESC }}\n" > "${DPKG_DIR}/DEBIAN/control" - # build dpkg - fakeroot dpkg-deb --build "${DPKG_DIR}" "${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.DPKG_NAME }}" - fi - - name: Publish - uses: softprops/action-gh-release@v2 - if: steps.vars.outputs.DEPLOY - with: - draft: true - files: | - ${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_NAME }} - ${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.DPKG_NAME }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - test_busybox: - name: Tests/BusyBox test suite - needs: [ min_version, deps ] - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest } - steps: - - name: Initialize workflow variables - id: vars - shell: bash - run: | - ## VARs setup - echo "TEST_SUMMARY_FILE=busybox-result.json" >> $GITHUB_OUTPUT - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install/setup prerequisites - shell: bash - run: | - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev - ## Install/setup prerequisites - make prepare-busytest - - name: Run BusyBox test suite - id: summary - shell: bash - run: | - ## Run BusyBox test suite - set -v - cp .busybox-config target/debug/.config - ## Run BusyBox test suite - bindir=$(pwd)/target/debug - cd tmp/busybox-*/testsuite - output=$(bindir=$bindir ./runtest 2>&1 || true) - printf "%s\n" "${output}" - FAIL=$(echo "$output" | grep "^FAIL:\s" | wc --lines) - PASS=$(echo "$output" | grep "^PASS:\s" | wc --lines) - SKIP=$(echo "$output" | grep "^SKIPPED:\s" | wc --lines) - TOTAL=`expr $FAIL + $PASS + $SKIP` - echo "FAIL $FAIL" - echo "SKIP $SKIP" - echo "PASS $PASS" - echo "TOTAL $TOTAL" - cd - - output="Busybox tests summary = TOTAL: $TOTAL / PASS: $PASS / FAIL: $FAIL / SKIP: $SKIP" - echo "${output}" - if [[ "$FAIL" -gt 0 || "$ERROR" -gt 0 ]]; then echo "::warning ::${output}" ; fi - jq -n \ - --arg date "$(date --rfc-email)" \ - --arg sha "$GITHUB_SHA" \ - --arg total "$TOTAL" \ - --arg pass "$PASS" \ - --arg skip "$SKIP" \ - --arg fail "$FAIL" \ - '{($date): { sha: $sha, total: $total, pass: $pass, skip: $skip, fail: $fail, }}' > '${{ steps.vars.outputs.TEST_SUMMARY_FILE }}' - HASH=$(sha1sum '${{ steps.vars.outputs.TEST_SUMMARY_FILE }}' | cut --delim=" " -f 1) - echo "HASH=${HASH}" >> $GITHUB_OUTPUT - - name: Reserve SHA1/ID of 'test-summary' - uses: actions/upload-artifact@v4 - with: - name: "${{ steps.summary.outputs.HASH }}" - path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}" - - name: Reserve test results summary - uses: actions/upload-artifact@v4 - with: - name: busybox-test-summary - path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}" - - name: Upload json results - uses: actions/upload-artifact@v4 - with: - name: busybox-result.json - path: ${{ steps.vars.outputs.TEST_SUMMARY_FILE }} - - test_toybox: - name: Tests/Toybox test suite - needs: [ min_version, deps ] - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest } - steps: - - 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; } - TEST_SUMMARY_FILE="toybox-result.json" - outputs TEST_SUMMARY_FILE - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.RUST_MIN_SRV }} - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install/setup prerequisites - shell: bash - run: | - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev - - name: Build coreutils as multiple binaries - shell: bash - run: | - ## Build individual uutil binaries - set -v - make - - name: Run toybox src - shell: bash - run: | - make toybox-src - - name: Run Toybox test suite - id: summary - shell: bash - run: | - ## Run Toybox test suite - set -v - cd tmp/toybox-*/ - make defconfig - make tests &> tmp.log || true - cat tmp.log - FAIL=$(grep "FAIL" tmp.log | wc --lines) - PASS=$(grep "PASS:" tmp.log| wc --lines) - SKIP=$(grep " disabled$" tmp.log| wc --lines) - TOTAL=`expr $FAIL + $PASS + $SKIP` - echo "FAIL $FAIL" - echo "SKIP $SKIP" - echo "PASS $PASS" - echo "TOTAL $TOTAL" - cd - - jq -n \ - --arg date "$(date --rfc-email)" \ - --arg sha "$GITHUB_SHA" \ - --arg total "$TOTAL" \ - --arg pass "$PASS" \ - --arg skip "$SKIP" \ - --arg fail "$FAIL" \ - '{($date): { sha: $sha, total: $total, pass: $pass, skip: $skip, fail: $fail, }}' > '${{ steps.vars.outputs.TEST_SUMMARY_FILE }}' - output="Toybox tests summary = TOTAL: $TOTAL / PASS: $PASS / FAIL: $FAIL / SKIP: $SKIP" - echo "${output}" - if [[ "$FAIL" -gt 0 || "$ERROR" -gt 0 ]]; then echo "::warning ::${output}" ; fi - HASH=$(sha1sum '${{ steps.vars.outputs.TEST_SUMMARY_FILE }}' | cut --delim=" " -f 1) - echo "HASH=${HASH}" >> $GITHUB_OUTPUT - - name: Reserve SHA1/ID of 'test-summary' - uses: actions/upload-artifact@v4 - with: - name: "${{ steps.summary.outputs.HASH }}" - path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}" - - name: Reserve test results summary - uses: actions/upload-artifact@v4 - with: - name: toybox-test-summary - path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}" - - name: Upload json results - uses: actions/upload-artifact@v4 - with: - 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 } - # FIXME: Re-enable macos code coverage - # - { 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@v2 - with: - tool: nextest,grcov@0.8.24 - - uses: Swatinem/rust-cache@v2 - - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - # - 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 - - ## Install the llvm-tools component to get access to `llvm-profdata` - rustup component add llvm-tools - - - name: Run test and coverage - id: run_test_cov - run: | - outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; } - - # Run the coverage script - ./util/build-run-test-coverage-linux.sh - - outputs REPORT_FILE - env: - COVERAGE_DIR: ${{ github.workspace }}/coverage - FEATURES_OPTION: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} - # RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }} - - - name: Upload coverage results (to Codecov.io) - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - file: ${{ steps.run_test_cov.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 }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - name: build and test all programs individually - shell: bash - run: | - for f in $(util/show-utils.sh) - do - echo "Building and testing $f" - cargo test -p "uu_$f" || exit 1 - done - - test_all_features: - name: Test all features separately - needs: [ min_version, deps ] - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest] - # windows-latest - https://github.com/uutils/coreutils/issues/7044 - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - name: build and test all features individually - shell: bash - run: | - for f in $(util/show-utils.sh) - do - echo "Running tests with --features=$f and --no-default-features" - cargo test --features=$f --no-default-features - done - - test_selinux: - name: Build/SELinux - needs: [ min_version, deps ] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@stable - - name: Setup Lima - uses: lima-vm/lima-actions/setup@v1 - id: lima-actions-setup - - name: Cache ~/.cache/lima - uses: actions/cache@v4 - with: - path: ~/.cache/lima - key: lima-${{ steps.lima-actions-setup.outputs.version }} - - name: Start Fedora VM with SELinux - run: limactl start --plain --name=default --cpus=1 --disk=30 --memory=4 --network=lima:user-v2 template://fedora - - name: Setup SSH - uses: lima-vm/lima-actions/ssh@v1 - - run: rsync -v -a -e ssh . lima-default:~/work/ - - name: Setup Rust and other build deps in VM - run: | - lima sudo dnf install gcc g++ git rustup libselinux-devel clang-devel attr -y - lima rustup-init -y --default-toolchain stable - - name: Verify SELinux Status - run: | - lima getenforce - lima ls -laZ /etc/selinux - - name: Build and Test with SELinux - run: | - lima ls - lima bash -c "cd work && cargo test --features 'feat_selinux'" - - name: Lint with SELinux - run: lima bash -c "cd work && cargo clippy --all-targets --features 'feat_selinux' -- -D warnings" diff --git a/.github/workflows/CheckScripts.yml b/.github/workflows/CheckScripts.yml deleted file mode 100644 index 78a4656fcde..00000000000 --- a/.github/workflows/CheckScripts.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: CheckScripts - -# spell-checker:ignore ludeeus mfinelli shellcheck scandir shfmt - -env: - SCRIPT_DIR: 'util' - -on: - push: - branches: - - '*' - paths: - - 'util/**/*.sh' - pull_request: - branches: - - main - paths: - - 'util/**/*.sh' - -# End the current execution if there is a new changeset in the PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -jobs: - shell_check: - name: ShellScript/Check - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Run ShellCheck - uses: ludeeus/action-shellcheck@master - env: - SHELLCHECK_OPTS: -s bash - with: - severity: warning - scandir: ${{ env.SCRIPT_DIR }} - format: tty - - shell_fmt: - name: ShellScript/Format - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Setup shfmt - uses: mfinelli/setup-shfmt@v3 - - name: Run shfmt - shell: bash - run: | - # fmt options: bash syntax, 4 spaces indent, indent for switch-case - echo "## show the differences between formatted and original scripts..." - find ${{ env.SCRIPT_DIR }} -name "*.sh" -print0 | xargs -0 shfmt -ln=bash -i 4 -ci -d || true diff --git a/.github/workflows/FixPR.yml b/.github/workflows/FixPR.yml deleted file mode 100644 index bbdf50b30b5..00000000000 --- a/.github/workflows/FixPR.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: FixPR - -# spell-checker:ignore Swatinem dtolnay dedupe - -# Trigger automated fixes for PRs being merged (with associated commits) - -env: - BRANCH_TARGET: main - -on: - # * only trigger on pull request closed to specific branches - # ref: https://github.community/t/trigger-workflow-only-on-pull-request-merge/17359/9 - pull_request: - branches: - - main # == env.BRANCH_TARGET ## unfortunately, env context variables are only available in jobs/steps (see ) - types: [ closed ] - -jobs: - code_deps: - # Refresh dependencies (ie, 'Cargo.lock') and show updated dependency tree - if: github.event.pull_request.merged == true ## only for PR merges - name: Update/dependencies - runs-on: ${{ matrix.job.os }} - strategy: - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Initialize job variables - id: vars - shell: bash - run: | - # surface MSRV from CICD workflow - RUST_MIN_SRV=$(grep -P "^\s+RUST_MIN_SRV:" .github/workflows/CICD.yml | grep -Po "(?<=\x22)\d+[.]\d+(?:[.]\d+)?(?=\x22)" ) - echo "RUST_MIN_SRV=${RUST_MIN_SRV}" >> $GITHUB_OUTPUT - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ steps.vars.outputs.RUST_MIN_SRV }} - - uses: Swatinem/rust-cache@v2 - - name: Ensure updated 'Cargo.lock' - shell: bash - run: | - # Ensure updated '*/Cargo.lock' - # * '*/Cargo.lock' is required to be in a format that `cargo` of MinSRV can interpret (eg, v1-format for MinSRV < v1.38) - for dir in "." "fuzz"; do - ( cd "$dir" && (cargo fetch --locked --quiet || cargo +${{ steps.vars.outputs.RUST_MIN_SRV }} update) ) - done - - name: Info - shell: bash - run: | - # Info - ## environment - echo "## environment" - echo "CI='${CI}'" - ## tooling info display - echo "## tooling" - which gcc >/dev/null 2>&1 && (gcc --version | head -1) || true - rustup -V 2>/dev/null - rustup show active-toolchain - cargo -V - rustc -V - cargo tree -V - ## dependencies - echo "## dependency list" - cargo fetch --locked --quiet - ## * using the 'stable' toolchain is necessary to avoid "unexpected '--filter-platform'" errors - RUSTUP_TOOLCHAIN=stable cargo tree --locked --no-dedupe -e=no-dev --prefix=none --features ${{ matrix.job.features }} | grep -vE "$PWD" | sort --unique - - name: Commit any changes (to '${{ env.BRANCH_TARGET }}') - uses: EndBug/add-and-commit@v9 - with: - new_branch: ${{ env.BRANCH_TARGET }} - default_author: github_actions - message: "maint ~ refresh 'Cargo.lock' 'fuzz/Cargo.lock'" - add: Cargo.lock fuzz/Cargo.lock - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - code_format: - # Recheck/refresh code formatting - if: github.event.pull_request.merged == true ## only for PR merges - name: Update/format - runs-on: ${{ matrix.job.os }} - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Initialize job variables - id: vars - shell: bash - run: | - # target-specific options - # * CARGO_FEATURES_OPTION - CARGO_FEATURES_OPTION='' ; - if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi - echo "CARGO_FEATURES_OPTION=${CARGO_FEATURES_OPTION}" >> $GITHUB_OUTPUT - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - name: "`cargo fmt`" - shell: bash - run: | - cargo fmt - - name: "`cargo fmt` tests" - shell: bash - run: | - # `cargo fmt` of tests - find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- - - name: Commit any changes (to '${{ env.BRANCH_TARGET }}') - uses: EndBug/add-and-commit@v9 - with: - new_branch: ${{ env.BRANCH_TARGET }} - default_author: github_actions - message: "maint ~ rustfmt (`cargo fmt`)" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/GnuComment.yml b/.github/workflows/GnuComment.yml deleted file mode 100644 index 7fe42070e82..00000000000 --- a/.github/workflows/GnuComment.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: GnuComment - -# spell-checker:ignore zizmor backquote - -on: - workflow_run: - workflows: ["GnuTests"] - types: - - completed # zizmor: ignore[dangerous-triggers] - -permissions: {} -jobs: - post-comment: - permissions: - actions: read # to list workflow runs artifacts - pull-requests: write # to comment on pr - - runs-on: ubuntu-latest - if: > - github.event.workflow_run.event == 'pull_request' - steps: - - name: 'Download artifact' - uses: actions/github-script@v7 - with: - script: | - // List all artifacts from GnuTests - var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{ github.event.workflow_run.id }}, - }); - - // Download the "comment" artifact, which contains a PR number (NR) and result.txt - var matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "comment" - })[0]; - var download = await github.rest.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - }); - var fs = require('fs'); - fs.writeFileSync('${{ github.workspace }}/comment.zip', Buffer.from(download.data)); - - run: unzip comment.zip - - - name: 'Comment on PR' - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - var fs = require('fs'); - var issue_number = Number(fs.readFileSync('./NR')); - var content = fs.readFileSync('./result.txt'); - if (content.toString().trim().length > 7) { // 7 because we have backquote + \n - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue_number, - body: 'GNU testsuite comparison:\n```\n' + content + '```' - }); - } diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml deleted file mode 100644 index 4f8edea3085..00000000000 --- a/.github/workflows/android.yml +++ /dev/null @@ -1,207 +0,0 @@ -name: Android - -# spell-checker:ignore (people) reactivecircus Swatinem dtolnay juliangruber -# spell-checker:ignore (shell/tools) TERMUX nextest udevadm pkill -# spell-checker:ignore (misc) swiftshader playstore DATALOSS noaudio - -on: - pull_request: - push: - branches: - - '*' - - -permissions: - contents: read # to fetch code (actions/checkout) - -# End the current execution if there is a new changeset in the PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -env: - TERMUX: v0.118.0 - KEY_POSTFIX: nextest+rustc-hash+adb+sshd+upgrade+XGB+inc18 - COMMON_EMULATOR_OPTIONS: -no-window -noaudio -no-boot-anim -camera-back none -gpu swiftshader_indirect -metrics-collection - EMULATOR_DISK_SIZE: 12GB - EMULATOR_HEAP_SIZE: 2048M - EMULATOR_BOOT_TIMEOUT: 1200 # 20min - -jobs: - test_android: - name: Test builds - timeout-minutes: 90 - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] # , macos-latest - cores: [4] # , 6 - ram: [4096, 8192] - api-level: [28] - target: [google_apis_playstore] - arch: [x86, x86_64] # , arm64-v8a - exclude: - - ram: 8192 - arch: x86 - - ram: 4096 - arch: x86_64 - runs-on: ${{ matrix.os }} - env: - EMULATOR_RAM_SIZE: ${{ matrix.ram }} - EMULATOR_CORES: ${{ matrix.cores }} - RUNNER_OS: ${{ matrix.os }} - AVD_CACHE_KEY: "set later due to limitations of github actions not able to concatenate env variables" - steps: - - name: Concatenate values to environment file - run: | - echo "AVD_CACHE_KEY=${{ matrix.os }}-${{ matrix.cores }}-${{ matrix.ram }}-${{ matrix.api-level }}-${{ matrix.target }}-${{ matrix.arch }}+termux-${{ env.TERMUX }}+${{ env.KEY_POSTFIX }}" >> $GITHUB_ENV - - name: Collect information about runner - if: always() - continue-on-error: true - run: | - hostname - uname -a - free -mh - df -Th - cat /proc/cpuinfo - - name: (Linux) create links from home to data partition - if: ${{ runner.os == 'Linux' }} - continue-on-error: true - run: | - ls -lah /mnt/ - cat /mnt/DATALOSS_WARNING_README.txt - sudo mkdir /mnt/data - sudo chmod a+rwx /mnt/data - mkdir /mnt/data/.android && ln -s /mnt/data/.android ~/.android - mkdir /mnt/data/work && ln -s /mnt/data/work ~/work - - name: Enable KVM group perms (linux hardware acceleration) - if: ${{ runner.os == 'Linux' }} - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Collect information about runner - if: always() - continue-on-error: true - run: | - free -mh - df -Th - - name: Restore AVD cache - uses: actions/cache/restore@v4 - id: avd-cache - continue-on-error: true - with: - path: | - ~/.android/avd/* - ~/.android/avd/*/snapshots/* - ~/.android/adb* - ~/__rustc_hash__ - key: avd-${{ env.AVD_CACHE_KEY }} - - name: Collect information about runner after AVD cache - if: always() - continue-on-error: true - run: | - free -mh - df -Th - ls -lah /mnt/data - du -sch /mnt/data - - name: Delete AVD Lockfile when run from cache - if: steps.avd-cache.outputs.cache-hit == 'true' - run: | - rm -f \ - ~/.android/avd/*.avd/*.lock \ - ~/.android/avd/*/*.lock - - name: Create and cache emulator image - if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2.34.0 - with: - api-level: ${{ matrix.api-level }} - target: ${{ matrix.target }} - arch: ${{ matrix.arch }} - ram-size: ${{ env.EMULATOR_RAM_SIZE }} - heap-size: ${{ env.EMULATOR_HEAP_SIZE }} - disk-size: ${{ env.EMULATOR_DISK_SIZE }} - cores: ${{ env.EMULATOR_CORES }} - force-avd-creation: true - emulator-options: ${{ env.COMMON_EMULATOR_OPTIONS }} -no-snapshot-load - emulator-boot-timeout: ${{ env.EMULATOR_BOOT_TIMEOUT }} - script: | - util/android-commands.sh init "${{ matrix.arch }}" "${{ matrix.api-level }}" "${{ env.TERMUX }}" - - name: Save AVD cache - if: steps.avd-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v4 - with: - path: | - ~/.android/avd/* - ~/.android/avd/*/snapshots/* - ~/.android/adb* - ~/__rustc_hash__ - key: avd-${{ env.AVD_CACHE_KEY }} - - uses: juliangruber/read-file-action@v1 - id: read_rustc_hash - with: - # ~ expansion didn't work - path: ${{ runner.os == 'Linux' && '/home/runner/__rustc_hash__' || '/Users/runner/__rustc_hash__' }} - trim: true - - name: Restore rust cache - id: rust-cache - uses: actions/cache/restore@v4 - with: - path: ~/__rust_cache__ - # The version vX at the end of the key is just a development version to avoid conflicts in - # the github cache during the development of this workflow - key: ${{ matrix.arch }}_${{ matrix.target}}_${{ steps.read_rustc_hash.outputs.content }}_${{ hashFiles('**/Cargo.toml', '**/Cargo.lock') }}_v3 - - name: Collect information about runner resources - if: always() - continue-on-error: true - run: | - free -mh - df -Th - - name: Build and Test - uses: reactivecircus/android-emulator-runner@v2.34.0 - with: - api-level: ${{ matrix.api-level }} - target: ${{ matrix.target }} - arch: ${{ matrix.arch }} - ram-size: ${{ env.EMULATOR_RAM_SIZE }} - heap-size: ${{ env.EMULATOR_HEAP_SIZE }} - disk-size: ${{ env.EMULATOR_DISK_SIZE }} - cores: ${{ env.EMULATOR_CORES }} - force-avd-creation: false - emulator-options: ${{ env.COMMON_EMULATOR_OPTIONS }} -no-snapshot-save -snapshot ${{ env.AVD_CACHE_KEY }} - emulator-boot-timeout: ${{ env.EMULATOR_BOOT_TIMEOUT }} - # This is not a usual script. Every line is executed in a separate shell with `sh -c`. If - # one of the lines returns with error the whole script is failed (like running a script with - # set -e) and in consequences the other lines (shells) are not executed. - script: | - util/android-commands.sh sync_host - util/android-commands.sh build - util/android-commands.sh tests - if [ "${{ steps.rust-cache.outputs.cache-hit }}" != 'true' ]; then util/android-commands.sh sync_image; fi; exit 0 - - name: Collect information about runner resources - if: always() - continue-on-error: true - run: | - free -mh - df -Th - - name: Save rust cache - if: steps.rust-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v4 - with: - path: ~/__rust_cache__ - key: ${{ matrix.arch }}_${{ matrix.target}}_${{ steps.read_rustc_hash.outputs.content }}_${{ hashFiles('**/Cargo.toml', '**/Cargo.lock') }}_v3 - - name: archive any output (error screenshots) - if: always() - uses: actions/upload-artifact@v4 - with: - name: test_output_${{ env.AVD_CACHE_KEY }} - path: output - - name: Collect information about runner resources - if: always() - continue-on-error: true - run: | - free -mh - df -Th diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml deleted file mode 100644 index 1c78fcaa2a3..00000000000 --- a/.github/workflows/code-quality.yml +++ /dev/null @@ -1,193 +0,0 @@ -name: Code Quality - -# spell-checker:ignore (people) reactivecircus Swatinem dtolnay juliangruber pell taplo -# spell-checker:ignore (misc) TERMUX noaudio pkill swiftshader esac sccache pcoreutils shopt subshell dequote - -on: - pull_request: - push: - branches: - - '*' - -env: - # * style job configuration - STYLE_FAIL_ON_FAULT: true ## (bool) fail the build if a style job contains a fault (error or warning); may be overridden on a per-job basis - -permissions: - contents: read # to fetch code (actions/checkout) - -# End the current execution if there is a new changeset in the PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -jobs: - - style_format: - name: Style/format - runs-on: ${{ matrix.job.os }} - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - 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; } - # failure mode - unset FAIL_ON_FAULT ; case "$STYLE_FAIL_ON_FAULT" in - ''|0|f|false|n|no|off) FAULT_TYPE=warning ;; - *) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;; - esac; - outputs FAIL_ON_FAULT FAULT_TYPE - - name: "`cargo fmt` testing" - shell: bash - run: | - ## `cargo fmt` testing - unset fault - fault_type="${{ steps.vars.outputs.FAULT_TYPE }}" - fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]') - # * convert any errors/warnings to GHA UI annotations; ref: - S=$(cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s\n" "$S" | sed -E -n -e "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::${fault_type} file=\1,line=\2::${fault_prefix}: \`cargo fmt\`: style violation (file:'\1', line:\2; use \`cargo fmt -- \"\1\"\`)/p" ; fault=true ; } - if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi - - style_lint: - name: Style/lint - runs-on: ${{ matrix.job.os }} - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - - { os: macos-latest , features: feat_os_macos } - - { os: windows-latest , features: feat_os_windows } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: clippy - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - 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; } - # failure mode - unset FAIL_ON_FAULT ; case "$STYLE_FAIL_ON_FAULT" in - ''|0|f|false|n|no|off) FAULT_TYPE=warning ;; - *) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;; - esac; - outputs FAIL_ON_FAULT FAULT_TYPE - - name: "`cargo clippy` lint testing" - uses: nick-fields/retry@v3 - with: - max_attempts: 3 - retry_on: error - timeout_minutes: 90 - shell: bash - command: | - ## `cargo clippy` lint testing - unset fault - fault_type="${{ steps.vars.outputs.FAULT_TYPE }}" - fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]') - # * convert any warnings to GHA UI annotations; ref: - S=$(cargo clippy --all-targets --features ${{ matrix.job.features }} --tests -pcoreutils -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::${fault_type} file=\2,line=\3,col=\4::${fault_prefix}: \`cargo clippy\`: \1 (file:'\2', line:\3)/p;" -e '}' ; fault=true ; } - if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi - - style_spellcheck: - name: Style/spelling - runs-on: ${{ matrix.job.os }} - strategy: - matrix: - job: - - { os: ubuntu-latest , features: feat_os_unix } - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - 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; } - # failure mode - unset FAIL_ON_FAULT ; case "$STYLE_FAIL_ON_FAULT" in - ''|0|f|false|n|no|off) FAULT_TYPE=warning ;; - *) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;; - esac; - outputs FAIL_ON_FAULT FAULT_TYPE - - name: Install/setup prerequisites - shell: bash - run: | - sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell -g ; - - name: Run `cspell` - shell: bash - run: | - ## Run `cspell` - unset fault - fault_type="${{ steps.vars.outputs.FAULT_TYPE }}" - fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]') - # * find cspell configuration ; note: avoid quotes around ${cfg_file} b/c `cspell` (v4) doesn't correctly dequote the config argument (or perhaps a subshell expansion issue?) - cfg_files=($(shopt -s nullglob ; echo {.vscode,.}/{,.}c[sS]pell{.json,.config{.js,.cjs,.json,.yaml,.yml},.yaml,.yml} ;)) - cfg_file=${cfg_files[0]} - unset CSPELL_CFG_OPTION ; if [ -n "$cfg_file" ]; then CSPELL_CFG_OPTION="--config $cfg_file" ; fi - S=$(cspell ${CSPELL_CFG_OPTION} --no-summary --no-progress .) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n "s/${PWD//\//\\/}\/(.*):(.*):(.*) - (.*)/::${fault_type} file=\1,line=\2,col=\3::${fault_type^^}: \4 (file:'\1', line:\2)/p" ; fault=true ; true ; } - if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi - - toml_format: - name: Style/toml - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: Check - run: npx --yes @taplo/cli fmt --check - - python: - name: Style/Python - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: ruff - uses: astral-sh/ruff-action@v3 - with: - src: "./util" - - - name: ruff - format - uses: astral-sh/ruff-action@v3 - with: - src: "./util" - args: format --check - - name: Run Python unit tests - shell: bash - run: | - python3 -m unittest util/test_compare_test_results.py diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml deleted file mode 100644 index 6e96bfd9599..00000000000 --- a/.github/workflows/freebsd.yml +++ /dev/null @@ -1,201 +0,0 @@ -name: FreeBSD - -# spell-checker:ignore sshfs usesh vmactions taiki Swatinem esac fdescfs fdesc sccache nextest copyback - -env: - # * style job configuration - STYLE_FAIL_ON_FAULT: true ## (bool) fail the build if a style job contains a fault (error or warning); may be overridden on a per-job basis - -on: - pull_request: - push: - branches: - - '*' - -permissions: - contents: read # to fetch code (actions/checkout) - -# End the current execution if there is a new changeset in the PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -jobs: - style: - name: Style and Lint - runs-on: ${{ matrix.job.os }} - timeout-minutes: 90 - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-24.04 , features: unix } - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Prepare, build and test - uses: vmactions/freebsd-vm@v1.2.0 - with: - usesh: true - sync: rsync - copyback: false - # We need jq and GNU coreutils to run show-utils.sh and bash to use inline shell string replacement - prepare: pkg install -y curl sudo jq coreutils bash - run: | - ## Prepare, build, and test - # implementation modelled after ref: - # * NOTE: All steps need to be run in this block, otherwise, we are operating back on the mac host - set -e - # - TEST_USER=tester - REPO_NAME=${GITHUB_WORKSPACE##*/} - WORKSPACE_PARENT="/home/runner/work/${REPO_NAME}" - WORKSPACE="${WORKSPACE_PARENT}/${REPO_NAME}" - # - pw adduser -n ${TEST_USER} -d /root/ -g wheel -c "Coreutils user to build" -w random - chown -R ${TEST_USER}:wheel /root/ "${WORKSPACE_PARENT}"/ - whoami - # - # Further work needs to be done in a sudo as we are changing users - sudo -i -u ${TEST_USER} bash << EOF - set -e - whoami - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh -y -c rustfmt,clippy --profile=minimal -t stable - . ${HOME}/.cargo/env - ## VARs setup - cd "${WORKSPACE}" - unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in - ''|0|f|false|n|no|off) FAULT_TYPE=warning ;; - *) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;; - esac; - FAULT_PREFIX=\$(echo "\${FAULT_TYPE}" | tr '[:lower:]' '[:upper:]') - # * determine sub-crate utility list - UTILITY_LIST="\$(./util/show-utils.sh --features ${{ matrix.job.features }})" - CARGO_UTILITY_LIST_OPTIONS="\$(for u in \${UTILITY_LIST}; do echo -n "-puu_\${u} "; done;)" - ## Info - # environment - echo "## environment" - echo "CI='${CI}'" - echo "REPO_NAME='${REPO_NAME}'" - echo "TEST_USER='${TEST_USER}'" - echo "WORKSPACE_PARENT='${WORKSPACE_PARENT}'" - echo "WORKSPACE='${WORKSPACE}'" - echo "FAULT_PREFIX='\${FAULT_PREFIX}'" - echo "UTILITY_LIST='\${UTILITY_LIST}'" - env | sort - # tooling info - echo "## tooling info" - cargo -V - rustc -V - # - # To ensure that files are cleaned up, we don't want to exit on error - set +e - unset FAULT - ## cargo fmt testing - echo "## cargo fmt testing" - # * convert any errors/warnings to GHA UI annotations; ref: - S=\$(cargo fmt -- --check) && printf "%s\n" "\$S" || { printf "%s\n" "\$S" ; printf "%s\n" "\$S" | sed -E -n -e "s/^Diff[[:space:]]+in[[:space:]]+\${PWD//\//\\\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*\$/::\${FAULT_TYPE} file=\1,line=\2::\${FAULT_PREFIX}: \\\`cargo fmt\\\`: style violation (file:'\1', line:\2; use \\\`cargo fmt -- \"\1\"\\\`)/p" ; FAULT=true ; } - ## cargo clippy lint testing - if [ -z "\${FAULT}" ]; then - echo "## cargo clippy lint testing" - # * convert any warnings to GHA UI annotations; ref: - S=\$(cargo clippy --all-targets \${CARGO_UTILITY_LIST_OPTIONS} -- -D warnings 2>&1) && printf "%s\n" "\$S" || { printf "%s\n" "\$S" ; printf "%s" "\$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*\$/::\${FAULT_TYPE} file=\2,line=\3,col=\4::\${FAULT_PREFIX}: \\\`cargo clippy\\\`: \1 (file:'\2', line:\3)/p;" -e '}' ; FAULT=true ; } - fi - # Clean to avoid to rsync back the files - cargo clean - if [ -n "\${FAIL_ON_FAULT}" ] && [ -n "\${FAULT}" ]; then exit 1 ; fi - EOF - - test: - name: Tests - runs-on: ${{ matrix.job.os }} - timeout-minutes: 90 - strategy: - fail-fast: false - matrix: - job: - - { os: ubuntu-24.04 , features: unix } - env: - mem: 4096 - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: Swatinem/rust-cache@v2 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 - - name: Prepare, build and test - uses: vmactions/freebsd-vm@v1.2.0 - with: - usesh: true - sync: rsync - copyback: false - prepare: pkg install -y curl gmake sudo - run: | - ## Prepare, build, and test - # implementation modelled after ref: - # * NOTE: All steps need to be run in this block, otherwise, we are operating back on the mac host - set -e - # - # We need a file-descriptor file system to test test_ls::test_ls_io_errors - mount -t fdescfs fdesc /dev/fd - # - TEST_USER=tester - REPO_NAME=${GITHUB_WORKSPACE##*/} - WORKSPACE_PARENT="/home/runner/work/${REPO_NAME}" - WORKSPACE="${WORKSPACE_PARENT}/${REPO_NAME}" - # - pw adduser -n ${TEST_USER} -d /root/ -g wheel -c "Coreutils user to build" -w random - # chown -R ${TEST_USER}:wheel /root/ "${WORKSPACE_PARENT}"/ - chown -R ${TEST_USER}:wheel /root/ "${WORKSPACE_PARENT}"/ - whoami - # - # Further work needs to be done in a sudo as we are changing users - sudo -i -u ${TEST_USER} sh << EOF - set -e - whoami - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh -y --profile=minimal - . $HOME/.cargo/env - # Install nextest - mkdir -p ~/.cargo/bin - curl -LsSf https://get.nexte.st/latest/freebsd | tar zxf - -C ~/.cargo/bin - ## Info - # environment - echo "## environment" - echo "CI='${CI}'" - echo "REPO_NAME='${REPO_NAME}'" - echo "TEST_USER='${TEST_USER}'" - echo "WORKSPACE_PARENT='${WORKSPACE_PARENT}'" - echo "WORKSPACE='${WORKSPACE}'" - env | sort - # tooling info - echo "## tooling info" - cargo -V - cargo nextest --version - rustc -V - # - # To ensure that files are cleaned up, we don't want to exit on error - set +e - cd "${WORKSPACE}" - unset FAULT - cargo build || FAULT=1 - export PATH=~/.cargo/bin:${PATH} - export RUST_BACKTRACE=1 - export CARGO_TERM_COLOR=always - if (test -z "\$FAULT"); then cargo nextest run --hide-progress-bar --profile ci --features '${{ matrix.job.features }}' || FAULT=1 ; fi - if (test -z "\$FAULT"); then cargo nextest run --hide-progress-bar --profile ci --all-features -p uucore || FAULT=1 ; fi - # Clean to avoid to rsync back the files - cargo clean - if (test -n "\$FAULT"); then exit 1 ; fi - EOF diff --git a/.github/workflows/fuzzing.yml b/.github/workflows/fuzzing.yml deleted file mode 100644 index e7da4b5926d..00000000000 --- a/.github/workflows/fuzzing.yml +++ /dev/null @@ -1,281 +0,0 @@ -name: Fuzzing - -# spell-checker:ignore fuzzer dtolnay Swatinem - -on: - pull_request: - push: - branches: - - '*' - -permissions: - contents: read # to fetch code (actions/checkout) - -# End the current execution if there is a new changeset in the PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -jobs: - fuzz-build: - name: Build the fuzzers - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly - - name: Install `cargo-fuzz` - run: cargo install cargo-fuzz - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "cargo-fuzz-cache-key" - cache-directories: "fuzz/target" - - name: Run `cargo-fuzz build` - run: cargo +nightly fuzz build - - fuzz-run: - needs: fuzz-build - name: Fuzz - runs-on: ubuntu-latest - timeout-minutes: 5 - env: - RUN_FOR: 60 - strategy: - matrix: - test-target: - - { name: fuzz_test, should_pass: true } - # https://github.com/uutils/coreutils/issues/5311 - - { name: fuzz_date, should_pass: false } - - { name: fuzz_expr, should_pass: true } - - { name: fuzz_printf, should_pass: true } - - { name: fuzz_echo, should_pass: true } - - { name: fuzz_seq, should_pass: false } - - { name: fuzz_sort, should_pass: false } - - { name: fuzz_wc, should_pass: false } - - { name: fuzz_cut, should_pass: false } - - { name: fuzz_split, should_pass: false } - - { name: fuzz_tr, should_pass: false } - - { name: fuzz_env, should_pass: false } - - { name: fuzz_cksum, should_pass: false } - - { name: fuzz_parse_glob, should_pass: true } - - { name: fuzz_parse_size, should_pass: true } - - { name: fuzz_parse_time, should_pass: true } - - { name: fuzz_seq_parse_number, should_pass: true } - - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly - - name: Install `cargo-fuzz` - run: cargo install cargo-fuzz - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "cargo-fuzz-cache-key" - cache-directories: "fuzz/target" - - name: Restore Cached Corpus - uses: actions/cache/restore@v4 - with: - key: corpus-cache-${{ matrix.test-target.name }} - path: | - fuzz/corpus/${{ matrix.test-target.name }} - - name: Run ${{ matrix.test-target.name }} for XX seconds - id: run_fuzzer - shell: bash - continue-on-error: ${{ !matrix.test-target.name.should_pass }} - run: | - mkdir -p fuzz/stats - STATS_FILE="fuzz/stats/${{ matrix.test-target.name }}.txt" - cargo +nightly fuzz run ${{ matrix.test-target.name }} -- -max_total_time=${{ env.RUN_FOR }} -timeout=${{ env.RUN_FOR }} -detect_leaks=0 -print_final_stats=1 2>&1 | tee "$STATS_FILE" - - # Extract key stats from the output - if grep -q "stat::number_of_executed_units" "$STATS_FILE"; then - RUNS=$(grep "stat::number_of_executed_units" "$STATS_FILE" | awk '{print $2}') - echo "runs=$RUNS" >> "$GITHUB_OUTPUT" - else - echo "runs=unknown" >> "$GITHUB_OUTPUT" - fi - - if grep -q "stat::average_exec_per_sec" "$STATS_FILE"; then - EXEC_RATE=$(grep "stat::average_exec_per_sec" "$STATS_FILE" | awk '{print $2}') - echo "exec_rate=$EXEC_RATE" >> "$GITHUB_OUTPUT" - else - echo "exec_rate=unknown" >> "$GITHUB_OUTPUT" - fi - - if grep -q "stat::new_units_added" "$STATS_FILE"; then - NEW_UNITS=$(grep "stat::new_units_added" "$STATS_FILE" | awk '{print $2}') - echo "new_units=$NEW_UNITS" >> "$GITHUB_OUTPUT" - else - echo "new_units=unknown" >> "$GITHUB_OUTPUT" - fi - - # Save should_pass value to file for summary job to use - echo "${{ matrix.test-target.should_pass }}" > "fuzz/stats/${{ matrix.test-target.name }}.should_pass" - - # Print stats to job output for immediate visibility - echo "----------------------------------------" - echo "FUZZING STATISTICS FOR ${{ matrix.test-target.name }}" - echo "----------------------------------------" - echo "Runs: $(grep -q "stat::number_of_executed_units" "$STATS_FILE" && grep "stat::number_of_executed_units" "$STATS_FILE" | awk '{print $2}' || echo "unknown")" - echo "Execution Rate: $(grep -q "stat::average_exec_per_sec" "$STATS_FILE" && grep "stat::average_exec_per_sec" "$STATS_FILE" | awk '{print $2}' || echo "unknown") execs/sec" - echo "New Units: $(grep -q "stat::new_units_added" "$STATS_FILE" && grep "stat::new_units_added" "$STATS_FILE" | awk '{print $2}' || echo "unknown")" - echo "Expected: ${{ matrix.test-target.name.should_pass }}" - if grep -q "SUMMARY: " "$STATS_FILE"; then - echo "Status: $(grep "SUMMARY: " "$STATS_FILE" | head -1)" - else - echo "Status: Completed" - fi - echo "----------------------------------------" - - # Add summary to GitHub step summary - echo "### Fuzzing Results for ${{ matrix.test-target.name }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY - echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY - - if grep -q "stat::number_of_executed_units" "$STATS_FILE"; then - echo "| Runs | $(grep "stat::number_of_executed_units" "$STATS_FILE" | awk '{print $2}') |" >> $GITHUB_STEP_SUMMARY - fi - - if grep -q "stat::average_exec_per_sec" "$STATS_FILE"; then - echo "| Execution Rate | $(grep "stat::average_exec_per_sec" "$STATS_FILE" | awk '{print $2}') execs/sec |" >> $GITHUB_STEP_SUMMARY - fi - - if grep -q "stat::new_units_added" "$STATS_FILE"; then - echo "| New Units | $(grep "stat::new_units_added" "$STATS_FILE" | awk '{print $2}') |" >> $GITHUB_STEP_SUMMARY - fi - - echo "| Should pass | ${{ matrix.test-target.should_pass }} |" >> $GITHUB_STEP_SUMMARY - - if grep -q "SUMMARY: " "$STATS_FILE"; then - echo "| Status | $(grep "SUMMARY: " "$STATS_FILE" | head -1) |" >> $GITHUB_STEP_SUMMARY - else - echo "| Status | Completed |" >> $GITHUB_STEP_SUMMARY - fi - - echo "" >> $GITHUB_STEP_SUMMARY - - name: Save Corpus Cache - uses: actions/cache/save@v4 - with: - key: corpus-cache-${{ matrix.test-target.name }} - path: | - fuzz/corpus/${{ matrix.test-target.name }} - - name: Upload Stats - uses: actions/upload-artifact@v4 - with: - name: fuzz-stats-${{ matrix.test-target.name }} - path: | - fuzz/stats/${{ matrix.test-target.name }}.txt - fuzz/stats/${{ matrix.test-target.name }}.should_pass - retention-days: 5 - fuzz-summary: - needs: fuzz-run - name: Fuzzing Summary - runs-on: ubuntu-latest - if: always() - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Download all stats - uses: actions/download-artifact@v4 - with: - path: fuzz/stats-artifacts - pattern: fuzz-stats-* - merge-multiple: true - - name: Prepare stats directory - run: | - mkdir -p fuzz/stats - # Debug: List content of stats-artifacts directory - echo "Contents of stats-artifacts directory:" - find fuzz/stats-artifacts -type f | sort - - # Extract files from the artifact directories - handle nested directories - find fuzz/stats-artifacts -type f -name "*.txt" -exec cp {} fuzz/stats/ \; - find fuzz/stats-artifacts -type f -name "*.should_pass" -exec cp {} fuzz/stats/ \; - - # Debug information - echo "Contents of stats directory after extraction:" - ls -la fuzz/stats/ - echo "Contents of should_pass files (if any):" - cat fuzz/stats/*.should_pass 2>/dev/null || echo "No should_pass files found" - - name: Generate Summary - run: | - echo "# Fuzzing Summary" > fuzzing_summary.md - echo "" >> fuzzing_summary.md - echo "| Target | Runs | Exec/sec | New Units | Should pass | Status |" >> fuzzing_summary.md - echo "|--------|------|----------|-----------|-------------|--------|" >> fuzzing_summary.md - - TOTAL_RUNS=0 - TOTAL_NEW_UNITS=0 - - for stat_file in fuzz/stats/*.txt; do - TARGET=$(basename "$stat_file" .txt) - SHOULD_PASS_FILE="${stat_file%.*}.should_pass" - - # Get expected status - if [ -f "$SHOULD_PASS_FILE" ]; then - EXPECTED=$(cat "$SHOULD_PASS_FILE") - else - EXPECTED="unknown" - fi - - # Extract runs - if grep -q "stat::number_of_executed_units" "$stat_file"; then - RUNS=$(grep "stat::number_of_executed_units" "$stat_file" | awk '{print $2}') - TOTAL_RUNS=$((TOTAL_RUNS + RUNS)) - else - RUNS="unknown" - fi - - # Extract execution rate - if grep -q "stat::average_exec_per_sec" "$stat_file"; then - EXEC_RATE=$(grep "stat::average_exec_per_sec" "$stat_file" | awk '{print $2}') - else - EXEC_RATE="unknown" - fi - - # Extract new units added - if grep -q "stat::new_units_added" "$stat_file"; then - NEW_UNITS=$(grep "stat::new_units_added" "$stat_file" | awk '{print $2}') - if [[ "$NEW_UNITS" =~ ^[0-9]+$ ]]; then - TOTAL_NEW_UNITS=$((TOTAL_NEW_UNITS + NEW_UNITS)) - fi - else - NEW_UNITS="unknown" - fi - - # Extract status - if grep -q "SUMMARY: " "$stat_file"; then - STATUS=$(grep "SUMMARY: " "$stat_file" | head -1) - else - STATUS="Completed" - fi - - echo "| $TARGET | $RUNS | $EXEC_RATE | $NEW_UNITS | $EXPECTED | $STATUS |" >> fuzzing_summary.md - done - - echo "" >> fuzzing_summary.md - echo "## Overall Statistics" >> fuzzing_summary.md - echo "" >> fuzzing_summary.md - echo "- **Total runs:** $TOTAL_RUNS" >> fuzzing_summary.md - echo "- **Total new units discovered:** $TOTAL_NEW_UNITS" >> fuzzing_summary.md - echo "- **Average execution rate:** $(grep -h "stat::average_exec_per_sec" fuzz/stats/*.txt | awk '{sum += $2; count++} END {if (count > 0) print sum/count " execs/sec"; else print "unknown"}')" >> fuzzing_summary.md - - # Add count by expected status - echo "- **Tests expected to pass:** $(find fuzz/stats -name "*.should_pass" -exec cat {} \; | grep -c "true")" >> fuzzing_summary.md - echo "- **Tests expected to fail:** $(find fuzz/stats -name "*.should_pass" -exec cat {} \; | grep -c "false")" >> fuzzing_summary.md - - # Write to GitHub step summary - cat fuzzing_summary.md >> $GITHUB_STEP_SUMMARY - - name: Show Summary - run: | - cat fuzzing_summary.md - - name: Upload Summary - uses: actions/upload-artifact@v4 - with: - name: fuzzing-summary - path: fuzzing_summary.md - retention-days: 5 diff --git a/util/run-gnu-test.sh b/util/run-gnu-test.sh index 7fa52f84ee0..00996d271eb 100755 --- a/util/run-gnu-test.sh +++ b/util/run-gnu-test.sh @@ -94,9 +94,9 @@ fi if test "$1" != "run-root"; then # run the regular tests if test $# -ge 1; then - timeout -sKILL 4h "${MAKE}" -j "$("${NPROC}")" check TESTS="$SPECIFIC_TESTS" SUBDIRS=. RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes VERBOSE=no gl_public_submodule_commit="" srcdir="${path_GNU}" || : # Kill after 4 hours in case something gets stuck in make + timeout -sKILL 4h "${MAKE}" -j "$("${NPROC}")" check TESTS="$SPECIFIC_TESTS" SUBDIRS=. RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes VERBOSE=yes gl_public_submodule_commit="" srcdir="${path_GNU}" || : # Kill after 4 hours in case something gets stuck in make else - timeout -sKILL 4h "${MAKE}" -j "$("${NPROC}")" check SUBDIRS=. RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes VERBOSE=no gl_public_submodule_commit="" srcdir="${path_GNU}" || : # Kill after 4 hours in case something gets stuck in make + timeout -sKILL 4h "${MAKE}" -j "$("${NPROC}")" check SUBDIRS=. RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes VERBOSE=yes gl_public_submodule_commit="" srcdir="${path_GNU}" || : # Kill after 4 hours in case something gets stuck in make fi else # in case we would like to run tests requiring root