Files
anki/.github/workflows/ci.yml
Abdo 3c9b1daf35 CI: Apply a consistent Cargo profile (#5133)
## Linked issue

Related:
https://github.com/ankitects/anki/pull/5102#issuecomment-4923922894

## Summary / motivation


This adds a new Cargo profile (`ci`) for use in all Rust build commands
on CI. The goal is to reduce unnecessary recompilation of the same
crates in dev/release profiles.

## Steps to reproduce (before)

View the logs of the last CI run on main and notice that some crates are
getting compiled with the `release` profile, e.g. compilation ends with
"Finished `release` profile [optimized]".

## How to test (after)

View the logs of the last CI run in this PR and confirm all Rust
compilation commands end with "Finished `ci` profile [unoptimized]",
indicating that only a single profile is being used.

### Checklist (minimum)

- [x] I ran `./ninja check` or an equivalent relevant check locally.
- [ ] I added or updated tests when the change is non-trivial or
behavior changed.

## Scope

- [x] This PR is focused on one change (no unrelated edits).
2026-08-12 10:17:29 +03:00

602 lines
19 KiB
YAML

name: CI
on:
workflow_dispatch:
push:
branches: [main, 'release/**']
pull_request:
branches: [main]
types: [opened, synchronize, reopened, labeled]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
N2_OUTPUT_PROGRESS: "1"
N2_OUTPUT_SUCCESS: "1"
jobs:
minilints:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
with:
fetch-depth: 0
filter: blob:none
- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 #v1
- name: Check for non-documentation changes
id: non-doc-changes
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 #v47.0.6
with:
files: |
**
files_ignore: |
**/*.md
**/*.mdx
docs/**/*.png
docs/**/*.svg
docs-site/**/*.png
docs-site/**/*.jpg
docs-site/**/*.svg
docs-site/**/*.mp4
- name: Run minilints
if: steps.non-doc-changes.outputs.any_changed == 'true'
run: cargo run -p minilints -- check /tmp/minilints.stamp
env:
CONTRIBUTORS_BYPASS_EMAILS: ${{ vars.CONTRIBUTORS_BYPASS_EMAILS }}
# Lightweight formatting checks (no build outputs needed).
# Uses individual tool installs instead of setup-anki to stay fast.
format:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 #v1
- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 #v7
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v7.0.0
with:
node-version: '20'
- name: Install n2
run: tools/install-n2
env:
RUSTFLAGS: "--cap-lints warn"
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Run format checks
run: just fmt
# Linux runs on every PR and push to main.
check-linux:
runs-on: ubuntu-24.04
name: check (linux)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
- name: Restore cargo cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
~/.cargo/bin
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-${{ runner.os }}-
- name: Restore build output cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-Linux-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
restore-keys: |
build-Linux-${{ github.event.pull_request.number || 'main' }}-
build-Linux-main-
build-Linux-
- name: Setup build environment
uses: ./.github/actions/setup-anki
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Install cargo-llvm-cov, cargo-nextest and cargo-deny
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 #v2.85.3
with:
tool: |
cargo-llvm-cov@0.8.4
cargo-nextest@0.9.99
cargo-deny@0.20.2
- name: Symlink node_modules
run: ln -sf out/node_modules .
- name: Restore coverage baseline
if: github.event_name == 'pull_request'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out/coverage
key: coverage-baseline-linux-${{ github.sha }}
restore-keys: coverage-baseline-linux-
- name: Move restored baseline aside
if: github.event_name == 'pull_request'
run: test -d out/coverage && mv out/coverage out/coverage-baseline || true
- name: Build
run: just build
- name: Lint and test
env:
ONLINE_TESTS: "1"
run: |
just lint
just test --coverage
- name: Run complexipy diff
id: complexipy
continue-on-error: true
run: |
git fetch origin main:main 2>/dev/null || true
just complexipy-diff
- name: Upload SARIF results for complexipy
if: steps.complexipy.outcome == 'failure'
uses: github/codeql-action/upload-sarif@a6fd1787519fd23e68309fad43738e41a6ff2a9d #v4
with:
sarif_file: out/complexipy/complexipy-results.sarif
category: complexipy
- name: Cache coverage baseline
if: github.ref_name == 'main'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out/coverage
key: coverage-baseline-linux-${{ github.sha }}
- name: Check coverage regression
if: github.event_name == 'pull_request'
run: python3 tools/coverage/check-coverage-regression.py out/coverage-baseline out/coverage
- name: Run e2e tests
run: just test-e2e
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1
with:
name: playwright-report
path: out/e2e-report/
retention-days: 7
- name: Ensure libs importable
env:
SKIP_RUN: "1"
run: ./run
- name: Check Rust dependencies
if: github.event_name == 'pull_request'
id: rust-deps
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 #v47.0.6
with:
files: |
Cargo.lock
**/Cargo.toml
.deny.toml
- name: Run cargo-deny check
if: github.event_name != 'pull_request' || steps.rust-deps.outputs.any_changed == 'true'
shell: bash
run: cargo deny check
# out/pyenv contains a venv with absolute Python paths that break
# across runs. out/build.ninja is regenerated by configure each time.
# Remove both before saving so the cache stays portable.
- name: Clean non-cacheable state
if: always()
shell: bash
run: |
rm -rf out/pyenv
rm -f out/build.ninja
- name: Save build output cache
if: always()
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-Linux-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
# ARM Linux. Runs on pushes to release branches, manual dispatch, or on PRs
# with the check:linux label (not on every push to main).
check-linux-arm:
if: >-
(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/'))
|| github.event_name == 'workflow_dispatch'
|| contains(github.event.pull_request.labels.*.name, 'check:linux')
runs-on: ubuntu-24.04-arm
name: check (linux-arm)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
- name: Restore cargo cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
~/.cargo/bin
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: cargo-arm64-Linux-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-arm64-Linux-
- name: Restore build output cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-arm64-Linux-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
restore-keys: |
build-arm64-Linux-${{ github.event.pull_request.number || 'main' }}-
build-arm64-Linux-main-
build-arm64-Linux-
- name: Setup build environment
uses: ./.github/actions/setup-anki
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Install cargo-llvm-cov and cargo-nextest
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 #v2.85.3
with:
tool: |
cargo-llvm-cov@0.8.4
cargo-nextest@0.9.99
- name: Symlink node_modules
run: ln -sf out/node_modules .
- name: Build
run: just build
- name: Lint and test
run: |
just lint
just test
- name: Clean non-cacheable state
if: always()
shell: bash
run: |
rm -rf out/pyenv
rm -f out/build.ninja
- name: Save build output cache
if: always()
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-arm64-Linux-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
# Intel Mac. Runs on pushes to release branches, manual dispatch, or on PRs
# with the check:macos label (not on every push to main).
check-macos-intel:
if: >-
(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/'))
|| github.event_name == 'workflow_dispatch'
|| contains(github.event.pull_request.labels.*.name, 'check:macos')
runs-on: macos-15-intel
name: check (macos-intel)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
with:
submodules: true
- name: Restore cargo cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
~/.cargo/bin
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: cargo-intel-macOS-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-intel-macOS-
- name: Restore build output cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-intel-macOS-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
restore-keys: |
build-intel-macOS-${{ github.event.pull_request.number || 'main' }}-
build-intel-macOS-main-
build-intel-macOS-
- name: Setup build environment
uses: ./.github/actions/setup-anki
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Install cargo-llvm-cov and cargo-nextest
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 #v2.85.3
with:
tool: |
cargo-llvm-cov@0.8.4
cargo-nextest@0.9.99
- name: Symlink node_modules
run: ln -sf out/node_modules .
- name: Build
run: just build
- name: Lint and test
run: |
just lint
just test
- name: Clean non-cacheable state
if: always()
shell: bash
run: |
rm -rf out/pyenv
rm -f out/build.ninja
- name: Save build output cache
if: always()
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-intel-macOS-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
# Runs on pushes to main or on PRs with the check:macos label.
check-macos:
if: >-
github.event_name == 'push'
|| github.event_name == 'workflow_dispatch'
|| contains(github.event.pull_request.labels.*.name, 'check:macos')
runs-on: macos-latest
name: check (macos)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
with:
submodules: true
- name: Restore cargo cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
~/.cargo/bin
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: cargo-macOS-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-macOS-
- name: Restore build output cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-macOS-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
restore-keys: |
build-macOS-${{ github.event.pull_request.number || 'main' }}-
build-macOS-main-
build-macOS-
- name: Setup build environment
uses: ./.github/actions/setup-anki
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Install cargo-llvm-cov and cargo-nextest
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 #v2.85.3
with:
tool: |
cargo-llvm-cov@0.8.4
cargo-nextest@0.9.99
- name: Symlink node_modules
run: ln -sf out/node_modules .
- name: Build
run: just build
- name: Lint and test
run: |
just lint
just test
- name: Clean non-cacheable state
if: always()
shell: bash
run: |
rm -rf out/pyenv
rm -f out/build.ninja
- name: Save build output cache
if: always()
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-macOS-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
# Runs on pushes to main or on PRs with the check:windows label.
check-windows:
if: >-
github.event_name == 'push'
|| github.event_name == 'workflow_dispatch'
|| contains(github.event.pull_request.labels.*.name, 'check:windows')
runs-on: windows-latest
name: check (windows)
# Colocate CARGO_HOME and TEMP on D: to keep all I/O on the same fast
# local disk.
env:
CARGO_HOME: D:\cargo-home
TEMP: D:\tmp
TMP: D:\tmp
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
with:
submodules: true
- name: Prepare D:\ directories
shell: bash
run: mkdir -p /d/cargo-home /d/tmp
- name: Restore cargo cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: |
D:\cargo-home\registry\index
D:\cargo-home\registry\cache
D:\cargo-home\git\db
D:\cargo-home\bin
D:\cargo-home\.crates.toml
D:\cargo-home\.crates2.json
key: cargo-Windows-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-Windows-
- name: Restore build output cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-Windows-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
restore-keys: |
build-Windows-${{ github.event.pull_request.number || 'main' }}-
build-Windows-main-
build-Windows-
- name: Setup build environment
uses: ./.github/actions/setup-anki
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Install cargo-llvm-cov and cargo-nextest
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 #v2.85.3
with:
tool: |
cargo-llvm-cov@0.8.4
cargo-nextest@0.9.99
- name: Build
run: just build
- name: Lint and test
run: |
just lint
just test
# Also remove node_modules on Windows — file-locking corrupts the cache.
- name: Clean non-cacheable state
if: always()
shell: bash
run: |
rm -rf out/pyenv out/node_modules
rm -f out/build.ninja
- name: Save build output cache
if: always()
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-Windows-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
# ARM Windows. Runs on pushes to release branches, manual dispatch, or on
# PRs with the check:windows label (not on every push to main).
check-windows-arm:
if: >-
(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/'))
|| github.event_name == 'workflow_dispatch'
|| contains(github.event.pull_request.labels.*.name, 'check:windows')
runs-on: windows-11-arm
name: check (windows-arm)
# Unlike the x64 Windows runner, windows-11-arm has no D: drive, so we use
# the default C:-based CARGO_HOME and TEMP.
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v4
with:
submodules: true
- name: Restore cargo cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
~/.cargo/bin
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: cargo-arm64-Windows-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-arm64-Windows-
- name: Restore build output cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-arm64-Windows-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}
restore-keys: |
build-arm64-Windows-${{ github.event.pull_request.number || 'main' }}-
build-arm64-Windows-main-
build-arm64-Windows-
- name: Setup build environment
uses: ./.github/actions/setup-anki
- name: Install just
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4
- name: Install cargo-llvm-cov and cargo-nextest
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 #v2.85.3
with:
tool: |
cargo-llvm-cov@0.8.4
cargo-nextest@0.9.99
- name: Build
run: just build
- name: Lint and test
run: |
just lint
just test
# Also remove node_modules on Windows — file-locking corrupts the cache.
- name: Clean non-cacheable state
if: always()
shell: bash
run: |
rm -rf out/pyenv out/node_modules
rm -f out/build.ninja
- name: Save build output cache
if: always()
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
with:
path: out
key: build-arm64-Windows-${{ github.event.pull_request.number || 'main' }}-${{ github.run_id }}