templatepy 0.2.8.dev0__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. templatepy-0.3.2/CITATION.cff +17 -0
  2. templatepy-0.3.2/PKG-INFO +92 -0
  3. templatepy-0.3.2/README.md +76 -0
  4. templatepy-0.3.2/VERSION +1 -0
  5. templatepy-0.3.2/copier.yaml +64 -0
  6. templatepy-0.3.2/pyproject.toml +46 -0
  7. templatepy-0.3.2/src/templatepy/__init__.py +6 -0
  8. templatepy-0.3.2/template/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  9. templatepy-0.3.2/template/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  10. templatepy-0.3.2/template/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  11. templatepy-0.3.2/template/.github/workflows/bump.yml +47 -0
  12. templatepy-0.3.2/template/.github/workflows/ci.yml +83 -0
  13. templatepy-0.3.2/template/.github/workflows/docs.yml +31 -0
  14. templatepy-0.3.2/template/.github/workflows/pr-review.yml +96 -0
  15. templatepy-0.3.2/template/.github/workflows/release.yml +35 -0
  16. templatepy-0.3.2/template/.gitignore +71 -0
  17. templatepy-0.3.2/template/.gitleaks.toml +17 -0
  18. templatepy-0.3.2/template/.pre-commit-config.yaml +34 -0
  19. templatepy-0.3.2/template/CITATION.cff +33 -0
  20. templatepy-0.3.2/template/CODE_OF_CONDUCT.md +31 -0
  21. templatepy-0.3.2/template/CONTRIBUTING.md +29 -0
  22. templatepy-0.3.2/template/LICENSE +12 -0
  23. templatepy-0.3.2/template/README.md +41 -0
  24. templatepy-0.3.2/template/docs/index.md +29 -0
  25. templatepy-0.3.2/template/mkdocs.yml +23 -0
  26. templatepy-0.3.2/template/pyproject.toml +112 -0
  27. templatepy-0.3.2/template/src/[[ project_slug ]]/__init__.py +8 -0
  28. templatepy-0.3.2/template/src/[[ project_slug ]]/py.typed +0 -0
  29. templatepy-0.3.2/template/tests/conftest.py +1 -0
  30. templatepy-0.3.2/template/tests/integration/test_placeholder.py +6 -0
  31. templatepy-0.3.2/template/tests/unit/test_placeholder.py +8 -0
  32. templatepy-0.2.8.dev0/.bumpversion.cfg +0 -32
  33. templatepy-0.2.8.dev0/.gitignore +0 -139
  34. templatepy-0.2.8.dev0/.pre-commit-config.yaml +0 -20
  35. templatepy-0.2.8.dev0/.secrets.baseline +0 -127
  36. templatepy-0.2.8.dev0/CODE_OF_CONDUCT.md +0 -128
  37. templatepy-0.2.8.dev0/CONTRIBUTING.md +0 -7
  38. templatepy-0.2.8.dev0/LICENSE +0 -29
  39. templatepy-0.2.8.dev0/MANIFEST.in +0 -4
  40. templatepy-0.2.8.dev0/PKG-INFO +0 -402
  41. templatepy-0.2.8.dev0/README.md +0 -345
  42. templatepy-0.2.8.dev0/pyproject.toml +0 -114
  43. templatepy-0.2.8.dev0/setup.cfg +0 -4
  44. templatepy-0.2.8.dev0/setup.py +0 -3
  45. templatepy-0.2.8.dev0/templatepy/__init__.py +0 -13
  46. templatepy-0.2.8.dev0/templatepy/example.data.file.config +0 -2
  47. templatepy-0.2.8.dev0/templatepy/example.data.file.test-extension-yu48 +0 -2
  48. templatepy-0.2.8.dev0/templatepy.egg-info/PKG-INFO +0 -402
  49. templatepy-0.2.8.dev0/templatepy.egg-info/SOURCES.txt +0 -21
  50. templatepy-0.2.8.dev0/templatepy.egg-info/dependency_links.txt +0 -1
  51. templatepy-0.2.8.dev0/templatepy.egg-info/entry_points.txt +0 -2
  52. templatepy-0.2.8.dev0/templatepy.egg-info/not-zip-safe +0 -1
  53. templatepy-0.2.8.dev0/templatepy.egg-info/requires.txt +0 -9
  54. templatepy-0.2.8.dev0/templatepy.egg-info/top_level.txt +0 -2
@@ -0,0 +1,17 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ type: software
4
+ title: "templatepy: Copier template for modern Python packages"
5
+ repository-code: https://github.com/larsrollik/templatepy
6
+ url: https://larsrollik.github.io/templatepy
7
+ license: BSD-3-Clause
8
+ authors:
9
+ - family-names: Rollik
10
+ given-names: Lars B.
11
+ orcid: https://orcid.org/0000-0003-0160-6971
12
+
13
+ # After first Zenodo release, add:
14
+ # identifiers:
15
+ # - type: doi
16
+ # value: 10.5281/zenodo.XXXXXXX
17
+ # description: Zenodo concept DOI
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: templatepy
3
+ Version: 0.3.2
4
+ Summary: Copier template for modern Python packages
5
+ Project-URL: Homepage, https://github.com/larsrollik/templatepy
6
+ Project-URL: Documentation, https://larsrollik.github.io/templatepy
7
+ Project-URL: Repository, https://github.com/larsrollik/templatepy
8
+ Author-email: "Lars B. Rollik" <l.b.rollik@protonmail.com>
9
+ Keywords: copier,packaging,python,template
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Software Development :: Code Generators
14
+ Requires-Python: >=3.12
15
+ Description-Content-Type: text/markdown
16
+
17
+ # templatepy
18
+
19
+ Copier template for modern Python packages.
20
+
21
+ **[→ Full documentation](https://larsrollik.github.io/templatepy)**
22
+
23
+ ## Stack
24
+
25
+ | Tool | Role |
26
+ |---|---|
27
+ | uv | dependency management, virtual environments |
28
+ | hatchling + hatch-vcs | build backend; version from git tags |
29
+ | commitizen | Conventional Commits enforcement; auto bump on merge |
30
+ | ruff | linting + formatting |
31
+ | mypy | static type checking |
32
+ | pytest + pytest-cov | testing with coverage |
33
+ | gitleaks | secret scanning |
34
+
35
+ ## Quickstart
36
+
37
+ ```sh
38
+ uv tool install copier
39
+ copier copy gh:larsrollik/templatepy my-new-project
40
+ cd my-new-project
41
+ git init && git add -A && git commit -m "chore: initial commit from templatepy"
42
+ uv sync --extra dev
43
+ uv run pre-commit install --hook-type pre-commit --hook-type commit-msg
44
+ ```
45
+
46
+ ## Update existing project
47
+
48
+ ```sh
49
+ cd my-existing-project && copier update
50
+ ```
51
+
52
+ ## Release flow
53
+
54
+ ```
55
+ feature branch → PR → CI gate (lint + test + secrets) must pass
56
+ merge blocked until green
57
+
58
+ merge to main (rebase)
59
+
60
+ bump.yml fires: cz bump → tag vX.Y.Z
61
+
62
+ release.yml fires on tag:
63
+ → GitHub release (wheel + sdist attached)
64
+ → PyPI via OIDC trusted publishing (no stored token)
65
+ → Zenodo webhook (if enabled)
66
+ ```
67
+
68
+ ## PyPI setup (one-time per repo)
69
+
70
+ Uses OIDC trusted publishing — no API token stored in GitHub secrets.
71
+
72
+ 1. pypi.org → project → Settings → Publishing → Add trusted publisher
73
+ 2. Owner: `<github-user>`, Repository: `<repo>`, Workflow: `release.yml`
74
+ 3. Done — the workflow handles authentication automatically.
75
+
76
+ ## Branch protection (required for CI gate)
77
+
78
+ Repo settings → Branches → Add rule for `main`:
79
+ - ✅ Require status checks: `CI` job
80
+ - ✅ Require branches to be up to date
81
+ - ✅ Require linear history
82
+
83
+ For the auto-bump workflow to push the bump commit back to main:
84
+ - ✅ Allow specified actors to bypass → add `github-actions[bot]`
85
+
86
+ ## Docs
87
+
88
+ ```sh
89
+ uv run mkdocs serve
90
+ ```
91
+
92
+ Deploy to GitHub Pages on push to main via `docs.yml` (automatic).
@@ -0,0 +1,76 @@
1
+ # templatepy
2
+
3
+ Copier template for modern Python packages.
4
+
5
+ **[→ Full documentation](https://larsrollik.github.io/templatepy)**
6
+
7
+ ## Stack
8
+
9
+ | Tool | Role |
10
+ |---|---|
11
+ | uv | dependency management, virtual environments |
12
+ | hatchling + hatch-vcs | build backend; version from git tags |
13
+ | commitizen | Conventional Commits enforcement; auto bump on merge |
14
+ | ruff | linting + formatting |
15
+ | mypy | static type checking |
16
+ | pytest + pytest-cov | testing with coverage |
17
+ | gitleaks | secret scanning |
18
+
19
+ ## Quickstart
20
+
21
+ ```sh
22
+ uv tool install copier
23
+ copier copy gh:larsrollik/templatepy my-new-project
24
+ cd my-new-project
25
+ git init && git add -A && git commit -m "chore: initial commit from templatepy"
26
+ uv sync --extra dev
27
+ uv run pre-commit install --hook-type pre-commit --hook-type commit-msg
28
+ ```
29
+
30
+ ## Update existing project
31
+
32
+ ```sh
33
+ cd my-existing-project && copier update
34
+ ```
35
+
36
+ ## Release flow
37
+
38
+ ```
39
+ feature branch → PR → CI gate (lint + test + secrets) must pass
40
+ merge blocked until green
41
+
42
+ merge to main (rebase)
43
+
44
+ bump.yml fires: cz bump → tag vX.Y.Z
45
+
46
+ release.yml fires on tag:
47
+ → GitHub release (wheel + sdist attached)
48
+ → PyPI via OIDC trusted publishing (no stored token)
49
+ → Zenodo webhook (if enabled)
50
+ ```
51
+
52
+ ## PyPI setup (one-time per repo)
53
+
54
+ Uses OIDC trusted publishing — no API token stored in GitHub secrets.
55
+
56
+ 1. pypi.org → project → Settings → Publishing → Add trusted publisher
57
+ 2. Owner: `<github-user>`, Repository: `<repo>`, Workflow: `release.yml`
58
+ 3. Done — the workflow handles authentication automatically.
59
+
60
+ ## Branch protection (required for CI gate)
61
+
62
+ Repo settings → Branches → Add rule for `main`:
63
+ - ✅ Require status checks: `CI` job
64
+ - ✅ Require branches to be up to date
65
+ - ✅ Require linear history
66
+
67
+ For the auto-bump workflow to push the bump commit back to main:
68
+ - ✅ Allow specified actors to bypass → add `github-actions[bot]`
69
+
70
+ ## Docs
71
+
72
+ ```sh
73
+ uv run mkdocs serve
74
+ ```
75
+
76
+ Deploy to GitHub Pages on push to main via `docs.yml` (automatic).
@@ -0,0 +1 @@
1
+ 0.3.2
@@ -0,0 +1,64 @@
1
+ # templatepy — copier template configuration
2
+ # Usage: copier copy gh:larsrollik/templatepy my-new-project
3
+ # Update: copier update (inside an existing generated project)
4
+
5
+ _subdirectory: template
6
+ _min_copier_version: "9.0"
7
+ _answers_file: .copier-answers.yml
8
+
9
+ # Use [[ ]] delimiters in template files to avoid conflicts with
10
+ # GitHub Actions ${{ }} expression syntax.
11
+ _envops:
12
+ block_start_string: "[%"
13
+ block_end_string: "%]"
14
+ variable_start_string: "[["
15
+ variable_end_string: "]]"
16
+ comment_start_string: "[#"
17
+ comment_end_string: "#]"
18
+
19
+ # ---------------------------------------------------------------------------
20
+ # Questions
21
+ # ---------------------------------------------------------------------------
22
+
23
+ project_name:
24
+ type: str
25
+ help: "Human-readable project name (e.g. 'My Awesome Project')"
26
+
27
+ project_slug:
28
+ type: str
29
+ help: "Python package name — lowercase, underscores (e.g. 'my_awesome_project')"
30
+ default: "{{ project_name | lower | replace(' ', '_') | replace('-', '_') }}"
31
+
32
+ project_description:
33
+ type: str
34
+ help: "Short one-line description"
35
+
36
+ author_name:
37
+ type: str
38
+ help: "Your full name"
39
+
40
+ author_email:
41
+ type: str
42
+ help: "Your email address"
43
+
44
+ github_username:
45
+ type: str
46
+ help: "GitHub username or organization"
47
+
48
+ github_repo:
49
+ type: str
50
+ help: "GitHub repository name"
51
+ default: "{{ project_slug | replace('_', '-') }}"
52
+
53
+ python_requires:
54
+ type: str
55
+ help: "Minimum Python version"
56
+ default: "3.12"
57
+ choices:
58
+ - "3.12"
59
+ - "3.13"
60
+
61
+ year:
62
+ type: int
63
+ help: "Copyright year"
64
+ default: "{{ '%Y' | strftime }}"
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "templatepy"
7
+ dynamic = ["version"]
8
+ description = "Copier template for modern Python packages"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ authors = [
12
+ {name = "Lars B. Rollik", email = "l.b.rollik@protonmail.com"},
13
+ ]
14
+ keywords = ["copier", "template", "packaging", "python"]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Topic :: Software Development :: Code Generators",
20
+ ]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/larsrollik/templatepy"
24
+ Documentation = "https://larsrollik.github.io/templatepy"
25
+ Repository = "https://github.com/larsrollik/templatepy"
26
+
27
+ [tool.hatch.version]
28
+ source = "vcs"
29
+ fallback-version = "0.3.0"
30
+
31
+ [tool.hatch.build.targets.wheel]
32
+ packages = ["src/templatepy"]
33
+
34
+ [tool.hatch.build.targets.wheel.force-include]
35
+ "copier.yaml" = "templatepy/copier.yaml"
36
+ "template" = "templatepy/template"
37
+
38
+ [tool.hatch.build.targets.sdist]
39
+ include = ["src", "copier.yaml", "template", "CITATION.cff", "README.md", "VERSION"]
40
+
41
+ [tool.commitizen]
42
+ version_provider = "commitizen"
43
+ version = "0.3.2"
44
+ version_files = ["VERSION"]
45
+ tag_format = "v$version"
46
+ update_changelog_on_bump = false
@@ -0,0 +1,6 @@
1
+ from importlib.metadata import version, PackageNotFoundError
2
+
3
+ try:
4
+ __version__ = version("templatepy")
5
+ except PackageNotFoundError:
6
+ __version__ = "unknown"
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something isn't working
4
+ labels: bug
5
+ ---
6
+
7
+ ## Description
8
+
9
+ _Clear description of the bug._
10
+
11
+ ## Steps to reproduce
12
+
13
+ 1. ...
14
+ 2. ...
15
+
16
+ ## Expected behaviour
17
+
18
+ _What should happen._
19
+
20
+ ## Actual behaviour
21
+
22
+ _What actually happens._
23
+
24
+ ## Environment
25
+
26
+ - OS:
27
+ - Python version:
28
+ - Package version:
29
+
30
+ ## Additional context
31
+
32
+ _Logs, screenshots, related issues._
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea or improvement
4
+ labels: enhancement
5
+ ---
6
+
7
+ ## Problem
8
+
9
+ _What problem does this solve? What use case does it enable?_
10
+
11
+ ## Proposed solution
12
+
13
+ _Describe what you'd like to see._
14
+
15
+ ## Alternatives considered
16
+
17
+ _Other approaches you've thought about._
18
+
19
+ ## Additional context
20
+
21
+ _Anything else relevant._
@@ -0,0 +1,18 @@
1
+ ## Summary
2
+
3
+ _What does this PR do? Link to any relevant issue with `closes #N`._
4
+
5
+ ## Type
6
+
7
+ - [ ] Bug fix
8
+ - [ ] New feature
9
+ - [ ] Refactor / cleanup
10
+ - [ ] Docs / chore
11
+
12
+ ## Checklist
13
+
14
+ - [ ] Branch created from `main`
15
+ - [ ] Commits follow Conventional Commits (`cz commit`)
16
+ - [ ] Version bumped with `cz bump` and pushed with `--follow-tags` (if releasing)
17
+ - [ ] Tests added or updated
18
+ - [ ] `uv run pre-commit run --all-files` passes locally
@@ -0,0 +1,47 @@
1
+ name: Auto bump
2
+
3
+ # Runs after every push to main. If there are bumpable conventional commits
4
+ # since the last tag, creates a version bump commit + tag and pushes both.
5
+ # The tag push then triggers release.yml.
6
+ #
7
+ # Loop prevention: skips if the triggering commit message starts with "bump:"
8
+ # (i.e. the bump commit itself just pushed back to main).
9
+ #
10
+ # Branch protection: the github-actions bot must be allowed to push to main.
11
+ # Repo settings → Branches → edit main rule →
12
+ # "Allow specified actors to bypass required pull requests" → add github-actions[bot]
13
+
14
+ on:
15
+ push:
16
+ branches: [main]
17
+
18
+ permissions:
19
+ contents: write
20
+
21
+ jobs:
22
+ bump:
23
+ name: Version bump
24
+ runs-on: ubuntu-latest
25
+ if: "!startsWith(github.event.head_commit.message, 'bump:')"
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 0
30
+ token: ${{ secrets.GITHUB_TOKEN }}
31
+
32
+ - name: Configure git identity
33
+ run: |
34
+ git config user.name "github-actions[bot]"
35
+ git config user.email "github-actions[bot]@users.noreply.github.com"
36
+
37
+ - uses: astral-sh/setup-uv@v5
38
+
39
+ - name: Bump version
40
+ run: |
41
+ uvx commitizen bump --yes || EXIT=$?
42
+ if [ "${EXIT:-0}" -eq 21 ]; then
43
+ echo "No bumpable commits since last tag — skipping release."
44
+ exit 0
45
+ fi
46
+ [ "${EXIT:-0}" -eq 0 ] || exit $EXIT
47
+ git push --follow-tags
@@ -0,0 +1,83 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ["**"]
6
+ tags-ignore: ["v*"] # tag pushes are handled by release.yml
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ lint:
15
+ name: Lint
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0 # needed for hatch-vcs version derivation
21
+
22
+ - uses: astral-sh/setup-uv@v5
23
+ with:
24
+ python-version: "[[ python_requires ]]"
25
+
26
+ - name: Install dependencies
27
+ run: uv sync --extra dev
28
+
29
+ - name: Run pre-commit (ruff + mypy + commitizen + gitleaks)
30
+ run: uv run pre-commit run --all-files --show-diff-on-failure
31
+
32
+ test:
33
+ name: Test (Python ${{ matrix.python-version }})
34
+ runs-on: ubuntu-latest
35
+ if: github.event_name == 'pull_request'
36
+ strategy:
37
+ fail-fast: false
38
+ matrix:
39
+ python-version: ["3.12", "3.13"]
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ with:
43
+ fetch-depth: 0
44
+
45
+ - uses: astral-sh/setup-uv@v5
46
+ with:
47
+ python-version: ${{ matrix.python-version }}
48
+
49
+ - name: Install dependencies
50
+ run: uv sync --extra dev
51
+
52
+ - name: Run tests
53
+ run: uv run pytest
54
+
55
+ secrets-scan:
56
+ name: Secrets scan
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+ with:
61
+ fetch-depth: 0
62
+ - uses: gitleaks/gitleaks-action@v2
63
+ env:
64
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65
+
66
+ ci:
67
+ name: CI
68
+ runs-on: ubuntu-latest
69
+ needs: [lint, test, secrets-scan]
70
+ if: always()
71
+ steps:
72
+ - name: Check required jobs
73
+ run: |
74
+ if [[ "${{ needs.lint.result }}" != "success" ]]; then
75
+ echo "lint failed" && exit 1
76
+ fi
77
+ if [[ "${{ needs.test.result }}" != "success" && "${{ needs.test.result }}" != "skipped" ]]; then
78
+ echo "test failed" && exit 1
79
+ fi
80
+ if [[ "${{ needs.secrets-scan.result }}" != "success" ]]; then
81
+ echo "secrets-scan failed" && exit 1
82
+ fi
83
+ echo "All required checks passed."
@@ -0,0 +1,31 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - "docs/**"
8
+ - "mkdocs.yml"
9
+ - "src/**/*.py" # rebuild on source changes if using mkdocstrings
10
+
11
+ permissions:
12
+ contents: write # needed for gh-deploy to push to gh-pages branch
13
+
14
+ jobs:
15
+ deploy:
16
+ name: Deploy docs to GitHub Pages
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # full history for git-revision-date plugin (if added later)
22
+
23
+ - uses: astral-sh/setup-uv@v5
24
+ with:
25
+ python-version: "[[ python_requires ]]"
26
+
27
+ - name: Install dependencies
28
+ run: uv sync --extra dev
29
+
30
+ - name: Deploy
31
+ run: uv run mkdocs gh-deploy --force
@@ -0,0 +1,96 @@
1
+ name: PR Review (optional LLM)
2
+
3
+ # Optional AI-assisted pull request review.
4
+ # Uncomment ONE of the sections below and configure the required secret.
5
+ #
6
+ # This workflow has a no-op placeholder job so it stays valid while
7
+ # both options remain commented out.
8
+
9
+ on:
10
+ pull_request:
11
+ types: [opened, synchronize, ready_for_review]
12
+
13
+ jobs:
14
+
15
+ # ── Option A: Claude API (Anthropic) ─────────────────────────────────────
16
+ # Requires secret: ANTHROPIC_API_KEY
17
+ # Docs: https://docs.anthropic.com/en/api/getting-started
18
+ #
19
+ # llm-review-claude:
20
+ # name: Claude PR review
21
+ # runs-on: ubuntu-latest
22
+ # steps:
23
+ # - uses: actions/checkout@v4
24
+ # with:
25
+ # fetch-depth: 0
26
+ #
27
+ # - name: Generate diff
28
+ # id: diff
29
+ # run: |
30
+ # DIFF=$(git diff origin/main...HEAD -- '*.py' | head -c 8000)
31
+ # echo "content<<EOF" >> "$GITHUB_OUTPUT"
32
+ # echo "$DIFF" >> "$GITHUB_OUTPUT"
33
+ # echo "EOF" >> "$GITHUB_OUTPUT"
34
+ #
35
+ # - name: Review with Claude
36
+ # env:
37
+ # ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
38
+ # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39
+ # PR_NUMBER: ${{ github.event.pull_request.number }}
40
+ # run: |
41
+ # if [ -z "$ANTHROPIC_API_KEY" ]; then
42
+ # echo "ANTHROPIC_API_KEY not set — skipping."
43
+ # exit 0
44
+ # fi
45
+ # REVIEW=$(curl -s https://api.anthropic.com/v1/messages \
46
+ # -H "x-api-key: $ANTHROPIC_API_KEY" \
47
+ # -H "anthropic-version: 2023-06-01" \
48
+ # -H "content-type: application/json" \
49
+ # -d "{
50
+ # \"model\": \"claude-sonnet-4-6\",
51
+ # \"max_tokens\": 1024,
52
+ # \"messages\": [{
53
+ # \"role\": \"user\",
54
+ # \"content\": \"Review this Python PR diff for bugs, style issues, and improvements. Be concise.\n\n${{ steps.diff.outputs.content }}\"
55
+ # }]
56
+ # }" | python3 -c "import sys,json; print(json.load(sys.stdin)['content'][0]['text'])")
57
+ # gh pr comment "$PR_NUMBER" --body "## Claude PR Review\n\n${REVIEW}"
58
+
59
+ # ── Option B: Local Ollama (self-hosted runner) ───────────────────────────
60
+ # Requires: a self-hosted runner with Ollama running on localhost:11434
61
+ # Docs: https://ollama.com / https://docs.github.com/en/actions/hosting-your-own-runners
62
+ #
63
+ # llm-review-ollama:
64
+ # name: Ollama PR review
65
+ # runs-on: self-hosted
66
+ # steps:
67
+ # - uses: actions/checkout@v4
68
+ # with:
69
+ # fetch-depth: 0
70
+ #
71
+ # - name: Generate diff
72
+ # id: diff
73
+ # run: |
74
+ # DIFF=$(git diff origin/main...HEAD -- '*.py' | head -c 4000)
75
+ # echo "content<<EOF" >> "$GITHUB_OUTPUT"
76
+ # echo "$DIFF" >> "$GITHUB_OUTPUT"
77
+ # echo "EOF" >> "$GITHUB_OUTPUT"
78
+ #
79
+ # - name: Review with Ollama
80
+ # env:
81
+ # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
82
+ # PR_NUMBER: ${{ github.event.pull_request.number }}
83
+ # OLLAMA_MODEL: "llama3.2" # change to your preferred model
84
+ # run: |
85
+ # PROMPT="Review this Python PR diff for bugs, style issues, and improvements. Be concise.\n\n${{ steps.diff.outputs.content }}"
86
+ # REVIEW=$(curl -s http://localhost:11434/api/generate \
87
+ # -d "{\"model\": \"${OLLAMA_MODEL}\", \"prompt\": \"${PROMPT}\", \"stream\": false}" \
88
+ # | python3 -c "import sys,json; print(json.load(sys.stdin)['response'])")
89
+ # gh pr comment "$PR_NUMBER" --body "## Ollama PR Review (${OLLAMA_MODEL})\n\n${REVIEW}"
90
+
91
+ # Placeholder — remove once an option above is uncommented
92
+ no-op:
93
+ name: LLM review (not configured)
94
+ runs-on: ubuntu-latest
95
+ steps:
96
+ - run: echo "LLM PR review not configured. See .github/workflows/pr-review.yml."
@@ -0,0 +1,35 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v[0-9]*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write # required for PyPI OIDC trusted publishing
11
+
12
+ jobs:
13
+ release:
14
+ name: Build, release, publish
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0 # required for hatch-vcs to read tags
20
+
21
+ - uses: astral-sh/setup-uv@v5
22
+ with:
23
+ python-version: "[[ python_requires ]]"
24
+
25
+ - name: Build
26
+ run: uv build
27
+
28
+ - name: Create GitHub release
29
+ uses: softprops/action-gh-release@v2
30
+ with:
31
+ files: dist/*
32
+ generate_release_notes: false
33
+
34
+ - name: Publish to PyPI
35
+ run: uv publish --trusted-publishing automatic