@bostonuniversity/buwp-local 0.6.0 → 0.6.2

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.
@@ -383,6 +383,153 @@ npx buwp-local wp user create username user@bu.edu
383
383
 
384
384
  **Module:** `lib/commands/wp.js`
385
385
 
386
+ ## Architectural Advantages
387
+
388
+ ### Why Docker + Volume Mappings Over VM Sandboxes
389
+
390
+ Traditional VM sandbox environments face a fundamental architectural limitation: **WordPress core and developer code share the same filesystem**. This creates a destructive update cycle.
391
+
392
+ #### The VM Sandbox Problem
393
+
394
+ ```
395
+ ┌───────────────────────────────────────┐
396
+ │ VM Filesystem │
397
+ │ │
398
+ │ /var/www/html/ │
399
+ │ ├── wp-admin/ (WordPress core)│
400
+ │ ├── wp-includes/ (WordPress core)│
401
+ │ └── wp-content/ │
402
+ │ ├── plugins/ │
403
+ │ │ └── my-plugin/ ← Your code
404
+ │ └── themes/ │
405
+ │ └── my-theme/ ← Your code
406
+ │ │
407
+ │ ALL IN ONE PLACE = Problem! │
408
+ └───────────────────────────────────────┘
409
+
410
+ To update WordPress → Must rebuild entire VM
411
+ Rebuild entire VM → Your code gets overwritten
412
+ ```
413
+
414
+ **Consequences:**
415
+ - Monthly rebuild schedules required
416
+ - Developers must backup code before rebuilds
417
+ - Team-wide coordination overhead
418
+ - All-or-nothing updates (everyone updates together)
419
+ - Risk of losing work if backup/restore fails
420
+
421
+ #### The buwp-local Solution
422
+
423
+ Docker's **volume mapping architecture** creates a clean separation:
424
+
425
+ ```
426
+ ┌─────────────────────────────────┐
427
+ │ Your Mac's Filesystem │ ← Developer code lives here
428
+ │ │ (permanent, survives updates)
429
+ │ ~/projects/my-plugin/ │
430
+ │ ├── my-plugin.php │
431
+ │ ├── includes/ │
432
+ │ └── assets/ │
433
+ └────────────┬────────────────────┘
434
+ │ Volume mapping (bind mount)
435
+
436
+ ┌─────────────────────────────────┐
437
+ │ Docker Container │ ← WordPress core lives here
438
+ │ │ (disposable, updates don't affect code)
439
+ │ /var/www/html/ │
440
+ │ ├── wp-admin/ (from image)│
441
+ │ ├── wp-includes/ (from image)│
442
+ │ └── wp-content/ │
443
+ │ └── plugins/ │
444
+ │ └── my-plugin/ ──┐ │ (mapped from Mac)
445
+ │ │ │
446
+ │ SEPARATED = No conflicts! │ │
447
+ └────────────────────────────────┴─┘
448
+ ```
449
+
450
+ **Technical Benefits:**
451
+
452
+ 1. **Persistent Code** - Your code lives on the host filesystem, not in the container. Destroy and recreate containers as much as you want—code never changes.
453
+
454
+ 2. **Independent Updates** - Pull new WordPress images (`docker pull`) without affecting your development code. Update on your schedule, not a team calendar.
455
+
456
+ 3. **Instant Rollback** - Switch between WordPress versions by changing the image tag. Your code stays constant while you test different WordPress versions.
457
+
458
+ 4. **Zero Coordination** - Each developer controls their own environment. No rebuild meetings, no freeze periods, no waiting for others.
459
+
460
+ 5. **Safe Testing** - Test breaking changes in WordPress without risk. If something goes wrong, recreate the container—your code was never in danger.
461
+
462
+ #### Workflow Comparison
463
+
464
+ **VM Sandbox Workflow:**
465
+ ```
466
+ Week 1-3: Develop in VM
467
+ Week 4: Monthly rebuild
468
+ 1. Backup your code manually
469
+ 2. Coordinate with team
470
+ 3. Wait for new VM image
471
+ 4. Restore code manually
472
+ 5. Re-test everything
473
+ 6. Hope nothing broke
474
+ Time lost: 2-4 hours + coordination overhead
475
+ ```
476
+
477
+ **buwp-local Workflow:**
478
+ ```
479
+ Anytime: New WordPress version available
480
+ 1. docker pull ghcr.io/bu-ist/buwp:latest
481
+ 2. npx buwp-local start
482
+ 3. Test (your code unchanged)
483
+ Time: 2 minutes
484
+ ```
485
+
486
+ #### Real-World Example
487
+
488
+ **Scenario:** 6-week plugin development project. WordPress update lands in week 3.
489
+
490
+ **VM Approach:**
491
+ - Wait for scheduled monthly rebuild (week 4)
492
+ - Backup your work
493
+ - Rebuild overwrites everything
494
+ - Restore and re-test
495
+ - **Impact:** 2-4 hours lost, risk of data loss
496
+
497
+ **buwp-local Approach:**
498
+ - Pull new image when convenient (any time in week 3-6)
499
+ - Containers recreate with new WordPress version
500
+ - Your code untouched on local filesystem
501
+ - **Impact:** 2 minutes, zero risk
502
+
503
+ ### Separation of Concerns
504
+
505
+ This architecture provides clean boundaries:
506
+
507
+ | Concern | Location | Update Mechanism |
508
+ |---------|----------|------------------|
509
+ | WordPress core | Docker image | `docker pull` |
510
+ | BU plugins | Docker image | `docker pull` |
511
+ | BU theme | Docker image | `docker pull` |
512
+ | **Your plugin** | **Local filesystem** | **Your editor** |
513
+ | **Your theme** | **Local filesystem** | **Your editor** |
514
+ | Database | Docker volume | Persists across updates |
515
+ | Uploads | Docker volume | Persists across updates |
516
+
517
+ Updates to WordPress never touch your development code. Updates to your code never require rebuilding WordPress.
518
+
519
+ ### Additional Architectural Benefits
520
+
521
+ 1. **Live Reload** - File changes sync instantly via volume mappings. Save in your editor, refresh browser, see changes.
522
+
523
+ 2. **IDE Integration** - Use any editor (VS Code, PHPStorm, Sublime) with full IDE features (autocomplete, debugging, git integration).
524
+
525
+ 3. **Version Control** - Your code is already on the host filesystem where git lives. No special workflows to commit from inside VMs.
526
+
527
+ 4. **Multiple Projects** - Run multiple projects simultaneously, each with isolated environments. No VM resource conflicts.
528
+
529
+ 5. **Portable Configuration** - Commit `.buwp-local.json` to version control. Teammates get identical environments with one command.
530
+
531
+ For detailed migration guidance, see [MIGRATION_FROM_VM.md](MIGRATION_FROM_VM.md).
532
+
386
533
  ## Security Model
387
534
 
388
535
  ### Credential Security
package/docs/CHANGELOG.md CHANGED
@@ -7,10 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.2]
11
+
12
+ ### Fixed
13
+ - **Project paths with spaces** - Fixed shell command construction to properly quote Docker Compose file paths when project directory contains spaces
14
+ - Prevents shell word-splitting errors like `unknown docker command: "compose folder/..."`
15
+ - All Docker Compose commands (`start`, `stop`, `destroy`, `logs`, `wp`) now correctly handle paths with spaces and special characters
16
+
17
+ ### Changed
18
+ - Volume mapping generation now uses cleaner functional programming pattern with `map()` and spread operator
19
+ - Improved code readability in `generateWordPressService()` by isolating volume mapping transformation
20
+
21
+ ## [0.6.1]
22
+
23
+ ### Added
24
+ - Container registry accessibility check on `start` command
25
+ - Automatic Docker image pull with helpful authentication guidance
26
+ - GitHub Packages authentication assistance when image access is denied
27
+
28
+ ### Fixed
29
+ - Clear error messages for registry authentication failures with actionable next steps
30
+
31
+ ## [0.6.0]
32
+
10
33
  ### Added
11
34
  - Credential validation on `start` command with interactive setup prompt
12
35
  - Documentation consolidation in `docs/` directory
13
36
  - Comprehensive guides: GETTING_STARTED.md, COMMANDS.md, CREDENTIALS.md, MULTI_PROJECT.md, ARCHITECTURE.md
37
+ - Robust `/etc/hosts` detection with smart one-time warnings
38
+ - VM Sandbox migration guide highlighting architectural advantages
14
39
 
15
40
  ## [0.5.3]
16
41
 
@@ -0,0 +1,237 @@
1
+ # Migration from VM Sandboxes
2
+
3
+ This guide explains the architectural advantages of buwp-local compared to traditional VM sandbox environments and provides practical migration advice.
4
+
5
+ ## Difficulties with VM Sandboxes
6
+
7
+ 1. DV01 sandboxes are very slow.
8
+ 2. The shared server is a single point of failure, and stability issues impact all developers.
9
+ 3. Reliance on SFTP for code editing is becoming outdated and hard to support.
10
+ 4. VM Sandboxes need periodic updates.
11
+
12
+ ## The VM Sandbox Updates Problem
13
+
14
+ In traditional VM-based development environments:
15
+
16
+ 1. **Monthly rebuild cycles** - VM sandboxes must be periodically replaced with fresh builds to keep WordPress core, plugins, and infrastructure up to date
17
+ 2. **Manual preservation** - Developers must manually back up their work before each rebuild and restore it afterward
18
+ 3. **Coordination overhead** - Team-wide rebuild schedules require coordination and can interrupt active development
19
+ 4. **All-or-nothing updates** - The entire team must update together, regardless of individual project needs
20
+
21
+ ## How buwp-local Solves This
22
+
23
+ buwp-local uses **Docker's volume mapping architecture** to fundamentally separate concerns:
24
+
25
+ ```
26
+ ┌─────────────────────────────────────┐
27
+ │ Your Local Filesystem │
28
+ │ (Your code lives here permanently) │
29
+ │ │
30
+ │ /path/to/your-plugin/ │
31
+ │ ├── plugin.php │
32
+ │ ├── includes/ │
33
+ │ └── assets/ │
34
+ └─────────────┬───────────────────────┘
35
+ │ Volume mapping
36
+
37
+ ┌─────────────────────────────────────┐
38
+ │ Docker Container │
39
+ │ (WordPress core lives here) │
40
+ │ │
41
+ │ /var/www/html/ │
42
+ │ ├── wp-admin/ (from image) │
43
+ │ ├── wp-includes/ (from image) │
44
+ │ └── wp-content/ │
45
+ │ └── plugins/ │
46
+ │ └── your-plugin/ ←──── │ (mapped from local)
47
+ └─────────────────────────────────────┘
48
+ ```
49
+
50
+ ### Key Architectural Differences
51
+
52
+ | Aspect | VM Sandbox | buwp-local |
53
+ |--------|------------|------------|
54
+ | **Code location** | Inside VM filesystem | Your local filesystem |
55
+ | **WordPress core** | Inside VM filesystem | Inside disposable container |
56
+ | **Update mechanism** | Deploy entire WP build | Pull new Docker image |
57
+ | **Your code** | Overwritten on rebuild | Always preserved |
58
+ | **Update schedule** | Team-wide coordination | Individual developer choice |
59
+
60
+ ## Advantages
61
+
62
+ ### 1. Persistent Code
63
+
64
+ Your development work lives on your Mac's filesystem. Even if you destroy and recreate containers hundreds of times, your code remains untouched.
65
+
66
+ ```bash
67
+ # This destroys the container but NOT your code
68
+ npx buwp-local destroy
69
+
70
+ # Start fresh - your code is still there
71
+ npx buwp-local start
72
+ ```
73
+
74
+ ### 2. Individual Update Schedules
75
+
76
+ Only those plugin and themes that you explicitly map into the container are fixed to the working code in your local filesystem. All of the other code resources from the BU WordPress build come from the container and can be updated independently.
77
+
78
+ Update WordPress whenever it makes sense for YOUR project:
79
+
80
+ ```bash
81
+ # You in January: Pull latest image
82
+ docker pull ghcr.io/bu-ist/buwp:latest
83
+
84
+ # Colleague in February: Still working on older version
85
+ # No problem - they update when ready
86
+ ```
87
+
88
+ ### 3. Instant Version Switching
89
+
90
+ Test different WordPress versions without losing work:
91
+
92
+ ```yaml
93
+ # .buwp-local.json
94
+ {
95
+ "image": "ghcr.io/bu-ist/bu-wp-docker-mod_shib:arm64-wp5-8" # Stable version
96
+ }
97
+ ```
98
+
99
+ ```yaml
100
+ # Switch to test new features
101
+ {
102
+ "image": "ghcr.io/bu-ist/bu-wp-docker-mod_shib:arm64-wp6-0" # Release candidate
103
+ }
104
+ ```
105
+
106
+ Your code stays the same - only the WordPress version changes.
107
+
108
+ ### 4. No Rebuild Coordination
109
+
110
+ Every developer controls their own environment:
111
+
112
+ - No team-wide rebuild meetings
113
+ - No "freeze" periods before rebuilds
114
+ - No coordination overhead
115
+ - No waiting for others
116
+
117
+
118
+ ---
119
+
120
+ ## What Changes in Your Workflow
121
+
122
+ ### Before (VM Sandbox)
123
+
124
+ ```
125
+ 1. Connect to VM via SSH SFTP
126
+ 2. Edit code in VM filesystem
127
+ 3. Test changes in VM's WordPress (dv01 is slow!)
128
+ 4. Before monthly rebuild: Back up your changes
129
+ 5. After rebuild: Restore changes and pray
130
+ 6. Repeat monthly
131
+ ```
132
+
133
+ ### After (buwp-local)
134
+
135
+ ```
136
+ 1. Edit code in your favorite local editor
137
+ 2. Changes instantly sync to container
138
+ 3. Test changes at http://yourproject.local
139
+ 4. When WordPress update available: docker pull
140
+ 5. That's it - your code was never touched
141
+ ```
142
+
143
+ ## Frequently Asked Questions
144
+
145
+ ### "What if I need the old VM for something?"
146
+
147
+ Keep it! buwp-local and VM sandboxes can coexist. Use buwp-local for active development and VMs for other purposes.
148
+
149
+ ### "What about database snapshots?"
150
+
151
+ buwp-local includes the same `wp site-manager snapshot-pull` command as production. Pull from production/staging anytime:
152
+
153
+ ```bash
154
+ npx buwp-local wp site-manager snapshot-pull --source=https://www.bu.edu/site/
155
+ ```
156
+
157
+ ### "Can I share my environment with teammates?"
158
+
159
+ Your `.buwp-local.json` configuration can be committed to version control. Teammates run:
160
+
161
+ ```bash
162
+ git clone your-repo
163
+ npm install
164
+ npx buwp-local start
165
+ ```
166
+
167
+ Everyone gets an identical environment with their own isolated containers.
168
+
169
+ ### "What happens to my database when I update?"
170
+
171
+ Docker volumes persist your database across container updates:
172
+
173
+ ```bash
174
+ # Your database lives in a named volume
175
+ docker volume ls | grep wordpress-db
176
+
177
+ # It survives container recreation
178
+ npx buwp-local destroy # Removes container
179
+ npx buwp-local start # Database still intact
180
+ ```
181
+
182
+ ### "How do I completely start fresh?"
183
+
184
+ ```bash
185
+ # Remove everything including database (this is notional, the actual command does not yet support the --volumes flag)
186
+ npx buwp-local destroy --volumes
187
+
188
+ # Or keep database, just refresh WordPress
189
+ npx buwp-local stop
190
+ docker pull ghcr.io/bu-ist/bu-wordpress:new-tag
191
+ npx buwp-local start
192
+ ```
193
+
194
+ ## Troubleshooting
195
+
196
+ ### Container won't start
197
+
198
+ ```bash
199
+ # Check Docker Desktop is running
200
+ docker info
201
+
202
+ # Check port conflicts
203
+ npx buwp-local start --verbose
204
+ ```
205
+
206
+ ### Code changes not appearing
207
+
208
+ Check volume mappings in `.buwp-local.json`:
209
+
210
+ ```json
211
+ {
212
+ "volumeMappings": [
213
+ {
214
+ "localPath": "./",
215
+ "containerPath": "/var/www/html/wp-content/plugins/your-plugin"
216
+ }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ ### Credentials not loading
222
+
223
+ ```bash
224
+ # Verify Keychain entries
225
+ npx buwp-local keychain list
226
+
227
+ # Or use .env.local fallback
228
+ npx buwp-local keychain export > .env.local
229
+ ```
230
+
231
+ See [CREDENTIALS.md](CREDENTIALS.md) for detailed credential management.
232
+
233
+ ## Additional Resources
234
+
235
+ - [Getting Started Guide](GETTING_STARTED.md) - Step-by-step setup
236
+ - [Command Reference](COMMANDS.md) - Complete CLI documentation
237
+ - [Architecture Guide](ARCHITECTURE.md) - Technical deep-dive
package/docs/ROADMAP.md CHANGED
@@ -19,11 +19,8 @@ Strategic direction and development priorities for buwp-local.
19
19
 
20
20
  ---
21
21
 
22
- ## Current Phase: v0.6.0 - Quality & Robustness
22
+ ## v0.6.0 - Quality & Robustness
23
23
  **Status:** Shipped
24
-
25
- **Status:** In Progress
26
- **Target Date:** December 2024
27
24
  **Focus:** Foundation improvements before team rollout
28
25
 
29
26
  ### Features in Development
@@ -104,28 +101,50 @@ hostile.remove('127.0.0.1', config.hostname);
104
101
 
105
102
  ---
106
103
 
104
+ ## Incremental Functional Improvements: v0.6.x
105
+ **Status:** Currently Ongoing
106
+ **Focus:** Enhancements based on initial user experience
107
+
108
+ ### Shipped in v0.6.1
109
+ - **Container Registry Assistance**
110
+ - Guide users on setting up access to private registries (ghcr.io)
111
+ - Automatic check for registry login or existing image on `start`
112
+
113
+ ### Planned for v0.6.2
114
+
115
+ - ***Get spaces in volume mappings working correctly***
116
+ - Fix issues with spaces in host paths causing Docker errors
117
+ - Ensure cross-platform compatibility (Windows, macOS, Linux)
118
+
119
+ - **Basic docs on existing Xdebug features**
120
+ - Quickstart guide for enabling and using Xdebug in containers
121
+
122
+ - **Volume Mapping pattern guide**
123
+ - Documentation on different volume mapping strategies for various development workflows
124
+
107
125
  ## Next Phase: v0.7.0 - Developer Experience
108
126
 
109
127
  **Status:** Planned
110
- **Timeline:** January 2025 (after team onboarding feedback)
128
+ **Timeline:** After team onboarding feedback
111
129
  **Focus:** Ease of use and visibility
112
130
 
113
131
  ### Potential Features
114
132
 
115
- - **Xdebug Integration**
116
- - Enable Xdebug in containers
117
- - Documentation for IDE setup
118
- - Configuration options in `.buwp-local.json`
119
-
120
133
  - **Security Checks**
121
134
  - Check database access on db port (e.g. `localhost:3306`)
122
135
  - Consider more stringent default database passwords
136
+ - The database can have restricted content in it, so we need to ensure that users are aware of this and take appropriate measures.
137
+
138
+ - **Xdebug Integration**
139
+ - Command to help generate Xdebug configuration for IDEs (VSCode, Zed)
140
+ - Documentation on usage patterns
123
141
 
124
142
  - **Improved Windows and Linux support**
125
143
  - Multiplatform /etc/hosts hostname management
126
- - Evaluate credential storage solutions for non-macOS platforms
144
+ - Evaluate credential storage solutions for non-macOS platforms (https://www.npmjs.com/package/keytar)
127
145
 
128
146
  - **Project Status & Listing**
147
+ - Central tracking of all buwp-local projects in `~/.buwp-local/projects.json`
129
148
  - View all running projects: `buwp-local list`
130
149
  - Quick status checks: `buwp-local status`
131
150
 
@@ -139,6 +158,12 @@ hostile.remove('127.0.0.1', config.hostname);
139
158
  - Credential issues → clear next steps
140
159
  - Port conflicts → suggest alternatives
141
160
 
161
+ - **Multi project experience**
162
+ - There is a problem when starting a new project when an existing project exists in docker but is stopped. When starting the new project, docker first starts the container for the stopped project for unknown reasons. If the new project uses the same ports, this causes conflicts. Need to investigate and resolve, projects should be isolated and not interfere with each other.
163
+
164
+ - **Docker Volume management assistant**
165
+ - listing and cleanup of unused volumes
166
+
142
167
  ### Prioritization
143
168
  Will be informed by feedback from initial 2-3 users and actual pain points observed during rollout.
144
169
 
@@ -163,19 +188,19 @@ Will be informed by feedback from initial 2-3 users and actual pain points obser
163
188
 
164
189
  ## Roadmap by User Stage
165
190
 
166
- ### Stage 1: Initial Users (Now)
191
+ ### Stage 1: Initial Users
167
192
  **Users:** 1-3 developers
168
193
  **Goal:** Validate core functionality
169
194
  **Release:** v0.6.0
170
195
  **Focus:** Robustness, clear setup, good documentation
171
196
 
172
- ### Stage 2: Team Rollout (Q1 2025)
197
+ ### Stage 2: Team Rollout
173
198
  **Users:** 10-15 developers
174
199
  **Goal:** Find and fix real-world issues
175
200
  **Release:** v0.7.0+
176
201
  **Focus:** Developer experience, error handling
177
202
 
178
- ### Stage 3: Broader Adoption (Q2 2025+)
203
+ ### Stage 3: Broader Adoption
179
204
  **Users:** 20+ developers
180
205
  **Goal:** Self-service onboarding
181
206
  **Release:** v1.0.0+
@@ -196,9 +221,7 @@ Will be informed by feedback from initial 2-3 users and actual pain points obser
196
221
  - Video tutorials for setup
197
222
 
198
223
  ### Quality
199
- - Standardized error handling across commands
200
- - Centralized logging system
201
- - Better validation for edge cases
224
+ - Standardized help for all CLI commands
202
225
 
203
226
  ---
204
227
 
@@ -213,35 +236,9 @@ Features will be prioritized based on:
213
236
 
214
237
  ---
215
238
 
216
- ## How to Use This Roadmap
217
-
218
- **For Users:**
219
- - See what's coming and when
220
- - Understand current release focus
221
- - Provide feedback on priorities
222
-
223
- **For Contributors:**
224
- - Clear phases and timeline
225
- - See future enhancement opportunities
226
- - Link to technical details in [ARCHITECTURE.md](ARCHITECTURE.md)
227
-
228
- ---
229
-
230
239
  ## Technical Details
231
240
 
232
241
  For detailed information about planned features, implementation approaches, and architecture decisions, see:
233
242
 
234
243
  - **[ARCHITECTURE.md](ARCHITECTURE.md)** - Planned Features section
235
244
  - **[CHANGELOG.md](CHANGELOG.md)** - Version history and release notes
236
-
237
- ---
238
-
239
- ## Feedback
240
-
241
- Have ideas for the roadmap? Questions about priorities?
242
-
243
- - **Early users:** Direct feedback via chat/email
244
- - **GitHub issues:** Feature requests and suggestions
245
- - **Team meetings:** Quarterly roadmap reviews
246
-
247
- Current focus: Getting v0.6.0 stable and ready for initial rollout to 2-3 users. 🚀
@@ -0,0 +1,16 @@
1
+ feedback from 0.6.1
2
+
3
+ For volume mapped sandbox flavor, make a new directory for the sandbox project.
4
+
5
+ Next, use npm init to create a package.json file if you don't have one already:
6
+
7
+ ```bash
8
+ npm init -y
9
+ ```
10
+
11
+ Then install buwp-local as a development dependency:
12
+
13
+ ```bash
14
+ npm install --save-dev @bostonuniversity/buwp-local
15
+ ```
16
+
@@ -50,7 +50,7 @@ async function destroyCommand(options) {
50
50
  try {
51
51
  // This is the actual docker compose down command that removes everything
52
52
  execSync(
53
- `docker compose -p ${projectName} -f ${composePath} down -v`,
53
+ `docker compose -p ${projectName} -f "${composePath}" down -v`,
54
54
  {
55
55
  cwd: composeDir,
56
56
  stdio: 'inherit'
@@ -85,7 +85,7 @@ function confirmDestroy(projectName) {
85
85
  console.log(chalk.yellow(`This will destroy project: ${chalk.bold(projectName)}`));
86
86
  console.log(chalk.yellow(' - Stop all containers'));
87
87
  console.log(chalk.yellow(' - Remove all containers'));
88
- console.log(chalk.yellow(' - Delete all volumes (including database data)\n'));
88
+ console.log(chalk.yellow(' - Delete all volumes (including database data) (except maybe not, please fix)\n'));
89
89
 
90
90
  rl.question(chalk.red('Are you sure you want to continue? (yes/no): '), (answer) => {
91
91
  rl.close();
@@ -36,7 +36,7 @@ async function logsCommand(options) {
36
36
 
37
37
  // Build docker compose logs command
38
38
  const composeDir = path.dirname(composePath);
39
- let command = `docker compose -p ${projectName} -f ${composePath} logs`;
39
+ let command = `docker compose -p ${projectName} -f "${composePath}" logs`;
40
40
 
41
41
  if (options.follow) {
42
42
  command += ' -f';
@@ -137,6 +137,34 @@ async function promptCredentialSetup(missingCreds) {
137
137
  return shouldSetup;
138
138
  }
139
139
 
140
+ // Check if image is accessible
141
+ async function checkImageAccess(imageName) {
142
+ try {
143
+ // Try to inspect image locally
144
+ execSync(`docker image inspect ${imageName}`, { stdio: 'pipe' });
145
+ return true; // Image exists locally
146
+ } catch {
147
+ // Image doesn't exist, try to pull
148
+ try {
149
+ console.log(chalk.gray(`Checking access to ${imageName}...`));
150
+ execSync(`docker pull ${imageName}`, { stdio: 'pipe' });
151
+ return true;
152
+ } catch (pullError) {
153
+ if (pullError.message.includes('unauthorized') ||
154
+ pullError.message.includes('denied')) {
155
+ console.log(chalk.yellow('\n⚠️ Cannot access container image\n'));
156
+ console.log('The BU WordPress image requires GitHub Packages authentication.\n');
157
+ console.log('Run this command to authenticate:\n');
158
+ console.log(chalk.cyan(' docker login ghcr.io\n'));
159
+ console.log('You will need a GitHub personal access token with "read:packages" scope.');
160
+ console.log('See: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry\n');
161
+ return false;
162
+ }
163
+ throw pullError; // Other error, let it surface
164
+ }
165
+ }
166
+ }
167
+
140
168
  async function startCommand(options) {
141
169
  console.log(chalk.blue('🚀 Starting BU WordPress local environment...\n'));
142
170
 
@@ -204,6 +232,18 @@ async function startCommand(options) {
204
232
  console.log(chalk.green('✓ Required credentials validated\n'));
205
233
  }
206
234
 
235
+ // Check image accessibility
236
+ console.log(chalk.gray('Checking container image access...'));
237
+ const imageAccessible = await checkImageAccess(config.image);
238
+
239
+ if (!imageAccessible) {
240
+ console.log(chalk.red('\n❌ Cannot proceed without access to container image.'));
241
+ console.log(chalk.gray('Please authenticate with GitHub Packages and try again.\n'));
242
+ process.exit(1);
243
+ }
244
+
245
+ console.log(chalk.green('✓ Container image accessible\n'));
246
+
207
247
  // Check /etc/hosts for hostname entry
208
248
  if (!hasShownHostsWarning(projectPath)) {
209
249
  const hostsCheck = checkHostsFile(config.hostname);
@@ -273,7 +313,7 @@ async function startCommand(options) {
273
313
  // This is the actual docker compose up command that starts everything
274
314
  // If there is a local .env file, it will take over the temp env file generated from the keychain, because it is specified last.
275
315
  execSync(
276
- `docker compose -p ${projectName} ${tempEnvFileFlag} ${envFileFlag} -f ${composePath} up -d`,
316
+ `docker compose -p ${projectName} ${tempEnvFileFlag} ${envFileFlag} -f "${composePath}" up -d`,
277
317
  {
278
318
  cwd: composeDir,
279
319
  stdio: 'inherit'
@@ -39,7 +39,7 @@ async function stopCommand() {
39
39
 
40
40
  try {
41
41
  execSync(
42
- `docker compose -p ${projectName} -f ${composePath} stop`,
42
+ `docker compose -p ${projectName} -f "${composePath}" stop`,
43
43
  {
44
44
  cwd: composeDir,
45
45
  stdio: 'inherit'
@@ -35,7 +35,7 @@ async function wpCommand(args, _options) {
35
35
  // Build docker compose exec command for WP-CLI
36
36
  const composeDir = path.dirname(composePath);
37
37
  const wpArgs = args.join(' ');
38
- const command = `docker compose -p ${projectName} -f ${composePath} exec wordpress wp ${wpArgs}`;
38
+ const command = `docker compose -p ${projectName} -f "${composePath}" exec wordpress wp ${wpArgs}`;
39
39
 
40
40
  // Execute WP-CLI command
41
41
  try {
@@ -152,16 +152,13 @@ function generateWordPressService(config, wpVolumeName) {
152
152
  environment.WORDPRESS_CONFIG_EXTRA = wpConfigExtra;
153
153
  }
154
154
 
155
- // Build volumes array
156
- const volumes = [`${wpVolumeName}:/var/www/html`];
157
-
158
- // Add custom mappings
159
- if (config.mappings && Array.isArray(config.mappings)) {
160
- config.mappings.forEach(mapping => {
161
- const localPath = path.resolve(mapping.local);
162
- volumes.push(`${localPath}:${mapping.container}`);
163
- });
164
- }
155
+ // Build volumes array with base WordPress volume
156
+ const customVolumes = (config.mappings || []).map(mapping => {
157
+ const localPath = path.resolve(mapping.local);
158
+ return `${localPath}:${mapping.container}`;
159
+ });
160
+
161
+ const volumes = [`${wpVolumeName}:/var/www/html`, ...customVolumes];
165
162
 
166
163
  return {
167
164
  image: config.image,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bostonuniversity/buwp-local",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Local WordPress development environment for Boston University projects",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
package/readme.md CHANGED
@@ -4,6 +4,15 @@ This repository contains resources and instructions for setting up a local WordP
4
4
 
5
5
  The package can be installed in a specific repo for development of that one package, or standalone for more general use, mapping local code into the container as needed.
6
6
 
7
+ > **Why buwp-local over VM sandboxes?**
8
+ >
9
+ > Traditional VM sandboxes require **monthly rebuilds that wipe your development code**. With buwp-local's Docker architecture, your code lives on your local filesystem while only WordPress core updates. This means:
10
+ > - ✅ **Keep your work** - No more monthly rebuild cycles that erase local changes
11
+ > - ✅ **Update independently** - Pull WordPress updates on your schedule, not a global calendar
12
+ > - ✅ **Instant rollback** - Switch between WordPress versions without losing work
13
+ >
14
+ > Learn more: [Migration from VM Sandboxes](docs/MIGRATION_FROM_VM.md)
15
+
7
16
  ## Quickstart for plugin or theme development
8
17
 
9
18
  1. **Install Docker**: Make sure you have [Docker Desktop](https://www.docker.com/products/docker-desktop) installed and running on your machine.