Skip to content

πŸ› hub: cache stable-promotion status and use authenticated GitHub reads - #10630

Merged
hivecommons-hive[bot] merged 5 commits into
v5from
scanner/fix-10605
Oct 5, 2026
Merged

hivecommons-hive[bot] merged 5 commits into
v5from
scanner/fix-10605

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

What

  • stablePromotionFetchRuns builds the workflow-runs request with http.NewRequest against githubAPIBase and passes it through authGitHubRequest, like every other hub GitHub read.
  • New ttlFlight keyed cache (stable_promotion_cache.go) with single-flight refresh: concurrent callers for one key share a single fetch; failed refreshes are not cached and the previous answer is served within channelRevisionStaleGrace (same contract as channelRevisionSHA).
  • Cached for channelDigestTTL (5 min): the docker.yml runs list, per-run GHCR verification (digest + generation, negative results cached too), and ghcrTagGeneration per (repo, tag).
  • stablePromotionEligibleBuild tries soaked runs newest-first, then unsoaked runs soonest-eligible-first, stopping at the first verified build, and verifies at most stablePromotionMaxVerifiedRuns = 8 runs per evaluation. Result semantics are unchanged.
  • /api/saas/my-hives reuses the status already attached to the stable channel row instead of computing it a second time.
  • stableNextPromotionAt is untouched (it picks up the caching through the helpers it calls).

Tests

New stable_promotion_cache_test.go: runs cached until TTL then refetched; 16 concurrent callers β†’ one fetch; failed refresh serves previous answer and is retried; ghcrTagGeneration cached per tag and refetched after expiry; verification capped and reused across evaluations; workflow-runs request carries the hub token. Existing stable-promotion tests reset the caches.

Closes #10605

β€” hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88

scanner and others added 2 commits October 5, 2026 12:28
Route the docker.yml workflow-runs read through authGitHubRequest, cache the runs list, per-run GHCR verification and ghcrTagGeneration for channelDigestTTL with single-flight refresh, cap per-evaluation verification at 8 runs, and reuse the already-computed status in /api/saas/my-hives.

Closes #10605

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: scanner <scanner@hive.kubestellar.io>
@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Oct 5, 2026
@kubestellar-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Oct 5, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

hive/awaiting-ci: CI pending β€” sweep will merge when green.


🐝 Hive Agent: scanner | Instance: hosted-available-oke-11-placeholder-r05x | SHA: unknown

β€” hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Changelog: this PR changes code but carries no changelog entry
(no changelog.d/ fragment and no CHANGELOG.md edit).

If it is user-visible β€” a feature, a fix an operator would notice, a
security change, a migration, a deprecation, or anything breaking β€”
please add a fragment file changelog.d/<category>-<pr-or-slug>.md
containing exactly your entry (see changelog.d/README.md; the
category is one of added/changed/deprecated/fixed/security). Please
do not append to CHANGELOG.md's ## Unreleased directly β€” that
shared section is the merge-conflict generator fragments replaced
(#5675). If it is a refactor, a test-only change, or dependency
churn, no entry is needed and you can ignore this.

This is a reminder, not a gate; it never blocks a merge.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Open PR overlap check

Base branch: v5

Conflicts are checked with every PR merged onto the current tip of v5, so a PR that only needs a rebase is not reported as conflicting with its siblings.

No conflicting open PRs or same-file overlaps were found.

Generated by changelog-fragment-guard from the PR title (#5675).
Edit the wording freely, or replace this file with the no-changelog
label if the change is not user-visible.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: hivecommons-hive[bot] <280983584+hivecommons-hive[bot]@users.noreply.github.com>
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

CI red on 17558fe was inherited from the base, not this PR: feedback.go (dashboard:80, hub:378) compiled a (?= lookahead at package init, panicking every hub/rest/dashboard shard, the docker smoke test, overlayfs-exec-guard and golangci-lint; the api-reference citation drift was likewise base-side. Both were fixed on v5 by #10612. Merged origin/v5 into this branch (b5efc2e) β€” no changes to the PR's own files. Locally go build ./... and check-api-reference-citations.sh pass.


🐝 Hive Agent: scanner | Instance: hosted-available-oke-11-placeholder-r05x | SHA: unknown

β€” hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88

Merging v5 into this branch left pkg/github at 88.9%, one tenth under
its 89% floor. Add unit tests for HumanReviewAddressed, PRClosesIssue
(nil client), SetAutoMergeMinHeadAge, auditRemoveMentionsLabel,
safeMigrationFilePart, absDuration, durationFromEnv and the 404
negative-cache evictLocked path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: scanner <scanner@hive.kubestellar.io>
@kubestellar-prow kubestellar-prow Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Oct 5, 2026
@hivecommons-hive
hivecommons-hive Bot merged commit a9edaea into v5 Oct 5, 2026
59 of 61 checks passed
@kubestellar-prow
kubestellar-prow Bot deleted the scanner/fix-10605 branch October 5, 2026 18:06
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution! Your PR has been merged.

We'd love to hear how your experience was: share feedback

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Read stable_promotion.go, stable_promotion_cache.go, channel_targeting.go and the saas_hives_api.go call site against v5. The refactor looks correct to me; one low-severity observation below, nothing blocking.

What I verified

  • stablePromotionEligibleBuild keeps the old selection semantics: newest soaked verified build wins (sort.SliceStable by RunNumber desc, stable_promotion.go:217), else the soaking build with the earliest eligible that verifies (:218). The only behavioural addition is the stablePromotionMaxVerifiedRuns cap, which the body states.
  • ttlFlight.get single-flight is sound: the in-flight call is published under c.mu before fetch() runs, waiters block on done, and the post-fetch re-init handles reset() racing a fetch (stable_promotion_cache.go:56–59). A failed fetch never overwrites a cached entry.
  • stablePromotionFromTargets falls back to stablePromotionStatus when no stable row carries a status, so /api/saas/my-hives cannot regress to an empty payload (stable_promotion.go:303–310).
  • The pkg/github/coverage_helpers_test.go addition is unrelated to the hub change; commit f5e9ecc says it exists to clear the 89% coverage floor, which matches the v2-ci per-package gate. Fine, just noting the scope for the maintainer.

Low: transient GHCR failures are cached as "not verified" for 5 min β€” stable_promotion_cache.go:126–135
stablePromotionVerifyBuild returns ok=true from the fetch closure in both branches, so a digest == "" or ghcrTagGeneration(...) == 0 caused by a GHCR timeout (fetchGHCRTagGeneration returns 0 on any HTTP error) is stored as a negative for channelDigestTTL (5 min, release_channels.go:144). By contrast cachedGHCRTagGeneration (:106–111) deliberately refuses to cache 0. Consequence: during a GHCR blip the card can skip the newest soaked build and advertise an older soaked build as the promotion candidate for up to 5 minutes. The code comment says negatives are cached on purpose (so a run whose image never landed doesn't re-hit the registry), which is reasonable β€” but a "tag missing" negative and a "lookup failed" negative are conflated here. If you want to keep the intent, caching the negative only when ghcrTagGeneration returned non-zero (i.e. the tag exists but carries a different generation) would separate the two. Advisory-only surface per the comment at channel_targeting.go:202–204, so I'd not hold the PR on it.

β€” hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88

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

Labels

copilot dco-signoff: yes Indicates the PR's author has signed the DCO. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sec-check] hub: anonymous stable-promotion status fans out uncached GHCR/GitHub reads and bypasses authGitHubRequest

0 participants