Skip to content

Commit c5d3a80

Browse files
committed
pypi workflow prepared
1 parent ccfd761 commit c5d3a80

8 files changed

Lines changed: 521 additions & 6 deletions

File tree

.github/workflows/.yamllint-ignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# This is valid GitHub Actions syntax - the validator may not recognize environment names

.github/workflows/release.yml

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
name: Build and Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: read
10+
id-token: write # Required for trusted publishing to PyPI
11+
12+
env:
13+
PYTHON_VERSION: "3.11"
14+
15+
jobs:
16+
validate-version:
17+
name: Validate Version Match
18+
runs-on: ubuntu-latest
19+
outputs:
20+
version: ${{ steps.get-version.outputs.version }}
21+
tag-version: ${{ steps.get-tag.outputs.tag-version }}
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- name: Get tag version
27+
id: get-tag
28+
run: |
29+
TAG_VERSION=${GITHUB_REF#refs/tags/v}
30+
echo "tag-version=$TAG_VERSION" >> $GITHUB_OUTPUT
31+
echo "Tag version: $TAG_VERSION"
32+
33+
- name: Get pyproject.toml version
34+
id: get-version
35+
run: |
36+
VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
37+
echo "version=$VERSION" >> $GITHUB_OUTPUT
38+
echo "pyproject.toml version: $VERSION"
39+
40+
- name: Validate version match
41+
run: |
42+
TAG_VERSION="${{ steps.get-tag.outputs.tag-version }}"
43+
PYPROJECT_VERSION="${{ steps.get-version.outputs.version }}"
44+
45+
echo "Comparing versions:"
46+
echo " Git tag: v$TAG_VERSION"
47+
echo " pyproject.toml: $PYPROJECT_VERSION"
48+
49+
if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then
50+
echo "❌ ERROR: Version mismatch!"
51+
echo " Git tag version: $TAG_VERSION"
52+
echo " pyproject.toml version: $PYPROJECT_VERSION"
53+
echo ""
54+
echo "To fix this:"
55+
echo "1. Update version in pyproject.toml to match tag, or"
56+
echo "2. Create a new tag that matches pyproject.toml version"
57+
exit 1
58+
fi
59+
60+
echo "✅ Versions match! Proceeding with release of version $PYPROJECT_VERSION"
61+
62+
build:
63+
name: Build Distribution
64+
runs-on: ubuntu-latest
65+
needs: validate-version
66+
67+
steps:
68+
- uses: actions/checkout@v4
69+
70+
- name: Set up Python ${{ env.PYTHON_VERSION }}
71+
uses: actions/setup-python@v4
72+
with:
73+
python-version: ${{ env.PYTHON_VERSION }}
74+
75+
- name: Install uv
76+
uses: astral-sh/setup-uv@v3
77+
with:
78+
enable-cache: true
79+
80+
- name: Install build dependencies
81+
run: |
82+
python -m pip install --upgrade pip
83+
python -m pip install build twine check-manifest
84+
85+
- name: Validate MANIFEST.in
86+
run: |
87+
check-manifest --verbose
88+
89+
- name: Build sdist and wheel
90+
run: |
91+
echo "Building distributions for asyncmiele v${{ needs.validate-version.outputs.version }}"
92+
python -m build --sdist --wheel --outdir dist/
93+
94+
- name: Verify distributions
95+
run: |
96+
echo "Built distributions:"
97+
ls -la dist/
98+
echo "Checking distributions:"
99+
python -m twine check dist/*
100+
101+
- name: Upload build artifacts
102+
uses: actions/upload-artifact@v4
103+
with:
104+
name: python-distributions
105+
path: dist/
106+
retention-days: 7
107+
108+
test-install:
109+
name: Test Installation
110+
runs-on: ubuntu-latest
111+
needs: build
112+
strategy:
113+
matrix:
114+
python-version: ["3.11", "3.12"]
115+
116+
steps:
117+
- name: Set up Python ${{ matrix.python-version }}
118+
uses: actions/setup-python@v4
119+
with:
120+
python-version: ${{ matrix.python-version }}
121+
122+
- name: Download build artifacts
123+
uses: actions/download-artifact@v4
124+
with:
125+
name: python-distributions
126+
path: dist/
127+
128+
- name: Test wheel installation
129+
run: |
130+
echo "Testing wheel installation on Python ${{ matrix.python-version }}"
131+
pip install dist/*.whl
132+
python -c "import asyncmiele; print('✅ Import successful')"
133+
134+
publish-pypi:
135+
name: Publish to PyPI
136+
runs-on: ubuntu-latest
137+
needs: [validate-version, build, test-install]
138+
139+
steps:
140+
- name: Download build artifacts
141+
uses: actions/download-artifact@v4
142+
with:
143+
name: python-distributions
144+
path: dist/
145+
146+
- name: Publish to PyPI
147+
uses: pypa/gh-action-pypi-publish@release/v1
148+
with:
149+
print-hash: true
150+
verbose: true
151+
152+
github-release:
153+
name: Create GitHub Release
154+
runs-on: ubuntu-latest
155+
needs: [validate-version, publish-pypi]
156+
permissions:
157+
contents: write
158+
159+
steps:
160+
- uses: actions/checkout@v4
161+
with:
162+
fetch-depth: 0
163+
164+
- name: Download build artifacts
165+
uses: actions/download-artifact@v4
166+
with:
167+
name: python-distributions
168+
path: dist/
169+
170+
- name: Generate changelog
171+
id: changelog
172+
run: |
173+
echo "Generating changelog since last release..."
174+
PREVIOUS_TAG=$(git tag --sort=-version:refname | grep -v "^${{ github.ref_name }}$" | head -1)
175+
176+
if [ -z "$PREVIOUS_TAG" ]; then
177+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
178+
else
179+
CHANGELOG=$(git log $PREVIOUS_TAG..${{ github.ref_name }} --pretty=format:"- %s (%h)" --no-merges)
180+
fi
181+
182+
if [ -z "$CHANGELOG" ]; then
183+
CHANGELOG="- No notable changes in this release"
184+
fi
185+
186+
echo "changelog<<EOF" >> $GITHUB_OUTPUT
187+
echo "$CHANGELOG" >> $GITHUB_OUTPUT
188+
echo "EOF" >> $GITHUB_OUTPUT
189+
190+
- name: Create GitHub Release
191+
uses: softprops/action-gh-release@v2
192+
with:
193+
tag_name: ${{ github.ref_name }}
194+
name: Release ${{ github.ref_name }}
195+
body: |
196+
# AsyncMiele ${{ needs.validate-version.outputs.version }}
197+
198+
## What's Changed
199+
${{ steps.changelog.outputs.changelog }}
200+
201+
## Installation
202+
```bash
203+
pip install asyncmiele==${{ needs.validate-version.outputs.version }}
204+
```
205+
206+
## Requirements
207+
- Python 3.11+
208+
draft: false
209+
prerelease: ${{ contains(needs.validate-version.outputs.version, 'rc') || contains(needs.validate-version.outputs.version, 'beta') || contains(needs.validate-version.outputs.version, 'alpha') }}
210+
files: |
211+
dist/asyncmiele-${{ needs.validate-version.outputs.version }}-py3-none-any.whl
212+
dist/asyncmiele-${{ needs.validate-version.outputs.version }}.tar.gz
213+
214+

MANIFEST.in

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Include essential files
2+
include README.md
3+
include LICENSE
4+
include CHANGELOG.md
5+
include pyproject.toml
6+
7+
# Include package source code
8+
recursive-include asyncmiele *.py
9+
recursive-include resources *.py *.json
10+
11+
# Include examples and scripts for documentation purposes
12+
recursive-include examples *.py *.md *.json
13+
recursive-include scripts *.py
14+
15+
# Exclude development and testing files
16+
exclude .envrc
17+
exclude pytest.ini
18+
exclude uv.lock
19+
exclude *.json
20+
exclude device_*.json
21+
exclude *_profile_*.json
22+
23+
# Exclude development directories
24+
recursive-exclude .vscode *
25+
recursive-exclude .pytest_cache *
26+
recursive-exclude .github *
27+
recursive-exclude tests *
28+
recursive-exclude docs *
29+
30+
recursive-exclude .venv *
31+
recursive-exclude .git *
32+
33+
# Exclude build artifacts
34+
recursive-exclude *.egg-info *
35+
recursive-exclude build *
36+
recursive-exclude dist *
37+
recursive-exclude __pycache__ *
38+
recursive-exclude .* *
39+
40+
# Exclude OS and IDE files
41+
exclude .DS_Store
42+
exclude Thumbs.db
43+
exclude .gitignore
44+
exclude .gitattributes
45+
46+
# Exclude development configuration files
47+
exclude CONTRIBUTING.md
48+
exclude *.cfg
49+
exclude *.ini
50+
exclude tox.ini
51+
exclude .pre-commit-config.yaml
52+
53+
# Force include pyproject.toml (it may get excluded by .* pattern)
54+
include pyproject.toml

asyncmiele/py.typed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)