repomatic.metadata.git module¶
Git commit-range logic of Metadata.
Resolves the commit range an event bundles, the release commits inside it,
what those commits changed, and the per-commit matrices built by rewinding
the checkout. This is the one concern that can touch the repository state,
always restoring it (see _restored_worktree).
- class repomatic.metadata.git.GitMetadata[source]¶
Bases:
objectCommit ranges, changed files, and the per-commit matrices.
A concern mixin of
Metadata: never instantiated on its own, and reads sibling concerns throughself.- git_deepen(commit_hash, max_attempts=10, deepen_increment=50)[source]¶
Deepen a shallow clone until the provided
commit_hashis found.Progressively fetches more commits from the current repository until the specified commit is found or max attempts is reached.
Returns
Trueif the commit was found,Falseotherwise.- Return type:
- commit_matrix(commits)[source]¶
Pre-compute a matrix of commits.
Danger
This method temporarily modifies the state of the repository to compute version metadata from the past.
To prevent any loss of uncommitted data, it stashes local changes before its checkouts and restores the initial state however the scan exits, through
_restored_worktree().The list of commits is augmented with long and short SHA values, as well as current version. Most recent commit is first, oldest is last.
Returns a ready-to-use matrix structure:
{ "commit": [ "346ce664f055fbd042a25ee0b7e96702e95", "6f27db47612aaee06fdf08744b09a9f5f6c2", ], "include": [ { "commit": "346ce664f055fbd042a25ee0b7e96702e95", "short_sha": "346ce66", "current_version": "2.0.1", }, { "commit": "6f27db47612aaee06fdf08744b09a9f5f6c2", "short_sha": "6f27db4", "current_version": "2.0.0", }, ], }
- property changed_files: tuple[str, ...] | None[source]¶
Returns the list of files changed in the current event’s commit range.
Uses
git diff --name-onlybetween the start and end of the commit range. ReturnsNoneif no commit range is available (e.g., outside CI).
- property binary_affecting_paths: tuple[str, ...][source]¶
Path prefixes that affect compiled binaries for this project.
Combines the static
BINARY_AFFECTING_PATHS(common files likepyproject.toml,uv.lock,tests/) with project-specific source directories derived from[project.scripts]inpyproject.toml.For example, a project with
mpm = "meta_package_manager.__main__:main"addsmeta_package_manager/as an affecting path. This makes the check reusable across downstream repositories without hardcoding source directories.
- property head_commit_message: str[source]¶
Returns
github.event.head_commit.messagefrom the event payload.Set for
pushevents. Empty string for events that do not carry a head commit (pull_request,schedule,workflow_dispatch).
- property yaml_changed: bool[source]¶
Returns
Truewhen the current event’s commit range touches at least one YAML file.Lets per-job lint gates short-circuit on pushes / PRs that don’t touch YAML. Falls back to “repo contains any YAML file” when the commit range is unavailable (
workflow_dispatch), preserving the existing behavior of those manual runs.
- property zsh_changed: bool[source]¶
Returns
Truewhen the current event’s commit range touches at least one Zsh file.Falls back to “repo contains any Zsh file” when the commit range is unavailable.
- property workflows_changed: bool[source]¶
Returns
Truewhen the current event’s commit range touches at least one GitHub workflow file.Falls back to “repo contains any workflow file” when the commit range is unavailable.
- property skip_binary_build: bool[source]¶
Returns
Trueif binary builds should be skipped for this event.Binary builds are expensive and time-consuming. This property identifies contexts where the changes cannot possibly affect compiled binaries, allowing workflows to skip Nuitka compilation jobs.
Three mechanisms are checked:
Branch name — PRs from known non-code branches (documentation,
.mailmap,.gitignore, etc.) are skipped.Version-bump commit — Push events whose head commit is a user-initiated version bump (
Bump (major|minor) version to) are skipped: the bump merge changes only version strings anduv.lock, so the new binary differs from the previous one only in the baked-in version string. The[changelog] Post-release bumpprefix is deliberately not checked here: theprepare-releasemerge bundles the release commit with the post-release-bump commit, and the release commit must still produce its binary.Changed files — Push events where all changed files fall outside
binary_affecting_pathsare skipped. This avoids ~2h of Nuitka builds for documentation-only commits tomain.
- property commit_range: tuple[str | None, str] | None[source]¶
Range of commits bundled within the triggering event.
A workflow run is triggered by a singular event, which might encapsulate one or more commits. This means the workflow will only run once on the last commit, even if multiple new commits were pushed.
This is critical for releases where two commits are pushed together:
[changelog] Release vX.Y.Z— the release commit[changelog] Post-release bump vX.Y.Z → vX.Y.Z— the post-release bump
Without extracting the full commit range, the release commit would be missed since
github.event.head_commitonly exposes the post-release bump.This property also enables processing each commit individually when we want to keep a carefully constructed commit history. The typical example is a pull request that is merged upstream but we’d like to produce artifacts (builds, packages, etc.) for each individual commit.
The default
GITHUB_SHAenvironment variable is not enough as it only points to the last commit. We need to inspect the commit history to find all new ones. New commits need to be fetched differently inpushandpull_requestevents.See also
See also
Pull request events on GitHub are a bit complex, see: The Many SHAs of a GitHub Pull Request.
- property current_commit: Commit[source]¶
Returns the current
Commitobject.Raises if
HEADcannot be resolved (an empty repository), mirroring the previous behavior where traversing an empty history raised too.
- property current_commit_matrix: Matrix | None[source]¶
Pre-computed matrix with long and short SHA values of the current commit.
- property new_commits: tuple[Commit, ...] | None[source]¶
Returns list of all
Commitobjects bundled within the triggering event.This extracts all commits from the push event, not just
head_commit. For releases, this typically includes both the release commit and the post-release bump commit, allowing downstream jobs to process each one.Commits are returned in chronological order (oldest first, most recent last).
- property new_commits_matrix: Matrix | None[source]¶
Pre-computed matrix with long and short SHA values of new commits.
- property release_commits: tuple[Commit, ...] | None[source]¶
Returns list of
Commitobjects to be tagged within the triggering event.This filters
new_commitsto find release commits that need special handling: tagging, PyPI publishing, and GitHub release creation.This is essential because when a release is pushed,
github.event.head_commitonly exposes the post-release bump commit, not the release commit. By extracting all commits from the event (vianew_commits) and filtering for release commits here, we ensure the release workflow can properly identify and process the[changelog] Release vX.Y.Zcommit.We cannot identify a release commit based on the presence of a
vX.Y.Ztag alone. That’s because the tag is not present in theprepare-releasepull request produced by thechangelog.yamlworkflow. The tag is created later by therelease.yamlworkflow, when the pull request is merged tomain.Our best option is to identify a release based on the full commit message, using the template from the
changelog.yamlworkflow.