Skip to content
Merged
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
9 changes: 2 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions:
contents: read

env:
CI_RECIPES_VERSION: 6e790adf553ecff9f5ba5a3d0beeb9a9256a29ee
CI_RECIPES_VERSION: 83ccd6f83d7e7ef40f5d6faf2e11960f1de74a78

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down Expand Up @@ -74,12 +74,7 @@ jobs:
.dockerignore \
Dockerfile \
docker-entrypoint-sqlite.sh \
sqlite-database-integration-loader.php \
sqlite-diagnostics.php \
sqlite-local-core-update.php \
sqlite-select-id-key-fix.php \
sqlite-wordpress-performance.php \
sqlite-wordpress-smtp.php \
plugins \
tool-reset-user-password.php \
tool-update-site-url.php \
tests/image-smoke.sh \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ concurrency:
cancel-in-progress: false

env:
CI_RECIPES_VERSION: 6e790adf553ecff9f5ba5a3d0beeb9a9256a29ee
CI_RECIPES_VERSION: 83ccd6f83d7e7ef40f5d6faf2e11960f1de74a78
REGISTRY_IMAGE: soulteary/sqlite-wordpress
GHCR_IMAGE: ghcr.io/soulteary/sqlite-wordpress

Expand Down
32 changes: 30 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,26 @@

## [Unreleased]

## [2026.09.03-r1] - 2026-09-03

### Fixed

- Refreshed the pinned `wordpress:7.1.0-php8.5-apache` manifest digest after
the official mutable tag changed, restoring the fail-closed upstream image
check required by image-building pull requests and releases.
- Updated CI image-change detection to track the consolidated `plugins/`
directory so future project-owned plugin changes cannot skip image smoke
tests or upstream base-image verification.

### Changed

- Consolidated all project-owned must-use plugin source files under the
repository's `plugins/` directory while preserving their flat
`wp-content/mu-plugins/` installation paths and runtime behavior.
- Replaced repository-local CI validation Bash scripts with the SHA-pinned
`ci-recipes` Go CLI and moved the architecture-independent upstream image
check out of the three-platform smoke-test matrix.
check out of the three-platform smoke-test matrix. Updated the pinned recipe
to recognize both the consolidated and legacy MU-plugin source layouts.
- Marked `2026.09.02-r2` as published after both registries, supply-chain
evidence, signatures, and mutable aliases passed verification; switched the
Quick Start and Compose example from a local `main` build to the immutable
Expand All @@ -15,6 +30,18 @@
protected lightweight and annotated tag support and the GitHub Release
publication order.

### Release status

- Prepared as the first immutable release for 2026-09-03. Until its protected
tag is published and the two registry indexes, evidence, and signatures are
verified, `2026.09.02-r2` remains the current complete release.

### Compatibility notes

- The source-tree cleanup does not change runtime plugin paths or behavior.
Existing document-root volumes continue to receive the same managed files in
the flat `wp-content/mu-plugins/` directory during entrypoint reconciliation.

## [2026.09.02-r2] - 2026-09-02

### Fixed
Expand Down Expand Up @@ -255,7 +282,8 @@
- SQLite Database Integration 3.0.0 uses WAL journaling by default; keep the database, `-wal`, and `-shm` files on the same persistent volume.
- The native `wp_mysql_parser` extension is built for amd64 and arm64. Other published platforms use the integration's pure-PHP parser fallback.

[Unreleased]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.09.02-r2...HEAD
[Unreleased]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.09.03-r1...HEAD
[2026.09.03-r1]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.09.02-r2...2026.09.03-r1
[2026.09.02-r2]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.09.02-r1...2026.09.02-r2
[2026.09.02-r1]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.09.01-r1...2026.09.02-r1
[2026.09.01-r1]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.08.31-r3...2026.09.01-r1
Expand Down
9 changes: 6 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ php tests/test-sqlite-local-core-update.php
php tests/test-sqlite-select-id-key-fix.php
php tests/test-tool-update-site-url.php
php tests/test-tool-reset-user-password.php
go install github.com/soulteary/ci-recipes/cmd/ci-recipes@6e790adf553ecff9f5ba5a3d0beeb9a9256a29ee
ci-recipes docker-sqlite-wordpress validate-release 2026.09.02-r2
go install github.com/soulteary/ci-recipes/cmd/ci-recipes@83ccd6f83d7e7ef40f5d6faf2e11960f1de74a78
ci-recipes docker-sqlite-wordpress validate-release 2026.09.03-r1
```

To reproduce the remaining lint and configuration checks:
Expand Down Expand Up @@ -199,7 +199,10 @@ Please search for existing issues before opening a new one. When reporting a bug
## Code Style Conventions

- **Dockerfile**: Keep the multi-stage build structure clear; keep necessary comments for non-obvious trade-offs (such as skipping the Rust build per platform).
- **PHP** (`sqlite-select-id-key-fix.php`, etc.): Follow the WordPress coding standards and keep behavior conservative and safe to fall back on, avoiding destructive changes for cases that cannot be fully reasoned about.
- **PHP plugins** (`plugins/sqlite-select-id-key-fix.php`, etc.): Keep
project-owned MU-plugin sources in `plugins/`, follow the WordPress coding
standards, and keep behavior conservative and safe to fall back on, avoiding
destructive changes for cases that cannot be fully reasoned about.
- **YAML workflows**: Keep pull-request validation and the release-triggered `Release` workflow consistent with the supported platform matrix and release policy.
- Comments should explain intent and constraints, not restate what the code already expresses.

Expand Down
18 changes: 9 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# plugin: https://github.com/WordPress/sqlite-database-integration
# The optional native Rust extension `wp_mysql_parser` accelerates the MySQL
# lexer/parser used by the SQLite driver. It requires the 3.0 monorepo layout.
ARG IMAGE_VERSION=2026.09.02-r2
ARG IMAGE_VERSION=2026.09.03-r1
ARG IMAGE_REVISION=unknown
ARG WORDPRESS_VERSION=7.1.0
ARG WORDPRESS_IMAGE=wordpress:7.1.0-php8.5-apache@sha256:d05574507fdb46ad9be0c12a86c54c5e0603c282ea2d967f939081baf9665c6d
ARG WORDPRESS_IMAGE=wordpress:7.1.0-php8.5-apache@sha256:397daa8a8816347e724362c2122129601eb0811fbaff0ce9b2b22c7b057a745d
ARG SQLITE_DATABASE_INTEGRATION_VERSION=3.0.1
ARG SQLITE_DATABASE_INTEGRATION_COMMIT=abf0dac137cf4e17866fea44b8a83d68b43792c4
ARG RUSTUP_VERSION=1.29.0
Expand Down Expand Up @@ -114,7 +114,7 @@ LABEL org.opencontainers.image.authors="soulteary@gmail.com" \
org.opencontainers.image.revision="${IMAGE_REVISION}" \
org.opencontainers.image.licenses="Apache-2.0 AND GPL-2.0-or-later" \
org.opencontainers.image.base.name="docker.io/library/wordpress:7.1.0-php8.5-apache" \
org.opencontainers.image.base.digest="sha256:d05574507fdb46ad9be0c12a86c54c5e0603c282ea2d967f939081baf9665c6d" \
org.opencontainers.image.base.digest="sha256:397daa8a8816347e724362c2122129601eb0811fbaff0ce9b2b22c7b057a745d" \
io.soulteary.wordpress.version="${WORDPRESS_VERSION}" \
io.soulteary.sqlite-integration.version="${SQLITE_DATABASE_INTEGRATION_VERSION}"

Expand All @@ -128,38 +128,38 @@ COPY --from=ext-builder /plugin ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/s
# Companion must-use plugin: normalizes SELECT column-name casing (e.g. "P.id")
# that SQLite otherwise returns as the declared column name (e.g. "ID"). Files
# in the mu-plugins root are auto-loaded and cannot be deactivated.
COPY sqlite-select-id-key-fix.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-select-id-key-fix.php
COPY plugins/sqlite-select-id-key-fix.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-select-id-key-fix.php

# Companion must-use plugin: read-only diagnostics page under the Tools menu
# that surfaces the native parser / SQLite / environment / integration state.
# Auto-loaded from the mu-plugins root and cannot be deactivated.
COPY sqlite-diagnostics.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-diagnostics.php
COPY plugins/sqlite-diagnostics.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-diagnostics.php

# Optional SMTP transport with an administrator settings page and per-field
# environment overrides. It is disabled by default and includes OwlMail-safe
# defaults for the optional Compose integration.
COPY sqlite-wordpress-smtp.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-wordpress-smtp.php
COPY plugins/sqlite-wordpress-smtp.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-wordpress-smtp.php

# Optional, disabled-by-default server performance display. Administrators or
# an exact boolean environment override can expose generation time and PHP
# memory usage in the toolbar and public page footer.
COPY sqlite-wordpress-performance.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-wordpress-performance.php
COPY plugins/sqlite-wordpress-performance.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-wordpress-performance.php

# WordPress's official entrypoint intentionally leaves an initialized docroot
# untouched. Bundle the exact pinned core as a no-content archive and let this
# MU plugin replace only matching WordPress.org update offers with a verified
# temporary copy of that local package.
COPY --from=ext-builder /wordpress-core-no-content.zip /usr/src/wordpress-upgrades/wordpress-${WORDPRESS_VERSION}-no-content.zip
COPY --from=ext-builder /wordpress-core-no-content.zip.sha256 /usr/src/wordpress-upgrades/wordpress-${WORDPRESS_VERSION}-no-content.zip.sha256
COPY sqlite-local-core-update.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-local-core-update.php
COPY plugins/sqlite-local-core-update.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-local-core-update.php

# mu-plugins only auto-loads .php files in the mu-plugins root; it does NOT
# recurse into subdirectories, so the plugin's own
# sqlite-database-integration/load.php is never executed on its own. This
# root-level loader requires that load.php to mount its admin UI (the SQLite
# health-check / settings page under Settings). The SQLite driver itself loads
# via wp-content/db.php and does not depend on this loader.
COPY sqlite-database-integration-loader.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-database-integration-loader.php
COPY plugins/sqlite-database-integration-loader.php ${WORDPRESS_PREPARE_DIR}/wp-content/mu-plugins/sqlite-database-integration-loader.php

# Disabled-by-default emergency endpoint for repairing the database-backed
# WordPress Address (`siteurl`) and Site Address (`home`) after a domain change.
Expand Down
42 changes: 26 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

WordPress with SQLite, ready to use out of the box.

> **Latest container release:**
> [`2026.09.02-r2`](https://github.com/soulteary/docker-sqlite-wordpress/releases/tag/2026.09.02-r2)
> is published to Docker Hub and GHCR as matching five-platform indexes at
<!-- release-availability: pending -->
> **Container release availability:** `2026.09.03-r1` is prepared but is not
> published yet as a verified container image. The previous verified release,
> [`2026.09.02-r2`](https://github.com/soulteary/docker-sqlite-wordpress/releases/tag/2026.09.02-r2),
> remains available from Docker Hub and GHCR with matching manifest digest
> `sha256:9a5ceb20d80485de3e71bfe4a454f913408c6cdc995df17c2805e90fea5a049a`.
> The verified `2026.09.02` and `latest` aliases were promoted from the same
> release. Pin the exact CalVer tag or manifest digest for reproducible
> deployments.
> Until the protected `2026.09.03-r1` tag succeeds in both registries, build
> current `main` as shown in Quick Start. The existing `latest` alias still
> represents the previous release and does not include this candidate's fixes.

- Based on [official image](https://hub.docker.com/_/wordpress), Easier and more sustainable solution.
- DockerHub Page: https://hub.docker.com/r/soulteary/sqlite-wordpress
Expand Down Expand Up @@ -59,26 +61,32 @@ docker exec -it <container> ls -l /var/www/html/wp-content/mu-plugins/

## Quick Start

Pull the immutable CalVer release for reproducible deployments, or use the
rolling `latest` alias when automatic version movement is intentional:
Until `2026.09.03-r1` is published, build current `main` locally:

```bash
docker build -t sqlite-wordpress:main .
```

After the protected release workflow succeeds, pull the rolling tag for
convenience or the immutable CalVer release for reproducible deployments:

```bash
# Docker Hub: use an immutable release
docker pull soulteary/sqlite-wordpress:2026.09.02-r2
# GHCR: use an immutable release
docker pull ghcr.io/soulteary/sqlite-wordpress:2026.09.02-r2
# Docker Hub: use latest
docker pull soulteary/sqlite-wordpress
# Docker Hub: use an immutable release
docker pull soulteary/sqlite-wordpress:2026.09.03-r1
# GHCR: use latest
docker pull ghcr.io/soulteary/sqlite-wordpress:latest
# GHCR: use an immutable release
docker pull ghcr.io/soulteary/sqlite-wordpress:2026.09.03-r1
```

Launch the published image on port `8080`:
Launch the locally built image on port `8080`:

```bash
docker run --rm -it -p 127.0.0.1:8080:80 \
-v "$(pwd)/wordpress:/var/www/html" \
soulteary/sqlite-wordpress:2026.09.02-r2
sqlite-wordpress:main
```

You can also use docker compose to start wordpress:
Expand All @@ -87,7 +95,9 @@ You can also use docker compose to start wordpress:
services:

wordpress:
image: soulteary/sqlite-wordpress:2026.09.02-r2
build:
context: .
image: sqlite-wordpress:main
restart: always
ports:
# Safe local default. Change this only when intentionally publishing the
Expand All @@ -97,7 +107,7 @@ services:
- ./wordpress:/var/www/html
```

Save the file as `docker-compose.yml` and execute `docker compose up -d`,
Save the file as `docker-compose.yml` and execute `docker compose up --build`,
then use a browser to access `localhost:8080`.

![](.github/ready-to-use.jpg)
Expand Down
12 changes: 6 additions & 6 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ tag protection remains the authoritative control.
php tests/test-sqlite-select-id-key-fix.php
php tests/test-tool-update-site-url.php
php tests/test-tool-reset-user-password.php
go install github.com/soulteary/ci-recipes/cmd/ci-recipes@6e790adf553ecff9f5ba5a3d0beeb9a9256a29ee
ci-recipes docker-sqlite-wordpress validate-release 2026.09.02-r2
go install github.com/soulteary/ci-recipes/cmd/ci-recipes@83ccd6f83d7e7ef40f5d6faf2e11960f1de74a78
ci-recipes docker-sqlite-wordpress validate-release 2026.09.03-r1
```

4. Let pull-request CI test amd64, native arm64, and the 32-bit ARM pure-PHP
Expand All @@ -57,7 +57,7 @@ Publish from the GitHub Releases page after the release pull request is merged
and `main` CI succeeds:

1. Open **Releases → Draft a new release**.
2. Enter `2026.09.02-r2` in **Choose a tag**, choose **Create new tag**, and
2. Enter `2026.09.03-r1` in **Choose a tag**, choose **Create new tag**, and
target the current `main` branch.
3. Generate and review the release notes, then select **Publish release**.

Expand All @@ -74,8 +74,8 @@ Manual dispatch remains the explicit operator path described below.
The `Release` workflow builds each runtime platform once and publishes the same
manifest digest to Docker Hub and GHCR under the immutable exact tag:

- `soulteary/sqlite-wordpress:2026.09.02-r2`
- `ghcr.io/soulteary/sqlite-wordpress:2026.09.02-r2`
- `soulteary/sqlite-wordpress:2026.09.03-r1`
- `ghcr.io/soulteary/sqlite-wordpress:2026.09.03-r1`

BuildKit emits an SPDX SBOM and maximum-mode SLSA provenance for each platform.
The merged index receives OCI version, source, revision, and license
Expand Down Expand Up @@ -136,7 +136,7 @@ manifest; an additional valid signature referrer does not change its digest.
Set the exact tag once for all commands:

```bash
release=2026.09.02-r2
release=2026.09.03-r1
```

1. Confirm both registries expose the same five runtime platforms, SBOM, and
Expand Down
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
services:

wordpress:
image: soulteary/sqlite-wordpress:2026.09.02-r2
build:
context: .
image: sqlite-wordpress:main
restart: always
ports:
# Safe local default. Replace 127.0.0.1 only when intentionally publishing
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions tests/test-mu-plugin-metadata.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ if (( ${#project_mu_plugins[@]} == 0 )); then
fi

for plugin in "${project_mu_plugins[@]}"; do
if [[ "${plugin}" != plugins/*.php ]]; then
echo "Project-owned MU Plugin source must be stored under plugins/: ${plugin}" >&2
exit 1
fi
if [[ ! -f "${plugin}" ]]; then
echo "Project-owned MU Plugin source is missing: ${plugin}" >&2
exit 1
Expand All @@ -33,4 +37,9 @@ for plugin in "${project_mu_plugins[@]}"; do
fi
done

if find . -maxdepth 1 -type f -name 'sqlite-*.php' -print -quit | grep -q .; then
echo "Project-owned MU Plugin sources must not be stored in the repository root." >&2
exit 1
fi

echo "Project-owned MU Plugin metadata is valid."
2 changes: 1 addition & 1 deletion tests/test-sqlite-local-core-update.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function __construct( $code, $message = '' ) {
class Core_Upgrader {}
class Plugin_Upgrader {}

require dirname( __DIR__ ) . '/sqlite-local-core-update.php';
require dirname( __DIR__ ) . '/plugins/sqlite-local-core-update.php';

function local_core_assert_same( $expected, $actual, $label ) {
if ( $expected !== $actual ) {
Expand Down
2 changes: 1 addition & 1 deletion tests/test-sqlite-select-id-key-fix.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
function add_filter() {}
function add_action() {}

require dirname( __DIR__ ) . '/sqlite-select-id-key-fix.php';
require dirname( __DIR__ ) . '/plugins/sqlite-select-id-key-fix.php';

/**
* @param mixed $expected Expected value.
Expand Down
2 changes: 1 addition & 1 deletion tests/test-sqlite-wordpress-performance.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function add_node( $node ) {
}
}

require dirname( __DIR__ ) . '/sqlite-wordpress-performance.php';
require dirname( __DIR__ ) . '/plugins/sqlite-wordpress-performance.php';

function performance_test_assert_same( $expected, $actual, $label ) {
if ( $expected !== $actual ) {
Expand Down
2 changes: 1 addition & 1 deletion tests/test-sqlite-wordpress-smtp.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public function isSMTP() {
}
}

require dirname( __DIR__ ) . '/sqlite-wordpress-smtp.php';
require dirname( __DIR__ ) . '/plugins/sqlite-wordpress-smtp.php';

function smtp_test_assert_same( $expected, $actual, $label ) {
if ( $expected !== $actual ) {
Expand Down