Skip to content

Latest commit

 

History

History
578 lines (476 loc) · 22 KB

File metadata and controls

578 lines (476 loc) · 22 KB

Manifest-Based Installation System - Status

Last Updated: 2026-01-04 Current Phase: PRODUCTION - Multi-manifest architecture with mise tools consolidation! ✅

Recent Updates - Phase 4 Complete! 🎉

Multi-Manifest Architecture - Completed 2026-01-04

  • Split monolithic 438-line packages.yaml into 3 organized files
  • Created common.yaml (cross-platform packages + consolidated mise tools)
  • Created ubuntu.yaml (Ubuntu-specific packages)
  • Created macos.yaml (macOS-specific packages)
  • Consolidated 35 mise packages from 140 lines → 50 lines (64% reduction)
  • Reorganized from 4 categories → 9 specific categories
  • Removed unused bulk_install_groups feature (191 lines of dead code)
  • All 184 tests passing ✅

Quick Start

# Run all tests (184 tests)
make -f test.mk test

# View test coverage
make -f test.mk test-coverage

# Install packages (manifest is now the default)
./install.sh --minimal --dry-run    # Preview minimal profile
./install.sh --dry-run              # Preview dev profile

# Direct manifest usage (now uses directory)
bash install/packages-manifest.sh minimal --dry-run
bash install/packages-manifest.sh dev

# Test manifest queries (multi-manifest aware)
source install/lib/manifest-parser.sh
# Queries now work with merged manifests automatically
get_packages_for_profile_multi install/manifests minimal ubuntu
validate_manifest_schema install/manifests/common.yaml

Completed Work

Phase 1: Foundation ✅ COMPLETE

What was built:

  1. Manifest Parser (install/lib/manifest-parser.sh)

    • Full YAML querying library using yq
    • Functions for filtering by profile, platform, category
    • Priority chain resolution
    • Package manager config extraction
    • 22 passing tests
  2. JSON Schema Validation (install/schemas/package-manifest.schema.json)

    • Comprehensive schema definition
    • Validates all manifest fields and constraints
    • Enforces profile rules (packages XOR includes/excludes)
    • Platform and priority value enums
    • PPA format validation (must start with "ppa:")
    • 27 passing tests
  3. Package Manifest (install/manifests/packages.yaml)

    • Defines all packages with metadata
    • 4 installation profiles: full, dev, minimal, remote
    • 4 categories: language_runtimes, general_tools, system_libraries, gui_applications
    • ~70 packages defined with platform filters and priority chains
    • Bulk install groups for optimization
  4. Test Infrastructure

    • BATS testing framework
    • Test fixtures and helpers
    • Makefile-based test runner (test.mk)
    • 49/49 tests passing

Key Files:

  • install/lib/manifest-parser.sh - Parser with validation
  • install/schemas/package-manifest.schema.json - JSON Schema
  • install/manifests/packages.yaml - Package definitions
  • install/tests/test-manifest-parser.bats - Parser tests (22)
  • install/tests/test-schema-validation.bats - Schema tests (27)
  • test.mk - Test runner
  • mise/config.toml - Added pipx:check-jsonschema

Dependencies Installed:

mise install yq@latest                        # YAML processor
mise install bats@latest                      # Test framework
mise install pipx:check-jsonschema@latest     # Schema validator

Phase 2: Backend Modules ✅ COMPLETE

What was built: All 4 package manager backends implemented with comprehensive test coverage using TDD methodology.

Backends Implemented:

1. APT Backend (install/lib/backend-apt.sh) ✅

Test Results: 22/22 tests passing

Functions:

  • apt_get_package_name - Extract package name(s) from manifest
  • apt_check_installed - Check if package is installed via dpkg
  • apt_install_package - Install single package with dry-run support
  • apt_install_bulk - Batch install multiple packages

Features:

  • Handles single package or packages array
  • Checks installation status before installing
  • Comprehensive error handling and validation
  • Dry-run mode for testing
  • Installation summaries

2. Homebrew Backend (install/lib/backend-homebrew.sh) ✅

Test Results: 27/27 tests passing Functions:

  • brew_get_package_name - Extract package name from manifest
  • brew_is_cask - Determine if package is a cask or formula
  • brew_check_installed - Check installation status
  • brew_install_package - Install formula or cask with dry-run support
  • brew_add_tap - Add custom Homebrew taps
  • brew_install_bulk - Batch install multiple packages

Features:

  • Automatically distinguishes formulas from casks
  • Validates tap name format
  • Handles mixed formula/cask installations
  • Installation summaries

3. PPA Backend (install/lib/backend-ppa.sh) ✅

Test Results: 23/23 tests passing Functions:

  • ppa_get_repository - Extract PPA repository URL from manifest
  • ppa_get_package_name - Extract package name(s) from manifest
  • ppa_get_gpg_key - Get optional GPG key URL
  • ppa_check_added - Check if PPA is already added
  • ppa_add_repository - Add PPA with optional GPG key
  • ppa_install_package - Add PPA and install packages

Features:

  • Validates PPA format (must start with "ppa:")
  • Handles optional GPG keys
  • Checks if PPA already added before adding
  • Automatically runs apt-get update after adding PPA
  • Supports multiple packages per PPA

4. mise Backend (install/lib/backend-mise.sh) ✅

Test Results: 22/22 tests passing Functions:

  • mise_is_managed - Check if package is managed by mise
  • mise_check_available - Check if mise command exists
  • mise_check_tool_available - Check if tool exists in mise registry
  • mise_check_installed - Check if tool is installed (not just listed)
  • mise_get_version - Get version to install (defaults to "latest")
  • mise_install_tool - Install tool with dry-run support
  • mise_sync_with_manifest - Sync all mise tools in a category

Features:

  • Distinguishes between listed and actually installed tools
  • Handles explicit version specifications
  • Syncs entire categories of mise-managed tools
  • Gracefully handles mise not being available

Test Files:

  • install/tests/test-backend-apt.bats - APT backend tests (22)
  • install/tests/test-backend-homebrew.bats - Homebrew backend tests (27)
  • install/tests/test-backend-ppa.bats - PPA backend tests (23)
  • install/tests/test-backend-mise.bats - mise backend tests (22)

TDD Methodology Used: All backends were developed using strict Test-Driven Development:

  1. ✅ Write failing tests first (Red phase)
  2. ✅ Implement minimal code to pass tests (Green phase)
  3. ✅ Refactor while keeping tests green (Refactor phase)
  4. ✅ Verify no regressions with full test suite

Common Backend Interface: All backends follow a consistent pattern:

<backend>_install_package(manifest_file, package_name, [dry_run])
<backend>_check_installed(package_name)
<backend>_get_package_name(manifest_file, package_name)

Phase 2 Test Coverage:

  • Total: 94/94 tests passing
  • All backends tested with dry-run mode
  • Error handling and validation tested
  • Edge cases covered (missing files, corrupted manifests, invalid packages)

Phase 3: Integration Layer ✅ COMPLETE

What was built: Complete manifest-driven package installation orchestration system with CLI interface.

Implementation: install/packages-manifest.sh - Main orchestration layer

Features:

  • Profile-based installation: Select from full, dev, minimal, or remote profiles
  • Automatic backend resolution: Determines best package manager for each package based on priority chains
  • Platform detection: Automatically filters packages by OS (ubuntu, macos, linux)
  • Mixed backend orchestration: Handles apt, homebrew, PPA, and mise in single installation
  • Dry-run mode: Test installations without making changes (--dry-run)
  • CLI interface: User-friendly command-line tool with help documentation
  • Comprehensive error handling: Graceful degradation and detailed reporting
  • Installation summaries: Track succeeded, skipped, and failed packages

Functions Implemented:

  • detect_platform() - Detects current OS (ubuntu/macos/linux)
  • get_profile_packages() - Returns all packages for a profile
  • resolve_package_backend() - Determines best backend for a package
  • install_package_with_backend() - Installs package using specified backend
  • install_from_manifest() - Main installation orchestrator
  • manifest_install_main() - CLI entry point with argument parsing

Test Results: 30/30 integration tests passing

CLI Usage Examples:

# Show help
bash install/packages-manifest.sh --help

# Install with dry-run
bash install/packages-manifest.sh minimal --dry-run

# Install dev profile
bash install/packages-manifest.sh dev

# Custom manifest
bash install/packages-manifest.sh --manifest=custom.yaml full

Install.sh Integration ✅ COMPLETE - MANIFEST IS NOW DEFAULT

What was done: Fully integrated manifest-based installation as the default and only package installation system.

Implementation Changes in install.sh:

  • Removed legacy install/packages.sh (683 lines removed)
  • Removed USE_MANIFEST flag and --use-manifest option
  • Manifest installation is now always used in Step 2
  • Profile mapping: --minimal or --no-languages → "minimal" profile, default → "dev" profile

Usage:

# Install packages (manifest is the only way)
./install.sh --dry-run           # Dev profile (59 packages)
./install.sh --minimal --dry-run  # Minimal profile (6 packages)
./install.sh --minimal            # Install minimal profile

# Direct manifest CLI
bash install/packages-manifest.sh dev --dry-run
bash install/packages-manifest.sh minimal

Profile Mapping:

  • --minimal or --no-languages → "minimal" profile (6 core CLI tools)
  • Default → "dev" profile (59 packages - all tools except GUI apps)
  • Future: Could add --full flag for "full" profile (including GUI apps)

Benefits:

  • ✅ Simplified codebase: No legacy code to maintain
  • ✅ Declarative: All packages defined in YAML
  • ✅ Testable: 173 passing tests
  • ✅ Maintainable: Easy to add/remove packages
  • ✅ Consistent: One installation path for all users

Migration Complete:

  • Legacy install/packages.sh removed
  • Manifest system is production-ready
  • No backwards compatibility needed

Phase 4: Multi-Manifest Reorganization ✅ COMPLETE

What was built: Complete reorganization of package manifests into logical, platform-specific files with consolidated mise tools.

Key Changes:

  1. File Structure Reorganization:

    • Replaced single packages.yaml (438 lines) with 3 focused files
    • common.yaml (~200 lines) - Cross-platform packages and mise tools
    • ubuntu.yaml (~120 lines) - Ubuntu-specific packages
    • macos.yaml (~80 lines) - macOS-specific packages
  2. Consolidated mise Tools Format:

    • New mise_tools section with compressed inline format
    • Reduced 35 mise packages from 140 lines → 50 lines (64% reduction)
    • Explicit global: true flag for mise installations
    • Example format: { name: fzf, desc: "Fuzzy finder" }
  3. Category Reorganization:

    • Split overly-broad general_tools (39 packages) into 9 specific categories:
      • core_utils - Essential POSIX utilities (7 packages)
      • shell_tools - Shell enhancements (6 packages)
      • dev_tools - Development utilities (8 packages)
      • git_tools - Git ecosystem (6 packages)
      • file_tools - File management (6 packages)
      • monitoring_tools - System monitoring (5 packages)
      • language_runtimes - Programming languages (8 packages)
      • system_libraries - Build dependencies (12 packages)
      • gui_applications - Desktop apps (1 package)
  4. Multi-Manifest Loading:

    • New functions in manifest-parser.sh:
      • load_manifests_for_platform() - Loads common + platform-specific
      • merge_manifests() - Merges YAML files (later overrides earlier)
      • expand_mise_tools() - Converts mise_tools to package format
    • Automatic platform detection (ubuntu/macos/linux)
    • Orchestration layer updated to use manifest directories
  5. Schema Updates:

    • Added mise_tools section support
    • Made profiles/categories/packages optional (for platform-specific files)
    • Added new platforms: fedora, debian, arch, amazonlinux

Test Results: 184/184 tests passing ✅

  • 14 new parser tests for multi-manifest functionality
  • Updated 30 integration tests for directory-based loading
  • Removed 3 schema validation tests for unused bulk_install_groups feature

Benefits:

  • ✅ Multi-distro ready: Easy to add Fedora, Arch, Debian support
  • ✅ Reduced duplication: 64% reduction in mise package definitions
  • ✅ Logical organization: 9 specific categories vs 4 overly-broad
  • ✅ Platform separation: Ubuntu/macOS packages cleanly separated
  • ✅ Scalable: Each distro gets its own file, common packages shared
  • ✅ Explicit mise global install: mise_tools.global: true

Files Modified:

  • install/lib/manifest-parser.sh - Added multi-manifest support (lines 306-528)
  • install/packages-manifest.sh - Updated to use manifest directories
  • install.sh - Updated to pass manifest directory
  • install/schemas/package-manifest.schema.json - Added mise_tools section
  • install/tests/test-manifest-parser.bats - Added 14 new tests
  • install/tests/test-integration.bats - Updated for directory structure
  • install/tests/test-schema-validation.bats - Updated for optional sections

Files Created:

  • install/manifests/common.yaml - Cross-platform packages
  • install/manifests/ubuntu.yaml - Ubuntu-specific packages
  • install/manifests/macos.yaml - macOS-specific packages

Files Removed:

  • install/manifests/packages.yaml - Replaced by multi-manifest structure

Current Manifest Schema

File Structure

install/manifests/
├── common.yaml    # Cross-platform packages + mise tools
├── ubuntu.yaml    # Ubuntu-specific packages
├── macos.yaml     # macOS-specific packages
└── schemas/
    └── package-manifest.schema.json

Loading: Platform automatically detected, merges common.yaml + {platform}.yaml

Profiles (defined in common.yaml)

  • full: Complete dev environment (all categories)
  • dev: Headless dev (all except GUI apps)
  • minimal: Essential CLI only (git, curl, wget, tmux, tree, pinentry)
  • remote: Lightweight server (minimal + htop + build-essential)

Categories (9 specific categories)

  • core_utils: Essential POSIX utilities (priority: apt → homebrew)
  • shell_tools: Shell enhancements (priority: mise → homebrew → apt)
  • dev_tools: Development utilities (priority: mise → homebrew)
  • git_tools: Git ecosystem tools (priority: mise → homebrew → apt)
  • file_tools: File search/management (priority: mise → homebrew)
  • monitoring_tools: System monitoring (priority: mise → homebrew → apt)
  • language_runtimes: Programming languages (priority: mise)
  • system_libraries: Build dependencies (priority: apt only)
  • gui_applications: Desktop apps (priority: homebrew-cask → flatpak)

Package Definition Example (Traditional)

# In common.yaml or platform-specific file
packages:
  git:
    category: core_utils
    description: "Version control system"
    priority: ["apt", "homebrew"]  # Override category default
    platforms: ["ubuntu", "macos"]  # Optional
    apt:
      package: git
    homebrew:
      package: git

Mise Tools Definition Example (Consolidated Format)

# In common.yaml
mise_tools:
  global: true  # Install globally (mise use -g)

  categories:
    shell_tools:
      description: "Shell enhancement tools"
      tools:
        - { name: fzf, desc: "Fuzzy finder" }
        - { name: zoxide, desc: "Smarter cd command" }
        - { name: bat, desc: "Cat with syntax highlighting" }

    dev_tools:
      description: "Development utilities"
      tools:
        - { name: jq, desc: "JSON processor" }
        - { name: yq, desc: "YAML processor" }
        - { name: shellcheck, desc: "Shell script linter" }

Note: mise_tools are automatically expanded into package format during manifest loading.

Testing Strategy

Run Tests

make -f test.mk help           # Show all commands
make -f test.mk test           # Run all tests
make -f test.mk test-parser    # Parser tests only
make -f test.mk test-verbose   # Verbose output
make -f test.mk test-watch     # Watch mode
make -f test.mk test-coverage  # Coverage summary

Test Structure

install/tests/
├── fixtures/
│   └── test-packages.yaml           # Test data
├── test-helper.bash                 # Common utilities
├── test-manifest-parser.bats        # Parser tests (36 - includes multi-manifest)
├── test-schema-validation.bats      # Schema tests (27)
├── test-integration.bats            # Integration tests (30)
├── test-backend-apt.bats            # APT backend tests (22)
├── test-backend-homebrew.bats       # Homebrew backend tests (27)
├── test-backend-ppa.bats            # PPA backend tests (23)
└── test-backend-mise.bats           # mise backend tests (22)

Total: 184 tests passing ✅

Important Commands

Validate Manifests

# Using function (validates individual files)
source install/lib/manifest-parser.sh
validate_manifest_schema install/manifests/common.yaml
validate_manifest_schema install/manifests/ubuntu.yaml
validate_manifest_schema install/manifests/macos.yaml

# Direct command
check-jsonschema --schemafile install/schemas/package-manifest.schema.json \
  install/manifests/common.yaml

Query Manifests

source install/lib/manifest-parser.sh

# Multi-manifest queries (recommended - auto-merges)
get_packages_for_profile_multi install/manifests minimal ubuntu
get_packages_for_profile_multi install/manifests dev macos

# Single-file queries (for testing individual manifests)
get_packages_for_profile install/manifests/common.yaml minimal
get_packages_for_platform install/manifests/common.yaml ubuntu
get_package_priority install/manifests/common.yaml git
is_managed_by_mise install/manifests/common.yaml ruby

# Load and merge manifests manually
manifests=($(load_manifests_for_platform install/manifests ubuntu))
merged=$(merge_manifests "${manifests[@]}")
echo "$merged" > /tmp/merged.yaml

Documentation

All documentation is in AGENTS.md:

  • Full refactor overview and architecture
  • Phase 1, 2, 3 details
  • Manifest schema reference
  • Testing guide
  • Adding packages and profiles
  • Migration strategy

Key Decisions Made

  1. Schema Validation: Using check-jsonschema via mise (not yq, which lacks schema support)
  2. Version Format: Accepts both string "1.0" and number 1.0
  3. Profile Types: Support both category-based (includes/excludes) and explicit (packages array)
  4. Priority Chain: Per-package overrides category defaults
  5. NO snap: Explicitly excluded from valid package managers
  6. Graceful Degradation: Schema validation falls back to basic yq validation if check-jsonschema unavailable
  7. Multi-Manifest Architecture: Common + platform-specific files for scalability (Phase 4)
  8. Consolidated mise Format: Inline { name, desc } format for 64% space reduction
  9. Optional Schema Sections: Profiles/categories/packages optional to support platform-specific files
  10. 9 Categories: Replaced overly-broad general_tools with 9 specific categories

Known Issues / TODOs

  • None currently - All phases complete, 184/184 tests passing ✅

Git Status

New files (ready to commit):
- install/manifests/common.yaml
- install/manifests/ubuntu.yaml
- install/manifests/macos.yaml
- REFACTOR_STATUS.md (this file - updated)

Modified:
- install/lib/manifest-parser.sh (added multi-manifest support)
- install/packages-manifest.sh (updated for manifest directories)
- install.sh (updated to pass manifest directory)
- install/schemas/package-manifest.schema.json (added mise_tools section)
- install/tests/test-manifest-parser.bats (added 14 tests)
- install/tests/test-integration.bats (updated for directory structure)
- install/tests/test-schema-validation.bats (updated for optional sections)
- test.mk (updated coverage count)

Removed:
- install/manifests/packages.yaml (replaced by multi-manifest)

Context for AI Assistants

Current Status:

  • All 4 Phases Complete - 184/184 tests passing
  • Multi-manifest architecture implemented and tested
  • Manifest is the only installation system (no legacy code)
  • Production-ready with comprehensive test coverage
  • Dead code removed - 191 lines of unused code eliminated

Quick Reference:

  • Run tests: make -f test.mk test
  • Install packages: ./install.sh --dry-run
  • Manifests: install/manifests/{common,ubuntu,macos}.yaml
  • Parser: install/lib/manifest-parser.sh
  • Orchestration: install/packages-manifest.sh

Future Enhancements:

  • Add fedora.yaml, debian.yaml, arch.yaml for additional distro support
  • Consider adding GUI tools categories
  • Explore automatic manifest validation in CI/CD

Session Notes

Session 2026-01-04 - Phase 4 Complete + Dead Code Cleanup:

  • Split packages.yaml into multi-manifest architecture
  • Created common.yaml, ubuntu.yaml, macos.yaml
  • Consolidated 35 mise packages (140 lines → 50 lines, 64% reduction)
  • Reorganized into 9 specific categories (was 4 overly-broad)
  • Added multi-manifest loading and merging functions
  • Updated schema to support mise_tools section
  • Removed legacy packages.yaml
  • Removed unused bulk_install_groups feature (191 lines dead code)
  • Updated all 184 tests to pass with new structure
  • Updated all documentation

Session 2026-01-03 - Phases 1-3 Complete:

  • Implemented all 4 backend modules (apt, homebrew, ppa, mise) using TDD
  • Created integration layer with CLI (packages-manifest.sh)
  • Removed legacy install/packages.sh (683 lines)
  • Made manifest the default and only installation system
  • Added comprehensive JSON Schema validation
  • Built test infrastructure with 173 passing tests
  • Complete migration from legacy to manifest-based system

Initial session:

  • Implemented manifest parser with yq
  • Created package manifest with profiles
  • Built test infrastructure
  • 22 parser tests passing