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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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 }}
# ort-sys downloads the prebuilt ONNX Runtime archive at build time into
# ~/.cache/ort.pyke.io/dfbin/<target>/<hash>. Keyed on runner.os plus the
# lock: one runner OS per job, and the lock is what pins ort/ort-sys, so
# bumping the pin starts cold rather than restoring an older tree (no
# restore-keys). The path assumes ORT_CACHE_DIR and XDG_CACHE_HOME are
# unset, as they are on the CI runners — either one relocates the tree.
- name: Cache ONNX Runtime download
uses: actions/cache@v6
with:
path: ~/.cache/ort.pyke.io
key: ${{ runner.os }}-ort-pyke-${{ hashFiles('**/Cargo.lock') }}
- 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 }}
# Same prebuilt ONNX Runtime archive as the Test job: same runner OS and
# the same lock, so the same key hits rather than downloading and
# uploading the tree twice. As above, the path assumes ORT_CACHE_DIR and
# XDG_CACHE_HOME are unset, as they are on the CI runners.
- name: Cache ONNX Runtime download
uses: actions/cache@v6
with:
path: ~/.cache/ort.pyke.io
key: ${{ runner.os }}-ort-pyke-${{ hashFiles('**/Cargo.lock') }}
- 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.92. 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.92.0
- name: Cache cargo registry
uses: actions/cache@v6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-msrv-1.92.0-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v6
with:
path: target
key: ${{ runner.os }}-cargo-build-target-msrv-1.92.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