05_17_04: Monorepo Tools - AudioLab Workspace Management¶
Executive Summary¶
Tools for managing AudioLab's component-based monorepo. Handles package organization, dependency tracking, selective builds, and coordinated releases across L0-L3 architecture layers.
Key Features: - Multi-package workspace management - Dependency graph and validation - Selective builds (affected packages only) - Topological build ordering - Layer-based organization (L0 → L1 → L2 → L3) - Change impact analysis
Architecture¶
Workspace Structure¶
AudioLab Monorepo
├── L0: Kernels (Atomic DSP operations)
├── L1: Atoms (Basic processing blocks)
│ └── depends on: L0
├── L2: Cells (Complex components)
│ └── depends on: L0, L1
├── L3: Engines (Complete processors)
│ └── depends on: L0, L1, L2
└── Core Libraries (Foundation)
Dependency Rules¶
- L1 can depend on L0 only
- L2 can depend on L0, L1
- L3 can depend on L0, L1, L2
- No circular dependencies
- Core libraries are leaf nodes
Packages¶
L0 - Kernels¶
- Path:
3 - COMPONENTS/05_MODULES/05_04_KERNELS_L0 - Type: Library
- Dependencies: None
- Description: Atomic DSP operations
L1 - Atoms¶
- Path:
3 - COMPONENTS/05_MODULES/05_07_ATOMS_L1 - Type: Library
- Dependencies: kernels
- Description: Basic processing blocks
L2 - Cells¶
- Path:
3 - COMPONENTS/05_MODULES/05_10_CELLS_L2 - Type: Library
- Dependencies: atoms, kernels
- Description: Complex components
L3 - Engines¶
- Path:
3 - COMPONENTS/05_MODULES/05_13_ENGINES_L3 - Type: Library
- Dependencies: cells, atoms, kernels
- Description: Complete processors
Core Libraries¶
- type-system: Type system and parameter types
- core-interfaces: Core interfaces and base classes
- math-primitives: Math and DSP primitives
- buffer-management: Buffer and memory management
Usage¶
List Packages¶
Output:
AudioLab Monorepo Packages
============================================================
L0:
- kernels [library]
L1:
- atoms [library] (deps: kernels)
L2:
- cells [library] (deps: atoms, kernels)
L3:
- engines [library] (deps: cells, atoms, kernels)
other:
- core-interfaces [library]
- type-system [library]
- math-primitives [library]
- buffer-management [library]
Check Status¶
Output:
Package Status
============================================================
✓ kernels 3 - COMPONENTS/05_MODULES/05_04_KERNELS_L0
✓ atoms 3 - COMPONENTS/05_MODULES/05_07_ATOMS_L1
✓ cells 3 - COMPONENTS/05_MODULES/05_10_CELLS_L2
✓ engines 3 - COMPONENTS/05_MODULES/05_13_ENGINES_L3
✓ core-interfaces 2 - FOUNDATION/04_CORE/04_01_core_interfaces
Generate Dependency Graph¶
Generates dependency-graph.dot:
digraph AudioLab {
rankdir=LR;
node [shape=box];
subgraph cluster_L0 {
label="L0";
"kernels";
}
subgraph cluster_L1 {
label="L1";
"atoms";
}
"atoms" -> "kernels";
"cells" -> "atoms";
"cells" -> "kernels";
"engines" -> "cells";
"engines" -> "atoms";
"engines" -> "kernels";
}
Convert to SVG:
Find Affected Packages¶
Output:
Impact: If kernels changes, all L1-L3 must be rebuilt.
Build Affected Packages Only¶
Output:
Building 4 affected packages: atoms, cells, engines, kernels
Build order: kernels → atoms → cells → engines
Building kernels...
cd 3 - COMPONENTS/05_MODULES/05_04_KERNELS_L0 && cmake --build build
Building atoms...
cd 3 - COMPONENTS/05_MODULES/05_07_ATOMS_L1 && cmake --build build
...
Build Specific Packages¶
Selective Builds¶
Strategy¶
Affected-only builds: Only build packages that: 1. Have source changes 2. Depend on packages with changes (downstream)
Change Detection¶
# Detect changed files
git diff --name-only main
# Map files → packages
changed_packages = []
for file in changed_files:
if file.startswith('3 - COMPONENTS/05_MODULES/05_07_ATOMS_L1'):
changed_packages.append('atoms')
# Find affected packages (downstream dependencies)
affected = get_affected_packages(changed_packages)
Build Order¶
Topological sort based on dependency graph:
kernels (no deps)
↓
atoms (depends on kernels)
↓
cells (depends on atoms, kernels)
↓
engines (depends on cells, atoms, kernels)
Dependency Management¶
Validation¶
On commit:
Enforced rules: - ✅ L1 → L0 only - ✅ L2 → L0, L1 - ✅ L3 → L0, L1, L2 - ❌ No L0 → L1 (reverse dependency) - ❌ No circular dependencies
Graph Analysis¶
# Build dependency graph
graph = {
'atoms': {'kernels'},
'cells': {'atoms', 'kernels'},
'engines': {'cells', 'atoms', 'kernels'},
}
# Find affected packages
def get_affected(changed):
affected = set(changed)
changed_flag = True
while changed_flag:
changed_flag = False
for pkg, deps in graph.items():
if pkg not in affected and deps.intersection(affected):
affected.add(pkg)
changed_flag = True
return affected
CI/CD Integration¶
GitHub Actions¶
- name: Detect affected packages
run: |
python monorepo_manager.py affected > affected.txt
- name: Build affected only
run: |
python monorepo_manager.py build --affected
- name: Test affected only
run: |
for pkg in $(cat affected.txt); do
cd $pkg && ctest
done
Benefits¶
- Faster CI: Only build/test what changed
- Parallel builds: Independent packages build in parallel
- Efficient caching: Cache by package + commit hash
Versioning Strategy¶
Coordinated Versioning¶
All packages share same version:
Benefits: - Simplified dependency management - Clear compatibility guarantees - Easier releases
On release: - All packages bump version together - Single changelog for all changes
Best Practices¶
DO ✅¶
- Keep packages small and focused
- Minimize cross-package dependencies
- Use interfaces for loose coupling
- Build in topological order
- Test affected packages on changes
- Cache build artifacts
- Use selective builds in CI/CD
DON'T ❌¶
- Create circular dependencies
- Skip dependency validation
- Build all packages on small changes
- Mix concerns across packages
- Ignore layer boundaries (L0-L3)
Performance¶
Selective Build Savings¶
Example scenario:
- Change in kernels package
- Traditional: Build all 4 layers (100%)
- Selective: Build affected only (100% - kernels changed)
Example scenario 2:
- Change in engines package only
- Traditional: Build all 4 layers (100%)
- Selective: Build engines only (25%)
- Savings: 75% build time
Parallel Builds¶
Independent packages build in parallel:
kernels (start)
↓
atoms + core-libs (parallel)
↓
cells (depends on atoms)
↓
engines (depends on cells)
Configuration Files¶
- monorepo_config.yaml: Workspace configuration
- monorepo_manager.py: Management CLI tool
Integration¶
With Build System¶
With Version Control¶
With CI/CD¶
- Detect affected packages
- Build/test affected only
- Cache per package
- Parallel execution
Part of AudioLab Version Control System (05_17_VERSION_CONTROL)