Skip to content

Commit 851d1c4

Browse files
feat: add example consumer repositories and workflows for CPython Patch PR Action
1 parent e20c7a0 commit 851d1c4

File tree

7 files changed

+227
-1
lines changed

7 files changed

+227
-1
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,20 @@ Set `automerge: true` and wire a follow-up job that applies your preferred autom
135135

136136
---
137137

138+
## Example consumer repositories
139+
140+
Clone one of the templates in [`examples/`](examples) to see the action running in
141+
the context of a real repository:
142+
143+
- [`examples/minimal`](examples/minimal) – single-job workflow scheduled weekly.
144+
- [`examples/guarded`](examples/guarded) – dry-run preview with release-note
145+
gating and concurrency controls.
146+
147+
Each template ships with a README snippet and status badge you can adapt when
148+
bootstrapping your own public showcase repository.
149+
150+
---
151+
138152
## Permissions
139153

140154
The workflow requires:

docs/tasks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ Use Context7 MCP for up to date documentation.
219219
Enable `codeql-analysis`. Attach provenance to releases.
220220
Verify: CodeQL green. Provenance present.
221221

222-
35. [ ] **Example consumer repos**
222+
35. [x] **Example consumer repos**
223223
Public minimal and guarded samples using the Action.
224224
Verify: Badges and scheduled runs visible.
225225

examples/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Example Consumer Repositories
2+
3+
This directory hosts ready-to-fork templates that demonstrate how to adopt the
4+
CPython Patch PR Action in downstream projects. Each template includes:
5+
6+
- A minimal repository `README.md` with status badges you can reuse.
7+
- A scheduled workflow that exercises the action.
8+
- Optional guardrails tailored to the scenario.
9+
10+
To use one of the samples:
11+
12+
1. Create a new public repository (recommended names listed below).
13+
2. Copy the corresponding template files, preserving the directory structure.
14+
3. Update the status badge URLs in the README to match your repository.
15+
4. Push to `main`. The schedule and any manually dispatched runs will validate the setup.
16+
17+
Available templates:
18+
19+
- `minimal/` – single-job workflow that bumps a single CPython track on a weekly cadence.
20+
- `guarded/` – two-stage workflow that performs a dry-run preview before applying updates and requires a protection keyword in release notes before merging.
21+
22+
Badges use the canonical GitHub Actions syntax:
23+
24+
```md
25+
![Workflow status](https://github.com/<owner>/<repo>/actions/workflows/python-version-patch.yml/badge.svg)
26+
```
27+
28+
Replace `<owner>` and `<repo>` with your namespace and repository name after
29+
creating the consumer repo.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: CPython Patch PR (Guarded)
2+
3+
on:
4+
schedule:
5+
- cron: '15 7 * * 1-5' # Weekdays at 07:15 UTC
6+
workflow_dispatch:
7+
8+
concurrency:
9+
group: python-version-patch
10+
cancel-in-progress: false
11+
12+
env:
13+
TRACK: '3.13'
14+
SECURITY_KEYWORDS: 'security,CVE,critical'
15+
16+
jobs:
17+
preview:
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
outputs:
22+
new_version: ${{ steps.preview.outputs.new_version }}
23+
files_changed: ${{ steps.preview.outputs.files_changed }}
24+
skipped_reason: ${{ steps.preview.outputs.skipped_reason }}
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
- name: Preview CPython patch diff
30+
id: preview
31+
uses: casperkristiansson/python-version-patch-pr@v0
32+
with:
33+
track: ${{ env.TRACK }}
34+
dry_run: true
35+
36+
- name: Summarize planned changes
37+
if: steps.preview.outputs.skipped_reason == ''
38+
run: |
39+
echo "Found proposed bump to version: ${{ steps.preview.outputs.new_version }}"
40+
echo "Files changed JSON:"
41+
echo '${{ steps.preview.outputs.files_changed }}'
42+
43+
apply:
44+
needs: preview
45+
if: needs.preview.outputs.skipped_reason == ''
46+
runs-on: ubuntu-latest
47+
permissions:
48+
contents: write
49+
pull-requests: write
50+
environment:
51+
name: production
52+
steps:
53+
- name: Checkout repository
54+
uses: actions/checkout@v4
55+
with:
56+
fetch-depth: 0
57+
58+
- name: Enforce release note guard
59+
env:
60+
NEW_VERSION: ${{ needs.preview.outputs.new_version }}
61+
SECURITY_KEYWORDS: ${{ env.SECURITY_KEYWORDS }}
62+
run: |
63+
if [[ -z "$NEW_VERSION" ]]; then
64+
echo "No new version detected; skipping guard."
65+
exit 0
66+
fi
67+
68+
python - <<'PY'
69+
import os
70+
import sys
71+
import urllib.request
72+
73+
version = os.environ['NEW_VERSION']
74+
keywords = [kw.strip().lower() for kw in os.environ.get('SECURITY_KEYWORDS', '').split(',') if kw.strip()]
75+
if not keywords:
76+
sys.exit(0)
77+
78+
slug = 'python-' + version.replace('.', '')
79+
url = f'https://www.python.org/downloads/release/{slug}/'
80+
print(f'Fetching release notes from {url}')
81+
try:
82+
with urllib.request.urlopen(url, timeout=30) as response:
83+
body = response.read().decode('utf-8', errors='replace').lower()
84+
except Exception as exc: # noqa: BLE001
85+
print(f'Failed to fetch release notes: {exc}')
86+
sys.exit(1)
87+
88+
if any(keyword in body for keyword in keywords):
89+
print('Security keyword detected in release notes.')
90+
else:
91+
print('No security keywords found; aborting update.')
92+
sys.exit(1)
93+
PY
94+
95+
- name: Apply CPython patch update
96+
uses: casperkristiansson/python-version-patch-pr@v0
97+
with:
98+
track: ${{ env.TRACK }}
99+
automerge: false
100+
env:
101+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

examples/guarded/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Guarded CPython Patch PR Example
2+
3+
This template demonstrates a more conservative deployment of the CPython Patch
4+
PR Action. It performs a dry-run preview, checks release notes for security
5+
keywords, and only applies updates when the guard passes.
6+
7+
![Workflow status](https://github.com/<owner>/python-version-patch-pr-example-guarded/actions/workflows/python-version-patch.yml/badge.svg)
8+
9+
## Highlights
10+
11+
- Two-job workflow with a dry-run preview and gated apply step.
12+
- Concurrency group to avoid overlapping runs.
13+
- Example of inspecting `skipped_reason` and release note metadata before
14+
applying changes.
15+
- Ready-made status badge and README snippet for downstream repositories.
16+
17+
## Setup instructions
18+
19+
1. Create a repository named `python-version-patch-pr-example-guarded` (or use
20+
a similar descriptive name).
21+
2. Copy this directory into the new repository root.
22+
3. Replace `<owner>` in the badge URL with your user or organization handle.
23+
4. Update the `SECURITY_KEYWORDS` environment variable if you want to tailor
24+
the release note gate.
25+
26+
After pushing to `main`, the scheduled job runs every weekday at 07:15 UTC. You
27+
can also trigger the workflow manually with `workflow_dispatch` for testing.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: CPython Patch PR
2+
3+
on:
4+
schedule:
5+
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
6+
workflow_dispatch:
7+
8+
jobs:
9+
bump-python:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: Update CPython patch versions
19+
uses: casperkristiansson/python-version-patch-pr@v0
20+
with:
21+
track: '3.12'
22+
env:
23+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

examples/minimal/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Minimal CPython Patch PR Example
2+
3+
This template shows the smallest practical setup for the CPython Patch PR
4+
Action. It monitors a single CPython minor stream and opens a pull request
5+
whenever a new patch becomes available.
6+
7+
![Workflow status](https://github.com/<owner>/python-version-patch-pr-example-minimal/actions/workflows/python-version-patch.yml/badge.svg)
8+
9+
## Repository structure
10+
11+
```
12+
.
13+
├── .github
14+
│ └── workflows
15+
│ └── python-version-patch.yml
16+
└── README.md (this file)
17+
```
18+
19+
## Recommended setup steps
20+
21+
1. Create a repository named `python-version-patch-pr-example-minimal` (or
22+
similar).
23+
2. Copy this directory into the new repository root.
24+
3. Replace `<owner>` in the badge URL above with your GitHub username or
25+
organization.
26+
4. Optionally adjust the cron schedule or tracked CPython version in the
27+
workflow.
28+
29+
The included workflow runs weekly and can also be triggered manually via
30+
`workflow_dispatch`. The action writes updated pins, commits them to the
31+
`chore/bump-python-<track>` branch, and opens or updates a corresponding pull
32+
request.

0 commit comments

Comments
 (0)