mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 23:02:38 +00:00
790884b177
- the build and test steps won't run until/unless Dependency and MSRV checks pass - code coverage won't run until/unless the build steps all pass ## [why] This helps make more efficient use of CI resources and can help more easily visualize build issues from the resultant GHA dashboard flow diagram.
864 lines
41 KiB
YAML
864 lines
41 KiB
YAML
name: CICD
|
|
|
|
# spell-checker:ignore (acronyms) CICD MSVC musl
|
|
# spell-checker:ignore (env/flags) Awarnings Ccodegen Coverflow Cpanic RUSTDOCFLAGS RUSTFLAGS Zpanic
|
|
# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain
|
|
# spell-checker:ignore (names) CodeCOV MacOS MinGW Peltoche rivy
|
|
# spell-checker:ignore (shell/tools) choco clippy dmake dpkg esac fakeroot gmake grcov halium lcov libssl mkdir popd printf pushd rustc rustfmt rustup shopt xargs
|
|
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend pell runtest tempfile testsuite uutils
|
|
|
|
# ToDO: [2021-06; rivy] change from `cargo-tree` to `cargo tree` once MSRV is >= 1.45
|
|
|
|
env:
|
|
PROJECT_NAME: coreutils
|
|
PROJECT_DESC: "Core universal (cross-platform) utilities"
|
|
PROJECT_AUTH: "uutils"
|
|
RUST_MIN_SRV: "1.47.0" ## MSRV v1.47.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: [push, pull_request]
|
|
|
|
jobs:
|
|
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 }}
|
|
# env:
|
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
|
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@v2
|
|
- name: Initialize workflow variables
|
|
id: vars
|
|
shell: bash
|
|
run: |
|
|
## VARs setup
|
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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
|
|
## note: requires 'nightly' toolchain b/c `cargo-udeps` uses the `rustc` '-Z save-analysis' option
|
|
## * ... ref: <https://github.com/est31/cargo-udeps/issues/73>
|
|
- name: Install `rust` toolchain
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: nightly
|
|
default: true
|
|
profile: minimal
|
|
- name: Install `cargo-udeps`
|
|
uses: actions-rs/install@v0.1
|
|
with:
|
|
crate: cargo-udeps
|
|
version: latest
|
|
use-tool-cache: false
|
|
env:
|
|
RUSTUP_TOOLCHAIN: stable
|
|
- 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
|
|
|
|
style_format:
|
|
name: Style/format
|
|
runs-on: ${{ matrix.job.os }}
|
|
# env:
|
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
job:
|
|
- { os: ubuntu-latest , features: feat_os_unix }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Initialize workflow variables
|
|
id: vars
|
|
shell: bash
|
|
run: |
|
|
## VARs setup
|
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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: Install `rust` toolchain
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: stable
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
components: rustfmt
|
|
- 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: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
|
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
|
|
- name: "`cargo fmt` testing of integration tests"
|
|
if: success() || failure() # run regardless of prior step success/failure
|
|
shell: bash
|
|
run: |
|
|
## `cargo fmt` testing of integration tests
|
|
unset fault
|
|
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
|
|
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
|
|
# 'tests' is the standard/usual integration test directory
|
|
if [ -d tests ]; then
|
|
# * 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>
|
|
S=$(find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s\n" "$S" | sed -E -n "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 ; }
|
|
fi
|
|
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:
|
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
|
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@v2
|
|
- name: Initialize workflow variables
|
|
id: vars
|
|
shell: bash
|
|
run: |
|
|
## VARs setup
|
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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 "-puu_${u}"; done;)"
|
|
outputs CARGO_UTILITY_LIST_OPTIONS
|
|
- name: Install/setup prerequisites
|
|
shell: bash
|
|
run: |
|
|
case '${{ matrix.job.os }}' in
|
|
macos-latest) brew install coreutils ;; # needed for show-utils.sh
|
|
esac
|
|
- name: Install `rust` toolchain
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: stable
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
components: clippy
|
|
- name: "`cargo clippy` lint testing"
|
|
shell: bash
|
|
run: |
|
|
## `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: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
|
S=$(cargo clippy --all-targets ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} ${{ steps.vars.outputs.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 ; }
|
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
|
|
|
style_spellcheck:
|
|
name: Style/spelling
|
|
runs-on: ${{ matrix.job.os }}
|
|
# env:
|
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
|
strategy:
|
|
matrix:
|
|
job:
|
|
- { os: ubuntu-latest , features: feat_os_unix }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Initialize workflow variables
|
|
id: vars
|
|
shell: bash
|
|
run: |
|
|
## VARs setup
|
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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
|
|
- name: Install/setup prerequisites
|
|
shell: bash
|
|
run: |
|
|
## Install/setup prerequisites
|
|
# * pin installed cspell to v4.2.8 (cspell v5+ is broken for NodeJS < v12)
|
|
## maint: [2021-11-10; rivy] `cspell` version may be advanced to v5 when used with NodeJS >= v12
|
|
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell@4.2.8 -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
|
|
# * `cspell`
|
|
## maint: [2021-11-10; rivy] the `--no-progress` option for `cspell` is a `cspell` v5+ option
|
|
# 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 ; }
|
|
S=$(cspell ${CSPELL_CFG_OPTION} --no-summary "**/*") && 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
|
|
|
|
min_version:
|
|
name: MinRustV # Minimum supported rust version (aka, MinSRV or MSRV)
|
|
runs-on: ${{ matrix.job.os }}
|
|
strategy:
|
|
matrix:
|
|
job:
|
|
- { os: ubuntu-latest , features: feat_os_unix }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Initialize workflow variables
|
|
id: vars
|
|
shell: bash
|
|
run: |
|
|
## VARs setup
|
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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: Install `rust` toolchain (v${{ env.RUST_MIN_SRV }})
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: ${{ env.RUST_MIN_SRV }}
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
- name: Install `cargo-tree` # for dependency information
|
|
uses: actions-rs/install@v0.1
|
|
with:
|
|
crate: cargo-tree
|
|
version: latest
|
|
use-tool-cache: true
|
|
env:
|
|
RUSTUP_TOOLCHAIN: stable
|
|
- 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)
|
|
cargo fetch --locked --quiet || { echo "::error file=Cargo.lock::Incompatible (or out-of-date) 'Cargo.lock' file; update using \`cargo +${{ env.RUST_MIN_SRV }} update\`" ; exit 1 ; }
|
|
- 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 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 tree --all --locked --no-dev-dependencies --no-indent ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} | grep -vE "$PWD" | sort --unique
|
|
- name: Test
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
command: test
|
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils
|
|
env:
|
|
RUSTFLAGS: "-Awarnings"
|
|
|
|
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@v2
|
|
- name: Install `rust` toolchain
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: stable
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
- 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>
|
|
cargo fetch --locked --quiet || { echo "::error file=Cargo.lock::'Cargo.lock' file requires update (use \`cargo +${{ env.RUST_MIN_SRV }} update\`)" ; exit 1 ; }
|
|
|
|
build_makefile:
|
|
name: Build/Makefile
|
|
needs: [ min_version, deps ]
|
|
runs-on: ${{ matrix.job.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
job:
|
|
- { os: ubuntu-latest , features: feat_os_unix }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Install/setup prerequisites
|
|
shell: bash
|
|
run: |
|
|
## Install/setup prerequisites
|
|
sudo apt-get -y update ; sudo apt-get -y install python3-sphinx ;
|
|
- name: Install `rust` toolchain
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: stable
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
- name: "`make build`"
|
|
shell: bash
|
|
run: |
|
|
make build
|
|
- name: "`make test`"
|
|
shell: bash
|
|
run: |
|
|
make test
|
|
|
|
build:
|
|
name: Build
|
|
needs: [ min_version, deps ]
|
|
runs-on: ${{ matrix.job.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
job:
|
|
# { os , target , cargo-options , features , use-cross , toolchain }
|
|
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf, features: feat_os_unix_gnueabihf, use-cross: use-cross, }
|
|
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf , use-cross: use-cross }
|
|
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
|
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
|
|
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
|
|
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
|
|
- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
|
- { os: ubuntu-18.04 , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
|
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
|
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
|
- { os: macos-latest , target: x86_64-apple-darwin , features: feat_os_macos }
|
|
- { os: windows-latest , target: i686-pc-windows-gnu , features: feat_os_windows }
|
|
- { 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 } ## note: requires rust >= 1.43.0 to link correctly
|
|
- { os: windows-latest , target: x86_64-pc-windows-msvc , features: feat_os_windows }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Initialize workflow variables
|
|
id: vars
|
|
shell: bash
|
|
run: |
|
|
## VARs setup
|
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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:8}
|
|
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 ;; 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_USE_CROSS (truthy)
|
|
CARGO_USE_CROSS='true' ; case '${{ matrix.job.use-cross }}' in ''|0|f|false|n|no) unset CARGO_USE_CROSS ;; esac;
|
|
outputs CARGO_USE_CROSS
|
|
# ** pass needed environment into `cross` container (iff `cross` not already configured via "Cross.toml")
|
|
if [ -n "${CARGO_USE_CROSS}" ] && [ ! -e "Cross.toml" ] ; then
|
|
printf "[build.env]\npassthrough = [\"CI\"]\n" > Cross.toml
|
|
fi
|
|
# * test only library and/or binaries for arm-type targets
|
|
unset CARGO_TEST_OPTIONS ; case '${{ matrix.job.target }}' in aarch64-* | arm-*) CARGO_TEST_OPTIONS="--bins" ;; esac;
|
|
outputs CARGO_TEST_OPTIONS
|
|
# * executable for `strip`?
|
|
STRIP="strip"
|
|
case ${{ matrix.job.target }} in
|
|
aarch64-*-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;;
|
|
arm-*-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;;
|
|
*-pc-windows-msvc) STRIP="" ;;
|
|
esac;
|
|
outputs STRIP
|
|
- 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-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
|
esac
|
|
case '${{ matrix.job.os }}' in
|
|
macos-latest) brew install coreutils ;; # needed for testing
|
|
esac
|
|
- 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-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
|
esac
|
|
case '${{ matrix.job.os }}' in
|
|
macos-latest) brew install coreutils ;; # needed for testing
|
|
esac
|
|
- name: rust toolchain ~ install
|
|
uses: actions-rs/toolchain@v1
|
|
# env:
|
|
# # Override auto-detection of RAM for Rustc install.
|
|
# # https://github.com/rust-lang/rustup/issues/2229#issuecomment-585855925
|
|
# RUSTUP_UNPACK_RAM: "21474836480"
|
|
with:
|
|
toolchain: ${{ steps.vars.outputs.TOOLCHAIN }}
|
|
target: ${{ matrix.job.target }}
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
- name: Initialize toolchain-dependent workflow variables
|
|
id: dep_vars
|
|
shell: bash
|
|
run: |
|
|
## Dependent VARs setup
|
|
outputs() { step_id="dep_vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
|
# * 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 "-puu_${u}"; done;)"
|
|
outputs CARGO_UTILITY_LIST_OPTIONS
|
|
- name: Install `cargo-tree` # for dependency information
|
|
uses: actions-rs/install@v0.1
|
|
with:
|
|
crate: cargo-tree
|
|
version: latest
|
|
use-tool-cache: true
|
|
env:
|
|
RUSTUP_TOOLCHAIN: stable
|
|
- 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 tree -V
|
|
# dependencies
|
|
echo "## dependency list"
|
|
cargo fetch --locked --quiet
|
|
cargo-tree tree --locked --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --all --no-dev-dependencies --no-indent | grep -vE "$PWD" | sort --unique
|
|
- name: Build
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
use-cross: ${{ steps.vars.outputs.CARGO_USE_CROSS }}
|
|
command: build
|
|
args: --release --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
|
|
- name: Test
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
use-cross: ${{ steps.vars.outputs.CARGO_USE_CROSS }}
|
|
command: test
|
|
args: --target=${{ matrix.job.target }} ${{ steps.vars.outputs.CARGO_TEST_OPTIONS}} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
|
|
- name: Test individual utilities
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
use-cross: ${{ steps.vars.outputs.CARGO_USE_CROSS }}
|
|
command: test
|
|
args: --target=${{ matrix.job.target }} ${{ steps.vars.outputs.CARGO_TEST_OPTIONS}} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }}
|
|
- name: Archive executable artifacts
|
|
uses: actions/upload-artifact@v2
|
|
with:
|
|
name: ${{ env.PROJECT_NAME }}-${{ matrix.job.target }}
|
|
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@v1
|
|
if: steps.vars.outputs.DEPLOY
|
|
with:
|
|
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 }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
job:
|
|
- { os: ubuntu-latest }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Install/setup prerequisites
|
|
shell: bash
|
|
run: |
|
|
## Install/setup prerequisites
|
|
make prepare-busytest
|
|
- name: Install `rust` toolchain
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: stable
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
- name: "Run BusyBox test suite"
|
|
shell: bash
|
|
run: |
|
|
## Run BusyBox test suite
|
|
bindir=$(pwd)/target/debug
|
|
cd tmp/busybox-*/testsuite
|
|
output=$(bindir=$bindir ./runtest 2>&1 || true)
|
|
printf "%s\n" "${output}"
|
|
n_fails=$(echo "$output" | grep "^FAIL:\s" | wc --lines)
|
|
if [ $n_fails -gt 0 ] ; then echo "::warning ::${n_fails}+ test failures" ; fi
|
|
|
|
test_freebsd:
|
|
name: Tests/FreeBSD test suite
|
|
needs: [ min_version, deps ]
|
|
runs-on: ${{ matrix.job.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
job:
|
|
- { os: macos-10.15 , features: unix } ## GHA MacOS-11.0 VM won't have VirtualBox; refs: <https://github.com/actions/virtual-environments/issues/4060> , <https://github.com/actions/virtual-environments/pull/4010>
|
|
env:
|
|
mem: 2048
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
- name: Prepare, build and test
|
|
## spell-checker:ignore (ToDO) sshfs usesh vmactions
|
|
uses: vmactions/freebsd-vm@v0.1.5
|
|
with:
|
|
usesh: true
|
|
# sync: sshfs
|
|
prepare: pkg install -y curl gmake sudo
|
|
run: |
|
|
## Prepare, build, and test
|
|
# implementation modelled after ref: <https://github.com/rust-lang/rustup/pull/2783>
|
|
# * 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="/Users/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/ "/Users/runner/work/${REPO_NAME}"/
|
|
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
|
|
## 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
|
|
rustc -V
|
|
#
|
|
cd "${WORKSPACE}"
|
|
unset FAULT
|
|
cargo build || FAULT=1
|
|
cargo test --features "${{ matrix.job.features }}" || FAULT=1
|
|
cargo test --features "${{ matrix.job.features }}" -p uucore || FAULT=1
|
|
# Clean to avoid to rsync back the files
|
|
cargo clean
|
|
if (test -n "$FAULT"); then exit 1 ; fi
|
|
EOF
|
|
|
|
coverage:
|
|
name: Code Coverage
|
|
needs: build
|
|
runs-on: ${{ matrix.job.os }}
|
|
strategy:
|
|
fail-fast: true
|
|
matrix:
|
|
# job: [ { os: ubuntu-latest }, { os: macos-latest }, { os: windows-latest } ]
|
|
job:
|
|
- { os: ubuntu-latest , features: unix }
|
|
- { os: macos-latest , features: macos }
|
|
- { os: windows-latest , features: windows }
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
# - 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="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; 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
|
|
# staging directory
|
|
STAGING='_staging'
|
|
outputs STAGING
|
|
# 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
|
|
- name: rust toolchain ~ install
|
|
uses: actions-rs/toolchain@v1
|
|
with:
|
|
toolchain: ${{ steps.vars.outputs.TOOLCHAIN }}
|
|
default: true
|
|
profile: minimal # minimal component installation (ie, no documentation)
|
|
- name: Initialize toolchain-dependent workflow variables
|
|
id: dep_vars
|
|
shell: bash
|
|
run: |
|
|
## Dependent VARs setup
|
|
outputs() { step_id="dep_vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
|
# * determine sub-crate utility list
|
|
UTILITY_LIST="$(./util/show-utils.sh ${CARGO_FEATURES_OPTION})"
|
|
CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo "-puu_${u}"; done;)"
|
|
outputs CARGO_UTILITY_LIST_OPTIONS
|
|
- name: Test uucore
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
command: test
|
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast -p uucore
|
|
env:
|
|
CARGO_INCREMENTAL: "0"
|
|
RUSTC_WRAPPER: ""
|
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
|
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
|
- name: Test
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
command: test
|
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast
|
|
env:
|
|
CARGO_INCREMENTAL: "0"
|
|
RUSTC_WRAPPER: ""
|
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
|
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
|
- name: Test individual utilities
|
|
uses: actions-rs/cargo@v1
|
|
with:
|
|
command: test
|
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }}
|
|
env:
|
|
CARGO_INCREMENTAL: "0"
|
|
RUSTC_WRAPPER: ""
|
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
|
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
|
- name: "`grcov` ~ install"
|
|
uses: actions-rs/install@v0.1
|
|
with:
|
|
crate: grcov
|
|
version: latest
|
|
use-tool-cache: false
|
|
- name: Generate coverage data (via `grcov`)
|
|
id: coverage
|
|
shell: bash
|
|
run: |
|
|
## Generate coverage data
|
|
COVERAGE_REPORT_DIR="target/debug"
|
|
COVERAGE_REPORT_FILE="${COVERAGE_REPORT_DIR}/lcov.info"
|
|
# GRCOV_IGNORE_OPTION='--ignore build.rs --ignore "/*" --ignore "[a-zA-Z]:/*"' ## `grcov` ignores these params when passed as an environment variable (why?)
|
|
# GRCOV_EXCLUDE_OPTION='--excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()"' ## `grcov` ignores these params when passed as an environment variable (why?)
|
|
mkdir -p "${COVERAGE_REPORT_DIR}"
|
|
# display coverage files
|
|
grcov . --output-type files --ignore build.rs --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" | sort --unique
|
|
# generate coverage report
|
|
grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()"
|
|
echo ::set-output name=report::${COVERAGE_REPORT_FILE}
|
|
- name: Upload coverage results (to Codecov.io)
|
|
uses: codecov/codecov-action@v1
|
|
# if: steps.vars.outputs.HAS_CODECOV_TOKEN
|
|
with:
|
|
# token: ${{ secrets.CODECOV_TOKEN }}
|
|
file: ${{ steps.coverage.outputs.report }}
|
|
## flags: IntegrationTests, UnitTests, ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
|
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
|
name: codecov-umbrella
|
|
fail_ci_if_error: false
|