name: CI on: pull_request: push: branches: - main - master env: CARGO_TERM_COLOR: always RUST_MIN_STACK: 67108864 CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 RUSTUP_MAX_RETRIES: 10 # Gitea Actions runner tool cache. Actions like setup-node/setup-python can reuse this. RUNNER_TOOL_CACHE: /toolcache jobs: rust-fmt: name: Rustfmt runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Cache Rust toolchain uses: actions/cache@v4 with: path: | ~/.rustup/toolchains ~/.rustup/update-hashes key: rustup-rustfmt-${{ runner.os }}-stable-v1 restore-keys: | rustup-${{ runner.os }}-stable-v1 rustup- - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: components: rustfmt - name: Rustfmt run: cargo fmt --all -- --check rust-clippy: name: Clippy runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Cache Rust toolchain uses: actions/cache@v4 with: path: | ~/.rustup/toolchains ~/.rustup/update-hashes key: rustup-clippy-${{ runner.os }}-stable-v1 restore-keys: | rustup-${{ runner.os }}-stable-v1 rustup- - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: components: clippy - name: Cache Cargo registry + index uses: actions/cache@v4 with: path: | ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db key: cargo-registry-${{ hashFiles('**/Cargo.lock') }} restore-keys: | cargo-registry- - name: Cache Cargo build artifacts uses: actions/cache@v4 with: path: target key: cargo-clippy-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('**/*.rs', '**/Cargo.toml') }} restore-keys: | cargo-clippy-${{ hashFiles('**/Cargo.lock') }}- cargo-clippy- - name: Clippy run: cargo clippy --workspace --all-targets --all-features -- -D warnings rust-test: name: Tests runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Cache Rust toolchain uses: actions/cache@v4 with: path: | ~/.rustup/toolchains ~/.rustup/update-hashes key: rustup-test-${{ runner.os }}-stable-v1 restore-keys: | rustup-${{ runner.os }}-stable-v1 rustup- - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Cache Cargo registry + index uses: actions/cache@v4 with: path: | ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db key: cargo-registry-${{ hashFiles('**/Cargo.lock') }} restore-keys: | cargo-registry- - name: Cache Cargo build artifacts uses: actions/cache@v4 with: path: target key: cargo-test-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('**/*.rs', '**/Cargo.toml') }} restore-keys: | cargo-test-${{ hashFiles('**/Cargo.lock') }}- cargo-test- - name: Tests run: cargo test --workspace --all-features rust-audit: name: Cargo Audit & Deny runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Cache Rust toolchain uses: actions/cache@v4 with: path: | ~/.rustup/toolchains ~/.rustup/update-hashes key: rustup-audit-${{ runner.os }}-stable-v1 restore-keys: | rustup-${{ runner.os }}-stable-v1 rustup- - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Cache Cargo registry + index uses: actions/cache@v4 with: path: | ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db key: cargo-registry-${{ hashFiles('**/Cargo.lock') }} restore-keys: | cargo-registry- - name: Cache cargo-binstall and installed binaries uses: actions/cache@v4 with: path: | ~/.cargo/bin/cargo-binstall ~/.cargo/bin/cargo-deny key: cargo-security-tools-v2 - name: Install cargo-binstall run: | if ! command -v cargo-binstall &> /dev/null; then curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash fi - name: Install security tools (pre-built binaries) run: | command -v cargo-deny &> /dev/null || cargo binstall --no-confirm --locked cargo-deny - name: Cargo Deny run: cargo deny check web-blocking: name: Web Blocking Checks runs-on: ubuntu-latest defaults: run: working-directory: web steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "22" cache: "npm" cache-dependency-path: web/package-lock.json - name: Install dependencies run: npm ci - name: ESLint run: npm run lint - name: TypeScript run: npm run typecheck - name: Build run: npm run build security-blocking: name: Security Blocking Checks runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Install Gitleaks run: | mkdir -p "$HOME/bin" GITLEAKS_VERSION="8.24.2" ARCH="$(uname -m)" case "$ARCH" in x86_64) ARCH="x64" ;; aarch64|arm64) ARCH="arm64" ;; *) echo "Unsupported architecture: $ARCH" exit 1 ;; esac curl -sSfL \ -o /tmp/gitleaks.tar.gz \ "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_${ARCH}.tar.gz" tar -xzf /tmp/gitleaks.tar.gz -C "$HOME/bin" gitleaks chmod +x "$HOME/bin/gitleaks" - name: Gitleaks run: | "$HOME/bin/gitleaks" git \ --report-format sarif \ --report-path gitleaks.sarif \ --config .gitleaks.toml web-advisory: name: Web Advisory Checks runs-on: ubuntu-latest continue-on-error: true defaults: run: working-directory: web steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "22" cache: "npm" cache-dependency-path: web/package-lock.json - name: Install dependencies run: npm ci - name: Knip run: npm run knip continue-on-error: true - name: NPM Audit (prod deps) run: npm audit --omit=dev continue-on-error: true security-advisory: name: Security Advisory Checks runs-on: ubuntu-latest continue-on-error: true steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install Semgrep run: pip install semgrep - name: Semgrep run: semgrep scan --config p/default --error continue-on-error: true