diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5c63cbb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,95 @@ +name: CI + +on: + merge_group: + pull_request: + workflow_dispatch: + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + maybe-expedite: + outputs: + value: ${{ steps.expedite.outputs.value }} + + runs-on: ubuntu-latest + + steps: + - name: Log github refs + run: | + echo '```' >> "$GITHUB_STEP_SUMMARY" + echo 'github.ref: ${{ github.ref }}' >> "$GITHUB_STEP_SUMMARY" + echo 'github.sha: ${{ github.sha }}' >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check if merging an up-to-date branch + if: ${{ github.event_name == 'merge_group' }} + id: expedite + run: | + N="$(expr "${{ github.ref }}" : '.*-\([0-9]\+\)-[^-]*$')" + BASE_SHA="$(gh api /repos/${{ github.repository }}/pulls/"$N" | jq -r '.base.sha')" + if git diff --quiet ${{ github.event.merge_group.base_sha }} "$BASE_SHA"; then + echo "value=1" >> "$GITHUB_OUTPUT" + fi + env: + GH_TOKEN: ${{ github.token }} + + test: + needs: [maybe-expedite] + + if: ${{ ! needs.maybe-expedite.outputs.value }} + + strategy: + fail-fast: ${{ github.event_name == 'merge_group' }} + matrix: + environment: [ubuntu-latest, macos-latest] + + runs-on: ${{ matrix.environment }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Install tools + run: | + rustup install nightly + rustup +nightly component add clippy + cargo install cargo-dylint dylint-link || true + cargo install cargo-hack || true + cargo install cargo-udeps --locked || true + cargo install group-runner || true + + - name: Build + run: cargo test --no-run + + - name: Test + run: cargo test --config "target.'cfg(all())'.runner = 'group-runner'" + + all-checks: + needs: [test] + + if: ${{ always() }} + + runs-on: ubuntu-latest + + steps: + - name: Check results + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + run: exit 1 diff --git a/Cargo.lock b/Cargo.lock index 54962bd..2188047 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,7 @@ dependencies = [ "assert_cmd", "cargo_metadata", "clap", + "ctor", "ctrlc", "hex", "lcov", @@ -238,6 +239,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "ctrlc" version = "3.4.5" diff --git a/Cargo.toml b/Cargo.toml index 2c7da20..e12a276 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ sha2 = "0.10" tempfile = "3.13" [dev-dependencies] +ctor = "0.2" regex = "1.11" [lints.rust.unexpected_cfgs] diff --git a/tests/ci.rs b/tests/ci.rs index 4cdc8a8..0a83e2e 100644 --- a/tests/ci.rs +++ b/tests/ci.rs @@ -1,8 +1,13 @@ use assert_cmd::assert::OutputAssertExt; use regex::Regex; -use std::{fs::read_to_string, path::Path, process::Command}; +use std::{env::remove_var, fs::read_to_string, path::Path, process::Command}; use tempfile::tempdir; +#[ctor::ctor] +fn initialize() { + remove_var("CARGO_TERM_COLOR"); +} + #[test] fn clippy() { Command::new("cargo")