feat(duo): add cli command with binary download management

Summary

Implements glab duo cli command that automatically downloads, manages, and executes the GitLab Duo CLI binary from the GitLab Package Registry. This provides a seamless installation experience similar to npx, but with glab managing the binary lifecycle.

Command naming: The command is glab duo cli (with glab duo aliased to it for convenience). This preserves agent for potential future use and aligns the command name with the underlying "GitLab Duo CLI" tool.

Recent Updates

Command Rename (Latest)

  • Renamed command from agent to cli to better reflect the underlying "GitLab Duo CLI" tool
  • Updated all config keys: duo_agent_*duo_cli_*
  • Updated command structure to follow MR review guidelines (.gitlab/duo/mr-review-instructions.yaml)
  • Added complete() method for proper command pattern compliance
  • Command is now glab duo cli (with glab duo aliased to it)

API Integration Improvements

  • Refactored to use proper client-go API methods throughout
    • client.Packages.ListProjectPackages() for package listing
    • client.Packages.ListPackageFiles() for file metadata
    • client.GenericPackages.DownloadPackageFile() for downloads
  • Improved type safety (fixed int vs int64 type mismatch)
  • Removed manual URL construction and HTTP handling

Installation Directory Simplification

  • Simplified to use platform standards directly:
    • Unix: ~/.local/bin (systemd file-hierarchy specification standard)
    • Windows: %LOCALAPPDATA%\Programs\Duo
  • Removed unnecessary XDG checks (no XDG standard exists for executables)
  • Clearer documentation about standard installation paths

Configuration Behavior Fixes

  • Fixed duo_cli_auto_download: false behavior to prompt instead of error
  • Fixed duo_cli_auto_run: false behavior to prompt instead of error
  • Consistent semantic across all auto_* configs:
    • "true" → auto-execute without prompting
    • "false" or unset → prompt the user each time
    • "false" means "don't auto-X", not "never X"

What This Does

For Users

  • Running glab duo or glab duo cli automatically downloads and launches the Duo CLI
  • No need to manually install or manage the Duo CLI binary
  • Automatic update checking with notifications
  • Uses glab's authentication (OAuth2 tokens with auto-refresh via credential helper)
  • Works across platforms: macOS (x64, arm64), Linux (x64, arm64), Windows (x64-baseline)

Key Features

Binary Management

  • Downloads platform-specific binaries from GitLab Package Registry (project 46519181)
  • Installs to standard locations:
    • Unix: ~/.local/bin/duo
    • Windows: %LOCALAPPDATA%\Programs\Duo\duo.exe
  • SHA256 checksum verification for integrity
  • Version tracking in glab config to prevent unnecessary re-downloads
  • Manual updates via glab duo cli --update or glab duo --update

User Experience

  • Interactive prompts for first-time download and execution
  • Preferences saved to config (can be set to always prompt via false value)
  • Command alias: glab duo defaults to glab duo cli
  • Unknown flags passed through to Duo CLI (via FParseErrWhitelist.UnknownFlags)
  • Update checks every 24 hours (non-blocking, user notification only)

Authentication

  • Uses glab auth credential-helper for token management
  • Duo CLI automatically calls credential helper (no manual token passing)
  • Supports OAuth2 tokens with automatic refresh
  • Centralized authentication through glab

Configuration

New config keys added to config.yaml:

duo_cli_auto_run: true/false          # "true" = skip prompt, "false" = always prompt
duo_cli_auto_download: true/false     # "true" = skip prompt, "false" = always prompt
duo_cli_binary_path: <path>           # Installed binary location (auto-set)
duo_cli_binary_version: <version>     # Installed version (auto-set)
duo_cli_binary_checksum: <sha256>     # Binary checksum (auto-set)
duo_cli_last_update_check: <timestamp> # Last update check (auto-set)

Implementation Details

Architecture

  • internal/commands/duo/cli/: Main command package
  • internal/commands/duo/cli/cliutils/: Utility package following glab's <command>utils pattern
    • binaryManager: Handles download, installation, verification, and updates
    • platform: Detects OS/arch and provides platform-specific paths and binary names
  • GitLab Package Registry API integration using client-go library
  • Atomic installation using temp files to prevent partial installs
  • Follows complete/validate/run command pattern per MR review guidelines

API Integration

  • Uses gitlab.com/gitlab-org/api/client-go for all GitLab API calls
  • Proper API methods with context support and type safety
  • Unauthenticated client for public package downloads
  • Structured error handling with clear user messages

Update Checking

  • Background check every 24 hours (configurable via GLAB_DUO_CLI_CHECK_UPDATE)
  • Uses hashicorp/go-version for semantic version comparison
  • Non-blocking: shows notification only, doesn't interrupt user flow
  • Version validation ensures glab-managed binaries (checks config metadata)

Error Handling

  • Graceful network error handling with clear messages
  • Mandatory checksum verification prevents corrupted installs
  • Platform validation with helpful error messages
  • Distinguishes between glab-managed and external binaries

Binary Execution

  • Unix (macOS/Linux): Uses syscall.Exec() to replace glab process with Duo CLI
    • Provides better signal handling and terminal control for interactive TUI
    • Process replacement ensures clean terminal state
  • Windows: Uses subprocess with exit code propagation
    • Windows doesn't have exec(), so subprocess is required
    • Exits with Duo CLI's exit code for proper error handling

Testing

  • Command structure and flag handling
  • Binary validation and checksum verification
  • Platform detection for all supported combinations
  • Config persistence and retrieval
  • Update checking logic and version comparison
  • Tests use t.Parallel() where compatible (excluded for tests using t.Setenv())
  • All tests follow MR review guidelines (use cmdtest, testify assertions)

Breaking Changes

None - this is a new command. The existing glab duo ask command is unchanged.

Known Limitations

Duo CLI Help Flag

  • Duo CLI has a limitation where --help is intercepted by Bun runtime (shows Bun help instead of Duo CLI help)
  • This affects flag discoverability - tracking with Duo CLI team to address upstream
  • Unknown flags are passed through successfully, but users must discover them via docs or source code

Duo Direct Command

  • glab duo direct currently errors with a duo binary bug (not a glab issue)
  • Error: TypeError: id is not an Object. (evaluating '"baseId" in id')
  • Arguments are correctly passed through by glab
  • This is a bug in the upstream duo binary, not in our integration
  • Non-blocking issue per reviewer feedback

Testing Instructions

# Clean install test
rm -f ~/.local/bin/duo
glab config set duo_cli_auto_download false
glab duo
# → Should prompt to download (even with false value)
# → Should install binary
# → Should launch Duo CLI

# Update test
glab duo --update
# → Should check for latest version
# → Should show update status

# Config persistence test
glab config get duo_cli_binary_version
glab config get duo_cli_binary_path
# → Should show installed version and path

# Authentication test (requires OAuth2 login)
glab auth status
# → Ensure authenticated
glab duo
# → Should authenticate successfully via credential helper

# Test auto config behavior
glab config set duo_cli_auto_run false
glab duo
# → Should still prompt (not error)

# Test explicit cli subcommand
glab duo cli
# → Should work identically to `glab duo`
Edited by Kai Armstrong

Merge request reports

Loading