Skip to content

Commit b96b514

Browse files
committed
Added release workflow and script
1 parent 14a178d commit b96b514

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

.github/workflows/release.yml

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
name: Build and Release to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # Trigger on version tags like v1.0.0, v0.2.1, etc.
7+
workflow_dispatch: # Allow manual triggering
8+
inputs:
9+
test_release:
10+
description: 'Release to Test PyPI instead of PyPI'
11+
required: false
12+
default: false
13+
type: boolean
14+
15+
jobs:
16+
build:
17+
name: Build distribution packages
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0 # Full history for proper versioning
24+
25+
- name: Set up Python
26+
uses: actions/setup-python@v4
27+
with:
28+
python-version: '3.11'
29+
cache: 'pip'
30+
31+
- name: Install build dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
python -m pip install build twine
35+
36+
- name: Build package
37+
run: python -m build
38+
39+
- name: Check distribution
40+
run: python -m twine check dist/*
41+
42+
- name: Upload build artifacts
43+
uses: actions/upload-artifact@v4
44+
with:
45+
name: dist
46+
path: dist/
47+
48+
test:
49+
name: Run tests before release
50+
runs-on: ubuntu-latest
51+
strategy:
52+
matrix:
53+
python-version: ["3.9", "3.10", "3.11"]
54+
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- name: Set up Python ${{ matrix.python-version }}
59+
uses: actions/setup-python@v4
60+
with:
61+
python-version: ${{ matrix.python-version }}
62+
cache: 'pip'
63+
64+
- name: Install dependencies
65+
run: |
66+
python -m pip install --upgrade pip
67+
pip install .[dev]
68+
69+
- name: Run tests
70+
run: pytest
71+
72+
73+
publish-test:
74+
name: Publish to Test PyPI
75+
needs: [build, test]
76+
runs-on: ubuntu-latest
77+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.test_release == 'true'
78+
environment:
79+
name: test-pypi
80+
url: https://test.pypi.org/p/{{cookiecutter.project_name}}
81+
permissions:
82+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
83+
84+
steps:
85+
- name: Download build artifacts
86+
uses: actions/download-artifact@v4
87+
with:
88+
name: dist
89+
path: dist/
90+
91+
- name: Publish to Test PyPI
92+
uses: pypa/gh-action-pypi-publish@release/v1
93+
with:
94+
repository-url: https://test.pypi.org/legacy/
95+
96+
publish:
97+
name: Publish to PyPI
98+
needs: [build, test]
99+
runs-on: ubuntu-latest
100+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
101+
permissions:
102+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
103+
104+
steps:
105+
- name: Download build artifacts
106+
uses: actions/download-artifact@v4
107+
with:
108+
name: dist
109+
path: dist/
110+
111+
- name: Publish to PyPI
112+
uses: pypa/gh-action-pypi-publish@release/v1
113+
114+
create-release:
115+
name: Create GitHub Release
116+
needs: [publish]
117+
runs-on: ubuntu-latest
118+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
119+
permissions:
120+
contents: write
121+
122+
steps:
123+
- uses: actions/checkout@v4
124+
125+
- name: Extract version from tag
126+
id: version
127+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
128+
129+
- name: Download build artifacts
130+
uses: actions/download-artifact@v4
131+
with:
132+
name: dist
133+
path: dist/
134+
135+
- name: Extract changelog for version
136+
id: changelog
137+
run: |
138+
# Extract changelog section for this version
139+
if [ -f CHANGELOG.md ]; then
140+
awk "/^## \[?${{ steps.version.outputs.VERSION }}\]?/ {flag=1; next} /^## / {flag=0} flag" CHANGELOG.md > release_notes.md
141+
if [ ! -s release_notes.md ]; then
142+
echo "No changelog found for version ${{ steps.version.outputs.VERSION }}" > release_notes.md
143+
fi
144+
else
145+
echo "Release ${{ steps.version.outputs.VERSION }}" > release_notes.md
146+
fi
147+
148+
- name: Create Release
149+
uses: softprops/action-gh-release@v1
150+
with:
151+
tag_name: ${{ github.ref_name }}
152+
name: Release ${{ steps.version.outputs.VERSION }}
153+
body_path: release_notes.md
154+
files: dist/*
155+
draft: false
156+
prerelease: ${{ contains(steps.version.outputs.VERSION, '-') }}

scripts/release.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
# Release script for cookiecutter-rompy
3+
set -e
4+
5+
# Determine version bump type
6+
if [ -z "$1" ]; then
7+
echo "Usage: $0 <major|minor|patch>"
8+
exit 1
9+
fi
10+
11+
# Bump version
12+
bump2version $1
13+
14+
# Push changes and tags
15+
git push && git push --tags
16+
17+
# GitHub release
18+
gh release create $(python -c "import toml; print(toml.load('pyproject.toml')['project']['version'])") --title "Release $(python -c "import toml; print(toml.load('pyproject.toml')['project']['version'])")" --notes "Automated release via script."
19+
20+
# Publish to PyPI
21+
python -m build
22+
twine upload dist/*
23+
24+
# Cleanup
25+
echo "Release successful."

0 commit comments

Comments
 (0)