Skip to content

Commit 784fae3

Browse files
retlehsclaude
andauthored
🐳 Publish Acorn dev container to GHCR and optimize setup (#477)
* 🔥 Remove Minio, Selenium, Soketi, and Meilisearch services from devcontainer * 📝 Add dev container README * ♻️ Refactor devcontainer setup and add customization - Add customizable WordPress site title (defaults to "Acorn Testing") - Fix twentytwentyfour → twentytwentyfive theme removal - Use composer create-project for proper Sage theme installation - Add automatic bun build step after Sage installation - Fix chown permissions scope from /roots to /roots/app - Remove sudo from chmod commands in devcontainer.json - Add devcontainer CLI usage documentation to README - Document site title and repository customization options 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * 🔧 Use composer require instead of create-project for Sage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * ♻️ Update routing tests to work with Sage theme - Refactor routing tests from mu-plugin approach to Sage theme integration - Add proper backup/restore of Sage functions.php with cleanup in tearDown - Add COMPOSER_ROOT_VERSION env var to handle version constraints cleanly - Update GitHub Actions to test with Sage theme activation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * ⚡ Skip Xdebug installation in CI environments - Detect CI environment and skip Xdebug install when CI=true - Improves CI build speed and test performance - Maintains full debugging capabilities for local development 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * 🐛 Fix devcontainer build timeout and remove legacy soil plugin - Remove Git feature that was causing build timeouts locally - Remove soil plugin activation (legacy code) - Export COMPOSER_ROOT_VERSION in setup script to ensure Sage v11 installation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * 🔧 Fix Sage v11 installation and remove duplicate Acorn - Remove existing Acorn before re-adding with version alias - Force Sage v11 installation by aliasing local Acorn as 5.0.x-dev - Remove Sage's vendored Acorn to use Bedrock's version - Add destroy.sh script for thorough cleanup * 🐛 Fix CI verification step after routing test refactor The /test/ route no longer exists since we moved from mu-plugin to Sage theme integration * 🔧 Remove unused COMPOSER_ROOT_VERSION environment variable No longer needed since we use dynamic version aliasing during setup * 🚀 Add dev container publishing workflow - Create devcontainer.yml workflow to publish image to GHCR - Update integration.yml to use published image cache - Publishes ghcr.io/roots/acorn-devcontainer:latest from main branch * 🔧 Enable dev container publishing on feature branch for testing - Add devcontainer-updates branch to publishing trigger - Tag images with branch name for testing - Update integration workflow to use branch-tagged cache * 🔥 Trigger dev container workflow * 🚀 Prepare dev container workflows for production - Remove branch-specific testing configuration - Publish workflow now only runs on main branch - Integration workflow uses :latest cache from GHCR - Clean up testing artifacts from Dockerfile --------- Co-authored-by: Claude <[email protected]>
1 parent e61b024 commit 784fae3

File tree

11 files changed

+231
-132
lines changed

11 files changed

+231
-132
lines changed

.devcontainer/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
3939
zip \
4040
# && pecl install imagick-3.7.0 && docker-php-ext-enable imagick \ # https://github.com/Imagick/imagick/issues/689
4141
&& pecl install -o -f redis && docker-php-ext-enable redis \
42-
&& pecl install xdebug-3.4.0 && docker-php-ext-enable xdebug \
42+
&& if [ -z "$CI" ]; then pecl install xdebug-3.4.0 && docker-php-ext-enable xdebug; fi \
4343
&& apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
4444

4545
# Install composer

.devcontainer/README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Acorn Development Container
2+
3+
This dev container provides a full WordPress development environment for working on Acorn, Acorn packages, and testing Sage themes.
4+
5+
## Quick Start
6+
7+
### VS Code (Recommended)
8+
1. Open in VS Code with Dev Containers extension
9+
2. Wait for container build and WordPress installation
10+
3. Access site at http://localhost:8080
11+
12+
### Command Line
13+
```bash
14+
# Install devcontainer CLI
15+
npm install -g @devcontainers/cli
16+
17+
# Start dev container
18+
devcontainer up --workspace-folder .
19+
20+
# Execute commands in container
21+
devcontainer exec --workspace-folder . wp --info
22+
```
23+
24+
## Services
25+
26+
| Service | URL/Port | Purpose |
27+
|---------|----------|---------|
28+
| WordPress | http://localhost:8080 | Main application |
29+
| Mailpit | http://localhost:8025 | Email testing UI |
30+
| Database | localhost:3306 | MariaDB 10 |
31+
| Redis | localhost:6379 | Object caching |
32+
33+
## Default Credentials
34+
35+
- **WordPress Admin**: `admin` / `password`
36+
- **Database**: `database_name` / `database_user` / `database_password`
37+
38+
## Common Commands
39+
40+
```bash
41+
# WordPress CLI
42+
wp plugin list
43+
wp theme activate sage
44+
wp acorn optimize:clear
45+
46+
# Composer (Acorn)
47+
cd /roots/acorn
48+
composer test
49+
50+
# Build tools (themes)
51+
cd /roots/app/public/content/themes/sage
52+
bun install
53+
bun run build
54+
bun run dev
55+
```
56+
57+
## Project Structure
58+
59+
- `/roots/acorn` - Your local Acorn repository
60+
- `/roots/app` - WordPress installation (Bedrock)
61+
- `/roots/app/public/content/themes/` - WordPress themes
62+
- `/roots/app/public/content/plugins/` - WordPress plugins
63+
64+
## Features
65+
66+
- **PHP 8.4** with Xdebug configured
67+
- **Composer** and **WP-CLI** pre-installed
68+
- **Volta** for Node.js management
69+
- **Bun** for fast JavaScript builds
70+
- Auto-links themes/plugins based on `composer.json` type
71+
- Git dirty prompt indicator
72+
73+
## Customization
74+
75+
**WordPress Site Title**: Defaults to "Acorn Testing". Override with:
76+
```bash
77+
WP_SITE_TITLE="My Custom Site"
78+
```
79+
80+
**WordPress Repository**: Clones Bedrock by default. To use a different setup:
81+
```bash
82+
REPOSITORY_URL=https://github.com/your/repo.git
83+
```
84+
85+
## Troubleshooting
86+
87+
- **Port conflicts**: Change ports in `.env` (e.g., `FORWARD_WEB_PORT=8081`)
88+
- **Rebuild container**: `Dev Containers: Rebuild Container` in VS Code
89+
- **Database issues**: Container includes automatic database reset on setup

.devcontainer/destroy.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
3+
# Kill and remove all devcontainer containers (more aggressive)
4+
echo "Force stopping all devcontainer containers..."
5+
docker ps -q | xargs -r docker kill 2>/dev/null || true
6+
7+
echo "Removing all containers..."
8+
docker ps -aq | xargs -r docker rm -f 2>/dev/null || true
9+
10+
# Remove all devcontainer volumes
11+
echo "Removing all devcontainer volumes..."
12+
docker volume ls -q | grep -E "acorn_devcontainer|devcontainer_acorn|devcontainer" | xargs -r docker volume rm -f 2>/dev/null || true
13+
14+
# Clean up any dangling resources
15+
echo "Cleaning up dangling resources..."
16+
docker system prune -f --volumes 2>/dev/null || true
17+
18+
# Wait a moment for ports to be released
19+
sleep 2
20+
21+
# Check if anything is still running on port 8080
22+
if lsof -i :8080 >/dev/null 2>&1; then
23+
echo "Warning: Something is still running on port 8080"
24+
lsof -i :8080
25+
else
26+
echo "Port 8080 is clear"
27+
fi
28+
29+
echo "Devcontainer cleanup complete!"

.devcontainer/devcontainer.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,11 @@
1313
"userGid": "1000",
1414
"upgradePackages": "true"
1515
},
16-
"ghcr.io/devcontainers/features/sshd:1": {},
17-
"ghcr.io/devcontainers/features/git:1": {
18-
"version": "latest"
19-
}
16+
"ghcr.io/devcontainers/features/sshd:1": {}
2017
},
2118
"initializeCommand": "[ ! -f '.devcontainer/.env' ] && cp '.devcontainer/config/app/.env.example' '.devcontainer/.env' || true",
22-
"onCreateCommand": "sudo chmod +x ./${localWorkspaceFolderBasename}/.devcontainer/install.sh && ./${localWorkspaceFolderBasename}/.devcontainer/install.sh",
23-
"postCreateCommand": "sudo chmod +x ./${localWorkspaceFolderBasename}/.devcontainer/setup.sh && ./${localWorkspaceFolderBasename}/.devcontainer/setup.sh",
19+
"onCreateCommand": "chmod +x ./${localWorkspaceFolderBasename}/.devcontainer/install.sh && ./${localWorkspaceFolderBasename}/.devcontainer/install.sh",
20+
"postCreateCommand": "chmod +x ./${localWorkspaceFolderBasename}/.devcontainer/setup.sh && ./${localWorkspaceFolderBasename}/.devcontainer/setup.sh",
2421
"forwardPorts": [],
2522
"containerEnv": {
2623
"APP_SERVICE": "acorn.test",

.devcontainer/docker-compose.yml

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -77,36 +77,6 @@ services:
7777
retries: 3
7878
timeout: 5s
7979

80-
storage:
81-
image: 'minio/minio:latest'
82-
ports:
83-
- '${FORWARD_MINIO_PORT:-9000}:9000'
84-
- '${FORWARD_MINIO_CONSOLE_PORT:-8900}:8900'
85-
environment:
86-
MINIO_ACCESS_KEY: '${MINIO_ACCESS_KEY}'
87-
MINIO_SECRET_KEY: '${MINIO_SECRET_KEY}'
88-
volumes:
89-
- 'storage:/data'
90-
networks:
91-
- acorn
92-
healthcheck:
93-
test:
94-
[
95-
'CMD',
96-
'curl',
97-
'-f',
98-
'http://localhost:9000/minio/health/live'
99-
]
100-
retries: 3
101-
timeout: 5s
102-
103-
browser:
104-
image: 'selenium/standalone-chrome'
105-
extra_hosts:
106-
- 'host.docker.internal:host-gateway'
107-
networks:
108-
- acorn
109-
11080
mail:
11181
image: 'axllent/mailpit:latest'
11282
ports:
@@ -115,40 +85,6 @@ services:
11585
networks:
11686
- acorn
11787

118-
websocket:
119-
image: 'quay.io/soketi/soketi:latest-16-alpine'
120-
environment:
121-
SOKETI_DEBUG: '${SOKETI_DEBUG:-1}'
122-
SOKETI_METRICS_SERVER_PORT: '9601'
123-
SOKETI_DEFAULT_APP_ID: '${PUSHER_APP_ID}'
124-
SOKETI_DEFAULT_APP_KEY: '${PUSHER_APP_KEY}'
125-
SOKETI_DEFAULT_APP_SECRET: '${PUSHER_APP_SECRET}'
126-
ports:
127-
- '${PUSHER_PORT:-6001}:6001'
128-
- '${PUSHER_METRICS_PORT:-9601}:9601'
129-
networks:
130-
- acorn
131-
132-
search:
133-
image: 'getmeili/meilisearch:latest'
134-
ports:
135-
- '${FORWARD_MEILISEARCH_PORT:-7700}:7700'
136-
volumes:
137-
- 'search:/meili_data'
138-
networks:
139-
- acorn
140-
healthcheck:
141-
test:
142-
[
143-
'CMD',
144-
'wget',
145-
'--no-verbose',
146-
'--spider',
147-
'http://localhost:7700/health'
148-
]
149-
retries: 3
150-
timeout: 5s
151-
15288
networks:
15389
acorn:
15490
driver: bridge
@@ -157,5 +93,3 @@ volumes:
15793
app:
15894
database:
15995
cache:
160-
storage:
161-
search:

.devcontainer/install.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fi
2323

2424
REPOSITORY_URL="${REPOSITORY_URL:-'https://github.com/roots/bedrock.git'}"
2525

26-
sudo chown -R vscode:www-data /roots
26+
sudo chown -R vscode:www-data /roots/app
2727
cd /roots/app
2828

2929
# if composer.json already exists, exit early
@@ -91,18 +91,18 @@ else
9191
&& composer require -d /roots/app $(cat "${WORKSPACE_FOLDER}/composer.json" | jq '.name' | tr -d '"') --no-interaction -W --ignore-platform-reqs
9292
fi
9393

94-
composer remove -d /roots/app wpackagist-theme/twentytwentyfour
94+
composer remove -d /roots/app wpackagist-theme/twentytwentyfive
9595
composer require -d /roots/app roots/acorn-prettify -W
9696

9797
# Set filesystem permissions
98-
sudo chown -R vscode:www-data /roots/app
98+
sudo chown -R vscode:www-data /roots/app/public/content
9999
sudo find /roots/app/ -type d -exec chmod g+s {} \;
100100
sudo chmod g+w -R /roots/app
101101

102102
cd /roots
103103

104104
# wp-cli.yml file
105-
cat <<WPCLI > /roots/wp-cli.yml
105+
sudo tee /roots/wp-cli.yml > /dev/null <<WPCLI
106106
path: /roots/app/public/wp
107107
server:
108108
docroot: /roots/app/public

.devcontainer/setup.sh

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ volta install bun
1111

1212
WORKSPACE_FOLDER="${WORKSPACE_FOLDER:-"${PWD##*/}"}"
1313

14+
# WordPress site title - defaults to "Acorn Testing", can be overridden
15+
WP_SITE_TITLE="${WP_SITE_TITLE:-"Acorn Testing"}"
16+
1417
# source our application env vars to be used here
1518
. '/roots/app/.env';
1619

@@ -31,12 +34,26 @@ if [ -f 'package.json' ]; then
3134
fi
3235

3336
wp db reset --yes
34-
wp core install --url="${WP_HOME}" --title="Roots Test" --admin_user="admin" --admin_email="[email protected]" --admin_password="password1" --skip-email
37+
wp core install --url="${WP_HOME}" --title="${WP_SITE_TITLE}" --admin_user="admin" --admin_email="[email protected]" --admin_password="password" --skip-email
3538

36-
# Add sage if there are no themes
37-
if [ ! "$(ls -d $(wp theme path --skip-plugins --skip-themes 2>/dev/null)/*/)" ]; then
38-
composer require -d /roots/app roots/sage
39+
# Add sage if it's not active
40+
if ! wp theme status sage --skip-plugins --skip-themes 2>/dev/null | grep -q "^sage.*active"; then
41+
# Only require sage if it doesn't exist
42+
if ! wp theme is-installed sage --skip-plugins --skip-themes 2>/dev/null; then
43+
# Remove existing Acorn to replace with version-aliased one
44+
composer remove roots/acorn --no-update
45+
# Add our local Acorn repository with version alias
46+
composer config repositories.acorn '{"type": "path", "url": "/roots/acorn", "options": {"versions": {"roots/acorn": "5.0.x-dev"}}}'
47+
# Install Sage v11 with our aliased Acorn
48+
composer require "roots/sage:^11.0" "roots/acorn:5.0.x-dev" -W
49+
fi
3950
wp theme activate sage
51+
# Build the Sage theme
52+
cd $(wp theme path --skip-plugins --skip-themes 2>/dev/null)/sage
53+
# Remove Sage's vendored Acorn to use Bedrock's version
54+
composer remove roots/acorn --no-update
55+
composer update --no-install
56+
bun install && bun run build
4057
fi
4158

4259
install_theme() {
@@ -55,5 +72,4 @@ find $(wp theme path --skip-plugins --skip-themes 2>/dev/null) -mindepth 1 -maxd
5572
while read theme; do install_theme "$theme"; done
5673

5774
wp dotenv salts regenerate --skip-plugins --skip-themes 2>/dev/null || true
58-
wp plugin activate soil --skip-plugins --skip-themes 2>/dev/null || true
5975
wp rewrite structure '%postname%' --hard --skip-plugins --skip-themes 2>/dev/null

.github/workflows/devcontainer.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Publish Dev Container
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- '.devcontainer/**'
8+
workflow_dispatch:
9+
10+
jobs:
11+
build-and-push:
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
packages: write
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Log in to GitHub Container Registry
21+
uses: docker/login-action@v3
22+
with:
23+
registry: ghcr.io
24+
username: ${{ github.actor }}
25+
password: ${{ secrets.GITHUB_TOKEN }}
26+
27+
- name: Build and push Dev Container
28+
uses: devcontainers/[email protected]
29+
with:
30+
imageName: ghcr.io/roots/acorn-devcontainer
31+
cacheFrom: ghcr.io/roots/acorn-devcontainer
32+
push: always

.github/workflows/integration.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@ jobs:
1616
uses: devcontainers/[email protected]
1717
with:
1818
configFile: .devcontainer/devcontainer.json
19+
cacheFrom: ghcr.io/roots/acorn-devcontainer
20+
push: never
1921
runCmd: |
20-
cd /roots/app
21-
composer install
22-
# ???
23-
composer remove roots/acorn
24-
composer require roots/acorn --no-interaction
25-
composer require --dev nunomaduro/collision
26-
composer require --dev spatie/laravel-ignition
27-
# ???
22+
# Wait for database to be ready
2823
while ! mysqladmin ping -h"database" --silent; do
2924
sleep 1
3025
done
31-
wp core install --url=http://web:8080 --title=Acorn --admin_user=admin --admin_password=admin [email protected] --skip-email --allow-root
26+
# Ensure WordPress is installed
27+
cd /roots/app
28+
wp core install --url=http://web:8080 --title="Acorn Testing" --admin_user=admin --admin_password=password [email protected] --skip-email --allow-root
29+
# Ensure Sage theme is activated
30+
wp theme activate sage
31+
# Clear optimization cache
3232
wp acorn optimize:clear
33-
33+
# Run the routing integration tests
3434
cd /roots/acorn
3535
composer install
3636
composer run-script test tests/Integration/Routing
3737
38-
- name: Verify routes
38+
- name: Verify site is running
3939
run: |
40-
curl -s http://localhost:8080/test/ | grep "Howdy"
40+
curl -I http://localhost:8080 | grep "200 OK"

tests/Integration/Routing/RoutingTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
$response = $client->request('GET', 'http://web:8080/non-existent-'.time());
4545
expect($response->getStatusCode())->toBe(404);
46-
expect((string) $response->getBody())->toContain('Page not found');
46+
expect((string) $response->getBody())->toContain('Not Found');
4747
expect((string) $response->getBody())->toHaveBodyClass('error404');
4848
});
4949

0 commit comments

Comments
 (0)