Project 10: distro-flow

Build a distribution and update system for your CLI.

Quick Reference

Attribute Value
Difficulty Level 3 (Advanced)
Time Estimate 1 week
Language Go (Alternatives: Rust)
Prerequisites CLI basics, packaging concepts
Key Topics Releases, updates, shell completion

1. Learning Objectives

By completing this project, you will:

  1. Package binaries for macOS, Linux, and Windows.
  2. Implement a self-update flow with checksum verification.
  3. Generate shell completion scripts and install them.
  4. Design a release workflow that can be automated.
  5. Handle failed updates safely with rollback behavior.

2. Theoretical Foundation

2.1 Core Concepts

  • Versioning: Semantic versioning communicates change scope and compatibility.
  • Distribution Channels: GitHub Releases, Homebrew taps, and package managers have different expectations.
  • Integrity Verification: Checksums or signatures prevent tampered binaries.
  • Shell Completion: Autocomplete reduces user error and improves adoption.

2.2 Why This Matters

Distribution and updates are part of user trust. A tool that cannot update reliably becomes abandoned quickly.

2.3 Historical Context / Background

Tools like kubectl, gh, and terraform rely on robust release pipelines. Many CLIs fail not because of features but because installation is painful. Your project focuses on that gap.

2.4 Common Misconceptions

  • “Updating is just downloading a file”: Updates must verify integrity and handle permissions.
  • “Completions are optional”: They dramatically improve usability.

3. Project Specification

3.1 What You Will Build

A CLI named distro-flow that:

  • Builds release artifacts for multiple platforms
  • Provides a self-update command
  • Generates shell completion scripts
  • Prints version info

3.2 Functional Requirements

  1. Release Build: Produce platform-specific binaries with version metadata.
  2. Update Check: Compare current version vs latest release.
  3. Self-Update: Download binary and replace current executable.
  4. Completion: Generate completions for bash/zsh/fish.
  5. Verification: Validate checksums before replacing.

3.3 Non-Functional Requirements

  • Reliability: Update should be atomic and recoverable.
  • Portability: Work on macOS, Linux, Windows.
  • Security: Reject invalid or unsigned downloads.

3.4 Example Usage / Output

$ distro-flow version
v1.2.3

$ distro-flow update
Checking for updates...
Downloading v1.2.4...
Verified checksum.
Updated to v1.2.4

3.5 Real World Outcome

The user installs your CLI, runs distro-flow completion zsh to enable autocomplete, and later runs distro-flow update to upgrade. The tool replaces its binary safely and exits with success, leaving no corrupted files if the update fails.


4. Solution Architecture

4.1 High-Level Design

+--------------+     +-----------------+     +------------------+
| Version Info | --> | Update Checker  | --> | Installer        |
+--------------+     +-----------------+     +------------------+

4.2 Key Components

Component Responsibility Key Decisions
Builder Cross-compile build matrix
Checker Fetch release info API choice
Installer Replace binary atomic swap
Completion Generate scripts shell formats

4.3 Algorithm Overview

Key Algorithm: Self-update

  1. Query release endpoint for latest version.
  2. Compare to current version.
  3. Download artifact and checksum.
  4. Verify checksum.
  5. Swap binary atomically.

Complexity Analysis:

  • Time: dominated by download
  • Space: O(size of binary)

5. Implementation Guide

5.1 Development Environment Setup

mkdir distro-flow && cd distro-flow
go mod init distro-flow

5.2 Project Structure

distro-flow/
├── cmd/
│   ├── root.go
│   ├── update.go
│   └── completion.go
├── internal/
│   ├── release/
│   └── install/
└── README.md

5.3 The Core Question You Are Answering

“How do I distribute and update a CLI without breaking users’ installations?”

5.4 Concepts You Must Understand First

  1. Semantic versioning
  2. Cross-compilation
  3. File replacement and permissions

5.5 Questions to Guide Your Design

  1. How do you handle update failure mid-download?
  2. Where should completion scripts live?
  3. How do you verify release integrity?

5.6 Thinking Exercise

Walk through replacing a running binary on your OS. What permissions are required? What happens if the file is locked?

5.7 The Interview Questions They Will Ask

  1. Why do you need checksum verification?
  2. What is an atomic update and why does it matter?
  3. How do you support multiple platforms in releases?

5.8 Hints in Layers

Hint 1: Start by embedding version info in the binary.

Hint 2: Generate completions using your CLI framework.

Hint 3: Use temp file + rename for binary replacement.

5.9 Books That Will Help

Topic Book Chapter
Release workflows “Continuous Delivery” Ch. 8
Tooling “Effective Shell” Packaging section

5.10 Implementation Phases

Phase 1: Foundation (2-3 days)

Goals:

  • Version info
  • Completion generation

Checkpoint: --version and completions work.

Phase 2: Update Flow (2-3 days)

Goals:

  • Update check
  • Download and verify

Checkpoint: Update runs in test mode.

Phase 3: Polish (1-2 days)

Goals:

  • Atomic swap and rollback

Checkpoint: Failed update leaves original binary intact.


6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Version comparison semver parsing
Integration Tests Update flow download mock
Edge Cases No network error messaging

6.2 Critical Test Cases

  1. Update when already latest -> no action.
  2. Corrupt checksum -> update aborted.
  3. Missing permissions -> clear error.

7. Common Pitfalls and Debugging

Pitfall Symptom Solution
Overwrite running binary Crash Use temp + rename
Skipping verification Security risk Require checksums
Wrong completion path No autocomplete Document install steps

8. Extensions and Challenges

8.1 Beginner Extensions

  • Add --dry-run update
  • Add --channel (stable/beta)

8.2 Intermediate Extensions

  • Add signature verification
  • Add uninstall command

8.3 Advanced Extensions

  • Add delta updates
  • Add update server

9. Real-World Connections

  • GitHub release automation
  • CLI distribution pipelines

10. Resources

  • goreleaser or cargo-dist
  • GitHub Releases API docs

11. Self-Assessment Checklist

  • I can explain atomic update steps
  • I can verify binary integrity with checksums

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Completion scripts + version info

Full Completion:

  • Working update flow with checksum verification

Excellence (Going Above and Beyond):

  • Signature verification and release channels