-
Notifications
You must be signed in to change notification settings - Fork 3
146 lines (121 loc) · 4.55 KB
/
publish_version.yml
File metadata and controls
146 lines (121 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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:
build:
runs-on: ubuntu-latest
container:
image: cubertgmbh/cuvis_pyil:3.5.0-ubuntu24.04
permissions:
contents: read
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: python3 -m pip install -U build twine
- name: Read package name/version from pyproject.toml
id: meta
run: |
python3 - <<'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=$(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:
NAME: ${{ steps.meta.outputs.name }}
VERSION: ${{ steps.meta.outputs.version }}
TARGET: ${{ inputs.repository }}
run: |
python3 - <<'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: |
python3 -m build
- 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/' }}