ha
This commit is contained in:
315
scripts/README_tui.md
Normal file
315
scripts/README_tui.md
Normal file
@@ -0,0 +1,315 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user