holder-kit 0.0.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.
- holder_kit-0.0.1/.github/actions/core-sdk/action.yml +21 -0
- holder_kit-0.0.1/.github/workflows/ci.yml +325 -0
- holder_kit-0.0.1/.github/workflows/launchpad.yml +79 -0
- holder_kit-0.0.1/.github/workflows/release.yml +243 -0
- holder_kit-0.0.1/.github/workflows/ubuntu-packages.yml +47 -0
- holder_kit-0.0.1/.gitignore +10 -0
- holder_kit-0.0.1/CMakeLists.txt +93 -0
- holder_kit-0.0.1/LICENSE +674 -0
- holder_kit-0.0.1/PKG-INFO +118 -0
- holder_kit-0.0.1/README.md +96 -0
- holder_kit-0.0.1/core-source.json +4 -0
- holder_kit-0.0.1/docs/building.md +171 -0
- holder_kit-0.0.1/docs/development.md +128 -0
- holder_kit-0.0.1/docs/packaging.md +184 -0
- holder_kit-0.0.1/docs/record-contracts.md +312 -0
- holder_kit-0.0.1/docs/walkthrough.md +125 -0
- holder_kit-0.0.1/docs/workflow.png +0 -0
- holder_kit-0.0.1/examples/card_lifecycle.py +34 -0
- holder_kit-0.0.1/examples/detached_records.py +27 -0
- holder_kit-0.0.1/examples/graph_analysis.py +27 -0
- holder_kit-0.0.1/examples/milestone_analysis.py +31 -0
- holder_kit-0.0.1/examples/pandas_analysis.py +44 -0
- holder_kit-0.0.1/examples/tag_analysis.py +25 -0
- holder_kit-0.0.1/make.sh +26 -0
- holder_kit-0.0.1/packaging/linux/debian/changelog +6 -0
- holder_kit-0.0.1/packaging/linux/debian/control +25 -0
- holder_kit-0.0.1/packaging/linux/debian/copyright +13 -0
- holder_kit-0.0.1/packaging/linux/debian/rules +19 -0
- holder_kit-0.0.1/packaging/linux/debian/source/format +1 -0
- holder_kit-0.0.1/pyproject.toml +32 -0
- holder_kit-0.0.1/release-core.json +5 -0
- holder_kit-0.0.1/scripts/__init__.py +1 -0
- holder_kit-0.0.1/scripts/check-release-distributions.py +57 -0
- holder_kit-0.0.1/scripts/configure-holder-ppa.sh +14 -0
- holder_kit-0.0.1/scripts/core-sdk.py +17 -0
- holder_kit-0.0.1/scripts/develop.py +437 -0
- holder_kit-0.0.1/scripts/prepare-debian-source.py +54 -0
- holder_kit-0.0.1/scripts/repair-linux-wheel.py +99 -0
- holder_kit-0.0.1/scripts/system-core-build-info.py +38 -0
- holder_kit-0.0.1/scripts/test-installed-debian.py +42 -0
- holder_kit-0.0.1/scripts/test-installed-wheel.py +48 -0
- holder_kit-0.0.1/scripts/ubuntu-package-ci.sh +40 -0
- holder_kit-0.0.1/scripts/wheel-notices.py +101 -0
- holder_kit-0.0.1/src/holderkit/__init__.py +195 -0
- holder_kit-0.0.1/src/holderkit/_native.pyi +52 -0
- holder_kit-0.0.1/src/holderkit/collections.py +304 -0
- holder_kit-0.0.1/src/holderkit/data/__init__.py +36 -0
- holder_kit-0.0.1/src/holderkit/data/card.py +166 -0
- holder_kit-0.0.1/src/holderkit/data/connection.py +28 -0
- holder_kit-0.0.1/src/holderkit/data/milestone.py +71 -0
- holder_kit-0.0.1/src/holderkit/data/project.py +96 -0
- holder_kit-0.0.1/src/holderkit/data/tag.py +38 -0
- holder_kit-0.0.1/src/holderkit/dataframe.py +63 -0
- holder_kit-0.0.1/src/holderkit/graph.py +43 -0
- holder_kit-0.0.1/src/holderkit/py.typed +0 -0
- holder_kit-0.0.1/src/native/module.c +868 -0
- holder_kit-0.0.1/tests/test_connections.py +80 -0
- holder_kit-0.0.1/tests/test_graph.py +102 -0
- holder_kit-0.0.1/tests/test_holder.py +252 -0
- holder_kit-0.0.1/tests/test_make.py +264 -0
- holder_kit-0.0.1/tests/test_milestones.py +234 -0
- holder_kit-0.0.1/tests/test_pandas.py +252 -0
- holder_kit-0.0.1/tests/test_tags.py +163 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Fetch core SDK
|
|
2
|
+
description: Use the run-wide immutable core selection and verify cached SDK archives
|
|
3
|
+
inputs:
|
|
4
|
+
commit:
|
|
5
|
+
description: Resolved core commit
|
|
6
|
+
required: true
|
|
7
|
+
build-type:
|
|
8
|
+
description: Core and shim build configuration
|
|
9
|
+
default: RelWithDebInfo
|
|
10
|
+
runs:
|
|
11
|
+
using: composite
|
|
12
|
+
steps:
|
|
13
|
+
- uses: HolderTeam/holder-core/.github/actions/core-sdk@main
|
|
14
|
+
with:
|
|
15
|
+
commit: ${{ inputs.commit }}
|
|
16
|
+
build-type: ${{ inputs.build-type }}
|
|
17
|
+
- name: Configure Python build tools
|
|
18
|
+
shell: bash
|
|
19
|
+
run: |
|
|
20
|
+
echo 'CMAKE_GENERATOR=Ninja' >> "$GITHUB_ENV"
|
|
21
|
+
echo "SKBUILD_CMAKE_BUILD_TYPE=$HOLDER_CORE_BUILD_TYPE" >> "$GITHUB_ENV"
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
inputs:
|
|
10
|
+
core_ref:
|
|
11
|
+
description: Core version tag or full commit SHA (empty selects latest-green)
|
|
12
|
+
required: false
|
|
13
|
+
type: string
|
|
14
|
+
workflow_call:
|
|
15
|
+
inputs:
|
|
16
|
+
core_ref:
|
|
17
|
+
description: Exact published core commit to test
|
|
18
|
+
required: true
|
|
19
|
+
type: string
|
|
20
|
+
kit_ref:
|
|
21
|
+
description: Holder Kit source revision (resolved once for all jobs)
|
|
22
|
+
default: main
|
|
23
|
+
type: string
|
|
24
|
+
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
core-sdk:
|
|
30
|
+
name: Resolve core SDK once
|
|
31
|
+
runs-on: ubuntu-24.04
|
|
32
|
+
outputs:
|
|
33
|
+
commit: ${{ steps.resolve.outputs.commit }}
|
|
34
|
+
kit_commit: ${{ steps.source.outputs.kit_commit }}
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v7
|
|
37
|
+
with:
|
|
38
|
+
repository: HolderTeam/holder-kit
|
|
39
|
+
ref: ${{ github.repository == 'HolderTeam/holder-kit' && github.sha || inputs.kit_ref || 'main' }}
|
|
40
|
+
persist-credentials: false
|
|
41
|
+
- id: source
|
|
42
|
+
name: Record Holder Kit source revision
|
|
43
|
+
shell: bash
|
|
44
|
+
run: echo "kit_commit=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
|
45
|
+
- uses: actions/setup-python@v7
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
- id: resolve
|
|
49
|
+
uses: HolderTeam/holder-core/.github/actions/core-sdk@main
|
|
50
|
+
with:
|
|
51
|
+
command: resolve
|
|
52
|
+
core-ref: ${{ inputs.core_ref || 'latest-green' }}
|
|
53
|
+
|
|
54
|
+
linux:
|
|
55
|
+
needs: core-sdk
|
|
56
|
+
name: ${{ matrix.name }}
|
|
57
|
+
runs-on: ${{ matrix.runner }}
|
|
58
|
+
timeout-minutes: 45
|
|
59
|
+
strategy:
|
|
60
|
+
fail-fast: false
|
|
61
|
+
matrix:
|
|
62
|
+
include:
|
|
63
|
+
- runner: ubuntu-24.04
|
|
64
|
+
name: Ubuntu 24.04 / Python 3.12 / compatibility
|
|
65
|
+
python-version: "3.12"
|
|
66
|
+
comprehensive: true
|
|
67
|
+
sanitized: false
|
|
68
|
+
# Use the canonical SDK's distribution dependency ABI. Native
|
|
69
|
+
# Ubuntu-series integration belongs to the Debian package builds.
|
|
70
|
+
- runner: ubuntu-24.04
|
|
71
|
+
name: Ubuntu 24.04 / Python 3.14 / shim sanitizers
|
|
72
|
+
python-version: "3.14"
|
|
73
|
+
comprehensive: false
|
|
74
|
+
sanitized: true
|
|
75
|
+
|
|
76
|
+
steps:
|
|
77
|
+
- name: Check out Holder Kit
|
|
78
|
+
uses: actions/checkout@v7
|
|
79
|
+
with:
|
|
80
|
+
repository: HolderTeam/holder-kit
|
|
81
|
+
ref: ${{ needs.core-sdk.outputs.kit_commit }}
|
|
82
|
+
persist-credentials: false
|
|
83
|
+
|
|
84
|
+
- name: Fetch verified core SDK
|
|
85
|
+
uses: ./.github/actions/core-sdk
|
|
86
|
+
with:
|
|
87
|
+
commit: ${{ needs.core-sdk.outputs.commit }}
|
|
88
|
+
|
|
89
|
+
- name: Install native build dependencies
|
|
90
|
+
run: |
|
|
91
|
+
sudo apt-get update
|
|
92
|
+
sudo apt-get install -y --no-install-recommends \
|
|
93
|
+
build-essential \
|
|
94
|
+
cmake \
|
|
95
|
+
ninja-build \
|
|
96
|
+
pkg-config \
|
|
97
|
+
python3-dev \
|
|
98
|
+
python3-venv \
|
|
99
|
+
libssl-dev \
|
|
100
|
+
nlohmann-json3-dev \
|
|
101
|
+
libyaml-cpp-dev \
|
|
102
|
+
libspdlog-dev \
|
|
103
|
+
libsqlite3-dev \
|
|
104
|
+
libsodium-dev \
|
|
105
|
+
libgit2-dev \
|
|
106
|
+
libmd4c-dev \
|
|
107
|
+
libsecret-1-dev
|
|
108
|
+
|
|
109
|
+
- name: Set up selected Python
|
|
110
|
+
uses: actions/setup-python@v7
|
|
111
|
+
with:
|
|
112
|
+
python-version: ${{ matrix.python-version }}
|
|
113
|
+
|
|
114
|
+
- name: Create isolated CI environment
|
|
115
|
+
run: |
|
|
116
|
+
python3 -m venv "${RUNNER_TEMP}/holder-ci-venv"
|
|
117
|
+
echo "${RUNNER_TEMP}/holder-ci-venv/bin" >> "${GITHUB_PATH}"
|
|
118
|
+
|
|
119
|
+
- name: Install packaging tools
|
|
120
|
+
run: python3 -m pip install --upgrade pip
|
|
121
|
+
|
|
122
|
+
- name: Build and install Holder Kit with complete test dependencies
|
|
123
|
+
if: ${{ matrix.comprehensive }}
|
|
124
|
+
run: python3 -m pip install --verbose '.[test]'
|
|
125
|
+
|
|
126
|
+
- name: Build instrumented Holder Kit for lifecycle smoke tests
|
|
127
|
+
if: ${{ matrix.sanitized }}
|
|
128
|
+
run: python3 -m pip install --verbose --config-settings=cmake.define.HOLDER_KIT_SANITIZE=address,undefined . 'pytest>=8'
|
|
129
|
+
|
|
130
|
+
- name: Configure sanitizer runtime
|
|
131
|
+
if: ${{ matrix.sanitized }}
|
|
132
|
+
run: |
|
|
133
|
+
asan_library="$(gcc -print-file-name=libasan.so)"
|
|
134
|
+
if ! file -L "${asan_library}" | grep -q 'ELF'; then
|
|
135
|
+
asan_library="$(ldconfig -p | awk '/libasan\.so/{print $NF; exit}')"
|
|
136
|
+
fi
|
|
137
|
+
test -f "${asan_library}"
|
|
138
|
+
echo "LD_PRELOAD=${asan_library}" >> "${GITHUB_ENV}"
|
|
139
|
+
echo "ASAN_OPTIONS=detect_leaks=0:halt_on_error=1" >> "${GITHUB_ENV}"
|
|
140
|
+
echo "UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1" >> "${GITHUB_ENV}"
|
|
141
|
+
|
|
142
|
+
- name: Show installed build
|
|
143
|
+
run: |
|
|
144
|
+
python3 --version
|
|
145
|
+
python3 -c 'import sys; print(sys.executable)'
|
|
146
|
+
python3 -m pip show holder-kit
|
|
147
|
+
python3 -c 'import holderkit; print(holderkit.__file__)'
|
|
148
|
+
|
|
149
|
+
- name: Run instrumented Python lifecycle smoke tests
|
|
150
|
+
if: ${{ matrix.sanitized }}
|
|
151
|
+
run: |
|
|
152
|
+
python3 -m pytest --verbose \
|
|
153
|
+
tests/test_holder.py::test_native_extension_imports \
|
|
154
|
+
tests/test_holder.py::test_complete_card_lifecycle \
|
|
155
|
+
tests/test_holder.py::test_context_destruction_releases_native_resources
|
|
156
|
+
|
|
157
|
+
- name: Run complete Python tests
|
|
158
|
+
if: ${{ matrix.comprehensive }}
|
|
159
|
+
run: python3 -m pytest --verbose
|
|
160
|
+
|
|
161
|
+
- name: Run strict type checking
|
|
162
|
+
if: ${{ matrix.comprehensive }}
|
|
163
|
+
run: python3 -m mypy
|
|
164
|
+
|
|
165
|
+
- name: Run lifecycle example
|
|
166
|
+
run: python3 examples/card_lifecycle.py
|
|
167
|
+
|
|
168
|
+
- name: Run detached-record and pandas examples
|
|
169
|
+
if: ${{ matrix.comprehensive }}
|
|
170
|
+
run: |
|
|
171
|
+
python3 examples/detached_records.py
|
|
172
|
+
python3 examples/pandas_analysis.py
|
|
173
|
+
|
|
174
|
+
- name: Build wheel
|
|
175
|
+
if: ${{ matrix.comprehensive }}
|
|
176
|
+
run: |
|
|
177
|
+
python3 -m pip install build
|
|
178
|
+
python3 -m build --wheel --outdir dist
|
|
179
|
+
ls -lh dist
|
|
180
|
+
|
|
181
|
+
- name: Install wheel in a fresh base environment
|
|
182
|
+
if: ${{ matrix.comprehensive }}
|
|
183
|
+
run: |
|
|
184
|
+
python3 -m venv "${RUNNER_TEMP}/holder-wheel-venv"
|
|
185
|
+
"${RUNNER_TEMP}/holder-wheel-venv/bin/python" -m pip install --upgrade pip
|
|
186
|
+
"${RUNNER_TEMP}/holder-wheel-venv/bin/python" -m pip install --verbose dist/*.whl
|
|
187
|
+
|
|
188
|
+
- name: Smoke-test installed wheel without pandas
|
|
189
|
+
if: ${{ matrix.comprehensive }}
|
|
190
|
+
run: |
|
|
191
|
+
"${RUNNER_TEMP}/holder-wheel-venv/bin/python" - <<'PY'
|
|
192
|
+
import importlib.util
|
|
193
|
+
import json
|
|
194
|
+
from importlib.metadata import distribution
|
|
195
|
+
from importlib.resources import files
|
|
196
|
+
import sys
|
|
197
|
+
import tempfile
|
|
198
|
+
from pathlib import Path
|
|
199
|
+
|
|
200
|
+
assert importlib.util.find_spec("pandas") is None
|
|
201
|
+
|
|
202
|
+
import holderkit
|
|
203
|
+
from holderkit import _native
|
|
204
|
+
|
|
205
|
+
installed = distribution("holder-kit")
|
|
206
|
+
assert installed.metadata["Name"] == "holder-kit"
|
|
207
|
+
assert installed.files is not None
|
|
208
|
+
assert all(path.parts[0] != "holder" for path in installed.files)
|
|
209
|
+
assert importlib.util.find_spec("holder") is None
|
|
210
|
+
assert _native.__name__ == "holderkit._native"
|
|
211
|
+
assert _native.Context.__module__ == "holderkit._native"
|
|
212
|
+
assert holderkit.HolderError.__module__ == "holderkit._native"
|
|
213
|
+
resources = files("holderkit")
|
|
214
|
+
assert resources.joinpath("py.typed").is_file()
|
|
215
|
+
assert resources.joinpath("_schema.sql").read_text(encoding="utf-8")
|
|
216
|
+
assert json.loads(resources.joinpath("_core_build.json").read_text(encoding="utf-8"))
|
|
217
|
+
|
|
218
|
+
assert "pandas" not in sys.modules
|
|
219
|
+
with tempfile.TemporaryDirectory(prefix="holder-wheel-smoke-") as temporary:
|
|
220
|
+
with holderkit.open(Path(temporary) / "data") as context:
|
|
221
|
+
project = context.create_project("Wheel smoke test")
|
|
222
|
+
card = context.create_card(
|
|
223
|
+
project.project_id, "Installed wheel", "standalone body"
|
|
224
|
+
)
|
|
225
|
+
assert context.get_card_content(card.card_id) == "standalone body"
|
|
226
|
+
assert context.cards.to_records(project.project_id)[0]["card_id"] == card.card_id
|
|
227
|
+
try:
|
|
228
|
+
context.cards.to_dataframe(project.project_id)
|
|
229
|
+
except ModuleNotFoundError as error:
|
|
230
|
+
assert "holder-kit[pandas]" in str(error)
|
|
231
|
+
else:
|
|
232
|
+
raise AssertionError("base wheel unexpectedly provided pandas")
|
|
233
|
+
PY
|
|
234
|
+
|
|
235
|
+
macos:
|
|
236
|
+
needs: core-sdk
|
|
237
|
+
name: macOS 15 / Python 3.12
|
|
238
|
+
runs-on: macos-15
|
|
239
|
+
timeout-minutes: 30
|
|
240
|
+
|
|
241
|
+
steps:
|
|
242
|
+
- name: Check out Holder Kit
|
|
243
|
+
uses: actions/checkout@v7
|
|
244
|
+
with:
|
|
245
|
+
repository: HolderTeam/holder-kit
|
|
246
|
+
ref: ${{ needs.core-sdk.outputs.kit_commit }}
|
|
247
|
+
persist-credentials: false
|
|
248
|
+
|
|
249
|
+
- name: Set up Python 3.12
|
|
250
|
+
uses: actions/setup-python@v7
|
|
251
|
+
with:
|
|
252
|
+
python-version: "3.12"
|
|
253
|
+
|
|
254
|
+
- name: Fetch verified core SDK
|
|
255
|
+
uses: ./.github/actions/core-sdk
|
|
256
|
+
with:
|
|
257
|
+
commit: ${{ needs.core-sdk.outputs.commit }}
|
|
258
|
+
|
|
259
|
+
- name: Install native build dependencies
|
|
260
|
+
run: |
|
|
261
|
+
brew install \
|
|
262
|
+
cmake \
|
|
263
|
+
ninja \
|
|
264
|
+
pkg-config \
|
|
265
|
+
nlohmann-json \
|
|
266
|
+
yaml-cpp \
|
|
267
|
+
spdlog \
|
|
268
|
+
sqlite \
|
|
269
|
+
libsodium \
|
|
270
|
+
libgit2 \
|
|
271
|
+
md4c \
|
|
272
|
+
openssl@3
|
|
273
|
+
|
|
274
|
+
- name: Build and install Holder Kit
|
|
275
|
+
run: |
|
|
276
|
+
python3 -m pip install --upgrade pip
|
|
277
|
+
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_PREFIX_PATH=$(brew --prefix);$(brew --prefix openssl@3) -DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" \
|
|
278
|
+
python3 -m pip install --verbose . 'pytest>=8'
|
|
279
|
+
|
|
280
|
+
- name: Run base Python tests
|
|
281
|
+
run: python3 -m pytest --verbose tests/test_holder.py
|
|
282
|
+
|
|
283
|
+
- name: Run lifecycle example
|
|
284
|
+
run: python3 examples/card_lifecycle.py
|
|
285
|
+
|
|
286
|
+
windows:
|
|
287
|
+
needs: core-sdk
|
|
288
|
+
name: Windows Server 2025 / Python 3.12
|
|
289
|
+
runs-on: windows-2025
|
|
290
|
+
timeout-minutes: 45
|
|
291
|
+
|
|
292
|
+
steps:
|
|
293
|
+
- name: Check out Holder Kit
|
|
294
|
+
uses: actions/checkout@v7
|
|
295
|
+
with:
|
|
296
|
+
repository: HolderTeam/holder-kit
|
|
297
|
+
ref: ${{ needs.core-sdk.outputs.kit_commit }}
|
|
298
|
+
persist-credentials: false
|
|
299
|
+
|
|
300
|
+
- name: Set up Python 3.12
|
|
301
|
+
uses: actions/setup-python@v7
|
|
302
|
+
with:
|
|
303
|
+
python-version: "3.12"
|
|
304
|
+
|
|
305
|
+
- name: Set up MSVC developer environment
|
|
306
|
+
uses: ilammy/msvc-dev-cmd@v1
|
|
307
|
+
|
|
308
|
+
- name: Fetch verified core SDK
|
|
309
|
+
uses: ./.github/actions/core-sdk
|
|
310
|
+
with:
|
|
311
|
+
commit: ${{ needs.core-sdk.outputs.commit }}
|
|
312
|
+
|
|
313
|
+
- name: Build and install Holder Kit
|
|
314
|
+
run: |
|
|
315
|
+
python -m pip install --upgrade pip
|
|
316
|
+
python -m pip install --verbose . "pytest>=8"
|
|
317
|
+
|
|
318
|
+
- name: Verify native extension and bundled runtime dependencies
|
|
319
|
+
run: python -c "import holderkit; print(holderkit.__file__)"
|
|
320
|
+
|
|
321
|
+
- name: Run base Python tests
|
|
322
|
+
run: python -m pytest --verbose tests/test_holder.py
|
|
323
|
+
|
|
324
|
+
- name: Run lifecycle example
|
|
325
|
+
run: python examples/card_lifecycle.py
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: Prepare Holder Kit Launchpad packages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: Expected pyproject.toml version
|
|
8
|
+
required: true
|
|
9
|
+
default: '0.0.1'
|
|
10
|
+
package_revision:
|
|
11
|
+
description: Debian revision (increment for each replacement upload)
|
|
12
|
+
required: true
|
|
13
|
+
default: '1'
|
|
14
|
+
core_package_version:
|
|
15
|
+
description: Exact core package version before the Ubuntu suffix
|
|
16
|
+
required: true
|
|
17
|
+
default: '0.2.0-1'
|
|
18
|
+
upload:
|
|
19
|
+
description: Sign and upload the source candidates to the Holder PPA
|
|
20
|
+
type: boolean
|
|
21
|
+
default: false
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
source:
|
|
28
|
+
runs-on: ubuntu-24.04
|
|
29
|
+
strategy:
|
|
30
|
+
fail-fast: false
|
|
31
|
+
matrix:
|
|
32
|
+
series: [noble, resolute]
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v7
|
|
35
|
+
with:
|
|
36
|
+
persist-credentials: false
|
|
37
|
+
- name: Install source packaging tools
|
|
38
|
+
run: |
|
|
39
|
+
sudo apt-get update
|
|
40
|
+
sudo apt-get install -y --no-install-recommends devscripts debhelper dh-python dput gnupg
|
|
41
|
+
- name: Prepare pinned source candidate
|
|
42
|
+
env:
|
|
43
|
+
UPSTREAM_VERSION: ${{ inputs.version }}
|
|
44
|
+
PACKAGE_REVISION: ${{ inputs.package_revision }}
|
|
45
|
+
CORE_PACKAGE_VERSION: ${{ inputs.core_package_version }}
|
|
46
|
+
SERIES: ${{ matrix.series }}
|
|
47
|
+
run: |
|
|
48
|
+
python3 scripts/prepare-debian-source.py --version "$UPSTREAM_VERSION" \
|
|
49
|
+
--package-revision "$PACKAGE_REVISION" --series "$SERIES" \
|
|
50
|
+
--core-package-version "${CORE_PACKAGE_VERSION}~${SERIES}1"
|
|
51
|
+
debuild -S -d -us -uc
|
|
52
|
+
- name: Save source candidate
|
|
53
|
+
run: |
|
|
54
|
+
mkdir -p out/source
|
|
55
|
+
cp ../holder-kit_*.dsc ../holder-kit_*.tar.* \
|
|
56
|
+
../holder-kit_*_source.changes ../holder-kit_*_source.buildinfo out/source/
|
|
57
|
+
- uses: actions/upload-artifact@v7
|
|
58
|
+
with:
|
|
59
|
+
name: holder-kit-source-${{ matrix.series }}
|
|
60
|
+
path: out/source/*
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
- name: Sign source candidate
|
|
63
|
+
if: inputs.upload
|
|
64
|
+
env:
|
|
65
|
+
PPA_GPG_PRIVATE_KEY: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
|
66
|
+
run: |
|
|
67
|
+
test -n "$PPA_GPG_PRIVATE_KEY"
|
|
68
|
+
mkdir -p ~/.gnupg
|
|
69
|
+
chmod 700 ~/.gnupg
|
|
70
|
+
printf '%s\n' "$PPA_GPG_PRIVATE_KEY" | gpg --batch --import
|
|
71
|
+
keyid="$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ {print $5; exit}')"
|
|
72
|
+
test -n "$keyid"
|
|
73
|
+
printf 'batch\nyes\npinentry-mode loopback\n' > ~/.gnupg/gpg.conf
|
|
74
|
+
printf 'allow-loopback-pinentry\n' > ~/.gnupg/gpg-agent.conf
|
|
75
|
+
gpgconf --kill gpg-agent
|
|
76
|
+
debsign -k"$keyid" ../holder-kit_*_source.changes
|
|
77
|
+
- name: Upload source candidate
|
|
78
|
+
if: inputs.upload
|
|
79
|
+
run: dput ppa:holderteam/holder ../holder-kit_*_source.changes
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
name: Kit release wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- .github/workflows/release.yml
|
|
7
|
+
- .github/actions/core-sdk/**
|
|
8
|
+
- release-core.json
|
|
9
|
+
- pyproject.toml
|
|
10
|
+
- CMakeLists.txt
|
|
11
|
+
- src/**
|
|
12
|
+
- scripts/*wheel*.py
|
|
13
|
+
- scripts/check-release-distributions.py
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
inputs:
|
|
16
|
+
destination:
|
|
17
|
+
description: Build candidates, or publish a version tag after validation
|
|
18
|
+
type: choice
|
|
19
|
+
options: [none, testpypi, pypi]
|
|
20
|
+
default: none
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
prepare:
|
|
27
|
+
runs-on: ubuntu-24.04
|
|
28
|
+
outputs:
|
|
29
|
+
version: ${{ steps.config.outputs.version }}
|
|
30
|
+
core_commit: ${{ steps.config.outputs.core_commit }}
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v7
|
|
33
|
+
with:
|
|
34
|
+
persist-credentials: false
|
|
35
|
+
- uses: actions/setup-python@v7
|
|
36
|
+
with:
|
|
37
|
+
python-version: '3.12'
|
|
38
|
+
- id: config
|
|
39
|
+
env:
|
|
40
|
+
DESTINATION: ${{ inputs.destination || 'none' }}
|
|
41
|
+
run: |
|
|
42
|
+
python - <<'PY'
|
|
43
|
+
import json, os, re, tomllib
|
|
44
|
+
from pathlib import Path
|
|
45
|
+
version = tomllib.loads(Path('pyproject.toml').read_text())['project']['version']
|
|
46
|
+
pin = json.loads(Path('release-core.json').read_text())
|
|
47
|
+
assert pin['repository'] == 'HolderTeam/holder-core'
|
|
48
|
+
assert re.fullmatch(r'[0-9a-f]{40}', pin['commit'])
|
|
49
|
+
assert pin['build_type'] == 'Release'
|
|
50
|
+
if os.environ['DESTINATION'] != 'none':
|
|
51
|
+
assert os.environ['GITHUB_REF'] == f'refs/tags/v{version}', 'Publishing requires the matching version tag'
|
|
52
|
+
with open(os.environ['GITHUB_OUTPUT'], 'a') as output:
|
|
53
|
+
output.write(f'version={version}\ncore_commit={pin["commit"]}\n')
|
|
54
|
+
PY
|
|
55
|
+
- uses: HolderTeam/holder-core/.github/actions/core-sdk@main
|
|
56
|
+
with:
|
|
57
|
+
command: resolve
|
|
58
|
+
core-ref: ${{ steps.config.outputs.core_commit }}
|
|
59
|
+
|
|
60
|
+
wheels:
|
|
61
|
+
needs: prepare
|
|
62
|
+
runs-on: ${{ matrix.runner }}
|
|
63
|
+
timeout-minutes: 45
|
|
64
|
+
strategy:
|
|
65
|
+
fail-fast: false
|
|
66
|
+
matrix:
|
|
67
|
+
python: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
68
|
+
runner: [ubuntu-24.04, windows-2025, macos-15]
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v7
|
|
71
|
+
with:
|
|
72
|
+
persist-credentials: false
|
|
73
|
+
- uses: actions/setup-python@v7
|
|
74
|
+
with:
|
|
75
|
+
python-version: ${{ matrix.python }}
|
|
76
|
+
- uses: ilammy/msvc-dev-cmd@v1
|
|
77
|
+
if: runner.os == 'Windows'
|
|
78
|
+
- uses: ./.github/actions/core-sdk
|
|
79
|
+
with:
|
|
80
|
+
commit: ${{ needs.prepare.outputs.core_commit }}
|
|
81
|
+
build-type: Release
|
|
82
|
+
- name: Linux native dependencies
|
|
83
|
+
if: runner.os == 'Linux'
|
|
84
|
+
run: |
|
|
85
|
+
sudo apt-get update
|
|
86
|
+
sudo apt-get install -y --no-install-recommends build-essential cmake ninja-build pkg-config \
|
|
87
|
+
patchelf libssl-dev nlohmann-json3-dev libyaml-cpp-dev libspdlog-dev \
|
|
88
|
+
libsqlite3-dev libsodium-dev libgit2-dev libmd4c-dev libsecret-1-dev
|
|
89
|
+
- name: macOS native dependencies
|
|
90
|
+
if: runner.os == 'macOS'
|
|
91
|
+
run: |
|
|
92
|
+
brew install cmake ninja pkg-config nlohmann-json yaml-cpp spdlog sqlite \
|
|
93
|
+
libsodium libgit2 md4c openssl@3
|
|
94
|
+
echo 'MACOSX_DEPLOYMENT_TARGET=15.0' >> "$GITHUB_ENV"
|
|
95
|
+
echo "CMAKE_ARGS=$CMAKE_ARGS -DCMAKE_PREFIX_PATH=$(brew --prefix);$(brew --prefix openssl@3) -DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3) -DCMAKE_OSX_ARCHITECTURES=arm64" >> "$GITHUB_ENV"
|
|
96
|
+
- name: Build wheel
|
|
97
|
+
shell: bash
|
|
98
|
+
run: |
|
|
99
|
+
python -m pip install --upgrade pip
|
|
100
|
+
python -m pip install build wheel twine
|
|
101
|
+
python -m build --wheel --outdir out/raw
|
|
102
|
+
- name: Bundle Linux runtime and validate manylinux ABI
|
|
103
|
+
if: runner.os == 'Linux'
|
|
104
|
+
run: |
|
|
105
|
+
python -m pip install 'auditwheel==6.8.2'
|
|
106
|
+
python scripts/repair-linux-wheel.py --output dist out/raw/*.whl
|
|
107
|
+
- name: Bundle macOS runtime
|
|
108
|
+
if: runner.os == 'macOS'
|
|
109
|
+
run: |
|
|
110
|
+
python -m pip install delocate
|
|
111
|
+
python scripts/wheel-notices.py --output out/noticed out/raw/*.whl
|
|
112
|
+
delocate-wheel --require-archs arm64 -v -w dist out/noticed/*.whl
|
|
113
|
+
- name: Bundle Windows runtime
|
|
114
|
+
if: runner.os == 'Windows'
|
|
115
|
+
shell: bash
|
|
116
|
+
run: |
|
|
117
|
+
python -m pip install delvewheel
|
|
118
|
+
python scripts/wheel-notices.py --output out/noticed out/raw/*.whl
|
|
119
|
+
python -m delvewheel repair --add-path "$HOLDER_CORE_SDK/bin" -w dist out/noticed/*.whl
|
|
120
|
+
- name: Check distribution metadata
|
|
121
|
+
shell: bash
|
|
122
|
+
run: python -m twine check --strict dist/*.whl
|
|
123
|
+
- name: Install wheel in a new virtualenv
|
|
124
|
+
shell: bash
|
|
125
|
+
env:
|
|
126
|
+
CORE_COMMIT: ${{ needs.prepare.outputs.core_commit }}
|
|
127
|
+
KIT_VERSION: ${{ needs.prepare.outputs.version }}
|
|
128
|
+
run: |
|
|
129
|
+
python -m venv out/test-venv
|
|
130
|
+
if [ "$RUNNER_OS" = Windows ]; then
|
|
131
|
+
test_python=out/test-venv/Scripts/python.exe
|
|
132
|
+
else
|
|
133
|
+
test_python=out/test-venv/bin/python
|
|
134
|
+
fi
|
|
135
|
+
"$test_python" -m pip install --no-deps dist/*.whl
|
|
136
|
+
env -u HOLDER_CORE_SDK -u CMAKE_ARGS -u LD_LIBRARY_PATH -u DYLD_LIBRARY_PATH \
|
|
137
|
+
"$test_python" -I scripts/test-installed-wheel.py --core-commit "$CORE_COMMIT" --version "$KIT_VERSION"
|
|
138
|
+
"$test_python" -m pip install 'pytest>=8' pandas networkx
|
|
139
|
+
"$test_python" -I -m pytest -q --import-mode=importlib tests/test_holder.py \
|
|
140
|
+
tests/test_connections.py tests/test_graph.py tests/test_pandas.py
|
|
141
|
+
- name: Linux wheel in a clean Debian runtime
|
|
142
|
+
if: runner.os == 'Linux'
|
|
143
|
+
env:
|
|
144
|
+
PYTHON_VERSION: ${{ matrix.python }}
|
|
145
|
+
CORE_COMMIT: ${{ needs.prepare.outputs.core_commit }}
|
|
146
|
+
KIT_VERSION: ${{ needs.prepare.outputs.version }}
|
|
147
|
+
run: |
|
|
148
|
+
docker run --rm -v "$PWD:/source:ro" \
|
|
149
|
+
-e CORE_COMMIT -e KIT_VERSION "python:${PYTHON_VERSION}-slim-trixie" \
|
|
150
|
+
bash -c 'python -m venv /venv && /venv/bin/python -m pip install --no-deps /source/dist/*.whl && cd /tmp && /venv/bin/python -I /source/scripts/test-installed-wheel.py --core-commit "$CORE_COMMIT" --version "$KIT_VERSION"'
|
|
151
|
+
- uses: actions/upload-artifact@v7
|
|
152
|
+
with:
|
|
153
|
+
name: wheel-${{ matrix.runner }}-${{ matrix.python }}
|
|
154
|
+
path: dist/*.whl
|
|
155
|
+
if-no-files-found: error
|
|
156
|
+
|
|
157
|
+
sdist:
|
|
158
|
+
needs: prepare
|
|
159
|
+
runs-on: ubuntu-24.04
|
|
160
|
+
steps:
|
|
161
|
+
- uses: actions/checkout@v7
|
|
162
|
+
with:
|
|
163
|
+
persist-credentials: false
|
|
164
|
+
- uses: actions/setup-python@v7
|
|
165
|
+
with:
|
|
166
|
+
python-version: '3.12'
|
|
167
|
+
- run: |
|
|
168
|
+
python -m pip install build twine
|
|
169
|
+
python -m build --sdist --outdir dist
|
|
170
|
+
python -m twine check --strict dist/*.tar.gz
|
|
171
|
+
- uses: ./.github/actions/core-sdk
|
|
172
|
+
with:
|
|
173
|
+
commit: ${{ needs.prepare.outputs.core_commit }}
|
|
174
|
+
build-type: Release
|
|
175
|
+
- name: Build and install the source archive with the pinned SDK
|
|
176
|
+
env:
|
|
177
|
+
CORE_COMMIT: ${{ needs.prepare.outputs.core_commit }}
|
|
178
|
+
KIT_VERSION: ${{ needs.prepare.outputs.version }}
|
|
179
|
+
run: |
|
|
180
|
+
sudo apt-get update
|
|
181
|
+
sudo apt-get install -y --no-install-recommends build-essential cmake ninja-build pkg-config \
|
|
182
|
+
libssl-dev nlohmann-json3-dev libyaml-cpp-dev libspdlog-dev libsqlite3-dev \
|
|
183
|
+
libsodium-dev libgit2-dev libmd4c-dev libsecret-1-dev
|
|
184
|
+
python -m venv out/source-test
|
|
185
|
+
out/source-test/bin/python -m pip install --no-deps dist/*.tar.gz
|
|
186
|
+
out/source-test/bin/python -I scripts/test-installed-wheel.py --core-commit "$CORE_COMMIT" --version "$KIT_VERSION"
|
|
187
|
+
- uses: actions/upload-artifact@v7
|
|
188
|
+
with:
|
|
189
|
+
name: source-distribution
|
|
190
|
+
path: dist/*.tar.gz
|
|
191
|
+
if-no-files-found: error
|
|
192
|
+
|
|
193
|
+
distributions:
|
|
194
|
+
needs: [prepare, wheels, sdist]
|
|
195
|
+
runs-on: ubuntu-24.04
|
|
196
|
+
steps:
|
|
197
|
+
- uses: actions/checkout@v7
|
|
198
|
+
with:
|
|
199
|
+
persist-credentials: false
|
|
200
|
+
- uses: actions/setup-python@v7
|
|
201
|
+
with:
|
|
202
|
+
python-version: '3.12'
|
|
203
|
+
- uses: actions/download-artifact@v4
|
|
204
|
+
with:
|
|
205
|
+
pattern: wheel-*
|
|
206
|
+
path: dist
|
|
207
|
+
merge-multiple: true
|
|
208
|
+
- uses: actions/download-artifact@v4
|
|
209
|
+
with:
|
|
210
|
+
name: source-distribution
|
|
211
|
+
path: dist
|
|
212
|
+
- run: python scripts/check-release-distributions.py dist --manifest out/release-manifest.json
|
|
213
|
+
- uses: actions/upload-artifact@v7
|
|
214
|
+
with:
|
|
215
|
+
name: release-distributions
|
|
216
|
+
path: dist/*
|
|
217
|
+
if-no-files-found: error
|
|
218
|
+
- uses: actions/upload-artifact@v7
|
|
219
|
+
with:
|
|
220
|
+
name: release-manifest
|
|
221
|
+
path: out/release-manifest.json
|
|
222
|
+
|
|
223
|
+
publish:
|
|
224
|
+
if: github.event_name == 'workflow_dispatch' && inputs.destination != 'none'
|
|
225
|
+
needs: distributions
|
|
226
|
+
runs-on: ubuntu-24.04
|
|
227
|
+
environment: ${{ inputs.destination }}
|
|
228
|
+
permissions:
|
|
229
|
+
contents: read
|
|
230
|
+
id-token: write
|
|
231
|
+
steps:
|
|
232
|
+
- uses: actions/download-artifact@v4
|
|
233
|
+
with:
|
|
234
|
+
name: release-distributions
|
|
235
|
+
path: dist
|
|
236
|
+
- name: Publish to TestPyPI
|
|
237
|
+
if: inputs.destination == 'testpypi'
|
|
238
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
239
|
+
with:
|
|
240
|
+
repository-url: https://test.pypi.org/legacy/
|
|
241
|
+
- name: Publish to PyPI
|
|
242
|
+
if: inputs.destination == 'pypi'
|
|
243
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|