Add deploy-{name} CI steps to all component templates (app-astro,
app-react, service, worker) so each component deploys independently
via kubectl set image on merge to main. Replace the skeleton's
generic deploy step with a verify step that confirms deployments.
Add GET /templates/components endpoint for listing available component
templates with optional type filter. Simplify component API by merging
type+template into a single type field (e.g., "app-react" instead of
type="app" template="app-react").
Include ESLint configs and pnpm-workspace.yaml in app templates.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Short-form DNS names (e.g. postgres.databases.svc) fail to resolve in
new pods due to k8s DNS search domain limitations. Switch all service
hostnames to FQDNs (*.svc.cluster.local).
Remove commonLabels from kustomization.yaml — it injected labels into
all selectors including NetworkPolicy egress rules (blocking DNS to
CoreDNS) and Deployment selectors (causing immutability errors).
Add OTEL_EXPORTER_OTLP_ENDPOINT env var to deployment YAML so the
telemetry collector endpoint uses the FQDN without requiring a binary
rebuild.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds the composable monorepo template system that generates project skeletons
with pluggable components (service, worker, app-react, app-astro, cli).
Key changes:
- Monorepo skeleton templates with shared pkg/, scripts/, and git hooks
- Component templates (service, worker, app-react, app-astro, cli) with
Dockerfiles, CI steps, and component.yaml manifests
- Component domain model with validation and dependency resolution
- Component handler endpoints for CRUD and composition
- Template provider extended with BuildComposableProject and component assembly
- Deployer extended with composable project deployment support
- Handler timeout constants (TimeoutFastLookup through TimeoutLongRunning)
- envutil package for centralized env var reads with defaults
- api.DecodeJSON helper for standardized request body decoding
- Standardized response helpers (WriteBadRequest, WriteNotFound, etc.)
- Replaced fullstack-app cookbook with composable-app cookbook
- Hardened handler timeouts, logging, and error responses across all handlers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a worker dies mid-build, queue maintenance now updates both
work_queue and build_audit tables when requeuing stale tasks.
This prevents builds from showing "running" forever in the API.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The shared worker pool (claudebox-0) now handles all project builds
with dynamic git cloning. The dedicated per-project pods were stuck
in Init state and are no longer needed.
Removed:
- claudebox-aeries StatefulSet and PVC
- claudebox-pantheon StatefulSet and PVC
- Associated secrets and configmaps (deleted from cluster)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When Claude fails to execute, error messages now include:
- Captured stderr output from the failed command
- Troubleshooting commands to exec into pod and run `claude login`
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add session_id, model, allowed_tools to Claude request handler
- Update OpenAPI spec for Claude endpoint
- Fix BuildExecutor constructor call sites
- Rewrite landing-test.sh for agent-driven flow
- Fix cookbook documentation for correct API format
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: WorkerService.ClaimTask() was modifying the audit entry
in memory but never persisting it to the database. This caused build
tasks to remain stuck at "pending" status even after being claimed.
Changes:
- Add UpdateStatus method to port.BuildAudit interface
- Implement UpdateStatus in postgres.BuildAuditRepository
- Fix ClaimTask to call audit.UpdateStatus() to persist status
- Add test coverage for audit update during task claim
- Update all mock implementations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix pipeline API response format (.data not .data.pipelines)
- Add pipeline monitoring with timeout
- Add site HTTP 200 verification
- Add DNS alias add/remove testing
- Show test results summary with pass/fail status
The woodpecker-deployer-rbac.yaml was in kustomization.yaml but
release.sh only applied rdev-api.yaml directly. This caused CI
deploy steps to fail with RBAC forbidden errors.
Now release.sh --deploy applies both manifests.
- Initial K8s deployment auto-creation during project creation
- DNS record upsert support (create or update existing records)
- Ingress host management for domain aliases (AddIngressHost/RemoveIngressHost)
- Woodpecker deployer RBAC manifest for CI deploy steps
- Single-commit template seeding via Gitea bulk file API
Closes automation gaps exposed during www.threesix.ai launch:
- Projects now auto-create K8s Deployment/Service/Ingress on creation
- Domain aliases automatically update both DNS and K8s ingress
- CI deploy steps work without manual RBAC setup
- Template seeding triggers only one CI pipeline (not per-file)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The deployer was using cert-manager.io/issuer (namespace-scoped)
referencing letsencrypt-threesix which only exists in the threesix
namespace. Projects deploy to the projects namespace, so changed to
cert-manager.io/cluster-issuer with letsencrypt-prod.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The destinations format caused Kaniko to push images with the full
registry URL as part of the repo path (registry.threesix.ai/name
instead of just name). Using registry + repo + tags format pushes
to the correct path.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The templates referenced zot.orchard9.ai which has no DNS record.
The actual zot registry is at registry.threesix.ai. Also updated
static templates to use Kaniko plugin instead of docker:24-dind.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The deployer was blindly calling Namespaces().Create() which triggered
cluster-scope RBAC checks even when the namespace already existed.
Now checks with Get() first and only creates if NotFound.
Also adds namespace get/create and secrets create/update/patch
permissions to the rdev-api-deployer ClusterRole.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Switch from raw gcr.io/kaniko-project/executor:debug to
woodpeckerci/plugin-kaniko with destinations setting. Also use
npm install instead of npm ci (no lock file in templates) and
skip-tls-verify for self-signed registry certs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Zot is configured without authentication, so remove the auth
configuration step from templates. Added --insecure flag for
internal registry access.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace Docker-in-Docker (privileged mode) with Kaniko for container
builds. This allows CI pipelines to run without requiring trusted
repo status in Woodpecker.
- astro-landing: Use Kaniko with from_secret for registry auth
- go-api: Use Kaniko with from_secret for registry auth
- default: Use Kaniko with from_secret for registry auth
Kaniko builds and pushes images without requiring privileged mode,
making it compatible with Woodpecker's default security settings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PipelineErrorResponse struct to handler
- Add Errors field to PipelineResponse struct
- Add mapPipelineErrors helper function
- Include errors in both ListPipelines and GetPipeline responses
Root cause of CI failures: Woodpecker trust level doesn't allow privileged mode
for docker steps. Errors were being returned by Woodpecker but not exposed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CIPipelineError struct to domain with Type, Message, IsWarning fields
- Map Woodpecker Pipeline.Errors to domain.CIPipeline.Errors
- Fix migration 013: UUID type for project_id, cast id to text for MD5
- Remove invalid domain data migration (columns don't exist)
- Update release.sh with --deploy flag and migration support
- Fix test nil pointer: check errors in TestAPIKeyRepository_ProjectIDArrayHandling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add --deploy flag documentation to quick reference
- Update platform status with Multi-Domain Support (Done)
- Add current version indicator
- Add new implementation entries to cookbook
- Mark cookbook ready for E2E testing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Landing page cookbook implementation (Weeks 1-4):
Domain Infrastructure:
- Add project_domains table with migration (013_project_domains.sql)
- Add ProjectDomain model with domain types (primary_auto, primary_custom, alias)
- Add SlugGenerator and ProjectDomainRepository interfaces
- Implement postgres adapters for domain and slug management
Service Layer:
- Add domain CRUD methods to ProjectInfraService
- Generate 8-char random slugs for auto-domains
- Support custom subdomains during project creation
- Add site_live health check to project status
- Trigger CI build after template seeding
Handler Updates:
- Add DomainService interface and adapter pattern
- Rewrite domain handlers to use database-backed service
- Add proper error handling for duplicate/missing domains
CI Integration:
- Add TriggerBuild to CIProvider interface
- Implement TriggerBuild in Woodpecker adapter
- Manually trigger initial build after template seed
Cookbook & Scripts:
- Add landing-test.sh script for E2E testing
- Add release.sh for version releases
- Add logs.sh for quick log access
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>