Add pre-commit auto-update workflow - #57
Conversation
Adds a monthly (and manually triggerable) workflow that runs pre-commit-update, pushes the result to an update-pre-commit-deps branch, and opens a PR with reviewers and the DevOps label. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
forsyth2
left a comment
There was a problem hiding this comment.
I've visually inspected the PR. As part of this review, providing some explanations for myself from Claude.
What the workflow does
This is a scheduled GitHub Actions job for the zppy-interfaces repo that keeps pre-commit hooks (and their pinned dependency versions in .pre-commit-config.yaml) up to date automatically:
- Trigger: runs on a schedule, or manually via
workflow_dispatch. - Set up environment: creates a conda/micromamba environment with Python 3.14.
- Install tools:
pre-commit, thepre-commit-updatePyPI tool, and GitHub'sghCLI. - Apply updates: clones the repo fresh, creates a branch
update-pre-commit-deps, runspre-commit-update(which bumps hook versions), and commits the result. If nothing changed, thegit commitfails, and that failure is caught to setUP_TO_DATE=trueinstead of erroring out the job. - Push changes: force-pushes the branch — but only if something actually changed (
UP_TO_DATE == 'false'). - Open a PR: creates a pull request from that branch, tagging reviewers and adding a
DevOpslabel — again, only if there were changes.
| # 3. Entry: Day of the month when the process will be started [1-28/29/30/31] | ||
| # 4. Entry: Month of the year when the process will be started [1-12] | ||
| # 5. Entry: Weekday when the process will be started [0-6] [0 is Sunday] | ||
| - cron: '0 8 1 * *' |
There was a problem hiding this comment.
From Claude:
Does cron: '0 8 1 * *' mean 8am on the 1st of every month?
Yes. The five fields are minute hour day-of-month month day-of-week, so:
0→ minute 08→ hour 81→ day-of-month 1*→ every month*→ any day-of-week (irrelevant since day-of-month is already fixed)
So it runs at 08:00 UTC on the 1st of every month. (Cron schedules in GitHub Actions are always in UTC, regardless of where the repo or runner is located.)
| git clone https://github.com/E3SM-Project/zppy-interfaces.git update-pre-commit-deps | ||
| cd update-pre-commit-deps | ||
| # Configure git using GitHub Actions credentials. | ||
| git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" |
There was a problem hiding this comment.
From Claude:
Where does 41898282 come from?
That's the actual GitHub user ID number for the github-actions[bot] account. GitHub documents this as the standard way to author commits "as" the bot so they display with the bot's avatar/identity and are properly attributed as automated commits (e.g., excluded from contributor stats, recognized by GitHub as a bot author). It's not something defined anywhere in this repo — it's a fixed, well-known constant that's commonly copy-pasted into workflows across many projects. You can verify it yourself by checking the public API for that account:
curl https://api.github.com/users/github-actions%5Bbot%5D
which returns "id": 41898282.
| env: | ||
| UP_TO_DATE: false | ||
| PYTHON_VERSION: "3.14" | ||
| REVIEWERS: "xylar,forsyth2" |
There was a problem hiding this comment.
From Claude:
env.* (e.g. env.PYTHON_VERSION, env.UP_TO_DATE, env.REVIEWERS) — these are defined in this file, right at the top under the workflow-level env: block. UP_TO_DATE starts as false and gets overwritten later using echo "UP_TO_DATE=true" >> "$GITHUB_ENV" if the commit step finds no changes — that's the mechanism GitHub Actions provides for a step to update an env var that later steps can read.
| with: | ||
| branch: update-pre-commit-deps | ||
| directory: update-pre-commit-deps | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} |
There was a problem hiding this comment.
From Claude:
secrets.GITHUB_TOKEN — this is not defined anywhere in the file or repo settings. GitHub Actions automatically creates and injects a fresh GITHUB_TOKEN secret for every workflow run, scoped to that repository, with permissions controlled by the repo's Actions settings (Settings → Actions → General → Workflow permissions). You never set this yourself.
There was a problem hiding this comment.
Ah, that's a good point. We need to set this up.
There was a problem hiding this comment.
Oh, or maybe not. Let's see if it's automatic like Claude says.
There was a problem hiding this comment.
(I had to set up my own secret for at least some of my repos, but I guess it wasn't for this.)
| --reviewer ${{ env.REVIEWERS }} \ | ||
| --label DevOps | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} |
There was a problem hiding this comment.
From Claude:
github.token — this is just another way to reference that same automatic token, but via the built-in github context object rather than the secrets context. github.token and secrets.GITHUB_TOKEN refer to the identical token; the workflow actually uses both in different steps (a bit redundant, but harmless).
There was a problem hiding this comment.
Pull request overview
Adds a scheduled (monthly) and manually-triggerable GitHub Actions workflow to
auto-update pre-commit hook revisions, push the results to an
update-pre-commit-deps branch, and open a PR with preset reviewers/label.
Changes:
- Introduces a new Actions workflow triggered by cron +
workflow_dispatch - Creates a micromamba environment, runs
pre-commit-update, commits changes - Pushes the update branch and opens a PR via
gh
Suppressed comments (1)
.github/workflows/pre_commit_update_workflow.yml:79
ghis installed inside the micromamba environment, but this step does not activate that environment, sogh pr createis likely to fail withgh: command not found(each Actions step starts a fresh shell). Activatepre_commit_devhere before runninggh.
- name: Make PR and add reviewers and labels
if: ${{ env.UP_TO_DATE == 'false' }}
run: |
cd update-pre-commit-deps
gh pr create \
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # pre-commit-update doesn't try to include non-release versions | ||
| pre-commit-update | ||
| git add . | ||
| # The second command will fail if no changes were present, so we ignore it | ||
| git commit -m "Update pre-commit dependencies" || ( echo "UP_TO_DATE=true" >> "$GITHUB_ENV") |
There was a problem hiding this comment.
Very good point. I'll add that.
There was a problem hiding this comment.
python scripts/sync_pre_commit_versions.py should address this.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Xylar Asay-Davis <xylarstorm@gmail.com>
The pre-commit auto-update workflow bumped the `rev` values in .pre-commit-config.yaml but left the matching pins in conda/dev.yml and the `qa` extra of pyproject.toml untouched, so the generated PR was internally inconsistent. Add scripts/sync_pre_commit_versions.py, which maps each repo `rev` (and any `additional_dependencies` pinned with `==`) to the exact-pin entries of the same package in conda/dev.yml and pyproject.toml, rewriting them in place. Run it from the workflow right after `pre-commit-update` so the sync lands in the same auto-generated commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (2)
.pre-commit-config.yaml:45
types-PyYAMLis added as anadditional_dependenciesentry without any version constraint. That makes pre-commit runs non-reproducible (future releases could change type stubs and break mypy) and it also diverges from the existing pattern of constraining additional deps (e.g.flake8-isort==...). Consider pinning or at least adding a lower-bound to match the repo’s QA dependency constraints.
hooks:
- id: mypy
args: ["--config=pyproject.toml"]
additional_dependencies: [types-PyYAML]
.github/workflows/pre_commit_update_workflow.yml:93
- This step always runs
gh pr create, which will fail (and fail the scheduled workflow) if an open PR already exists forupdate-pre-commit-depsfrom a prior run. Handling the “PR already exists” case (edit/update it instead of creating a new one) will make the monthly schedule reliable.
- name: Make PR and add reviewers and labels
if: ${{ env.UP_TO_DATE == 'false' }}
run: |
cd update-pre-commit-deps
gh pr create \
--title "Update pre-commit and its dependencies" \
--body "This PR was auto-generated to update pre-commit and its dependencies." \
--head update-pre-commit-deps \
--reviewer ${{ env.REVIEWERS }} \
--label DevOps
Summary
Adds a monthly (and manually triggerable) workflow that runs pre-commit-update, pushes the result to an update-pre-commit-deps branch, and opens a PR with reviewers and the DevOps label.
Select one: This pull request is...
Please fill out either the "Small Change" or "Big Change" section (the latter includes the numbered subsections), and delete the other.
Small Change