diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a5a6cc6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,172 @@ +name: Release + +on: + workflow_dispatch: + push: + tags: + - "v*" + +permissions: + contents: read + +jobs: + validate: + name: Validate release ref + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Validate trigger and version + shell: bash + run: | + set -euo pipefail + + if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then + if [[ "${GITHUB_REF}" != "refs/heads/main" ]]; then + echo "Manual TestPyPI releases must be run from the main branch." >&2 + exit 1 + fi + exit 0 + fi + + if [[ "${GITHUB_EVENT_NAME}" != "push" || "${GITHUB_REF}" != refs/tags/v* ]]; then + echo "PyPI releases must be triggered by a v* tag push." >&2 + exit 1 + fi + + project_version="$(python - <<'PY' + import tomllib + + with open("pyproject.toml", "rb") as pyproject: + print(tomllib.load(pyproject)["tool"]["poetry"]["version"]) + PY + )" + tag_version="${GITHUB_REF_NAME#v}" + + if [[ "${project_version}" != "${tag_version}" ]]; then + echo "Tag version ${tag_version} does not match pyproject.toml version ${project_version}." >&2 + exit 1 + fi + + build-sdist: + name: Build sdist + needs: validate + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: recursive + persist-credentials: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + + - name: Install build tooling + run: python -m pip install --upgrade pip build + + - name: Build sdist + run: python -m build --sdist --outdir dist + + - name: Upload sdist + uses: actions/upload-artifact@v7 + with: + name: release-sdist + path: dist/*.tar.gz + + build-wheels: + name: Build wheels on ${{ matrix.os }} + needs: validate + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ macos-latest, windows-latest ] + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: recursive + persist-credentials: false + + - name: Build wheels + uses: pypa/cibuildwheel@v3.4.1 + + - name: Upload wheels + uses: actions/upload-artifact@v7 + with: + name: release-wheels-${{ matrix.os }} + path: wheelhouse/*.whl + + check-distributions: + name: Check distributions + needs: [ build-sdist, build-wheels ] + runs-on: ubuntu-latest + + steps: + - name: Download distributions + uses: actions/download-artifact@v7 + with: + pattern: release-* + path: dist + merge-multiple: true + + - name: Install validation tooling + run: python -m pip install --upgrade pip twine + + - name: Check distribution metadata + run: python -m twine check dist/* + + publish-testpypi: + name: Publish to TestPyPI + needs: check-distributions + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + environment: + name: testpypi + url: https://test.pypi.org/p/pysatl-core + permissions: + id-token: write + + steps: + - name: Download distributions + uses: actions/download-artifact@v7 + with: + pattern: release-* + path: dist + merge-multiple: true + + - name: Publish package distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + + publish-pypi: + name: Publish to PyPI + needs: check-distributions + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/pysatl-core + permissions: + id-token: write + + steps: + - name: Download distributions + uses: actions/download-artifact@v7 + with: + pattern: release-* + path: dist + merge-multiple: true + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/README.md b/README.md index e2a0cdb..a7e4910 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ The library is designed as a **foundational kernel** rather than a ready-to-use > **Project status** > PySATL Core is currently in **early alpha**. -> It is not published to PyPI yet. After the first alpha release, the package -> will be installable with `pip install pysatl-core`. +> The public API may change between alpha releases. --- @@ -51,13 +50,16 @@ The library is designed as a **foundational kernel** rather than a ready-to-use ## Installation -After the first PyPI release: +Install from PyPI: ```bash pip install pysatl-core ``` -Until then, install from source. +Linux wheels are not published yet. On Linux, `pip` builds the package from the +source distribution and requires a working C toolchain. + +For development, install from source. Clone the repository: diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 0abf245..275ebd8 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -4,14 +4,13 @@ Changelog Unreleased ---------- +Version 0.1.0a0 (Alpha) - 2026-05-10 +------------------------------------ + * Prepared package metadata for the first alpha publication. * Added package build, wheel installation, and binary extension smoke checks. * Switched the UNU.RAN binding build to compile vendored sources into the CFFI extension. - -Version 0.0.1a0 (Alpha, planned) ---------------------------------- - * Initial release with core functionality * Basic distribution framework * Family system for parametric distributions diff --git a/docs/source/user_guide/installation.rst b/docs/source/user_guide/installation.rst index 9d308bb..9014ebf 100644 --- a/docs/source/user_guide/installation.rst +++ b/docs/source/user_guide/installation.rst @@ -3,20 +3,20 @@ Installation .. note:: - PySATL Core is currently in an early alpha stage and is not published to - PyPI yet. After the first alpha release, the package will be installable with - ``pip install pysatl-core``. + PySATL Core is currently in an early alpha stage. The public API may change + between alpha releases. From PyPI --------- -After the first release, install the package with: +Install the package with: .. code-block:: bash pip install pysatl-core -Until then, use a source checkout. +Linux wheels are not published yet. On Linux, ``pip`` builds the package from +the source distribution and requires a working C toolchain. Clone the repository -------------------- diff --git a/pyproject.toml b/pyproject.toml index 9234230..4f9c769 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ requires = [ [tool.poetry] name = "pysatl-core" -version = "0.0.1a0" +version = "0.1.0a0" description = "Computation core for PySATL" readme = "README.md" license = "MIT"