Implementation Roadmap: Controller-Based Architecture
Version: 2.0
Date: January 2026
Status: Current
Executive Summary
This document outlines the remaining work to complete the migration from the v1alpha1 (Localbuild) architecture to the v1alpha2 (Platform-based) controller architecture. Much of the foundation has been completed, and this roadmap focuses on the final steps needed to fully deprecate the Localbuild controller.
Current Implementation Status
✅ Completed Work
The following components have been successfully implemented:
Phase 1: v1alpha2 CRDs and Controllers
✅ GiteaProvider CRD - Defined in
api/v1alpha2/giteaprovider_types.go✅ GiteaProvider Controller - Implemented in
pkg/controllers/gitprovider/giteaprovider_controller.go- Waits for Platform owner reference before reconciling
- Discovers configuration from Platform CR
- Full unit test coverage
✅ NginxGateway CRD - Defined in
api/v1alpha2/nginxgateway_types.go✅ NginxGateway Controller - Implemented in
pkg/controllers/gatewayprovider/nginxgateway_controller.go- Complete implementation with tests
- Integration tests in place
✅ ArgoCDProvider CRD - Defined in
api/v1alpha2/argocdprovider_types.go✅ ArgoCDProvider Controller - Implemented in
pkg/controllers/gitopsprovider/argocdprovider_controller.go- Full controller implementation
- Unit tests included
✅ Platform CRD - Defined in
api/v1alpha2/platform_types.go✅ Platform Controller - Implemented in
pkg/controllers/platform/platform_controller.go- Owner reference pattern fully implemented
- Aggregates status from all three provider types (Git, Gateway, GitOps)
- Duck-typing support for provider independence
- RBAC permissions for updating provider CRs
Phase 2: CLI Integration
- ✅ CLI creates GiteaProvider CR -
pkg/build/build.go::createGiteaProvider()(line 394) - ✅ CLI creates ArgoCDProvider CR -
pkg/build/build.go::createArgoCDProvider()(line 428) - ✅ CLI creates NginxGateway CR -
pkg/build/build.go::createNginxGateway()(line 456) - ✅ CLI creates Platform CR -
pkg/build/build.go::createPlatform()(line 481)- Platform references all three provider types
- Proper ordering: Providers created before Platform
Phase 3: Provider Duck-Typing
- ✅ Duck-typing utilities -
pkg/util/provider/directorygit.go- Git provider duck-typinggateway.go- Gateway provider duck-typinggitops.go- GitOps provider duck-typing
Phase 4: Custom Package Integration
- ✅ CustomPackage Platform Integration -
pkg/controllers/custompackage/controller.go- Discovers git provider from Platform CR via duck-typing
- Supports explicit Platform reference via
spec.platformRef - Falls back to default Platform named "platform" in same namespace
- Maintains backward compatibility with Localbuild
- Full RBAC permissions for Platform resource access
🚧 Partially Complete
- Owner Reference Pattern ✅ Implemented but providers created AFTER Platform
- Platform controller adds owner references ✅
- Providers wait for owner references ✅
- Issue: CLI creates Platform AFTER providers, causing initial reconcile to happen before owner ref is set
- Fix needed: See Priority 1 below
❌ Not Yet Implemented
Critical Path Items
Localbuild CR Creation - Still active in CLI
- CLI still creates Localbuild CR (line 281-318 in
pkg/build/build.go) - Both v1alpha1 and v1alpha2 paths are active
- Need to remove Localbuild CR creation after v1alpha2 is proven stable
- CLI still creates Localbuild CR (line 281-318 in
Localbuild Controller Deprecation - Still active
- Controller still exists in
pkg/controllers/localbuild/ - Still registered in
pkg/controllers/run.go - Need migration plan and deprecation timeline
- Controller still exists in
Remaining Work - Prioritized
Priority 1: Fix Provider Creation Order (Low Risk) ⚡
Problem: Currently the CLI creates providers first, then Platform. This causes providers to reconcile before the Platform can add owner references, leading to a "WaitingForPlatform" phase initially.
Solution: Reorder the CLI to create Platform CR before provider CRs, or make providers wait longer before attempting reconciliation.
Implementation:
// In pkg/build/build.go, reorder around line 320-354:
// Create Platform CR FIRST (before providers)
setupLog.V(1).Info("Creating platform resource")
if err := b.createPlatform(ctx, kubeClient); err != nil {
if b.statusReporter != nil {
b.statusReporter.FailStep("resources", err)
}
return fmt.Errorf("creating platform resource: %w", err)
}
// Then create providers (they will wait for Platform to add owner refs)
setupLog.V(1).Info("Creating giteaprovider resource")
if err := b.createGiteaProvider(ctx, kubeClient); err != nil {
// ...
}
// ... continue with other providersFiles to modify:
pkg/build/build.go- Reorder CR creation (1 line move, ~20 lines)
Testing:
- Verify Platform creates owner references quickly
- Verify providers transition from WaitingForPlatform → Installing → Ready
- Check that all components reach Ready state
- Run integration tests
Timeline: 1-2 days
Risk: Low - Simple reordering, no logic changes
Priority 2: Platform Controller Orchestration (Completed) ✅
Status: ✅ COMPLETED - Platform controller orchestrates provider installation via owner references.
What Was Implemented:
- Platform controller sets owner references on provider CRs
- Platform controller aggregates status from all providers (Git, Gateway, GitOps)
- Platform reaches "Ready" state when all providers are Ready
- Uses duck-typing for provider independence
What Was NOT Implemented (and should not be):
- Bootstrap repository creation was initially planned but removed due to circular dependency
- ArgoCD, Gitea, and Nginx are "Essential Packages" installed by their provider controllers, not via GitOps
- Bootstrap GitRepository and Application CRs should be created by users or custom packages, not Platform controller
Files modified:
pkg/controllers/platform/platform_controller.go- Owner reference setup and status aggregation
Testing:
- ✅ Unit tests for provider aggregation
- ✅ Platform reaches Ready when all providers are Ready
- ✅ Duck-typing support verified
Timeline: Completed January 2026
Risk: Low - Simple orchestration, no complex logic
Priority 2: Custom Package Migration (Completed) ✅
Status: ✅ COMPLETED - Custom packages now use the Platform resource for git provider discovery.
What Was Implemented:
- CustomPackage controller updated to discover git provider from Platform CR
- Supports explicit Platform reference via
spec.platformReffield - Falls back to default Platform named "platform" in same namespace if no explicit reference
- Maintains backward compatibility with Localbuild by falling back to CustomPackage spec fields
- Uses duck-typing to work with any git provider type
- Full RBAC permissions added for Platform resource access
Implementation Details:
- Added
PlatformReffield to CustomPackage spec (optional) - Implemented
discoverGitProviderFromPlatform()method that:- Checks for explicit Platform reference first
- Falls back to default "platform" in same namespace
- Extracts git provider info using duck-typing utilities
- Falls back to CustomPackage spec fields for backward compatibility
- Updated
getGitProviderInfo()to prefer Platform discovery over CustomPackage spec - Added kubebuilder RBAC markers for Platform resource access
Files Modified:
api/v1alpha1/custom_package_types.go- Added PlatformRef field and PlatformReference typepkg/controllers/custompackage/controller.go- Implemented Platform discovery logic- Added RBAC permissions for reading Platform resources
Testing:
- ✅ Custom packages work with explicit Platform reference
- ✅ Custom packages work with default Platform lookup
- ✅ Backward compatibility maintained with Localbuild path
- ✅ Duck-typing support verified with different provider types
Timeline: Completed
Risk: Low - Backward compatible implementation
Priority 3: Remove Localbuild CR Creation from CLI (Low Risk) 🗑️
Problem: CLI still creates Localbuild CR alongside v1alpha2 CRs, creating redundancy and potential confusion.
Prerequisites:
- Priority 2 complete (custom packages working)
- All integration tests passing with v1alpha2 path
Implementation:
// In pkg/build/build.go, DELETE lines 281-318:
// Remove entire Localbuild CR creation block
// Keep only v1alpha2 CR creation:
// - createGiteaProvider()
// - createArgoCDProvider()
// - createNginxGateway()
// - createPlatform()Files to modify:
pkg/build/build.go- Remove Localbuild CR creation (~40 lines deleted)
Testing:
- Full e2e test suite
- Verify all functionality works without Localbuild CR
- Test custom packages
- Test with various CLI flags
- Performance comparison
Timeline: 2-3 days
Risk: Low - Well-tested with v1alpha2 path before removal
Priority 4: Deprecate Localbuild Controller (Low Risk) 📝
Problem: Localbuild controller is no longer needed once v1alpha2 architecture is fully operational.
Prerequisites:
- Priority 3 complete (CLI doesn't create Localbuild CRs)
- Multiple releases with v1alpha2 architecture stable
- Migration documentation complete
Implementation Phases:
Phase A: Mark as Deprecated (Release N)
- Add deprecation warnings to Localbuild CRD
- Update documentation stating Localbuild is deprecated
- Add runtime warnings when Localbuild CR is created
- Keep controller functional for migration period
Phase B: Remove Controller (Release N+2 or later)
- Remove controller registration from
pkg/controllers/run.go - Delete
pkg/controllers/localbuild/directory - Keep CRD definition for data migration
- Provide migration guide
Files to modify:
api/v1alpha1/localbuild_types.go- Add deprecation noticespkg/controllers/localbuild/controller.go- Add deprecation warningspkg/controllers/run.go- Eventually remove registration- Documentation - Update with migration guide
Timeline:
- Phase A: 1 week
- Phase B: 1 week (after 2+ releases)
Risk: Low - Controlled deprecation with long migration period
Priority 5: Documentation Updates (Ongoing) 📚
Continuous Updates Needed:
User Documentation
- Update getting started guides
- Document v1alpha2 CRs and usage
- Provide examples for each provider type
- Migration guide from v1alpha1 to v1alpha2
Developer Documentation
- Architecture diagrams with current state
- Controller interaction patterns
- Testing guidelines
- Adding new provider types
API Documentation
- CRD field descriptions
- Status field meanings
- Provider interface contracts
Files to update:
docs/user/- User guidesexamples/v1alpha2/- Example CRsREADME.md- Main getting started- API documentation (godoc comments)
Timeline: Ongoing throughout implementation
Risk: Low - Documentation only
Implementation Timeline
Sprint 1 (Week 1-2)
- ✅ Priority 1: Fix provider creation order
- ✅ Priority 2: Platform controller orchestration (owner references and status aggregation)
- Documentation: Update architecture diagrams
Sprint 2 (Week 3-4)
- ✅ Priority 2: Custom package migration
- Testing: Integration tests for v1alpha2 path
Sprint 3 (Week 5-6)
- Priority 3: Remove Localbuild CR creation
- Priority 4A: Mark Localbuild as deprecated
- Testing: Full e2e test suite
- Documentation: Migration guide
Sprint 4+ (Week 7+)
- Monitoring and bug fixes
- Performance optimization
- Additional provider implementations (GitHub, GitLab, etc.)
- Release planning
Future (After 2+ stable releases)
- Priority 4B: Remove Localbuild controller
- Cloud provider implementations (AWS, Azure, GCP)
Total Timeline: ~6-8 weeks for core migration (Priorities 1-3)
Testing Strategy
Unit Tests
- Platform controller tests exist
- Provider controller tests exist
- Custom package integration tests
Integration Tests
- Provider wait for owner reference
- Platform aggregation of all provider types
- Custom packages with v1alpha2 architecture
- Full workflow: CLI → Platform → Providers → Ready
E2E Tests
-
idpbuilder createwith v1alpha2 only (no Localbuild) - All core components operational
- Custom packages deployment
- Multi-provider scenarios
Performance Tests
- Benchmark v1alpha2 vs v1alpha1 performance
- Resource utilization comparison
- Time to Ready comparison
Success Criteria
- Platform controller orchestrates provider installation via owner references
- Platform controller aggregates provider status
- Custom packages work with v1alpha2 architecture
- CLI creates only v1alpha2 CRs (no Localbuild)
- All integration tests pass
- All e2e tests pass
- Performance is equal or better than v1alpha1
- Documentation is complete and accurate
- Migration guide is available
- Localbuild controller marked as deprecated
Risks and Mitigations
| Risk | Impact | Likelihood | Mitigation |
|---|---|---|---|
| Breaking existing users | High | Low | Keep both paths working during transition, long deprecation period |
| Performance regression | Medium | Low | Benchmark and compare, optimize as needed |
| Missing functionality | High | Medium | Comprehensive feature parity checklist, thorough testing |
| Complex migration | Medium | Medium | Detailed step-by-step guide, automation where possible |
| Custom package breakage | Medium | Medium | Maintain backward compatibility, test all package scenarios |
Reference Documentation
Technical Specifications
- Controller Architecture Specification - Overall architecture design
- Resource Creation Sequencing - State transitions and coordination
- Client Architecture Specification - Future CLI enhancements
Archived Implementation Docs
- Archived Implementation Documentation - Historical planning documents
Current Codebase
api/v1alpha2/- v1alpha2 CRD definitionspkg/controllers/platform/- Platform controllerpkg/controllers/gitprovider/- Git provider controllerspkg/controllers/gatewayprovider/- Gateway provider controllerspkg/controllers/gitopsprovider/- GitOps provider controllerspkg/controllers/localbuild/- Legacy Localbuild controller (to be deprecated)pkg/build/build.go- CLI CR creation logicexamples/v1alpha2/- Example CRs
Questions and Open Issues
Open Questions
Bootstrap timing: Should Platform wait for providers to be fully Ready before creating bootstrap resources, or create them in parallel?
- Recommendation: Wait for Ready to avoid race conditions
Custom package controller: Should it be independent or part of Platform?✅ Resolved- Resolution: Kept independent with Platform integration for provider discovery
Migration automation: Should we provide a tool to migrate v1alpha1 to v1alpha2?
- Recommendation: Not needed - v1alpha2 is new deployment, not migration
Known Issues
Platform creates owner references after providers start reconciling✅ Fixed in Priority 1Custom package handling still in Localbuild controller✅ Fixed - Custom packages now use Platform resource- No e2e tests for v1alpha2-only path yet
Getting Help
For questions about this roadmap or the implementation:
- Check the technical specifications for design details
- Review archived implementation docs for historical context
- Open a GitHub issue for discussion
- Refer to the Controller Architecture Spec for architectural guidance
Last Updated: January 2026
Next Review: After Priority 3 completion (Localbuild CR removal)