From 0c9c8becc867a663fa7ed474fde0cafebe396a33 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 13:17:23 +0100 Subject: [PATCH 01/15] Add first version of automatic deployment workflow --- .github/workflows/publish_version.yml | 126 ++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .github/workflows/publish_version.yml diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml new file mode 100644 index 0000000..4bef822 --- /dev/null +++ b/.github/workflows/publish_version.yml @@ -0,0 +1,126 @@ +name: Publish to PyPI + +on: + workflow_dispatch: + inputs: + repository: + description: "Target index" + type: choice + options: [pypi, testpypi] + default: testpypi + ref: + description: "Git ref to build (branch/tag/SHA). Leave empty to use the UI-selected ref." + required: false + default: "" + +concurrency: + group: pypi-publish + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + container: + image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu24.04 + + environment: ${{ inputs.repository }} + + permissions: + contents: read + id-token: write # required for PyPI Trusted Publishing (OIDC) + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + ref: ${{ inputs.ref || github.ref }} + + # Optional hard stop: only allow repo admins to proceed + - name: Enforce admin-only trigger + uses: actions/github-script@v7 + with: + script: | + const owner = context.repo.owner; + const repo = context.repo.repo; + const username = context.actor; + + const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ + owner, repo, username + }); + + core.info(`Actor permission: ${data.permission}`); + if (data.permission !== "admin") { + core.setFailed(`Only repository admins may publish. (${username} has: ${data.permission})`); + } + + + - name: Install build tooling + run: python -m pip install --upgrade pip build + + - name: Read package name/version from pyproject.toml + id: meta + run: | + python - <<'PY' + import sys, json + try: + import tomllib # py3.11+ + except ModuleNotFoundError: + import tomli as tomllib # fallback if needed + from pathlib import Path + + data = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8")) + proj = data.get("project", {}) + name = proj.get("name") + version = proj.get("version") + if not name or not version: + print("Missing [project].name or [project].version in pyproject.toml", file=sys.stderr) + sys.exit(2) + + print(f"name={name}") + print(f"version={version}") + with open("pkg_meta.json", "w", encoding="utf-8") as f: + json.dump({"name": name, "version": version}, f) + PY + echo "name=$(python -c "import json; print(json.load(open('pkg_meta.json'))['name'])")" >> "$GITHUB_OUTPUT" + echo "version=$(python -c "import json; print(json.load(open('pkg_meta.json'))['version'])")" >> "$GITHUB_OUTPUT" + + - name: Abort if this version already exists on the target index + env: + NAME: ${{ steps.meta.outputs.name }} + VERSION: ${{ steps.meta.outputs.version }} + TARGET: ${{ inputs.repository }} + run: | + python - <<'PY' + import json, os, sys, urllib.request, urllib.error + + name = os.environ["NAME"] + version = os.environ["VERSION"] + target = os.environ["TARGET"] + + base = "https://pypi.org/pypi" if target == "pypi" else "https://test.pypi.org/pypi" + url = f"{base}/{name}/json" + + try: + with urllib.request.urlopen(url) as resp: + data = json.load(resp) + except urllib.error.HTTPError as e: + if e.code == 404: + print(f"{name} not found on {target}; OK to publish {version}.") + sys.exit(0) + raise + + releases = data.get("releases", {}) + if version in releases and releases[version]: + print(f"Version {name}=={version} already exists on {target}. Aborting.") + sys.exit(1) + + print(f"Version {name}=={version} not present on {target}; OK to publish.") + PY + + - name: Build sdist and wheel + run: python -m build + + - name: Publish (Trusted Publishing / OIDC) + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From c808aa270cfe23350fa4a650957195715701c795 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 13:43:55 +0100 Subject: [PATCH 02/15] changed python to python3 --- .github/workflows/publish_version.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 4bef822..29d7664 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -55,12 +55,12 @@ jobs: - name: Install build tooling - run: python -m pip install --upgrade pip build + run: python3 -m pip install --upgrade pip build - name: Read package name/version from pyproject.toml id: meta run: | - python - <<'PY' + python3 - <<'PY' import sys, json try: import tomllib # py3.11+ @@ -81,8 +81,8 @@ jobs: with open("pkg_meta.json", "w", encoding="utf-8") as f: json.dump({"name": name, "version": version}, f) PY - echo "name=$(python -c "import json; print(json.load(open('pkg_meta.json'))['name'])")" >> "$GITHUB_OUTPUT" - echo "version=$(python -c "import json; print(json.load(open('pkg_meta.json'))['version'])")" >> "$GITHUB_OUTPUT" + echo "name=$(python3 -c "import json; print(json.load(open('pkg_meta.json'))['name'])")" >> "$GITHUB_OUTPUT" + echo "version=$(python3 -c "import json; print(json.load(open('pkg_meta.json'))['version'])")" >> "$GITHUB_OUTPUT" - name: Abort if this version already exists on the target index env: @@ -90,7 +90,7 @@ jobs: VERSION: ${{ steps.meta.outputs.version }} TARGET: ${{ inputs.repository }} run: | - python - <<'PY' + python3 - <<'PY' import json, os, sys, urllib.request, urllib.error name = os.environ["NAME"] @@ -118,7 +118,7 @@ jobs: PY - name: Build sdist and wheel - run: python -m build + run: python3 -m build - name: Publish (Trusted Publishing / OIDC) uses: pypa/gh-action-pypi-publish@release/v1 From 62bd77cb3b84cf95b3e081e6192825ef0e5e4f8f Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 13:46:49 +0100 Subject: [PATCH 03/15] wip --- .github/workflows/publish_version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 29d7664..a8f772e 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -55,7 +55,7 @@ jobs: - name: Install build tooling - run: python3 -m pip install --upgrade pip build + run: python3 -m pip install --upgrade build - name: Read package name/version from pyproject.toml id: meta From 8a866c14ad7c56a722e3e4ac8624cfef29dd0a84 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 13:53:05 +0100 Subject: [PATCH 04/15] pin version of github action --- .github/workflows/publish_version.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index a8f772e..b5425c0 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -120,7 +120,7 @@ jobs: - name: Build sdist and wheel run: python3 -m build - - name: Publish (Trusted Publishing / OIDC) - uses: pypa/gh-action-pypi-publish@release/v1 + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1.13.0 with: repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From bf08f775c8c7557ee8a5b9e042e4db6804ca8d43 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 13:55:27 +0100 Subject: [PATCH 05/15] pin version of github action --- .github/workflows/publish_version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index b5425c0..242e1be 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -121,6 +121,6 @@ jobs: run: python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@release/v1.13.0 + uses: pypa/gh-action-pypi-publish@v1.13.0 with: repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From bdcdd874a470a867984ab4e63dfd03f163c4bc21 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 13:58:09 +0100 Subject: [PATCH 06/15] pinning version --- .github/workflows/publish_version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 242e1be..c89e2f4 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -121,6 +121,6 @@ jobs: run: python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.13.0 + uses: pypa/gh-action-pypi-publish@v1.11.0 with: repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From 88ef4d04eb39245ecdcccf5968dd939d58ca8832 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:01:34 +0100 Subject: [PATCH 07/15] setuptools version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f338423..f5ecad6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" [project] From 2b12b37c821f949cecb685f6e01282ef2959b96c Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:10:31 +0100 Subject: [PATCH 08/15] deactivate twine check --- .github/workflows/publish_version.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index c89e2f4..1a8a4ad 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -123,4 +123,5 @@ jobs: - name: Publish uses: pypa/gh-action-pypi-publish@v1.11.0 with: + verify-metadata: false repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From 3bb6df67c0ad9f8062102e18651334db2b3eb2c4 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:17:46 +0100 Subject: [PATCH 09/15] wip --- .github/workflows/publish_version.yml | 3 +-- .gitignore | 5 +++-- pyproject.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 1a8a4ad..19bdf76 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -55,7 +55,7 @@ jobs: - name: Install build tooling - run: python3 -m pip install --upgrade build + run: python3 -m pip install - name: Read package name/version from pyproject.toml id: meta @@ -123,5 +123,4 @@ jobs: - name: Publish uses: pypa/gh-action-pypi-publish@v1.11.0 with: - verify-metadata: false repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} diff --git a/.gitignore b/.gitignore index 5123bc8..d3a4025 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /dist /build -/.venv +/.venv* /.eggs /cuvis.egg-info /MANIFEST.in @@ -8,6 +8,7 @@ /cuvis/_cuvis_pyil.pyd /venv /cuvis/__pycache__ -/.venv310 + /tests/__pycache__ /.claude + diff --git a/pyproject.toml b/pyproject.toml index f5ecad6..f338423 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=68", "wheel"] +requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [project] From c9861ca1db3f5d52cc95e56f2c84da4c9f00ce64 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:20:23 +0100 Subject: [PATCH 10/15] wip --- .github/workflows/publish_version.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 19bdf76..b1bf1a6 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -53,9 +53,8 @@ jobs: core.setFailed(`Only repository admins may publish. (${username} has: ${data.permission})`); } - - name: Install build tooling - run: python3 -m pip install + run: python3 -m pip install build - name: Read package name/version from pyproject.toml id: meta From 239068210018c4c74beb17d39f0af5a31c6b303e Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:27:04 +0100 Subject: [PATCH 11/15] wip --- .github/workflows/publish_version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index b1bf1a6..48ef8f0 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -54,7 +54,7 @@ jobs: } - name: Install build tooling - run: python3 -m pip install build + run: python3 -m pip install -U build twine - name: Read package name/version from pyproject.toml id: meta From 1c3ded112ae1c9971c2a349b3ebee9432e829810 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:31:08 +0100 Subject: [PATCH 12/15] pin gh-action-pypi-publish to newest version --- .github/workflows/publish_version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 48ef8f0..b456121 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -120,6 +120,6 @@ jobs: run: python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.11.0 + uses: pypa/gh-action-pypi-publish@v1.13.0 with: repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From 2bec5b4c04df970bd790be074379bb801030249a Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:37:40 +0100 Subject: [PATCH 13/15] testing other ubuntu version --- .github/workflows/publish_version.yml | 6 ++++-- prebuild.py | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index b456121..5e42d95 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -21,7 +21,7 @@ jobs: publish: runs-on: ubuntu-latest container: - image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu24.04 + image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu22.04 environment: ${{ inputs.repository }} @@ -117,7 +117,9 @@ jobs: PY - name: Build sdist and wheel - run: python3 -m build + run: | + python3 ./prebuild.py + python3 -m build - name: Publish uses: pypa/gh-action-pypi-publish@v1.13.0 diff --git a/prebuild.py b/prebuild.py index 326463c..027df7d 100644 --- a/prebuild.py +++ b/prebuild.py @@ -4,7 +4,11 @@ def get_git_commit_hash(): try: - return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip() + return ( + subprocess.check_output(["git", "rev-parse", "HEAD"]) + .decode("ascii") + .strip() + ) except subprocess.CalledProcessError: return "unknown" From 7661750e84b7533a17d30646fe70fd845da23c6f Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:47:12 +0100 Subject: [PATCH 14/15] refactored workflow --- .github/workflows/publish_version.yml | 30 ++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 5e42d95..78a66d9 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -18,16 +18,13 @@ concurrency: cancel-in-progress: false jobs: - publish: + build: runs-on: ubuntu-latest container: image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu22.04 - environment: ${{ inputs.repository }} - permissions: contents: read - id-token: write # required for PyPI Trusted Publishing (OIDC) steps: - name: Checkout @@ -121,7 +118,30 @@ jobs: python3 ./prebuild.py python3 -m build - - name: Publish + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + + environment: ${{ inputs.repository }} + + permissions: + contents: read + id-token: write # required for PyPI Trusted Publishing (OIDC) + + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@v1.13.0 with: repository-url: ${{ inputs.repository == 'pypi' && 'https://upload.pypi.org/legacy/' || 'https://test.pypi.org/legacy/' }} From 28fa3baae4c8168191af9810b38ce30322287ce7 Mon Sep 17 00:00:00 2001 From: birkholz-cubert Date: Mon, 12 Jan 2026 15:54:59 +0100 Subject: [PATCH 15/15] wip --- .github/workflows/publish_version.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/publish_version.yml b/.github/workflows/publish_version.yml index 78a66d9..1bf86aa 100644 --- a/.github/workflows/publish_version.yml +++ b/.github/workflows/publish_version.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu22.04 + image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu24.04 permissions: contents: read @@ -115,7 +115,6 @@ jobs: - name: Build sdist and wheel run: | - python3 ./prebuild.py python3 -m build - name: Upload build artifacts