millwright 2.2.0__tar.gz → 2.3.1__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 (121) hide show
  1. millwright-2.3.1/.github/SECURITY.md +27 -0
  2. millwright-2.3.1/.github/dependabot.yml +59 -0
  3. millwright-2.3.1/.github/workflows/ci.yml +367 -0
  4. millwright-2.3.1/.github/workflows/codeql.yml +40 -0
  5. millwright-2.3.1/.github/workflows/release.yml +383 -0
  6. {millwright-2.2.0 → millwright-2.3.1}/.gitignore +4 -0
  7. millwright-2.3.1/CHANGELOG.md +301 -0
  8. {millwright-2.2.0 → millwright-2.3.1}/CONTRIBUTING.md +4 -1
  9. {millwright-2.2.0 → millwright-2.3.1}/Cargo.lock +881 -28
  10. {millwright-2.2.0 → millwright-2.3.1}/Cargo.toml +77 -2
  11. {millwright-2.2.0 → millwright-2.3.1}/GUIDE.md +1 -1
  12. {millwright-2.2.0 → millwright-2.3.1}/PKG-INFO +43 -6
  13. {millwright-2.2.0 → millwright-2.3.1}/README.md +42 -5
  14. millwright-2.3.1/RELEASING.md +132 -0
  15. millwright-2.3.1/benches/gpu_compute.rs +74 -0
  16. millwright-2.3.1/benches/gpu_inference.rs +62 -0
  17. millwright-2.3.1/deny.toml +34 -0
  18. {millwright-2.2.0 → millwright-2.3.1}/docs/deploy.html +24 -2
  19. {millwright-2.2.0 → millwright-2.3.1}/docs/index.html +6 -4
  20. {millwright-2.2.0 → millwright-2.3.1}/docs/insight.html +2 -1
  21. {millwright-2.2.0 → millwright-2.3.1}/docs/python.html +32 -1
  22. {millwright-2.2.0 → millwright-2.3.1}/examples/automl.rs +1 -1
  23. millwright-2.3.1/examples/gpu.rs +78 -0
  24. millwright-2.3.1/examples/gpu_compute.rs +59 -0
  25. {millwright-2.2.0 → millwright-2.3.1}/examples/portability.rs +2 -2
  26. {millwright-2.2.0 → millwright-2.3.1}/examples/workflow.rs +3 -3
  27. {millwright-2.2.0 → millwright-2.3.1}/guide.html +3 -3
  28. {millwright-2.2.0 → millwright-2.3.1}/index.html +12 -10
  29. millwright-2.3.1/millwright.pyi +179 -0
  30. {millwright-2.2.0 → millwright-2.3.1}/pyproject.toml +6 -1
  31. millwright-2.3.1/requirements/ci-python.txt +3 -0
  32. millwright-2.3.1/requirements/onnx-check.txt +1 -0
  33. millwright-2.3.1/requirements/test-python.txt +1 -0
  34. millwright-2.3.1/scripts/check-branch-coverage.py +26 -0
  35. millwright-2.3.1/scripts/check-lcov-coverage.py +45 -0
  36. millwright-2.3.1/scripts/release.ps1 +64 -0
  37. {millwright-2.2.0 → millwright-2.3.1}/scripts/release.sh +16 -7
  38. millwright-2.3.1/scripts/sync-version.py +81 -0
  39. {millwright-2.2.0 → millwright-2.3.1}/src/anomaly.rs +108 -5
  40. millwright-2.3.1/src/automl.rs +889 -0
  41. millwright-2.3.1/src/automl_tests.rs +254 -0
  42. {millwright-2.2.0 → millwright-2.3.1}/src/backends/smartcore.rs +92 -46
  43. {millwright-2.2.0 → millwright-2.3.1}/src/ensemble.rs +291 -122
  44. millwright-2.3.1/src/ensemble_tests.rs +235 -0
  45. {millwright-2.2.0 → millwright-2.3.1}/src/evaluate.rs +37 -25
  46. millwright-2.3.1/src/gpu.rs +298 -0
  47. {millwright-2.2.0 → millwright-2.3.1}/src/lib.rs +11 -2
  48. {millwright-2.2.0 → millwright-2.3.1}/src/logistic.rs +152 -4
  49. millwright-2.3.1/src/onnx.rs +1232 -0
  50. millwright-2.3.1/src/onnx_native.rs +978 -0
  51. millwright-2.3.1/src/onnx_tests.rs +161 -0
  52. {millwright-2.2.0 → millwright-2.3.1}/src/pipeline.rs +41 -1
  53. {millwright-2.2.0 → millwright-2.3.1}/src/profile.rs +120 -523
  54. millwright-2.3.1/src/profile_alerts.rs +121 -0
  55. millwright-2.3.1/src/profile_render.rs +197 -0
  56. millwright-2.3.1/src/profile_tests.rs +156 -0
  57. {millwright-2.2.0 → millwright-2.3.1}/src/python.rs +562 -401
  58. millwright-2.3.1/src/python_data.rs +163 -0
  59. millwright-2.3.1/src/python_estimators.rs +310 -0
  60. {millwright-2.2.0 → millwright-2.3.1}/src/serve.rs +10 -0
  61. {millwright-2.2.0 → millwright-2.3.1}/src/table.rs +10 -2
  62. {millwright-2.2.0 → millwright-2.3.1}/src/traits.rs +25 -0
  63. millwright-2.3.1/src/transform.rs +468 -0
  64. millwright-2.3.1/src/transform_advanced.rs +437 -0
  65. millwright-2.3.1/src/transform_tests.rs +196 -0
  66. {millwright-2.2.0 → millwright-2.3.1}/tests/ensemble_zoo.rs +1 -2
  67. {millwright-2.2.0 → millwright-2.3.1}/tests/golden.rs +2 -2
  68. millwright-2.3.1/tests/gpu_compute.rs +161 -0
  69. millwright-2.3.1/tests/gpu_inference.rs +271 -0
  70. {millwright-2.2.0 → millwright-2.3.1}/tests/onnx_export.rs +121 -0
  71. millwright-2.3.1/tests/property_inputs.rs +66 -0
  72. millwright-2.3.1/tests/python/compat_smoke.py +14 -0
  73. millwright-2.3.1/tests/python/conftest.py +21 -0
  74. millwright-2.3.1/tests/python/test_ensembles_and_automl.py +153 -0
  75. millwright-2.3.1/tests/python/test_frame_and_profile.py +42 -0
  76. millwright-2.3.1/tests/python/test_pipeline.py +46 -0
  77. millwright-2.3.1/tests/python/test_search_and_portability.py +53 -0
  78. millwright-2.3.1/tests/python/typing_contract.py +15 -0
  79. millwright-2.2.0/.github/workflows/ci.yml +0 -195
  80. millwright-2.2.0/.github/workflows/release-crate.yml +0 -50
  81. millwright-2.2.0/.github/workflows/release-python.yml +0 -133
  82. millwright-2.2.0/CHANGELOG.md +0 -145
  83. millwright-2.2.0/RELEASING.md +0 -94
  84. millwright-2.2.0/src/automl.rs +0 -574
  85. millwright-2.2.0/src/onnx.rs +0 -1075
  86. millwright-2.2.0/src/transform.rs +0 -1096
  87. millwright-2.2.0/tests/python_smoke.py +0 -29
  88. {millwright-2.2.0 → millwright-2.3.1}/.cargo/audit.toml +0 -0
  89. {millwright-2.2.0 → millwright-2.3.1}/CNAME +0 -0
  90. {millwright-2.2.0 → millwright-2.3.1}/LICENSE +0 -0
  91. {millwright-2.2.0 → millwright-2.3.1}/benches/throughput.rs +0 -0
  92. {millwright-2.2.0 → millwright-2.3.1}/docs/data.html +0 -0
  93. {millwright-2.2.0 → millwright-2.3.1}/docs/pipelines.html +0 -0
  94. {millwright-2.2.0 → millwright-2.3.1}/docs/site.css +0 -0
  95. {millwright-2.2.0 → millwright-2.3.1}/examples/backends.rs +0 -0
  96. {millwright-2.2.0 → millwright-2.3.1}/examples/explore.rs +0 -0
  97. {millwright-2.2.0 → millwright-2.3.1}/examples/insight.rs +0 -0
  98. {millwright-2.2.0 → millwright-2.3.1}/examples/operations.rs +0 -0
  99. {millwright-2.2.0 → millwright-2.3.1}/examples/specialized.rs +0 -0
  100. {millwright-2.2.0 → millwright-2.3.1}/examples/spine.rs +0 -0
  101. {millwright-2.2.0 → millwright-2.3.1}/examples/trust.rs +0 -0
  102. {millwright-2.2.0 → millwright-2.3.1}/src/backends/chronos.rs +0 -0
  103. {millwright-2.2.0 → millwright-2.3.1}/src/backends/incremental.rs +0 -0
  104. {millwright-2.2.0 → millwright-2.3.1}/src/backends/linfa.rs +0 -0
  105. {millwright-2.2.0 → millwright-2.3.1}/src/backends/mod.rs +0 -0
  106. {millwright-2.2.0 → millwright-2.3.1}/src/balance.rs +0 -0
  107. {millwright-2.2.0 → millwright-2.3.1}/src/calibration.rs +0 -0
  108. {millwright-2.2.0 → millwright-2.3.1}/src/diagnostics.rs +0 -0
  109. {millwright-2.2.0 → millwright-2.3.1}/src/error.rs +0 -0
  110. {millwright-2.2.0 → millwright-2.3.1}/src/explain.rs +0 -0
  111. {millwright-2.2.0 → millwright-2.3.1}/src/frame.rs +0 -0
  112. {millwright-2.2.0 → millwright-2.3.1}/src/monitor.rs +0 -0
  113. {millwright-2.2.0 → millwright-2.3.1}/src/registry.rs +0 -0
  114. {millwright-2.2.0 → millwright-2.3.1}/src/rng.rs +0 -0
  115. {millwright-2.2.0 → millwright-2.3.1}/src/selection/cv.rs +0 -0
  116. {millwright-2.2.0 → millwright-2.3.1}/src/selection/mod.rs +0 -0
  117. {millwright-2.2.0 → millwright-2.3.1}/src/selection/scoring.rs +0 -0
  118. {millwright-2.2.0 → millwright-2.3.1}/src/selection/search.rs +0 -0
  119. {millwright-2.2.0 → millwright-2.3.1}/src/viz.rs +0 -0
  120. {millwright-2.2.0 → millwright-2.3.1}/tests/hero_snippet.rs +0 -0
  121. {millwright-2.2.0 → millwright-2.3.1}/tests/real_data.rs +0 -0
@@ -0,0 +1,27 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes are provided for the latest published Millwright release. Users
6
+ should upgrade to the newest version available on crates.io or PyPI before
7
+ reporting an issue that may already have been corrected.
8
+
9
+ ## Reporting a vulnerability
10
+
11
+ Please do not open a public issue for a suspected vulnerability. Use
12
+ [GitHub private vulnerability reporting](https://github.com/mi7plus/millwright/security/advisories/new)
13
+ to share the affected version, impact, reproduction steps, and any suggested
14
+ mitigation privately with the maintainers.
15
+
16
+ You should receive an acknowledgement within seven days. The maintainers will
17
+ then validate the report, coordinate a fix and release where necessary, and
18
+ agree on disclosure timing with the reporter. Please allow a reasonable
19
+ remediation window before publishing details.
20
+
21
+ ## Scope
22
+
23
+ Reports about the Rust crate, Python wheels, serialization and ONNX handling,
24
+ model registry, inference server, release artifacts, or build and publishing
25
+ pipeline are in scope. Vulnerabilities in an upstream dependency should also be
26
+ reported upstream when appropriate; please still notify Millwright privately if
27
+ the dependency creates a practical risk for Millwright users.
@@ -0,0 +1,59 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: cargo
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 5
8
+ groups:
9
+ rust-infrastructure:
10
+ patterns: ["*"]
11
+ exclude-patterns:
12
+ # These crates form type/serialization boundaries with the exact-pinned
13
+ # ML engines. Upgrade them deliberately, with the full feature matrix.
14
+ - "ndarray"
15
+ - "prost"
16
+ - "sha2"
17
+ - "criterion"
18
+ ignore:
19
+ # Engine versions are exact by design. Dependabot PRs cannot safely infer
20
+ # coordinated upgrades across their ndarray and ONNX type boundaries.
21
+ - dependency-name: "ndarray"
22
+ - dependency-name: "prost"
23
+ - dependency-name: "sha2"
24
+ - dependency-name: "criterion"
25
+ - dependency-name: "smartcore"
26
+ - dependency-name: "imbalance-rs"
27
+ - dependency-name: "model-selection-rs"
28
+ - dependency-name: "linfa*"
29
+ - dependency-name: "hyperopt-rs"
30
+ - dependency-name: "regression-diagnostics"
31
+ - dependency-name: "shap-rs"
32
+ - dependency-name: "plotters-statistical"
33
+ - dependency-name: "onnx-export-rs"
34
+ - dependency-name: "driftwatch"
35
+ - dependency-name: "chronos-ts"
36
+ - dependency-name: "incremental-rs"
37
+ - dependency-name: "polars"
38
+ labels: ["dependencies", "rust"]
39
+
40
+ - package-ecosystem: github-actions
41
+ directory: /
42
+ schedule:
43
+ interval: weekly
44
+ groups:
45
+ actions:
46
+ patterns: ["*"]
47
+ exclude-patterns: ["dtolnay/rust-toolchain"]
48
+ ignore:
49
+ # @1.95 is a Rust toolchain selector, not an action release. It is also
50
+ # expressed as an input in CI, but keep this guard against regressions.
51
+ - dependency-name: "dtolnay/rust-toolchain"
52
+ labels: ["dependencies", "github-actions"]
53
+
54
+ - package-ecosystem: pip
55
+ directory: /
56
+ schedule:
57
+ interval: weekly
58
+ open-pull-requests-limit: 3
59
+ labels: ["dependencies", "python"]
@@ -0,0 +1,367 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ # One in-flight run per ref; a new push cancels the previous.
13
+ concurrency:
14
+ group: ci-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ env:
18
+ CARGO_TERM_COLOR: always
19
+ # Every job builds against the committed Cargo.lock. `--locked` turns a stale
20
+ # or drifted lockfile into a hard error — the reproducibility guarantee that
21
+ # pairs with the exact-version engine pins in Cargo.toml.
22
+ CARGO_NET_RETRY: "3"
23
+ RUSTFLAGS: "-D warnings"
24
+
25
+ jobs:
26
+ consistency:
27
+ name: version & links
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
31
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
32
+ with:
33
+ python-version: "3.x"
34
+ - name: verify every public version marker
35
+ run: python scripts/sync-version.py --check
36
+ - name: check local and external HTML links
37
+ uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2
38
+ with:
39
+ args: >-
40
+ --no-progress
41
+ --accept 200,204,206,429
42
+ --retry-wait-time 2
43
+ index.html guide.html docs/*.html README.md CONTRIBUTING.md RELEASING.md
44
+ .github/SECURITY.md
45
+ fail: true
46
+
47
+ fmt:
48
+ name: rustfmt
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
52
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
53
+ with:
54
+ components: rustfmt
55
+ - run: cargo fmt --all --check
56
+
57
+ clippy:
58
+ name: clippy (${{ matrix.features }})
59
+ runs-on: ubuntu-latest
60
+ strategy:
61
+ fail-fast: false
62
+ matrix:
63
+ include:
64
+ - features: "--no-default-features"
65
+ - features: "" # default features
66
+ - features: "--features full"
67
+ steps:
68
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
69
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
70
+ with:
71
+ components: clippy
72
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
73
+ - run: cargo clippy --locked --all-targets ${{ matrix.features }}
74
+
75
+ docs:
76
+ name: doc
77
+ runs-on: ubuntu-latest
78
+ env:
79
+ RUSTDOCFLAGS: "-D warnings"
80
+ steps:
81
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
82
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
83
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
84
+ # `full` is every Rust-facing feature (python is a cdylib, doc'd separately
85
+ # by maturin/pyo3), so this exercises the whole documented surface.
86
+ - run: cargo doc --locked --no-deps --features full
87
+
88
+ test:
89
+ name: test (${{ matrix.name }})
90
+ runs-on: ubuntu-latest
91
+ strategy:
92
+ fail-fast: false
93
+ matrix:
94
+ include:
95
+ # The spine, minimal: no backend at all, then the smartcore spine.
96
+ - { name: "core-only", features: "--no-default-features" }
97
+ - { name: "spine", features: "--no-default-features --features smartcore-backend" }
98
+ # The default install.
99
+ - { name: "default", features: "" }
100
+ # Each feature in isolation. Dependencies declared by that feature are
101
+ # enabled transitively; unrelated defaults cannot hide a bad edge.
102
+ - { name: "eda", features: "--no-default-features --features eda" }
103
+ - { name: "calibration", features: "--no-default-features --features calibration" }
104
+ - { name: "anomaly", features: "--no-default-features --features anomaly" }
105
+ - { name: "linfa", features: "--no-default-features --features linfa-backend" }
106
+ - { name: "hpo", features: "--no-default-features --features hpo" }
107
+ - { name: "diagnostics", features: "--no-default-features --features diagnostics" }
108
+ - { name: "explain", features: "--no-default-features --features explain" }
109
+ - { name: "viz", features: "--no-default-features --features viz" }
110
+ - { name: "onnx", features: "--no-default-features --features onnx" }
111
+ - { name: "registry", features: "--no-default-features --features registry" }
112
+ - { name: "monitor", features: "--no-default-features --features monitor" }
113
+ - { name: "serve", features: "--no-default-features --features serve" }
114
+ - { name: "timeseries", features: "--no-default-features --features timeseries" }
115
+ - { name: "incremental", features: "--no-default-features --features incremental" }
116
+ - { name: "automl", features: "--no-default-features --features automl" }
117
+ # Everything at once — the superset build, including both ndarray worlds.
118
+ - { name: "full", features: "--features full" }
119
+ steps:
120
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
121
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
122
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
123
+ if: matrix.name == 'full'
124
+ with:
125
+ python-version: "3.14"
126
+ - name: install the official ONNX checker
127
+ if: matrix.name == 'full'
128
+ run: python -m pip install --requirement requirements/onnx-check.txt
129
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
130
+ with:
131
+ key: ${{ matrix.name }}
132
+ - run: cargo test --locked ${{ matrix.features }}
133
+ if: matrix.name != 'full'
134
+ - name: test full feature set with external ONNX validation
135
+ if: matrix.name == 'full'
136
+ run: cargo test --locked ${{ matrix.features }}
137
+ env:
138
+ MILLWRIGHT_ONNX_CHECKER: python
139
+
140
+ # Cross-platform confidence on the default install, without multiplying the
141
+ # whole feature matrix across three operating systems.
142
+ os:
143
+ name: test (${{ matrix.os }})
144
+ runs-on: ${{ matrix.os }}
145
+ strategy:
146
+ fail-fast: false
147
+ matrix:
148
+ os: [windows-latest, macos-latest]
149
+ steps:
150
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
151
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
152
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
153
+ - run: cargo test --locked
154
+
155
+ msrv:
156
+ name: minimum Rust 1.95
157
+ runs-on: ubuntu-latest
158
+ steps:
159
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
160
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
161
+ with:
162
+ toolchain: "1.95"
163
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
164
+ - run: cargo check --locked --all-targets --features full
165
+
166
+ supply-chain:
167
+ name: advisories
168
+ runs-on: ubuntu-latest
169
+ steps:
170
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
171
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
172
+ - run: cargo install cargo-audit --locked
173
+ - run: cargo audit
174
+
175
+ dependency-policy:
176
+ name: dependency policy
177
+ runs-on: ubuntu-latest
178
+ steps:
179
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
180
+ - uses: taiki-e/install-action@bf681f3be21c0d2daea0ea20bbf590138fc96a2b # cargo-deny
181
+ - run: cargo deny check
182
+
183
+ coverage:
184
+ name: coverage
185
+ runs-on: ubuntu-latest
186
+ steps:
187
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
188
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
189
+ with:
190
+ components: llvm-tools-preview
191
+ - uses: taiki-e/install-action@d630c3ba8c9bb0648bcefda869fb0d9b98c611d9 # cargo-llvm-cov
192
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
193
+ - name: measure full-feature Rust coverage
194
+ run: cargo llvm-cov --locked --features full --workspace --lcov --output-path lcov.info
195
+ - name: enforce coverage floor
196
+ run: >-
197
+ cargo llvm-cov report --summary-only
198
+ --fail-under-lines 82
199
+ --fail-under-functions 75
200
+ --fail-under-regions 84
201
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
202
+ with:
203
+ name: rust-coverage
204
+ path: lcov.info
205
+ if-no-files-found: error
206
+
207
+ branch-coverage:
208
+ name: branch coverage
209
+ runs-on: ubuntu-latest
210
+ steps:
211
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
212
+ # LLVM branch instrumentation remains a nightly-only cargo-llvm-cov mode.
213
+ - uses: dtolnay/rust-toolchain@7c8d7d138f5c09cef361f8214cf96882cd029cdb # nightly
214
+ with:
215
+ components: llvm-tools-preview
216
+ - uses: taiki-e/install-action@d630c3ba8c9bb0648bcefda869fb0d9b98c611d9 # cargo-llvm-cov
217
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
218
+ with:
219
+ key: branch-coverage
220
+ - name: measure decision coverage
221
+ run: >-
222
+ cargo +nightly llvm-cov --locked --features full --workspace --branch
223
+ --cobertura --output-path branch-coverage.xml
224
+ - name: enforce branch coverage floor
225
+ run: python scripts/check-branch-coverage.py branch-coverage.xml --minimum 65
226
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
227
+ with:
228
+ name: rust-branch-coverage
229
+ path: branch-coverage.xml
230
+ if-no-files-found: error
231
+
232
+ semver:
233
+ name: public API compatibility
234
+ runs-on: ubuntu-latest
235
+ steps:
236
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
237
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
238
+ - run: cargo install cargo-semver-checks --locked
239
+ - run: cargo semver-checks check-release
240
+
241
+ # Compile and *run* the examples (the `test` jobs only build the library and
242
+ # its tests), plus a compile-check of the benchmarks. The dedicated `msrv`
243
+ # job above proves the declared Rust 1.95 floor independently.
244
+ examples:
245
+ name: examples & benches
246
+ runs-on: ubuntu-latest
247
+ steps:
248
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
249
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
250
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
251
+ - name: run every example
252
+ run: |
253
+ for ex in spine explore trust workflow backends insight portability operations specialized automl; do
254
+ echo "::group::$ex"
255
+ cargo run --locked --features full --example "$ex"
256
+ echo "::endgroup::"
257
+ done
258
+ - name: compile benchmarks
259
+ run: cargo bench --locked --features full --no-run
260
+
261
+ package:
262
+ name: package (publish dry-run)
263
+ runs-on: ubuntu-latest
264
+ steps:
265
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
266
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
267
+ # No rust-cache here: `cargo publish` builds a copy under target/package,
268
+ # which the cache action's post-step chokes on.
269
+ # Prove the crate packages and builds from its packaged form as it would on
270
+ # crates.io — catches missing files, bad metadata, and path/dev-dep leaks.
271
+ - run: cargo publish --dry-run --locked
272
+
273
+ python:
274
+ name: python wheel (build & test)
275
+ runs-on: ubuntu-latest
276
+ steps:
277
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
278
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
279
+ with:
280
+ components: llvm-tools-preview
281
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
282
+ with:
283
+ # pytest 9 contains the tmpdir security fix and requires Python 3.10+.
284
+ # The separate ABI matrix still smoke-tests the wheel on Python 3.9.
285
+ python-version: "3.10"
286
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
287
+ - uses: taiki-e/install-action@d630c3ba8c9bb0648bcefda869fb0d9b98c611d9 # cargo-llvm-cov
288
+ # The `python` feature can't be linked by `cargo test` (pyo3's
289
+ # extension-module defers libpython), so it is built the way it ships:
290
+ # as an abi3 wheel via maturin, then smoke-imported.
291
+ - run: python -m pip install --requirement requirements/ci-python.txt
292
+ - name: build instrumented wheel and measure Python binding coverage
293
+ shell: bash
294
+ run: |
295
+ cargo llvm-cov clean --workspace
296
+ source <(cargo llvm-cov show-env --export-prefix)
297
+ maturin build --locked --out wheel
298
+ python -m pip install --force-reinstall wheel/*.whl
299
+ python -m pytest -q tests/python
300
+ cargo llvm-cov report --lcov --output-path python-bindings.lcov
301
+ python scripts/check-lcov-coverage.py python-bindings.lcov \
302
+ --minimum 45 --file src/python.rs --file src/python_data.rs
303
+ - run: python -m mypy --strict tests/python/typing_contract.py
304
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
305
+ with:
306
+ name: python-binding-coverage
307
+ path: python-bindings.lcov
308
+ if-no-files-found: error
309
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
310
+ with:
311
+ name: python-abi3-wheel
312
+ path: wheel/*.whl
313
+ if-no-files-found: error
314
+
315
+ python-compat:
316
+ name: python wheel (${{ matrix.python }})
317
+ needs: python
318
+ runs-on: ubuntu-latest
319
+ strategy:
320
+ fail-fast: false
321
+ matrix:
322
+ python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
323
+ steps:
324
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
325
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
326
+ with:
327
+ python-version: ${{ matrix.python }}
328
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
329
+ with:
330
+ name: python-abi3-wheel
331
+ path: wheel
332
+ - run: python -m pip install --no-deps wheel/*.whl
333
+ - run: python tests/python/compat_smoke.py
334
+
335
+ ci-success:
336
+ name: CI success
337
+ if: always()
338
+ needs:
339
+ - consistency
340
+ - fmt
341
+ - clippy
342
+ - docs
343
+ - test
344
+ - os
345
+ - msrv
346
+ - supply-chain
347
+ - dependency-policy
348
+ - coverage
349
+ - branch-coverage
350
+ - semver
351
+ - examples
352
+ - package
353
+ - python
354
+ - python-compat
355
+ runs-on: ubuntu-latest
356
+ steps:
357
+ - name: require every CI job to succeed
358
+ env:
359
+ RESULTS: ${{ toJSON(needs) }}
360
+ shell: bash
361
+ run: |
362
+ failures="$(jq -r 'to_entries[] | select(.value.result != "success") | "\(.key): \(.value.result)"' <<< "$RESULTS")"
363
+ if [ -n "$failures" ]; then
364
+ echo "::error::one or more CI jobs did not succeed"
365
+ printf '%s\n' "$failures"
366
+ exit 1
367
+ fi
@@ -0,0 +1,40 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "17 4 * * 1"
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+ security-events: write
15
+
16
+ concurrency:
17
+ group: codeql-${{ github.ref }}
18
+ cancel-in-progress: true
19
+
20
+ jobs:
21
+ analyze:
22
+ name: analyze (${{ matrix.language }})
23
+ runs-on: ubuntu-24.04
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ include:
28
+ - language: rust
29
+ build-mode: none
30
+ - language: python
31
+ build-mode: none
32
+ steps:
33
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
34
+ - name: initialize CodeQL
35
+ uses: github/codeql-action/init@4c0873ef8656cb3c50b3f42fb63bc1ade0cfa827 # v4
36
+ with:
37
+ languages: ${{ matrix.language }}
38
+ build-mode: ${{ matrix.build-mode }}
39
+ - name: analyze
40
+ uses: github/codeql-action/analyze@4c0873ef8656cb3c50b3f42fb63bc1ade0cfa827 # v4