Skip to content

fix(pre-commit, github-actions): use tag creation date for cooldown instead of commit date#15350

Open
robaiken wants to merge 19 commits into
dependabot:mainfrom
robaiken:robaiken/pre-commit-cooldown-use-tag-date
Open

fix(pre-commit, github-actions): use tag creation date for cooldown instead of commit date#15350
robaiken wants to merge 19 commits into
dependabot:mainfrom
robaiken:robaiken/pre-commit-cooldown-use-tag-date

Conversation

@robaiken

@robaiken robaiken commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Previously, cooldown in the pre-commit and GitHub Actions ecosystems used the commit's committer date (%cd) to determine when a version was released. This is inaccurate when a tag points to an older commit — for example, when a tag is republished, force-pushed, or created long after the commit was authored.

Changes

Implements a three-tier date resolution strategy for cooldown:

  1. GitHub Release published_at (via Octokit) — most accurate, reflects actual publication time even after re-tagging
  2. Tag creation date (git for-each-ref %(creatordate:iso)) — tagger date for annotated tags
  3. Commit date (git show %cd) — final fallback for lightweight tags

Key implementation details:

  • GitHub releases are fetched once and cached per finder instance (cached_github_releases)
  • Falls back gracefully: no GitHub Release → try tag date → use commit date
  • Works for non-GitHub repos (gracefully falls back to git-based detection)
  • No clone needed when GitHub Release exists (saves time)

Why this matters

Scenario Old behavior New behavior
Tag points to 30-day-old commit, published today Bypasses cooldown ❌ Correctly in cooldown ✅
Mutable tag (v4) force-pushed to new commit Uses old commit date ❌ Uses release publish date ✅
Re-tagged release Uses commit date ❌ Uses new publish date ✅

Testing

Added tests for both ecosystems covering:

  • GitHub Release published_at used when available (skips git clone)
  • Fallback to for-each-ref when no release exists
  • Fallback to commit date when for-each-ref returns empty
  • Annotated tags with old commits correctly apply cooldown
  • Existing cooldown tests continue to pass (they hit the fallback path)

robaiken and others added 2 commits June 18, 2026 11:58
… date

Previously, cooldown used the commit's committer date (%cd) to determine
when a version was released. This is inaccurate when a tag points to an
older commit — for example, when a tag is republished or created long
after the commit was authored. In such cases, the cooldown window could
be incorrectly bypassed because the commit date is already old.

This change uses git for-each-ref with %(creatordate:iso) which returns:
- The tagger date for annotated tags (when the tag was actually created)
- The commit date for lightweight tags (unchanged behavior)

This ensures cooldown evaluates based on when a release was actually made
available, not when the underlying commit was originally authored.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mmit date

Same fix as pre-commit: the commit_metadata_details method now uses
git for-each-ref with %(creatordate:iso) to get the tag creation date
instead of git show --format="%cd" which returns the commit date.

This prevents cooldown bypass when a tag points to an old commit (e.g.,
mutable major-version tags like v4 that get force-pushed to new commits).

Falls back to commit date if for-each-ref returns empty (e.g., tag ref
not found in the bare clone).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the L: github:actions GitHub Actions label Jun 18, 2026
@robaiken robaiken changed the title fix(pre-commit): use tag creation date for cooldown instead of commit date fix(pre-commit, github-actions): use tag creation date for cooldown instead of commit date Jun 18, 2026
Adds tests for both pre-commit and GitHub Actions ecosystems verifying:
- Tag creation date (not commit date) is used for cooldown evaluation
- Fallback to commit date when for-each-ref returns empty
- Annotated tags pointing to old commits correctly apply cooldown
- Mutable tags that are recently re-created are correctly in cooldown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a three-tier fallback for determining release dates in cooldown:
1. GitHub Release published_at via Octokit (most accurate)
2. Tag creation date via git for-each-ref %(creatordate:iso)
3. Commit date via git show %cd (final fallback)

The GitHub Release published_at is the most accurate because it
reflects when the release was actually published, even after re-tagging.
The releases are cached per finder instance to avoid repeated API calls
when iterating multiple candidate versions.

When no GitHub Release exists (e.g., non-GitHub repos, tags without
releases), falls back to the git-based date detection.

Includes tests for both pre-commit and GitHub Actions ecosystems.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves release cooldown accuracy for pre-commit and GitHub Actions git-sourced dependencies by preferring a tag’s creation date (%(creatordate)) over the underlying commit’s committer date, preventing recently created/republished tags that point to older commits from bypassing cooldown.

Changes:

  • pre-commit: evaluate cooldown using tag creation date via git for-each-ref, with fallback to git show commit date when needed.
  • GitHub Actions: update SHA-pinned cooldown date lookup to prefer the latest version tag’s creation date via git for-each-ref, with fallback to git show.
  • Add/adjust specs to stub git for-each-ref behavior and validate fallback behavior.
Show a summary per file
File Description
pre_commit/lib/dependabot/pre_commit/update_checker/latest_version_finder.rb Switch cooldown evaluation from commit date to tag creation date (with fallback).
pre_commit/spec/dependabot/pre_commit/update_checker/latest_version_finder_spec.rb Update cooldown specs to stub the new git for-each-ref command and add coverage for tag-vs-commit date scenarios.
github_actions/lib/dependabot/github_actions/update_checker/latest_version_finder.rb Prefer tag creation date for SHA-pinned cooldown evaluation, falling back to commit date.
github_actions/spec/dependabot/github_actions/update_checker/latest_version_finder_spec.rb Add direct coverage for commit_metadata_details including for-each-ref and fallback paths.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

Comment thread pre_commit/lib/dependabot/pre_commit/update_checker/latest_version_finder.rb Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/5 changed files
  • Comments generated: 2

Comment thread pre_commit/lib/dependabot/pre_commit/update_checker/latest_version_finder.rb Outdated
robaiken and others added 5 commits June 18, 2026 12:28
…ve_messages)

- Extract fetch_date_from_git helper to reduce commit_metadata_details size
- Use instance_double for Sawyer::Resource and Octokit::Client
- Combine multiple stubs with receive_messages

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Normalize tag names (strip 'tags/' prefix) to prevent constructing
  invalid refs like refs/tags/tags/v1.0.0
- Move GitHub Release check before git clone in pre-commit (avoids
  unnecessary clone when published_at is available)
- Fix memoization bug in GitHub Actions (extract resolve method to
  avoid return inside ||= block)
- Make test assertions deterministic (use exact values instead of
  Time.now comparisons)
- Add GitHub releases stubs to git-fallback tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sawyer::Resource uses dynamic attributes via method_missing, so
instance_double cannot verify tag_name/published_at. Switch to
plain double with rubocop disable comment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace git show stub with git for-each-ref in update_checker_spec
- Add GitHub Releases client stub (empty releases for clone fallback)
- Add prerelease: false to Sawyer::Resource doubles to prevent
  leaking into GitCommitChecker#github_release_prerelease?

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Removes rubocop:disable RSpec/VerifiedDoubles comments by using
Struct instead of plain doubles for Sawyer::Resource mocks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 5/6 changed files
  • Comments generated: 1

When only some candidates have GitHub Releases and those are in
cooldown, fall back to git clone for the remaining candidates
instead of incorrectly marking all as rejected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 5/6 changed files
  • Comments generated: 2

Comment thread pre_commit/lib/dependabot/pre_commit/update_checker/latest_version_finder.rb Outdated
When falling back to git clone because some candidates lack releases,
the clone path now still prefers published_at for candidates that DO
have releases, preserving the intended priority:
Release published_at > tag creation date > commit date.

Also fixes method comment to accurately describe return contract.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 5/6 changed files
  • Comments generated: 2

Comment thread pre_commit/lib/dependabot/pre_commit/update_checker/latest_version_finder.rb Outdated
Replace 'return []' with if/else expression inside the ||= block
so empty results (non-GitHub sources) are properly cached and
the release-fetch logic isn't re-evaluated on every call.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 5/6 changed files
  • Comments generated: 0 new

Prevents test failures when run on a different day.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@robaiken robaiken marked this pull request as ready for review June 18, 2026 15:31
@robaiken robaiken requested a review from a team as a code owner June 18, 2026 15:31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@robaiken robaiken force-pushed the robaiken/pre-commit-cooldown-use-tag-date branch from 8e022d9 to a1ff310 Compare June 18, 2026 15:44
robaiken and others added 4 commits June 18, 2026 17:35
Deduplicates cooldown date resolution logic between pre-commit and
GitHub Actions into a common module. Both ecosystems now include
Dependabot::GitCooldownDateResolver and implement two bridge methods:
- cooldown_source_url: returns the git source URL
- cooldown_credentials: returns the credentials array

Shared methods: normalize_tag_name, resolve_candidate_date,
github_release_published_at, tag_creation_date, cached_github_releases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tests all 5 public methods:
- normalize_tag_name (prefix stripping)
- tag_creation_date (for-each-ref + commit date fallback)
- github_release_published_at (release lookup)
- resolve_candidate_date (3-tier priority)
- cached_github_releases (caching, non-GitHub, API errors)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L: github:actions GitHub Actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants