rust-py-audit 0.3.0__tar.gz → 0.3.2__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 (47) hide show
  1. rust_py_audit-0.3.2/.github/workflows/release.yml +208 -0
  2. rust_py_audit-0.3.2/CHANGELOG.md +50 -0
  3. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/Cargo.lock +1 -1
  4. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/Cargo.toml +1 -1
  5. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/PKG-INFO +11 -1
  6. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/README.md +10 -0
  7. rust_py_audit-0.3.2/ROADMAP.md +68 -0
  8. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/pyproject.toml +1 -1
  9. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/python/rust_py_audit/__init__.py +1 -1
  10. rust_py_audit-0.3.0/.github/workflows/release.yml +0 -117
  11. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/.gitignore +0 -0
  12. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/LICENSE +0 -0
  13. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/__init__.py +0 -0
  14. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/basic_usage.py +0 -0
  15. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/django_example/__init__.py +0 -0
  16. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/django_example/settings.py +0 -0
  17. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/django_example/urls.py +0 -0
  18. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/django_example/views.py +0 -0
  19. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/fastapi_app.py +0 -0
  20. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/examples/immutablelog_basic.py +0 -0
  21. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/python/rust_py_audit/django.py +0 -0
  22. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/python/rust_py_audit/fastapi.py +0 -0
  23. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/audit_logger.rs +0 -0
  24. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/errors.rs +0 -0
  25. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/event.rs +0 -0
  26. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/hash.rs +0 -0
  27. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/immutablelog_client.rs +0 -0
  28. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/immutablelog_config.rs +0 -0
  29. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/immutablelog_receipt.rs +0 -0
  30. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/lib.rs +0 -0
  31. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/pyconv.rs +0 -0
  32. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/retry.rs +0 -0
  33. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/storage.rs +0 -0
  34. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/src/verifier.rs +0 -0
  35. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/conftest.py +0 -0
  36. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_audit_logger.py +0 -0
  37. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_concurrency.py +0 -0
  38. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_django_immutablelog.py +0 -0
  39. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_django_middleware.py +0 -0
  40. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_fastapi_immutablelog.py +0 -0
  41. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_fastapi_middleware.py +0 -0
  42. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_flush_pending.py +0 -0
  43. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_hello.py +0 -0
  44. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_immutablelog_hybrid.py +0 -0
  45. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_immutablelog_remote.py +0 -0
  46. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_metadata_bigint.py +0 -0
  47. {rust_py_audit-0.3.0 → rust_py_audit-0.3.2}/tests/test_verify.py +0 -0
@@ -0,0 +1,208 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch: {}
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ # Nothing gets built, and nothing reaches PyPI, until this passes. Publishing
14
+ # to PyPI is irreversible: a bad wheel cannot be replaced, only yanked.
15
+ test:
16
+ name: Test (Rust + Python)
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: dtolnay/rust-toolchain@stable
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.12"
24
+
25
+ # --no-default-features drops extension-module, which tells the linker to
26
+ # leave libpython symbols undefined. That is correct for the wheel but
27
+ # produces a test binary that cannot link on Linux.
28
+ - name: Rust unit tests
29
+ env:
30
+ PYO3_PYTHON: python
31
+ run: cargo test --no-default-features --lib
32
+
33
+ - name: Build, install the extension and run the Python tests
34
+ # `pip install` drives the maturin build backend, so it compiles the
35
+ # Rust extension and installs it (plus the dev extras) into the
36
+ # runner's Python — no virtualenv needed, unlike `maturin develop`,
37
+ # which aborts when it cannot find one.
38
+ run: |
39
+ python -m pip install --upgrade pip
40
+ python -m pip install ".[dev]"
41
+ python -m pytest
42
+
43
+ linux:
44
+ runs-on: ubuntu-latest
45
+ needs: test
46
+ strategy:
47
+ matrix:
48
+ target: [x86_64, aarch64]
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - uses: PyO3/maturin-action@v1
52
+ env:
53
+ # `ring` (puxado por `rustls`, via `reqwest`) falha ao cross-compilar
54
+ # sua assembly pregenerada para aarch64 dentro do container manylinux
55
+ # do maturin-action: o cross-gcc não define `__ARM_ARCH` por padrão
56
+ # nesse ambiente, e o preprocessor de `ring` exige essa macro
57
+ # (erro: "ARM assembler must define __ARM_ARCH"). Forçar a macro via
58
+ # CFLAGS é o workaround padrão para esse problema conhecido — não
59
+ # afeta o build x86_64 (a env var é específica do target aarch64).
60
+ CFLAGS_aarch64_unknown_linux_gnu: -D__ARM_ARCH=8
61
+ with:
62
+ target: ${{ matrix.target }}
63
+ args: --release --out dist --find-interpreter
64
+ manylinux: auto
65
+ - uses: actions/upload-artifact@v4
66
+ with:
67
+ name: wheels-linux-${{ matrix.target }}
68
+ path: dist
69
+
70
+ musllinux:
71
+ runs-on: ubuntu-latest
72
+ needs: test
73
+ strategy:
74
+ matrix:
75
+ target: [x86_64, aarch64]
76
+ steps:
77
+ - uses: actions/checkout@v4
78
+ - uses: PyO3/maturin-action@v1
79
+ with:
80
+ target: ${{ matrix.target }}
81
+ args: --release --out dist --find-interpreter
82
+ manylinux: musllinux_1_2
83
+ - uses: actions/upload-artifact@v4
84
+ with:
85
+ name: wheels-musllinux-${{ matrix.target }}
86
+ path: dist
87
+
88
+ windows:
89
+ runs-on: windows-latest
90
+ needs: test
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+ - uses: actions/setup-python@v5
94
+ with:
95
+ architecture: x64
96
+ - uses: PyO3/maturin-action@v1
97
+ with:
98
+ target: x64
99
+ args: --release --out dist --find-interpreter
100
+ - uses: actions/upload-artifact@v4
101
+ with:
102
+ name: wheels-windows-x64
103
+ path: dist
104
+
105
+ macos:
106
+ runs-on: macos-latest
107
+ needs: test
108
+ strategy:
109
+ matrix:
110
+ target: [x86_64, aarch64]
111
+ steps:
112
+ - uses: actions/checkout@v4
113
+ - uses: PyO3/maturin-action@v1
114
+ with:
115
+ target: ${{ matrix.target }}
116
+ args: --release --out dist --find-interpreter
117
+ - uses: actions/upload-artifact@v4
118
+ with:
119
+ name: wheels-macos-${{ matrix.target }}
120
+ path: dist
121
+
122
+ sdist:
123
+ runs-on: ubuntu-latest
124
+ needs: test
125
+ steps:
126
+ - uses: actions/checkout@v4
127
+ - uses: PyO3/maturin-action@v1
128
+ with:
129
+ command: sdist
130
+ args: --out dist
131
+ - uses: actions/upload-artifact@v4
132
+ with:
133
+ name: wheels-sdist
134
+ path: dist
135
+
136
+ release:
137
+ name: Publish to PyPI
138
+ runs-on: ubuntu-latest
139
+ needs: [test, linux, musllinux, windows, macos, sdist]
140
+ steps:
141
+ - uses: actions/download-artifact@v4
142
+ with:
143
+ pattern: wheels-*
144
+ path: dist
145
+ merge-multiple: true
146
+ - uses: actions/setup-python@v5
147
+ with:
148
+ python-version: "3.12"
149
+ - name: Install maturin
150
+ run: python -m pip install --upgrade maturin requests
151
+
152
+ # A sanity check before anything leaves the runner: publishing an
153
+ # incomplete set is worse than not publishing, because PyPI never lets a
154
+ # filename be reused — a half-uploaded version can only be completed,
155
+ # never replaced.
156
+ - name: Verify the artifact set is complete
157
+ run: |
158
+ set -euo pipefail
159
+ ls -la dist/
160
+ test -n "$(find dist -name '*.tar.gz' -print -quit)" \
161
+ || { echo "::error::sdist ausente — abortando antes de publicar"; exit 1; }
162
+ wheels=$(find dist -name '*.whl' | wc -l)
163
+ echo "wheels: $wheels"
164
+ test "$wheels" -ge 7 \
165
+ || { echo "::error::só $wheels wheels; esperado >= 7 (2 linux, 2 musl, 1 win, 2 macos)"; exit 1; }
166
+
167
+ # PyPI returns a transient 500 often enough to matter, and the upload is
168
+ # file-by-file: a failure halfway leaves the version published in part.
169
+ # --skip-existing makes the retry idempotent (already-uploaded files are
170
+ # skipped by name), so a second attempt finishes the job instead of
171
+ # failing on the files that did make it.
172
+ - name: Publish to PyPI (with retry)
173
+ uses: nick-fields/retry@v3
174
+ env:
175
+ MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
176
+ with:
177
+ timeout_minutes: 15
178
+ max_attempts: 4
179
+ retry_wait_seconds: 45
180
+ command: maturin upload --non-interactive --skip-existing dist/*
181
+
182
+ # Proves the release is actually complete, rather than trusting an exit
183
+ # code that a partial upload can still produce.
184
+ - name: Verify every file reached PyPI
185
+ run: |
186
+ set -euo pipefail
187
+ python - <<'PY'
188
+ import os, sys, glob, time, requests
189
+ version = os.environ["GITHUB_REF_NAME"].lstrip("v")
190
+ local = {os.path.basename(p) for p in glob.glob("dist/*")}
191
+ url = f"https://pypi.org/pypi/rust-py-audit/{version}/json"
192
+ for attempt in range(6): # PyPI's JSON API is cached
193
+ response = requests.get(url, timeout=30)
194
+ if response.status_code == 200:
195
+ remote = {f["filename"] for f in response.json()["urls"]}
196
+ missing = local - remote
197
+ if not missing:
198
+ print(f"OK: {len(remote)} arquivos publicados na {version}")
199
+ sys.exit(0)
200
+ else:
201
+ missing = local
202
+ print(f"tentativa {attempt + 1}: faltam {len(missing)}")
203
+ time.sleep(20)
204
+ print("::error::faltaram arquivos no PyPI:")
205
+ for name in sorted(missing):
206
+ print(f" - {name}")
207
+ sys.exit(1)
208
+ PY
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+
3
+ Todas as mudanças relevantes deste projeto são registradas aqui.
4
+
5
+ O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/),
6
+ e o versionamento segue [SemVer](https://semver.org/lang/pt-BR/).
7
+
8
+ ## [0.3.2] - 2026-08-11
9
+
10
+ Release de infraestrutura: nada muda no comportamento da biblioteca.
11
+
12
+ ### Corrigido
13
+
14
+ - **A publicação não roda mais sem teste.** O `release.yml` era o único
15
+ workflow do repositório e só tinha jobs de build: `git push --tags`
16
+ publicava no PyPI sem nenhum `cargo test` nem `pytest`. Agora existe um job
17
+ `test` e todos os jobs de wheel, o de sdist e o de release declaram
18
+ `needs: test`. (BACKLOG2 P1-1)
19
+ - **O upload aguenta o 500 do PyPI.** O upload é arquivo por arquivo e sem
20
+ transação — uma falha no meio deixa a versão publicada pela metade, e o PyPI
21
+ nunca permite reusar um nome de arquivo. O passo de publicação agora tem
22
+ retry (4 tentativas), continua usando `--skip-existing` para ser idempotente,
23
+ confere o conjunto de artefatos **antes** de subir qualquer coisa (aborta se
24
+ faltar o sdist) e valida contra a API do PyPI **depois**, listando nome por
25
+ nome o que não chegou. (BACKLOG2 P1-9)
26
+
27
+ ### Adicionado
28
+
29
+ - Este `CHANGELOG.md`. (BACKLOG2 P1-5)
30
+
31
+ ## [0.3.1] e anteriores
32
+
33
+ Sem changelog retroativo. O histórico do que entrou em cada versão está no
34
+ `ROADMAP.md`, e o das mudanças no `git log`.
35
+
36
+ Resumo do que o projeto entrega hoje:
37
+
38
+ - `AuditLogger` com log append-only em JSONL e cadeia de hashes encadeada.
39
+ - `verify()` para detectar adulteração da cadeia.
40
+ - Integração com o ImmutableLog nos modos remoto e híbrido.
41
+ - Middlewares para FastAPI e Django.
42
+ - Wheels `abi3-py310` — uma wheel por plataforma, válida da 3.10 em diante.
43
+
44
+ ### Limitação conhecida (não corrigida nesta versão)
45
+
46
+ ⚠️ **Múltiplos processos escrevendo no mesmo arquivo quebram a cadeia.** Cada
47
+ processo mantém seu próprio `last_hash` em memória e não há `flock` no append,
48
+ então dois workers gunicorn apontando para o mesmo JSONL produzem uma cadeia
49
+ inconsistente — e `verify()` acusa corrupção. O modo de falha é silencioso até
50
+ alguém rodar `verify()`. Ver **P2-4** no `BACKLOG2.md`.
@@ -1597,7 +1597,7 @@ dependencies = [
1597
1597
 
1598
1598
  [[package]]
1599
1599
  name = "rust_py_audit"
1600
- version = "0.3.0"
1600
+ version = "0.3.2"
1601
1601
  dependencies = [
1602
1602
  "httpmock",
1603
1603
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rust_py_audit"
3
- version = "0.3.0"
3
+ version = "0.3.2"
4
4
  edition = "2021"
5
5
  description = "Auditoria de eventos com cadeia de hashes (SHA-256) para apps Python, core em Rust via PyO3."
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rust-py-audit
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -409,6 +409,16 @@ For each queued event:
409
409
 
410
410
  ---
411
411
 
412
+ ## Roadmap
413
+
414
+ `rust-py-audit` is mature (v0.3.0): the SHA-256 hash chain, JSONL storage,
415
+ FastAPI/Django middlewares, and the ImmutableLog `local`/`remote`/`hybrid`
416
+ integration are shipped and stable. Directional ideas under consideration (log
417
+ rotation, incremental verification, more delivery backends, an async client, a
418
+ Flask middleware) are tracked in [ROADMAP.md](./ROADMAP.md).
419
+
420
+ ---
421
+
412
422
  ## Building from Source
413
423
 
414
424
  Requires Rust and [maturin](https://github.com/PyO3/maturin).
@@ -372,6 +372,16 @@ For each queued event:
372
372
 
373
373
  ---
374
374
 
375
+ ## Roadmap
376
+
377
+ `rust-py-audit` is mature (v0.3.0): the SHA-256 hash chain, JSONL storage,
378
+ FastAPI/Django middlewares, and the ImmutableLog `local`/`remote`/`hybrid`
379
+ integration are shipped and stable. Directional ideas under consideration (log
380
+ rotation, incremental verification, more delivery backends, an async client, a
381
+ Flask middleware) are tracked in [ROADMAP.md](./ROADMAP.md).
382
+
383
+ ---
384
+
375
385
  ## Building from Source
376
386
 
377
387
  Requires Rust and [maturin](https://github.com/PyO3/maturin).
@@ -0,0 +1,68 @@
1
+ # Roadmap — rust-py-audit
2
+
3
+ Direction for `rust-py-audit`: a tamper-evident audit log for Python with a Rust
4
+ core (PyO3 + maturin). The library is already mature (v0.3.0) — the SHA-256 hash
5
+ chain, JSONL storage, FastAPI/Django middlewares, and the ImmutableLog
6
+ `local`/`remote`/`hybrid` integration are shipped and stable. This document tracks
7
+ what is done and the **directional** ideas under consideration.
8
+
9
+ > Status legend: ✅ shipped · 🔜 planned (next) · 💡 idea (no version yet) · ⚠️ note
10
+
11
+ > ⚠️ Beyond "shipped", items below are **inferred directions, not commitments**.
12
+ > Confirm priorities with the maintainer before planning a release around them.
13
+
14
+ ---
15
+
16
+ ## Shipped — up to v0.3.0
17
+
18
+ - ✅ `AuditLogger` with `log(...)`, `verify()`, `last_hash()`.
19
+ - ✅ **SHA-256 hash chain** — each event embeds the previous event's hash; any
20
+ edit, deletion, or reordering is detected by `verify()` (re-read from disk,
21
+ never trusts an in-memory cache).
22
+ - ✅ Append-only **JSONL** storage — one event per line, no database.
23
+ - ✅ Thread-safe — the chain stays linear under concurrency.
24
+ - ✅ Free-form JSON-serializable `metadata`.
25
+ - ✅ FastAPI and Django middlewares (log state-changing requests:
26
+ POST/PUT/PATCH/DELETE).
27
+ - ✅ **ImmutableLog integration** — `local`/`remote`/`hybrid` modes, automatic
28
+ retry with idempotency key, pending queue (`audit.pending.jsonl`),
29
+ `flush_pending()`, and transient (`pending`) vs permanent (`failed`) failure
30
+ handling that never takes down the application response.
31
+ - ✅ `severity`, `immutable_trail`, and `env` delivery metadata (never enter the
32
+ hash, so `verify()` stays valid after `flush_pending()`).
33
+ - ✅ ImmutableLog HTTP client runs in the Rust core (PyO3 + reqwest).
34
+
35
+ ---
36
+
37
+ ## Directional ideas (no version assigned — confirm before planning)
38
+
39
+ - 💡 **Log rotation / segmentation** — roll the JSONL by size or date while
40
+ preserving chain continuity across segments (carry the last hash forward).
41
+ - 💡 **Incremental verification** — verify only events appended since the last
42
+ known-good hash, instead of re-reading the whole file every time.
43
+ - 💡 **More delivery backends** — additional sinks alongside ImmutableLog (e.g.
44
+ S3/object storage, syslog, a generic webhook), reusing the retry/pending logic.
45
+ - 💡 **Async client** — non-blocking delivery path for high-throughput async apps.
46
+ - 💡 **Flask middleware** — parity with the FastAPI/Django adapters.
47
+ - 💡 **Query/read helpers** — iterate or filter recorded events (by actor, action,
48
+ resource, time range) without hand-parsing the JSONL.
49
+ - 💡 **Benchmarks suite** — hashing + append throughput under concurrency.
50
+
51
+ ---
52
+
53
+ ## Known limitations (by design, for now)
54
+
55
+ - Local JSONL is single-file and append-only (no built-in rotation yet).
56
+ - `verify()` re-reads the entire file (O(n)); fine for typical logs, see the
57
+ incremental-verification idea above for very large files.
58
+ - ImmutableLog delivery is synchronous on the `log()` path (bounded by
59
+ `timeout_ms` + retries); `hybrid` mode never raises, queuing transient failures.
60
+
61
+ ---
62
+
63
+ ## Contributing to the roadmap
64
+
65
+ Versions and ordering are indicative and may shift. Bump the version in **both**
66
+ `Cargo.toml` and `pyproject.toml` (kept in sync) plus `__version__`, ship tests
67
+ (`cargo test --no-default-features` + `pytest`), then tag `vX.Y.Z` to trigger the
68
+ release workflow (Trusted Publishing / OIDC to PyPI).
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "rust-py-audit"
7
- version = "0.3.0"
7
+ version = "0.3.2"
8
8
  description = "Fast, tamper-evident event auditing (hash chain) for Python apps, with a Rust core."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -8,5 +8,5 @@ que existe um módulo nativo por trás.
8
8
 
9
9
  from ._rust_py_audit import AuditLogger, hello
10
10
 
11
- __version__ = "0.3.0"
11
+ __version__ = "0.3.2"
12
12
  __all__ = ["AuditLogger", "hello"]
@@ -1,117 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- push:
5
- tags:
6
- - "v*"
7
- workflow_dispatch: {}
8
-
9
- permissions:
10
- contents: read
11
-
12
- jobs:
13
- linux:
14
- runs-on: ubuntu-latest
15
- strategy:
16
- matrix:
17
- target: [x86_64, aarch64]
18
- steps:
19
- - uses: actions/checkout@v4
20
- - uses: PyO3/maturin-action@v1
21
- env:
22
- # `ring` (puxado por `rustls`, via `reqwest`) falha ao cross-compilar
23
- # sua assembly pregenerada para aarch64 dentro do container manylinux
24
- # do maturin-action: o cross-gcc não define `__ARM_ARCH` por padrão
25
- # nesse ambiente, e o preprocessor de `ring` exige essa macro
26
- # (erro: "ARM assembler must define __ARM_ARCH"). Forçar a macro via
27
- # CFLAGS é o workaround padrão para esse problema conhecido — não
28
- # afeta o build x86_64 (a env var é específica do target aarch64).
29
- CFLAGS_aarch64_unknown_linux_gnu: -D__ARM_ARCH=8
30
- with:
31
- target: ${{ matrix.target }}
32
- args: --release --out dist --find-interpreter
33
- manylinux: auto
34
- - uses: actions/upload-artifact@v4
35
- with:
36
- name: wheels-linux-${{ matrix.target }}
37
- path: dist
38
-
39
- musllinux:
40
- runs-on: ubuntu-latest
41
- strategy:
42
- matrix:
43
- target: [x86_64, aarch64]
44
- steps:
45
- - uses: actions/checkout@v4
46
- - uses: PyO3/maturin-action@v1
47
- with:
48
- target: ${{ matrix.target }}
49
- args: --release --out dist --find-interpreter
50
- manylinux: musllinux_1_2
51
- - uses: actions/upload-artifact@v4
52
- with:
53
- name: wheels-musllinux-${{ matrix.target }}
54
- path: dist
55
-
56
- windows:
57
- runs-on: windows-latest
58
- steps:
59
- - uses: actions/checkout@v4
60
- - uses: actions/setup-python@v5
61
- with:
62
- architecture: x64
63
- - uses: PyO3/maturin-action@v1
64
- with:
65
- target: x64
66
- args: --release --out dist --find-interpreter
67
- - uses: actions/upload-artifact@v4
68
- with:
69
- name: wheels-windows-x64
70
- path: dist
71
-
72
- macos:
73
- runs-on: macos-latest
74
- strategy:
75
- matrix:
76
- target: [x86_64, aarch64]
77
- steps:
78
- - uses: actions/checkout@v4
79
- - uses: PyO3/maturin-action@v1
80
- with:
81
- target: ${{ matrix.target }}
82
- args: --release --out dist --find-interpreter
83
- - uses: actions/upload-artifact@v4
84
- with:
85
- name: wheels-macos-${{ matrix.target }}
86
- path: dist
87
-
88
- sdist:
89
- runs-on: ubuntu-latest
90
- steps:
91
- - uses: actions/checkout@v4
92
- - uses: PyO3/maturin-action@v1
93
- with:
94
- command: sdist
95
- args: --out dist
96
- - uses: actions/upload-artifact@v4
97
- with:
98
- name: wheels-sdist
99
- path: dist
100
-
101
- release:
102
- name: Publish to PyPI
103
- runs-on: ubuntu-latest
104
- needs: [linux, musllinux, windows, macos, sdist]
105
- steps:
106
- - uses: actions/download-artifact@v4
107
- with:
108
- pattern: wheels-*
109
- path: dist
110
- merge-multiple: true
111
- - name: Publish to PyPI
112
- uses: PyO3/maturin-action@v1
113
- env:
114
- MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
115
- with:
116
- command: upload
117
- args: --non-interactive --skip-existing dist/*
File without changes
File without changes
File without changes
File without changes