castle-token 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.
- castle_token-0.1.0/.github/workflows/ci.yml +26 -0
- castle_token-0.1.0/.github/workflows/node-release.yml +234 -0
- castle_token-0.1.0/.github/workflows/node.yml +37 -0
- castle_token-0.1.0/.github/workflows/python-release.yml +179 -0
- castle_token-0.1.0/.github/workflows/python.yml +55 -0
- castle_token-0.1.0/.gitignore +27 -0
- castle_token-0.1.0/Cargo.lock +833 -0
- castle_token-0.1.0/Cargo.toml +35 -0
- castle_token-0.1.0/PKG-INFO +90 -0
- castle_token-0.1.0/README.md +171 -0
- castle_token-0.1.0/pyproject.toml +29 -0
- castle_token-0.1.0/python/Cargo.toml +23 -0
- castle_token-0.1.0/python/README.md +71 -0
- castle_token-0.1.0/python/castle_token/__init__.py +23 -0
- castle_token-0.1.0/python/castle_token/__init__.pyi +80 -0
- castle_token-0.1.0/python/castle_token/py.typed +0 -0
- castle_token-0.1.0/python/examples/mint_token.py +60 -0
- castle_token-0.1.0/python/src/lib.rs +234 -0
- castle_token-0.1.0/python/tests/test_smoke.py +58 -0
- castle_token-0.1.0/src/ce.rs +224 -0
- castle_token-0.1.0/src/codec.rs +68 -0
- castle_token-0.1.0/src/error.rs +57 -0
- castle_token-0.1.0/src/events.rs +166 -0
- castle_token-0.1.0/src/fingerprint/context.rs +400 -0
- castle_token-0.1.0/src/fingerprint/devices.json +363 -0
- castle_token-0.1.0/src/fingerprint/devices.rs +39 -0
- castle_token-0.1.0/src/fingerprint/encode.rs +186 -0
- castle_token-0.1.0/src/fingerprint/mod.rs +214 -0
- castle_token-0.1.0/src/fingerprint/parts/extra.rs +58 -0
- castle_token-0.1.0/src/fingerprint/parts/mod.rs +30 -0
- castle_token-0.1.0/src/fingerprint/parts/part0.rs +243 -0
- castle_token-0.1.0/src/fingerprint/parts/part4.rs +183 -0
- castle_token-0.1.0/src/fingerprint/parts/part7.rs +241 -0
- castle_token-0.1.0/src/lib.rs +19 -0
- castle_token-0.1.0/src/main.rs +80 -0
- castle_token-0.1.0/src/token/encoder.rs +133 -0
- castle_token-0.1.0/src/token/inner_payload.rs +32 -0
- castle_token-0.1.0/src/token/mod.rs +180 -0
- castle_token-0.1.0/src/token/time_token.rs +109 -0
- castle_token-0.1.0/src/xxtea.rs +144 -0
- castle_token-0.1.0/tests/decode_roundtrip.rs +90 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
CARGO_TERM_COLOR: always
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: fmt + clippy + test
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
19
|
+
with:
|
|
20
|
+
components: rustfmt, clippy
|
|
21
|
+
- uses: Swatinem/rust-cache@v2
|
|
22
|
+
- run: cargo fmt --all --check
|
|
23
|
+
# Scope clippy/test to the core crate so this Rust-only job never builds
|
|
24
|
+
# the PyO3 cdylib (which needs a Python interpreter) — see python.yml.
|
|
25
|
+
- run: cargo clippy -p castle-token --all-targets -- -D warnings
|
|
26
|
+
- run: cargo test -p castle-token
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
name: Node release
|
|
2
|
+
|
|
3
|
+
# Cross-arch prebuilt-binary pipeline for the `castle-token` npm package.
|
|
4
|
+
#
|
|
5
|
+
# Triggered by a `vX.Y.Z` tag: builds the addon for every target in
|
|
6
|
+
# node/package.json `napi.targets`, runs the binaries on real OS/arch matrices,
|
|
7
|
+
# then publishes the main package + the per-platform `optionalDependencies`
|
|
8
|
+
# packages so `npm i castle-token` pulls a prebuilt .node with no Rust toolchain.
|
|
9
|
+
#
|
|
10
|
+
# `workflow_dispatch` runs build + test only (no publish) for dry-runs.
|
|
11
|
+
#
|
|
12
|
+
# Release process:
|
|
13
|
+
# 1. set the SAME version in node/package.json `version` AND all 8
|
|
14
|
+
# `optionalDependencies` entries — they must match exactly. (`napi version`
|
|
15
|
+
# updates the npm/<platform>/ packages but NOT the root optionalDependencies,
|
|
16
|
+
# so bump those by hand or with a script.)
|
|
17
|
+
# 2. commit, then `git tag vX.Y.Z && git push origin vX.Y.Z`.
|
|
18
|
+
# Requires a repo secret `NPM_TOKEN` that is an npm **Automation** token — a
|
|
19
|
+
# classic/granular token fails publish with EOTP when the account has 2FA. The
|
|
20
|
+
# publish job fail-fasts if the tag/version disagree or npm auth is missing.
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
push:
|
|
24
|
+
tags:
|
|
25
|
+
- 'v*.*.*'
|
|
26
|
+
workflow_dispatch:
|
|
27
|
+
|
|
28
|
+
env:
|
|
29
|
+
CARGO_TERM_COLOR: always
|
|
30
|
+
APP_NAME: castle-token
|
|
31
|
+
DEBUG: napi:*
|
|
32
|
+
|
|
33
|
+
defaults:
|
|
34
|
+
run:
|
|
35
|
+
working-directory: node
|
|
36
|
+
|
|
37
|
+
jobs:
|
|
38
|
+
build:
|
|
39
|
+
name: build ${{ matrix.settings.target }}
|
|
40
|
+
runs-on: ${{ matrix.settings.host }}
|
|
41
|
+
strategy:
|
|
42
|
+
fail-fast: false
|
|
43
|
+
matrix:
|
|
44
|
+
settings:
|
|
45
|
+
- host: ubuntu-latest
|
|
46
|
+
target: x86_64-unknown-linux-gnu
|
|
47
|
+
build: npm run build -- --target x86_64-unknown-linux-gnu --use-napi-cross
|
|
48
|
+
- host: ubuntu-latest
|
|
49
|
+
target: x86_64-unknown-linux-musl
|
|
50
|
+
build: npm run build -- --target x86_64-unknown-linux-musl -x
|
|
51
|
+
- host: ubuntu-latest
|
|
52
|
+
target: aarch64-unknown-linux-gnu
|
|
53
|
+
build: npm run build -- --target aarch64-unknown-linux-gnu --use-napi-cross
|
|
54
|
+
- host: ubuntu-latest
|
|
55
|
+
target: aarch64-unknown-linux-musl
|
|
56
|
+
build: npm run build -- --target aarch64-unknown-linux-musl -x
|
|
57
|
+
- host: macos-latest
|
|
58
|
+
target: x86_64-apple-darwin
|
|
59
|
+
build: npm run build -- --target x86_64-apple-darwin
|
|
60
|
+
- host: macos-latest
|
|
61
|
+
target: aarch64-apple-darwin
|
|
62
|
+
build: npm run build -- --target aarch64-apple-darwin
|
|
63
|
+
- host: windows-latest
|
|
64
|
+
target: x86_64-pc-windows-msvc
|
|
65
|
+
build: npm run build -- --target x86_64-pc-windows-msvc
|
|
66
|
+
- host: windows-latest
|
|
67
|
+
target: aarch64-pc-windows-msvc
|
|
68
|
+
build: npm run build -- --target aarch64-pc-windows-msvc
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v7
|
|
71
|
+
- uses: actions/setup-node@v6
|
|
72
|
+
with:
|
|
73
|
+
node-version: 24
|
|
74
|
+
cache: npm
|
|
75
|
+
cache-dependency-path: node/package-lock.json
|
|
76
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
77
|
+
with:
|
|
78
|
+
targets: ${{ matrix.settings.target }}
|
|
79
|
+
- uses: Swatinem/rust-cache@v2
|
|
80
|
+
with:
|
|
81
|
+
workspaces: ". -> target"
|
|
82
|
+
key: ${{ matrix.settings.target }}
|
|
83
|
+
# musl targets cross-compile via cargo-zigbuild (`-x`); gnu targets use the
|
|
84
|
+
# napi cross-toolchain (`--use-napi-cross`), which the CLI fetches itself.
|
|
85
|
+
- uses: mlugg/setup-zig@v2
|
|
86
|
+
if: ${{ contains(matrix.settings.target, 'musl') }}
|
|
87
|
+
with:
|
|
88
|
+
version: 0.14.1
|
|
89
|
+
- uses: taiki-e/install-action@v2
|
|
90
|
+
if: ${{ contains(matrix.settings.target, 'musl') }}
|
|
91
|
+
with:
|
|
92
|
+
tool: cargo-zigbuild
|
|
93
|
+
- run: npm ci
|
|
94
|
+
- name: Build
|
|
95
|
+
run: ${{ matrix.settings.build }}
|
|
96
|
+
shell: bash
|
|
97
|
+
- uses: actions/upload-artifact@v7
|
|
98
|
+
with:
|
|
99
|
+
name: bindings-${{ matrix.settings.target }}
|
|
100
|
+
# path is repo-root-relative (not working-directory); the wildcard's
|
|
101
|
+
# common ancestor (node/) is stripped, so the artifact holds the bare
|
|
102
|
+
# castle-token.<target>.node, which the test job's `path: node` places
|
|
103
|
+
# back at node/ for the local-first loader.
|
|
104
|
+
path: node/${{ env.APP_NAME }}.*.node
|
|
105
|
+
if-no-files-found: error
|
|
106
|
+
|
|
107
|
+
test-macos-windows:
|
|
108
|
+
name: test ${{ matrix.settings.target }} - node@${{ matrix.node }}
|
|
109
|
+
needs: build
|
|
110
|
+
runs-on: ${{ matrix.settings.host }}
|
|
111
|
+
strategy:
|
|
112
|
+
fail-fast: false
|
|
113
|
+
matrix:
|
|
114
|
+
settings:
|
|
115
|
+
- host: macos-latest
|
|
116
|
+
target: aarch64-apple-darwin
|
|
117
|
+
architecture: arm64
|
|
118
|
+
- host: macos-latest
|
|
119
|
+
target: x86_64-apple-darwin
|
|
120
|
+
architecture: x64
|
|
121
|
+
- host: windows-latest
|
|
122
|
+
target: x86_64-pc-windows-msvc
|
|
123
|
+
architecture: x64
|
|
124
|
+
- host: windows-11-arm
|
|
125
|
+
target: aarch64-pc-windows-msvc
|
|
126
|
+
architecture: arm64
|
|
127
|
+
node: ['22', '24']
|
|
128
|
+
steps:
|
|
129
|
+
- uses: actions/checkout@v7
|
|
130
|
+
- uses: actions/setup-node@v6
|
|
131
|
+
with:
|
|
132
|
+
node-version: ${{ matrix.node }}
|
|
133
|
+
architecture: ${{ matrix.settings.architecture }}
|
|
134
|
+
- uses: actions/download-artifact@v8
|
|
135
|
+
with:
|
|
136
|
+
name: bindings-${{ matrix.settings.target }}
|
|
137
|
+
path: node
|
|
138
|
+
- run: node --test
|
|
139
|
+
|
|
140
|
+
test-linux:
|
|
141
|
+
name: test ${{ matrix.target }} - node@${{ matrix.node }}
|
|
142
|
+
needs: build
|
|
143
|
+
runs-on: ${{ contains(matrix.target, 'aarch64') && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
|
144
|
+
strategy:
|
|
145
|
+
fail-fast: false
|
|
146
|
+
matrix:
|
|
147
|
+
target:
|
|
148
|
+
- x86_64-unknown-linux-gnu
|
|
149
|
+
- x86_64-unknown-linux-musl
|
|
150
|
+
- aarch64-unknown-linux-gnu
|
|
151
|
+
- aarch64-unknown-linux-musl
|
|
152
|
+
node: ['22', '24']
|
|
153
|
+
steps:
|
|
154
|
+
- uses: actions/checkout@v7
|
|
155
|
+
- uses: actions/download-artifact@v8
|
|
156
|
+
with:
|
|
157
|
+
name: bindings-${{ matrix.target }}
|
|
158
|
+
path: node
|
|
159
|
+
# gnu binaries run on the host's Node directly; musl ones run in an Alpine
|
|
160
|
+
# container. arm64 targets use the native ubuntu-24.04-arm runner (no QEMU).
|
|
161
|
+
- name: Test (gnu, native)
|
|
162
|
+
if: ${{ !contains(matrix.target, 'musl') }}
|
|
163
|
+
uses: actions/setup-node@v6
|
|
164
|
+
with:
|
|
165
|
+
node-version: ${{ matrix.node }}
|
|
166
|
+
- name: Test (gnu, native)
|
|
167
|
+
if: ${{ !contains(matrix.target, 'musl') }}
|
|
168
|
+
run: node --test
|
|
169
|
+
- name: Test (musl, Alpine container)
|
|
170
|
+
if: ${{ contains(matrix.target, 'musl') }}
|
|
171
|
+
uses: addnab/docker-run-action@v3
|
|
172
|
+
with:
|
|
173
|
+
image: node:${{ matrix.node }}-alpine
|
|
174
|
+
options: -v ${{ github.workspace }}:/work -w /work/node
|
|
175
|
+
run: node --test
|
|
176
|
+
|
|
177
|
+
publish:
|
|
178
|
+
name: publish to npm
|
|
179
|
+
runs-on: ubuntu-latest
|
|
180
|
+
needs:
|
|
181
|
+
- test-macos-windows
|
|
182
|
+
- test-linux
|
|
183
|
+
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
|
184
|
+
permissions:
|
|
185
|
+
contents: write # napi prepublish creates a GitHub release + uploads .node assets
|
|
186
|
+
id-token: write # npm provenance
|
|
187
|
+
env:
|
|
188
|
+
# job-level so the version guard, `npm whoami`, the root publish, and the
|
|
189
|
+
# per-platform publishes napi prepublish spawns all see the token.
|
|
190
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
191
|
+
steps:
|
|
192
|
+
- uses: actions/checkout@v7
|
|
193
|
+
- uses: actions/setup-node@v6
|
|
194
|
+
with:
|
|
195
|
+
node-version: 24
|
|
196
|
+
cache: npm
|
|
197
|
+
cache-dependency-path: node/package-lock.json
|
|
198
|
+
registry-url: https://registry.npmjs.org
|
|
199
|
+
- run: npm ci
|
|
200
|
+
- name: Verify tag matches package + optionalDependencies versions
|
|
201
|
+
run: |
|
|
202
|
+
PKG=$(node -p "require('./package.json').version")
|
|
203
|
+
if [ "$GITHUB_REF" != "refs/tags/v$PKG" ]; then
|
|
204
|
+
echo "::error::tag $GITHUB_REF does not match package.json v$PKG"; exit 1
|
|
205
|
+
fi
|
|
206
|
+
node -e "const p=require('./package.json');const bad=Object.entries(p.optionalDependencies).filter(([,v])=>v!==p.version);if(bad.length){console.error('optionalDependencies out of sync with '+p.version+':',bad);process.exit(1)}"
|
|
207
|
+
shell: bash
|
|
208
|
+
- name: Verify npm auth (must be an automation token)
|
|
209
|
+
run: npm whoami
|
|
210
|
+
- name: Recreate per-platform npm package dirs
|
|
211
|
+
run: npx napi create-npm-dirs
|
|
212
|
+
- uses: actions/download-artifact@v8
|
|
213
|
+
with:
|
|
214
|
+
path: node/artifacts
|
|
215
|
+
- name: Move .node files into npm/<platform>/
|
|
216
|
+
run: npm run artifacts # napi artifacts --output-dir artifacts
|
|
217
|
+
- name: Assert every platform binary is present (1 per target)
|
|
218
|
+
run: |
|
|
219
|
+
count=$(ls npm/*/${{ env.APP_NAME }}.*.node | wc -l)
|
|
220
|
+
echo "found $count platform binaries"
|
|
221
|
+
test "$count" -eq 8 || { echo "::error::expected 8 platform binaries, found $count"; exit 1; }
|
|
222
|
+
shell: bash
|
|
223
|
+
- name: List packages
|
|
224
|
+
run: ls -R npm
|
|
225
|
+
shell: bash
|
|
226
|
+
- name: Publish
|
|
227
|
+
# `npm publish` runs prepublishOnly (`napi prepublish -t npm`), which
|
|
228
|
+
# publishes each per-platform package + a GitHub release, then publishes
|
|
229
|
+
# the main package.
|
|
230
|
+
run: |
|
|
231
|
+
npm config set provenance true
|
|
232
|
+
npm publish --access public
|
|
233
|
+
env:
|
|
234
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Node
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
CARGO_TERM_COLOR: always
|
|
11
|
+
|
|
12
|
+
defaults:
|
|
13
|
+
run:
|
|
14
|
+
working-directory: node
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
name: build + test (${{ matrix.os }})
|
|
19
|
+
runs-on: ${{ matrix.os }}
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v7
|
|
26
|
+
- uses: actions/setup-node@v6
|
|
27
|
+
with:
|
|
28
|
+
node-version: 20
|
|
29
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
30
|
+
- uses: Swatinem/rust-cache@v2
|
|
31
|
+
with:
|
|
32
|
+
workspaces: ". -> target"
|
|
33
|
+
# `napi build` compiles the addon and regenerates index.js / index.d.ts;
|
|
34
|
+
# `node --test` then loads the freshly built .node and runs the smoke tests.
|
|
35
|
+
- run: npm install
|
|
36
|
+
- run: npm run build
|
|
37
|
+
- run: npm test
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
name: Python release
|
|
2
|
+
|
|
3
|
+
# Build wheels + sdist for the `castle-token` Python package (PyO3 / maturin) and
|
|
4
|
+
# publish to PyPI via Trusted Publishing (OIDC — no stored token).
|
|
5
|
+
#
|
|
6
|
+
# `abi3-py39` means ONE wheel per platform/arch covers every CPython >= 3.9, so
|
|
7
|
+
# there is no per-Python-version matrix.
|
|
8
|
+
#
|
|
9
|
+
# Triggered by a `vX.Y.Z` tag (shared with the npm release — bump all package
|
|
10
|
+
# versions together). `workflow_dispatch` builds the wheels WITHOUT publishing.
|
|
11
|
+
#
|
|
12
|
+
# One-time PyPI setup (Trusted Publishing), at
|
|
13
|
+
# https://pypi.org/manage/account/publishing/ — add a "pending publisher":
|
|
14
|
+
# PyPI project name: castle-token
|
|
15
|
+
# Owner: 0x640480
|
|
16
|
+
# Repository: castle-rs
|
|
17
|
+
# Workflow name: python-release.yml
|
|
18
|
+
# Environment: pypi
|
|
19
|
+
# The wheel version comes from python/Cargo.toml `[package] version` (pyproject
|
|
20
|
+
# declares `dynamic = ["version"]`); keep it in sync with the tag.
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
push:
|
|
24
|
+
tags:
|
|
25
|
+
- 'v*.*.*'
|
|
26
|
+
workflow_dispatch:
|
|
27
|
+
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
|
|
31
|
+
env:
|
|
32
|
+
MATURIN_ARGS: --release --out dist --manifest-path python/Cargo.toml
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
linux:
|
|
36
|
+
name: wheel manylinux-${{ matrix.target }}
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
strategy:
|
|
39
|
+
fail-fast: false
|
|
40
|
+
matrix:
|
|
41
|
+
target: [x86_64, aarch64]
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v7
|
|
44
|
+
- uses: actions/setup-python@v6
|
|
45
|
+
with:
|
|
46
|
+
python-version: '3.x'
|
|
47
|
+
- name: Build wheel
|
|
48
|
+
uses: PyO3/maturin-action@v1
|
|
49
|
+
with:
|
|
50
|
+
target: ${{ matrix.target }}
|
|
51
|
+
args: ${{ env.MATURIN_ARGS }}
|
|
52
|
+
manylinux: auto
|
|
53
|
+
sccache: 'true'
|
|
54
|
+
- uses: actions/upload-artifact@v7
|
|
55
|
+
with:
|
|
56
|
+
name: wheels-manylinux-${{ matrix.target }}
|
|
57
|
+
path: dist
|
|
58
|
+
|
|
59
|
+
musllinux:
|
|
60
|
+
name: wheel musllinux-${{ matrix.target }}
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
strategy:
|
|
63
|
+
fail-fast: false
|
|
64
|
+
matrix:
|
|
65
|
+
target: [x86_64, aarch64]
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v7
|
|
68
|
+
- uses: actions/setup-python@v6
|
|
69
|
+
with:
|
|
70
|
+
python-version: '3.x'
|
|
71
|
+
- name: Build wheel
|
|
72
|
+
uses: PyO3/maturin-action@v1
|
|
73
|
+
with:
|
|
74
|
+
target: ${{ matrix.target }}
|
|
75
|
+
args: ${{ env.MATURIN_ARGS }}
|
|
76
|
+
manylinux: musllinux_1_2
|
|
77
|
+
sccache: 'true'
|
|
78
|
+
- uses: actions/upload-artifact@v7
|
|
79
|
+
with:
|
|
80
|
+
name: wheels-musllinux-${{ matrix.target }}
|
|
81
|
+
path: dist
|
|
82
|
+
|
|
83
|
+
macos:
|
|
84
|
+
name: wheel macos-${{ matrix.target }}
|
|
85
|
+
runs-on: ${{ matrix.runner }}
|
|
86
|
+
strategy:
|
|
87
|
+
fail-fast: false
|
|
88
|
+
matrix:
|
|
89
|
+
include:
|
|
90
|
+
- runner: macos-15-intel
|
|
91
|
+
target: x86_64
|
|
92
|
+
- runner: macos-latest
|
|
93
|
+
target: aarch64
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/checkout@v7
|
|
96
|
+
- uses: actions/setup-python@v6
|
|
97
|
+
with:
|
|
98
|
+
python-version: '3.x'
|
|
99
|
+
- name: Build wheel
|
|
100
|
+
uses: PyO3/maturin-action@v1
|
|
101
|
+
with:
|
|
102
|
+
target: ${{ matrix.target }}
|
|
103
|
+
args: ${{ env.MATURIN_ARGS }}
|
|
104
|
+
sccache: 'true'
|
|
105
|
+
- uses: actions/upload-artifact@v7
|
|
106
|
+
with:
|
|
107
|
+
name: wheels-macos-${{ matrix.target }}
|
|
108
|
+
path: dist
|
|
109
|
+
|
|
110
|
+
windows:
|
|
111
|
+
name: wheel windows-x64
|
|
112
|
+
runs-on: windows-latest
|
|
113
|
+
steps:
|
|
114
|
+
- uses: actions/checkout@v7
|
|
115
|
+
- uses: actions/setup-python@v6
|
|
116
|
+
with:
|
|
117
|
+
python-version: '3.x'
|
|
118
|
+
architecture: x64
|
|
119
|
+
- name: Build wheel
|
|
120
|
+
uses: PyO3/maturin-action@v1
|
|
121
|
+
with:
|
|
122
|
+
target: x64
|
|
123
|
+
args: ${{ env.MATURIN_ARGS }}
|
|
124
|
+
sccache: 'true'
|
|
125
|
+
- uses: actions/upload-artifact@v7
|
|
126
|
+
with:
|
|
127
|
+
name: wheels-windows-x64
|
|
128
|
+
path: dist
|
|
129
|
+
|
|
130
|
+
sdist:
|
|
131
|
+
name: sdist
|
|
132
|
+
runs-on: ubuntu-latest
|
|
133
|
+
steps:
|
|
134
|
+
- uses: actions/checkout@v7
|
|
135
|
+
- name: Build sdist
|
|
136
|
+
uses: PyO3/maturin-action@v1
|
|
137
|
+
with:
|
|
138
|
+
command: sdist
|
|
139
|
+
args: --out dist --manifest-path python/Cargo.toml
|
|
140
|
+
- uses: actions/upload-artifact@v7
|
|
141
|
+
with:
|
|
142
|
+
name: wheels-sdist
|
|
143
|
+
path: dist
|
|
144
|
+
|
|
145
|
+
publish:
|
|
146
|
+
name: Publish to PyPI
|
|
147
|
+
runs-on: ubuntu-latest
|
|
148
|
+
needs: [linux, musllinux, macos, windows, sdist]
|
|
149
|
+
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
|
150
|
+
environment:
|
|
151
|
+
name: pypi
|
|
152
|
+
url: https://pypi.org/p/castle-token
|
|
153
|
+
permissions:
|
|
154
|
+
id-token: write # OIDC for Trusted Publishing
|
|
155
|
+
attestations: write # PEP 740 attestations
|
|
156
|
+
contents: read
|
|
157
|
+
steps:
|
|
158
|
+
- uses: actions/checkout@v7
|
|
159
|
+
- name: Verify tag matches python/Cargo.toml version
|
|
160
|
+
# the wheel version is `dynamic` (maturin reads python/Cargo.toml); guard
|
|
161
|
+
# against a tag that disagrees, which would publish a stale version.
|
|
162
|
+
run: |
|
|
163
|
+
VER=$(python3 -c "import tomllib;print(tomllib.load(open('python/Cargo.toml','rb'))['package']['version'])")
|
|
164
|
+
if [ "$GITHUB_REF" != "refs/tags/v$VER" ]; then
|
|
165
|
+
echo "::error::tag $GITHUB_REF does not match python/Cargo.toml v$VER"; exit 1
|
|
166
|
+
fi
|
|
167
|
+
shell: bash
|
|
168
|
+
- uses: actions/download-artifact@v8
|
|
169
|
+
with:
|
|
170
|
+
# merge every wheels-* artifact into a single flat dist/ directory
|
|
171
|
+
pattern: wheels-*
|
|
172
|
+
path: dist
|
|
173
|
+
merge-multiple: true
|
|
174
|
+
- name: List distributions
|
|
175
|
+
run: ls -R dist
|
|
176
|
+
- name: Publish
|
|
177
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
178
|
+
with:
|
|
179
|
+
packages-dir: dist
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Python
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
CARGO_TERM_COLOR: always
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: build + pytest (${{ matrix.os }})
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
20
|
+
defaults:
|
|
21
|
+
run:
|
|
22
|
+
working-directory: python
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
|
+
- uses: actions/setup-python@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.x"
|
|
28
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
29
|
+
- uses: Swatinem/rust-cache@v2
|
|
30
|
+
with:
|
|
31
|
+
workspaces: ". -> target"
|
|
32
|
+
# `pip install .` drives the maturin build backend (builds + installs the
|
|
33
|
+
# abi3 wheel into the CI interpreter), then run the smoke tests.
|
|
34
|
+
- run: python -m pip install --upgrade pip
|
|
35
|
+
- run: pip install . pytest
|
|
36
|
+
- run: pytest tests -q
|
|
37
|
+
|
|
38
|
+
wheels:
|
|
39
|
+
name: build wheels (${{ matrix.os }})
|
|
40
|
+
runs-on: ${{ matrix.os }}
|
|
41
|
+
strategy:
|
|
42
|
+
fail-fast: false
|
|
43
|
+
matrix:
|
|
44
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v7
|
|
47
|
+
- uses: PyO3/maturin-action@v1
|
|
48
|
+
with:
|
|
49
|
+
command: build
|
|
50
|
+
args: --release --out dist --manifest-path python/Cargo.toml
|
|
51
|
+
manylinux: auto
|
|
52
|
+
- uses: actions/upload-artifact@v7
|
|
53
|
+
with:
|
|
54
|
+
name: wheels-${{ matrix.os }}
|
|
55
|
+
path: dist
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Build artifacts
|
|
2
|
+
/target
|
|
3
|
+
|
|
4
|
+
# rustfmt backups
|
|
5
|
+
**/*.rs.bk
|
|
6
|
+
.env
|
|
7
|
+
.mcp.json
|
|
8
|
+
|
|
9
|
+
# Large browser captures the wire format was reverse-engineered from
|
|
10
|
+
*.har
|
|
11
|
+
|
|
12
|
+
# Reverse-engineering artifact (downloaded Castle bundle)
|
|
13
|
+
/bundle.js
|
|
14
|
+
|
|
15
|
+
# Python binding build artifacts
|
|
16
|
+
__pycache__/
|
|
17
|
+
*.pyc
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
*.so
|
|
20
|
+
dist/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
.venv/
|
|
23
|
+
|
|
24
|
+
# Node binding build artifacts (the per-platform .node is built, not committed;
|
|
25
|
+
# the generated index.js / index.d.ts loader + types ARE committed)
|
|
26
|
+
node_modules/
|
|
27
|
+
*.node
|