cc-workspace 4.2.1 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -7
- package/bin/cli.js +38 -10
- package/global-skills/agents/e2e-validator.md +387 -0
- package/global-skills/agents/implementer.md +108 -25
- package/global-skills/agents/team-lead.md +113 -50
- package/global-skills/dispatch-feature/SKILL.md +88 -50
- package/global-skills/dispatch-feature/references/anti-patterns.md +21 -16
- package/global-skills/dispatch-feature/references/spawn-templates.md +70 -83
- package/global-skills/e2e-validator/references/container-strategies.md +304 -0
- package/global-skills/e2e-validator/references/scenario-extraction.md +151 -0
- package/global-skills/e2e-validator/references/test-frameworks.md +207 -0
- package/package.json +1 -1
- package/global-skills/hooks/guard-session-checkout.sh +0 -33
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Implementer Spawn Templates
|
|
2
2
|
|
|
3
3
|
Reference file for dispatch-feature. Loaded on-demand, not at skill activation.
|
|
4
4
|
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
>
|
|
5
|
+
> Each implementer handles exactly ONE commit unit. The team-lead spawns
|
|
6
|
+
> implementers sequentially per service — one per commit unit in the plan.
|
|
7
|
+
> Implementers do NOT receive the constitution automatically. Every spawn
|
|
8
|
+
> template below includes a "Constitution" section that you MUST fill with
|
|
9
|
+
> all rules from your workspace's `constitution.md`.
|
|
8
10
|
|
|
9
|
-
## Backend/API
|
|
11
|
+
## Backend/API implementer spawn template
|
|
10
12
|
|
|
11
13
|
```
|
|
12
|
-
You are
|
|
14
|
+
You are implementer for [service], handling Commit [N] of [total]: [commit title].
|
|
15
|
+
Commits 1 to [N-1] are already on the session branch. Do NOT redo earlier work.
|
|
16
|
+
|
|
17
|
+
Read the CLAUDE.md in your repo first.
|
|
13
18
|
|
|
14
19
|
## Git workflow (CRITICAL — read first)
|
|
15
20
|
You are working in a temporary worktree. If you don't commit, YOUR WORK WILL BE LOST
|
|
@@ -26,53 +31,46 @@ You are already in an isolated worktree — all git commands run HERE, not in th
|
|
|
26
31
|
3. If checkout fails with "did not match any file(s)":
|
|
27
32
|
git fetch origin session/{session-name}
|
|
28
33
|
git checkout session/{session-name}
|
|
29
|
-
4.
|
|
30
|
-
5. Before reporting back, verify ALL changes are committed:
|
|
31
|
-
git status (must show: nothing to commit, working tree clean)
|
|
32
|
-
6. If git status shows uncommitted changes when you're done: COMMIT THEM NOW
|
|
34
|
+
4. Check existing commits: git log --oneline -5
|
|
33
35
|
|
|
34
36
|
Branch `session/{session-name}` ALREADY EXISTS. Do NOT create other branches.
|
|
35
|
-
Do NOT create branches named worktree-agent-* — use the session branch.
|
|
36
37
|
|
|
37
38
|
## Constitution (non-negotiable)
|
|
38
39
|
[paste all rules from your workspace's constitution.md]
|
|
39
40
|
|
|
40
41
|
## API contract
|
|
41
|
-
[paste the exact request/response shapes
|
|
42
|
+
[paste the exact request/response shapes relevant to THIS commit]
|
|
42
43
|
[note: frontend will build TypeScript interfaces from these shapes]
|
|
43
44
|
|
|
44
|
-
## Your
|
|
45
|
-
[paste
|
|
45
|
+
## Your single commit unit
|
|
46
|
+
[paste ONLY the tasks for this specific commit unit — NOT the whole plan]
|
|
47
|
+
|
|
48
|
+
## What previous commits already did
|
|
49
|
+
[brief summary: "Commit 1 added models X, Y, Z. Commit 2 added services A, B."]
|
|
46
50
|
|
|
47
51
|
## Instructions
|
|
48
52
|
1. Read the repo CLAUDE.md first — follow its conventions
|
|
49
|
-
2. Implement the tasks above
|
|
53
|
+
2. Implement ONLY the tasks above — do not touch code from earlier commits
|
|
50
54
|
3. Use the LSP tool for code navigation (go-to-definition, find-references)
|
|
51
55
|
4. Run the existing test suite — report pass/fail
|
|
52
56
|
5. List any dead code created or exposed by your changes
|
|
53
|
-
6.
|
|
57
|
+
6. If your changes exceed ~300 lines, split into multiple commits
|
|
58
|
+
(data → logic → API layer), each compilable
|
|
54
59
|
7. If you hit an architectural decision NOT covered by the plan: STOP and
|
|
55
60
|
report the dilemma instead of guessing
|
|
56
|
-
8.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
## Commit strategy (mandatory)
|
|
61
|
-
- **One commit per logical unit** — each task in "Your tasks" = one commit minimum
|
|
62
|
-
- **Max ~300 lines per commit** — if a task produces more, split it:
|
|
63
|
-
1. Data layer first (models, migrations, DTOs, repositories)
|
|
64
|
-
2. Business logic (use cases, services, validation)
|
|
65
|
-
3. API layer (controllers, routes, requests)
|
|
66
|
-
4. Tests for the above
|
|
67
|
-
- **Commit message format**: `feat(domain): description` or `fix(domain): description`
|
|
68
|
-
- **Each commit must compile and pass tests** — no broken intermediate states
|
|
69
|
-
- **Commit as you go** — do NOT accumulate all changes for a single final commit
|
|
61
|
+
8. COMMIT before reporting. Run: git status (must be clean), git log --oneline -3
|
|
62
|
+
(your commit must appear)
|
|
63
|
+
9. Report back: commit hash + message, files created/modified, tests pass/fail,
|
|
64
|
+
dead code found, blockers
|
|
70
65
|
```
|
|
71
66
|
|
|
72
|
-
## Frontend
|
|
67
|
+
## Frontend implementer spawn template
|
|
73
68
|
|
|
74
69
|
```
|
|
75
|
-
You are
|
|
70
|
+
You are implementer for [service], handling Commit [N] of [total]: [commit title].
|
|
71
|
+
Commits 1 to [N-1] are already on the session branch. Do NOT redo earlier work.
|
|
72
|
+
|
|
73
|
+
Read the CLAUDE.md in your repo first.
|
|
76
74
|
|
|
77
75
|
## Git workflow (CRITICAL — read first)
|
|
78
76
|
You are working in a temporary worktree. If you don't commit, YOUR WORK WILL BE LOST
|
|
@@ -89,56 +87,48 @@ You are already in an isolated worktree — all git commands run HERE, not in th
|
|
|
89
87
|
3. If checkout fails with "did not match any file(s)":
|
|
90
88
|
git fetch origin session/{session-name}
|
|
91
89
|
git checkout session/{session-name}
|
|
92
|
-
4.
|
|
93
|
-
5. Before reporting back, verify ALL changes are committed:
|
|
94
|
-
git status (must show: nothing to commit, working tree clean)
|
|
95
|
-
6. If git status shows uncommitted changes when you're done: COMMIT THEM NOW
|
|
90
|
+
4. Check existing commits: git log --oneline -5
|
|
96
91
|
|
|
97
92
|
Branch `session/{session-name}` ALREADY EXISTS. Do NOT create other branches.
|
|
98
|
-
Do NOT create branches named worktree-agent-* — use the session branch.
|
|
99
93
|
|
|
100
94
|
## Constitution (non-negotiable)
|
|
101
95
|
[paste all rules from your workspace's constitution.md]
|
|
102
96
|
|
|
103
97
|
## UX Standards (non-negotiable)
|
|
104
|
-
[paste full content of frontend-ux-standards.md]
|
|
98
|
+
[paste full content of frontend-ux-standards.md — only if this commit involves UI components]
|
|
105
99
|
|
|
106
100
|
## API contract (TypeScript interfaces)
|
|
107
|
-
[paste exact response shapes
|
|
101
|
+
[paste exact response shapes relevant to THIS commit]
|
|
108
102
|
|
|
109
|
-
## Your
|
|
110
|
-
[paste
|
|
103
|
+
## Your single commit unit
|
|
104
|
+
[paste ONLY the tasks for this specific commit unit — NOT the whole plan]
|
|
105
|
+
|
|
106
|
+
## What previous commits already did
|
|
107
|
+
[brief summary: "Commit 1 added types/interfaces. Commit 2 added store/composables."]
|
|
111
108
|
|
|
112
109
|
## Instructions
|
|
113
110
|
1. Read the repo CLAUDE.md first — follow its conventions
|
|
114
|
-
2. Implement the tasks
|
|
111
|
+
2. Implement ONLY the tasks above — do not touch code from earlier commits
|
|
115
112
|
3. Use the LSP tool for code navigation
|
|
116
|
-
4.
|
|
113
|
+
4. If this commit adds components: MUST handle 4 states (skeleton, empty+CTA, error+retry, success)
|
|
117
114
|
5. Run the existing test suite — report pass/fail
|
|
118
115
|
6. List any dead code (unused components, composables, store actions, CSS)
|
|
119
|
-
7.
|
|
116
|
+
7. If your changes exceed ~300 lines, split into multiple commits
|
|
117
|
+
(types → store → components → pages), each compilable
|
|
120
118
|
8. If you hit an architectural decision NOT covered by the plan: STOP and escalate
|
|
121
|
-
9.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
## Commit strategy (mandatory)
|
|
126
|
-
- **One commit per logical unit** — each task = one commit minimum
|
|
127
|
-
- **Max ~300 lines per commit** — if a task produces more, split it:
|
|
128
|
-
1. Types/interfaces and API service layer
|
|
129
|
-
2. Store/composables (state management)
|
|
130
|
-
3. Components (one commit per complex component)
|
|
131
|
-
4. Page integration + routing
|
|
132
|
-
5. Tests for the above
|
|
133
|
-
- **Commit message format**: `feat(domain): description` or `fix(domain): description`
|
|
134
|
-
- **Each commit must compile and pass tests** — no broken intermediate states
|
|
135
|
-
- **Commit as you go** — do NOT accumulate all changes for a single final commit
|
|
119
|
+
9. COMMIT before reporting. Run: git status (must be clean), git log --oneline -3
|
|
120
|
+
(your commit must appear)
|
|
121
|
+
10. Report back: commit hash + message, files created/modified, tests pass/fail,
|
|
122
|
+
dead code found, UX compliance, blockers
|
|
136
123
|
```
|
|
137
124
|
|
|
138
|
-
## Infra/Config
|
|
125
|
+
## Infra/Config implementer spawn template
|
|
139
126
|
|
|
140
127
|
```
|
|
141
|
-
You are
|
|
128
|
+
You are implementer for [service], handling Commit [N] of [total]: [commit title].
|
|
129
|
+
Commits 1 to [N-1] are already on the session branch. Do NOT redo earlier work.
|
|
130
|
+
|
|
131
|
+
Read the CLAUDE.md in your repo first.
|
|
142
132
|
|
|
143
133
|
## Git workflow (CRITICAL — read first)
|
|
144
134
|
You are working in a temporary worktree. If you don't commit, YOUR WORK WILL BE LOST
|
|
@@ -155,31 +145,29 @@ You are already in an isolated worktree — all git commands run HERE, not in th
|
|
|
155
145
|
3. If checkout fails with "did not match any file(s)":
|
|
156
146
|
git fetch origin session/{session-name}
|
|
157
147
|
git checkout session/{session-name}
|
|
158
|
-
4.
|
|
159
|
-
5. Before reporting back, verify ALL changes are committed:
|
|
160
|
-
git status (must show: nothing to commit, working tree clean)
|
|
161
|
-
6. If git status shows uncommitted changes when you're done: COMMIT THEM NOW
|
|
148
|
+
4. Check existing commits: git log --oneline -5
|
|
162
149
|
|
|
163
150
|
Branch `session/{session-name}` ALREADY EXISTS. Do NOT create other branches.
|
|
164
|
-
Do NOT create branches named worktree-agent-* — use the session branch.
|
|
165
151
|
|
|
166
152
|
## Constitution (non-negotiable)
|
|
167
153
|
[paste all rules from your workspace's constitution.md]
|
|
168
154
|
|
|
169
|
-
## Your
|
|
170
|
-
[paste tasks — typically
|
|
155
|
+
## Your single commit unit
|
|
156
|
+
[paste ONLY the tasks for this commit — typically gateway routes, configs, env vars]
|
|
157
|
+
|
|
158
|
+
## What previous commits already did
|
|
159
|
+
[brief summary if applicable]
|
|
171
160
|
|
|
172
161
|
## Instructions
|
|
173
162
|
1. Read the repo CLAUDE.md first
|
|
174
|
-
2. Implement the configuration changes
|
|
163
|
+
2. Implement ONLY the configuration changes for this commit
|
|
175
164
|
3. Verify consistency with other services (env vars, routes, schemas)
|
|
176
|
-
4. No code changes — only configuration
|
|
177
|
-
5.
|
|
178
|
-
6.
|
|
179
|
-
7.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
commits made (hash + message), blockers
|
|
165
|
+
4. No application code changes — only configuration
|
|
166
|
+
5. Commit message format: `chore(service): description`
|
|
167
|
+
6. If you hit an architectural decision NOT covered by the plan: STOP and escalate
|
|
168
|
+
7. COMMIT before reporting. Run: git status (must be clean), git log --oneline -3
|
|
169
|
+
(your commit must appear)
|
|
170
|
+
8. Report back: commit hash + message, files modified, consistency check results, blockers
|
|
183
171
|
```
|
|
184
172
|
|
|
185
173
|
## Explore/Haiku subagent template (read-only)
|
|
@@ -198,11 +186,10 @@ You are an explorer scanning [target]. Read-only — do NOT modify any files.
|
|
|
198
186
|
|
|
199
187
|
## Failure handling
|
|
200
188
|
|
|
201
|
-
When
|
|
202
|
-
- **Test regression or missing file** (recoverable): fix
|
|
189
|
+
When an implementer reports back:
|
|
190
|
+
- **Test regression or missing file** (recoverable): fix commit unit description, re-dispatch ONCE
|
|
203
191
|
- **Architectural decision not in plan** (blocking): STOP the wave, escalate to user
|
|
204
|
-
- **No report
|
|
205
|
-
|
|
206
|
-
- **
|
|
207
|
-
|
|
208
|
-
re-dispatch with explicit instruction to commit.
|
|
192
|
+
- **No commit in report**: the implementer forgot to commit. Verify on session branch
|
|
193
|
+
with a Task subagent. If no commit exists, re-dispatch with emphasis on committing.
|
|
194
|
+
- **Max re-dispatches per commit unit**: 2. After that, escalate to user.
|
|
195
|
+
- **Giant commit (>400 lines)**: note in session log, consider splitting in future plans
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Container Strategies — E2E Validator Reference
|
|
2
|
+
|
|
3
|
+
## Overlay strategy (preferred — repos have docker-compose)
|
|
4
|
+
|
|
5
|
+
When repos already have `docker-compose.yml`, generate an **overlay** file that:
|
|
6
|
+
- Creates a shared e2e network
|
|
7
|
+
- Overrides env vars for test isolation
|
|
8
|
+
- Adds health checks if missing
|
|
9
|
+
- Maps worktree paths as build contexts
|
|
10
|
+
|
|
11
|
+
### Template: docker-compose.e2e.yml (overlay)
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
# E2E overlay — use with: docker compose -f ../repo/docker-compose.yml -f ./e2e/docker-compose.e2e.yml up
|
|
15
|
+
# Generated by e2e-validator agent
|
|
16
|
+
|
|
17
|
+
networks:
|
|
18
|
+
e2e:
|
|
19
|
+
driver: bridge
|
|
20
|
+
|
|
21
|
+
services:
|
|
22
|
+
# Override each service to join the e2e network and use test env
|
|
23
|
+
api:
|
|
24
|
+
networks:
|
|
25
|
+
- e2e
|
|
26
|
+
environment:
|
|
27
|
+
- APP_ENV=testing
|
|
28
|
+
- DB_DATABASE=app_test
|
|
29
|
+
- LOG_LEVEL=debug
|
|
30
|
+
healthcheck:
|
|
31
|
+
test: ["CMD", "curl", "-sf", "http://localhost:8000/health"]
|
|
32
|
+
interval: 5s
|
|
33
|
+
timeout: 3s
|
|
34
|
+
retries: 10
|
|
35
|
+
start_period: 30s
|
|
36
|
+
|
|
37
|
+
frontend:
|
|
38
|
+
networks:
|
|
39
|
+
- e2e
|
|
40
|
+
environment:
|
|
41
|
+
- VITE_API_URL=http://api:8000
|
|
42
|
+
- NODE_ENV=development
|
|
43
|
+
healthcheck:
|
|
44
|
+
test: ["CMD", "curl", "-sf", "http://localhost:9000"]
|
|
45
|
+
interval: 5s
|
|
46
|
+
timeout: 3s
|
|
47
|
+
retries: 10
|
|
48
|
+
|
|
49
|
+
db:
|
|
50
|
+
networks:
|
|
51
|
+
- e2e
|
|
52
|
+
environment:
|
|
53
|
+
- POSTGRES_DB=app_test
|
|
54
|
+
- POSTGRES_USER=test
|
|
55
|
+
- POSTGRES_PASSWORD=test
|
|
56
|
+
healthcheck:
|
|
57
|
+
test: ["CMD-SHELL", "pg_isready -U test"]
|
|
58
|
+
interval: 3s
|
|
59
|
+
timeout: 2s
|
|
60
|
+
retries: 10
|
|
61
|
+
tmpfs:
|
|
62
|
+
- /var/lib/postgresql/data # RAM disk for speed
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Worktree build context override
|
|
66
|
+
|
|
67
|
+
When testing session branches, override the build context to point to worktrees:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
services:
|
|
71
|
+
api:
|
|
72
|
+
build:
|
|
73
|
+
context: /tmp/e2e-api
|
|
74
|
+
dockerfile: Dockerfile
|
|
75
|
+
frontend:
|
|
76
|
+
build:
|
|
77
|
+
context: /tmp/e2e-frontend
|
|
78
|
+
dockerfile: Dockerfile
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Standalone strategy (repos have NO docker-compose)
|
|
82
|
+
|
|
83
|
+
Generate a complete `docker-compose.e2e.yml` from scratch.
|
|
84
|
+
|
|
85
|
+
### Per-stack templates
|
|
86
|
+
|
|
87
|
+
#### PHP/Laravel
|
|
88
|
+
```yaml
|
|
89
|
+
services:
|
|
90
|
+
api:
|
|
91
|
+
build:
|
|
92
|
+
context: /tmp/e2e-api
|
|
93
|
+
dockerfile: Dockerfile
|
|
94
|
+
ports:
|
|
95
|
+
- "8000:8000"
|
|
96
|
+
environment:
|
|
97
|
+
- APP_ENV=testing
|
|
98
|
+
- APP_KEY=${APP_KEY}
|
|
99
|
+
- DB_CONNECTION=pgsql
|
|
100
|
+
- DB_HOST=db
|
|
101
|
+
- DB_PORT=5432
|
|
102
|
+
- DB_DATABASE=app_test
|
|
103
|
+
- DB_USERNAME=test
|
|
104
|
+
- DB_PASSWORD=test
|
|
105
|
+
depends_on:
|
|
106
|
+
db:
|
|
107
|
+
condition: service_healthy
|
|
108
|
+
healthcheck:
|
|
109
|
+
test: ["CMD", "curl", "-sf", "http://localhost:8000/health"]
|
|
110
|
+
interval: 5s
|
|
111
|
+
retries: 10
|
|
112
|
+
start_period: 30s
|
|
113
|
+
command: >
|
|
114
|
+
sh -c "php artisan migrate --force && php artisan serve --host=0.0.0.0 --port=8000"
|
|
115
|
+
networks:
|
|
116
|
+
- e2e
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Node.js (Express/Fastify)
|
|
120
|
+
```yaml
|
|
121
|
+
services:
|
|
122
|
+
api:
|
|
123
|
+
build:
|
|
124
|
+
context: /tmp/e2e-api
|
|
125
|
+
ports:
|
|
126
|
+
- "3000:3000"
|
|
127
|
+
environment:
|
|
128
|
+
- NODE_ENV=test
|
|
129
|
+
- DATABASE_URL=postgresql://test:test@db:5432/app_test
|
|
130
|
+
depends_on:
|
|
131
|
+
db:
|
|
132
|
+
condition: service_healthy
|
|
133
|
+
healthcheck:
|
|
134
|
+
test: ["CMD", "curl", "-sf", "http://localhost:3000/health"]
|
|
135
|
+
interval: 5s
|
|
136
|
+
retries: 10
|
|
137
|
+
networks:
|
|
138
|
+
- e2e
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Vue/Quasar (frontend)
|
|
142
|
+
```yaml
|
|
143
|
+
services:
|
|
144
|
+
frontend:
|
|
145
|
+
build:
|
|
146
|
+
context: /tmp/e2e-frontend
|
|
147
|
+
ports:
|
|
148
|
+
- "9000:9000"
|
|
149
|
+
environment:
|
|
150
|
+
- VITE_API_URL=http://localhost:8000
|
|
151
|
+
healthcheck:
|
|
152
|
+
test: ["CMD", "curl", "-sf", "http://localhost:9000"]
|
|
153
|
+
interval: 5s
|
|
154
|
+
retries: 10
|
|
155
|
+
command: npx quasar dev --port 9000 --hostname 0.0.0.0
|
|
156
|
+
networks:
|
|
157
|
+
- e2e
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### React/Next
|
|
161
|
+
```yaml
|
|
162
|
+
services:
|
|
163
|
+
frontend:
|
|
164
|
+
build:
|
|
165
|
+
context: /tmp/e2e-frontend
|
|
166
|
+
ports:
|
|
167
|
+
- "3000:3000"
|
|
168
|
+
environment:
|
|
169
|
+
- NEXT_PUBLIC_API_URL=http://localhost:8000
|
|
170
|
+
healthcheck:
|
|
171
|
+
test: ["CMD", "curl", "-sf", "http://localhost:3000"]
|
|
172
|
+
interval: 5s
|
|
173
|
+
retries: 10
|
|
174
|
+
networks:
|
|
175
|
+
- e2e
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### Python/FastAPI
|
|
179
|
+
```yaml
|
|
180
|
+
services:
|
|
181
|
+
api:
|
|
182
|
+
build:
|
|
183
|
+
context: /tmp/e2e-api
|
|
184
|
+
ports:
|
|
185
|
+
- "8000:8000"
|
|
186
|
+
environment:
|
|
187
|
+
- DATABASE_URL=postgresql://test:test@db:5432/app_test
|
|
188
|
+
- ENVIRONMENT=testing
|
|
189
|
+
depends_on:
|
|
190
|
+
db:
|
|
191
|
+
condition: service_healthy
|
|
192
|
+
healthcheck:
|
|
193
|
+
test: ["CMD", "curl", "-sf", "http://localhost:8000/health"]
|
|
194
|
+
interval: 5s
|
|
195
|
+
retries: 10
|
|
196
|
+
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
|
|
197
|
+
networks:
|
|
198
|
+
- e2e
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Go
|
|
202
|
+
```yaml
|
|
203
|
+
services:
|
|
204
|
+
api:
|
|
205
|
+
build:
|
|
206
|
+
context: /tmp/e2e-api
|
|
207
|
+
ports:
|
|
208
|
+
- "8080:8080"
|
|
209
|
+
environment:
|
|
210
|
+
- DATABASE_URL=postgresql://test:test@db:5432/app_test
|
|
211
|
+
- ENV=test
|
|
212
|
+
depends_on:
|
|
213
|
+
db:
|
|
214
|
+
condition: service_healthy
|
|
215
|
+
healthcheck:
|
|
216
|
+
test: ["CMD", "curl", "-sf", "http://localhost:8080/health"]
|
|
217
|
+
interval: 5s
|
|
218
|
+
retries: 10
|
|
219
|
+
networks:
|
|
220
|
+
- e2e
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Database templates
|
|
224
|
+
|
|
225
|
+
#### PostgreSQL
|
|
226
|
+
```yaml
|
|
227
|
+
db:
|
|
228
|
+
image: postgres:16-alpine
|
|
229
|
+
environment:
|
|
230
|
+
- POSTGRES_DB=app_test
|
|
231
|
+
- POSTGRES_USER=test
|
|
232
|
+
- POSTGRES_PASSWORD=test
|
|
233
|
+
healthcheck:
|
|
234
|
+
test: ["CMD-SHELL", "pg_isready -U test"]
|
|
235
|
+
interval: 3s
|
|
236
|
+
retries: 10
|
|
237
|
+
tmpfs:
|
|
238
|
+
- /var/lib/postgresql/data
|
|
239
|
+
networks:
|
|
240
|
+
- e2e
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### MySQL
|
|
244
|
+
```yaml
|
|
245
|
+
db:
|
|
246
|
+
image: mysql:8.0
|
|
247
|
+
environment:
|
|
248
|
+
- MYSQL_DATABASE=app_test
|
|
249
|
+
- MYSQL_USER=test
|
|
250
|
+
- MYSQL_PASSWORD=test
|
|
251
|
+
- MYSQL_ROOT_PASSWORD=root
|
|
252
|
+
healthcheck:
|
|
253
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
254
|
+
interval: 3s
|
|
255
|
+
retries: 10
|
|
256
|
+
tmpfs:
|
|
257
|
+
- /var/lib/mysql
|
|
258
|
+
networks:
|
|
259
|
+
- e2e
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Redis
|
|
263
|
+
```yaml
|
|
264
|
+
redis:
|
|
265
|
+
image: redis:7-alpine
|
|
266
|
+
healthcheck:
|
|
267
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
268
|
+
interval: 3s
|
|
269
|
+
retries: 5
|
|
270
|
+
networks:
|
|
271
|
+
- e2e
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### MongoDB
|
|
275
|
+
```yaml
|
|
276
|
+
mongo:
|
|
277
|
+
image: mongo:7
|
|
278
|
+
environment:
|
|
279
|
+
- MONGO_INITDB_DATABASE=app_test
|
|
280
|
+
healthcheck:
|
|
281
|
+
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
|
|
282
|
+
interval: 3s
|
|
283
|
+
retries: 10
|
|
284
|
+
tmpfs:
|
|
285
|
+
- /data/db
|
|
286
|
+
networks:
|
|
287
|
+
- e2e
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Startup sequence
|
|
291
|
+
|
|
292
|
+
Always start in dependency order:
|
|
293
|
+
1. Databases (db, redis, mongo) — wait for healthy
|
|
294
|
+
2. Backend services (api) — wait for healthy
|
|
295
|
+
3. Frontend services — wait for healthy
|
|
296
|
+
4. Run tests
|
|
297
|
+
|
|
298
|
+
## Teardown
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
docker compose -f ./e2e/docker-compose.e2e.yml down -v --remove-orphans
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Always use `-v` to remove test volumes and `--remove-orphans` for cleanup.
|