Skip to content

Commit 764b09f

Browse files
committed
Added more context for running tests suites with Laravel projects
1 parent 40de955 commit 764b09f

5 files changed

Lines changed: 324 additions & 23 deletions

File tree

resources/boost/guidelines/core.blade.php

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
## Key facts
66

77
- Spin follows Docker Compose syntax exactly — `spin up` runs `docker compose up`, `spin run` runs `docker compose run`, etc.
8-
- Projects use a **Docker Compose overrides** pattern: a base `docker-compose.yml` merged with `docker-compose.dev.yml` (local) or `docker-compose.prod.yml` (production).
8+
- Projects use a **Docker Compose overrides** pattern: a base `docker-compose.yml` merged with `docker-compose.$SPIN_ENV.yml`. `SPIN_ENV` defaults to `dev` (→ `docker-compose.dev.yml`). Common values: `dev`, `ci`, `prod`.
99
- Laravel projects use `serversideup/php` Docker images (fpm-nginx, fpm-apache, frankenphp, cli).
1010
- The `.infrastructure/` folder stores configuration files (`conf/`) and gitignored volume data (`volume_data/`).
11-
- `SPIN_ENV` defaults to `dev`. Running `spin up` uses `docker-compose.yml` + `docker-compose.dev.yml`.
1211
- In Docker, services connect via container name as hostname (`DB_HOST=mysql`, `REDIS_HOST=redis`), not `localhost`.
1312

1413
## Essential commands
@@ -17,14 +16,54 @@
1716
|---------|---------|
1817
| `spin up` | Start development environment (foreground) |
1918
| `spin up --build` | Start and rebuild containers (recommended default if custom Dockerfile is used) |
20-
| `spin run <service> <cmd>` | Run a one-off command in a new container |
21-
| `spin exec <service> <cmd>` | Run a command in a running container |
19+
| `spin exec <service> <cmd>` | Run a command in a running container (reuses live container, near-instant) |
20+
| `spin run <service> <cmd>` | Run a one-off command in a new container (use when the stack is not running) |
2221
| `spin deploy <env>` | Deploy to a provisioned server |
2322
| `spin provision` | Provision and configure servers |
2423

24+
### `spin exec` vs `spin run`
25+
26+
- **`spin exec`** — use when the stack is running. Reuses the live container. This is the right default for `artisan`, `composer`, `npm`, tests, and ad-hoc commands during development.
27+
- **`spin run`** — use when the stack is not running, or when a fresh container with different env vars or isolated state is needed. Creates (and removes) a new container each invocation.
28+
29+
### The `-T` flag (disable pseudo-TTY)
30+
31+
Compose auto-detects TTY by default, so interactive use from a terminal usually works without `-T`. **In AI agent, CI, and other subprocess contexts**, that auto-detection can misfire — Compose sees a TTY on stdin while downstream output is being captured, which can cause hangs, ANSI-garbled output, or prompts with nowhere to respond.
32+
33+
Pass `-T` as a defensive default when running commands from an AI agent, CI pipeline, or any wrapper script:
34+
35+
```bash
36+
./vendor/bin/spin exec -T php php artisan test
37+
./vendor/bin/spin run -T php composer install
38+
```
39+
40+
Omit `-T` when interactivity is actually needed (`artisan tinker` without `--execute`, interactive `make:*` prompts, `spin exec php bash`).
41+
42+
### Running Laravel tests
43+
44+
Prefer the **already-running dev stack** — it's faster than spinning up a parallel CI stack:
45+
46+
```bash
47+
./vendor/bin/spin exec -T php php artisan test
48+
./vendor/bin/spin exec -T php php artisan test --filter=ExampleTest
49+
```
50+
51+
`php artisan test` works for both PHPUnit and Pest. If the project exposes a `composer test` script, prefer that via `spin exec -T php composer test`.
52+
53+
**Before assuming the dev stack is enough, inspect the test config** (`phpunit.xml`, `phpunit.xml.dist`, or `phpunit.dist.xml`):
54+
55+
- If `<php>` overrides `DB_CONNECTION` to `sqlite` with `DB_DATABASE=:memory:` (and `CACHE_STORE`/`QUEUE_CONNECTION`/`SESSION_DRIVER` set to `array`/`sync`), tests are self-contained — the dev stack is plenty.
56+
- If the test config uses the real database/cache services, the dev stack usually still works. Reach for `SPIN_ENV=ci` only when CI parity is needed (reproducing a CI-only failure, matching exact service versions, dry-running the pipeline). See the **spin-laravel-development** skill's `TESTING.md` for the full CI-parity workflow.
57+
2558
## When to activate the full skill
2659

27-
For tasks involving Docker Compose configuration, Dockerfile changes, `serversideup/php` image settings, adding Laravel services (databases, queues, Horizon, Reverb), server provisioning, deployment, or troubleshooting containerized environments — activate the **spin-laravel-development** skill.
60+
Activate the **spin-laravel-development** skill for tasks involving:
61+
- Docker Compose configuration or Dockerfile changes
62+
- `serversideup/php` image settings
63+
- Adding Laravel services (databases, queues, Horizon, Reverb)
64+
- Running tests with CI parity (`SPIN_ENV=ci`)
65+
- Running multiple Compose environments in parallel
66+
- Server provisioning, deployment, or troubleshooting containerized environments
2867

2968
## Laravel Boost MCP setup
3069

@@ -44,7 +83,20 @@
4483
spin run php php artisan boost:install
4584
```
4685

47-
**IMPORTANT:** `spin-mcp-wait.sh` is exclusively for MCP server startup. NEVER use it to run commands. Always use `spin run` or `spin exec` for running commands (e.g., `spin run php composer install`).
86+
**IMPORTANT:** `spin-mcp-wait.sh` is exclusively for MCP server startup. NEVER use it to run commands. Always invoke `spin exec` (running stack) or `spin run` (stopped stack) directly.
87+
88+
If this error appears, drop `spin-mcp-wait.sh` and invoke `spin` directly:
89+
90+
```
91+
Error: spin-mcp-wait.sh is only for starting the MCP server. Use 'spin' directly instead.
92+
```
93+
94+
Correct:
95+
96+
```bash
97+
./vendor/bin/spin exec -T php php artisan test
98+
./vendor/bin/spin run -T php php artisan migrate
99+
```
48100

49101
## Templates
50102

resources/boost/skills/spin-laravel-development/COMMANDS.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,21 @@ Examples:
7373
```bash
7474
spin run php composer install
7575
spin run php php artisan migrate
76-
spin run node yarn install
76+
spin run node npm install
77+
spin run -T php composer install # Defensive -T for AI/CI/subprocess contexts
7778
```
7879

7980
Spin-specific options:
8081
- `--skip-pull` — Do not automatically pull images
8182
- `--force-pull` — Pull images regardless of cache
8283

84+
Key Docker Compose options:
85+
- `-T` — Disable pseudo-TTY allocation. Compose auto-detects TTY by default, so terminal use works without it. Pass `-T` as a defensive default when invoking from an AI agent, CI pipeline, or subprocess — auto-detection can misfire there and cause hangs or garbled output.
86+
8387
The container is automatically removed after the command completes. Container dependencies are not started.
8488

89+
Use `spin run` when the stack is not running or when isolated state / different env vars are needed. If the stack is already running, prefer `spin exec` — it reuses the live container and is near-instant.
90+
8591
### `spin exec`
8692

8793
Run a command in a **currently running** container (requires `spin up` to be active).
@@ -90,12 +96,20 @@ Run a command in a **currently running** container (requires `spin up` to be act
9096
spin exec [OPTIONS] SERVICE COMMAND
9197
```
9298

93-
Example:
99+
Examples:
94100

95101
```bash
96-
spin exec php php artisan tinker
102+
spin exec php php artisan test
103+
spin exec php composer install
104+
spin exec php php artisan tinker # Interactive — no -T needed
105+
spin exec -T php php artisan test # Defensive -T for AI/CI/subprocess contexts
97106
```
98107

108+
Key Docker Compose options:
109+
- `-T` — Disable pseudo-TTY allocation. Compose auto-detects TTY by default, so terminal use works without it. Pass `-T` as a defensive default when invoking from an AI agent, CI pipeline, or subprocess — auto-detection can misfire there, causing hangs, ANSI-garbled output, or prompts with nowhere to respond.
110+
111+
`spin exec` is the default choice for `artisan`, `composer`, `npm`, and ad-hoc commands during active development.
112+
99113
### `spin logs`
100114

101115
View container logs.

resources/boost/skills/spin-laravel-development/SKILL.md

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: spin-laravel-development
3-
description: "Develops and deploys Laravel applications using Spin and serversideup/php Docker images. Covers Docker Compose configuration, development environment setup, container commands, Laravel service configuration (databases, queues, Horizon, Reverb), server provisioning, and deployment workflows. Use when working with Spin, Docker Compose files, serversideup/php images, spin commands, configuring Laravel services in Docker, or deploying Laravel apps to production servers."
3+
description: "Develops, tests, and deploys Laravel applications using Spin and serversideup/php Docker images. Covers Docker Compose configuration, development environment setup, container commands, running Laravel tests (PHPUnit and Pest), SPIN_ENV selection and CI parity, parallel Compose environments, Laravel service configuration (databases, queues, Horizon, Reverb), server provisioning, and deployment workflows. Use when working with Spin, Docker Compose files, serversideup/php images, spin commands, running artisan test, configuring Laravel services in Docker, or deploying Laravel apps to production servers."
44
---
55

66
# Spin Laravel Development
@@ -13,6 +13,7 @@ description: "Develops and deploys Laravel applications using Spin and serversid
1313
- [Project structure](#project-structure)
1414
- [Dockerfile pattern](#dockerfile-pattern)
1515
- [Development workflow](#development-workflow)
16+
- [Running tests](#running-tests)
1617
- [serversideup/php images](#serversideupphp-images)
1718
- [Laravel services](#laravel-services)
1819
- [Deployment](#deployment)
@@ -24,7 +25,8 @@ description: "Develops and deploys Laravel applications using Spin and serversid
2425

2526
- **NEVER** run commands that could destroy data without explicitly confirming with the user first. This includes `docker system prune`, `docker volume rm`, dropping databases, removing services, or any destructive operation.
2627
- If Spin fails to run, it is likely because Docker Desktop is not started. Check with `docker info`. If Docker is not running, tell the user to start Docker Desktop and offer to retry before continuing.
27-
- Always prefer `spin run` over `spin exec` for one-off commands — it is safer because it creates an isolated container.
28+
- Prefer `spin exec <service> <cmd>` when the stack is running — it reuses the live container and is near-instant. Use `spin run` when the stack is not running or isolated state is needed.
29+
- Pass `-T` as a defensive default when invoking commands from an AI agent, CI, or subprocess context. Compose auto-detects TTY in regular terminals, but that detection can misfire when wrapped, causing hangs or garbled output.
2830

2931
## Laravel Boost MCP
3032

@@ -38,12 +40,18 @@ BOOST_COMPOSER_EXECUTABLE_PATH="./vendor/bin/spin run php composer"
3840
BOOST_NPM_EXECUTABLE_PATH="./vendor/bin/spin run node npm"
3941
```
4042

41-
**NEVER use `spin-mcp-wait.sh` to run commands.** It is exclusively for MCP server startup. The script will refuse non-MCP invocations with an error. Always use `spin run` or `spin exec` for running commands:
43+
**NEVER use `spin-mcp-wait.sh` to run commands.** It is exclusively for MCP server startup. The script will refuse non-MCP invocations with this error:
44+
45+
```
46+
Error: spin-mcp-wait.sh is only for starting the MCP server. Use 'spin' directly instead.
47+
```
48+
49+
If that error appears, drop `spin-mcp-wait.sh` and invoke `spin` directly:
4250

4351
```bash
44-
spin run php composer install # Correct
45-
spin run php php artisan migrate # Correct
46-
spin-mcp-wait.sh spin run php ... # WRONG — never do this
52+
./vendor/bin/spin exec -T php php artisan test # Correct
53+
./vendor/bin/spin run -T php php artisan migrate # Correct
54+
./vendor/bin/spin-mcp-wait.sh ./vendor/bin/spin run php # WRONG — never do this
4755
```
4856

4957
## How Spin works
@@ -184,17 +192,27 @@ spin up -d # Detached mode (background)
184192

185193
### Running commands
186194

187-
Syntax: `spin run <service> <command>` — the first argument is the **service name** from `docker-compose.yml`.
195+
Syntax: `spin <exec|run> [-T] <service> <command>` — the service argument is the **service name** from `docker-compose.yml`.
188196

189197
```bash
190-
spin run php composer install
191-
spin run php php artisan migrate # First "php" = service, second "php" = binary
192-
spin run php php artisan make:model Post
193-
spin run node yarn install
194-
spin run node yarn dev
198+
spin exec php composer install
199+
spin exec php php artisan migrate # First "php" = service, second "php" = binary
200+
spin run php php artisan make:model Post
201+
spin exec node npm install
202+
spin exec node npm run dev
195203
```
196204

197-
**`run` vs `exec`**: Use `spin run` for one-off commands (creates a new container, runs, exits). Use `spin exec` to execute in an already-running container (requires `spin up` to be active). Prefer `spin run` for package installs, migrations, artisan commands.
205+
**`exec` vs `run`**:
206+
207+
- **`spin exec`** reuses the live container from an already-running stack. Near-instant. Default for `artisan`, `composer`, `npm`, and ad-hoc commands during development.
208+
- **`spin run`** creates a new container each invocation. Use when the stack is not running, or when isolated state / different env vars are needed.
209+
210+
**The `-T` flag**: Compose auto-detects TTY, so interactive terminal usage works without `-T`. Add `-T` as a defensive default when invoking from an AI agent, CI pipeline, or wrapper script — auto-detection can misfire in those contexts, causing hangs or ANSI-garbled output:
211+
212+
```bash
213+
./vendor/bin/spin exec -T php php artisan test # AI/CI-safe
214+
./vendor/bin/spin exec php artisan tinker # Interactive — omit -T
215+
```
198216

199217
### Volume mounting
200218

@@ -242,6 +260,25 @@ SPIN_APP_DOMAIN=laravel.dev.test
242260

243261
See [COMMANDS.md](COMMANDS.md) for the complete 26-command reference.
244262

263+
## Running tests
264+
265+
Prefer the **already-running dev stack** — it's faster than spinning up a parallel CI stack:
266+
267+
```bash
268+
./vendor/bin/spin exec -T php php artisan test
269+
./vendor/bin/spin exec -T php php artisan test --filter=ExampleTest
270+
./vendor/bin/spin exec -T php composer test # If the project exposes a composer test script
271+
```
272+
273+
`php artisan test` works for both PHPUnit and Pest.
274+
275+
**Before assuming the dev stack is enough, inspect the test config** (`phpunit.xml`, `phpunit.xml.dist`, or `phpunit.dist.xml`):
276+
277+
- If the `<php>` block overrides `DB_CONNECTION` to `sqlite` with `DB_DATABASE=:memory:` (and cache/queue/session set to `array`/`sync`), tests are self-contained — the dev stack is plenty.
278+
- If the test config uses the real database/cache services, the dev stack usually still works. Reach for `SPIN_ENV=ci` only when CI parity is explicitly needed: reproducing a CI-only failure, matching exact service versions, or dry-running the pipeline before pushing.
279+
280+
See [TESTING.md](TESTING.md) for the full CI-parity workflow, parallel Compose environments, and the override-network gotcha.
281+
245282
## serversideup/php images
246283

247284
Choose the right variant:
@@ -332,6 +369,9 @@ The `.spin.yml` file defines users, providers, servers, and environments. Suppor
332369
| Stale containers | Use `spin up --build` to rebuild |
333370
| DB password not working | Credentials are only created on first container init — remove volume to reset |
334371
| Permission errors in container | Check `SPIN_USER_ID`/`SPIN_GROUP_ID` match host user |
372+
| Command hangs in AI/CI wrapper | Compose TTY auto-detection misfired — add `-T` to `spin exec`/`spin run` |
373+
| `SPIN_ENV=ci` clobbered dev containers | `docker-compose.ci.yml` needs its own `name:` project (see [TESTING.md](TESTING.md)) |
374+
| "host not found" between services on `SPIN_ENV=ci` | Override network didn't include inherited services (see [TESTING.md](TESTING.md)) |
335375

336376
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for remote server debugging and Docker Swarm troubleshooting.
337377

@@ -343,4 +383,5 @@ See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for remote server debugging and Doc
343383
| [DOCKER-IMAGES.md](DOCKER-IMAGES.md) | Configuring serversideup/php images, environment variables, health checks |
344384
| [DEPLOYMENT.md](DEPLOYMENT.md) | Setting up deployment pipelines or running `spin deploy` |
345385
| [LARAVEL-SERVICES.md](LARAVEL-SERVICES.md) | Adding databases, queues, Horizon, Reverb, or other Docker services |
346-
| [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | Debugging issues on remote servers or Docker Swarm |
386+
| [TESTING.md](TESTING.md) | Running Laravel tests, `SPIN_ENV=ci` CI parity, parallel Compose stacks |
387+
| [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | Debugging issues on remote servers, Docker Swarm, or Compose network/stack collisions |

0 commit comments

Comments
 (0)