vexcalibur 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 (97) hide show
  1. vexcalibur-0.1.0/.github/dependabot.yml +23 -0
  2. vexcalibur-0.1.0/.github/workflows/ci.yml +292 -0
  3. vexcalibur-0.1.0/.github/workflows/codeql.yml +36 -0
  4. vexcalibur-0.1.0/.github/workflows/dependency-review.yml +22 -0
  5. vexcalibur-0.1.0/.github/workflows/pages.yml +77 -0
  6. vexcalibur-0.1.0/.github/workflows/pre-commit.yml +43 -0
  7. vexcalibur-0.1.0/.github/workflows/pypi.yml +330 -0
  8. vexcalibur-0.1.0/.github/workflows/release.yml +462 -0
  9. vexcalibur-0.1.0/.github/workflows/scorecard.yml +44 -0
  10. vexcalibur-0.1.0/.github/workflows/sync-style-guide.yml +61 -0
  11. vexcalibur-0.1.0/.gitignore +12 -0
  12. vexcalibur-0.1.0/.pre-commit-config.yaml +14 -0
  13. vexcalibur-0.1.0/.python-version +1 -0
  14. vexcalibur-0.1.0/.readthedocs.yaml +17 -0
  15. vexcalibur-0.1.0/.secrets.baseline +122 -0
  16. vexcalibur-0.1.0/.tool-versions +3 -0
  17. vexcalibur-0.1.0/AGENTS.md +194 -0
  18. vexcalibur-0.1.0/CONTRIBUTING.md +62 -0
  19. vexcalibur-0.1.0/LICENSE +202 -0
  20. vexcalibur-0.1.0/Makefile +73 -0
  21. vexcalibur-0.1.0/PKG-INFO +223 -0
  22. vexcalibur-0.1.0/README.md +184 -0
  23. vexcalibur-0.1.0/SECURITY.md +23 -0
  24. vexcalibur-0.1.0/docs/assets/badges/ci.svg +6 -0
  25. vexcalibur-0.1.0/docs/assets/badges/codeql.svg +6 -0
  26. vexcalibur-0.1.0/docs/assets/badges/dependency-review.svg +6 -0
  27. vexcalibur-0.1.0/docs/assets/badges/scorecard.svg +6 -0
  28. vexcalibur-0.1.0/docs/assets/vexcalibur-banner.png +0 -0
  29. vexcalibur-0.1.0/docs/conf.py +65 -0
  30. vexcalibur-0.1.0/docs/development/ci.md +156 -0
  31. vexcalibur-0.1.0/docs/development/python-style.md +58 -0
  32. vexcalibur-0.1.0/docs/explanation/architecture.md +104 -0
  33. vexcalibur-0.1.0/docs/explanation/project-status.md +49 -0
  34. vexcalibur-0.1.0/docs/external/README.md +15 -0
  35. vexcalibur-0.1.0/docs/external/google-python-style-guide.md +3707 -0
  36. vexcalibur-0.1.0/docs/how-to/generate-cyclonedx-vex.md +209 -0
  37. vexcalibur-0.1.0/docs/how-to/publish-to-pypi.md +188 -0
  38. vexcalibur-0.1.0/docs/how-to/use-private-osv-mirror.md +69 -0
  39. vexcalibur-0.1.0/docs/index.md +44 -0
  40. vexcalibur-0.1.0/docs/reference/cli.md +350 -0
  41. vexcalibur-0.1.0/docs/reference/cyclonedx-vex-output.md +114 -0
  42. vexcalibur-0.1.0/docs/reference/local-findings.md +55 -0
  43. vexcalibur-0.1.0/docs/reference/provider-contract.md +124 -0
  44. vexcalibur-0.1.0/docs/reference/python-api.rst +105 -0
  45. vexcalibur-0.1.0/docs/tutorials/offline-local-findings.md +83 -0
  46. vexcalibur-0.1.0/docs/tutorials/quickstart.md +79 -0
  47. vexcalibur-0.1.0/pyproject.toml +133 -0
  48. vexcalibur-0.1.0/scripts/check-installed-cli.sh +40 -0
  49. vexcalibur-0.1.0/scripts/next-release-tag.sh +177 -0
  50. vexcalibur-0.1.0/scripts/verify-dist-metadata.py +106 -0
  51. vexcalibur-0.1.0/setup.cfg +4 -0
  52. vexcalibur-0.1.0/src/vexcalibur/__init__.py +14 -0
  53. vexcalibur-0.1.0/src/vexcalibur/_version.py +24 -0
  54. vexcalibur-0.1.0/src/vexcalibur/cli.py +336 -0
  55. vexcalibur-0.1.0/src/vexcalibur/compat/__init__.py +1 -0
  56. vexcalibur-0.1.0/src/vexcalibur/compat/vexy.py +263 -0
  57. vexcalibur-0.1.0/src/vexcalibur/domain.py +67 -0
  58. vexcalibur-0.1.0/src/vexcalibur/generate.py +133 -0
  59. vexcalibur-0.1.0/src/vexcalibur/github_sbom.py +656 -0
  60. vexcalibur-0.1.0/src/vexcalibur/py.typed +1 -0
  61. vexcalibur-0.1.0/src/vexcalibur/sbom.py +497 -0
  62. vexcalibur-0.1.0/src/vexcalibur/source_options.py +56 -0
  63. vexcalibur-0.1.0/src/vexcalibur/sources/__init__.py +1 -0
  64. vexcalibur-0.1.0/src/vexcalibur/sources/local.py +262 -0
  65. vexcalibur-0.1.0/src/vexcalibur/sources/osv.py +515 -0
  66. vexcalibur-0.1.0/src/vexcalibur/vex.py +262 -0
  67. vexcalibur-0.1.0/src/vexcalibur.egg-info/PKG-INFO +223 -0
  68. vexcalibur-0.1.0/src/vexcalibur.egg-info/SOURCES.txt +95 -0
  69. vexcalibur-0.1.0/src/vexcalibur.egg-info/dependency_links.txt +1 -0
  70. vexcalibur-0.1.0/src/vexcalibur.egg-info/entry_points.txt +3 -0
  71. vexcalibur-0.1.0/src/vexcalibur.egg-info/requires.txt +12 -0
  72. vexcalibur-0.1.0/src/vexcalibur.egg-info/scm_file_list.json +90 -0
  73. vexcalibur-0.1.0/src/vexcalibur.egg-info/scm_version.json +8 -0
  74. vexcalibur-0.1.0/src/vexcalibur.egg-info/top_level.txt +1 -0
  75. vexcalibur-0.1.0/tests/fixtures/findings/all-analysis-states.json +49 -0
  76. vexcalibur-0.1.0/tests/fixtures/sbom/cyclonedx-json-1.4-simple.json +21 -0
  77. vexcalibur-0.1.0/tests/fixtures/sbom/cyclonedx-json-1.5-simple.json +21 -0
  78. vexcalibur-0.1.0/tests/fixtures/sbom/cyclonedx-json-simple.json +32 -0
  79. vexcalibur-0.1.0/tests/fixtures/sbom/cyclonedx-xml-1.4-simple.xml +15 -0
  80. vexcalibur-0.1.0/tests/fixtures/sbom/cyclonedx-xml-1.5-simple.xml +15 -0
  81. vexcalibur-0.1.0/tests/fixtures/sbom/cyclonedx-xml-simple.xml +10 -0
  82. vexcalibur-0.1.0/tests/fixtures/vexy/legacy-config.yml +2 -0
  83. vexcalibur-0.1.0/tests/golden/cyclonedx-vex-all-analysis-states.json +171 -0
  84. vexcalibur-0.1.0/tests/golden/cyclonedx-vex-simple.json +90 -0
  85. vexcalibur-0.1.0/tests/golden/vexy-compat-cli.json +105 -0
  86. vexcalibur-0.1.0/tests/integration/check_installed_cli.py +321 -0
  87. vexcalibur-0.1.0/tests/test_cli.py +1065 -0
  88. vexcalibur-0.1.0/tests/test_generate.py +558 -0
  89. vexcalibur-0.1.0/tests/test_github_sbom.py +642 -0
  90. vexcalibur-0.1.0/tests/test_local_findings.py +366 -0
  91. vexcalibur-0.1.0/tests/test_osv_client.py +635 -0
  92. vexcalibur-0.1.0/tests/test_release_version.py +390 -0
  93. vexcalibur-0.1.0/tests/test_sbom.py +970 -0
  94. vexcalibur-0.1.0/tests/test_verify_dist_metadata.py +122 -0
  95. vexcalibur-0.1.0/tests/test_vex.py +189 -0
  96. vexcalibur-0.1.0/tests/test_vexy_compat.py +342 -0
  97. vexcalibur-0.1.0/uv.lock +2502 -0
@@ -0,0 +1,23 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: uv
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ time: "09:00"
9
+ groups:
10
+ python-dependencies:
11
+ patterns:
12
+ - "*"
13
+
14
+ - package-ecosystem: github-actions
15
+ directory: /
16
+ schedule:
17
+ interval: weekly
18
+ day: monday
19
+ time: "09:30"
20
+ groups:
21
+ github-actions:
22
+ patterns:
23
+ - "*"
@@ -0,0 +1,292 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+ inputs:
10
+ run_scheduled_profile:
11
+ description: "Run the scheduled CI profile, including live external-service compatibility"
12
+ required: false
13
+ default: false
14
+ type: boolean
15
+ run_live_services:
16
+ description: "Run live external-service compatibility checks"
17
+ required: false
18
+ default: false
19
+ type: boolean
20
+ schedule:
21
+ - cron: "17 9 * * *"
22
+
23
+ permissions:
24
+ contents: read
25
+
26
+ env:
27
+ MAX_PYTHON: "3.14"
28
+ UV_CACHE_DIR: /tmp/vexcalibur-uv-cache
29
+ XDG_CACHE_HOME: /tmp/vexcalibur-cache
30
+
31
+ jobs:
32
+ quality:
33
+ name: Quality
34
+ runs-on: ubuntu-latest
35
+ if: github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
36
+ steps:
37
+ - name: Checkout
38
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
39
+ with:
40
+ fetch-depth: 0
41
+ persist-credentials: false
42
+
43
+ - name: Set up uv
44
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
45
+ with:
46
+ version-file: .tool-versions
47
+ enable-cache: true
48
+ python-version: ${{ env.MAX_PYTHON }}
49
+
50
+ - name: Install dependencies
51
+ run: uv sync --frozen
52
+
53
+ - name: Check lock file
54
+ run: uv lock --check
55
+
56
+ - name: Check formatting
57
+ run: uv run --frozen ruff format --check src tests scripts/*.py docs/conf.py
58
+
59
+ - name: Lint
60
+ run: uv run --frozen ruff check src tests scripts/*.py docs/conf.py
61
+
62
+ - name: Type check
63
+ run: uv run --frozen mypy src
64
+
65
+ workflow-lint:
66
+ name: Workflow lint
67
+ runs-on: ubuntu-latest
68
+ if: github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
69
+ steps:
70
+ - name: Checkout
71
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
72
+ with:
73
+ fetch-depth: 0
74
+ persist-credentials: false
75
+
76
+ - name: Install workflow tools
77
+ uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0
78
+ with:
79
+ version: "v2026.6.12"
80
+ github_token: ""
81
+ cache: true
82
+ install_args: "actionlint shellcheck"
83
+
84
+ - name: Lint workflows
85
+ run: actionlint -shellcheck shellcheck .github/workflows/*.yml
86
+
87
+ - name: Lint shell scripts
88
+ run: shellcheck scripts/*.sh
89
+
90
+ security:
91
+ name: Repository security
92
+ runs-on: ubuntu-latest
93
+ steps:
94
+ - name: Checkout
95
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
96
+ with:
97
+ fetch-depth: 0
98
+ persist-credentials: false
99
+
100
+ - name: Set up uv
101
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
102
+ with:
103
+ version-file: .tool-versions
104
+ enable-cache: true
105
+ python-version: ${{ env.MAX_PYTHON }}
106
+
107
+ - name: Install dependencies
108
+ run: uv sync --frozen
109
+
110
+ - name: Audit Python dependencies
111
+ run: uv run --frozen pip-audit --cache-dir /tmp/vexcalibur-pip-audit-cache
112
+
113
+ - name: Scan pull request for secrets
114
+ if: github.event_name == 'pull_request'
115
+ env:
116
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
117
+ GH_TOKEN: ${{ github.token }}
118
+ run: |
119
+ gh api "/repos/${GITHUB_REPOSITORY}/contents/.secrets.baseline?ref=${BASE_SHA}" --jq .content \
120
+ | base64 --decode > /tmp/base.secrets.baseline
121
+ git ls-files -z | xargs -0 uv run --frozen detect-secrets-hook --baseline /tmp/base.secrets.baseline --
122
+
123
+ - name: Scan pushed code for secrets
124
+ if: github.event_name != 'pull_request'
125
+ run: git ls-files -z | xargs -0 uv run --frozen detect-secrets-hook --baseline .secrets.baseline --
126
+
127
+ test:
128
+ name: Test (Python ${{ matrix.python-version }})
129
+ runs-on: ubuntu-latest
130
+ if: github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
131
+ strategy:
132
+ fail-fast: false
133
+ matrix:
134
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
135
+ steps:
136
+ - name: Checkout
137
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
138
+ with:
139
+ fetch-depth: 0
140
+ persist-credentials: false
141
+
142
+ - name: Set up uv
143
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
144
+ with:
145
+ version-file: .tool-versions
146
+ enable-cache: true
147
+ python-version: ${{ matrix.python-version }}
148
+
149
+ - name: Install dependencies
150
+ run: uv sync --frozen
151
+
152
+ - name: Run offline tests
153
+ run: uv run --frozen pytest -m "not live" --cov-fail-under=75
154
+
155
+ - name: Upload coverage XML
156
+ if: matrix.python-version == env.MAX_PYTHON
157
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
158
+ with:
159
+ name: coverage-xml
160
+ path: coverage.xml
161
+ retention-days: 14
162
+
163
+ build:
164
+ name: Build package
165
+ runs-on: ubuntu-latest
166
+ if: github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
167
+ steps:
168
+ - name: Checkout
169
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
170
+ with:
171
+ fetch-depth: 0
172
+ persist-credentials: false
173
+
174
+ - name: Set up uv
175
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
176
+ with:
177
+ version-file: .tool-versions
178
+ enable-cache: true
179
+ python-version: ${{ env.MAX_PYTHON }}
180
+
181
+ - name: Build distributions
182
+ run: uv build --clear --no-create-gitignore --no-sources
183
+
184
+ - name: Upload distributions
185
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
186
+ with:
187
+ name: dist
188
+ path: dist/
189
+ retention-days: 14
190
+
191
+ installed-cli:
192
+ name: Installed CLI
193
+ runs-on: ubuntu-latest
194
+ needs: build
195
+ if: github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
196
+ steps:
197
+ - name: Checkout
198
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
199
+ with:
200
+ fetch-depth: 0
201
+ persist-credentials: false
202
+
203
+ - name: Set up uv
204
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
205
+ with:
206
+ version-file: .tool-versions
207
+ enable-cache: true
208
+ python-version: ${{ env.MAX_PYTHON }}
209
+
210
+ - name: Download distributions
211
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
212
+ with:
213
+ name: dist
214
+ path: dist
215
+
216
+ - name: Select wheel
217
+ id: wheel
218
+ run: |
219
+ mapfile -t wheels < <(find dist -maxdepth 1 -type f -name "*.whl" | sort)
220
+ if [ "${#wheels[@]}" -ne 1 ]; then
221
+ echo "Expected exactly one wheel in dist, found ${#wheels[@]}" >&2
222
+ exit 2
223
+ fi
224
+ printf 'path=%s\n' "${wheels[0]}" >> "$GITHUB_OUTPUT"
225
+
226
+ - name: Run installed CLI checks
227
+ env:
228
+ VEXCALIBUR_WHEEL: ${{ steps.wheel.outputs.path }}
229
+ run: make installed-cli-check
230
+
231
+ docs:
232
+ name: Build docs
233
+ runs-on: ubuntu-latest
234
+ if: github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
235
+ steps:
236
+ - name: Checkout
237
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
238
+ with:
239
+ fetch-depth: 0
240
+ persist-credentials: false
241
+
242
+ - name: Set up uv
243
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
244
+ with:
245
+ version-file: .tool-versions
246
+ enable-cache: true
247
+ python-version: "3.13"
248
+
249
+ - name: Install dependencies
250
+ run: uv sync --frozen --extra docs
251
+
252
+ - name: Build documentation
253
+ run: make docs
254
+
255
+ live-services:
256
+ name: Live external-service compatibility
257
+ runs-on: ubuntu-latest
258
+ if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (inputs.run_scheduled_profile || inputs.run_live_services))
259
+ steps:
260
+ - name: Checkout
261
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
262
+ with:
263
+ fetch-depth: 0
264
+ persist-credentials: false
265
+
266
+ - name: Set up uv
267
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
268
+ with:
269
+ version-file: .tool-versions
270
+ enable-cache: true
271
+ python-version: ${{ env.MAX_PYTHON }}
272
+
273
+ - name: Install dependencies
274
+ run: uv sync --frozen
275
+
276
+ - name: Run live external-service compatibility tests
277
+ run: uv run --frozen pytest -m live -q
278
+
279
+ ci:
280
+ name: CI result
281
+ runs-on: ubuntu-latest
282
+ needs: [quality, workflow-lint, security, test, build, installed-cli, docs]
283
+ if: always() && github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.run_scheduled_profile)
284
+ steps:
285
+ - name: Check required jobs
286
+ run: |
287
+ for result in "${{ needs.quality.result }}" "${{ needs.workflow-lint.result }}" "${{ needs.security.result }}" "${{ needs.test.result }}" "${{ needs.build.result }}" "${{ needs.installed-cli.result }}" "${{ needs.docs.result }}"; do
288
+ if [ "$result" != "success" ]; then
289
+ echo "Required job failed or was skipped: $result"
290
+ exit 1
291
+ fi
292
+ done
@@ -0,0 +1,36 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "41 8 * * 1"
10
+ workflow_dispatch:
11
+
12
+ permissions: read-all
13
+
14
+ jobs:
15
+ analyze:
16
+ name: Analyze Python
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ actions: read
20
+ contents: read
21
+ security-events: write
22
+ steps:
23
+ - name: Checkout
24
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
25
+
26
+ - name: Initialize CodeQL
27
+ uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
28
+ with:
29
+ languages: python
30
+ queries: security-and-quality
31
+
32
+ - name: Perform CodeQL analysis
33
+ uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
34
+ with:
35
+ category: /language:python
36
+
@@ -0,0 +1,22 @@
1
+ name: Dependency Review
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: read
9
+ pull-requests: write
10
+
11
+ jobs:
12
+ dependency-review:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
17
+
18
+ - name: Review dependency changes
19
+ uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
20
+ with:
21
+ comment-summary-in-pr: always
22
+ fail-on-severity: high
@@ -0,0 +1,77 @@
1
+ name: Publish documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - ".github/workflows/pages.yml"
8
+ - ".tool-versions"
9
+ - "Makefile"
10
+ - "docs/**"
11
+ - "pyproject.toml"
12
+ - "src/**"
13
+ - "uv.lock"
14
+ workflow_dispatch:
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ concurrency:
20
+ group: github-pages
21
+ cancel-in-progress: false
22
+
23
+ env:
24
+ UV_CACHE_DIR: /tmp/vexcalibur-uv-cache
25
+
26
+ jobs:
27
+ build:
28
+ name: Build documentation
29
+ runs-on: ubuntu-latest
30
+ permissions:
31
+ contents: read
32
+ pages: read
33
+ steps:
34
+ - name: Checkout
35
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
36
+ with:
37
+ fetch-depth: 0
38
+ persist-credentials: false
39
+
40
+ - name: Set up uv
41
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
42
+ with:
43
+ version-file: .tool-versions
44
+ enable-cache: true
45
+ python-version: "3.13"
46
+
47
+ - name: Configure GitHub Pages
48
+ uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
49
+
50
+ - name: Install dependencies
51
+ run: uv sync --frozen --extra docs
52
+
53
+ - name: Build documentation
54
+ run: |
55
+ make docs
56
+ touch docs/_build/html/.nojekyll
57
+
58
+ - name: Upload GitHub Pages artifact
59
+ uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
60
+ with:
61
+ path: docs/_build/html
62
+
63
+ deploy:
64
+ name: Deploy documentation
65
+ runs-on: ubuntu-latest
66
+ needs: build
67
+ permissions:
68
+ contents: read
69
+ pages: write
70
+ id-token: write
71
+ environment:
72
+ name: github-pages
73
+ url: ${{ steps.deployment.outputs.page_url }}
74
+ steps:
75
+ - name: Deploy to GitHub Pages
76
+ id: deployment
77
+ uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
@@ -0,0 +1,43 @@
1
+ name: Pre-commit
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ env:
13
+ UV_CACHE_DIR: /tmp/vexcalibur-uv-cache
14
+
15
+ jobs:
16
+ pre-commit:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
21
+ with:
22
+ fetch-depth: 0
23
+ persist-credentials: false
24
+
25
+ - name: Set up uv
26
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
27
+ with:
28
+ version-file: .tool-versions
29
+ enable-cache: true
30
+ python-version: "3.14"
31
+
32
+ - name: Install dependencies
33
+ run: uv sync --frozen
34
+
35
+ - name: Run pre-commit
36
+ run: uv run --frozen pre-commit run --all-files
37
+
38
+ - name: Fail if hooks changed files
39
+ run: |
40
+ if ! git diff --quiet; then
41
+ git status --short
42
+ exit 1
43
+ fi