Skip to content

ci: automate the template's action pins - #62

Draft
tsvikas wants to merge 5 commits into
mainfrom
ci/automate-template-action-pins
Draft

ci: automate the template's action pins#62
tsvikas wants to merge 5 commits into
mainfrom
ci/automate-template-action-pins

Conversation

@tsvikas

@tsvikas tsvikas commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Closes the gap found while auditing the action pins: nothing watches
project_name/.github/workflows/, so those pins drift silently until someone
bumps them by hand.

Why not Dependabot

Its github-actions ecosystem only parses *.yml/*.yaml. Three of the four
template workflows are .jinja, so it sees only deps-update.yml. Setting
directory: /project_name would point it at the right folder (for
github-actions, directory: foo means foo/.github/workflows) but would not
change which extensions it parses. Renaming the templates is not available
either: ci.yml.jinja has lines like {%- if format_tool == "black" %} inside
a steps: sequence, which is not parseable YAML. The general request is
dependabot-core#5970,
still open.

pinact rewrites line by line instead of parsing YAML, so the templating is
irrelevant to it.

Design notes

  • Scoped to project_name/. Root workflows stay with Dependabot. Running
    both over the same lines would produce competing PRs.
  • Runs twice. A pin whose comment is a moving tag (# release/v1) needs one
    pass to resolve the comment to the version the SHA actually is, and only then
    can the next pass see a newer release exists. Verified: one pass took
    gh-action-pypi-publish from # release/v1 only as far as # v1.14.0; the
    second reached v1.14.1. The second pass is a no-op once converged.
  • xargs -0 -r. -0 because one template filename contains spaces. -r
    because with no file arguments pinact falls back to scanning
    .github/workflows, which would silently retarget the step at the root
    workflows if the glob ever stopped matching.
  • --min-age 7. Gates updates the way cooldown.default-days does for
    Dependabot: a pin will not move onto a release whose commit is younger than 7
    days. It also fails the run when a pin already in the tree is that young, which
    is kept deliberately rather than suppressed via min_age.always: false -- the
    updater cannot introduce such a pin itself, so one that fresh got there by hand.
    Note this fails today, because setup-uv v9.0.0 was pinned in 80fe49b at 5 days
    old. It clears on 2026-07-28, ahead of the first scheduled run on 2026-08-01.
  • Install is checksum-verified against the release's checksums.txt.

Verification

Ran the exact command from the workflow against a clone of this branch, with
checkout (9 sites, .jinja), prek-action (.jinja) and
gh-action-pypi-publish (the {% raw %}{% if in_pypi %}{% endraw %} file) reverted to older
SHAs and stale comments. It restored every one and the net diff against HEAD
came back empty. actionlint, zizmor, check-github-workflows and yamllint all
pass on the new workflow.

Not verified end to end: the scheduled run itself. Worth a workflow_dispatch
after merge.

Known limitation

PRs opened with GITHUB_TOKEN do not trigger on: pull_request workflows, so
the generated PR will not run CI on its own. The template's existing
deps-update.yml has the same property. A PAT or GitHub App token in the
token: input fixes it if that matters.

Possible follow-up

pinact run --verify in uv-tests.yml would catch a comment that disagrees
with its SHA, which is exactly the actions/cache # v5 bug this audit turned
up. Left out to keep this focused.

tsvikas and others added 2 commits July 26, 2026 14:58
Dependabot cannot reach the pins under project_name/.github/workflows/. Its
github-actions ecosystem only parses *.yml/*.yaml, and three of the four
template workflows are .jinja. Renaming them does not help either, because
Jinja control blocks inside a `steps:` sequence are not parseable YAML
(dependabot-core#5970 tracks the general gap). Until now those pins only moved
when someone bumped them by hand, which is how they drifted.

pinact rewrites line by line rather than parsing YAML, so the templating is
irrelevant to it, including the file named
"{% if in_pypi %}build-and-publish.yml{% endif %}.jinja".

Scoped to project_name/ on purpose: the root workflows stay with Dependabot,
since two updaters over the same lines would produce competing PRs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JP6NCazpaMz2Xfejds3mxq
The original cadence just mirrored dependabot's. That matching is not worth
much here: this updater has no cooldown equivalent to dependabot's
cooldown.default-days, so the tradeoff is different. A monthly run keeps each
PR down to a handful of pins, which is the difference between reviewing a bump
and rubber-stamping one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JP6NCazpaMz2Xfejds3mxq
@tsvikas
tsvikas force-pushed the ci/automate-template-action-pins branch from e7132aa to 23e8c85 Compare July 26, 2026 12:14
tsvikas and others added 3 commits July 26, 2026 15:22
Mirrors cooldown.default-days in .github/dependabot.yml, which the updater
otherwise had no equivalent of.

--min-age carries a second behaviour worth keeping rather than suppressing
(config `min_age.always: false` would drop it): the run fails outright when a
pin already in the tree is younger than the threshold. The updater itself can
never introduce one, since it will not move a pin onto a release that young, so
a pin that fresh arrived by hand. That is the case worth stopping for.

It fails right now for exactly that reason: setup-uv v9.0.0 was pinned in
80fe49b while its commit was 5 days old. It crosses the line on 2026-07-28,
before the next scheduled run on 2026-08-01.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JP6NCazpaMz2Xfejds3mxq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant