-
Notifications
You must be signed in to change notification settings - Fork 6
204 lines (181 loc) · 7.12 KB
/
Copy pathpublish-pypi.yml
File metadata and controls
204 lines (181 loc) · 7.12 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# Author: André Henrique (@mrhenrike) | União Geek — https://github.com/Uniao-Geek
#
# Auto-publish embedxpl to PyPI whenever the version in pyproject.toml
# is not yet available on PyPI.
#
# Flow:
# push to master (this repo only) → read version → check PyPI → if new → build + tag + publish
# push of v* tag → build + publish (direct release path)
# workflow_dispatch → dry-run on TestPyPI
#
# Security model:
# - Publishing uses OIDC Trusted Publisher ONLY (no API tokens in workflow)
# - All publish jobs guard on github.repository to prevent fork execution
# - The PyPI Trusted Publisher is bound to mrhenrike/EmbedXPL-Forge + this file + environment pypi
#
# One-time PyPI setup: https://pypi.org/manage/account/publishing/
# PyPI project name : embedxpl
# GitHub owner : mrhenrike
# GitHub repo : EmbedXPL-Forge
# Workflow file : publish-pypi.yml
# Environment : pypi
name: publish-pypi
on:
push:
branches:
- master
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write # needed to push version tag
id-token: write # required for OIDC Trusted Publishing
jobs:
# ------------------------------------------------------------------ #
# Check whether current version already exists on PyPI #
# ------------------------------------------------------------------ #
version-check:
name: "Check version vs PyPI"
if: github.repository == 'mrhenrike/EmbedXPL-Forge'
runs-on: ubuntu-latest
outputs:
version: ${{ steps.read.outputs.version }}
should_publish: ${{ steps.check.outputs.should_publish }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Read version from pyproject.toml
id: read
run: |
VERSION=$(python - <<'EOF'
import tomllib, pathlib
data = tomllib.loads(pathlib.Path("pyproject.toml").read_text())
print(data["project"]["version"])
EOF
)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Current version: $VERSION"
- name: Check if version is already on PyPI
id: check
run: |
VERSION="${{ steps.read.outputs.version }}"
HTTP=$(curl -s -o /dev/null -w "%{http_code}" \
"https://pypi.org/pypi/embedxpl/$VERSION/json")
echo "PyPI HTTP status for $VERSION: $HTTP"
if [ "$HTTP" = "404" ]; then
echo "should_publish=true" >> "$GITHUB_OUTPUT"
echo "Version $VERSION is NOT on PyPI — will publish"
else
echo "should_publish=false" >> "$GITHUB_OUTPUT"
echo "Version $VERSION already on PyPI — skipping publish"
fi
# ------------------------------------------------------------------ #
# Build sdist + wheel #
# ------------------------------------------------------------------ #
build:
name: "Build distribution"
runs-on: ubuntu-latest
needs: version-check
if: |
github.repository == 'mrhenrike/EmbedXPL-Forge' &&
(needs.version-check.outputs.should_publish == 'true' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install build tools
run: python -m pip install --upgrade pip build twine
- name: Build sdist and wheel
run: python -m build
- name: Verify with twine check
run: |
python -m twine check dist/*
echo "=== dist/ ==="
ls -lh dist/
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ needs.version-check.outputs.version }}
path: dist/
retention-days: 30
# ------------------------------------------------------------------ #
# Create git tag for the new version (only on push to master) #
# ------------------------------------------------------------------ #
tag-release:
name: "Create version tag"
runs-on: ubuntu-latest
needs: [version-check, build]
if: |
github.repository == 'mrhenrike/EmbedXPL-Forge' &&
needs.version-check.outputs.should_publish == 'true' &&
github.event_name == 'push' &&
github.ref == 'refs/heads/master'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create and push tag v${{ needs.version-check.outputs.version }}
run: |
VERSION="${{ needs.version-check.outputs.version }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git ls-remote --tags origin "refs/tags/v$VERSION" | grep -q "v$VERSION"; then
echo "Tag v$VERSION already exists on remote — skipping tag creation"
else
git tag -a "v$VERSION" -m "EmbedXPL-Forge v$VERSION (auto-tagged by CI)"
git push origin "v$VERSION"
echo "Tagged v$VERSION"
fi
# ------------------------------------------------------------------ #
# Publish to PyPI (production) #
# ------------------------------------------------------------------ #
publish-pypi:
name: "Publish to PyPI"
runs-on: ubuntu-latest
needs: [version-check, build]
if: |
github.repository == 'mrhenrike/EmbedXPL-Forge' &&
(needs.version-check.outputs.should_publish == 'true' || startsWith(github.ref, 'refs/tags/v')) &&
github.event_name != 'workflow_dispatch'
environment:
name: pypi
url: https://pypi.org/project/embedxpl/${{ needs.version-check.outputs.version }}/
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: dist-${{ needs.version-check.outputs.version }}
path: dist/
- name: Publish to PyPI via OIDC Trusted Publishing
uses: pypa/gh-action-pypi-publish@release/v1
with:
print-hash: true
verbose: true
skip_existing: true
# ------------------------------------------------------------------ #
# Dry-run on TestPyPI (manual dispatch only) #
# ------------------------------------------------------------------ #
publish-testpypi:
name: "Publish to TestPyPI (dry-run)"
if: github.repository == 'mrhenrike/EmbedXPL-Forge' && github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
needs: [version-check, build]
environment:
name: testpypi
url: https://test.pypi.org/project/embedxpl/
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: dist-${{ needs.version-check.outputs.version }}
path: dist/
- name: Publish to TestPyPI via OIDC Trusted Publishing
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
print-hash: true
verbose: true