Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ config:
| `phpunit.xml.dist` | PHPUnit 13 strict mode: `requireCoverageMetadata`, `failOnNotice`, `failOnWarning`, `failOnDeprecation`. |
| `compose.yml` / `Dockerfile` / `.devcontainer/` | The containerized toolchain (Composer, PHPUnit, Mago, Infection, PHPBench, roave BC-check). |
| `src/App/src/ConfigProvider.php` | The application's wiring entry point, declared under `extra.laminas.config-provider`. |
| `config/` | The Mezzio config: the aggregator (`config.php`), the container (`container.php`), the middleware pipeline (`pipeline.php`), and the layered `autoload/` files. |
| `public/index.php` | The front controller — `public/` is the document root. |
| `bin/clear-config-cache.php` | Drops the aggregated config cache; wired as `composer clear-config-cache`. |
| `data/cache/` | The config cache target, held in git by `.gitkeep` only. |

`mago.toml`, `phpunit.xml.dist`, `.gitattributes`, `codecov.yml`, `Dockerfile`,
`.dockerignore`, `infection.json5.dist`, `phpbench.json.dist` and devcontainer config are
Expand Down Expand Up @@ -60,5 +64,14 @@ docker compose exec tooling mago lint
docker compose down
```

To boot the application itself:

```shell
composer serve # php -S 0.0.0.0:8080 -t public/
```

No routes are registered yet, so every request answers `404` from Mezzio's default handler —
that is the expected state until the components are wired in and a route provider exists.

Packages whose tests need MySQL uncomment the `mysql` service in `compose.yml`, mirroring the
`db_image` / `db_env_json` / `db_port` values they declare in `webware-ci.json`.
53 changes: 53 additions & 0 deletions bin/clear-config-cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Webware package.
*
* Copyright (c) 2026 Joey Smith <jsmith@webinertia.net>
* and contributors.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

chdir(__DIR__ . '/../');

require 'vendor/autoload.php';

$config = include 'config/config.php';

if (! isset($config['config_cache_path'])) {
echo 'No configuration cache path found' . PHP_EOL;

exit(0);
}

if (! file_exists($config['config_cache_path'])) {
printf(
"Configured config cache file '%s' not found%s",
$config['config_cache_path'],
PHP_EOL,
);

exit(0);
}

if (false === unlink($config['config_cache_path'])) {
printf(
"Error removing config cache file '%s'%s",
$config['config_cache_path'],
PHP_EOL,
);

exit(1);
}

printf(
"Removed configured config cache file '%s'%s",
$config['config_cache_path'],
PHP_EOL,
);

exit(0);
135 changes: 73 additions & 62 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# ---------------------------------------------------------------------------
# Webware alignment local development environment
# Webware application development environment
#
# A persistent, interactive development environment that runs the full Webware
# toolchain (Composer, PHPUnit, Mago, Infection, PHPBench, roave BC-check)
# inside a container, so the host never needs a native PHP install. Works
# identically on Windows, WSL, Linux, and macOS.
# Two things live here:
#
# 1. The backing services the application talks to — MySQL, phpMyAdmin and
# Mailpit — each published to the host, because the application's PHP runs
# on the host and connects to them over 127.0.0.1.
# 2. The `tooling` container, which runs the full Webware toolchain (Composer,
# PHPUnit, Mago, Infection, PHPBench, roave BC-check) for anyone who wants
# the toolchain containerised rather than native.
#
# This compose file is the single source of truth for the environment. Two
# ways to use it:
Expand All @@ -21,13 +25,12 @@
# docker compose exec tooling mago lint
# docker compose down # stop it
#
# Packages whose tests need MySQL uncomment the `mysql` service below (and the
# `phpmyadmin` web UI if wanted), plus the `depends_on` block on `tooling`. The
# `mysql` service mirrors the `db_image` package parameter used by CI, and is
# reachable from `tooling` as host `mysql` on port 3306 — matching the PhpDb
# `mysql.local.php` connection convention. Packages that need a different
# engine add an equivalent service here (postgres, mariadb, ...) mirroring
# their own `db-image` parameter.
# Services are addressed from the host on 127.0.0.1: MySQL 3306, Mailpit SMTP
# 1025 / UI 8025, phpMyAdmin 8082. That is why config/autoload/mysql.local.php
# uses host 127.0.0.1 rather than the compose service name, and why phpMyAdmin
# does not take 8080 — that port belongs to the application (`composer serve`).
# The service values mirror the `db_image` / `db_env_json` / `db_port` package
# parameters used by CI.
# ---------------------------------------------------------------------------

services:
Expand Down Expand Up @@ -64,61 +67,69 @@ services:
# Windows) so downloads survive container rebuilds. It is only a cache
# — the developer's real artifacts all live on the host.
- composer-cache:/tmp/composer-cache
# Uncomment when the package's tests need MySQL (see the `mysql` service
# below). Ensures the database is ready before the shell attaches.
# depends_on:
# mysql:
# condition: service_healthy
# MySQL must be healthy before the shell attaches (see the `mysql` service
# below).
depends_on:
mysql:
condition: service_healthy
working_dir: /app

# -------------------------------------------------------------------------
# MySQL (optional) — uncomment this whole block for packages whose tests
# need a MySQL database (e.g. webware-acl via php-db/phpdb-mysql).
#
# Mirror the spec's `db_image` / `db_env_json` / `db_port` Package Parameters
# so the dev database matches CI. Point the package's local DB config (e.g.
# config/autoload/mysql.local.php) at host `mysql`, port 3306, using the
# credentials below. Adjust MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORD to
# the package's test-database convention. MYSQL_ALLOW_EMPTY_PASSWORD keeps
# the test-only database free of a root password and in sync with the CI
# `db_env_json` — remove it if the package pins a root password instead.
# MySQL — mirrors the CI `db_image` / `db_env_json` / `db_port` parameters so
# the dev database matches CI. Reachable from `tooling` as host `mysql` on
# port 3306, which is where config/autoload/mysql.local.php points.
# -------------------------------------------------------------------------
mysql:
image: mysql:9.7
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
MYSQL_DATABASE: webware
MYSQL_USER: webware
MYSQL_PASSWORD: webware
ports:
# Published so the database resolves from the host (127.0.0.1:3306);
# inside the compose network it is also reachable as host `mysql`.
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 30
volumes:
# Named volume keeps the data on the fast Linux filesystem and
# survives `docker compose down` (use `down -v` to wipe it).
- mysql-data:/var/lib/mysql
# -------------------------------------------------------------------------
# phpMyAdmin — web UI for the `mysql` service above, published on 8082 so the
# application keeps 8080 for itself (`composer serve`). Reachable at
# http://localhost:8082 (log in as root with an empty password, or with the
# MYSQL_USER / MYSQL_PASSWORD credentials).
# -------------------------------------------------------------------------
phpmyadmin:
image: phpmyadmin:latest
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_USER: root
PMA_PASSWORD: ""
ports:
- "8082:80"
depends_on:
mysql:
condition: service_healthy

# -------------------------------------------------------------------------
# Mailpit — catches outgoing mail for webware-mailer. Reachable from
# `tooling` as host `mailpit` on port 1025; the web UI is at
# http://localhost:8025.
# -------------------------------------------------------------------------
# mysql:
# image: mysql:9.7
# environment:
# MYSQL_ROOT_HOST: "%"
# MYSQL_ALLOW_EMPTY_PASSWORD: "true"
# MYSQL_DATABASE: webware
# MYSQL_USER: webware
# MYSQL_PASSWORD: webware
# healthcheck:
# test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
# interval: 5s
# timeout: 5s
# retries: 30
# volumes:
# # Named volume keeps the data on the fast Linux filesystem and
# # survives `docker compose down` (use `down -v` to wipe it).
# - mysql-data:/var/lib/mysql
#
# # phpMyAdmin — optional web UI for the `mysql` service above. Reachable at
# # http://localhost:8080 (log in as root with an empty password, or with
# # the MYSQL_USER / MYSQL_PASSWORD credentials). Uncomment alongside
# # `mysql`.
# phpmyadmin:
# image: phpmyadmin:latest
# environment:
# PMA_HOST: mysql
# PMA_PORT: 3306
# PMA_USER: root
# PMA_PASSWORD: ""
# ports:
# - "8080:80"
# depends_on:
# mysql:
# condition: service_healthy
mailpit:
image: axllent/mailpit:latest
ports:
- "8025:8025"
- "1025:1025"

volumes:
composer-cache:
# Used by the optional `mysql` service above.
mysql-data:
61 changes: 60 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,63 @@
"config-provider": "App\\ConfigProvider"
}
},
"repositories": [
{
"type": "path",
"url": "../webware-*",
"options": {
"symlink": true,
"reference": "none",
"versions": {
"webware/webware-core": "1.0.0-alpha.6",
"webware/webware-event": "1.0.0-alpha.2",
"webware/webware-log": "2.0.0-alpha.1",
"webware/webware-message": "1.0.0-beta.3",
"webware/webware-mailer": "1.0.0-beta.5",
"webware/webware-admin": "1.0.x-dev",
"webware/webware-htmx": "1.0.x-dev",
"webware/webware-console": "1.0.x-dev",
"webware/webware-navigation": "1.0.x-dev",
"webware/webware-acl": "1.0.0",
"webware/webware-usermanager": "1.0.0",
"webware/webware-tools": "1.0.0-beta.3"
}
}
},
{
"type": "path",
"url": "../message-bus",
"options": {
"symlink": true,
"reference": "none",
"versions": {
"webware/message-bus": "2.0.0-beta.3"
}
}
}
],
"require": {
"php": "~8.4.1 || ~8.5.0",
"psr/container": "^2.0"
"laminas/laminas-config-aggregator": "^1.19",
"laminas/laminas-diactoros": "^3.8",
"laminas/laminas-servicemanager": "^4.5",
"laminas/laminas-stdlib": "^3.21",
"mezzio/mezzio": "^3.26",
"mezzio/mezzio-fastroute": "^3.14",
"mezzio/mezzio-helpers": "^5.20",
"psr/container": "^2.0",
"webware/message-bus": "^2.0.0-beta.3",
"webware/webware-acl": "^1.0",
"webware/webware-admin": "1.0.x-dev",
"webware/webware-console": "1.0.x-dev",
"webware/webware-core": "^1.0.0-alpha.6",
"webware/webware-event": "^1.0.0-alpha.2",
"webware/webware-htmx": "1.0.x-dev",
"webware/webware-log": "^2.0.0-alpha.1",
"webware/webware-mailer": "^1.0.0-beta.5",
"webware/webware-message": "^1.0.0-beta.3",
"webware/webware-navigation": "1.0.x-dev",
"webware/webware-usermanager": "^1.0"
},
"require-dev": {
"infection/infection": "^0.35.0",
Expand Down Expand Up @@ -59,6 +113,11 @@
]
},
"scripts": {
"clear-config-cache": "php bin/clear-config-cache.php",
"serve": [
"Composer\\Config::disableProcessTimeout",
"php -S 0.0.0.0:8080 -t public/"
],
"test": "phpunit --no-coverage --colors=always --testsuite \"unit test\"",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml --coverage-text",
"test-integration": "phpunit --no-coverage --colors=always --testsuite \"integration test\"",
Expand Down
Loading
Loading