Skip to content

Commit 963be3d

Browse files
feat: copies github actions workflow release.yml to user's local machine
1 parent 33683c4 commit 963be3d

File tree

5 files changed

+109
-2
lines changed

5 files changed

+109
-2
lines changed

afterpython/_paths.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@dataclass
66
class Paths:
77
package_path: Path = field(init=False)
8+
templates_path: Path = field(init=False)
89
user_path: Path = field(init=False)
910
pyproject_path: Path = field(init=False)
1011
afterpython_path: Path = field(init=False)
@@ -15,6 +16,7 @@ class Paths:
1516
def __post_init__(self):
1617
# package path is the path to the afterpython package in user's site-packages
1718
self.package_path = Path(__file__).resolve().parents[0]
19+
self.templates_path = self.package_path / "templates"
1820
self.user_path = self._find_project_root()
1921
self.pyproject_path = self.user_path / "pyproject.toml"
2022
self.afterpython_path = self.user_path / "afterpython"

afterpython/cli/commands/init.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def init_ruff_toml():
1414
if ruff_toml_path.exists():
1515
click.echo(f"Ruff configuration file {ruff_toml_path} already exists")
1616
return
17-
ruff_template_path = ap.paths.package_path / "ruff-template.toml"
17+
ruff_template_path = ap.paths.templates_path / "ruff-template.toml"
1818
shutil.copy(ruff_template_path, ruff_toml_path)
1919
click.echo(f"Created {ruff_toml_path}")
2020
# add ruff-pre-commit hook to .pre-commit-config.yaml
@@ -55,6 +55,7 @@ def init(ctx):
5555
from afterpython.tools.myst import init_myst
5656
from afterpython.tools.pre_commit import init_pre_commit
5757
from afterpython.tools.commitizen import init_commitizen
58+
from afterpython.tools.github_actions import init_release_workflow
5859

5960
paths = ctx.obj["paths"]
6061
click.echo("Initializing afterpython...")
@@ -84,7 +85,9 @@ def init(ctx):
8485
init_ruff_toml()
8586

8687
if click.confirm(
87-
f"\nCreate commitizen configuration (cz.toml) in {afterpython_path}?",
88+
f"\nCreate commitizen configuration (cz.toml) in {afterpython_path} "
89+
f"and release workflow in .github/workflows/release.yml?",
8890
default=True,
8991
):
9092
init_commitizen()
93+
init_release_workflow()
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Release to PyPI and GitHub
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # Trigger on all version tags (v0.1.0, v0.1.0rc1, v0.1.0.dev4, etc.)
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write # Required for creating GitHub releases
13+
id-token: write # Required for PyPI trusted publishing
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: '3.11'
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v5
26+
with:
27+
version: "latest"
28+
29+
- name: Build package
30+
run: uv build
31+
32+
- name: Publish to PyPI
33+
run: uv publish
34+
35+
- name: Determine if pre-release
36+
id: check_prerelease
37+
run: |
38+
# Extract version from tag (remove 'v' prefix)
39+
VERSION="${GITHUB_REF_NAME#v}"
40+
41+
# Check if this is a pre-release or dev version
42+
# Matches: dev, rc, alpha, beta, a1, b2 (but not 'stable-version')
43+
if [[ "$VERSION" =~ (dev|rc|alpha|beta|a[0-9]+|b[0-9]+) ]]; then
44+
echo "prerelease=true" >> $GITHUB_OUTPUT
45+
else
46+
echo "prerelease=false" >> $GITHUB_OUTPUT
47+
fi
48+
49+
- name: Create GitHub Release
50+
uses: softprops/action-gh-release@v2
51+
with:
52+
tag_name: ${{ github.ref_name }}
53+
name: ${{ github.ref_name }}
54+
generate_release_notes: false
55+
prerelease: ${{ steps.check_prerelease.outputs.prerelease }}
56+
files: dist/* # Attach built packages (wheel + sdist)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import shutil
2+
3+
import click
4+
5+
import afterpython as ap
6+
7+
8+
def init_release_workflow():
9+
"""Initialize GitHub Actions release workflow.
10+
11+
Creates .github/workflows/release.yml in the user's project root.
12+
This workflow triggers on version tags and:
13+
- Builds the package with uv
14+
- Publishes to PyPI using trusted publishing
15+
- Creates GitHub releases (with pre-release detection)
16+
"""
17+
user_path = ap.paths.user_path
18+
workflow_dir = user_path / ".github" / "workflows"
19+
workflow_path = workflow_dir / "release.yml"
20+
21+
if workflow_path.exists():
22+
click.echo(f"GitHub Actions release workflow {workflow_path} already exists")
23+
return
24+
25+
# Create .github/workflows directory if it doesn't exist
26+
workflow_dir.mkdir(parents=True, exist_ok=True)
27+
28+
# Copy template from package
29+
template_path = ap.paths.templates_path / "release-workflow-template.yml"
30+
if not template_path.exists():
31+
raise FileNotFoundError(
32+
f"Template file not found: {template_path}\n"
33+
"This might indicate a corrupted installation. Please reinstall afterpython."
34+
)
35+
36+
shutil.copy(template_path, workflow_path)
37+
click.echo(f"Created {workflow_path}")
38+
click.echo(
39+
"\n📋 Next steps to enable releases:\n"
40+
" 1. Enable PyPI trusted publishing:\n"
41+
" - Go to https://pypi.org/manage/account/publishing/\n"
42+
" - Add your repository and workflow file: release.yml\n"
43+
" 2. Push tags to trigger releases:\n"
44+
" - Use 'ap bump --release' for stable releases (auto-pushes tag)\n"
45+
" - Use 'ap bump --pre' then 'ap release' for pre-releases\n"
46+
)

0 commit comments

Comments
 (0)