Files
nix-config/scripts/README_tui.md
mjallen18 70002a19e2 hmm
2026-04-07 18:39:42 -05:00

7.8 KiB
Executable File

Version TUI Documentation

Overview

The version_tui.py script is an interactive terminal interface for managing package versions in a NixOS repository. It provides a unified way to update version.json files, Python packages, and Home Assistant components.

Architecture

Core Components

  1. Package Discovery: Scans the repository for different package types
  2. Version Management: Handles version.json, Python default.nix, and Home Assistant components
  3. Hash Computation: Uses modern Nix commands for reliable hash generation
  4. Interactive Interface: Curses-based TUI with color support and keyboard navigation

Package Types Supported

1. Regular Packages (packages/**/version.json)

  • Standard version.json format with variables and sources
  • Support for variants (base + overrides)
  • Multiple fetcher types: github, git, url

2. Python Packages (packages/python/*/default.nix)

  • Parses version, pname, and source info from default.nix
  • Supports fetchFromGitHub and fetchPypi patterns
  • Updates version, hash, tag, and rev fields

3. Home Assistant Components (packages/homeassistant/*/default.nix)

  • Specialized parsing for HA component structure
  • Handles domain, version, owner, and repo extraction
  • GitHub-aware source management

Fetcher Types

GitHub Fetcher

{
  "fetcher": "github",
  "owner": "owner",
  "repo": "repo",
  "tag": "v1.0.0",
  "rev": "commit-hash",
  "hash": "sha256-..."
}

Git Fetcher

{
  "fetcher": "git", 
  "url": "https://github.com/user/repo.git",
  "rev": "commit-hash",
  "hash": "sha256-..."
}

URL Fetcher

{
  "fetcher": "url",
  "url": "https://example.com/file.tar.gz",
  "hash": "sha256-..."
}

Key Functions

Hash Computation

nix_prefetch_url(url: str)

Purpose: Compute SHA256 SRI hash for URL sources Method:

  1. Try nix store prefetch-file (modern, SRI output)
  2. Fallback to nix-prefetch-url (legacy, needs conversion)
  3. Convert to SRI format if needed

nix_prefetch_git(url: str, rev: str)

Purpose: Compute SHA256 SRI hash for Git repositories
Method:

  1. Use nix eval with builtins.fetchGit to get store path
  2. Hash the store path with nix hash path --type sha256
  3. Fallback to nix-prefetch-git if available

API Functions

gh_latest_release(owner, repo, token)

  • Gets latest release from GitHub API
  • Returns tag_name of latest release
  • Handles API errors gracefully

gh_latest_tag(owner, repo, token)

  • Gets all tags and returns the first one
  • Limited to 100 tags per page
  • Sorts by GitHub's default ordering

gh_head_commit(owner, repo)

  • Uses git ls-remote to get HEAD commit
  • No API token required
  • Fallback for when GitHub API fails

Special Cases

Raspberry Pi Linux

  • Prefers stable_YYYYMMDD tags over latest
  • Falls back to series-specific tags (rpi-X.Y)
  • Maintains compatibility with existing tagging schemes

CachyOS Linux

  • Fetches latest version from upstream PKGBUILD
  • Supports different suffixes (rc, hardened, lts)
  • Handles both .SRCINFO and PKGBUILD parsing

UI Navigation

Main Package List

↑/k/j     : Navigate up/down
g/G       : Go to top/bottom
Enter     : Open package details
f          : Cycle filters (all → regular → python → all)
q/ESC      : Quit

Package Details Screen

←/h/l   : Switch variants (if available)
↑/k/j   : Navigate sources
r          : Refresh candidates
h          : Recompute hash
e          : Edit field (path=value)
s          : Save changes
i          : Show full URL (URL sources)
Enter      : Action menu for selected source
Backspace  : Return to package list
q/ESC      : Quit

Action Menu

↑/k/j     : Select option
Enter      : Execute selected action
Backspace   : Cancel

File Structure Analysis

version.json Format

{
  "schemaVersion": 1,
  "variables": {
    "key": "value"
  },
  "sources": {
    "name": {
      "fetcher": "type",
      "...": "..."
    }
  },
  "variants": {
    "variant-name": {
      "sources": {
        "name": {
          "override": "value"
        }
      }
    }
  }
}

Python Package Parsing

The script extracts information from patterns like:

{
  pname = "package-name";
  version = "1.0.0";
  src = fetchFromGitHub {
    owner = "user";
    repo = "repo";
    rev = "v1.0.0";
    sha256 = "...";
  };
}

Home Assistant Component Parsing

{
  domain = "component_name";
  version = "1.0.0";
  src = fetchFromGitHub {
    owner = "user";
    repo = "repo";
    rev = "v1.0.0";
    sha256 = "...";
  };
}

Error Handling

Network Errors

  • Timeouts: 10-second timeout on HTTP requests
  • HTTP status codes: Proper handling of 4xx/5xx responses
  • Retry logic: Graceful fallback when APIs fail

API Rate Limiting

  • Uses GITHUB_TOKEN environment variable if available
  • Provides clear error messages when rate limited
  • Falls back to git commands when API fails

Git Command Failures

  • Robust error handling for git ls-remote
  • Validation of git command output
  • Clear error messages for debugging

Configuration

Environment Variables

  • GITHUB_TOKEN: GitHub personal access token (optional)
  • Increases API rate limits from 60/hour to 5000/hour

Dependencies

  • Required: nix command with experimental features
  • Optional: nix-prefetch-git, git commands
  • Python: Standard library + curses

Troubleshooting

Hash Mismatches

  1. Check if using correct Nix version
  2. Verify network connectivity to GitHub
  3. Try manual hash computation:
    nix store prefetch-file --hash-type sha256 <url>
    

Missing Candidates

  1. Check GitHub token availability
  2. Verify repository exists and is accessible
  3. Check network connectivity
  4. Try manual API calls with curl

Display Issues

  1. Ensure terminal supports colors and Unicode
  2. Check terminal size (minimum 80x24 recommended)
  3. Try resizing terminal window
  4. Use -r flag to force redraw

Development

Adding New Fetcher Types

  1. Update fetch_candidates_for() method
  2. Add parsing logic to appropriate parse_*() function
  3. Update hash computation methods
  4. Add UI handling for new type

Testing Changes

# Test individual functions
python3 -c "
from scripts.version_tui import nix_prefetch_url
print(nix_prefetch_url('https://example.com/file.tar.gz'))
"

# Test package parsing
python3 -c "
from scripts.version_tui import parse_python_package
print(parse_python_package(Path('packages/python/example/default.nix')))
"

Architecture Decisions

Why Multiple Hash Methods?

  • Different Nix versions have different available commands
  • Modern Nix uses nix store prefetch-file and nix eval
  • Legacy systems use nix-prefetch-url and nix-prefetch-git
  • Script tries modern methods first, falls back gracefully

Why Template Rendering?

  • Variables allow flexible version specifications
  • Supports ${variable} substitution in URLs and tags
  • Enables consistent updates across variants
  • Reduces duplication in version.json files

Why Two-Step Git Hash?

  • builtins.fetchGit provides store paths, not hashes
  • nix hash path works reliably on store paths
  • More consistent than trying to parse git command output
  • Works with all git repository formats

File Organization

scripts/
├── version_tui.py           # Main script
├── __pycache__/           # Python cache
└── README_tui.md           # This documentation

Security Considerations

  • No sensitive data is logged
  • GitHub tokens are handled securely via environment
  • Hash computation uses read-only operations
  • No credentials are stored or transmitted unnecessarily

Performance

  • Lazy loading of candidates (only when needed)
  • Caching of computed hashes during session
  • Parallel network requests where possible
  • Efficient terminal rendering with minimal refreshes