This repository was archived by the owner on Sep 10, 2025. It is now read-only.
Repository navigation
456 lines (373 loc) · 12.7 KB
/
Copy pathrelease-python-package.yml
File metadata and controls
456 lines (373 loc) · 12.7 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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
name: Release Python Package
on:
workflow_call:
inputs:
version:
description: 'Version to release (without v prefix)'
required: true
type: string
tag:
description: 'Git tag for the release'
required: true
type: string
secrets:
PYPI_API_TOKEN:
required: false
description: 'PyPI API token for publishing'
env:
PYTHON_VERSION: '3.11'
jobs:
validate-version:
name: Validate Version Consistency
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install toml packaging
- name: Validate versions
run: |
VERSION="${{ inputs.version }}"
# Check pyproject.toml version
python -c "
import toml
config = toml.load('sdk/python/pyproject.toml')
version = config['project']['version']
expected = '${VERSION}'
if version != expected:
print(f'Version mismatch in pyproject.toml: {version} != {expected}')
exit(1)
print(f'pyproject.toml version validated: {version}')
"
# Check __init__.py version if it exists
if [[ -f "sdk/python/ftl_sdk/__init__.py" ]]; then
INIT_VERSION=$(grep -E "__version__ = ['\"]" sdk/python/ftl_sdk/__init__.py | cut -d'"' -f2 || cut -d"'" -f2)
if [[ "${INIT_VERSION}" != "${VERSION}" ]]; then
echo "Version mismatch in __init__.py: ${INIT_VERSION} != ${VERSION}"
exit 1
fi
echo "__init__.py version validated: ${INIT_VERSION}"
fi
# Check manifest version
JSON_VERSION=$(jq -r '."sdk/python"' .release-please-manifest.json)
if [[ "${JSON_VERSION}" != "${VERSION}" ]]; then
echo "Version mismatch in manifest: ${JSON_VERSION} != ${VERSION}"
exit 1
fi
echo "Manifest version validated: ${JSON_VERSION}"
test-package:
name: Test Python Package
needs: validate-version
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install package and dependencies
run: |
cd sdk/python
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run linting
run: |
cd sdk/python
# Run ruff for linting
if command -v ruff >/dev/null 2>&1; then
ruff check .
ruff format --check .
fi
# Run mypy for type checking
if command -v mypy >/dev/null 2>&1; then
mypy ftl_sdk
fi
- name: Run tests
run: |
cd sdk/python
# Run pytest with coverage
if command -v pytest >/dev/null 2>&1; then
pytest tests/ -v --cov=ftl_sdk --cov-report=term-missing
else
python -m unittest discover tests/
fi
- name: Test documentation build
run: |
cd sdk/python
# Install doc dependencies
pip install sphinx sphinx-rtd-theme
# Build documentation
if [[ -d "docs" ]]; then
cd docs
make html
echo "Documentation built successfully"
fi
build-distribution:
name: Build Distribution Packages
needs: test-package
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: |
cd sdk/python
# Clean any previous builds
rm -rf dist/ build/ *.egg-info
# Build source distribution and wheel
python -m build
# List built packages
ls -la dist/
# Verify package contents
python -m zipfile -l dist/*.whl
tar -tzf dist/*.tar.gz | head -20
- name: Check package with twine
run: |
cd sdk/python
# Check package metadata
twine check dist/*
# Show package info
python -m twine check --verbose dist/*
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: python-dist
path: sdk/python/dist/
retention-days: 7
publish-pypi:
name: Publish to PyPI
needs: build-distribution
if: always() && needs.build-distribution.result == 'success'
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: python-dist
path: dist/
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install twine
run: |
python -m pip install --upgrade pip
pip install twine
- name: Publish to PyPI (API Token)
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
twine upload dist/*
echo "Published to PyPI using API token"
verify-publication:
name: Verify PyPI Publication
needs: publish-pypi
runs-on: ubuntu-latest
steps:
- name: Wait for PyPI to index
run: |
echo "Waiting for PyPI to index the package..."
sleep 60
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Verify package on PyPI
run: |
VERSION="${{ inputs.version }}"
# Check if package is available
pip index versions ftl-sdk | grep -q "${VERSION}" || {
echo "Version ${VERSION} not found on PyPI yet, waiting..."
sleep 30
pip index versions ftl-sdk | grep -q "${VERSION}" || {
echo "Warning: Version ${VERSION} not immediately available on PyPI"
}
}
echo "Package ftl-sdk ${VERSION} is available on PyPI"
- name: Test installation
run: |
# Create virtual environment
python -m venv test-env
source test-env/bin/activate
# Install from PyPI
pip install ftl-sdk==${{ inputs.version }}
# Test import and version
python -c "
import ftl_sdk
assert ftl_sdk.__version__ == '${{ inputs.version }}', f'Version mismatch: {ftl_sdk.__version__}'
print(f'Successfully installed and imported ftl_sdk {ftl_sdk.__version__}')
"
# Test basic functionality
python -c "
from ftl_sdk import FtlClient
print('FtlClient imported successfully')
"
deactivate
echo "✓ Package installation and import successful"
create-docs:
name: Generate Documentation
needs: verify-publication
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
cd sdk/python
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints
- name: Build documentation
run: |
cd sdk/python
# Create docs directory if it doesn't exist
mkdir -p docs
# Generate API documentation
if [[ ! -f "docs/conf.py" ]]; then
cat > docs/conf.py << 'EOF'
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
project = 'FTL Python SDK'
copyright = '2024, FasterTools'
author = 'FasterTools'
version = '${{ inputs.version }}'
release = version
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.viewcode',
'sphinx_autodoc_typehints',
]
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
EOF
fi
# Create index if it doesn't exist
if [[ ! -f "docs/index.rst" ]]; then
cat > docs/index.rst << 'EOF'
FTL Python SDK Documentation
============================
Version ${{ inputs.version }}
.. toctree::
:maxdepth: 2
:caption: Contents:
api
Installation
-----------
.. code-block:: bash
pip install ftl-sdk
Quick Start
----------
.. code-block:: python
from ftl_sdk import FtlClient
client = FtlClient()
# Use the client...
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
EOF
fi
# Build HTML documentation
cd docs
make html || sphinx-build -b html . _build/html
echo "Documentation built successfully"
- name: Upload documentation
uses: actions/upload-artifact@v4
with:
name: python-sdk-docs
path: sdk/python/docs/_build/html/
retention-days: 30
notify-downstream:
name: Notify Downstream Projects
needs: verify-publication
runs-on: ubuntu-latest
steps:
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Create notification issue
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const version = '${{ inputs.version }}';
const title = `Python SDK v${version} Released`;
const body = `
## FTL Python SDK v${version} has been released
### What's New
See the [CHANGELOG](https://github.com/fastertools/ftl/blob/main/sdk/python/CHANGELOG.md) for details.
### Installation
\`\`\`bash
pip install ftl-sdk==${version}
\`\`\`
Or update your \`requirements.txt\`:
\`\`\`
ftl-sdk==${version}
\`\`\`
Or update your \`pyproject.toml\`:
\`\`\`toml
[project]
dependencies = [
"ftl-sdk==${version}",
]
\`\`\`
### Documentation
- [PyPI Package](https://pypi.org/project/ftl-sdk/${version}/)
- [Documentation](https://ftl-sdk.readthedocs.io/en/v${version}/)
### Template Updates
Project templates have been automatically updated to use v${version}.
`;
try {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['release', 'python-sdk', 'announcement']
});
} catch (error) {
console.log('Could not create issue:', error.message);
}