@bostonuniversity/buwp-local 0.5.2 → 0.6.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/ROADMAP.md +2 -1
- package/docs/ARCHITECTURE.md +691 -0
- package/docs/CHANGELOG.md +149 -0
- package/docs/COMMANDS.md +462 -0
- package/docs/CREDENTIALS.md +484 -0
- package/docs/GETTING_STARTED.md +234 -0
- package/docs/MULTI_PROJECT.md +513 -0
- package/docs/ROADMAP.md +247 -0
- package/lib/commands/init.js +2 -1
- package/lib/commands/keychain.js +1 -1
- package/lib/commands/start.js +193 -8
- package/package.json +1 -1
- package/readme.md +13 -4
- /package/{IMPLEMENTATION_NOTES_V0.5.0_PHASE3.md → docs/archive/IMPLEMENTATION_NOTES_V0.5.0_PHASE3.md} +0 -0
- /package/{IMPLEMENTATION_SUMMARY.md → docs/archive/IMPLEMENTATION_SUMMARY.md} +0 -0
- /package/{KEYCHAIN_IMPLEMENTATION.md → docs/archive/KEYCHAIN_IMPLEMENTATION.md} +0 -0
- /package/{macos-keychain-notes.md → docs/archive/macos-keychain-notes.md} +0 -0
package/ROADMAP.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# buwp-local Development Roadmap
|
|
2
2
|
|
|
3
|
+
This is a historical document, see the current roadmap in the `docs/ROADMAP.md` file.
|
|
4
|
+
|
|
3
5
|
## ✅ Phase 1: Core Infrastructure (Complete)
|
|
4
6
|
|
|
5
7
|
**Status:** Shipped ✅
|
|
@@ -359,4 +361,3 @@ We've built a **solid foundation** for BU WordPress local development. The tool
|
|
|
359
361
|
3. Expand adoption gradually
|
|
360
362
|
4. Iterate and improve based on real usage
|
|
361
363
|
|
|
362
|
-
The path forward is clear, and the foundation is strong! 🚀
|
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Technical overview of how buwp-local works under the hood.
|
|
4
|
+
|
|
5
|
+
## System Overview
|
|
6
|
+
|
|
7
|
+
buwp-local is a CLI tool that generates and manages Docker Compose configurations for BU WordPress development environments.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
11
|
+
│ buwp-local CLI │
|
|
12
|
+
│ (Node.js/Commander) │
|
|
13
|
+
└─────────────────────────────────────────────────────────────┘
|
|
14
|
+
│
|
|
15
|
+
├─ Read Configuration
|
|
16
|
+
│ (.buwp-local.json)
|
|
17
|
+
│
|
|
18
|
+
├─ Load Credentials
|
|
19
|
+
│ (Keychain or .env.local)
|
|
20
|
+
│
|
|
21
|
+
├─ Generate Docker Compose
|
|
22
|
+
│ (docker-compose.yml)
|
|
23
|
+
│
|
|
24
|
+
└─ Execute Docker Compose
|
|
25
|
+
(via child process)
|
|
26
|
+
|
|
27
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
28
|
+
│ Docker Compose │
|
|
29
|
+
│ │
|
|
30
|
+
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐ │
|
|
31
|
+
│ │WordPress │ │ MySQL │ │ Redis │ │S3 Proxy │ │
|
|
32
|
+
│ │ Container│ │Container │ │Container│ │Container│ │
|
|
33
|
+
│ └──────────┘ └──────────┘ └─────────┘ └─────────┘ │
|
|
34
|
+
│ │
|
|
35
|
+
│ ┌──────────────────┐ ┌──────────────────┐ │
|
|
36
|
+
│ │ db_data volume │ │ wp_build volume │ │
|
|
37
|
+
│ └──────────────────┘ └──────────────────┘ │
|
|
38
|
+
└─────────────────────────────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Core Components
|
|
42
|
+
|
|
43
|
+
### 1. CLI Framework
|
|
44
|
+
|
|
45
|
+
**Technology:** Commander.js
|
|
46
|
+
|
|
47
|
+
**Entry Point:** `bin/buwp-local.js`
|
|
48
|
+
|
|
49
|
+
**Structure:**
|
|
50
|
+
```
|
|
51
|
+
bin/
|
|
52
|
+
buwp-local.js # CLI entry point, command routing
|
|
53
|
+
|
|
54
|
+
lib/
|
|
55
|
+
commands/
|
|
56
|
+
init.js # Interactive setup wizard
|
|
57
|
+
start.js # Start Docker Compose environment
|
|
58
|
+
stop.js # Stop containers
|
|
59
|
+
destroy.js # Remove containers and volumes
|
|
60
|
+
logs.js # View container logs
|
|
61
|
+
keychain.js # Keychain credential management
|
|
62
|
+
wp.js # WP-CLI proxy command
|
|
63
|
+
|
|
64
|
+
config.js # Configuration loading/validation
|
|
65
|
+
keychain.js # macOS Keychain integration
|
|
66
|
+
docker-compose.js # Docker Compose generation
|
|
67
|
+
utils.js # Utility functions
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2. Configuration Management
|
|
71
|
+
|
|
72
|
+
**Config File:** `.buwp-local.json`
|
|
73
|
+
|
|
74
|
+
**Schema:**
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"projectName": "string", // Unique project identifier
|
|
78
|
+
"hostname": "string", // Local hostname (e.g., project.local)
|
|
79
|
+
"multisite": "boolean", // Enable WordPress multisite
|
|
80
|
+
"image": "string", // Docker image to use
|
|
81
|
+
"services": {
|
|
82
|
+
"redis": "boolean", // Enable Redis cache
|
|
83
|
+
"s3proxy": "boolean", // Enable S3 proxy service
|
|
84
|
+
"shibboleth": "boolean" // Enable Shibboleth SSO
|
|
85
|
+
},
|
|
86
|
+
"ports": {
|
|
87
|
+
"http": "number", // HTTP port (default: 80)
|
|
88
|
+
"https": "number", // HTTPS port (default: 443)
|
|
89
|
+
"db": "number", // MySQL port (default: 3306)
|
|
90
|
+
"redis": "number" // Redis port (default: 6379)
|
|
91
|
+
},
|
|
92
|
+
"mappings": [
|
|
93
|
+
{
|
|
94
|
+
"local": "string", // Local path (relative or absolute)
|
|
95
|
+
"container": "string" // Container path (absolute)
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"env": {
|
|
99
|
+
"KEY": "value" // Custom environment variables
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Loading Process:**
|
|
105
|
+
|
|
106
|
+
1. Read `.buwp-local.json` from project directory
|
|
107
|
+
2. Apply defaults for missing values
|
|
108
|
+
3. Validate schema and paths
|
|
109
|
+
4. Sanitize project name for Docker compatibility
|
|
110
|
+
5. Merge with command-line options
|
|
111
|
+
|
|
112
|
+
**Module:** `lib/config.js`
|
|
113
|
+
|
|
114
|
+
### 3. Credential Management
|
|
115
|
+
|
|
116
|
+
#### macOS Keychain Integration
|
|
117
|
+
|
|
118
|
+
**Service:** `buwp-local`
|
|
119
|
+
**Account:** `<CREDENTIAL_NAME>`
|
|
120
|
+
**Access:** Via `security` command-line tool
|
|
121
|
+
|
|
122
|
+
**Implementation:**
|
|
123
|
+
The current implementation uses the macOS `security` CLI to store, retrieve, and delete credentials securely in the Keychain. It is essentially a wrapper around these commands:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Set credential
|
|
127
|
+
security add-generic-password \
|
|
128
|
+
-s "buwp-local" \
|
|
129
|
+
-a "WORDPRESS_DB_PASSWORD" \
|
|
130
|
+
-w "password123" \
|
|
131
|
+
-U
|
|
132
|
+
|
|
133
|
+
# Get credential
|
|
134
|
+
security find-generic-password \
|
|
135
|
+
-s "buwp-local" \
|
|
136
|
+
-a "WORDPRESS_DB_PASSWORD" \
|
|
137
|
+
-w
|
|
138
|
+
|
|
139
|
+
# Delete credential
|
|
140
|
+
security delete-generic-password \
|
|
141
|
+
-s "buwp-local" \
|
|
142
|
+
-a "WORDPRESS_DB_PASSWORD"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Features:**
|
|
146
|
+
- Stores 15 credential types
|
|
147
|
+
- Automatic hex decoding for legacy multiline credentials
|
|
148
|
+
- Secure storage with macOS encryption
|
|
149
|
+
- Global access across all projects
|
|
150
|
+
|
|
151
|
+
#### Credential Loading Flow
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
Start Command
|
|
155
|
+
│
|
|
156
|
+
├─ Check .env.local exists?
|
|
157
|
+
│ ├─ Yes → Load from .env.local (dotenv)
|
|
158
|
+
│ └─ No → Check Keychain
|
|
159
|
+
│ ├─ Found → Load from Keychain
|
|
160
|
+
│ └─ Not found → Prompt for setup
|
|
161
|
+
│
|
|
162
|
+
├─ Validate required credentials
|
|
163
|
+
│ └─ Missing? → Offer interactive setup
|
|
164
|
+
│
|
|
165
|
+
└─ Create secure temp env file
|
|
166
|
+
└─ Pass to Docker Compose
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Priority:**
|
|
170
|
+
1. `.env.local` (highest - overrides Keychain)
|
|
171
|
+
2. macOS Keychain (fallback)
|
|
172
|
+
3. Error if not found
|
|
173
|
+
|
|
174
|
+
**Module:** `lib/config.js` (`loadKeychainCredentials()`)
|
|
175
|
+
|
|
176
|
+
### 4. Secure Temporary Files
|
|
177
|
+
|
|
178
|
+
**Purpose:** Pass credentials to Docker Compose securely
|
|
179
|
+
|
|
180
|
+
**Location:** `.buwp-local/.env.XXXXXX` (random suffix)
|
|
181
|
+
|
|
182
|
+
**Permissions:** `0600` (owner read/write only)
|
|
183
|
+
|
|
184
|
+
**Lifecycle:**
|
|
185
|
+
1. **Create:** Before starting containers
|
|
186
|
+
2. **Use:** Docker Compose reads via `env_file` directive
|
|
187
|
+
3. **Delete:** After stopping containers or on process exit
|
|
188
|
+
|
|
189
|
+
**Implementation:**
|
|
190
|
+
```javascript
|
|
191
|
+
// lib/config.js
|
|
192
|
+
|
|
193
|
+
export function createSecureTempEnvFile(credentials) {
|
|
194
|
+
const tmpDir = path.join(process.cwd(), '.buwp-local');
|
|
195
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
196
|
+
|
|
197
|
+
const tmpFile = fs.mkdtempSync(path.join(tmpDir, '.env.'));
|
|
198
|
+
const envFilePath = path.join(tmpFile, '.env');
|
|
199
|
+
|
|
200
|
+
// Write credentials with escaped newlines
|
|
201
|
+
const content = Object.entries(credentials)
|
|
202
|
+
.map(([key, value]) => {
|
|
203
|
+
const escaped = value.replace(/\n/g, '\\n');
|
|
204
|
+
return `${key}=${escaped}`;
|
|
205
|
+
})
|
|
206
|
+
.join('\n');
|
|
207
|
+
|
|
208
|
+
fs.writeFileSync(envFilePath, content, { mode: 0o600 });
|
|
209
|
+
|
|
210
|
+
return envFilePath;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function secureDeleteTempEnvFile(filePath) {
|
|
214
|
+
if (fs.existsSync(filePath)) {
|
|
215
|
+
fs.unlinkSync(filePath);
|
|
216
|
+
fs.rmdirSync(path.dirname(filePath));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Why Not Process Environment?**
|
|
222
|
+
- ❌ Process env vars visible in `ps` output
|
|
223
|
+
- ❌ Can't handle multiline values reliably
|
|
224
|
+
- ✅ Temp files are more secure
|
|
225
|
+
- ✅ Docker Compose `env_file` is standard pattern
|
|
226
|
+
|
|
227
|
+
### 5. Docker Compose Generation
|
|
228
|
+
|
|
229
|
+
**Template:** Generated dynamically in memory
|
|
230
|
+
|
|
231
|
+
**Generation Process:**
|
|
232
|
+
|
|
233
|
+
1. **Base Services** (always included):
|
|
234
|
+
```yaml
|
|
235
|
+
services:
|
|
236
|
+
wordpress:
|
|
237
|
+
image: ghcr.io/bu-ist/bu-wp-docker-mod_shib:arm64-latest
|
|
238
|
+
environment:
|
|
239
|
+
WORDPRESS_DB_HOST: db
|
|
240
|
+
WORDPRESS_DB_USER: wordpress
|
|
241
|
+
env_file: .buwp-local/.env.XXXXXX
|
|
242
|
+
volumes:
|
|
243
|
+
- wp_build:/var/www/html
|
|
244
|
+
|
|
245
|
+
db:
|
|
246
|
+
image: mysql:8.0
|
|
247
|
+
environment:
|
|
248
|
+
MYSQL_DATABASE: wordpress
|
|
249
|
+
MYSQL_USER: wordpress
|
|
250
|
+
env_file: .buwp-local/.env.XXXXXX
|
|
251
|
+
volumes:
|
|
252
|
+
- db_data:/var/lib/mysql
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
2. **Add Optional Services** (if enabled):
|
|
256
|
+
```yaml
|
|
257
|
+
redis:
|
|
258
|
+
image: redis:alpine
|
|
259
|
+
|
|
260
|
+
s3proxy:
|
|
261
|
+
image: ghcr.io/bu-ist/s3-proxy:latest
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
3. **Add Volume Mappings**:
|
|
265
|
+
```yaml
|
|
266
|
+
wordpress:
|
|
267
|
+
volumes:
|
|
268
|
+
- ./:/var/www/html/wp-content/plugins/my-plugin
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
4. **Add Port Mappings**:
|
|
272
|
+
```yaml
|
|
273
|
+
wordpress:
|
|
274
|
+
ports:
|
|
275
|
+
- "80:80"
|
|
276
|
+
- "443:443"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
5. **Add Named Volumes**:
|
|
280
|
+
```yaml
|
|
281
|
+
volumes:
|
|
282
|
+
db_data:
|
|
283
|
+
name: ${projectName}_db_data
|
|
284
|
+
wp_build:
|
|
285
|
+
name: ${projectName}_wp_build
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Module:** `lib/docker-compose.js`
|
|
289
|
+
|
|
290
|
+
**Output:** `.buwp-local/docker-compose.yml`
|
|
291
|
+
|
|
292
|
+
**Important:** Generated file contains **variable references** (`${VAR_NAME}`), not actual credential values.
|
|
293
|
+
|
|
294
|
+
### 6. Docker Compose Execution
|
|
295
|
+
|
|
296
|
+
**Process:** Node.js child process spawning `docker compose` command
|
|
297
|
+
|
|
298
|
+
Once the docker-compose.yml is generated, buwp-local executes Docker Compose commands using the following pattern:
|
|
299
|
+
|
|
300
|
+
**Commands:**
|
|
301
|
+
```bash
|
|
302
|
+
# Start
|
|
303
|
+
docker compose -f .buwp-local/docker-compose.yml \
|
|
304
|
+
--project-name ${projectName} \
|
|
305
|
+
--env-file .buwp-local/.env.XXXXXX \
|
|
306
|
+
up -d
|
|
307
|
+
|
|
308
|
+
# Stop
|
|
309
|
+
docker compose -f .buwp-local/docker-compose.yml \
|
|
310
|
+
--project-name ${projectName} \
|
|
311
|
+
down
|
|
312
|
+
|
|
313
|
+
# Destroy
|
|
314
|
+
docker compose -f .buwp-local/docker-compose.yml \
|
|
315
|
+
--project-name ${projectName} \
|
|
316
|
+
down -v
|
|
317
|
+
|
|
318
|
+
# Logs
|
|
319
|
+
docker compose -f .buwp-local/docker-compose.yml \
|
|
320
|
+
--project-name ${projectName} \
|
|
321
|
+
logs
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Project Names:**
|
|
325
|
+
- Each project gets unique Docker Compose project name
|
|
326
|
+
- Format: sanitized directory name (lowercase, alphanumeric)
|
|
327
|
+
- Enables running multiple projects simultaneously
|
|
328
|
+
- All containers/volumes prefixed with project name
|
|
329
|
+
|
|
330
|
+
**Module:** `lib/commands/start.js`, `lib/commands/stop.js`
|
|
331
|
+
|
|
332
|
+
### 7. Volume Management
|
|
333
|
+
|
|
334
|
+
**Per-Project Volumes:**
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
volumes:
|
|
338
|
+
db_data:
|
|
339
|
+
name: ${projectName}_db_data # MySQL data
|
|
340
|
+
wp_build:
|
|
341
|
+
name: ${projectName}_wp_build # WordPress files
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Bind Mounts (Volume Mappings):**
|
|
345
|
+
|
|
346
|
+
```yaml
|
|
347
|
+
volumes:
|
|
348
|
+
- ./:/var/www/html/wp-content/plugins/my-plugin
|
|
349
|
+
- ../theme:/var/www/html/wp-content/themes/my-theme
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Volume Isolation:**
|
|
353
|
+
- Each project name gets unique volumes
|
|
354
|
+
- Prevents database conflicts between projects
|
|
355
|
+
- Allows multiple projects to run simultaneously
|
|
356
|
+
- Volumes persist until `destroy` command
|
|
357
|
+
|
|
358
|
+
**Shared Environment:**
|
|
359
|
+
- Multiple repos with same `projectName` share volumes
|
|
360
|
+
- Enables integration testing
|
|
361
|
+
- All mappings accumulate
|
|
362
|
+
|
|
363
|
+
### 8. WP-CLI Proxy
|
|
364
|
+
|
|
365
|
+
**Implementation:**
|
|
366
|
+
```bash
|
|
367
|
+
docker compose --project-name ${projectName} \
|
|
368
|
+
-f .buwp-local/docker-compose.yml \
|
|
369
|
+
exec wordpress \
|
|
370
|
+
wp ${args}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Usage:**
|
|
374
|
+
```bash
|
|
375
|
+
npx buwp-local wp plugin list
|
|
376
|
+
npx buwp-local wp user create username user@bu.edu
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Features:**
|
|
380
|
+
- Passes all arguments through to WP-CLI
|
|
381
|
+
- Runs inside WordPress container
|
|
382
|
+
- Requires containers to be running
|
|
383
|
+
|
|
384
|
+
**Module:** `lib/commands/wp.js`
|
|
385
|
+
|
|
386
|
+
## Security Model
|
|
387
|
+
|
|
388
|
+
### Credential Security
|
|
389
|
+
|
|
390
|
+
**Storage:**
|
|
391
|
+
- **Keychain:** Encrypted by macOS, protected by user authentication
|
|
392
|
+
- **`.env.local`:** File permissions should be `0600` (user-managed)
|
|
393
|
+
|
|
394
|
+
**In Transit:**
|
|
395
|
+
- Loaded in Node.js process memory
|
|
396
|
+
- Written to temp file with `0600` permissions
|
|
397
|
+
- Never logged or displayed (except explicit `keychain get` command)
|
|
398
|
+
|
|
399
|
+
**In Docker:**
|
|
400
|
+
- Passed via `env_file` directive (not command line)
|
|
401
|
+
- Not visible in `docker ps` or process list
|
|
402
|
+
- Not written to generated `docker-compose.yml`
|
|
403
|
+
|
|
404
|
+
**Cleanup:**
|
|
405
|
+
- Temp files deleted on stop/destroy
|
|
406
|
+
- Process exit handlers ensure cleanup
|
|
407
|
+
|
|
408
|
+
### File Permissions
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
.buwp-local/
|
|
412
|
+
docker-compose.yml # 0644 (safe - no credentials)
|
|
413
|
+
.env.XXXXXX/ # 0700 directory
|
|
414
|
+
.env # 0600 file (credentials)
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Git Ignore
|
|
418
|
+
|
|
419
|
+
**Must be ignored:**
|
|
420
|
+
```gitignore
|
|
421
|
+
.env.local
|
|
422
|
+
.buwp-local/
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**Safe to commit:**
|
|
426
|
+
```
|
|
427
|
+
.buwp-local.json # Configuration template (no secrets)
|
|
428
|
+
.env.local.example # Example with placeholder values
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Multi-Project Architecture
|
|
432
|
+
|
|
433
|
+
### Isolated Projects
|
|
434
|
+
|
|
435
|
+
```
|
|
436
|
+
Project A (bu-custom-analytics):
|
|
437
|
+
Volumes:
|
|
438
|
+
- bu-custom-analytics_db_data
|
|
439
|
+
- bu-custom-analytics_wp_build
|
|
440
|
+
Containers:
|
|
441
|
+
- bu-custom-analytics-wordpress-1
|
|
442
|
+
- bu-custom-analytics-db-1
|
|
443
|
+
Hostname: bu-custom-analytics.local
|
|
444
|
+
Ports: 8080, 8443
|
|
445
|
+
|
|
446
|
+
Project B (bu-slideshow):
|
|
447
|
+
Volumes:
|
|
448
|
+
- bu-slideshow_db_data
|
|
449
|
+
- bu-slideshow_wp_build
|
|
450
|
+
Containers:
|
|
451
|
+
- bu-slideshow-wordpress-1
|
|
452
|
+
- bu-slideshow-db-1
|
|
453
|
+
Hostname: bu-slideshow.local
|
|
454
|
+
Ports: 8081, 8444
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Key:** Different `projectName` = Complete isolation
|
|
458
|
+
|
|
459
|
+
### Shared Projects
|
|
460
|
+
|
|
461
|
+
```
|
|
462
|
+
Shared Environment (bu-sandbox):
|
|
463
|
+
Volumes:
|
|
464
|
+
- bu-sandbox_db_data # Shared
|
|
465
|
+
- bu-sandbox_wp_build # Shared
|
|
466
|
+
Containers:
|
|
467
|
+
- bu-sandbox-wordpress-1
|
|
468
|
+
- bu-sandbox-db-1
|
|
469
|
+
Mappings:
|
|
470
|
+
- ~/projects/plugin-a → /wp-content/plugins/plugin-a
|
|
471
|
+
- ~/projects/plugin-b → /wp-content/plugins/plugin-b
|
|
472
|
+
- ~/projects/theme → /wp-content/themes/theme
|
|
473
|
+
Hostname: bu-sandbox.local
|
|
474
|
+
Ports: 80, 443
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**Key:** Same `projectName` = Shared volumes and containers
|
|
478
|
+
|
|
479
|
+
## Performance Considerations
|
|
480
|
+
|
|
481
|
+
### Volume Performance
|
|
482
|
+
|
|
483
|
+
**Bind Mounts:**
|
|
484
|
+
- Direct host filesystem access
|
|
485
|
+
- Fast on macOS (Docker Desktop optimizations)
|
|
486
|
+
- Real-time code changes
|
|
487
|
+
|
|
488
|
+
**Named Volumes:**
|
|
489
|
+
- Better performance than bind mounts
|
|
490
|
+
- Used for database and WordPress core
|
|
491
|
+
- Persist between starts
|
|
492
|
+
|
|
493
|
+
### Resource Usage
|
|
494
|
+
|
|
495
|
+
**Typical Project:**
|
|
496
|
+
- WordPress container: ~200-500 MB RAM
|
|
497
|
+
- MySQL container: ~200-400 MB RAM
|
|
498
|
+
- Redis container: ~10-20 MB RAM
|
|
499
|
+
- S3 Proxy container: ~50-100 MB RAM
|
|
500
|
+
- Total: ~500 MB - 1 GB per project
|
|
501
|
+
|
|
502
|
+
**Multiple Projects:**
|
|
503
|
+
- Linear scaling per project
|
|
504
|
+
- 3 projects ≈ 1.5-3 GB RAM
|
|
505
|
+
- Docker Desktop overhead: ~500 MB
|
|
506
|
+
|
|
507
|
+
## Extensibility
|
|
508
|
+
|
|
509
|
+
### Adding New Services
|
|
510
|
+
|
|
511
|
+
Edit `lib/docker-compose.js`:
|
|
512
|
+
|
|
513
|
+
```javascript
|
|
514
|
+
if (config.services.myservice) {
|
|
515
|
+
compose.services.myservice = {
|
|
516
|
+
image: 'my/service:latest',
|
|
517
|
+
environment: {
|
|
518
|
+
SERVICE_CONFIG: '${MY_SERVICE_CONFIG}'
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
Add credential type to `lib/keychain.js`:
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
const CREDENTIAL_TYPES = [
|
|
528
|
+
// ... existing types
|
|
529
|
+
'MY_SERVICE_CONFIG'
|
|
530
|
+
];
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Adding New Commands
|
|
534
|
+
|
|
535
|
+
Create `lib/commands/mycommand.js`:
|
|
536
|
+
|
|
537
|
+
```javascript
|
|
538
|
+
import { Command } from 'commander';
|
|
539
|
+
|
|
540
|
+
export function myCommand(program) {
|
|
541
|
+
program
|
|
542
|
+
.command('mycommand')
|
|
543
|
+
.description('Description of my command')
|
|
544
|
+
.action(async (options) => {
|
|
545
|
+
// Implementation
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Register in `bin/buwp-local.js`:
|
|
551
|
+
|
|
552
|
+
```javascript
|
|
553
|
+
import { myCommand } from '../lib/commands/mycommand.js';
|
|
554
|
+
|
|
555
|
+
myCommand(program);
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Custom Docker Images
|
|
559
|
+
|
|
560
|
+
Override in `.buwp-local.json`:
|
|
561
|
+
|
|
562
|
+
```json
|
|
563
|
+
{
|
|
564
|
+
"image": "ghcr.io/bu-ist/custom-image:latest"
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
## Error Handling
|
|
569
|
+
|
|
570
|
+
### Configuration Errors
|
|
571
|
+
|
|
572
|
+
**Validation:** Runs before Docker Compose generation
|
|
573
|
+
|
|
574
|
+
**Common Issues:**
|
|
575
|
+
- Missing required fields → Prompt with defaults
|
|
576
|
+
- Invalid JSON → Clear error message with line number
|
|
577
|
+
- Invalid paths → Resolve and validate before use
|
|
578
|
+
|
|
579
|
+
### Docker Errors
|
|
580
|
+
|
|
581
|
+
**Detection:** Check exit codes from `docker compose` commands
|
|
582
|
+
|
|
583
|
+
**Common Issues:**
|
|
584
|
+
- Docker not running → Check `docker info`
|
|
585
|
+
- Port conflicts → Suggest alternate ports
|
|
586
|
+
- Image pull failures → Check authentication
|
|
587
|
+
- Volume permission issues → Suggest cleanup
|
|
588
|
+
|
|
589
|
+
### Credential Errors
|
|
590
|
+
|
|
591
|
+
**Validation:** Before starting containers
|
|
592
|
+
|
|
593
|
+
**Common Issues:**
|
|
594
|
+
- Missing credentials → Offer interactive setup
|
|
595
|
+
- Keychain access denied → Provide Keychain Access instructions
|
|
596
|
+
- Invalid format → Clear error about expected format
|
|
597
|
+
|
|
598
|
+
### Cleanup on Failure
|
|
599
|
+
|
|
600
|
+
These are the handlers to ensure temporary files are deleted on process exit:
|
|
601
|
+
|
|
602
|
+
**Process Exit Handlers:**
|
|
603
|
+
```javascript
|
|
604
|
+
process.on('SIGINT', cleanup);
|
|
605
|
+
process.on('SIGTERM', cleanup);
|
|
606
|
+
process.on('exit', cleanup);
|
|
607
|
+
|
|
608
|
+
function cleanup() {
|
|
609
|
+
secureDeleteTempEnvFile(tempEnvPath);
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
**Graceful Shutdown:**
|
|
614
|
+
- Delete temporary credential files
|
|
615
|
+
- Log cleanup actions
|
|
616
|
+
- Preserve volumes (unless `destroy`)
|
|
617
|
+
|
|
618
|
+
## Dependencies
|
|
619
|
+
|
|
620
|
+
### Runtime Dependencies
|
|
621
|
+
|
|
622
|
+
```json
|
|
623
|
+
{
|
|
624
|
+
"commander": "^12.x", // CLI framework
|
|
625
|
+
"js-yaml": "^4.x", // YAML generation
|
|
626
|
+
"chalk": "^5.x", // Terminal colors
|
|
627
|
+
"prompts": "^2.x", // Interactive prompts
|
|
628
|
+
"dotenv": "^16.x" // .env.local parsing
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### External Requirements
|
|
633
|
+
|
|
634
|
+
- **Node.js:** >=18.0.0 (ESM support)
|
|
635
|
+
- **Docker Desktop:** Latest stable
|
|
636
|
+
- **macOS:** 10.15+ (for Keychain integration)
|
|
637
|
+
- **Shell:** zsh or bash
|
|
638
|
+
|
|
639
|
+
### Platform Support
|
|
640
|
+
|
|
641
|
+
**Current:**
|
|
642
|
+
- ✅ macOS (Intel and Apple Silicon)
|
|
643
|
+
- ✅ Keychain integration (macOS only)
|
|
644
|
+
|
|
645
|
+
**Future:**
|
|
646
|
+
- 🔄 Linux (credential storage TBD)
|
|
647
|
+
- 🔄 Windows (WSL2 + credential storage TBD)
|
|
648
|
+
|
|
649
|
+
## Testing Strategy
|
|
650
|
+
|
|
651
|
+
### Manual Testing
|
|
652
|
+
|
|
653
|
+
**Test Commands:**
|
|
654
|
+
|
|
655
|
+
Unit tests not implemented yet, recommend vitest as with bu-protected-s3-object-lambda.
|
|
656
|
+
|
|
657
|
+
### Validation
|
|
658
|
+
|
|
659
|
+
**Config Validation:**
|
|
660
|
+
```bash
|
|
661
|
+
npx buwp-local config --validate
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
**Credential Validation:**
|
|
665
|
+
```bash
|
|
666
|
+
npx buwp-local keychain status
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
**Docker Validation:**
|
|
670
|
+
```bash
|
|
671
|
+
docker compose -f .buwp-local/docker-compose.yml config
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
## Future Enhancements
|
|
675
|
+
|
|
676
|
+
### Planned Features
|
|
677
|
+
|
|
678
|
+
- **Cross-platform credential storage** (Linux, Windows)
|
|
679
|
+
- **Automatic /etc/hosts management** (detect missing entries)
|
|
680
|
+
- **SSL certificate generation** (local HTTPS)
|
|
681
|
+
- **Central registry** (shared team configurations)
|
|
682
|
+
- **Health checks** (verify services are running)
|
|
683
|
+
- **Performance monitoring** (container resource usage)
|
|
684
|
+
- **Unit tests** vitest
|
|
685
|
+
|
|
686
|
+
## See Also
|
|
687
|
+
|
|
688
|
+
- [Getting Started](GETTING_STARTED.md) - User guide
|
|
689
|
+
- [Commands Reference](COMMANDS.md) - Full command list
|
|
690
|
+
- [Credentials Management](CREDENTIALS.md) - Security details
|
|
691
|
+
- [Multi-Project Setup](MULTI_PROJECT.md) - Running multiple projects
|