From 55f72b555d7aa2b715406da227898f42e1c0cbc7 Mon Sep 17 00:00:00 2001 From: Jeff Bailey Date: Sat, 22 Nov 2025 10:38:03 +0000 Subject: [PATCH] GitHub Actions workflow for running GNU tar tests This checks out GNU tar and runs its test suite against our built tar binary. The hooks in autotest aren't working correctly, so we manually overwrite the built binary with our generated binary for testing. --- .github/workflows/GnuTests.yml | 53 ++++++++++++++++++++++++++++++ util/build-gnu.sh | 60 ++++++++++++++++++++++++++++++++++ util/run-gnu-test.sh | 52 +++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 .github/workflows/GnuTests.yml create mode 100755 util/build-gnu.sh create mode 100755 util/run-gnu-test.sh diff --git a/.github/workflows/GnuTests.yml b/.github/workflows/GnuTests.yml new file mode 100644 index 0000000..63b8a4d --- /dev/null +++ b/.github/workflows/GnuTests.yml @@ -0,0 +1,53 @@ +name: GnuTests + +on: + pull_request: + push: + branches: + - '*' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + native: + name: Run GNU tests (native) + runs-on: ubuntu-24.04 + steps: + - name: Checkout code (uutils) + uses: actions/checkout@v4 + with: + path: 'uutils' + persist-credentials: false + + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + + - uses: Swatinem/rust-cache@v2 + with: + workspaces: "./uutils -> target" + + - name: Install dependencies + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y autoconf autopoint bison texinfo gperf gcc g++ gdb python3-pyinotify jq valgrind libacl1-dev libattr1-dev libcap-dev libselinux1-dev attr quilt gettext + + - name: Build binaries and GNU tar + shell: bash + run: | + cd 'uutils' + # This script will clone GNU tar and build everything + bash util/build-gnu.sh --release-build + + - name: Run GNU tests + shell: bash + run: | + cd 'uutils' + bash util/run-gnu-test.sh diff --git a/util/build-gnu.sh b/util/build-gnu.sh new file mode 100755 index 0000000..f91490a --- /dev/null +++ b/util/build-gnu.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -e + +ME="${0}" +ME_dir="$(dirname -- "$("${READLINK:-readlink}" -fm -- "${ME}")")" +REPO_main_dir="$(dirname -- "${ME_dir}")" + +# Default profile is 'debug' +UU_MAKE_PROFILE='debug' + +for arg in "$@" +do + if [ "$arg" == "--release-build" ]; then + UU_MAKE_PROFILE='release' + break + fi +done + +path_UUTILS=${path_UUTILS:-${REPO_main_dir}} +path_GNU="${path_GNU:-${path_UUTILS}/../gnu}" + +echo "Building uutils tar..." +cd "${path_UUTILS}" +cargo build --profile "${UU_MAKE_PROFILE}" --bin tarapp + +if [[ ! -z "$CARGO_TARGET_DIR" ]]; then + UU_BUILD_DIR="${CARGO_TARGET_DIR}/${UU_MAKE_PROFILE}" +else + UU_BUILD_DIR="${path_UUTILS}/target/${UU_MAKE_PROFILE}" +fi + +# Symlink tarapp to tar so tests find it as 'tar' +ln -sf "${UU_BUILD_DIR}/tarapp" "${UU_BUILD_DIR}/tar" +echo "Created symlink ${UU_BUILD_DIR}/tar -> tarapp" + +# Clone GNU tar if needed +if test ! -d "${path_GNU}/.git"; then + echo "Cloning GNU tar..." + git clone --recurse-submodules https://git.savannah.gnu.org/git/tar.git "${path_GNU}" + cd "${path_GNU}" + # Checkout v1.35 + git checkout v1.35 + + # Bootstrap requires gnulib. + # If git clone --recurse-submodules was used it might be there, but standard bootstrap fetches it. + # We need to make sure we have dependencies. + # FORCE_UNSAFE_CONFIGURE=1 might be needed if running as root in some envs, but usually fine. + ./bootstrap --skip-po +fi + +cd "${path_GNU}" + +if [ ! -f Makefile ]; then + echo "Configuring GNU tar..." + # Configure to build native tar (needed for test suite generation) + ./configure --quiet +fi + +echo "Building GNU tar (for test suite)..." +make -j$(nproc) diff --git a/util/run-gnu-test.sh b/util/run-gnu-test.sh new file mode 100755 index 0000000..770c796 --- /dev/null +++ b/util/run-gnu-test.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -e + +# Use GNU version for make, nproc, readlink on *BSD +case "$OSTYPE" in + *bsd*) + MAKE="gmake" + NPROC="gnproc" + READLINK="greadlink" + ;; + *) + MAKE="make" + NPROC="nproc" + READLINK="readlink" + ;; +esac + +ME="${0}" +ME_dir="$(dirname -- "$("${READLINK:-readlink}" -fm -- "${ME}")")" +REPO_main_dir="$(dirname -- "${ME_dir}")" + +path_UUTILS=${path_UUTILS:-${REPO_main_dir}} +path_GNU="${path_GNU:-${path_UUTILS}/../gnu}" + +# Determine profile +if [[ -d "${path_UUTILS}/target/release" ]]; then + UU_BUILD_DIR="${path_UUTILS}/target/release" +elif [[ -d "${path_UUTILS}/target/debug" ]]; then + UU_BUILD_DIR="${path_UUTILS}/target/debug" +else + echo "Could not find build directory in ${path_UUTILS}/target" + exit 1 +fi + +echo "Using uutils tar from: ${UU_BUILD_DIR}" + +cd "${path_GNU}" + +export RUST_BACKTRACE=1 + +# The GNU tar testsuite usually looks for 'tar' in the path or uses the one in src/ +# We force it to use ours by putting it first in PATH. +export PATH="${UU_BUILD_DIR}:$PATH" +export TAR="${UU_BUILD_DIR}/tar" + +echo "Running GNU tar tests..." + +# Run with timeout and make check +# We use TAR to set the tar binary for the testsuite +# Then we use $* to pass any additional user arguments (specific tests) +cp "${TAR}" src/tar +timeout -sKILL 4h "${MAKE}" -j "$("${NPROC}")" check