Skip to content

Commit c56ffc5

Browse files
committed
improved workflow for publishing
1 parent 3fbcdb8 commit c56ffc5

File tree

7 files changed

+965
-28
lines changed

7 files changed

+965
-28
lines changed

.github/workflows/publish.yml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,37 @@ on:
44
release:
55
types: [published]
66
workflow_dispatch:
7+
inputs:
8+
skip_tests:
9+
description: 'Skip test job (use with caution)'
10+
required: false
11+
type: boolean
12+
default: false
713

814
jobs:
15+
test:
16+
if: ${{ !inputs.skip_tests }}
17+
uses: ./.github/workflows/test.yml
18+
919
build:
20+
needs: test
21+
if: ${{ always() && (needs.test.result == 'success' || needs.test.result == 'skipped') }}
1022
runs-on: ubuntu-latest
1123
steps:
1224
- uses: actions/checkout@v4
13-
25+
1426
- name: Install uv
1527
uses: astral-sh/setup-uv@v4
1628
with:
1729
enable-cache: true
18-
30+
1931
- name: Set up Python
2032
run: uv python install 3.12
21-
33+
2234
- name: Build package
2335
run: |
2436
uv build
25-
37+
2638
- name: Upload artifacts
2739
uses: actions/upload-artifact@v4
2840
with:

.github/workflows/release.yml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Create Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: 'Tag to create release for (e.g., v0.9.3)'
11+
required: true
12+
type: string
13+
14+
jobs:
15+
create-release:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: write
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
25+
- name: Get version from tag
26+
id: get_version
27+
run: |
28+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
29+
TAG=${{ inputs.tag }}
30+
else
31+
TAG=${GITHUB_REF#refs/tags/}
32+
fi
33+
VERSION=${TAG#v}
34+
echo "tag=${TAG}" >> $GITHUB_OUTPUT
35+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
36+
37+
- name: Verify version matches pyproject.toml
38+
run: |
39+
PYPROJECT_VERSION=$(grep '^version = ' pyproject.toml | cut -d'"' -f2)
40+
if [ "${{ steps.get_version.outputs.version }}" != "${PYPROJECT_VERSION}" ]; then
41+
echo "Error: Tag version (${{ steps.get_version.outputs.version }}) does not match pyproject.toml version (${PYPROJECT_VERSION})"
42+
exit 1
43+
fi
44+
45+
- name: Get previous tag
46+
id: get_previous_tag
47+
run: |
48+
PREVIOUS_TAG=$(git tag --sort=-version:refname | grep -A1 "${{ steps.get_version.outputs.tag }}" | tail -1)
49+
if [ -z "$PREVIOUS_TAG" ] || [ "$PREVIOUS_TAG" = "${{ steps.get_version.outputs.tag }}" ]; then
50+
# If no previous tag, use first commit
51+
PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD)
52+
fi
53+
echo "previous_tag=${PREVIOUS_TAG}" >> $GITHUB_OUTPUT
54+
55+
- name: Generate changelog
56+
id: changelog
57+
run: |
58+
echo "## What's Changed" > RELEASE_NOTES.md
59+
echo "" >> RELEASE_NOTES.md
60+
61+
# Get commits since last tag
62+
git log ${{ steps.get_previous_tag.outputs.previous_tag }}..${{ steps.get_version.outputs.tag }} \
63+
--pretty=format:"* %s (%h)" \
64+
--no-merges >> RELEASE_NOTES.md
65+
66+
echo "" >> RELEASE_NOTES.md
67+
echo "" >> RELEASE_NOTES.md
68+
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.get_previous_tag.outputs.previous_tag }}...${{ steps.get_version.outputs.tag }}" >> RELEASE_NOTES.md
69+
70+
cat RELEASE_NOTES.md
71+
72+
- name: Create GitHub Release
73+
uses: softprops/action-gh-release@v1
74+
with:
75+
tag_name: ${{ steps.get_version.outputs.tag }}
76+
name: Release ${{ steps.get_version.outputs.tag }}
77+
body_path: RELEASE_NOTES.md
78+
draft: false
79+
prerelease: false
80+
env:
81+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Makefile

Lines changed: 118 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: clean clean-pyc clean-build clean-test clean-all test run build publish help install dev-install
1+
.PHONY: clean clean-pyc clean-build clean-test clean-all test run build publish help install dev-install version bump-patch bump-minor bump-major release
22

33
# Default target
44
help:
@@ -20,7 +20,14 @@ help:
2020
@echo " check - Run all checks (lint, typecheck, security, test)"
2121
@echo " run - Run the server"
2222
@echo " build - Build the project"
23-
@echo " publish - Build and publish to PyPI"
23+
@echo ""
24+
@echo "Release targets:"
25+
@echo " version - Show current version"
26+
@echo " bump-patch - Bump patch version (0.0.X)"
27+
@echo " bump-minor - Bump minor version (0.X.0)"
28+
@echo " bump-major - Bump major version (X.0.0)"
29+
@echo " publish - Create tag and trigger automated release"
30+
@echo " release - Alias for publish"
2431

2532
# Basic clean - Python bytecode and common artifacts
2633
clean: clean-pyc clean-build
@@ -142,32 +149,120 @@ build: clean-build
142149
fi
143150
@echo "Build complete. Distributions are in the 'dist' folder."
144151

145-
# Publish the package to PyPI using twine
146-
publish: build
147-
@echo "Publishing package..."
148-
@if [ ! -d "dist" ] || [ -z "$$(ls -A dist 2>/dev/null)" ]; then \
149-
echo "Error: No distribution files found. Run 'make build' first."; \
152+
# ============================================================================
153+
# Version Management and Release Targets
154+
# ============================================================================
155+
156+
# Show current version
157+
version:
158+
@version=$$(grep '^version = ' pyproject.toml | cut -d'"' -f2); \
159+
echo "Current version: $$version"
160+
161+
# Bump patch version (0.0.X)
162+
bump-patch:
163+
@echo "Bumping patch version..."
164+
@current=$$(grep '^version = ' pyproject.toml | cut -d'"' -f2); \
165+
major=$$(echo $$current | cut -d. -f1); \
166+
minor=$$(echo $$current | cut -d. -f2); \
167+
patch=$$(echo $$current | cut -d. -f3); \
168+
new_patch=$$(($$patch + 1)); \
169+
new_version="$$major.$$minor.$$new_patch"; \
170+
sed -i.bak "s/^version = \"$$current\"/version = \"$$new_version\"/" pyproject.toml && rm pyproject.toml.bak; \
171+
echo "Version bumped: $$current -> $$new_version"; \
172+
echo "Review the change, then run 'make publish' to release"
173+
174+
# Bump minor version (0.X.0)
175+
bump-minor:
176+
@echo "Bumping minor version..."
177+
@current=$$(grep '^version = ' pyproject.toml | cut -d'"' -f2); \
178+
major=$$(echo $$current | cut -d. -f1); \
179+
minor=$$(echo $$current | cut -d. -f2); \
180+
new_minor=$$(($$minor + 1)); \
181+
new_version="$$major.$$new_minor.0"; \
182+
sed -i.bak "s/^version = \"$$current\"/version = \"$$new_version\"/" pyproject.toml && rm pyproject.toml.bak; \
183+
echo "Version bumped: $$current -> $$new_version"; \
184+
echo "Review the change, then run 'make publish' to release"
185+
186+
# Bump major version (X.0.0)
187+
bump-major:
188+
@echo "Bumping major version..."
189+
@current=$$(grep '^version = ' pyproject.toml | cut -d'"' -f2); \
190+
major=$$(echo $$current | cut -d. -f1); \
191+
new_major=$$(($$major + 1)); \
192+
new_version="$$new_major.0.0"; \
193+
sed -i.bak "s/^version = \"$$current\"/version = \"$$new_version\"/" pyproject.toml && rm pyproject.toml.bak; \
194+
echo "Version bumped: $$current -> $$new_version"; \
195+
echo "Review the change, then run 'make publish' to release"
196+
197+
# Automated release - creates tag and pushes to trigger GitHub Actions
198+
publish:
199+
@echo "Starting automated release process..."
200+
@echo ""
201+
@# Get current version
202+
@version=$$(grep '^version = ' pyproject.toml | cut -d'"' -f2); \
203+
tag="v$$version"; \
204+
echo "Version: $$version"; \
205+
echo "Tag: $$tag"; \
206+
echo ""; \
207+
\
208+
echo "Pre-flight checks:"; \
209+
echo "=================="; \
210+
\
211+
if git diff --quiet && git diff --cached --quiet; then \
212+
echo "✓ Working directory is clean"; \
213+
else \
214+
echo "✗ Working directory has uncommitted changes"; \
215+
echo ""; \
216+
git status --short; \
217+
echo ""; \
218+
echo "Please commit or stash your changes before releasing."; \
150219
exit 1; \
151-
fi
152-
@last_build=$$(ls -t dist/*.tar.gz dist/*.whl 2>/dev/null | head -n 2); \
153-
if [ -z "$$last_build" ]; then \
154-
echo "Error: No valid distribution files found."; \
220+
fi; \
221+
\
222+
if git tag -l | grep -q "^$$tag$$"; then \
223+
echo "✗ Tag $$tag already exists"; \
224+
echo ""; \
225+
echo "To delete and recreate:"; \
226+
echo " git tag -d $$tag"; \
227+
echo " git push origin :refs/tags/$$tag"; \
155228
exit 1; \
229+
else \
230+
echo "✓ Tag $$tag does not exist yet"; \
156231
fi; \
157-
echo "Uploading: $$last_build"; \
158-
twine upload $$last_build
159-
@echo "Publish complete."
160-
161-
# Publish to test PyPI
162-
publish-test: build
163-
@echo "Publishing to test PyPI..."
164-
@last_build=$$(ls -t dist/*.tar.gz dist/*.whl 2>/dev/null | head -n 2); \
165-
if [ -z "$$last_build" ]; then \
166-
echo "Error: No valid distribution files found."; \
232+
\
233+
current_branch=$$(git rev-parse --abbrev-ref HEAD); \
234+
echo "✓ Current branch: $$current_branch"; \
235+
echo ""; \
236+
\
237+
echo "This will:"; \
238+
echo " 1. Create and push tag $$tag"; \
239+
echo " 2. Trigger GitHub Actions to:"; \
240+
echo " - Create a GitHub release with changelog"; \
241+
echo " - Run tests on all platforms"; \
242+
echo " - Build and publish to PyPI"; \
243+
echo ""; \
244+
read -p "Continue? (y/N) " -n 1 -r; \
245+
echo ""; \
246+
if [[ ! $$REPLY =~ ^[Yy]$$ ]]; then \
247+
echo "Aborted."; \
167248
exit 1; \
168249
fi; \
169-
echo "Uploading to test PyPI: $$last_build"; \
170-
twine upload --repository testpypi $$last_build
250+
\
251+
echo ""; \
252+
echo "Creating and pushing tag..."; \
253+
git tag -a "$$tag" -m "Release $$tag" && \
254+
git push origin "$$tag" && \
255+
echo "" && \
256+
echo "✓ Tag pushed successfully!" && \
257+
echo "" && \
258+
echo "GitHub Actions workflows triggered:" && \
259+
echo " - Release creation: https://github.com/$$(git config --get remote.origin.url | sed 's/.*://;s/.git$$//')/actions/workflows/release.yml" && \
260+
echo " - PyPI publishing: https://github.com/$$(git config --get remote.origin.url | sed 's/.*://;s/.git$$//')/actions/workflows/publish.yml" && \
261+
echo "" && \
262+
echo "Monitor progress at: https://github.com/$$(git config --get remote.origin.url | sed 's/.*://;s/.git$$//')/actions"
263+
264+
# Alias for publish
265+
release: publish
171266

172267
# Check code quality
173268
lint:

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,54 @@ A: InProcess is faster (same process), Subprocess is safer (isolated process). U
16681668
- Use directly if you need protocol-level control
16691669
- Use chuk-tool-processor if you want high-level tool execution
16701670

1671+
## Development & Publishing
1672+
1673+
### For Contributors
1674+
1675+
Development setup:
1676+
1677+
```bash
1678+
# Clone repository
1679+
git clone https://github.com/chrishayuk/chuk-tool-processor.git
1680+
cd chuk-tool-processor
1681+
1682+
# Install development dependencies
1683+
uv sync --dev
1684+
1685+
# Run tests
1686+
make test
1687+
1688+
# Run all quality checks
1689+
make check
1690+
```
1691+
1692+
### For Maintainers: Publishing Releases
1693+
1694+
The project uses **fully automated CI/CD** for releases. Publishing is as simple as:
1695+
1696+
```bash
1697+
# 1. Bump version
1698+
make bump-patch # or bump-minor, bump-major
1699+
1700+
# 2. Commit version change
1701+
git add pyproject.toml
1702+
git commit -m "version X.Y.Z"
1703+
git push
1704+
1705+
# 3. Create release (automated)
1706+
make publish
1707+
```
1708+
1709+
This will:
1710+
- Create and push a git tag
1711+
- Trigger GitHub Actions to create a release with auto-generated changelog
1712+
- Run tests across all platforms and Python versions
1713+
- Build and publish to PyPI automatically
1714+
1715+
For detailed release documentation, see:
1716+
- **[RELEASING.md](RELEASING.md)** - Complete release process guide
1717+
- **[docs/CI-CD.md](docs/CI-CD.md)** - Full CI/CD pipeline documentation
1718+
16711719
## Contributing & Support
16721720

16731721
- **GitHub**: [chrishayuk/chuk-tool-processor](https://github.com/chrishayuk/chuk-tool-processor)

0 commit comments

Comments
 (0)