diff --git a/.github/workflows/test-packages-input.yml b/.github/workflows/test-packages-input.yml new file mode 100644 index 0000000..2a83f9c --- /dev/null +++ b/.github/workflows/test-packages-input.yml @@ -0,0 +1,113 @@ +name: Test Packages Input + +# This workflow is a black-box integration test for the action's `packages` input. +# +# The fixture workspace contains three crates (package-a/package-b/package-c). Each crate writes a +# marker file (marker-package-*) when its tests run. We assert marker presence/absence to prove +# that: +# - when `packages` is empty, the action runs the whole workspace (`--all`) +# - when `packages` is provided, the action uses `-p ` and only runs those packages +# +# The fixture workspace also sets `default-members = ["package-a"]` to catch regressions where +# the action accidentally stops passing `--all` for the default (empty packages) case. + +on: + workflow_dispatch: + pull_request: + branches: [v1-master] + paths: + - "action.yml" + - "README.MD" + - ".github/workflows/test-packages-input.yml" + - "tests/fixtures/packages-input-workspace/**" + +jobs: + packages-input: + name: Packages Input - ${{ matrix.name }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: cargo empty (default all) + target: x86_64-unknown-linux-gnu + use_cross: false + use_tarpaulin: false + packages: "" + expect: "marker-package-a marker-package-b marker-package-c" + forbid: "" + + - name: cargo single + target: x86_64-unknown-linux-gnu + use_cross: false + use_tarpaulin: false + packages: | + package-b + expect: "marker-package-b" + forbid: "marker-package-a marker-package-c" + + - name: cargo multiple + target: x86_64-unknown-linux-gnu + use_cross: false + use_tarpaulin: false + packages: | + package-a + package-c + expect: "marker-package-a marker-package-c" + forbid: "marker-package-b" + + - name: cross multiple + target: aarch64-unknown-linux-gnu + use_cross: true + use_tarpaulin: false + packages: | + package-a + package-c + expect: "marker-package-a marker-package-c" + forbid: "marker-package-b" + + - name: tarpaulin single + target: x86_64-unknown-linux-gnu + use_cross: false + use_tarpaulin: true + packages: | + package-b + expect: "marker-package-b" + forbid: "marker-package-a marker-package-c" + + steps: + - name: Checkout Action Repository + uses: actions/checkout@v6 + + - name: Clean package markers + shell: bash + run: rm -f tests/fixtures/packages-input-workspace/marker-package-* + + - name: Run action + uses: ./ + with: + rust-project-path: tests/fixtures/packages-input-workspace + rust-toolchain: stable + target: ${{ matrix.target }} + use-cross: ${{ matrix.use_cross }} + use-tarpaulin: ${{ matrix.use_tarpaulin }} + upload-coverage: false + packages: ${{ matrix.packages }} + + - name: Assert markers + shell: bash + run: | + set -euo pipefail + root="tests/fixtures/packages-input-workspace" + expect="${{ matrix.expect }}" + forbid="${{ matrix.forbid }}" + + for f in $expect; do + test -f "$root/$f" || { echo "Missing marker: $f"; exit 1; } + done + + if [ -n "$forbid" ]; then + for f in $forbid; do + test ! -f "$root/$f" || { echo "Unexpected marker: $f"; exit 1; } + done + fi diff --git a/README.MD b/README.MD index 7fe0a6d..ce1470e 100644 --- a/README.MD +++ b/README.MD @@ -46,6 +46,9 @@ To use this action in your GitHub workflow, add the following step: codecov-flags: 'unittests' codecov-name: 'codecov-umbrella' features: 'feature1 feature2' + packages: | + package-a + package-b no-default-features: false use-cross: false additional-test-args: '--ignored --test-threads=1' @@ -70,6 +73,7 @@ To use this action in your GitHub workflow, add the following step: | `codecov-flags` | Flags to pass to Codecov | No | `'unittests'` | | `codecov-name` | Custom defined name for the upload | No | `'codecov-umbrella'` | | `features` | Space-separated list of features to enable during testing | No | `''` | +| `packages` | Multi-line list of package names to test (one per line). If empty, tests all packages in workspace | No | `''` | | `no-default-features` | Disable default features during testing | No | `false` | | `use-cross` | Use cross-rs for testing. If false, use cargo. | No | `false` | | `additional-test-args` | Additional arguments to pass to the cargo test command | No | `''` | @@ -204,4 +208,4 @@ rust-toolchain: 'beta' This GitHub Action is released under the [MIT License](LICENSE). -[rust-lw-binary]: https://github.com/Reloaded-Project/devops-rust-lightweight-binary \ No newline at end of file +[rust-lw-binary]: https://github.com/Reloaded-Project/devops-rust-lightweight-binary diff --git a/action.yml b/action.yml index 9b6d4c6..c326728 100644 --- a/action.yml +++ b/action.yml @@ -77,6 +77,11 @@ inputs: required: false default: "" + packages: + description: "Multi-line list of package names to test (one per line). If empty, tests all packages in workspace (--all)" + required: false + default: "" + runs: using: "composite" steps: @@ -90,6 +95,27 @@ runs: fi echo "SAFE_ADDITIONAL_TEST_ARGS=${SAFE_ADDITIONAL_TEST_ARGS}" >> $GITHUB_ENV + # Process packages input - convert multiline to space-separated, clean whitespace + SAFE_PACKAGES=$(echo "${{ inputs.packages }}" | tr -d '\r' | tr '\n\t' ' ' | tr -s ' ' | sed 's/^ *//;s/ *$//') + echo "SAFE_PACKAGES=${SAFE_PACKAGES}" >> $GITHUB_ENV + + # Build packages argument once and reuse across steps + if [ -n "$SAFE_PACKAGES" ]; then + PACKAGES_ARG="" + for pkg in $SAFE_PACKAGES; do + if [ -n "$pkg" ]; then + if [ -z "$PACKAGES_ARG" ]; then + PACKAGES_ARG="-p $pkg" + else + PACKAGES_ARG="$PACKAGES_ARG -p $pkg" + fi + fi + done + else + PACKAGES_ARG="--all" + fi + echo "PACKAGES_ARG=${PACKAGES_ARG}" >> $GITHUB_ENV + - name: Install Rust Toolchain if: inputs.install-rust-toolchain == 'true' uses: actions-rust-lang/setup-rust-toolchain@v1 @@ -164,7 +190,7 @@ runs: shell: bash working-directory: ${{ inputs.rust-project-path }} run: | - cargo +${{ inputs.rust-toolchain }} tarpaulin --all --out xml --engine llvm \ + cargo +${{ inputs.rust-toolchain }} tarpaulin $PACKAGES_ARG --out xml --engine llvm \ --features "${{ inputs.features }}" \ ${{ inputs.no-default-features == 'true' && '--no-default-features' || '' }} \ ${{ inputs.target != '' && format('--target "{0}"', inputs.target) || '' }} \ @@ -177,7 +203,7 @@ runs: shell: bash working-directory: ${{ inputs.rust-project-path }} run: | - cargo +${{ inputs.rust-toolchain }} test --all \ + cargo +${{ inputs.rust-toolchain }} test $PACKAGES_ARG \ --features "${{ inputs.features }}" \ ${{ inputs.no-default-features == 'true' && '--no-default-features' || '' }} \ ${{ inputs.target != '' && format('--target "{0}"', inputs.target) || '' }} \ @@ -190,7 +216,7 @@ runs: # the RUSTFLAGS are a hack around cross build errors on certain setups # https://github.com/cross-rs/cross/issues/1561 run: | - RUSTFLAGS="" cross +${{ inputs.rust-toolchain }} test --all \ + RUSTFLAGS="" cross +${{ inputs.rust-toolchain }} test $PACKAGES_ARG \ --features "${{ inputs.features }}" \ ${{ inputs.no-default-features == 'true' && '--no-default-features' || '' }} \ ${{ inputs.target != '' && format('--target "{0}"', inputs.target) || '' }} \ diff --git a/tests/fixtures/packages-input-workspace/Cargo.lock b/tests/fixtures/packages-input-workspace/Cargo.lock new file mode 100644 index 0000000..86db68e --- /dev/null +++ b/tests/fixtures/packages-input-workspace/Cargo.lock @@ -0,0 +1,15 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "package-a" +version = "0.1.0" + +[[package]] +name = "package-b" +version = "0.1.0" + +[[package]] +name = "package-c" +version = "0.1.0" diff --git a/tests/fixtures/packages-input-workspace/Cargo.toml b/tests/fixtures/packages-input-workspace/Cargo.toml new file mode 100644 index 0000000..9ef3c0f --- /dev/null +++ b/tests/fixtures/packages-input-workspace/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +resolver = "2" +members = [ + "package-a", + "package-b", + "package-c", +] + +# If the action accidentally drops `--all`, this makes the default behavior +# run only package-a. Our CI checks rely on this to detect regressions. +default-members = [ + "package-a", +] diff --git a/tests/fixtures/packages-input-workspace/package-a/Cargo.toml b/tests/fixtures/packages-input-workspace/package-a/Cargo.toml new file mode 100644 index 0000000..63162a0 --- /dev/null +++ b/tests/fixtures/packages-input-workspace/package-a/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "package-a" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/lib.rs" diff --git a/tests/fixtures/packages-input-workspace/package-a/src/lib.rs b/tests/fixtures/packages-input-workspace/package-a/src/lib.rs new file mode 100644 index 0000000..0fd07c3 --- /dev/null +++ b/tests/fixtures/packages-input-workspace/package-a/src/lib.rs @@ -0,0 +1,17 @@ +#[cfg(test)] +mod tests { + use std::fs; + use std::path::PathBuf; + + fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("package directory should have a workspace root parent") + .to_path_buf() + } + + #[test] + fn writes_marker() { + fs::write(workspace_root().join("marker-package-a"), "ok\n").unwrap(); + } +} diff --git a/tests/fixtures/packages-input-workspace/package-b/Cargo.toml b/tests/fixtures/packages-input-workspace/package-b/Cargo.toml new file mode 100644 index 0000000..9807a3f --- /dev/null +++ b/tests/fixtures/packages-input-workspace/package-b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "package-b" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/lib.rs" diff --git a/tests/fixtures/packages-input-workspace/package-b/src/lib.rs b/tests/fixtures/packages-input-workspace/package-b/src/lib.rs new file mode 100644 index 0000000..27f6b8f --- /dev/null +++ b/tests/fixtures/packages-input-workspace/package-b/src/lib.rs @@ -0,0 +1,17 @@ +#[cfg(test)] +mod tests { + use std::fs; + use std::path::PathBuf; + + fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("package directory should have a workspace root parent") + .to_path_buf() + } + + #[test] + fn writes_marker() { + fs::write(workspace_root().join("marker-package-b"), "ok\n").unwrap(); + } +} diff --git a/tests/fixtures/packages-input-workspace/package-c/Cargo.toml b/tests/fixtures/packages-input-workspace/package-c/Cargo.toml new file mode 100644 index 0000000..3658c0f --- /dev/null +++ b/tests/fixtures/packages-input-workspace/package-c/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "package-c" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/lib.rs" diff --git a/tests/fixtures/packages-input-workspace/package-c/src/lib.rs b/tests/fixtures/packages-input-workspace/package-c/src/lib.rs new file mode 100644 index 0000000..3f72cbc --- /dev/null +++ b/tests/fixtures/packages-input-workspace/package-c/src/lib.rs @@ -0,0 +1,17 @@ +#[cfg(test)] +mod tests { + use std::fs; + use std::path::PathBuf; + + fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("package directory should have a workspace root parent") + .to_path_buf() + } + + #[test] + fn writes_marker() { + fs::write(workspace_root().join("marker-package-c"), "ok\n").unwrap(); + } +}