Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Install additional dependencies for riscv64 CI workflow #6

Install additional dependencies for riscv64 CI workflow

Install additional dependencies for riscv64 CI workflow #6

Workflow file for this run

name: CICD
# spell-checker:ignore (abbrev/names) CACHEDIR 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 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 nofeatures nullglob onexitbegin onexitend pell runtest Swatinem tempfile testsuite toybox uutils libsystemd codspeed
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@v6
# 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@v6
# 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: <https://github.com/est31/cargo-udeps/issues/73>
# - 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@v6
# 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/[email protected]
# - name: Install/setup prerequisites
# shell: bash
# run: |
# sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu 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@v21
# 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@v6
# 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/[email protected]
# - 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@v6
# 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: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
# 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@v6
# with:
# persist-credentials: false
# - uses: dtolnay/rust-toolchain@stable
# with:
# target: aarch64-unknown-linux-gnu
# - uses: taiki-e/install-action@nextest
# - uses: Swatinem/rust-cache@v2
# # Test build on the system missing libselinux (don't install libselinux1-dev at here)
# - name: Run sccache-cache
# uses: mozilla-actions/[email protected]
# - name: "`make build`"
# # Also check that target/CACHEDIR.TAG is created on a fresh checkout
# shell: bash
# run: |
# set -x
# # Target directory must not exist to start with, otherwise cargo
# # will not create target/CACHEDIR.TAG.
# if [[ -d target ]]; then
# mv -T target target.cache
# fi
# # Check that we don't cross-build uudoc
# # also do not try to generate manpages for part of hashsum
# make install-manpages PREFIX=/tmp/usr UTILS=true RUSTC_ARCH="--target aarch64-unknown-linux-gnu"
# # build (host)
# make build
# echo "Check that target directory will be ignored by backup tools"
# test -f target/CACHEDIR.TAG
# # Restore cache for target/release (we only did a debug build)
# mv -t target/ target.cache/release 2>/dev/null || true
# - name: "`make nextest`"
# shell: bash
# run: make nextest PROFILE=ci CARGOFLAGS="--hide-progress-bar"
# env:
# RUST_BACKTRACE: "1"
# - name: "`make install PROFILE=release-fast COMPLETIONS=n MANPAGES=n LOCALES=n`"
# shell: bash
# run: |
# set -x
# DESTDIR=/tmp/ make PROFILE=release-fast COMPLETIONS=n MANPAGES=n LOCALES=n install
# # Check that utils are built with given profile
# ./target/release-fast/true
# # 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.bash
# ! test -f /tmp/usr/local/share/fish/vendor_completions.d/cat.fish
# env:
# RUST_BACKTRACE: "1"
# - name: "`make install`"
# shell: bash
# run: |
# set -x
# 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/md5sum.1
# # Check that the completion is present
# test -f /tmp/usr/local/share/zsh/site-functions/_b2sum
# test -f /tmp/usr/local/share/bash-completion/completions/head.bash
# test -f /tmp/usr/local/share/fish/vendor_completions.d/cat.fish
# env:
# RUST_BACKTRACE: "1"
# - name: "`make uninstall`"
# shell: bash
# run: |
# set -x
# 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.bash
# ! test -f /tmp/usr/local/share/fish/vendor_completions.d/cat.fish
# - name: "`make install MULTICALL=n`"
# shell: bash
# run: |
# set -x
# DESTDIR=/tmp/ make PROFILE=release MULTICALL=n install
# # Check that the utils are present
# test -f /tmp/usr/local/bin/hashsum
# # Check that hashsum symlinks are present
# test -h /tmp/usr/local/bin/b2sum
# test -h /tmp/usr/local/bin/md5sum
# test -h /tmp/usr/local/bin/sha1sum
# test -h /tmp/usr/local/bin/sha224sum
# test -h /tmp/usr/local/bin/sha256sum
# test -h /tmp/usr/local/bin/sha384sum
# test -h /tmp/usr/local/bin/sha512sum
# - name: "`make install MULTICALL=y LN=ln -svf`"
# shell: bash
# run: |
# set -x
# DESTDIR=/tmp/ make PROFILE=release MULTICALL=y LN="ln -svf" install
# # Check that relative symlinks of hashsum are present
# [ $(readlink /tmp/usr/local/bin/b2sum) = coreutils ]
# [ $(readlink /tmp/usr/local/bin/md5sum) = coreutils ]
# [ $(readlink /tmp/usr/local/bin/sha512sum) = coreutils ]
# - name: "`make UTILS=XXX`"
# shell: bash
# run: |
# set -x
# # Regression-test for https://github.com/uutils/coreutils/issues/8701
# make UTILS="rm chmod chown chgrp mv du"
# # Verifies that
# # 1. there is no "error: none of the selected packages contains this
# # feature: feat_external_libstdbuf"
# # 2. the makefile doesn't try to install libstdbuf even though stdbuf is skipped
# DESTDIR=/tmp/ make SKIP_UTILS="stdbuf" install
# 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@v6
# 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/[email protected]
# - 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@v6
# 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/[email protected]
# - 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@v6
# with:
# persist-credentials: false
# - uses: dtolnay/rust-toolchain@stable
# - uses: Swatinem/rust-cache@v2
# - name: Run sccache-cache
# uses: mozilla-actions/[email protected]
# - name: Install dependencies
# shell: bash
# run: |
# ## Install dependencies
# sudo apt-get update
# sudo apt-get install libselinux1-dev libsystemd-dev
# - name: "`make install`"
# shell: bash
# run: |
# ## `make install`
# make install DESTDIR=target/size-release/
# make install MULTICALL=y LN="ln -vf" DESTDIR=target/size-multi-release/
# # strip the results
# strip target/size*/usr/local/bin/*
# - name: Test for hardlinks
# shell: bash
# run: |
# [ $(stat -c %i target/size-multi-release/usr/local/bin/cp) = $(stat -c %i target/size-multi-release/usr/local/bin/coreutils) ]
# - 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@v11
# with:
# workflow: CICD.yml
# name: individual-size-result
# repo: uutils/coreutils
# path: dl
# - name: Download the previous size result
# uses: dawidd6/action-download-artifact@v11
# 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@v5
# with:
# name: individual-size-result
# path: individual-size-result.json
# - name: Upload the size result
# uses: actions/upload-artifact@v5
# 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 , default-features, features , use-cross , toolchain, skip-tests, workspace-tests, skip-package, skip-publish }
# - { 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: RISCV64 , target: riscv64gc-unknown-linux-gnu , features: feat_os_unix, use-cross: no}
# - { os: ubuntu-latest , target: aarch64-unknown-linux-musl , features: feat_os_unix_musl , 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_musl , use-cross: use-cross }
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: "feat_os_unix,test_risky_names", use-cross: use-cross, skip-publish: true }
# - { 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_musl , use-cross: use-cross }
# - { os: ubuntu-latest , target: x86_64-unknown-redox , features: feat_os_unix_redox , use-cross: redoxer , skip-tests: true }
# - { os: ubuntu-latest , target: wasm32-unknown-unknown , default-features: false, features: uucore/format, skip-tests: true, skip-package: true, skip-publish: true }
# - { os: macos-latest , target: aarch64-apple-darwin , features: feat_os_macos, workspace-tests: true } # M1 CPU
# # PR #7964: Mac should still build even if the feature is not enabled. Do not publish this.
# - { os: macos-latest , target: aarch64-apple-darwin , workspace-tests: true, skip-publish: true } # M1 CPU
# - { os: macos-latest , 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@v6
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_MIN_SRV }}
targets: ${{ matrix.job.target }}
- name: Install dependencies for RISC-V
if: matrix.job.target == 'riscv64gc-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y libatomic1 # fix -> /xx/node: error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory
sudo apt-get install jq binutils-riscv64-linux-gnu build-essential -y
- uses: Swatinem/rust-cache@v2
with:
key: "${{ matrix.job.os }}_${{ matrix.job.target }}"
- name: Run sccache-cache
if: matrix.job.target != 'riscv64gc-unknown-linux-gnu'
uses: mozilla-actions/[email protected]
- name: set up RUSTC_WRAPPER
if: matrix.job.target != 'riscv64gc-unknown-linux-gnu'
run: echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
- 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 ;;
riscv64gc-*) TARGET_ARCH=riscv64 ;;
arm-*-*hf) TARGET_ARCH=armhf ;;
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
# 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_DEFAULT_FEATURES_OPTION
CARGO_DEFAULT_FEATURES_OPTION='' ;
if [ "${{ matrix.job.default-features }}" == "false" ]; then CARGO_DEFAULT_FEATURES_OPTION='--no-default-features' ; fi
outputs CARGO_DEFAULT_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
# needed for target "aarch64-apple-darwin". There are two jobs, and the difference between them is whether "features" is set
if [ -z "${{ matrix.job.features }}" ]; then ARTIFACTS_SUFFIX='-nofeatures' ; fi
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
# * executable for `strip`?
STRIP="strip"
case ${{ matrix.job.target }} in
aarch64-*-linux-*) STRIP="aarch64-linux-gnu-strip" ;;
riscv64gc-*-linux-*) STRIP="riscv64-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: [email protected]
- name: Create all needed build/work directories
shell: bash
run: |
## Create build/work space
mkdir -p '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}'
- 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
;;
riscv64gc-unknown-linux-*)
sudo apt-get -y update
sudo apt-get -y install gcc-riscv64-linux-gnu
;;
*-redox*)
sudo apt-get -y update
sudo apt-get -y install fuse3 libfuse-dev
;;
esac
case '${{ matrix.job.os }}' in
macos-latest) brew install coreutils ;; # needed for testing
esac
case '${{ matrix.job.os }}' in
ubuntu-*)
# selinux and systemd headers needed to build tests
sudo apt-get -y update
sudo apt-get -y install libselinux1-dev libsystemd-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, and "system boot" entry is missing.
# The account also has empty gecos fields.
# To work around these issues for pinky (and who) tests, we create a fake utmp file with a
# system boot entry and a login entry for the GH runner account.
FAKE_UTMP_2='[2] [00000] [~~ ] [reboot] [~ ] [6.0.0-test] [0.0.0.0] [2022-02-22T22:11:22,222222+00:00]'
FAKE_UTMP_7='[7] [999999] [tty2] [runner] [tty2] [ ] [0.0.0.0] [2022-02-22T22:22:22,222222+00:00]'
(echo "$FAKE_UTMP_2" ; echo "$FAKE_UTMP_7") | 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
# add user with digital username for testing with issue #7787
echo 200:x:2000:2000::/home/200:/bin/bash | sudo tee -a /etc/passwd
echo 200:x:2000: | sudo tee -a /etc/group
;;
esac
- uses: taiki-e/install-action@v2
if: steps.vars.outputs.CARGO_CMD == 'redoxer'
with:
tool: [email protected]
- 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 }} ${{ steps.vars.outputs.CARGO_DEFAULT_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 }} ${{ steps.vars.outputs.CARGO_DEFAULT_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 }} ${{ steps.vars.outputs.CARGO_DEFAULT_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@v5
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
if: matrix.job.skip-package != true
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
- name: Publish
uses: softprops/action-gh-release@v2
if: steps.vars.outputs.DEPLOY && matrix.job.skip-publish != true
with:
draft: true
files: |
${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_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@v6
# with:
# persist-credentials: false
# - uses: Swatinem/rust-cache@v2
# - name: Run sccache-cache
# uses: mozilla-actions/[email protected]
# - 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@v5
# with:
# name: "${{ steps.summary.outputs.HASH }}"
# path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}"
# - name: Reserve test results summary
# uses: actions/upload-artifact@v5
# with:
# name: busybox-test-summary
# path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}"
# - name: Upload json results
# uses: actions/upload-artifact@v5
# 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@v6
# 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/[email protected]
# - 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@v5
# with:
# name: "${{ steps.summary.outputs.HASH }}"
# path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}"
# - name: Reserve test results summary
# uses: actions/upload-artifact@v5
# with:
# name: toybox-test-summary
# path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}"
# - name: Upload json results
# uses: actions/upload-artifact@v5
# 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@v6
# - uses: dtolnay/rust-toolchain@master
# with:
# toolchain: ${{ matrix.job.toolchain }}
# components: rustfmt
# - uses: taiki-e/install-action@v2
# with:
# tool: nextest,[email protected]
# - uses: Swatinem/rust-cache@v2
# - name: Run sccache-cache
# uses: mozilla-actions/[email protected]
# # - 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)
# 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, and "system boot" entry is missing.
# # The account also has empty gecos fields.
# # To work around these issues for pinky (and who) tests, we create a fake utmp file with a
# # system boot entry and a login entry for the GH runner account.
# FAKE_UTMP_2='[2] [00000] [~~ ] [reboot] [~ ] [6.0.0-test] [0.0.0.0] [2022-02-22T22:11:22,222222+00:00]'
# FAKE_UTMP_7='[7] [999999] [tty2] [runner] [tty2] [ ] [0.0.0.0] [2022-02-22T22:22:22,222222+00:00]'
# (echo "$FAKE_UTMP_2" ; echo "$FAKE_UTMP_7") | 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
# # add user with digital username for testing with issue #7787
# echo 200:x:2000:2000::/home/200:/bin/bash | sudo tee -a /etc/passwd
# echo 200:x:2000: | sudo tee -a /etc/group
# ;;
# 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 }}
# files: ${{ 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.job.os }}
# 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@v6
# with:
# persist-credentials: false
# - uses: dtolnay/rust-toolchain@stable
# - uses: Swatinem/rust-cache@v2
# - name: build and test all programs individually
# shell: bash
# run: |
# CARGO_FEATURES_OPTION='--features=${{ matrix.job.features }}' ;
# for f in $(util/show-utils.sh ${CARGO_FEATURES_OPTION})
# do
# echo "Building and testing $f"
# cargo test -p "uu_$f"
# done
# test_all_features:
# name: Test all features separately
# needs: [ min_version, deps ]
# runs-on: ${{ matrix.job.os }}
# 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 } https://github.com/uutils/coreutils/issues/7044
# steps:
# - uses: actions/checkout@v6
# with:
# persist-credentials: false
# - uses: dtolnay/rust-toolchain@stable
# - uses: Swatinem/rust-cache@v2
# - name: build and test all features individually
# shell: bash
# run: |
# command -v sudo && sudo rm -rf /usr/share/dotnet # avoid no space left
# CARGO_FEATURES_OPTION='--features=${{ matrix.job.features }}' ;
# for f in $(util/show-utils.sh ${CARGO_FEATURES_OPTION})
# 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@v6
# 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=4 --disk=30 --memory=4 --network=lima:user-v2 template:fedora
# - 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"
# test_selinux_stubs:
# name: Build/SELinux-Stubs (Non-Linux)
# needs: [ min_version, deps ]
# runs-on: ${{ matrix.job.os }}
# strategy:
# fail-fast: false
# matrix:
# job:
# - { os: macos-latest , features: feat_os_macos }
# - { os: windows-latest , features: feat_os_windows }
# steps:
# - uses: actions/checkout@v6
# with:
# persist-credentials: false
# - uses: dtolnay/rust-toolchain@stable
# - uses: Swatinem/rust-cache@v2
# - name: Build SELinux utilities as stubs
# run: cargo build -p uu_chcon -p uu_runcon
# - name: Verify stub binaries exist
# shell: bash
# run: |
# test -f target/debug/chcon || test -f target/debug/chcon.exe
# test -f target/debug/runcon || test -f target/debug/runcon.exe
# - name: Verify workspace builds with stubs
# run: cargo build --features ${{ matrix.job.features }}
# test_safe_traversal:
# name: Safe Traversal Security Check
# runs-on: ubuntu-latest
# needs: [ min_version, deps ]
# steps:
# - uses: actions/checkout@v6
# with:
# persist-credentials: false
# - uses: dtolnay/rust-toolchain@stable
# - uses: Swatinem/rust-cache@v2
# - name: Install strace
# run: sudo apt-get update && sudo apt-get install -y strace
# - name: Build utilities with safe traversal
# run: cargo build --release -p uu_rm -p uu_chmod -p uu_chown -p uu_chgrp -p uu_mv -p uu_du
# - name: Run safe traversal verification
# run: ./util/check-safe-traversal.sh