diff --git a/.github/actions/cargo-binstall/action.yaml b/.github/actions/cargo-binstall/action.yaml new file mode 100644 index 0000000..604fc3b --- /dev/null +++ b/.github/actions/cargo-binstall/action.yaml @@ -0,0 +1,18 @@ +name: Install cargo binaries +description: Install cargo binaries using cargo-binstall +inputs: + binstall: + description: "Programs to install with binstall" + required: true +runs: + using: "composite" + steps: + - name: Install cargo-binstall + shell: bash + run: > + curl -L --proto '=https' --tlsv1.3 -sSf https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz | sudo tar -xzv -C /usr/bin + + - name: Install cargo bins + shell: bash + run: > + cargo-binstall --no-confirm --min-tls-version 1.3 ${{ inputs.binstall }} diff --git a/.github/actions/setup-ci/action.yaml b/.github/actions/setup-ci/action.yaml new file mode 100644 index 0000000..235f7a9 --- /dev/null +++ b/.github/actions/setup-ci/action.yaml @@ -0,0 +1,19 @@ +name: Setup CI environment +inputs: + rust-cache-key: + description: "An additional cache key that is added alongside the automatic `job`-based cache key and can be used to further differentiate jobs." + required: false + rust-cache-shared-key: + description: "A cache key that is used instead of the automatic `job`-based key, and is stable over multiple jobs." + required: false +runs: + using: "composite" + steps: + - name: Install rust toolchain + shell: bash + run: rustup show + + - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2 + with: + key: "${{ inputs.rust-cache-key }}" + shared-key: "${{ inputs.rust-cache-shared-key }}" diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 5ba6fc5..de116a4 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -11,6 +11,18 @@ enabled: true, automerge: true }, + "customManagers": [ + { + "customType": "regex", + "fileMatch": ["^rust-toolchain\\.toml?$"], + "matchStrings": [ + "channel\\s*=\\s*\"(?\\d+\\.\\d+(\\.\\d+)?)\"" + ], + "depNameTemplate": "rust", + "packageNameTemplate": "rust-lang/rust", + "datasourceTemplate": "github-releases" + }, + ], packageRules: [ { matchCategories: ["rust"], diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..abdd40b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,104 @@ +name: CI tests +on: [push] + +jobs: + populate-rust-cache: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - uses: ./.github/actions/setup-ci + with: + rust-cache-shared-key: "base" + - run: cargo check --all-targets --all-features + continue-on-error: true + + rust-jobs: + name: ${{ matrix.job }} + runs-on: ubuntu-latest + needs: populate-rust-cache + strategy: + matrix: + job: + - cargo fmt --all -- --check + - cargo test + - cargo clippy -- -D warnings + fail-fast: false + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - uses: ./.github/actions/setup-ci + with: + rust-cache-shared-key: "base" + - run: ${{ matrix.job }} + + deny: + name: ${{ matrix.job }} + runs-on: ubuntu-latest + strategy: + matrix: + job: + - cargo deny --all-features check advisories + - cargo deny --all-features check bans licenses sources + fail-fast: false + # Prevent sudden announcement of a new advisory from failing CI: + continue-on-error: ${{ endsWith(matrix.job, 'check advisories') }} + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - uses: ./.github/actions/cargo-binstall + with: + binstall: "cargo-deny" + - run: ${{ matrix.job }} + + pre-commit: + name: Run pre-commit + runs-on: ubuntu-latest + needs: populate-rust-cache + env: + # These hooks are expensive and already run as dedicated jobs above + SKIP: "tests,clippy" + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - uses: ./.github/actions/setup-ci + with: + rust-cache-shared-key: "base" + + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 + - name: set PYVERSION + run: echo "PYVERSION=$(python --version | tr ' ' '-')" >> $GITHUB_ENV + + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + with: + path: ~/.cache/pre-commit + # Changes to pre-commit-config.yaml may require the installation of + # new binaries/scripts. When a cache hit occurs, changes to the cache + # aren't persisted at the end of the run, so making the key dependent + # on the configuration file ensures we always persist a complete cache. + key: pre-commit-${{ env.PYVERSION }}-${{ hashFiles('.pre-commit-config.yaml') }} + + - run: pip install pre-commit + - run: pre-commit run --all --color=always --show-diff-on-failure + + test-windows: + name: Test on Windows + runs-on: windows-latest + steps: + - run: git config --system core.autocrlf false && git config --system core.eol lf + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - uses: ./.github/actions/setup-ci + - run: cargo test + + coverage: + name: Code coverage + runs-on: ubuntu-latest + needs: populate-rust-cache + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - uses: ./.github/actions/setup-ci + - uses: ./.github/actions/cargo-binstall + with: + binstall: "cargo-tarpaulin" + - run: cargo tarpaulin --out Html + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4 + with: + name: tarpaulin-report + path: tarpaulin-report.html diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 9a31b0b..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,184 +0,0 @@ -name: CI tests -on: [push, pull_request] - -env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - -jobs: - build: - name: Build project - runs-on: ubuntu-latest - outputs: - rustc_cache_key: ${{ steps.setup_rust.outputs.cachekey }} - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - uses: dtolnay/rust-toolchain@stable - id: setup_rust - with: - components: "rustfmt, clippy" - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: "cargo-base-${{ steps.setup_rust.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}" - restore-keys: | - cargo-base-${{ env.RUSTC_CACHEKEY }} - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5 - - run: cargo build --locked --all-targets - - lint: - name: Run lints - runs-on: ubuntu-latest - needs: build - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: "cargo-lint-${{ needs.build.outputs.rustc_cache_key }}-${{ hashFiles('**/Cargo.lock') }}" - restore-keys: | - cargo-lint-${{ env.RUSTC_CACHEKEY }} - cargo-base-${{ env.RUSTC_CACHEKEY }} - fail-on-cache-miss: true - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5 - - - run: cargo fmt --all -- --check - - run: cargo check - - run: cargo clippy -- -D warnings - - - pre-commit: - name: Run pre-commit - runs-on: ubuntu-latest - needs: build - env: - # These hooks are expensive and already run as dedicated jobs above - SKIP: "tests,clippy" - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: "cargo-lint-${{ needs.build.outputs.rustc_cache_key }}-${{ hashFiles('**/Cargo.lock') }}" - restore-keys: | - cargo-lint-${{ env.RUSTC_CACHEKEY }} - cargo-base-${{ env.RUSTC_CACHEKEY }} - fail-on-cache-miss: true - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5 - - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 - - name: set PYVERSION - run: echo "PYVERSION=$(python --version | tr ' ' '-')" >> $GITHUB_ENV - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: ~/.cache/pre-commit - # Changes to pre-commit-config.yaml may require the installation of - # new binaries/scripts. When a cache hit occurs, changes to the cache - # aren't persisted at the end of the run, so making the key dependent - # on the configuration file ensures we always persist a complete cache. - key: pre-commit-${{ env.PYVERSION }}-${{ hashFiles('.pre-commit-config.yaml') }} - - - run: pip install pre-commit - - run: pre-commit run --all --color=always --show-diff-on-failure - - test-linux: - name: Test on Linux - runs-on: ubuntu-latest - needs: build - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: "cargo-test-${{ needs.build.outputs.rustc_cache_key }}-${{ hashFiles('**/Cargo.lock') }}" - restore-keys: | - cargo-test-${{ env.RUSTC_CACHEKEY }} - cargo-base-${{ env.RUSTC_CACHEKEY }} - fail-on-cache-miss: true - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5 - - - run: cargo test - - test-windows: - name: Test on Windows - runs-on: windows-latest - needs: build - steps: - - run: git config --system core.autocrlf false && git config --system core.eol lf - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - uses: dtolnay/rust-toolchain@stable - id: setup_rust - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: "cargo-windows-${{ needs.build.outputs.rustc_cache_key }}-${{ hashFiles('**/Cargo.lock') }}" - restore-keys: | - cargo-windows-${{ env.RUSTC_CACHEKEY }} - cargo-base-${{ env.RUSTC_CACHEKEY }} - fail-on-cache-miss: true - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5 - - - run: cargo test - - coverage: - name: Code coverage - runs-on: ubuntu-latest - needs: build - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: "cargo-coverage-${{ needs.build.outputs.rustc_cache_key }}-${{ hashFiles('**/Cargo.lock') }}" - restore-keys: | - cargo-coverage-${{ env.RUSTC_CACHEKEY }} - cargo-base-${{ env.RUSTC_CACHEKEY }} - fail-on-cache-miss: true - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5 - - - uses: actions-rs/tarpaulin@044a1e5bdace8dd2f727b1af63c1d9a1d3572068 # v0.1 - with: - # Constrained by https://github.com/actions-rs/tarpaulin/pull/23 - version: "0.22.0" - args: "--ignore-tests" - out-type: "Html" - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4 - with: - name: tarpaulin-report - path: tarpaulin-report.html diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..77c6b2a --- /dev/null +++ b/deny.toml @@ -0,0 +1,73 @@ +[output] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + +[advisories] +# Opt-in to new config format - https://github.com/EmbarkStudios/cargo-deny/pull/611 +version = 2 + +# The path where the advisory databases are cloned/fetched into +db-path = "$CARGO_HOME/advisory-dbs" +# The url(s) of the advisory databases to use +db-urls = ["https://github.com/rustsec/advisory-db"] +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [] + +[licenses] +# Opt-in to new config format - https://github.com/EmbarkStudios/cargo-deny/pull/611 +version = 2 + +# Licenses we accept, identified by their SPDX short identifier (+ optional +# exception) from https://spdx.org/licenses/ +allow = [ + "Apache-2.0", + "BSD-2-Clause", + "BSD-2-Clause-Patent", + "BSD-3-Clause", + "MIT", + "MPL-2.0", +] +unused-allowed-license = "allow" +exceptions = [ + { allow = ["Unicode-DFS-2016"], crate = "unicode-ident" }, +] +# Default confidence is 0.8, let's require a higher confidence level for now. +# We can lower this later if it's too pedantic. +confidence-threshold = 0.95 + +[bans] +# Lint level for when multiple versions of the same crate are detected. Deny +# for now to make this super obvious, though we might wish to change this back +# to the default of warn if that gets too disruptive. +# +# Background reading about the use of this check is at: +# https://embarkstudios.github.io/cargo-deny/checks/bans/index.html#use-case---duplicate-version-detection +multiple-versions = "deny" +skip = [ + # When encountering multiple versions of crates that we wish to tolerate, + # specify a `<=1.2.3` for the OLDEST version in use. That way, as soon as + # whichever dependency holding us back is updated, one of two things can + # happen: + # + # 1. The dependency is updated to a version that is compatible with the + # other dependencies, resolving the duplication. At this point a WARNING + # will be generated that the `<=1.2.3` version no longer matches anything. + # 2. The dependency is updated to a version that is still not compatible + # with the other dependencies, at which point the ban action will FAIL the + # result. We can then choose to again skip that version, or decide more + # drastic action is needed. + "syn:<=1.0.109", +] +wildcards = "deny" +allow-wildcard-paths = false + +[sources] +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = [] diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..7ae2b72 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.79.0" +profile = "default"