Dynamic service composition with PostGIS support#5
Merged
Conversation
Implements Phase 1 of dynamic service composition by adding detection functions to entrypoint.sh that analyze Gemfile and package.json to determine required services (PostgreSQL, MySQL, SQLite, Redis). Sets environment flags (NEEDS_POSTGRES, NEEDS_MYSQL, NEEDS_SQLITE, NEEDS_REDIS) that will be consumed by Phase 2 (docker-compose profiles) and Phase 3 (k8s conditional sidecars). Detection logic: - Scans Gemfile for pg, mysql2, sqlite3, redis, sidekiq gems - Scans package.json for pg, mysql2, sqlite3, redis, bull, bullmq packages - Multiple databases can be detected simultaneously - Logs detected services and exports flags for downstream use Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements Phase 2 of dynamic service composition by adding pre-launch service detection and Docker Compose profiles. This solves the timing paradox where entrypoint.sh detection runs inside the container after it's too late to decide which services Docker Compose should start. Changes: - Add bin/detect-services.sh for pre-launch service detection - Add profiles to docker-compose.yml (with-postgres, with-redis, claude) - Remove hard depends_on from claude service (apps handle retries) - Update bin/claude-sandbox to detect services and build profile flags The detection script analyzes Gemfile and package.json before container starts, using git archive pattern similar to auto_detect_ruby_version. Falls back to starting all services if detection fails or script is missing, ensuring backward compatibility. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add documentation to claude-sandbox README explaining how the automatic service detection works, including: - Detection logic for Gemfile and package.json - Pre-launch detection workflow - Fallback behavior for git archive limitations - Benefits of dynamic composition Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extends cmd_remote() to conditionally include postgres and redis sidecars based on pre-launch service detection, mirroring Phase 2's Docker Compose profile approach. Changes: - Add generate_k8s_job_yaml() function that creates YAML via heredoc with conditional blocks for sidecars - Add service detection to cmd_remote() reusing detect-services.sh - Replace static template approach with dynamic YAML generation - Include DATABASE_URL/REDIS_URL env vars only when respective sidecars are present - Export DATABASE_NAME for envsubst substitution - Maintain fail-open behavior: if detection fails, include all sidecars - Add note to job-template.yaml marking it as reference only Benefits: - Reduces resource waste by only provisioning needed sidecars - Faster job startup for repos without database dependencies - Consistent detection logic between local (docker-compose) and remote (k8s) Testing: - Validated YAML syntax with kubectl dry-run for all combinations - Verified container counts match expectations (1-3 containers) - Confirmed DATABASE_URL/REDIS_URL only present when sidecars included Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update README.md and k8s/TESTING.md to reflect the new dynamic sidecar behavior for Kubernetes jobs. Changes: - Update Remote section in README to highlight dynamic sidecar feature - Update Dynamic Service Composition section to mention K8s support - Replace Phase 2 testing instructions with dynamic detection tests - Add verification steps for container counts and env vars - Add test checklist items for dynamic sidecar validation - Document fallback behavior and git archive limitations The documentation now accurately reflects that both local (Docker Compose) and remote (Kubernetes) execution use the same service detection logic. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When SSH URLs are converted to HTTPS for K8s, git archive would prompt for username/password. Now embeds the token like entrypoint.sh does. Fixes authentication prompt when running: claude-sandbox remote Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Updated all references in: - entrypoint.sh - README.md - docs/ENV-FILES.md - docs/SOPS-SETUP.md - docs/.env.claude.example -> docs/.env.claude-sandbox.example The new name better describes the file's purpose: environment configuration specifically for the claude-sandbox container. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Prevents K8s from using stale cached images when tags are updated. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix gem patterns to match version constraints (e.g., gem 'pg', '~> 1.6') - Add fail-open: default to all services when git archive fails for GitHub URLs - This ensures Rails apps always get DATABASE_URL when needed Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The static job-template.yaml contained bash-style variable syntax
${DATABASE_NAME:-sandbox_development} which could cause URI parsing errors
if accidentally used. Changed to use the literal value since this file
is marked as "REFERENCE ONLY" and the actual dynamic generation in
claude-sandbox script already handles variable substitution correctly.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes K8s job generation to use postgis/postgis:16-3.4-alpine image and postgis:// URL scheme, making it consistent with Docker Compose local execution. PostGIS is backward compatible with PostgreSQL, enabling spatial database features without breaking existing projects. Changes: - bin/claude-sandbox line 337: postgres:// → postgis:// - bin/claude-sandbox line 361: postgres:16-alpine → postgis/postgis:16-3.4-alpine - k8s/job-template.yaml line 71: postgres:// → postgis:// - k8s/job-template.yaml line 100: postgres:16-alpine → postgis/postgis:16-3.4-alpine Docker Compose already used PostGIS (lines 12, 40), so this change ensures local/remote environment parity. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Close .claude-l86 and all subtasks (analyst, planner, implementer, reviewer) - Add lesson about universal upgrade strategy simplifying implementation - Capture analysis and specification artifacts Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
landovsky
added a commit
that referenced
this pull request
Feb 2, 2026
The Phase 3 dynamic K8s job generation was completed and merged in PR #5 (Dynamic service composition with PostGIS support). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete implementation of dynamic service composition for claude-sandbox, automatically detecting and provisioning only required services (Postgres/PostGIS, Redis, MySQL) in both Docker Compose and Kubernetes environments.
Feature Chain
This PR includes a series of interconnected features built in phases:
Phase 1: Service Detection (
.claude-53k)NEEDS_POSTGRES,NEEDS_REDIS,NEEDS_MYSQLPhase 2: Docker Compose Dynamic Profiles (
.claude-4nq)bin/detect-services.sh)Phase 3: K8s Dynamic Job Generation (
.claude-ogp)Phase 4: PostGIS Support (
.claude-l86)postgis/postgis:16-3.4-alpineimage (backward compatible)postgis://Additional Improvements
${DATABASE_NAME}variableimagePullPolicy: Alwaysfor fresh image pulls.env.claude→.env.claude-sandboxfor clarityGITHUB_TOKENin git archive URL for private reposFiles Changed
Core Implementation:
claude-sandbox/bin/claude-sandbox- Dynamic K8s job generationclaude-sandbox/bin/detect-services.sh- Service detection script (new)claude-sandbox/docker-compose.yml- Profile-based service compositionclaude-sandbox/entrypoint.sh- Service detection and loggingclaude-sandbox/k8s/job-template.yaml- Reference template (PostGIS)Documentation:
claude-sandbox/README.md- Feature documentationclaude-sandbox/k8s/TESTING.md- Test scenariosclaude-sandbox/docs/ENV-FILES.md- Updated for renameProcess Artifacts:
artifacts/lessons-learned.md- Captured learnings.beads/issues.jsonl- Issue trackingBenefits
✅ Resource Efficiency: Only provision services actually needed by the project
✅ Environment Parity: Same detection logic for local and remote
✅ PostGIS Support: Projects using spatial extensions now work
✅ Backward Compatible: Existing projects continue working unchanged
✅ Fail-Safe: Detection failures default to provisioning all services
✅ Maintainable: Clear separation between detection and provisioning
Testing
Related Issues
Closes
.claude-53k,.claude-4nq,.claude-ogp,.claude-l86Statistics
🤖 Generated with Claude Code