Skip to content

Pin a branch reference to a commit #322

Description

@fniessink

The problem

A GitHub Action referenced by a branch gets no pin. The README says so under GitHub Actions and pre-commit hooks: "An action referenced by a branch gets no pin, since it resolves to no version. Neither does a rev: that names a branch, or one that is already a bare commit SHA without a # frozen: comment."

That leaves the most exposed reference unprotected. uses: actions/checkout@main runs whatever the branch points at on the day the workflow runs, and whoever controls the repository can move it between two runs. Pinning to a commit SHA exists for exactly that risk, and the reference that carries the most of it is the one Update-time never pins.

A branch reference is not ignored today. _ACTION_RE in src/update_time/updaters/update_github_action.py matches it, and its repository is checked for staleness and archival. Only the pin is missing.

The commit is one request away

_get_commit(owner, repository, ref) in src/update_time/sources/github.py already fetches a commit by ref, and GitHub's commits endpoint accepts a branch name as that ref.

Probed 2026-09-03:

Reference Commit
actions/checkout@main f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a
pre-commit/pre-commit-hooks@main 44d7f9b7e32225d2bd590282037e4650064f3950

What the increment adds

A branch reference is pinned to the commit the branch points at, and the branch name travels beside it, the way a version does today:

uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # main

The branch name has to survive in the file. Without it the reference is a bare commit SHA, and the next run cannot tell which branch to follow, or that a branch was ever meant.

Decisions to take

What a later run does with it. A version tag moving is drift, and Update-time warns rather than adopting. A branch moving is what a branch does, so a warning at every run would be noise, and adopting silently would defeat the pin. Three candidate rules:

  • Hold the commit and say nothing, so the pin behaves like a frozen reference until the user changes it.
  • Hold the commit and report the newer one at INFO, so the user sees what adopting would take.
  • Adopt the newer commit, and require the reference to opt in with a marker first.

The third fits the existing language, where allow[hash-drift] already means adopting what a reference now points at. Whether a moving branch is hash drift, or a scope of its own, is the question to settle before any code moves.

The cooldown. A commit has a date, so the cooldown can hold a fresh commit back the way it holds a fresh release back. Whether it should, for a reference whose author chose to follow a branch, is a policy question rather than a technical one.

Pre-commit hooks. A rev: naming a branch has the same gap. Whether pre-commit's # frozen: convention can carry a branch name, and what pre-commit autoupdate then does with the line, has to be probed before this reaches .pre-commit-config.yaml.

Out of scope

A local action, which carries no @ and names no repository.

A rev: that is already a bare commit SHA with no comment. Nothing in the file says which branch or tag it came from, so there is nothing to follow.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions