Skip to content

GitHub Actions cooldown should use release date instead of tag commit date #13078

@guitarrapc

Description

@guitarrapc

Is there an existing issue for this?

  • I have searched the existing issues

Feature description

The current cooldown implementation for GitHub Actions package-ecosystem: "github-actions" dependencies uses the tag's commit date rather than the GitHub release publication date. This leads to unexpected behavior where cooldown periods don't work as users intuitively expect of Release date.

This affects the user experience significantly when:

  • Projects create tags in advance but publish releases later.

Current Behavior

The cooldown logic in github_actions/lib/dependabot/github_actions/update_checker/latest_version_finder.rb uses commit_metadata_details method which retrieves the commit date of the tag:

  • cooldown_filter method

def cooldown_filter(release)
return release unless cooldown_enabled?
return release unless cooldown_options
Dependabot.logger.info("Initializing cooldown filter")
release_date = commit_metadata_details
unless release_date
Dependabot.logger.info("No release date found, skipping cooldown filtering")
return release
end
if release_in_cooldown_period?(Time.parse(release_date))
Dependabot.logger.info("Filtered out (cooldown) #{dependency.name}, #{release}")
return nil
end
release
end

Problematic Scenario

Consider this timeline:

  1. 100 days ago: Tag v1.0.0 is created
  2. 2 days ago: GitHub release v1.0.0 is published for that tag
  3. Today: With cooldown=7 days, Dependabot immediately creates a PR for v1.0.0.

In this scenario...

  • Current result: PR is created immediately (tag is 100 days old)
  • Expected result: PR should wait 5 more days (release is only 2 days old)

User Expectations

I believe users typically configure cooldown periods to:

  • Allow time for community feedback on new releases
  • Avoid early adopter issues and wait for bug fix releases
  • Observe stability before updating dependencies

The expectation is that cooldown starts from when the release becomes publicly available, not when the underlying code was committed.

Note

Looking into consistency with other ecosystems, other package ecosystems in dependabot-core correctly use release publication dates.

  • Docker: Uses released_at from publication details

def apply_cooldown(candidate_tags)
return candidate_tags if should_skip_cooldown?
candidate_tags.reverse_each do |tag|
details = publication_detail(tag)
next if !details || !details.released_at
return [tag] unless cooldown_period?(details.released_at)
Dependabot.logger.info("Skipping tag #{tag.name} due to cooldown period")
end
[]
end

  • Go Modules: Uses release.released_at

def in_cooldown_period?(release)
begin
release_info = SharedHelpers.run_shell_command(
"go list -m -json #{dependency.name}@#{release.details.[]('version_string')}",
fingerprint: "go list -m -json <dependency_name>"
)
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
Dependabot.logger.info("Error while fetching release date info: #{e.message}")
return false
end
release.instance_variable_set(
:@released_at, JSON.parse(release_info)["Time"] ? Time.parse(JSON.parse(release_info)["Time"]) : nil
)
return false unless release.released_at
current_version = version_class.correct?(dependency.version) ? version_class.new(dependency.version) : nil
days = cooldown_days_for(current_version, release.version)
# Calculate the number of seconds passed since the release
passed_seconds = Time.now.to_i - release.released_at.to_i
passed_days = passed_seconds / DAY_IN_SECONDS
if passed_days < days
Dependabot.logger.info("Version #{release.version}, Release date: #{release.released_at}." \
" Days since release: #{passed_days} (cooldown days: #{days})")
end
# Check if the release is within the cooldown period
passed_seconds < days * DAY_IN_SECONDS
end

  • Git Submodules: Uses release.released_at

def in_cooldown_period?(release)
unless release.released_at
Dependabot.logger.info("Release date not available for ref tag #{release.tag}")
return false
end
days = cooldown_days
passed_seconds = Time.now.to_i - release.released_at.to_i
passed_days = passed_seconds / DAY_IN_SECONDS
if passed_days < days
Dependabot.logger.info("Filtered #{release.tag}, Released on: " \
"#{T.must(release.released_at).strftime('%Y-%m-%d')} " \
"(#{passed_days}/#{days} cooldown days)")
end
passed_seconds < days * DAY_IN_SECONDS
end

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions