name: CI
on:
push:
branches: [main]
pull_request:
branches: ['**']
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
jobs:
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - run: cargo test --all-features
examples:
name: Examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - run: cargo build --release
- name: Run every example, which asserts its own output
run: OXML="$PWD/target/release/oxml" ./examples/run-all.sh
example-coverage:
name: Examples cover the public API
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: stable
components: llvm-tools-preview
- uses: taiki-e/install-action@742a3317eac7bd62f91cd888b4eead5e784ba833 with:
tool: cargo-llvm-cov
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - run: python3 scripts/check-example-coverage.py
fuzz:
name: Fuzz (run_args)
runs-on: ubuntu-latest
env:
RUSTUP_TOOLCHAIN: nightly
strategy:
fail-fast: false
matrix:
target: [run_args]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: nightly
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - run: cargo install cargo-fuzz --locked
- name: Seed the corpus
run: |
mkdir -p fuzz/corpus/${{ matrix.target }}
cp fuzz/seeds/${{ matrix.target }}/* fuzz/corpus/${{ matrix.target }}/
- run: >
cargo fuzz run ${{ matrix.target }}
-- -max_total_time=300 -print_final_stats=1
- name: Upload any crash
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with:
name: fuzz-artifacts-${{ matrix.target }}
path: fuzz/artifacts/
if-no-files-found: ignore
dco:
name: DCO sign-off
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
fetch-depth: 0
- name: Every commit must carry a Signed-off-by
run: |
base="${{ github.event.pull_request.base.sha }}"
head="${{ github.event.pull_request.head.sha }}"
[ -n "$base" ] || { echo "not a pull request; nothing to check"; exit 0; }
fail=0
while read -r sha; do
[ -n "$sha" ] || continue
author="$(git log -1 --format='%an <%ae>' "$sha")"
# Bots cannot sign off, and requiring it of them would
# block every Dependabot update on a technicality.
case "$author" in
*"[bot]"*|*"dependabot"*) continue ;;
esac
if ! git log -1 --format='%B' "$sha" | grep -qi "^Signed-off-by: .\+ <.\+@.\+>"; then
echo "::error::$(git log -1 --format='%h %s' "$sha") has no Signed-off-by"
fail=1
fi
done <<< "$(git rev-list "$base..$head")"
if [ "$fail" -ne 0 ]; then
echo "Sign off with: git commit -s (or: git rebase --signoff $base)"
echo "See DCO in the repository root for what you are certifying."
exit 1
fi
echo "every commit is signed off"
branch-coverage:
name: Branch coverage
runs-on: ubuntu-latest
env:
RUSTUP_TOOLCHAIN: nightly
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: nightly
components: llvm-tools-preview
- uses: taiki-e/install-action@742a3317eac7bd62f91cd888b4eead5e784ba833 with:
tool: cargo-llvm-cov
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - name: Branch coverage must stay above 80%
run: |
cargo llvm-cov --branch --all-features --summary-only \
--ignore-filename-regex 'builds/cargo/package' | tee /tmp/branch.txt
awk '/^TOTAL/{
gsub(/%/,"",$NF)
if ($NF+0 < 80) {
print "::error::branch coverage " $NF "% is below the 80% floor"
exit 1
}
print "branch coverage " $NF "%"
}' /tmp/branch.txt
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: stable
components: rustfmt, clippy
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - run: cargo fmt --all --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: "-D warnings"
unsafe:
name: Forbid unsafe
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: The crate must forbid unsafe code
run: |
if ! grep -rq '#!\[forbid(unsafe_code)\]' src/; then
echo "::error::#![forbid(unsafe_code)] is missing"
exit 1
fi
echo "unsafe_code is forbidden"
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 with:
toolchain: stable
components: llvm-tools-preview
- uses: taiki-e/install-action@742a3317eac7bd62f91cd888b4eead5e784ba833 with:
tool: cargo-llvm-cov
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 - run: >
cargo llvm-cov --all-features --fail-under-lines 95
--ignore-filename-regex 'builds/cargo/package'