Skip to content

Commit 9130b00

Browse files
jeremyederclaude
andauthored
fix: improve dev-cluster skill with engine detection and fast inner-loop (#630)
## Summary Follow-up to #622. Fixes issues discovered while using the dev-cluster skill in practice: - **Container engine detection**: Skill defaulted to podman and failed when only docker was available. Now detects available engine before building. - **Dynamic port detection**: Hardcoded `localhost:8080` was wrong for Docker (maps to port 80). Now checks actual port mapping. - **PR-based workflow**: Added "Setting Up from a PR" section for the common `gh pr view` → checkout → build flow. - **Fast inner-loop**: Added section documenting `npm run dev` + `kubectl port-forward` for instant frontend hot-reload without image rebuilds. - **Build commands**: All `make build-*` examples now pass `CONTAINER_ENGINE=`. ## Test plan - [ ] Invoke dev-cluster skill and verify it detects docker/podman correctly - [ ] Verify port detection works for both Docker and Podman kind clusters - [ ] Test fast inner-loop instructions work end-to-end 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9c541e3 commit 9130b00

1 file changed

Lines changed: 125 additions & 27 deletions

File tree

.claude/skills/dev-cluster/SKILL.md

Lines changed: 125 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,65 @@ The Ambient Code Platform consists of these containerized components:
7272

7373
**Access:** http://localhost:3000 (frontend) / http://localhost:8080 (backend)
7474

75+
## Workflow: Setting Up from a PR
76+
77+
When a user provides a PR URL or number, follow this process:
78+
79+
### Step 1: Fetch PR Details
80+
```bash
81+
# Get PR metadata (title, branch, changed files, state)
82+
gh pr view <PR_NUMBER> --json title,headRefName,files,state,body
83+
```
84+
85+
### Step 2: Checkout the PR Branch
86+
```bash
87+
git fetch origin <branch_name>
88+
git checkout <branch_name>
89+
```
90+
91+
### Step 3: Determine Affected Components
92+
Analyze the changed files from the PR to identify which components need rebuilding (see component mapping below). Then follow the appropriate cluster workflow (Kind or Minikube).
93+
94+
## Detecting the Container Engine
95+
96+
**Before any build step**, detect which container engine is available:
97+
98+
```bash
99+
# Check which engine is available
100+
if command -v docker &>/dev/null && docker info &>/dev/null 2>&1; then
101+
CONTAINER_ENGINE=docker
102+
elif command -v podman &>/dev/null && podman info &>/dev/null 2>&1; then
103+
CONTAINER_ENGINE=podman
104+
else
105+
echo "ERROR: No container engine available"
106+
exit 1
107+
fi
108+
```
109+
110+
**Always pass `CONTAINER_ENGINE=` to make commands:**
111+
```bash
112+
make build-frontend CONTAINER_ENGINE=docker
113+
make build-all CONTAINER_ENGINE=docker
114+
```
115+
116+
## Detecting the Access URL
117+
118+
After deployment, **check the actual port mapping** instead of assuming a fixed port:
119+
120+
```bash
121+
# For kind with Docker: check the container's published ports
122+
docker ps --filter "name=ambient-local" --format "{{.Ports}}"
123+
# Example output: 0.0.0.0:80->30080/tcp → access at http://localhost
124+
# Example output: 0.0.0.0:8080->30080/tcp → access at http://localhost:8080
125+
126+
# Quick connectivity test
127+
curl -s -o /dev/null -w "%{http_code}" http://localhost:80
128+
```
129+
130+
**Port mapping depends on the container engine:**
131+
- **Docker**: host port 80 → http://localhost
132+
- **Podman**: host port 8080 → http://localhost:8080
133+
75134
## Workflow: Testing Changes in Kind
76135

77136
When a user says something like "test this changeset in kind", follow this process:
@@ -109,30 +168,31 @@ Note: By default, kind uses production Quay.io images. We'll need to:
109168
```
110169

111170
### Step 3: Build Changed Components
112-
```bash
113-
# Build specific components (from /workspace/repos/platform)
114-
cd /workspace/repos/platform
115171

172+
**Important:** Detect the container engine first (see "Detecting the Container Engine" above), then pass it to all build commands.
173+
174+
```bash
175+
# Build specific components — always pass CONTAINER_ENGINE
116176
# Build backend (if changed)
117-
make build-backend
177+
make build-backend CONTAINER_ENGINE=$CONTAINER_ENGINE
118178

119179
# Build frontend (if changed)
120-
make build-frontend
180+
make build-frontend CONTAINER_ENGINE=$CONTAINER_ENGINE
121181

122182
# Build operator (if changed)
123-
make build-operator
183+
make build-operator CONTAINER_ENGINE=$CONTAINER_ENGINE
124184

125185
# Build runner (if changed)
126-
make build-runner
186+
make build-runner CONTAINER_ENGINE=$CONTAINER_ENGINE
127187

128188
# Build state-sync (if changed)
129-
make build-state-sync
189+
make build-state-sync CONTAINER_ENGINE=$CONTAINER_ENGINE
130190

131191
# Build public-api (if changed)
132-
make build-public-api
192+
make build-public-api CONTAINER_ENGINE=$CONTAINER_ENGINE
133193

134194
# Or build all at once
135-
make build-all
195+
make build-all CONTAINER_ENGINE=$CONTAINER_ENGINE
136196
```
137197

138198
### Step 4: Setup/Update Kind Cluster
@@ -189,11 +249,14 @@ kubectl logs -l app=backend -n ambient-code --tail=50
189249
```
190250

191251
### Step 7: Provide Access Info
252+
253+
**Detect the actual URL** by checking the kind container's port mapping (see "Detecting the Access URL" above), then provide the correct URL to the user.
254+
192255
```
193256
✓ Deployment complete!
194257
195258
Access the platform at:
196-
- Frontend: http://localhost:8080 (or http://localhost with Docker)
259+
- Frontend: <detected URL from port mapping>
197260
- Test credentials: Check .env.test for the token
198261
199262
To view logs:
@@ -403,8 +466,8 @@ kubectl describe pod -l app=backend -n ambient-code | grep Image:
403466
Key environment variables that affect cluster behavior:
404467

405468
```bash
406-
# Container runtime
407-
CONTAINER_ENGINE=podman # or docker
469+
# Container runtime (detect automatically — see "Detecting the Container Engine")
470+
CONTAINER_ENGINE=docker # or podman
408471

409472
# Build platform
410473
PLATFORM=linux/amd64 # or linux/arm64
@@ -416,15 +479,46 @@ NAMESPACE=ambient-code
416479
REGISTRY=quay.io/your-org
417480
```
418481

482+
## Fast Inner-Loop: Run Frontend Locally (No Image Rebuilds)
483+
484+
For **frontend-only changes**, skip image rebuilds entirely. Run NextJS locally with hot-reload against the backend in the kind cluster:
485+
486+
```bash
487+
# Terminal 1: port-forward backend from kind cluster
488+
kubectl port-forward svc/backend-service 8080:8080 -n ambient-code
489+
490+
# Terminal 2: run frontend dev server with auth token
491+
cd components/frontend
492+
OC_TOKEN=$(kubectl get secret test-user-token -n ambient-code -o jsonpath='{.data.token}' | base64 -d) npm run dev
493+
494+
# Open http://localhost:3000
495+
```
496+
497+
**Why this works:**
498+
- The frontend's `BACKEND_URL` defaults to `http://localhost:8080/api`
499+
- NextJS API routes proxy all requests to the backend at that URL
500+
- `OC_TOKEN` is injected into `X-Forwarded-Access-Token` headers for authentication
501+
- Every file save triggers instant hot-reload — no Docker build, no kind load, no rollout restart
502+
503+
**When to use:**
504+
- Frontend-only changes (components, styles, pages, API routes)
505+
- Iterating on UI features rapidly
506+
- Debugging frontend issues
507+
508+
**When NOT to use:**
509+
- Backend, operator, or runner changes (those still need image rebuild + load)
510+
- Testing changes to container configuration or deployment manifests
511+
419512
## Best Practices
420513

421-
1. **Use kind for quick validation**: If you just need to verify changes work, kind is faster
422-
2. **Use minikube for development**: Better tooling for iterative development with `local-reload-*` commands
423-
3. **Always check logs**: After deploying, verify pods started successfully
424-
4. **Clean up when done**: `make kind-down` or `make local-clean` to free resources
425-
5. **Check what changed first**: Use `git status` and `git diff` to understand scope
426-
6. **Build only what changed**: Don't rebuild everything if only one component changed
427-
7. **Verify image pull policy**: Ensure deployments use `imagePullPolicy: Never` for local images
514+
1. **Use local dev server for frontend**: Fastest feedback loop, no image rebuilds needed
515+
2. **Use kind for backend/operator validation**: When you need to rebuild non-frontend components
516+
3. **Use minikube for development**: Better tooling for iterative development with `local-reload-*` commands
517+
4. **Always check logs**: After deploying, verify pods started successfully
518+
5. **Clean up when done**: `make kind-down` or `make local-clean` to free resources
519+
6. **Check what changed first**: Use `git status` and `git diff` to understand scope
520+
7. **Build only what changed**: Don't rebuild everything if only one component changed
521+
8. **Verify image pull policy**: Ensure deployments use `imagePullPolicy: Never` for local images
428522

429523
## Quick Reference
430524

@@ -435,12 +529,16 @@ Do you need to test local code changes?
435529
├─ No → Use kind (make kind-up)
436530
│ Fast, uses production images
437531
438-
└─ Yes → Do you need to iterate frequently?
439-
├─ NoUse kind with manual image loading
440-
Good for one-off tests
532+
└─ Yes → Is the change frontend-only?
533+
├─ YesRun locally with npm run dev
534+
Instant hot-reload, no image builds
441535
442-
└─ Yes → Use minikube (make local-up)
443-
Best for development with hot-reload
536+
└─ No → Do you need to iterate frequently?
537+
├─ No → Use kind with manual image loading
538+
│ Good for one-off tests
539+
540+
└─ Yes → Use minikube (make local-up)
541+
Best for development with hot-reload
444542
```
445543

446544
### Cheat Sheet
@@ -453,7 +551,7 @@ Do you need to test local code changes?
453551
| Check status | `kubectl get pods -n ambient-code` | `make local-status` |
454552
| View logs | `kubectl logs -f -l app=backend -n ambient-code` | `make local-logs-backend` |
455553
| Tear down | `make kind-down` | `make local-clean` |
456-
| Access URL | http://localhost:8080 | http://localhost:3000 |
554+
| Access URL | Detect from port mapping (Docker: `:80`, Podman: `:8080`) | http://localhost:3000 |
457555

458556
## When to Invoke This Skill
459557

@@ -482,7 +580,7 @@ Assistant (using dev-cluster skill):
482580
7. Verifies: `kubectl rollout status deployment/backend -n ambient-code`
483581
8. Provides access URL and log commands
484582

485-
Result: User can test their backend changes at http://localhost:8080
583+
Result: User can test their backend changes at the detected URL (http://localhost for Docker, http://localhost:8080 for Podman)
486584

487585
### Example 2: Incremental Development with Minikube
488586

0 commit comments

Comments
 (0)