Skip to content

cdn sources for gameap, daemon and gameapctl#22

Merged
et-nik merged 2 commits into
mainfrom
сdn-sources
Jul 10, 2026

Hidden character warning

The head ref may contain hidden characters: "\u0441dn-sources"
Merged

cdn sources for gameap, daemon and gameapctl#22
et-nik merged 2 commits into
mainfrom
сdn-sources

Conversation

@et-nik

@et-nik et-nik commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added resilient release discovery and downloads for the application, panel, and daemon.
    • Updates now automatically use the fastest available source and can fall back when a source is unavailable or incomplete.
    • Added support for selecting a preferred release source via configuration.
    • Improved prerelease handling and release asset identification.
  • Bug Fixes

    • Reduced update failures caused by temporary rate limits or unavailable endpoints.
    • Improved retry/failover behavior when a download attempt returns errors, including better handling of missing or unavailable release data.

@et-nik et-nik requested a review from Copilot July 9, 2026 22:59
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a6eb5ed-93a0-4bca-af59-c59a436d3ed4

📥 Commits

Reviewing files that changed from the base of the PR and between 3d446ec and e39592c.

📒 Files selected for processing (3)
  • pkg/releasesource/releasesource_internal_test.go
  • pkg/releasesource/selector.go
  • pkg/releasesource/source.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/releasesource/source.go
  • pkg/releasesource/selector.go
  • pkg/releasesource/releasesource_internal_test.go

📝 Walkthrough

Walkthrough

Release discovery and downloads now use a shared releasesource abstraction with GitHub/CDN selection, probing, fallback, and rate-limit handling. Daemon, panel, and self-update flows consume the new release type and downloader.

Changes

Release source migration

Layer / File(s) Summary
Static release metadata and retry controls
pkg/releasefinder/release_finder.go, pkg/releasefinder/release_finder_test.go
Release assets now include names, static-list lookup supports exact tags, retries can be disabled, and rate-limit errors are classified and tested.
Source configuration and release selection
pkg/releasesource/source.go, pkg/releasesource/selector.go, pkg/releasesource/releasesource_internal_test.go
GitHub and CDN sources are mapped per component, probed and ordered by latency, then used for release resolution with fallback and rate-limit retry behavior.
Release contract and fallback downloads
pkg/releasesource/releasesource.go, pkg/releasesource/releasesource_internal_test.go
Typed releases expose ordered URLs, while download functions try candidates sequentially and support both regular and file downloads.
Daemon, panel, and self-update integration
internal/actions/daemon/..., internal/actions/panel/update/panel_update_v4.go, internal/actions/selfupdate/self_update.go, pkg/panel/install.go
Application flows resolve component-specific releases and download through the shared source abstraction, including prerelease handling and primary-URL logging.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Action
  participant releasesource
  participant selector
  participant GitHubOrCDN
  Action->>releasesource: FindRelease(component, tag, platform)
  releasesource->>selector: Resolve release
  selector->>GitHubOrCDN: Probe and fetch release metadata
  GitHubOrCDN-->>selector: Tag and asset metadata
  selector-->>releasesource: Ordered candidate URLs
  releasesource-->>Action: Release
  Action->>releasesource: Download(release, destination)
  releasesource->>GitHubOrCDN: Try candidate URLs
  GitHubOrCDN-->>releasesource: Download result
  releasesource-->>Action: Completion or error
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.60% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding CDN release sources for gameap, daemon, and gameapctl.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch сdn-sources

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

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 adds a new releasesource package to resolve GameAP component releases from the best available upstream (GitHub Releases API or CDN mirrors), and updates existing install/update flows to use multi-source resolution and download fallback.

Changes:

  • Introduces pkg/releasesource with source probing, ordering, failover logic, and download URL candidate generation.
  • Extends pkg/releasefinder to support static GitHub-format release lists (for CDN mirrors) and adds NoRetry/IsRateLimitError to enable faster failover.
  • Migrates panel/daemon/selfupdate code paths to use releasesource for release resolution and downloads; adds coverage for new behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pkg/releasesource/source.go Defines components, source kinds, default source list, and URL builders.
pkg/releasesource/selector.go Implements probing, ordering, and failover logic across sources.
pkg/releasesource/releasesource.go Public API for finding releases and downloading with URL fallback.
pkg/releasesource/releasesource_internal_test.go Adds tests for probing order, failover, rate-limit behavior, and download fallback.
pkg/releasefinder/release_finder.go Adds static-list resolution, NoRetry, IsRateLimitError, and AssetName.
pkg/releasefinder/release_finder_test.go Adds/updates tests for static-list behavior, NoRetry, and AssetName.
pkg/panel/install.go Switches panel install resolution/download to releasesource.
internal/actions/selfupdate/self_update.go Switches self-update release resolution/download to releasesource.
internal/actions/panel/update/panel_update_v4.go Switches panel update resolution/download to releasesource.
internal/actions/daemon/update/daemon_update.go Switches daemon update downloads and resolution to releasesource.
internal/actions/daemon/install/daemon_install.go Switches daemon install downloads and resolution to releasesource.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +104 to +117
resp, err := httpClient.Do(req)
if err != nil {
return nil, errors.WithMessage(err, "failed to get releases")
}

bodyBytes, err := io.ReadAll(resp.Body)
_ = resp.Body.Close()
if err != nil {
return nil, errors.WithMessage(err, "failed to read response body")
}

if resp.StatusCode != http.StatusOK {
return nil, errors.Errorf("release list request failed with status code %d", resp.StatusCode)
}
@coveralls

coveralls commented Jul 9, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 29057465921

Coverage increased (+1.6%) to 13.176%

Details

  • Coverage increased (+1.6%) from the base build.
  • Patch coverage: 57 uncovered changes across 8 files (250 of 307 lines covered, 81.43%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
pkg/releasesource/selector.go 177 166 93.79%
pkg/releasesource/releasesource.go 30 20 66.67%
pkg/releasefinder/release_finder.go 47 39 82.98%
internal/actions/selfupdate/self_update.go 7 0 0.0%
internal/actions/daemon/install/daemon_install.go 6 0 0.0%
pkg/panel/install.go 6 0 0.0%
internal/actions/daemon/update/daemon_update.go 5 0 0.0%
internal/actions/panel/update/panel_update_v4.go 4 0 0.0%
Total (9 files) 307 250 81.43%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 13798
Covered Lines: 1818
Line Coverage: 13.18%
Coverage Strength: 10.45 hits per line

💛 - Coveralls

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
internal/actions/daemon/install/daemon_install.go (1)

1429-1447: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate release-resolution helper across daemon install/update.

This function is identical to findRelease in internal/actions/daemon/update/daemon_update.go (Lines 266-284): same tag-normalization-for-prerelease logic, same releasesource.FindRelease(ctx, releasesource.ComponentDaemon, ...) call. If prerelease-detection logic ever changes, it's easy to update one copy and miss the other, causing install/update to diverge in behavior.

Consider hoisting this into a shared helper (e.g. in pkg/releasesource) that both callers invoke.

♻️ Proposed shared helper (conceptual, in pkg/releasesource)
// FindReleaseWithPrereleaseDetection resolves a release, automatically
// enabling prerelease matching when opts.Tag has a prerelease suffix.
func FindReleaseWithPrereleaseDetection(
	ctx context.Context, component Component, kernel, platform string, opts releasefinder.FindOptions,
) (*Release, error) {
	if opts.Tag != "" {
		if norm, normErr := releasefinder.NormalizeTag(opts.Tag); normErr == nil && norm.HasPrereleaseSuffix() {
			opts.AllowPrerelease = true
		}
	}

	return FindRelease(ctx, component, kernel, platform, opts)
}
-func findDaemonRelease(ctx context.Context, opts releasefinder.FindOptions) (*releasesource.Release, error) {
-	if opts.Tag != "" {
-		if norm, normErr := releasefinder.NormalizeTag(opts.Tag); normErr == nil && norm.HasPrereleaseSuffix() {
-			opts.AllowPrerelease = true
-		}
-	}
-
-	release, err := releasesource.FindRelease(
-		ctx,
-		releasesource.ComponentDaemon,
-		runtime.GOOS,
-		runtime.GOARCH,
-		opts,
-	)
+func findDaemonRelease(ctx context.Context, opts releasefinder.FindOptions) (*releasesource.Release, error) {
+	release, err := releasesource.FindReleaseWithPrereleaseDetection(
+		ctx,
+		releasesource.ComponentDaemon,
+		runtime.GOOS,
+		runtime.GOARCH,
+		opts,
+	)
 	if err != nil {
 		return nil, errors.WithMessage(err, "failed to find release")
 	}

 	return release, nil
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/actions/daemon/install/daemon_install.go` around lines 1429 - 1447,
Duplicate prerelease-aware release resolution exists in findDaemonRelease and
update’s findRelease. Add a shared helper in pkg/releasesource that normalizes
opts.Tag, enables AllowPrerelease when appropriate, and delegates to
FindRelease; update both callers to use it while preserving their existing error
context.
pkg/releasesource/selector.go (1)

242-271: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Probing GitHub burns a request from the very rate-limit budget this feature aims to protect.

probe() sends a HEAD request to GitHub's API root (https://api.github.com) whenever a kindGitHub source is probed. GitHub counts virtually all REST API requests — HEAD included — against the primary rate limit; only GET /rate_limit is exempt. Since probing happens once per process via sync.Once, this costs one unauthenticated-quota request on every invocation just to measure latency/availability, on top of whatever the actual release lookup and any rate-limit retry consume.

Consider probing GitHub via GET /rate_limit instead (doesn't consume quota) or skipping the network probe for the GitHub source entirely and just relying on the actual find/retry logic to handle unavailability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/releasesource/selector.go` around lines 242 - 271, The probe method sends
a quota-consuming HEAD request for GitHub sources. Update selector.probe to
avoid probing kindGitHub with the generic request, either by using an exempt GET
request to /rate_limit or by returning a non-network probe result and relying on
the release lookup/retry logic for GitHub availability.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/releasesource/selector.go`:
- Around line 40-92: In selector.findRelease, avoid invoking retryGitHub when a
deterministic content error has already been captured from another source. Guard
the githubRateLimited retry block with contentErr == nil, preserving the
existing retry behavior only when no content error is available, then return
contentErr as currently implemented.

---

Nitpick comments:
In `@internal/actions/daemon/install/daemon_install.go`:
- Around line 1429-1447: Duplicate prerelease-aware release resolution exists in
findDaemonRelease and update’s findRelease. Add a shared helper in
pkg/releasesource that normalizes opts.Tag, enables AllowPrerelease when
appropriate, and delegates to FindRelease; update both callers to use it while
preserving their existing error context.

In `@pkg/releasesource/selector.go`:
- Around line 242-271: The probe method sends a quota-consuming HEAD request for
GitHub sources. Update selector.probe to avoid probing kindGitHub with the
generic request, either by using an exempt GET request to /rate_limit or by
returning a non-network probe result and relying on the release lookup/retry
logic for GitHub availability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 28ef0e96-bda7-4e5d-8053-c59456fedb5d

📥 Commits

Reviewing files that changed from the base of the PR and between 721c644 and 3d446ec.

📒 Files selected for processing (11)
  • internal/actions/daemon/install/daemon_install.go
  • internal/actions/daemon/update/daemon_update.go
  • internal/actions/panel/update/panel_update_v4.go
  • internal/actions/selfupdate/self_update.go
  • pkg/panel/install.go
  • pkg/releasefinder/release_finder.go
  • pkg/releasefinder/release_finder_test.go
  • pkg/releasesource/releasesource.go
  • pkg/releasesource/releasesource_internal_test.go
  • pkg/releasesource/selector.go
  • pkg/releasesource/source.go

Comment thread pkg/releasesource/selector.go
@et-nik et-nik merged commit ce54570 into main Jul 10, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants