drasi-lib 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. drasi_lib-0.1.0/.github/workflows/ci.yml +432 -0
  2. drasi_lib-0.1.0/.github/workflows/release.yml +233 -0
  3. drasi_lib-0.1.0/.gitignore +31 -0
  4. drasi_lib-0.1.0/CHANGELOG.md +73 -0
  5. drasi_lib-0.1.0/CONTRIBUTING.md +97 -0
  6. drasi_lib-0.1.0/Cargo.lock +4294 -0
  7. drasi_lib-0.1.0/Cargo.toml +56 -0
  8. drasi_lib-0.1.0/LICENSE +202 -0
  9. drasi_lib-0.1.0/Makefile +105 -0
  10. drasi_lib-0.1.0/PKG-INFO +241 -0
  11. drasi_lib-0.1.0/README.md +210 -0
  12. drasi_lib-0.1.0/docs/api-audit.md +315 -0
  13. drasi_lib-0.1.0/docs/metrics.md +183 -0
  14. drasi_lib-0.1.0/docs/plugins.md +133 -0
  15. drasi_lib-0.1.0/docs/releasing.md +204 -0
  16. drasi_lib-0.1.0/examples/README.md +262 -0
  17. drasi_lib-0.1.0/examples/_throwaway_postgres.py +91 -0
  18. drasi_lib-0.1.0/examples/install_plugin.py +78 -0
  19. drasi_lib-0.1.0/examples/postgres_cdc.py +110 -0
  20. drasi_lib-0.1.0/examples/python_source.py +99 -0
  21. drasi_lib-0.1.0/examples/streaming.py +99 -0
  22. drasi_lib-0.1.0/examples/sync_quickstart.py +68 -0
  23. drasi_lib-0.1.0/pyproject.toml +81 -0
  24. drasi_lib-0.1.0/python/drasi/__init__.py +62 -0
  25. drasi_lib-0.1.0/python/drasi/_drasi.pyi +466 -0
  26. drasi_lib-0.1.0/python/drasi/py.typed +0 -0
  27. drasi_lib-0.1.0/python/drasi/sync.py +528 -0
  28. drasi_lib-0.1.0/python/drasi/types.py +360 -0
  29. drasi_lib-0.1.0/rust-toolchain.toml +3 -0
  30. drasi_lib-0.1.0/scripts/build_plugins.py +138 -0
  31. drasi_lib-0.1.0/scripts/check_registry_pins.py +198 -0
  32. drasi_lib-0.1.0/scripts/check_version_sync.py +254 -0
  33. drasi_lib-0.1.0/src/components.rs +564 -0
  34. drasi_lib-0.1.0/src/conversions.rs +680 -0
  35. drasi_lib-0.1.0/src/engine.rs +2331 -0
  36. drasi_lib-0.1.0/src/errors.rs +344 -0
  37. drasi_lib-0.1.0/src/host.rs +48 -0
  38. drasi_lib-0.1.0/src/lib.rs +59 -0
  39. drasi_lib-0.1.0/src/plugins.rs +586 -0
  40. drasi_lib-0.1.0/src/runtime.rs +42 -0
  41. drasi_lib-0.1.0/src/secrets.rs +169 -0
  42. drasi_lib-0.1.0/src/stores.rs +314 -0
  43. drasi_lib-0.1.0/src/streams.rs +203 -0
  44. drasi_lib-0.1.0/tests/__init__.py +0 -0
  45. drasi_lib-0.1.0/tests/conftest.py +64 -0
  46. drasi_lib-0.1.0/tests/e2e/__init__.py +0 -0
  47. drasi_lib-0.1.0/tests/e2e/helpers.py +182 -0
  48. drasi_lib-0.1.0/tests/e2e/test_concurrency.py +155 -0
  49. drasi_lib-0.1.0/tests/e2e/test_durable_and_config.py +307 -0
  50. drasi_lib-0.1.0/tests/e2e/test_examples.py +162 -0
  51. drasi_lib-0.1.0/tests/e2e/test_introspection.py +200 -0
  52. drasi_lib-0.1.0/tests/e2e/test_lifecycle.py +220 -0
  53. drasi_lib-0.1.0/tests/e2e/test_local_plugins.py +155 -0
  54. drasi_lib-0.1.0/tests/e2e/test_oci_plugins.py +259 -0
  55. drasi_lib-0.1.0/tests/e2e/test_plugin_management.py +195 -0
  56. drasi_lib-0.1.0/tests/e2e/test_python_components.py +569 -0
  57. drasi_lib-0.1.0/tests/e2e/test_readme.py +50 -0
  58. drasi_lib-0.1.0/tests/e2e/test_stores.py +238 -0
  59. drasi_lib-0.1.0/tests/e2e/test_streaming.py +232 -0
  60. drasi_lib-0.1.0/tests/e2e/test_sync.py +157 -0
  61. drasi_lib-0.1.0/tests/e2e/test_testcontainers.py +209 -0
  62. drasi_lib-0.1.0/tests/unit/__init__.py +0 -0
  63. drasi_lib-0.1.0/tests/unit/test_parity.py +120 -0
  64. drasi_lib-0.1.0/tests/unit/test_registry_pins.py +77 -0
  65. drasi_lib-0.1.0/tests/unit/test_stubs.py +116 -0
  66. drasi_lib-0.1.0/tests/unit/test_version_sync.py +123 -0
@@ -0,0 +1,432 @@
1
+ # Copyright 2026 The Drasi Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ name: CI
16
+
17
+ on:
18
+ push:
19
+ branches: [main]
20
+ pull_request:
21
+ workflow_dispatch:
22
+
23
+ env:
24
+ CARGO_TERM_COLOR: always
25
+ RUST_BACKTRACE: 1
26
+
27
+ concurrency:
28
+ group: ${{ github.workflow }}-${{ github.ref }}
29
+ cancel-in-progress: true
30
+
31
+ # Linux runners are pinned to an explicit image rather than `ubuntu-latest`.
32
+ # The `ubuntu-latest` alias pool has been subject to prolonged starvation
33
+ # (measured 2h24m to allocate, while `ubuntu-24.04` allocated in 2s from the
34
+ # same repo at the same moment). Pinning also keeps the toolchain reproducible.
35
+ # Re-pin deliberately when upgrading; do not revert to `ubuntu-latest`.
36
+
37
+ jobs:
38
+ lint:
39
+ name: Lint
40
+ runs-on: ubuntu-24.04
41
+ steps:
42
+ - uses: actions/checkout@v5
43
+ - uses: dtolnay/rust-toolchain@stable
44
+ with:
45
+ components: clippy, rustfmt
46
+ - uses: astral-sh/setup-uv@v6
47
+ - uses: Swatinem/rust-cache@v2
48
+
49
+ - name: Install libclang for bindgen-capable builds
50
+ run: |
51
+ sudo apt-get update
52
+ sudo apt-get install -y clang libclang-dev
53
+
54
+ - name: Set up Python tooling
55
+ run: |
56
+ uv venv --python 3.12 .venv
57
+ uv pip install --python .venv/bin/python maturin pytest pytest-asyncio pytest-timeout ruff
58
+
59
+ - name: Rust formatting
60
+ run: cargo fmt --check
61
+
62
+ - name: Rust linting
63
+ env:
64
+ PYO3_PYTHON: ${{ github.workspace }}/.venv/bin/python
65
+ run: cargo clippy --all-targets -- -D warnings
66
+
67
+ - name: Python linting
68
+ run: .venv/bin/ruff check .
69
+
70
+ - name: Python formatting
71
+ run: .venv/bin/ruff format --check .
72
+
73
+ registry-pins:
74
+ name: Registry pin drift
75
+ runs-on: ubuntu-24.04
76
+ steps:
77
+ - uses: actions/checkout@v5
78
+ # Published plugins record the Drasi versions they were built against, and
79
+ # this host rejects anything that does not match on major.minor. If our
80
+ # pins drift, every published plugin silently becomes uninstallable.
81
+ - name: Check published plugin compatibility pins
82
+ run: python3 scripts/check_registry_pins.py
83
+
84
+ rust-tests:
85
+ name: Rust tests (${{ matrix.os }})
86
+ runs-on: ${{ matrix.os }}
87
+ strategy:
88
+ fail-fast: false
89
+ matrix:
90
+ os: [ubuntu-24.04, macos-latest, windows-latest]
91
+ steps:
92
+ - uses: actions/checkout@v5
93
+ - uses: dtolnay/rust-toolchain@stable
94
+ - uses: astral-sh/setup-uv@v6
95
+ - uses: Swatinem/rust-cache@v2
96
+
97
+ - name: Install libclang (Linux)
98
+ if: runner.os == 'Linux'
99
+ run: |
100
+ sudo apt-get update
101
+ sudo apt-get install -y clang libclang-dev
102
+
103
+ - name: Point bindgen at LLVM (Windows)
104
+ if: runner.os == 'Windows'
105
+ run: echo "LIBCLANG_PATH=$((gcm clang).source -replace 'clang.exe')" >> $env:GITHUB_ENV
106
+
107
+ - name: Set up Python
108
+ shell: bash
109
+ run: uv venv --python 3.12 .venv
110
+
111
+ - name: Resolve interpreter paths
112
+ shell: bash
113
+ run: |
114
+ if [ -d .venv/Scripts ]; then
115
+ echo "PY=$PWD/.venv/Scripts/python.exe" >> "$GITHUB_ENV"
116
+ echo "PYO3_PYTHON=$PWD/.venv/Scripts/python.exe" >> "$GITHUB_ENV"
117
+ else
118
+ echo "PY=$PWD/.venv/bin/python" >> "$GITHUB_ENV"
119
+ echo "PYO3_PYTHON=$PWD/.venv/bin/python" >> "$GITHUB_ENV"
120
+ fi
121
+
122
+ - name: Cargo tests
123
+ shell: bash
124
+ run: cargo test
125
+
126
+ hermetic-python:
127
+ name: Hermetic Python (${{ matrix.os }}, py${{ matrix.python }})
128
+ runs-on: ${{ matrix.os }}
129
+ strategy:
130
+ fail-fast: false
131
+ matrix:
132
+ include:
133
+ # abi3 gives one wheel for 3.10+, but the Python facade still needs
134
+ # version coverage. Keep the expensive OS cross-product on 3.12, then
135
+ # sweep every supported Python on Linux where runners are fastest.
136
+ - os: ubuntu-24.04
137
+ python: "3.10"
138
+ - os: ubuntu-24.04
139
+ python: "3.11"
140
+ - os: ubuntu-24.04
141
+ python: "3.12"
142
+ - os: ubuntu-24.04
143
+ python: "3.13"
144
+ - os: macos-latest
145
+ python: "3.12"
146
+ - os: windows-latest
147
+ python: "3.12"
148
+ steps:
149
+ - uses: actions/checkout@v5
150
+ - uses: dtolnay/rust-toolchain@stable
151
+ - uses: astral-sh/setup-uv@v6
152
+ - uses: Swatinem/rust-cache@v2
153
+
154
+ - name: Install libclang (Linux)
155
+ if: runner.os == 'Linux'
156
+ run: |
157
+ sudo apt-get update
158
+ sudo apt-get install -y clang libclang-dev
159
+
160
+ - name: Point bindgen at LLVM (Windows)
161
+ if: runner.os == 'Windows'
162
+ run: echo "LIBCLANG_PATH=$((gcm clang).source -replace 'clang.exe')" >> $env:GITHUB_ENV
163
+
164
+ - name: Set up the virtualenv
165
+ shell: bash
166
+ run: uv venv --python ${{ matrix.python }} .venv
167
+
168
+ - name: Resolve tool paths
169
+ shell: bash
170
+ run: |
171
+ if [ -d .venv/Scripts ]; then
172
+ echo "PY=$PWD/.venv/Scripts/python.exe" >> "$GITHUB_ENV"
173
+ echo "MATURIN=$PWD/.venv/Scripts/maturin.exe" >> "$GITHUB_ENV"
174
+ echo "PYTEST=$PWD/.venv/Scripts/pytest.exe" >> "$GITHUB_ENV"
175
+ else
176
+ echo "PY=$PWD/.venv/bin/python" >> "$GITHUB_ENV"
177
+ echo "MATURIN=$PWD/.venv/bin/maturin" >> "$GITHUB_ENV"
178
+ echo "PYTEST=$PWD/.venv/bin/pytest" >> "$GITHUB_ENV"
179
+ fi
180
+
181
+ - name: Install Python test dependencies
182
+ shell: bash
183
+ run: |
184
+ uv pip install --python "$PY" maturin pytest pytest-asyncio pytest-timeout
185
+
186
+ - name: Build the extension
187
+ shell: bash
188
+ env:
189
+ VIRTUAL_ENV: ${{ github.workspace }}/.venv
190
+ run: |
191
+ "$MATURIN" develop
192
+
193
+ - name: Unit and hermetic end-to-end tests
194
+ shell: bash
195
+ run: |
196
+ "$PYTEST" -m "not plugins and not oci and not docker" -v
197
+
198
+ local-plugins:
199
+ name: Local plugins (${{ matrix.os }}, py3.12)
200
+ runs-on: ${{ matrix.os }}
201
+ strategy:
202
+ fail-fast: false
203
+ matrix:
204
+ os: [ubuntu-24.04, macos-latest, windows-latest]
205
+ steps:
206
+ - uses: actions/checkout@v5
207
+ - uses: dtolnay/rust-toolchain@stable
208
+ - uses: astral-sh/setup-uv@v6
209
+ - uses: Swatinem/rust-cache@v2
210
+
211
+ - name: Install libclang (Linux)
212
+ if: runner.os == 'Linux'
213
+ run: |
214
+ sudo apt-get update
215
+ sudo apt-get install -y clang libclang-dev
216
+
217
+ - name: Point bindgen at LLVM (Windows)
218
+ if: runner.os == 'Windows'
219
+ run: echo "LIBCLANG_PATH=$((gcm clang).source -replace 'clang.exe')" >> $env:GITHUB_ENV
220
+
221
+ - name: Set up the virtualenv
222
+ shell: bash
223
+ run: uv venv --python 3.12 .venv
224
+
225
+ - name: Resolve tool paths
226
+ shell: bash
227
+ run: |
228
+ if [ -d .venv/Scripts ]; then
229
+ echo "PY=$PWD/.venv/Scripts/python.exe" >> "$GITHUB_ENV"
230
+ echo "MATURIN=$PWD/.venv/Scripts/maturin.exe" >> "$GITHUB_ENV"
231
+ echo "PYTEST=$PWD/.venv/Scripts/pytest.exe" >> "$GITHUB_ENV"
232
+ else
233
+ echo "PY=$PWD/.venv/bin/python" >> "$GITHUB_ENV"
234
+ echo "MATURIN=$PWD/.venv/bin/maturin" >> "$GITHUB_ENV"
235
+ echo "PYTEST=$PWD/.venv/bin/pytest" >> "$GITHUB_ENV"
236
+ fi
237
+
238
+ - name: Install Python test dependencies
239
+ shell: bash
240
+ run: |
241
+ uv pip install --python "$PY" maturin pytest pytest-asyncio pytest-timeout
242
+
243
+ - name: Build the extension
244
+ shell: bash
245
+ env:
246
+ VIRTUAL_ENV: ${{ github.workspace }}/.venv
247
+ run: |
248
+ "$MATURIN" develop
249
+
250
+ # Building these cdylibs fetches crates and dominates this tier; the cache
251
+ # key tracks the pin file because plugin compatibility depends on it.
252
+ - name: Cache the test plugins
253
+ id: plugin-cache
254
+ uses: actions/cache@v4
255
+ with:
256
+ path: plugins
257
+ key: plugins-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/build_plugins.py') }}
258
+
259
+ - name: Build the test plugins
260
+ if: steps.plugin-cache.outputs.cache-hit != 'true'
261
+ shell: bash
262
+ run: |
263
+ "$PY" scripts/build_plugins.py
264
+
265
+ - name: Locally built cdylib plugin tests
266
+ shell: bash
267
+ run: |
268
+ "$PYTEST" -m plugins -v
269
+
270
+ oci-plugins:
271
+ name: OCI plugins (${{ matrix.os }}, py3.12)
272
+ runs-on: ${{ matrix.os }}
273
+ strategy:
274
+ fail-fast: false
275
+ matrix:
276
+ os: [ubuntu-24.04, macos-latest, windows-latest]
277
+ steps:
278
+ - uses: actions/checkout@v5
279
+ - uses: dtolnay/rust-toolchain@stable
280
+ - uses: astral-sh/setup-uv@v6
281
+ - uses: Swatinem/rust-cache@v2
282
+
283
+ - name: Install libclang (Linux)
284
+ if: runner.os == 'Linux'
285
+ run: |
286
+ sudo apt-get update
287
+ sudo apt-get install -y clang libclang-dev
288
+
289
+ - name: Point bindgen at LLVM (Windows)
290
+ if: runner.os == 'Windows'
291
+ run: echo "LIBCLANG_PATH=$((gcm clang).source -replace 'clang.exe')" >> $env:GITHUB_ENV
292
+
293
+ - name: Set up the virtualenv
294
+ shell: bash
295
+ run: uv venv --python 3.12 .venv
296
+
297
+ - name: Resolve tool paths
298
+ shell: bash
299
+ run: |
300
+ if [ -d .venv/Scripts ]; then
301
+ echo "PY=$PWD/.venv/Scripts/python.exe" >> "$GITHUB_ENV"
302
+ echo "MATURIN=$PWD/.venv/Scripts/maturin.exe" >> "$GITHUB_ENV"
303
+ echo "PYTEST=$PWD/.venv/Scripts/pytest.exe" >> "$GITHUB_ENV"
304
+ else
305
+ echo "PY=$PWD/.venv/bin/python" >> "$GITHUB_ENV"
306
+ echo "MATURIN=$PWD/.venv/bin/maturin" >> "$GITHUB_ENV"
307
+ echo "PYTEST=$PWD/.venv/bin/pytest" >> "$GITHUB_ENV"
308
+ fi
309
+
310
+ - name: Install Python test dependencies
311
+ shell: bash
312
+ run: |
313
+ uv pip install --python "$PY" maturin pytest pytest-asyncio pytest-timeout
314
+
315
+ - name: Build the extension
316
+ shell: bash
317
+ env:
318
+ VIRTUAL_ENV: ${{ github.workspace }}/.venv
319
+ run: |
320
+ "$MATURIN" develop
321
+
322
+ - name: Registry download and install tests
323
+ shell: bash
324
+ env:
325
+ DRASI_OCI_TESTS: "1"
326
+ run: |
327
+ "$PYTEST" -m "oci and not docker" -v
328
+
329
+ docker:
330
+ name: Docker services (ubuntu-24.04, py3.12)
331
+ runs-on: ubuntu-24.04
332
+ steps:
333
+ - uses: actions/checkout@v5
334
+ - uses: dtolnay/rust-toolchain@stable
335
+ - uses: astral-sh/setup-uv@v6
336
+ - uses: Swatinem/rust-cache@v2
337
+
338
+ - name: Install libclang
339
+ run: |
340
+ sudo apt-get update
341
+ sudo apt-get install -y clang libclang-dev
342
+
343
+ - name: Set up the virtualenv
344
+ run: |
345
+ uv venv --python 3.12 .venv
346
+ uv pip install --python .venv/bin/python \
347
+ maturin pytest pytest-asyncio pytest-timeout \
348
+ testcontainers 'psycopg[binary]'
349
+
350
+ - name: Build the extension
351
+ env:
352
+ VIRTUAL_ENV: ${{ github.workspace }}/.venv
353
+ run: |
354
+ .venv/bin/maturin develop
355
+
356
+ # Hosted macOS and Windows runners do not expose a comparable Docker
357
+ # daemon, so this tier runs once on Linux after the OS/Python sweeps above.
358
+ - name: Testcontainers and registry-backed Docker tests
359
+ env:
360
+ DRASI_OCI_TESTS: "1"
361
+ run: |
362
+ .venv/bin/pytest -m docker -v
363
+
364
+ rocksdb:
365
+ name: RocksDB feature (ubuntu-24.04, py3.12)
366
+ runs-on: ubuntu-24.04
367
+ steps:
368
+ - uses: actions/checkout@v5
369
+ - uses: dtolnay/rust-toolchain@stable
370
+ - uses: astral-sh/setup-uv@v6
371
+ - uses: Swatinem/rust-cache@v2
372
+
373
+ - name: Install libclang and C++ toolchain
374
+ run: |
375
+ sudo apt-get update
376
+ sudo apt-get install -y clang libclang-dev build-essential
377
+
378
+ - name: Set up the virtualenv
379
+ run: |
380
+ uv venv --python 3.12 .venv
381
+ uv pip install --python .venv/bin/python maturin pytest pytest-asyncio pytest-timeout
382
+
383
+ - name: Cargo tests with RocksDB enabled
384
+ env:
385
+ PYO3_PYTHON: ${{ github.workspace }}/.venv/bin/python
386
+ run: cargo test --features rocksdb
387
+
388
+ - name: Build the extension with RocksDB enabled
389
+ env:
390
+ VIRTUAL_ENV: ${{ github.workspace }}/.venv
391
+ run: |
392
+ .venv/bin/maturin develop --features rocksdb
393
+
394
+ # The tests ask the build which index backends it has, so no environment
395
+ # variable is needed — and cannot drift from what was actually compiled.
396
+ - name: RocksDB-backed index store tests
397
+ run: |
398
+ .venv/bin/python -c "import drasi; assert 'rocksdb' in drasi.host_info()['index_backends']"
399
+ .venv/bin/pytest tests/e2e/test_stores.py -v
400
+
401
+ coverage:
402
+ name: Conversion and error coverage
403
+ runs-on: ubuntu-24.04
404
+ steps:
405
+ - uses: actions/checkout@v5
406
+ - uses: dtolnay/rust-toolchain@stable
407
+ with:
408
+ components: llvm-tools-preview
409
+ - uses: astral-sh/setup-uv@v6
410
+ - uses: Swatinem/rust-cache@v2
411
+ - uses: taiki-e/install-action@cargo-llvm-cov
412
+
413
+ - name: Install libclang
414
+ run: |
415
+ sudo apt-get update
416
+ sudo apt-get install -y clang libclang-dev
417
+
418
+ - name: Set up Python
419
+ run: uv venv --python 3.12 .venv
420
+
421
+ # The conversion and error layers are where a silent mistake turns into a
422
+ # wrong query result rather than a crash, so they are held to a high bar.
423
+ # `stores.rs` and `streams.rs` are excluded because `--lib` runs only the
424
+ # Rust unit tests; those two are exercised through the Python end-to-end
425
+ # tiers, so counting them here would measure the wrong thing.
426
+ - name: Coverage gate
427
+ env:
428
+ PYO3_PYTHON: ${{ github.workspace }}/.venv/bin/python
429
+ run: |
430
+ cargo llvm-cov --lib \
431
+ --ignore-filename-regex '(engine|components|plugins|host|runtime|lib|stores|streams)\.rs$' \
432
+ --fail-under-lines 80
@@ -0,0 +1,233 @@
1
+ # Copyright 2026 The Drasi Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ name: Release
16
+
17
+ on:
18
+ push:
19
+ tags:
20
+ - "v*"
21
+ workflow_dispatch:
22
+
23
+ permissions:
24
+ contents: read
25
+
26
+ env:
27
+ CARGO_TERM_COLOR: always
28
+ RUST_BACKTRACE: 1
29
+
30
+ concurrency:
31
+ group: ${{ github.workflow }}-${{ github.ref }}
32
+ cancel-in-progress: false
33
+
34
+ jobs:
35
+ wheels:
36
+ name: Wheel (${{ matrix.target }})
37
+ runs-on: ${{ matrix.os }}
38
+ strategy:
39
+ fail-fast: false
40
+ matrix:
41
+ include:
42
+ # Ubuntu 22.04 deliberately keeps the glibc floor lower for consumers.
43
+ - os: ubuntu-22.04
44
+ target: x86_64-unknown-linux-gnu
45
+ - os: ubuntu-22.04-arm
46
+ target: aarch64-unknown-linux-gnu
47
+ - os: macos-latest
48
+ target: aarch64-apple-darwin
49
+ # macOS 13 was retired, so its label never allocates a runner and the
50
+ # job queues forever. `macos-15-intel` is the standard x64 label; the
51
+ # older of the two available keeps the deployment target floor lower
52
+ # for consumers, in the same spirit as ubuntu-22.04 above.
53
+ - os: macos-15-intel
54
+ target: x86_64-apple-darwin
55
+ - os: windows-latest
56
+ target: x86_64-pc-windows-msvc
57
+
58
+ steps:
59
+ - uses: actions/checkout@v5
60
+ - uses: dtolnay/rust-toolchain@stable
61
+ - uses: astral-sh/setup-uv@v6
62
+ - uses: Swatinem/rust-cache@v2
63
+
64
+ - name: Install libclang (Linux)
65
+ if: runner.os == 'Linux'
66
+ run: sudo apt-get update && sudo apt-get install -y clang libclang-dev
67
+
68
+ - name: Point bindgen at LLVM (Windows)
69
+ if: runner.os == 'Windows'
70
+ run: echo "LIBCLANG_PATH=$((gcm clang).source -replace 'clang.exe')" >> $env:GITHUB_ENV
71
+
72
+ - name: Set up build tooling
73
+ shell: bash
74
+ run: |
75
+ uv venv --python 3.12 .build-venv
76
+ uv pip install --python "$(ls .build-venv/bin/python .build-venv/Scripts/python.exe 2>/dev/null | head -1)" \
77
+ 'maturin>=1.14,<2'
78
+
79
+ - name: Resolve build interpreter paths
80
+ shell: bash
81
+ run: |
82
+ if [ -d .build-venv/Scripts ]; then
83
+ echo "BUILD_VENV_BIN=$PWD/.build-venv/Scripts" >> "$GITHUB_ENV"
84
+ else
85
+ echo "BUILD_VENV_BIN=$PWD/.build-venv/bin" >> "$GITHUB_ENV"
86
+ fi
87
+
88
+ - name: Raise the macOS deployment target for the x64 wheel
89
+ if: matrix.target == 'x86_64-apple-darwin'
90
+ run: echo "MACOSX_DEPLOYMENT_TARGET=10.13" >> "$GITHUB_ENV"
91
+ # maturin defaults this target to 10.12, but RocksDB is C++17 and its
92
+ # aligned new/delete needs 10.13 or newer, so the build fails with
93
+ # "aligned deallocation function ... is only available on macOS 10.13
94
+ # or newer". 10.13 is the lowest floor that compiles; verified by
95
+ # cross-building librocksdb-sys for this target. The arm64 wheel is
96
+ # untouched, since that target starts at 11.0 anyway.
97
+
98
+ - name: Build abi3 release wheel
99
+ shell: bash
100
+ run: |
101
+ # abi3-py310 produces one wheel per platform for every supported Python.
102
+ "$BUILD_VENV_BIN/maturin" build \
103
+ --release \
104
+ --target "${{ matrix.target }}" \
105
+ --features pyo3/extension-module,rocksdb \
106
+ --out dist
107
+
108
+ - name: Set up smoke-test virtualenv
109
+ shell: bash
110
+ run: |
111
+ uv venv --python 3.12 .smoke-venv
112
+ if [ -d .smoke-venv/Scripts ]; then
113
+ echo "SMOKE_VENV_BIN=$PWD/.smoke-venv/Scripts" >> "$GITHUB_ENV"
114
+ echo "SMOKE_PY=$PWD/.smoke-venv/Scripts/python.exe" >> "$GITHUB_ENV"
115
+ else
116
+ echo "SMOKE_VENV_BIN=$PWD/.smoke-venv/bin" >> "$GITHUB_ENV"
117
+ echo "SMOKE_PY=$PWD/.smoke-venv/bin/python" >> "$GITHUB_ENV"
118
+ fi
119
+
120
+ - name: Install built wheel
121
+ shell: bash
122
+ run: |
123
+ uv pip install --python "$SMOKE_PY" dist/*.whl \
124
+ pytest pytest-asyncio pytest-timeout
125
+
126
+ - name: Prepare smoke-test tree
127
+ shell: bash
128
+ run: |
129
+ "$SMOKE_PY" - <<'PY'
130
+ from pathlib import Path
131
+ import shutil
132
+
133
+ root = Path.cwd()
134
+ smoke = root / "wheel-smoke"
135
+ if smoke.exists():
136
+ shutil.rmtree(smoke)
137
+ smoke.mkdir()
138
+
139
+ for name in [
140
+ "tests",
141
+ "docs",
142
+ "examples",
143
+ "scripts",
144
+ "python",
145
+ "Cargo.toml",
146
+ "Makefile",
147
+ "README.md",
148
+ "pyproject.toml",
149
+ ]:
150
+ source = root / name
151
+ destination = smoke / name
152
+ if source.is_dir():
153
+ shutil.copytree(
154
+ source,
155
+ destination,
156
+ ignore=shutil.ignore_patterns("__pycache__", ".pytest_cache"),
157
+ )
158
+ elif source.exists():
159
+ shutil.copy2(source, destination)
160
+ PY
161
+
162
+ - name: Smoke-test installed wheel
163
+ shell: bash
164
+ env:
165
+ REPO_ROOT: ${{ github.workspace }}
166
+ run: |
167
+ cd wheel-smoke
168
+ "$SMOKE_PY" - <<'PY'
169
+ from pathlib import Path
170
+ import os
171
+ import drasi
172
+
173
+ module = Path(drasi.__file__).resolve()
174
+ source_trees = [
175
+ (Path(os.environ["REPO_ROOT"]) / "python").resolve(),
176
+ (Path.cwd() / "python").resolve(),
177
+ ]
178
+ if any(module.is_relative_to(source_tree) for source_tree in source_trees):
179
+ raise SystemExit(f"smoke test imported the source tree: {module}")
180
+ print(f"smoke test imported installed wheel: {module}")
181
+ PY
182
+ "$SMOKE_VENV_BIN/pytest" -m "not plugins and not oci and not docker" -v
183
+
184
+ - name: Upload wheel artifact
185
+ uses: actions/upload-artifact@v4
186
+ with:
187
+ name: dist-${{ matrix.target }}
188
+ path: dist/*.whl
189
+ if-no-files-found: error
190
+
191
+ sdist:
192
+ name: Source distribution
193
+ runs-on: ubuntu-22.04
194
+ steps:
195
+ - uses: actions/checkout@v5
196
+ - uses: dtolnay/rust-toolchain@stable
197
+ - uses: astral-sh/setup-uv@v6
198
+
199
+ - name: Set up build tooling
200
+ run: |
201
+ uv venv --python 3.12 .build-venv
202
+ uv pip install --python .build-venv/bin/python 'maturin>=1.14,<2'
203
+
204
+ - name: Build sdist
205
+ run: .build-venv/bin/maturin sdist --out dist
206
+
207
+ - name: Upload sdist artifact
208
+ uses: actions/upload-artifact@v4
209
+ with:
210
+ name: dist-sdist
211
+ path: dist/*.tar.gz
212
+ if-no-files-found: error
213
+
214
+ publish:
215
+ name: Publish to PyPI
216
+ runs-on: ubuntu-24.04
217
+ needs: [wheels, sdist]
218
+ permissions:
219
+ contents: read
220
+ id-token: write
221
+ steps:
222
+ - name: Download distributions
223
+ uses: actions/download-artifact@v5
224
+ with:
225
+ pattern: dist-*
226
+ path: dist
227
+ merge-multiple: true
228
+
229
+ - name: Publish distributions
230
+ uses: pypa/gh-action-pypi-publish@release/v1
231
+ with:
232
+ packages-dir: dist
233
+ attestations: true
@@ -0,0 +1,31 @@
1
+ # Rust
2
+ /target/
3
+
4
+ # Python
5
+ __pycache__/
6
+ *.py[cod]
7
+ .venv/
8
+ venv/
9
+ *.egg-info/
10
+ dist/
11
+ build/
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .mypy_cache/
15
+
16
+ # Native extension built in-place by `maturin develop`
17
+ python/drasi/*.so
18
+ python/drasi/*.pyd
19
+ python/drasi/*.dylib
20
+
21
+ # Test plugin artifacts
22
+ /plugins/
23
+ /.plugin-cache/
24
+
25
+ # Editors / OS
26
+ .DS_Store
27
+ .idea/
28
+ .vscode/
29
+
30
+ # Local bootstrap venv used to obtain uv
31
+ .bootstrap/