-
Notifications
You must be signed in to change notification settings - Fork 3
165 lines (152 loc) · 6.83 KB
/
Copy pathci.yml
File metadata and controls
165 lines (152 loc) · 6.83 KB
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
name: M3 Memory CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
lint:
name: Lint (Ruff)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
cache: 'pip'
- name: Install Ruff
run: pip install ruff
- name: Run Ruff
# bench_*.py / benchmark_*.py are excluded: they carry the same mechanical
# lint debt, but editing them trips the pre-push bench-data guard (their
# source references private benchmark dataset paths). Lint them via a
# separate bench-aware change, not the standard CI gate.
run: ruff check bin/ memory/ --exclude 'bench_*.py' --exclude 'benchmark_*.py'
typecheck:
name: Type Check (Mypy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
cache: 'pip'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install types-PyYAML
- name: Run Mypy
run: mypy bin/ --ignore-missing-imports
security:
name: Security scan (Bandit + pip-audit on core deps)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
cache: 'pip'
# Bandit: static analysis on all code paths. Config (skips, exclusions)
# lives in pyproject.toml under [tool.bandit].
- name: Install Bandit
run: pip install "bandit[toml]"
- name: Run Bandit
run: bandit -c pyproject.toml -r bin/ m3_memory/
# pip-audit: scoped to CORE deps only (no [dev] / no opt-in rerank
# path). Bench/dev transitive CVEs (e.g. transformers, lxml) shouldn't
# gate merges since they don't reach end users; but a CVE in a real
# shipped dep should fail the build immediately. We install the
# package itself (core deps only — no extras) into a clean venv, then
# audit only the locally-installed transitive tree (-l). The local
# flag also skips m3-memory itself, which would otherwise fail audit
# before its release lands on PyPI (chicken-and-egg in pre-release CI).
- name: Install M3 (core deps only) into a clean venv
run: |
python -m venv /tmp/m3-core
/tmp/m3-core/bin/pip install --upgrade pip
# Install M3 to pull its core dependencies, then uninstall the
# package itself. pip-audit -l would otherwise try to look up
# m3-memory on PyPI and fail with "not found" before each release
# tag is published (chicken-and-egg in pre-release CI).
/tmp/m3-core/bin/pip install .
/tmp/m3-core/bin/pip uninstall -y m3-memory
/tmp/m3-core/bin/pip install pip-audit
- name: pip-audit (core deps, locally installed)
# CVE-2026-3219: pip itself — present because pip is in every venv,
# but pip is not a shipped runtime dependency of m3-memory. Ignored
# so the audit signal stays focused on actual shipped-library CVEs.
#
# PYSEC-2025-183: pyjwt "weak encryption" — affects ALL pyjwt versions
# (0.1.1–2.12.1) with no fixed version published, so it cannot be
# resolved by upgrading. The advisory is disputed by the pyjwt
# maintainers: the concern is the key length chosen by the calling
# application, not a flaw in the library. m3-memory's own code never
# imports `jwt`; pyjwt is present only transitively via the `mcp`
# core dependency, so the weak-key-length path is not reachable
# through m3-memory. Ignored; revisit if pyjwt ships a real fix.
run: /tmp/m3-core/bin/pip-audit --strict -l --ignore-vuln CVE-2026-3219 --ignore-vuln PYSEC-2025-183
# Emit the test matrix based on event type. Pull requests get a single fast
# cell (ubuntu + 3.12) for quick feedback; pushes to main/release run the
# full OS × Python grid so cross-platform coverage still gates the branch
# everything merges into. A bug that only shows on macOS/Windows or 3.11 is
# caught at merge time, not on every PR iteration.
matrix-setup:
name: Resolve test matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- id: set
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo 'matrix={"os":["ubuntu-latest"],"python-version":["3.12"]}' >> "$GITHUB_OUTPUT"
else
echo 'matrix={"os":["ubuntu-latest","macos-latest","windows-latest"],"python-version":["3.11","3.12"]}' >> "$GITHUB_OUTPUT"
fi
test:
name: Test on ${{ matrix.os }} (py${{ matrix.python-version }})
needs: [lint, typecheck, matrix-setup]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix-setup.outputs.matrix) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run Pytest (hermetic lane)
# The hermetic unit lane: everything that needs no external service and is
# not timing-sensitive.
# - `not integration` excludes tests needing a live service (requires_pg /
# requires_embedder / requires_gguf / requires_files_db) — GH runners
# provision none, so they'd only self-skip. Run them on a dev box (or a
# future services job) with `pytest -m integration`.
# - `not slow` excludes the perf tests (test_chatlog_perf). Their wall-clock
# budgets (e.g. enqueue < 200ms) assume a quiet, dedicated host; a shared
# ubuntu-latest runner misses them intermittently (measured 213ms vs 200ms
# budget — a scheduling flake, not a regression). Perf belongs on a
# baseline-stable host, not the PR gate. Run locally with `pytest -m slow`.
# --strict-markers makes a typo'd marker a hard error.
# See docs/design/TEST_SUITE_DESIGN.md.
run: |
pytest tests/ -m "not integration and not slow"