# Gitea Actions CI. # # Gitea Actions is workflow-compatible with GitHub Actions, so this runs on either # with no changes. It needs a registered runner with the `ubuntu-latest` label. # # The gates, in the order they fail fastest: # fmt — formatting, seconds # clippy — lints, denied rather than warned # test — 160 unit + integration tests # deny — RustSec advisories, licence policy, source policy # musl — the artifact §8 actually ships: one static binary name: CI on: push: branches: [main, master] pull_request: # Advisories appear without any code changing, so the dependency audit also # runs on a schedule rather than only on push. schedule: - cron: "0 6 * * 1" env: CARGO_TERM_COLOR: always # Fail the build on warnings. The tree is warning-clean, so keeping it that way # is cheaper than letting warnings accumulate. RUSTFLAGS: "-D warnings" jobs: check: name: fmt, clippy, test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust run: | # rustup is not guaranteed present on a self-hosted Gitea runner. if ! command -v rustup >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --profile minimal --component rustfmt,clippy echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" else rustup component add rustfmt clippy fi - name: Cache cargo uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo- - name: Formatting run: cargo fmt --all -- --check - name: Clippy run: cargo clippy --all-targets --all-features - name: Tests run: cargo test --all-features deny: name: advisories and licences runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust run: | if ! command -v rustup >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --profile minimal echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" fi - name: Cache cargo-deny uses: actions/cache@v4 with: path: ~/.cargo/bin/cargo-deny key: ${{ runner.os }}-cargo-deny - name: Install cargo-deny run: | command -v cargo-deny >/dev/null 2>&1 || cargo install cargo-deny --locked # Advisories, licences, bans and sources — see deny.toml for why the licence # allow-list is closed rather than a deny-list. - name: cargo deny run: cargo deny check musl: name: static musl binary runs-on: ubuntu-latest # Only gate merges on the artifact build once the cheaper checks have passed. needs: check steps: - uses: actions/checkout@v4 - name: Install Rust and musl target run: | if ! command -v rustup >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --profile minimal echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" export PATH="$HOME/.cargo/bin:$PATH" fi rustup target add x86_64-unknown-linux-musl sudo apt-get update && sudo apt-get install -y musl-tools - name: Cache cargo uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-musl-${{ hashFiles('Cargo.lock') }} restore-keys: ${{ runner.os }}-musl- # §8: "Ship a single static binary (musl target) plus the SQLite file." # rusqlite is built with `bundled`, so SQLite is compiled in; reqwest uses # rustls rather than OpenSSL, so there is no system TLS dependency to link. - name: Build run: cargo build --release --target x86_64-unknown-linux-musl - name: Verify the binary is actually static run: | BIN=target/x86_64-unknown-linux-musl/release/jray-server file "$BIN" # A dynamically-linked result would defeat §8's deployment story, so this # is asserted rather than assumed. # # Checked with `file`, not `ldd`: the musl target produces a static-PIE, # and `ldd` prints the musl loader for one — an `ldd`-based check reports # a perfectly static binary as dynamic. if ! file "$BIN" | grep -qE 'static-pie linked|statically linked'; then echo "::error::binary is not statically linked" >&2 exit 1 fi - name: Upload binary uses: actions/upload-artifact@v3 with: name: jray-server-x86_64-musl path: target/x86_64-unknown-linux-musl/release/jray-server if-no-files-found: error