Releasing and maintaining packages
The repository publishes two distributions at the same version:
| Distribution | Contents | Runtime requirements |
|---|---|---|
acadsharp |
Python interface, API catalog, managed assembly and interop adapter, XML reference, licenses | Python 3.11+; install [managed] and .NET 10 for Python.NET |
acadsharp-native |
Platform-specific NativeAOT shared library and licenses | Python 3.11+ and supported native platform; no .NET installation |
The universal managed wheel is built from the source distribution, which includes the recursive ACadSharp and CSUtilities source trees. Neither source builds nor package installation download a .NET SDK. Source builds require an already installed .NET 10 SDK. CI explicitly provisions its build toolchain.
Local verification
git submodule update --init --recursive
python -m pip install -e '.[dev,docs]'
python scripts/build_managed.py
python scripts/generate_api.py --assembly src/acadsharp/_managed/ACadSharp.dll --check
python -m pytest tests --ignore=tests/test_native.py
python -m ruff check src tests scripts setup.py packaging
python -m mkdocs build --strict
python -m build
python -m twine check --strict dist/*
python scripts/check_dist.py dist
python -m build creates the source archive first, extracts it into an isolated
temporary directory, and builds the wheel there. This verifies the source
distribution is sufficient without the original Git checkout or its submodules.
check_dist.py checks the assembly, XML docs, runtime configuration, type catalog,
upstream source inputs and licenses, and rejects generated build directories or
Git metadata in the source archive.
To build the native companion locally, select your runtime identifier:
linux-x64, linux-arm64, osx-x64, osx-arm64, or win-x64. Local
osx-x64 builds remain available for Intel Macs; the 0.1.0 hosted CI and release
wheel matrix includes Apple Silicon only on macOS.
python scripts/build_native.py --rid osx-arm64
ACADSHARP_NATIVE_DIR="$PWD/artifacts/native/osx-arm64" \
python -m build --wheel --outdir dist-native packaging/native
In PowerShell, set $env:ACADSHARP_NATIVE_DIR to the absolute artifact directory
before running the wheel command. NativeAOT requires the platform C/C++ toolchain:
Xcode Command Line Tools on macOS, Visual Studio C++ tools on Windows, or Clang and
zlib development headers on Linux. Native wheels have a py3-none-<platform> tag;
they use a C ABI through ctypes and do not depend on a CPython extension ABI.
The companion has no separate source archive; build it from the main project's
complete source archive or recursive checkout.
Continuous integration
ci.yml invokes reusable build.yml for branches and pull requests. It:
- Builds and audits the managed wheel and source archive.
- Installs the built wheel on Ubuntu, Windows, and macOS under Python 3.11–3.14.
- Builds native wheels for Linux x64/Arm64, macOS Arm64 (Apple Silicon), and Windows x64.
- Builds Linux binaries inside the official
manylinux_2_28images and runsauditwheel repairto inspect and package their ELF dependencies. - Tests each installed native wheel without Python.NET installed.
- Checks lint, generated API reference consistency, and documentation links.
Intel macOS is omitted from hosted CI and has no prebuilt native wheel in 0.1.0.
Intel Mac users can install acadsharp[managed] or build the native companion
locally with --rid osx-x64. Linux x64 and Windows x64 remain in the release matrix.
Native builds run on the corresponding CPU architecture. The Linux wheel's manylinux tag declares its actual glibc compatibility; Linux musl/Alpine and Windows Arm64 wheels are not currently published. macOS wheel tags are derived from the shared library's Mach-O deployment target; the filename declares that requirement independently of the Python interpreter used to build the wheel.
One-time service configuration
An owner must configure external services before the first public release:
- Create the four GitHub environments listed below. Add the repository's chosen release protection rules to both production environments.
- On each package index, create a pending Trusted Publisher for each project
with owner
wieslawsoltes, repositoryACadSharp.Python, workflowrelease.yml, and the project's exact environment from this table. For existing projects, add the publisher in the project's publishing settings. Package names must be available or owned by the publishing account. - In GitHub Settings → Pages, select GitHub Actions as the build source.
The
docs.ymlworkflow deploys the rendered site through thegithub-pagesenvironment on main, version tags, or manual dispatch.
| Project | PyPI environment | TestPyPI environment | Downloaded release artifacts |
|---|---|---|---|
acadsharp |
pypi |
testpypi |
distributions-managed (wheel and source archive) |
acadsharp-native |
pypi-native |
testpypi-native |
distributions-native-* (native wheels) |
PyPI rejects a second pending publisher with an identical owner, repository,
workflow and environment for a different project name. The separate environments
make each pending publishing identity unique while allowing both packages to use
release.yml. Registering acadsharp-native with pypi instead of pypi-native
will collide with the pending acadsharp publisher. Apply the same separation
when configuring TestPyPI.
The publish job runs once per project. Each run downloads only that project's artifact group and checks its distribution filename prefix before upload. The GitHub release waits for both publishing runs to succeed and attaches all built distributions.
On 2026-10-15, both production PyPI pending publishers were verified with the project/environment mapping above. All four GitHub publishing environments and the GitHub Pages workflow source are configured. These registrations authorize the matching workflow identities; package publication still requires a successful release run.
TestPyPI publisher registration has not been verified. Before a rehearsal,
configure both TestPyPI projects with their respective testpypi and
testpypi-native environments. GitHub environment creation alone does not grant
permission to publish on either package index.
Trusted Publishing exchanges GitHub's short-lived OIDC identity for an upload credential. No PyPI API token belongs in the repository or its secrets. See PyPI's Trusted Publishing guide and adding a publisher.
Cut a release
Before the first manual workflow run, merge the reviewed implementation branch
into the repository's default branch. GitHub only enables workflow_dispatch
for workflows that exist on the default branch; after that initial merge, a
manual run can select a release branch or tag. This applies to both release.yml
and docs.yml. Keeping the implementation on its feature branch does not
publish a package or deploy documentation.
See GitHub's manual workflow prerequisites.
- Update the version in
pyproject.toml,packaging/native/pyproject.toml, both Python__version__values, and the exact native/base dependency pins, and theVersioninmanaged/ACadSharp.Python/ACadSharp.Python.csproj. Add the release's changes to the changelog. - If updating ACadSharp, commit both recursive submodule revisions, update
upstream-versions.json, rebuild, and regenerate the API reference. Review the upstream version's supported CAD formats and any changed public types. - Complete local checks and CI, then create the exact
v<version>tag on the reviewed release commit.check_release.pyrejects a mismatching tag or pin. - To rehearse without publishing to PyPI, manually dispatch
release.ymlfrom the release branch withindex=testpypi. TestPyPI accepts a branch build; production requires the matching version tag. Use a fresh version if that filename already exists on TestPyPI. - Pushing a version tag triggers a fresh complete build and test run. After the
pypiandpypi-nativeenvironments permit their respective publishing runs, each run uploads its package with attestations. Once both succeed, the workflow creates a GitHub release containing all exact distributions.
Be aware that pushing any v* tag automatically requests a production release;
manual testpypi dispatch does not cancel that trigger. Rehearse from a branch
before pushing the version tag.
Package indexes do not permit replacing a published filename; fix a bad release
with a new version. A failed partial upload can be recovered by uploading only
the missing, already verified artifacts after inspecting the index contents.
Provenance and licenses
The managed assembly's build-info.json records its target framework, content
hash of source inputs, and ACadSharp/CSUtilities revisions. The release source
archive retains those revisions in upstream-versions.json. Upstream sources
remain pinned Git submodules in the repository. Dependency update pull requests
must regenerate the reference and pass the same test suite as a release.
Both distributions carry the upstream MIT license texts. The native companion also carries the .NET runtime license and third-party notices because NativeAOT embeds runtime components. These files are required by the native wheel builder.