Skip to content

Commit ca66b34

Browse files
committed
ci: consolidate rust workflows and supply-chain checks
Signed-off-by: lucarlig <luca.carlig@ibm.com>
1 parent da4a48c commit ca66b34

File tree

23 files changed

+7351
-434
lines changed

23 files changed

+7351
-434
lines changed

.github/CODEOWNERS

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
66
/mcpgateway/plugins @araujof @terylt @jonpspri
77

88
# Rust projects
9-
/tools_rust/ @lucarlig @dima-zakharov
10-
/mcp-servers/rust/ @lucarlig @dima-zakharov
9+
/crates/ @lucarlig @dima-zakharov @dawid-nowak
10+
/mcp-servers/rust/ @lucarlig @dima-zakharov @dawid-nowak
11+
/Cargo.toml @lucarlig @dima-zakharov @dawid-nowak
12+
/Cargo.lock @lucarlig @dima-zakharov @dawid-nowak
13+
/deny.toml @lucarlig @dima-zakharov @dawid-nowak
14+
/rust-toolchain.toml @lucarlig @dima-zakharov @dawid-nowak
15+
/supply-chain/ @lucarlig @dima-zakharov @dawid-nowak
16+
/.github/workflows/rust.yml @lucarlig @dima-zakharov @dawid-nowak
17+
/.github/workflows/pytest-rust.yml @lucarlig @dima-zakharov @dawid-nowak
1118

1219
# Ownership for all tests
1320
/tests/ @crivetimihai @kevalmahajan @madhav165

.github/workflows/docker-scan.yml

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ on:
1919
branches: ["main"]
2020
paths:
2121
- 'Containerfile.lite'
22+
- 'crates/**'
23+
- 'Cargo.toml'
24+
- 'Cargo.lock'
2225
- 'mcpgateway/**'
2326
- 'plugins/**'
2427
- 'pyproject.toml'
@@ -28,6 +31,9 @@ on:
2831
branches: ["main"]
2932
paths:
3033
- 'Containerfile.lite'
34+
- 'crates/**'
35+
- 'Cargo.toml'
36+
- 'Cargo.lock'
3137
- 'mcpgateway/**'
3238
- 'plugins/**'
3339
- 'pyproject.toml'
@@ -76,15 +82,44 @@ jobs:
7682
cache-to: type=gha,mode=max,scope=scan-build-amd64
7783

7884
- name: Generate SBOM (Syft)
79-
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0
80-
with:
81-
image: ${{ env.IMAGE_NAME }}:scan
82-
output-file: sbom.spdx.json
83-
upload-artifact: false
85+
run: |
86+
docker run --rm \
87+
-v /var/run/docker.sock:/var/run/docker.sock \
88+
-v "${PWD}:/work" \
89+
anchore/syft:v1.42.3 \
90+
"docker:${IMAGE_NAME}:scan" -o spdx-json=/work/sbom.spdx.json
8491
8592
- name: Upload SBOM
8693
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
8794
with:
8895
name: sbom
8996
path: sbom.spdx.json
9097
retention-days: 30
98+
99+
rust-enabled-build:
100+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
101+
name: Rust-enabled container smoke
102+
runs-on: ubuntu-latest
103+
timeout-minutes: 60
104+
105+
steps:
106+
- name: Checkout code
107+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
108+
with:
109+
persist-credentials: false
110+
111+
- name: Set up Docker Buildx
112+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
113+
114+
- name: Build Rust-enabled image locally
115+
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
116+
with:
117+
context: .
118+
file: Containerfile.lite
119+
platforms: linux/amd64
120+
push: false
121+
load: false
122+
build-args: |
123+
ENABLE_RUST=true
124+
cache-from: type=gha,scope=scan-build-rust-amd64
125+
cache-to: type=gha,mode=max,scope=scan-build-rust-amd64

.github/workflows/license-check.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,28 @@ on:
55
branches: ["main"]
66
paths:
77
- "pyproject.toml"
8+
- "Cargo.toml"
89
- "Cargo.lock"
10+
- "crates/**"
11+
- "mcp-servers/rust/**"
912
- "package.json"
1013
- "package-lock.json"
14+
- "license-policy.toml"
15+
- "scripts/license_checker.py"
1116
- ".github/workflows/license-check.yml"
1217
pull_request:
1318
types: [opened, synchronize, ready_for_review]
1419
branches: ["main"]
1520
paths:
1621
- "pyproject.toml"
22+
- "Cargo.toml"
1723
- "Cargo.lock"
24+
- "crates/**"
25+
- "mcp-servers/rust/**"
1826
- "package.json"
1927
- "package-lock.json"
28+
- "license-policy.toml"
29+
- "scripts/license_checker.py"
2030
- ".github/workflows/license-check.yml"
2131

2232
concurrency:

.github/workflows/pytest-rust.yml

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# ===============================================================
2+
# 🧪🦀 PyTest With Rust Build - Quality Gate
3+
# ===============================================================
4+
#
5+
# - builds/install Rust-backed components required by the Python suite
6+
# - runs the full pytest suite with Rust enabled
7+
# - measures branch + line coverage (fails < 90% main, < 35% doctest)
8+
# - posts changed-line coverage for PRs
9+
# ---------------------------------------------------------------
10+
11+
name: Tests & Coverage (Rust)
12+
13+
on:
14+
push:
15+
branches: ["main"]
16+
paths:
17+
- "crates/**"
18+
- "Cargo.toml"
19+
- "Cargo.lock"
20+
- "rust-toolchain.toml"
21+
- "deny.toml"
22+
- "tests/e2e_rust/**"
23+
- ".github/workflows/pytest-rust.yml"
24+
pull_request:
25+
types: [opened, synchronize, ready_for_review]
26+
branches: ["main"]
27+
paths:
28+
- "crates/**"
29+
- "Cargo.toml"
30+
- "Cargo.lock"
31+
- "rust-toolchain.toml"
32+
- "deny.toml"
33+
- "tests/e2e_rust/**"
34+
- ".github/workflows/pytest-rust.yml"
35+
36+
concurrency:
37+
group: ${{ github.workflow }}-${{ github.ref }}
38+
cancel-in-progress: true
39+
40+
permissions:
41+
contents: read
42+
43+
jobs:
44+
test:
45+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
46+
name: pytest-rust
47+
runs-on: ubuntu-latest
48+
timeout-minutes: 40
49+
services:
50+
redis:
51+
image: redis:7-bookworm
52+
ports:
53+
- 6379:6379
54+
options: >-
55+
--health-cmd "redis-cli ping"
56+
--health-interval 5s
57+
--health-timeout 3s
58+
--health-retries 20
59+
60+
env:
61+
PYTHONUNBUFFERED: "1"
62+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
63+
REQUIRE_RUST: "1"
64+
AUTH_ENCRYPTION_SECRET: ci-rust-auth-encryption-secret-1234567890 # pragma: allowlist secret
65+
REDIS_URL: redis://127.0.0.1:6379/0
66+
MCP_RUST_REDIS_URL: redis://127.0.0.1:6379/0
67+
68+
steps:
69+
- name: ⬇️ Checkout code
70+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
71+
with:
72+
persist-credentials: false
73+
fetch-depth: 0
74+
75+
- name: 🐍 Setup Python 3.12
76+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
77+
with:
78+
python-version: "3.12"
79+
cache: pip
80+
81+
- name: ⚡ Install uv
82+
uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
83+
with:
84+
version: "0.10.11"
85+
python-version: "3.12"
86+
87+
- name: 🦀 Install Rust stable
88+
run: |
89+
rustup toolchain install stable
90+
rustup default stable
91+
92+
- name: 📦 Cache Cargo dependencies
93+
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
94+
with:
95+
path: |
96+
~/.cargo/registry
97+
~/.cargo/git
98+
target
99+
key: ${{ runner.os }}-cargo-pytest-rust-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
100+
restore-keys: |
101+
${{ runner.os }}-cargo-pytest-rust-
102+
103+
- name: 🔨 Build Rust extensions
104+
run: make rust-install && make rust-verify-stubs
105+
106+
- name: 🧪 Run pytest
107+
run: |
108+
uv run --extra plugins pytest -n 0 \
109+
--durations=5 \
110+
--ignore=tests/fuzz \
111+
--ignore=tests/e2e/test_entra_id_integration.py \
112+
--cov=mcpgateway \
113+
--cov-report=xml \
114+
--cov-report=html \
115+
--cov-report=term \
116+
--cov-branch \
117+
--cov-fail-under=95
118+
119+
- name: 📈 Diff-cover (changed lines)
120+
if: github.event_name == 'pull_request'
121+
run: |
122+
uv run diff-cover coverage.xml \
123+
--compare-branch=origin/${{ github.base_ref }} \
124+
--fail-under=93
125+
126+
- name: 📊 Doctest coverage with threshold
127+
run: |
128+
uv run --extra plugins pytest -n 0 \
129+
--doctest-modules mcpgateway/ \
130+
--cov=mcpgateway \
131+
--cov-report=term \
132+
--cov-report=json:doctest-coverage.json \
133+
--cov-fail-under=30 \
134+
--tb=short

.github/workflows/pytest.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@ on:
1818
# paths:
1919
# - "mcpgateway/**"
2020
# - "tests/**"
21+
# - "!tests/e2e_rust/**"
2122
# - "pyproject.toml"
23+
# - "uv.lock"
2224
# - ".github/workflows/pytest.yml"
2325
pull_request:
2426
types: [opened, synchronize, ready_for_review]
2527
branches: ["main"]
2628
# paths:
2729
# - "mcpgateway/**"
2830
# - "tests/**"
31+
# - "!tests/e2e_rust/**"
2932
# - "pyproject.toml"
33+
# - "uv.lock"
3034
# - ".github/workflows/pytest.yml"
3135
# schedule:
3236
# - cron: '42 3 * * 1' # Monday 03:42 UTC
@@ -86,8 +90,6 @@ jobs:
8690
# Note: Rust plugin builds removed - all plugins now distributed as PyPI packages
8791
# Rust MCP runtime (tools_rust/mcp_runtime) not needed for main pytest suite
8892
# (e2e_rust tests are excluded and run in separate workflow)
89-
# -----------------------------------------------------------
90-
9193
# -----------------------------------------------------------
9294
# 3️⃣ Run the tests with coverage (fail under 95 %total coverage)
9395
# -----------------------------------------------------------

0 commit comments

Comments
 (0)