Skip to content

Phase 3 — All-in-one Docker test image (SQLite + Chromium, GHCR-published)#12

Open
edpittol wants to merge 16 commits into
mainfrom
4-phase-3-all-in-one-docker-test-image-sqlite-chromium-ghcr-published
Open

Phase 3 — All-in-one Docker test image (SQLite + Chromium, GHCR-published)#12
edpittol wants to merge 16 commits into
mainfrom
4-phase-3-all-in-one-docker-test-image-sqlite-chromium-ghcr-published

Conversation

@edpittol
Copy link
Copy Markdown
Member

Summary

Implements Phase 3 of the v0.1.0 design (ADR-0006): a single self-contained
Docker image — PHP, WordPress, WooCommerce, Storefront, SQLite, Chromium and
chromedriver all baked in — published to GHCR per PHP variant. Removes the
docker-compose stack and its driving Makefile targets.

Layered commits

  1. Smoke testtests/acceptance/ImageHealthCest.php. HPOS round-trip on SQLite, legacy order round-trip, homepage render, chromedriver liveness.
  2. WP bootstrapcomposer.json gains roots/wordpress-no-content, WooCommerce, Storefront and sqlite-database-integration via wpackagist + composer/installers. Bedrock-style public/index.php and public/wp-config.php adapt ABSPATH and WP_CONTENT_DIR for the new tree.
  3. Image + runtimeDockerfile (Alpine PHP, Chromium + chromedriver, SQLite, baked composer install + wp core install against the sqlite drop-in). codeception.yml enables BuiltInServerController, ChromeDriverController and the dev:start / dev:stop / wp:db:* / run:all commands. tests/acceptance.suite.yml switches WPDb to SQLite and WPWebDriver to localhost chromedriver. bin/test wraps docker run -v "\$PWD:/var/www/html".
  4. CI.github/workflows/build-test-runner.yml builds the matrix (php8.0, php8.4) and pushes both :php{N} and :vYYYY.MM-php{N} tags to GHCR on Dockerfile / composer / wp-config changes, weekly cron and manual dispatch.
  5. Cleanup — deletes Dockerfile.test, docker-compose.test.yml, docker-compose.local.yml, the docker-compose-driven Makefile and .env.test.
  6. DocsREADME.md documents bin/test, the raw docker run invocation, the GHCR tag scheme and the rebuild workflow. CHANGELOG.md records the additions, the suite migration to SQLite, and the docker-compose removal.

Out of scope (later phases)

  • Updating acceptance.yml to use the new image (Phase 4).
  • Updating the pre-push hook (Phase 4).
  • Plugin Module / Method Trait changes (Phase 5).
  • Removing orphan install scripts (install-woocommerce.sh, install-woocommerce-subscriptions.sh, setup-wordpress.sh) — flagged for a follow-up PR.

Test plan

  • build-test-runner workflow succeeds on PR for both PHP variants and pushes the image to GHCR.
  • docker run --rm ghcr.io/aztecweb/aztecweb-wp-browser-test-runner:php8.4 vendor/bin/codecept run acceptance ImageHealthCest passes all four smoke checks.
  • bin/test run acceptance ImageHealthCest works locally after composer install.
  • HPOS round-trip Cest still passes against the new SQLite-backed suite (OrderHPOSCest).
  • Legacy order Cest still passes (OrderCest).

Closes #4

edpittol added 6 commits May 19, 2026 15:22
Phase 3 acceptance criterion: ImageHealthCest exercises the four highest-risk
paths through the all-in-one test image — HPOS order round-trip on SQLite,
legacy order round-trip, homepage rendering with WooCommerce loaded, and a
basic chromedriver browser interaction.

Refs #4
composer.json now requires roots/wordpress-no-content, WooCommerce, Storefront
and sqlite-database-integration via wpackagist + composer/installers, routed
into a Bedrock-style public/ layout (public/wp + public/packages). public/
ships a thin index.php bootstrap and a wp-config.php adapted for the custom
ABSPATH/WP_CONTENT_DIR. wp-cli.yml points at the new core install path.

Refs #4
Dockerfile builds an Alpine PHP image with Chromium + chromedriver, SQLite,
WP-CLI and a baked composer install of the WordPress tree, then runs wp core
install against the sqlite-database-integration drop-in so the container ships
with a fully bootstrapped site. codeception.yml enables wp-browser's
BuiltInServerController and ChromeDriverController extensions plus the
dev:start/dev:stop/dev:info/wp:db:* and run:original/run:all commands. The
acceptance suite now targets SQLite via WPDb and localhost chromedriver via
WPWebDriver. bin/test is a thin wrapper around `docker run -v "$PWD:/var/www/html"`.

Refs #4
New workflow builds the all-in-one test image for the PHP 8.0 and PHP 8.4
variants and pushes to GHCR on Dockerfile / composer / wp-config changes,
weekly cron (so WordPress and WooCommerce updates land regularly), and manual
dispatch. Each build emits both a moving `:php{N}` tag and a per-content
`:vYYYY.MM-php{N}` tag so CI workflows can pin to an explicit content version.

Refs #4
The all-in-one Docker image is now the only supported test environment, so
Dockerfile.test, the two docker-compose service stacks, the docker-compose-
driven Makefile targets and the .env.test file driven by them are obsolete.

Refs #4
README explains the bin/test wrapper, the raw `docker run` invocation, the
GHCR tag scheme (`:php{N}` vs `:vYYYY.MM-php{N}`), the AZTEC_TEST_IMAGE
override and how the build-test-runner workflow refreshes the image.
CHANGELOG records the Phase 3 additions, the codeception.yml / suite.yml
moves to SQLite + chromedriver, and the removal of the docker-compose stack.

Refs #4
Comment thread public/wp-config.php
Comment thread Dockerfile Outdated
Comment thread Dockerfile Outdated
Comment thread Dockerfile Outdated
Comment thread Dockerfile Outdated
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The image will contain PHP and wp-browser dependencies. Don't consider the app code on it.

I liked the idea of generate new images. Bout I would prefer to discuss more about the workflow in another issue. So take this discussion for a new issue and remove the related code.

For now, consider to build a new image manually. Consider the full date (including seconds) as content_version. No input needed. And the image should be called ${{ github.repository }}-runner.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #13 scope is for generate new images automatically. In the command below, I would want to say that the image would be built with a manual trigger.

For now, consider to build a new image manually. Consider the full date (including seconds) as content_version. No input needed. And the image should be called ${{ github.repository }}-runner.

This deletion must be reverted and #13 specification must be updated.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted the deletion in b9bed81. The restored workflow is workflow_dispatch-only (no push, no cron, no input), image name ${{ github.repository }}-runner, content version v$(date -u +%Y%m%dT%H%M%SZ) (UTC datetime down to the second), matrix PHP 8.0 + 8.4. Each run pushes both $aztecweb-wp-browser-runner:php{N} (moving) and $aztecweb-wp-browser-runner:vYYYYMMDDThhmmssZ-php{N} (immutable). Trigger with the Actions UI or gh workflow run build-test-runner.yml.

Issue #13 rescoped accordingly: its title is now "Test runner image: automatic build & publish workflow", with manual marked as already-shipped in PR #12 and the open questions narrowed to triggers (push/cron) and matrix breadth. README and CHANGELOG updated in 79f61ef.

edpittol added 5 commits May 19, 2026 22:16
The build & publish workflow needs more design discussion (manual vs cron vs
push triggers, tag naming, content-version scheme, whether to keep moving
:php{N} pointers, image-naming). Removing the half-baked workflow from this
PR so the Dockerfile lands clean; the workflow conversation lives in #13.

Refs #4, #13
The plugin's documented switch is the DB_ENGINE constant — when set to
'sqlite' the drop-in routes WP to SQLite. wp-config.php now defines it
explicitly (default 'sqlite', env-overridable for future MySQL targeting).

Refs #4
Image now ships only PHP, Chromium, chromedriver, SQLite and Composer. The
library source, vendor/ and public/ WordPress tree come from the bind-mount
at /var/www/html — no COPY of the repo into the image, no in-image composer
install or wp core install. WP-CLI is a Composer dependency
(wp-cli/wp-cli-bundle); /var/www/html/vendor/bin is on PATH so `wp` works
once vendor/ is present. The image runs as a non-root `runner` user, so
WP_CLI_ALLOW_ROOT is gone too. bin/test is now a pure pass-through wrapper
that defaults to `codecept run` when called with no arguments.

Refs #4
The bootstrap sequence (db.copy drop-in, wp core install, plugin activation,
theme activation, HPOS sync) now lives in resources/install.sh and runs
against the mounted source tree at container start time. Plugin activations
are folded into a single `wp plugin activate woocommerce sqlite-database-integration`
call, the redundant HPOS enable/sync/disable toggle is dropped (one sync is
enough to create the wc_orders schema), and the whole script short-circuits
if `wp core is-installed` already.

Refs #4
README explains the new model: the image carries PHP + Chromium + SQLite +
Composer, while WordPress, WooCommerce and the library tree come from the
bind-mount. The "first-time setup" step pair (composer install + install.sh)
is documented up front, and the rebuild/workflow paragraph is replaced with
a pointer to #13. CHANGELOG records the slimmed image, the new install
script, the wp-cli/wp-cli-bundle dependency and the DB_ENGINE switch.

Refs #4
@edpittol
Copy link
Copy Markdown
Member Author

Pushed five layered commits (de6deb5..c099425) addressing the pending review comments. Mapping for traceability — your review is still in PENDING state so I'm leaving the response here rather than inline.

Pending comment Resolution Commit
public/wp-config.phpSQLite as database provider was not consider to be set. Check about DB_ENGINE define('DB_ENGINE', $envOr('DB_ENGINE', 'sqlite')) added (default sqlite, env-overridable) f10a78c
Dockerfile:11WP-CLI shouldn't be allowed to run as root Dropped WP_CLI_ALLOW_ROOT; added a non-root runner user (uid 1000); USER runner before WORKDIR 6f17fef
Dockerfile:66WP-CLI should be a Composer dependency. Add vendor/bin to the $PATH Removed curl wp-cli.phar; added wp-cli/wp-cli-bundle to require-dev; ENV PATH="/var/www/html/vendor/bin:${PATH}" 6f17fef
Dockerfile:91Move the installation to a shell script. Consider merge with setup-wordpress.sh. The file must stays at resources/install.sh. Try to optimize the maximum the number of calls to WP-CLI New resources/install.sh — idempotent (wp core is-installed short-circuit), 4 wp-cli calls instead of 8 (wp plugin activate woocommerce sqlite-database-integration combined; redundant HPOS enable/sync/disable dropped — one wp wc hpos sync is enough to create the wc_orders schema) 0a05dae
Dockerfile:74Don't include the source code in the image. It always must be mounted in the container initialization Dropped COPY . ., the composer install and the wp core install step from the Dockerfile. Image now ships only PHP, Chromium, chromedriver, SQLite and Composer. Source (vendor/, public/, src/, tests/) arrives via the bind-mount; resources/install.sh runs once per workspace to bootstrap the SQLite DB 6f17fef + 0a05dae
.github/workflows/build-test-runner.ymlTake this discussion for a new issue and remove the related code. Image named ${{ github.repository }}-runner. Full date as content_version. No input. Workflow file deleted. Discussion moved to #13 with the directives captured (manual build, slim contents, image naming, timestamp tag, no input). README also updated: image reference now …wp-browser-runner:php{N} and points at #13 for build/publish de6deb5 + c099425

Refreshed README documents the new bootstrap flow: bin/test composer install && bin/test bash resources/install.sh && bin/test. bin/test is now a pure pass-through wrapper — defaults to codecept run when called with no arguments.

Comment thread Dockerfile Outdated
edpittol added 4 commits May 19, 2026 22:56
…actions/runner

Moving off Alpine so the suggested `adduser --disabled-password --gecos ""
--uid 1001 runner` command (matching the actions/runner image convention)
applies verbatim — Alpine's BusyBox adduser doesn't accept those long flags.
The apk package list translates to apt-get equivalents: `chromium` +
`chromium-driver` (the Debian chromedriver lands at /usr/bin/chromedriver,
which .env.example now points at), the libpng/libjpeg/libzip dev headers,
sqlite3 + libsqlite3-dev, plus the standard build chain for PHP's gd/intl/
pdo_sqlite/zip extensions. Build-only -dev packages are purged after the
extension install so the final image stays lean.

Refs #4
This workflow is now `workflow_dispatch`-only — no push trigger, no cron, no
input. Each manual run derives an immutable content version from the UTC
build timestamp (vYYYYMMDDThhmmssZ) and tags the GHCR image as both
`${repo}-runner:php{N}` (moving) and `${repo}-runner:vYYYYMMDDThhmmssZ-php{N}`
(immutable). Matrix covers PHP 8.0 and 8.4. Automatic triggers are scoped to
#13 going forward.

Refs #4, #13
README's "Image tags" section now describes the immutable timestamp tag
scheme and tells maintainers to fire the workflow from the Actions UI (or
`gh workflow run build-test-runner.yml`). CHANGELOG records the manual
workflow and points at #13 for automatic-trigger work.

Refs #4, #13
Keep the php:cli-alpine base (smaller image, the option ADR-0006 prefers)
and translate the actions/runner-style adduser invocation to the BusyBox
flags Alpine ships with: -D (disabled password), -g "" (empty GECOS field),
-u 1001 (UID 1001 to match actions/runner). chromedriver returns to the
Alpine chromium-chromedriver location at /usr/lib/chromium/chromedriver.

Refs #4
@edpittol
Copy link
Copy Markdown
Member Author

Instruct Claude via CLAUDE.md how to run the project from bin/tests and how to build the image.

WordPress and the wider PHP ecosystem still emit a steady stream of
deprecation notices on PHP 8.x; reporting them as test failures adds noise
without surfacing actual regressions in the library. The image now drops a
tiny ini snippet at /usr/local/etc/php/conf.d/error-reporting.ini setting
`error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED`, so everything
except deprecation warnings still surfaces.

Refs #4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phase 3 — All-in-one Docker test image (SQLite + Chromium, GHCR-published)

1 participant