diff --git a/.github/DOCS.md b/.github/DOCS.md new file mode 100644 index 0000000..e932784 --- /dev/null +++ b/.github/DOCS.md @@ -0,0 +1,23 @@ +# Github config and workflows + +In this folder there is configuration for codecoverage, dependabot, and ci +workflows that check the library more deeply than the default configurations. + +This folder can be or was merged using a --allow-unrelated-histories merge +strategy from which provides a +reasonably sensible base for writing your own ci on. By using this strategy +the history of the CI repo is included in your repo, and future updates to +the CI can be merged later. + +To perform this merge run: + +```shell +git remote add ci https://github.com/jonhoo/rust-ci-conf.git +git fetch ci +git merge --allow-unrelated-histories ci/main +``` + +An overview of the files in this project is available at: +, which contains some +rationale for decisions and runs through an example of solving minimal version +and OpenSSL issues. diff --git a/.github/codecov.yml b/.github/codecov.yml index ff4f571..cd5ce8f 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -18,4 +18,4 @@ ignore: # Make comments less noisy comment: layout: "files" - require_changes: yes + require_changes: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8139a93..d0f091e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,8 +10,10 @@ updates: interval: daily ignore: - dependency-name: "*" - # patch and minor updates don't matter for libraries - # remove this ignore rule if your package has binaries + # patch and minor updates don't matter for libraries as consumers of this library build + # with their own lockfile, rather than the version specified in this library's lockfile + # remove this ignore rule if your package has binaries to ensure that the binaries are + # built with the exact set of dependencies and those are up to date. update-types: - "version-update:semver-patch" - "version-update:semver-minor" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 3fdc139..6b4d13a 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,10 +1,21 @@ +# This workflow runs whenever a PR is opened or updated, or a commit is pushed to main. It runs +# several checks: +# - fmt: checks that the code is formatted according to rustfmt +# - clippy: checks that the code does not contain any clippy warnings +# - doc: checks that the code can be documented without errors +# - hack: check combinations of feature flags +# - msrv: check that the msrv specified in the crate is correct permissions: contents: read +# This configuration allows maintainers of this repo to create a branch and pull request based on +# the new branch. Restricting the push trigger to the main branch ensures that the PR only gets +# built once. on: push: branches: [main] pull_request: -# Spend CI time only on latest ref: https://github.com/jonhoo/rust-ci-conf/pull/5 +# If new code is pushed to a PR branch, then cancel in progress workflows for that PR. Ensures that +# we don't waste CI time, and returns results quicker https://github.com/jonhoo/rust-ci-conf/pull/5 concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true @@ -32,6 +43,7 @@ jobs: strategy: fail-fast: false matrix: + # Get early warning of new lints which are regularly introduced in beta channels. toolchain: [stable, beta] steps: - uses: actions/checkout@v4 @@ -47,6 +59,9 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} doc: + # run docs generation on nightly rather than stable. This enables features like + # https://doc.rust-lang.org/beta/unstable-book/language-features/doc-cfg.html which allows an + # API be documented as only available in some specific platforms. runs-on: ubuntu-latest name: nightly / doc steps: @@ -60,6 +75,8 @@ jobs: env: RUSTDOCFLAGS: --cfg docsrs hack: + # cargo-hack checks combinations of feature flags to ensure that features are all additive + # which is required for feature unification runs-on: ubuntu-latest name: ubuntu / stable / features steps: @@ -71,9 +88,11 @@ jobs: - name: cargo install cargo-hack uses: taiki-e/install-action@cargo-hack # intentionally no target specifier; see https://github.com/jonhoo/rust-ci-conf/pull/4 + # --feature-powerset runs for every combination of features - name: cargo hack run: cargo hack --feature-powerset check msrv: + # check that we can build using the minimal rust version that is specified by this crate runs-on: ubuntu-latest # we use a matrix here just because env can't be used in job names # https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability diff --git a/.github/workflows/nostd.yml b/.github/workflows/nostd.yml index 00362a6..93a1698 100644 --- a/.github/workflows/nostd.yml +++ b/.github/workflows/nostd.yml @@ -1,10 +1,12 @@ +# This workflow checks whether the library is able to run without the std library (e.g., embedded). +# This entire file should be removed if this crate does not support no-std. See check.yml for +# information about how the concurrency cancelation and workflow triggering works permissions: contents: read on: push: branches: [main] pull_request: -# Spend CI time only on latest ref: https://github.com/jonhoo/rust-ci-conf/pull/5 concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true diff --git a/.github/workflows/safety.yml b/.github/workflows/safety.yml index ce1e38e..afea8df 100644 --- a/.github/workflows/safety.yml +++ b/.github/workflows/safety.yml @@ -1,10 +1,16 @@ +# This workflow runs checks for unsafe code. In crates that don't have any unsafe code, this can be +# removed. Runs: +# - miri - detects undefined behavior and memory leaks +# - address santizer - detects memory errors +# - leak sanitizer - detects memory leaks +# - loom - Permutation testing for concurrent code https://crates.io/crates/loom +# See check.yml for information about how the concurrency cancelation and workflow triggering works permissions: contents: read on: push: branches: [main] pull_request: -# Spend CI time only on latest ref: https://github.com/jonhoo/rust-ci-conf/pull/5 concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml index 4607f3e..15b1a7c 100644 --- a/.github/workflows/scheduled.yml +++ b/.github/workflows/scheduled.yml @@ -1,3 +1,6 @@ +# Run scheduled (rolling) jobs on a nightly basis, as your crate may break independently of any +# given PR. E.g., updates to rust nightly and updates to this crates dependencies. See check.yml for +# information about how the concurrency cancelation and workflow triggering works permissions: contents: read on: @@ -6,7 +9,6 @@ on: pull_request: schedule: - cron: '7 7 * * *' -# Spend CI time only on latest ref: https://github.com/jonhoo/rust-ci-conf/pull/5 concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true @@ -29,12 +31,16 @@ jobs: run: cargo test --locked --all-features --all-targets # https://twitter.com/alcuadrado/status/1571291687837732873 update: + # This action checks that updating the dependencies of this crate to the latest available that + # satisfy the versions in Cargo.toml does not break this crate. This is important as consumers + # of this crate will generally use the latest available crates. This is subject to the standard + # Cargo semver rules (i.e cargo does not update to a new major version unless explicitly told + # to). runs-on: ubuntu-latest name: ubuntu / beta / updated - # There's no point running this if no Cargo.lock was checked in in the - # first place, since we'd just redo what happened in the regular test job. - # Unfortunately, hashFiles only works in if on steps, so we reepeat it. - # if: hashFiles('Cargo.lock') != '' + # There's no point running this if no Cargo.lock was checked in in the first place, since we'd + # just redo what happened in the regular test job. Unfortunately, hashFiles only works in if on + # steps, so we repeat it. steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 56bd560..ab86e2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,10 +1,17 @@ +# This is the main CI workflow that runs the test suite on all pushes to main and all pull requests. +# It runs the following jobs: +# - required: runs the test suite on ubuntu with stable and beta rust toolchains +# - minimal: runs the test suite with the minimal versions of the dependencies that satisfy the +# requirements of this crate, and its dependencies +# - os-check: runs the test suite on mac and windows +# - coverage: runs the test suite and collects coverage information +# See check.yml for information about how the concurrency cancelation and workflow triggering works permissions: contents: read on: push: branches: [main] pull_request: -# Spend CI time only on latest ref: https://github.com/jonhoo/rust-ci-conf/pull/5 concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true @@ -15,6 +22,8 @@ jobs: name: ubuntu / ${{ matrix.toolchain }} strategy: matrix: + # run on stable and beta to ensure that tests won't break on the next version of the rust + # toolchain toolchain: [stable, beta] steps: - uses: actions/checkout@v4 @@ -25,6 +34,7 @@ jobs: with: toolchain: ${{ matrix.toolchain }} - name: cargo generate-lockfile + # enable this ci template to run regardless of whether the lockfile is checked in or not if: hashFiles('Cargo.lock') == '' run: cargo generate-lockfile # https://twitter.com/jonhoo/status/1571290371124260865 @@ -34,6 +44,28 @@ jobs: - name: cargo test --doc run: cargo test --locked --all-features --doc minimal: + # This action chooses the oldest version of the dependencies permitted by Cargo.toml to ensure + # that this crate is compatible with the minimal version that this crate and its dependencies + # require. This will pickup issues where this create relies on functionality that was introduced + # later than the actual version specified (e.g., when we choose just a major version, but a + # method was added after this version). + # + # This particular check can be difficult to get to succeed as often transitive dependencies may + # be incorrectly specified (e.g., a dependency specifies 1.0 but really requires 1.1.5). There + # is an alternative flag available -Zminimal-direct that uses the minimal versions for direct + # dependencies of this crate, while selecting the maximal versions for the transitive + # dependencies. Alternatively, you can add a line in your Cargo.toml to artificially increase + # the minimal dependency, which you do with e.g.: + # ```toml + # # for minimal-versions + # [target.'cfg(any())'.dependencies] + # openssl = { version = "0.10.55", optional = true } # needed to allow foo to build with -Zminimal-versions + # ``` + # The optional = true is necessary in case that dependency isn't otherwise transitively required + # by your library, and the target bit is so that this dependency edge never actually affects + # Cargo build order. See also + # https://github.com/jonhoo/fantoccini/blob/fde336472b712bc7ebf5b4e772023a7ba71b2262/Cargo.toml#L47-L49. + # This action is run on ubuntu with the stable toolchain, as it is not expected to fail runs-on: ubuntu-latest name: ubuntu / stable / minimal-versions steps: @@ -51,6 +83,7 @@ jobs: - name: cargo test run: cargo test --locked --all-features --all-targets os-check: + # run cargo test on mac and windows runs-on: ${{ matrix.os }} name: ${{ matrix.os }} / stable strategy: @@ -75,6 +108,8 @@ jobs: - name: cargo test run: cargo test --locked --all-features --all-targets coverage: + # use llvm-cov to build and collect coverage and outputs in a format that is compatible with + # codecov.io runs-on: ubuntu-latest name: ubuntu / stable / coverage steps: