Files
pi-pm3/BUILD_CONSTRAINTS.md
michael 4f35df1781 Initial commit - Phase 3/4
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 13:46:22 -08:00

278 lines
7.9 KiB
Markdown

# Build Constraints and Optimization Strategy
**Date:** 2025-11-27
**Critical Context:** This project has severe bandwidth constraints that make build optimization MANDATORY, not optional.
---
## Primary Constraint: Slow Network
**Measured download speed: ~265 kB/s (0.26 MB/s)**
### Impact on Build Times
| Stage | Download Size | Download Time | Total Time | Notes |
|-------|---------------|---------------|------------|-------|
| **stage0** | ~200 MB | 13 min | 18 min | Base Debian system |
| **stage1** | ~450 MB | 29 min | 37 min | Kernel + firmware |
| **stage2** | ~850 MB | 55 min | 65 min | Desktop + network tools |
| **stagePM3** | ~220 MB | 14 min | 59 min | PM3 build (downloads + compile) |
| **stageDangerousPi** | ~140 MB | 9 min | 12 min | Custom packages |
| **TOTAL** | **~1.86 GB** | **~120 min** | **~191 min** | **3+ hours** |
### Critical Implications
1. **Every failed build wastes 3+ hours**
2. **Stage0-2 alone = 2 hours of downloading**
3. **Cannot afford trial-and-error debugging**
4. **Pre-flight validation MUST be perfect**
5. **Incremental builds are MANDATORY for iteration**
---
## Build Optimization Strategy
### 1. QCOW2 Caching (MANDATORY)
```bash
# In pi-gen/config
USE_QCOW2=1 # NEVER disable this
```
**Why:** Enables copy-on-write snapshots. After stage2 completes once (2 hours), we can rebuild from that point in ~70 minutes instead of 3+ hours.
**Cache Location:** `/home/work/pi-gen-builder/work/*/stage*.qcow2`
### 2. Three-Tier Build Strategy
```bash
# Full build: Clean slate (3+ hours)
./build-image.sh full
# From PM3: Rebuild PM3 + customizations (70 min)
./build-image.sh from-pm3
# From DangerousPi: Rebuild only customizations (5 min)
./build-image.sh from-dtpi
```
**Daily workflow:**
- First build: `full` (one-time 3hr investment)
- Iterating on PM3 changes: `from-pm3` (70 min)
- Iterating on app/WiFi/config: `from-dtpi` (5 min)
### 3. Container vs Volume Management
**CRITICAL DISTINCTION:**
- **Container** (`docker rm pigen_work`): Safe to remove, just metadata
- **Volume** (`docker rm -v pigen_work`): ❌ NEVER DO THIS - nukes 2hr download cache
**Build script behavior:**
- `full` mode: Removes container AND volume (fresh start)
- `from-pm3` mode: Preserves cache, removes container
- `from-dtpi` mode: Preserves cache, removes container
---
## Pre-Flight Validation Requirements
### Philosophy
> **"Fail fast, fail loud, fail BEFORE downloading anything"**
With 3+ hour builds, we CANNOT afford to discover errors after stage0-2 completes.
### Current Checks (52 total)
✅ Pi-gen directory exists
✅ Docker available and accessible
✅ qemu-aarch64 registration
✅ Config file validation
✅ Stage structure (prerun.sh, EXPORT_IMAGE, substages)
✅ Build script syntax validation
✅ Dependency analysis (header → package mapping)
✅ Source file availability
✅ Build script validation
### Required Additions
The following checks MUST be added to prevent wasted builds:
#### A. Pre-Download Validation
- [ ] **Disk space check:** Require 15GB free before starting
- [ ] **Network connectivity:** Verify can reach deb.debian.org
- [ ] **Git repo accessibility:** Test clone URLs without cloning
- [ ] **Stage size estimation:** Warn if total download > threshold
#### B. Deep Script Analysis
- [ ] **File reference validation:** Grep for all file paths in scripts, verify they exist
- [ ] **Service file syntax:** Validate systemd .service files
- [ ] **Environment variables:** Check for undefined vars in scripts
- [ ] **Path existence:** Verify all mkdir -p targets don't conflict
- [ ] **Port conflicts:** Check for duplicate port assignments
#### C. Configuration Validation
- [ ] **STAGE_LIST ordering:** Ensure stages are in dependency order
- [ ] **EXPORT_IMAGE syntax:** Validate all EXPORT_IMAGE files
- [ ] **Duplicate substages:** Check for numbering conflicts (e.g., two 00-run.sh in same stage)
- [ ] **Username consistency:** Verify same user referenced across stages
#### D. Build Artifact Validation
- [ ] **Post-stage verification:** After each stage, check expected files exist
- [ ] **Binary executability:** Test compiled binaries actually run
- [ ] **Python import test:** Verify Python modules can be imported
- [ ] **Service enable test:** Verify systemd services are enabled
---
## Development Workflow Optimizations
### 1. Test Changes Locally First
Before modifying stage scripts, test commands locally:
```bash
# Test PM3 dependency installation
docker run --rm -it debian:trixie bash
> apt-get update && apt-get install -y gcc-arm-none-eabi
> which arm-none-eabi-gcc
# Test Python package installation
docker run --rm -it debian:trixie bash
> apt-get update && apt-get install -y python3-pip
> pip3 install --break-system-packages fastapi==0.115.0
```
**Saves:** Hours of build time by catching errors early
### 2. Use Build Log Analysis
During builds, monitor for early warning signs:
```bash
# Watch for errors in real-time
docker logs -f pigen_work 2>&1 | grep -i "error\|fail\|fatal"
# Check what stage we're on
./scripts/build-status.sh
# Estimate completion based on download speed
docker logs pigen_work 2>&1 | grep "Fetched.*in.*(" | tail -5
```
### 3. Parallel Development
While a build runs, prepare next iteration:
```bash
# Terminal 1: Build running
./build-image.sh full
# Terminal 2: Test next changes
cd /tmp/test-changes
# Test scripts, validate syntax, etc.
```
---
## Failure Recovery Procedures
### If Build Fails During stagePM3 or Later
**DO NOT KILL CONTAINER**
1. Let it fail completely
2. Check what stage completed:
```bash
ls -la /home/work/pi-gen-builder/work/*/stage*.qcow2
```
3. If stage2.qcow2 exists, you have cache:
```bash
./build-image.sh from-pm3
```
### If Build Fails During stage0-2
**Only kill if you know stage will fail:**
```bash
# Check if we have partial cache
ls -la /home/work/pi-gen-builder/work/*/stage*.qcow2
# If no .qcow2 files, killing wastes nothing
# If stage1.qcow2 exists, let it finish stage2
```
---
## Cost-Benefit Analysis
### Why Pre-Flight Validation Matters
**Without perfect validation:**
- Change PM3 script
- Start 3hr build
- Discover typo at hour 2.5
- Fix typo
- Restart 3hr build
- **Total time wasted: 6 hours**
**With perfect validation:**
- Change PM3 script
- Run pre-flight (30 seconds)
- Catch typo immediately
- Fix typo
- Run pre-flight again (30 seconds)
- Start build with confidence
- **Total time wasted: 60 seconds**
**ROI: 360x time savings**
---
## Questions for Future Optimization
1. **Network caching:** Should we set up apt-cacher-ng to cache Debian packages locally?
- Pro: Rebuilds wouldn't re-download same packages
- Con: Setup complexity, disk space (20GB+)
2. **Disk space monitoring:** Add alerts when cache disk < 10GB free?
3. **Build checkpointing:** Should we export stage2.qcow2 as a baseline artifact?
4. **Parallel builds:** Can we test multiple variants simultaneously?
5. **Common errors database:** Should we maintain a list of known failure patterns to check for?
---
## Action Items
### Immediate (Before Next Build)
- [ ] Add disk space check to pre-flight
- [ ] Add network connectivity check to pre-flight
- [ ] Document common failure patterns we've seen
- [ ] Test local command validation workflow
### Short-term (This Week)
- [ ] Add deep script validation (file references, env vars)
- [ ] Create build artifact verification
- [ ] Set up build time estimation based on network speed
- [ ] Document recovery procedures for each failure type
### Long-term (Future Optimization)
- [ ] Consider apt-cacher-ng for package caching
- [ ] Automated build artifact testing
- [ ] Build time alerting/monitoring
- [ ] Stage baseline export/import
---
## Key Takeaway
> **Every validation check we add to pre-flight saves potentially 3+ hours of wasted build time.**
>
> **Spending 5 minutes improving pre-flight can save hours of debugging.**
>
> **This is not premature optimization - it's mandatory survival strategy.**