feat: add --cool-down flag to update command with 7d default#29454
feat: add --cool-down flag to update command with 7d default#29454
Conversation
- Add new --cool-down flag (default 7d) to gh aw update command - Create update_cooldown.go with cooldown logic: - parseCoolDownFlag: parse "7d", "168h", "0" formats - isExemptFromCoolDown: exempt actions/* and github/* repos - checkReleaseCoolDown: check if release is within cooldown window - getReleasePublishedAtFn: injectable for tests - Thread coolDown parameter through UpdateWorkflows, UpdateActions, UpdateActionsInWorkflowFiles, updateActionRefsInContent, resolveLatestRelease, resolveLatestRef, resolveRedirectedUpdateLocation - Apply cooldown check after finding a newer release (fail-open if API unavailable) - Update upgrade_command.go to pass 0 cooldown (no cooldown for upgrade) - Add comprehensive tests in update_cooldown_test.go - Update all existing tests to pass 0 cooldown parameter Agent-Logs-Url: https://github.com/github/gh-aw/sessions/259f1ed8-f33f-44f5-99d1-0def0d5d86eb Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…ility Agent-Logs-Url: https://github.com/github/gh-aw/sessions/259f1ed8-f33f-44f5-99d1-0def0d5d86eb Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot actions-lock.json should store the release date |
There was a problem hiding this comment.
Pull request overview
Adds a configurable “cooldown” window to gh aw update so newly published releases are skipped by default (7 days), reducing the chance of adopting very fresh upstream releases.
Changes:
- Introduces
--cool-downflag ongh aw update(default7d;0disables), and threads the value through workflow + action update paths. - Adds new cooldown implementation (
parseCoolDownFlag, exempt repo logic, and release publish-date check via GitHub API) plus unit tests. - Updates upgrade/update call sites and existing tests to accommodate the new cooldown parameter (upgrade uses cooldown
0).
Show a summary per file
| File | Description |
|---|---|
| pkg/cli/update_command.go | Adds --cool-down flag parsing and passes cooldown through RunUpdateWorkflows. |
| pkg/cli/update_workflows.go | Threads cooldown into ref/release resolution and skips updates when latest release is within cooldown. |
| pkg/cli/update_actions.go | Threads cooldown into action updates (lock file + workflow content) and adds per-invocation cooldown caching for workflow file updates. |
| pkg/cli/update_redirects.go | Threads cooldown through redirect resolution’s latest-ref checks. |
| pkg/cli/update_cooldown.go | New core cooldown logic + GitHub release published-at lookup. |
| pkg/cli/update_cooldown_test.go | Unit tests for parsing, exemptions, cooldown decisions, and duration formatting. |
| pkg/cli/upgrade_command.go | Upgrade path calls UpdateActions with cooldown disabled (0). |
| pkg/cli/update_command_test.go | Updates tests to pass cooldown 0 to preserve prior semantics. |
| pkg/cli/update_actions_test.go | Updates tests for new function signatures / cooldown cache parameter. |
| pkg/cli/update_workflows_test.go | Updates tests to pass cooldown 0 to release resolution helpers. |
| pkg/cli/update_redirects_test.go | Updates tests for new cooldown parameter in redirect + latest-ref plumbing. |
| pkg/cli/README.md | Updates documented UpdateActions signature to include cooldown duration. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 12/12 changed files
- Comments generated: 2
| if err := client.Get(fmt.Sprintf("repos/%s/releases/tags/%s", repo, tag), &release); err != nil { | ||
| return time.Time{}, fmt.Errorf("failed to fetch release info for %s@%s: %w", repo, tag, err) |
There was a problem hiding this comment.
The release tag is interpolated into the REST path without URL-escaping. Tags can legally contain characters like / or spaces, which will break the repos/{repo}/releases/tags/{tag} endpoint (or produce the wrong resource). Consider escaping the tag path segment (e.g., via url.PathEscape) before building the URL.
| age := time.Since(publishedAt) | ||
| if age >= coolDown { | ||
| return coolDownCheckResult{} | ||
| } | ||
|
|
||
| remaining := coolDown - age | ||
| ageStr := formatCoolDownDuration(age) | ||
| remainingStr := formatCoolDownDuration(remaining) | ||
| periodStr := formatCoolDownDuration(coolDown) |
There was a problem hiding this comment.
age := time.Since(publishedAt) can be negative if the local clock is behind GitHub’s timestamp (or if the API returns a future published_at due to skew). In that case this code treats the release as being within the cooldown and computes an inflated remaining duration. Consider clamping age to 0 (or treating future timestamps as now) before comparing to coolDown and computing remaining.
🧪 Test Quality Sentinel ReportTest Quality Score: 96/100✅ Excellent test quality
Test Classification DetailsView All Test Classifications (7 tests)
Flagged Tests — Requires ReviewNo tests flagged. All new tests enforce clear behavioral contracts. Language SupportTests analyzed:
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators. References: §25208833812
|
- Add ReleasedAt *time.Time field to ActionCacheEntry (released_at JSON tag) - Add GetReleasedAt / SetReleasedAt methods to ActionCache - Preserve ReleasedAt across Set calls when SHA is unchanged - Clear ReleasedAt when SHA changes (stale date) - UpdateActions now uses cached release date (avoids extra API call on re-runs) and stores the fetched date after the first cooldown check - Add checkReleaseCoolDownWithDate helper for date-only checks - checkReleaseCoolDown now returns PublishedAt in result for caller caching - Add tests for ReleasedAt round-trip, SHA-change clearing, and new helpers Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3a9ffd04-058c-411a-8134-6993565f6214 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in f6f1f16. Added a Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot review all comments, recompile |
- Use url.PathEscape(tag) when building repos/{repo}/releases/tags/{tag}
to safely handle tags containing '/', spaces, or other special chars
- Replace manual if/clamp with max(age, 0) in checkReleaseCoolDownWithDate
to guard against future-dated published_at (clock skew / API skew)
- Add TestCheckReleaseCoolDownWithDate_FutureTimestamp test
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/14860b0f-e157-48f8-b0ba-db670494813c
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in 1f7f45e. Addressed all reviewer comments:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Summary
Adds a cooldown period feature to the
gh aw updatecommand. By default, new releases must be at least 7 days old before they are applied. This prevents accidentally picking up very fresh releases that may have regressions.Changes
New files
pkg/cli/update_cooldown.go: Core cooldown logic:parseCoolDownFlag— parses7d,168h,0etc.isExemptFromCoolDown—actions/*andgithub/*repos always bypass the cooldowncheckReleaseCoolDown— fetches release published date and compares to cooldown window; fail-open (if the date cannot be fetched, the update proceeds); returnsPublishedAtfor cachingcheckReleaseCoolDownWithDate— performs the cooldown check using an already-known date, skipping the API callgetReleasePublishedAtFn— injectable for tests; calls/repos/{repo}/releases/tags/{tag}pkg/cli/update_cooldown_test.go: Comprehensive unit testsModified files
update_command.go: New--cool-downflag (default7d); updatedRunUpdateWorkflowssignatureupdate_workflows.go: ThreadcoolDownthroughUpdateWorkflows→updateWorkflow→resolveLatestRef→resolveLatestRelease; cooldown check after finding a newer releaseupdate_actions.go: ThreadcoolDownthroughUpdateActions(with per-action cooldown check) andUpdateActionsInWorkflowFiles/updateActionRefsInContentupdate_redirects.go: ThreadcoolDownthroughresolveRedirectedUpdateLocationupgrade_command.go: Pass0cooldown (upgrade always applies latest)pkg/workflow/action_cache.go: Addedreleased_atfield toActionCacheEntry; addedGetReleasedAt/SetReleasedAtmethods;SetpreservesReleasedAtwhen SHA is unchanged and clears it when SHA changes0cooldown to preserve existing test semanticsBehaviour
--cool-down 7d— releases published within the last 7 days are skipped--cool-down 0— apply all available releases immediately--cool-down 3dor--cool-down 72h— custom periodactions/*andgithub/*are always updated regardless of cooldownactions-lock.jsonstores thereleased_atdate for each action entry. On the first run that encounters a new release, the date is fetched from the API and persisted. Subsequent runs use the cached date directly, avoiding redundant API calls.Testing
make build✅make lint✅make test-unit✅