Skip to content

Implement Phase 1 self-update core infrastructure#2

Merged
tayyebi merged 4 commits intomainfrom
copilot/implement-self-update-infrastructure
Jan 7, 2026
Merged

Implement Phase 1 self-update core infrastructure#2
tayyebi merged 4 commits intomainfrom
copilot/implement-self-update-infrastructure

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 5, 2026

Adds foundational infrastructure for cross-platform self-updates: version management, GitHub Releases API integration, platform detection, and asset selection. Supports 5 target platforms with pre-release channel handling.

Module Structure

src/update/
├── version.rs      # Semver parsing/comparison with pre-release support
├── github.rs       # Releases API client with rate limiting
├── platform.rs     # Runtime OS/arch → target triple mapping
├── asset.rs        # Binary selection from release assets
├── channel.rs      # Stable/beta/alpha/rc detection
├── error.rs        # Typed errors with actionable messages
└── mod.rs          # Public API: check_for_update()

Key Implementation Details

Version handling: Parses v1.2.3[-prerelease] format, compares major > minor > patch with stable > pre-release precedence.

Platform support: Maps runtime detection to exact target triples:

  • Linux: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu
  • macOS: x86_64-apple-darwin, aarch64-apple-darwin
  • Windows: x86_64-pc-windows-msvc (with .exe handling)

Asset matching: Parses zy-{VERSION}-{TARGET}[.exe] naming convention from CI workflow, validates extension consistency.

Rate limiting: Inspects X-RateLimit-* headers, returns errors with reset timestamps instead of silent failures.

Example Usage

use zy::update::{check_for_update, Channel, Platform, select_asset_for_platform};

// Check for updates on stable channel
if let Some(release) = check_for_update(Channel::Stable).await? {
    let platform = Platform::current();
    let asset = select_asset_for_platform(&release.assets, &platform)?;
    println!("Update available: {} at {}", release.version, asset.download_url);
}

Dependencies

  • chrono = "0.4" for rate limit timestamp formatting

Test Coverage

  • 29 unit tests (version parsing, platform detection, asset selection)
  • 3 integration tests (with 2 ignored to avoid rate limiting in CI)
  • 13 doc tests validating public API examples

No panics in production code; only 2 expect() calls (HTTP client creation, compile-time version constant).

Original prompt

Phase 1: Self-Update Core Infrastructure

🎯 Objective

Implement the foundational infrastructure for a robust, cross-platform self-update mechanism. This phase establishes version management, GitHub API integration, platform detection, and asset selection logic.

📦 Current Release Asset Convention

Based on .github/workflows/release.yml, releases follow this naming:

  • Pattern: zy-{VERSION}-{TARGET}[.exe]
  • Examples:
    • zy-1.0.1-x86_64-unknown-linux-gnu
    • zy-1.0.1-aarch64-apple-darwin
    • zy-1.0.1-x86_64-pc-windows-msvc.exe
  • Checksums: SHA256SUMS.txt (combined file with all binary hashes)
  • Supported Targets:
    • x86_64-unknown-linux-gnu
    • aarch64-unknown-linux-gnu
    • x86_64-apple-darwin
    • aarch64-apple-darwin
    • x86_64-pc-windows-msvc

🏗️ Implementation Requirements

1. Module Structure

Create src/update/ module with the following files:

src/update/
├── mod.rs              # Public API and exports
├── version.rs          # Semantic version comparison
├── github.rs           # GitHub Releases API client
├── platform.rs         # OS/arch detection
├── asset.rs            # Asset selection logic
├── channel.rs          # Release channel management
└── error.rs            # Typed error definitions

2. Version Management (version.rs)

  • Parse semantic versions from Git tags (e.g., v1.0.11.0.1)
  • Compare versions correctly (e.g., 1.0.1 < 1.2.0 < 2.0.0)
  • Support pre-release versions (alpha, beta, rc)
  • Detect current binary version from env!("CARGO_PKG_VERSION")

Required functionality:

pub struct Version {
    pub major: u64,
    pub minor: u64,
    pub patch: u64,
    pub pre_release: Option<String>,
}

impl Version {
    pub fn parse(s: &str) -> Result<Self, VersionError>;
    pub fn current() -> Self;
    pub fn is_newer_than(&self, other: &Version) -> bool;
}

3. GitHub Releases API Client (github.rs)

  • Query GitHub Releases API: GET https://api.github.com/repos/CloudzyVPS/cli/releases
  • Handle rate limiting (check X-RateLimit-Remaining header)
  • Implement exponential backoff retry logic (max 3 retries)
  • Parse release JSON responses
  • Filter releases by channel (stable/pre-release)
  • Handle network failures gracefully

Required functionality:

pub struct GitHubClient {
    repo_owner: String,
    repo_name: String,
    client: reqwest::Client,
}

pub struct Release {
    pub tag_name: String,
    pub version: Version,
    pub prerelease: bool,
    pub assets: Vec<Asset>,
    pub download_url: String,
}

impl GitHubClient {
    pub fn new(repo_owner: String, repo_name: String) -> Self;
    pub async fn get_latest_release(&self, channel: Channel) -> Result<Release, UpdateError>;
    pub async fn get_all_releases(&self) -> Result<Vec<Release>, UpdateError>;
}

Rate limiting requirements:

  • Check X-RateLimit-Remaining and X-RateLimit-Reset headers
  • If rate limit is exceeded, return clear error message with reset time
  • Implement retry with exponential backoff: 1s, 2s, 4s delays

4. Platform Detection (platform.rs)

Detect the current platform at runtime and map to the correct target triple.

Required functionality:

pub struct Platform {
    pub target: String,
    pub os: String,
    pub arch: String,
    pub extension: Option<String>, // Some(".exe") for Windows, None otherwise
}

impl Platform {
    pub fn current() -> Self;
    pub fn to_target_triple(&self) -> String;
}

Detection logic:

  • Use std::env::consts::OS and std::env::consts::ARCH
  • Map to exact target triples:
    • Linux x64 → x86_64-unknown-linux-gnu
    • Linux ARM64 → aarch64-unknown-linux-gnu
    • macOS x64 → x86_64-apple-darwin
    • macOS ARM64 → aarch64-apple-darwin
    • Windows x64 → x86_64-pc-windows-msvc
  • Set .exe extension only for Windows

5. Asset Selection (asset.rs)

Select the correct binary asset from a GitHub release based on the current platform.

Required functionality:

pub struct Asset {
    pub name: String,
    pub download_url: String,
    pub size: u64,
    pub content_type: String,
}

pub fn select_asset_for_platform(
    assets: &[Asset],
    platform: &Platform,
) -> Result<Asset, UpdateError>;

pub fn parse_asset_name(name: &str) -> Option<(String, String)>; // (version, target)

Selection logic:

  • Match asset name against pattern: zy-{VERSION}-{TARGET}[.exe]
  • Verify target triple matches current platform
  • Validate file extension (.exe for Windows, none for Unix)
  • Return error if no matching asset found

6. Channel Management (channel.rs)

Manage release channels (stable, beta, alpha, rc).

Required functionality:

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Channel {
    Stable,
    Beta,
    Alpha,
    ReleaseCandidate,
}

impl Channel {
    pub fn from_version(version: &str) -> Self;
    pub fn should_include_prerelease(&self) -> bool;
}

**Detection logic (matching CI workflow...

This pull request was created from Copilot chat.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits January 5, 2026 15:49
- Add semver and chrono dependencies
- Create update module with error types, version management, channel management, platform detection, asset selection, and GitHub API client
- Add comprehensive unit tests for all modules
- Expose update module via lib.rs
- All tests passing

Co-authored-by: tayyebi <14053493+tayyebi@users.noreply.github.com>
- Fix asset module doc examples to use public API
- Add integration tests for update functionality
- All tests passing (29 unit tests + 3 integration tests + 13 doc tests)

Co-authored-by: tayyebi <14053493+tayyebi@users.noreply.github.com>
- Remove unused semver dependency
- Fix redundant assertions in version tests
- Remove meaningless assert(true) calls in platform tests
- All tests still passing

Co-authored-by: tayyebi <14053493+tayyebi@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement core infrastructure for self-update mechanism Implement Phase 1 self-update core infrastructure Jan 5, 2026
Copilot AI requested a review from tayyebi January 5, 2026 16:03
@tayyebi tayyebi marked this pull request as ready for review January 7, 2026 11:21
@tayyebi tayyebi merged commit 7f85993 into main Jan 7, 2026
@tayyebi tayyebi deleted the copilot/implement-self-update-infrastructure branch January 7, 2026 15:01
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.

2 participants