315 lines
7.8 KiB
Markdown
Executable File
315 lines
7.8 KiB
Markdown
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
|
|
```json
|
|
{
|
|
"fetcher": "github",
|
|
"owner": "owner",
|
|
"repo": "repo",
|
|
"tag": "v1.0.0",
|
|
"rev": "commit-hash",
|
|
"hash": "sha256-..."
|
|
}
|
|
```
|
|
|
|
### Git Fetcher
|
|
```json
|
|
{
|
|
"fetcher": "git",
|
|
"url": "https://github.com/user/repo.git",
|
|
"rev": "commit-hash",
|
|
"hash": "sha256-..."
|
|
}
|
|
```
|
|
|
|
### URL Fetcher
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"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:
|
|
```nix
|
|
{
|
|
pname = "package-name";
|
|
version = "1.0.0";
|
|
src = fetchFromGitHub {
|
|
owner = "user";
|
|
repo = "repo";
|
|
rev = "v1.0.0";
|
|
sha256 = "...";
|
|
};
|
|
}
|
|
```
|
|
|
|
### Home Assistant Component Parsing
|
|
```nix
|
|
{
|
|
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:
|
|
```bash
|
|
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
|
|
```bash
|
|
# 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 |