You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CPython Patch PR Action is a GitHub Action that automatically scans your repository for pinned CPython patch versions (e.g. `3.12.4`) and opens an evergreen pull request whenever a new patch release is available. It keeps Dockerfiles, GitHub workflows, `.python-version`, `pyproject.toml`, `runtime.txt`, `Pipfile`, Conda environment files, and more aligned with the latest stable runtime—helping teams maintain secure, up-to-date Python environments without custom automation.
3
+
Automate CPython patch updates across every Python version reference in your repo. This GitHub Action handles security maintenance, Python version management, and CI/CD automation without custom scripts.
4
4
5
-
---
5
+
> Star and watch to get updates. Try the quick start below.
6
+
7
+
## Why this Action
8
+
9
+
DevOps, SRE, platform, and Python maintainers need consistent runtimes without manual patching. This action:
10
+
11
+
* Finds pinned CPython versions everywhere you declare them.
12
+
* Resolves the latest stable patch and opens an evergreen PR.
13
+
* Minimizes diffs and noise. Adds auditability and easy rollbacks.
* Cross-file detection: Dockerfiles, GitHub workflows, `.python-version`, `.tool-versions`, `runtime.txt`, `tox.ini`, `pyproject.toml`, `Pipfile`, Conda `environment.yml`, and more.
21
+
* Smart discovery: Pulls CPython tags from GitHub with python.org fallback. Checks GitHub runner availability. Pre-release guard on by default.
22
+
* Minimal rewrites: Targeted replacements that preserve image suffixes like `-slim` and `-alpine`. Dry-run summary before writes.
23
+
* Idempotent: Skips if already on latest and sets `skipped_reason=already_latest`.
24
+
* Branch and PR automation: Predictable branch name. Updates an existing PR or opens a new one via Octokit.
25
+
* External PR support: Emits outputs for `peter-evans/create-pull-request` when preferred.
26
+
* Automerge ready: Hook for label or merge after checks pass.
27
+
* Security keyword gate: Only upgrade if release notes include keywords such as `CVE` or `security`.
28
+
* Offline snapshots: Run without network using provided tag, runner, and release notes snapshots.
29
+
* CI matrix fan-out: Output a change matrix to scope targeted jobs.
6
30
7
31
## Quick start
8
32
9
-
1.**Add the workflow**
33
+
1. Add a scheduled workflow.
10
34
11
35
```yaml
12
36
name: CPython Patch Bot
@@ -34,34 +58,28 @@ CPython Patch PR Action is a GitHub Action that automatically scans your reposit
34
58
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35
59
```
36
60
37
-
2. **Review the pull request** – When a patch release appears, the action creates (or updates)`chore/bump-python-<track>` with all replacements and opens a PR against your default branch.
61
+
2. Review the PR. The action creates or updates `chore/bump-python-<track>` and opens a PR against the default branch.
38
62
39
-
3. **Merge or enable automerge** – Set `automerge: true` if you want the action (or a follow-up workflow) to merge after checks succeed.
63
+
3. Merge or enable automerge. Set `automerge: true` or wire your own automerge job.
40
64
41
-
---
65
+
## How it works
42
66
43
-
## Highlights
44
-
45
-
- 🔍 **Cross-file detection:** Finds pinned CPython versions in Dockerfiles, GitHub Actions workflows, `.python-version`, `.tool-versions`, `runtime.txt`, `tox.ini`, `pyproject.toml`, `Pipfile`, Conda `environment.yml`, and more.
46
-
- 🧠 **Smart discovery:** Pulls CPython tags from GitHub, falls back to python.org, checks GitHub runner availability, and enforces a pre-release guard by default.
47
-
- ✏️ **Minimal rewrites:** Calculates targeted replacements, preserves suffixes (e.g. `-slim`, `-alpine`), and emits a dry-run summary before writing.
48
-
- 🔁 **Idempotent runs:** Detects when everything is already on the latest patch and sets `skipped_reason=already_latest` to avoid noisy PRs.
49
-
- 🌿 **Branch + PR automation:** Creates a consistent branch name, commits changes, and either updates an existing PR or opens a new one via Octokit.
50
-
- 🔌 **External PR support:** Optionally emit metadata for `peter-evans/create-pull-request` if you prefer that workflow.
51
-
- 🤖 **Automerge ready:** Honor the `automerge` flag by labeling or merging once checks pass (implementation hook provided).
52
-
53
-
---
67
+
1. Scan repository for pinned CPython patch versions like `3.12.4` across supported files.
68
+
2. Discover latest patch for the selected `track` using GitHub tags with python.org fallback.
| `new_version` | Highest CPython patch identified during the run. |
85
101
| `files_changed` | JSON array of files rewritten. |
86
-
| `change_matrix` | JSON object suitable for `strategy.matrix` fan-out (entries contain `file` and `new_version`). |
102
+
| `change_matrix` | JSON object for `strategy.matrix` fan-out with entries `{ file, new_version }`. |
87
103
| `skipped_reason` | Machine-readable reason when no PR is created (`already_latest`, `multiple_tracks_detected`, `pre_release_guarded`, etc.). |
88
104
89
-
---
105
+
## Usage patterns
90
106
91
-
## Advanced configuration
92
-
93
-
### Dry-run previews
107
+
### Dry-run preview
94
108
95
109
```yaml
96
110
- name: CPython bump preview
@@ -100,18 +114,29 @@ Dockerfile
100
114
dry_run: true
101
115
```
102
116
103
-
The action prints a summary listing file paths, line numbers, and `old -> new` replacements so you can see the impact before committing.
117
+
Prints file paths, line numbers, and `old -> new` replacements before committing.
104
118
105
119
### Pre-release guard override
106
120
107
-
Keep release candidates out of production by default. Opt in when you intentionally want `rc`/alpha/beta builds:
108
-
109
121
```yaml
110
122
with:
111
123
include_prerelease: true
112
124
```
113
125
114
-
### External PR workflow
126
+
### Security keyword gate
127
+
128
+
Only roll forward when release notes match keywords.
129
+
130
+
```yaml
131
+
with:
132
+
security_keywords: |
133
+
CVE
134
+
security
135
+
```
136
+
137
+
When set, the action fetches GitHub release notes for the resolved tag (or uses `RELEASE_NOTES_SNAPSHOT`) and skips unless a keyword matches.
138
+
139
+
### External PR workflow (peter-evans)
115
140
116
141
```yaml
117
142
- name: Bump CPython patch versions
@@ -131,24 +156,11 @@ with:
131
156
132
157
### Automerge guidance
133
158
134
-
Set `automerge: true` and wire a follow-up job that applies your preferred automerge strategy (label-based, direct merge, etc.) based on the outputs emitted by the action.
159
+
Set `automerge: true` and attach your merge strategy in a follow-up job based on the action outputs.
135
160
136
-
### Security keyword gate
137
-
138
-
Supply `security_keywords` (one per line) to require matching terms inside the CPython release notes before applying an update. This is useful for only auto-rolling releases that contain security fixes:
139
-
140
-
```yaml
141
-
with:
142
-
security_keywords: |
143
-
CVE
144
-
security
145
-
```
146
-
147
-
When the keywords are provided, the action fetches the GitHub release notes for the resolved tag (or uses the optional `RELEASE_NOTES_SNAPSHOT` offline input) and skips the run unless at least one keyword is present.
148
-
149
-
### Matrix fan-out for CI
161
+
### CI matrix fan-out
150
162
151
-
Use the `change_matrix` output to drive follow-up jobs that need to iterate over the files touched by the upgrade:
163
+
Drive targeted follow-up jobs using the `change_matrix` output.
152
164
153
165
```yaml
154
166
jobs:
@@ -170,89 +182,70 @@ jobs:
170
182
- run: npm test -- ${{ matrix.file }}
171
183
```
172
184
173
-
Each matrix entry exposes `matrix.file` and `matrix.new_version`, enabling you to scope lint or test jobs to the files rewritten during the patch.
185
+
### Renovate and Dependabot coexistence
174
186
175
-
### Renovate/Dependabot coexistence
187
+
Avoid competing PRs while keeping other automated dependency updates.
176
188
177
-
If Renovate or Dependabot also try to bump CPython patch versions, they will race with this action
178
-
and open competing pull requests. Use the sample configurations below to disable CPython patch bumps
179
-
while still allowing those tools to manage other dependencies:
189
+
* `examples/coexistence/renovate.json` disables patch updates for the `python` base image and matching regex managers.
190
+
* `examples/coexistence/dependabot.yml` ignores semver patch updates for the `python` Docker image.
180
191
181
-
- `examples/coexistence/renovate.json`disables patch updates for the `python` base image in Dockerfiles
182
-
and any custom regex managers that match CPython pins.
183
-
- `examples/coexistence/dependabot.yml`ignores semver patch updates for the `python` Docker image
184
-
while keeping other ecosystems enabled.
192
+
Both samples are validated by tests. Copy and adjust schedules or rules as needed.
185
193
186
-
Both samples are validated by the test suite so you can copy them verbatim and adjust schedules or
187
-
additional dependency rules as needed.
188
-
189
-
---
190
-
191
-
## Example consumer repositories
192
-
193
-
Clone one of the templates in [`examples/`](examples) to see the action running in
0 commit comments