1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
name: CI
on:
push:
branches:
- main
pull_request:
schedule:
- cron: "0 6 * * *" # Nightly at 06:00 UTC
# Cache keys are keyed on the pinned model revisions (issue #217); the
# air-gapped/docs drift test in src/embedding.rs pins both keys against the
# profile revision constants — bump a key if and only if its revision changes.
env:
HF_CACHE_KEY: hf-hub-bge-small-en-v1.5-5c38ec7
HF_CACHE_KEY_E5: hf-hub-multilingual-e5-small-614241f
jobs:
test:
name: Test
runs-on: ubicloud-standard-4
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v6
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v6
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Cache HuggingFace models
uses: actions/cache@v6
with:
path: ~/.cache/huggingface/hub
key: ${{ runner.os }}-${{ env.HF_CACHE_KEY }}
- name: Format check
run: cargo fmt --check
- name: Clippy
run: cargo clippy --locked --all-targets -- -D warnings
- name: Test
run: cargo test --locked
- name: Test (ignored — requires model)
if: github.event_name == 'schedule'
run: cargo test --locked -- --ignored
# Note: ONNX Runtime shared library is auto-downloaded during build
# CI may need extra time on first run due to download
test-no-default-features:
name: Test (no default features)
runs-on: ubicloud-standard-4
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v6
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v6
with:
path: target
key: ${{ runner.os }}-cargo-build-target-ndf-${{ hashFiles('**/Cargo.lock') }}
- name: Cache HuggingFace models
uses: actions/cache@v6
with:
path: ~/.cache/huggingface/hub
key: ${{ runner.os }}-${{ env.HF_CACHE_KEY }}
- name: Clippy (no default features)
run: cargo clippy --locked --no-default-features --all-targets -- -D warnings
- name: Test (no default features)
run: cargo test --locked --no-default-features
# MSRV gate (issue #257). The declared `rust-version` in Cargo.toml is a
# promise to users, and the default `mcp` feature pulls a dependency graph
# (rmcp -> rmcp-macros -> darling 0.23) whose floor is far above that field
# used to claim. Nothing here checked the declared version, so it rotted.
# This job installs *exactly* the declared toolchain and checks BOTH feature
# sets with --locked — the default set and `--no-default-features` — so a
# dependency raising its own rust-version above the declaration reddens CI
# instead of breaking user builds, whichever feature set they build.
#
# Both feature sets must build on 1.88. Keep the toolchain pin in sync with
# `rust-version` in Cargo.toml, the minimum stated in README.md and the floor
# in CONTRIBUTING.md — `test_msrv_version_pins_agree` locks all four together.
msrv:
name: MSRV
runs-on: ubicloud-standard-4
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.88.0
- name: Cache cargo registry
uses: actions/cache@v6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-msrv-1.88.0-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v6
with:
path: target
key: ${{ runner.os }}-cargo-build-target-msrv-1.88.0-${{ hashFiles('**/Cargo.lock') }}
- name: Check (default features)
run: cargo check --locked --all-targets
- name: Check (no default features)
run: cargo check --locked --no-default-features --all-targets
# Dependency-advisory gate (issue #253). Runs on pull_request (and every push
# to main) plus the nightly schedule above, so a newly published RustSec
# advisory reddens the nightly even when nothing changed here. Kept separate
# from the test jobs: it needs no target/ or HuggingFace cache and no compile,
# so it reports in seconds. `--locked` checks the committed Cargo.lock — the
# graph we actually ship — instead of a fresh resolution nobody runs.
#
# cargo-deny is pinned so the gate's verdict cannot change under us mid-PR;
# bump it with `cargo deny --locked check advisories bans` run locally, since
# a new release can tighten reporting and turn green red.
deny:
name: Dependency advisories
runs-on: ubicloud-standard-4
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-deny
uses: taiki-e/install-action@v2
with:
tool: cargo-deny@0.20.2
- name: Check advisories and denied features
run: cargo deny --locked check advisories bans