From c31f14eb0924f34d64636710b329cb35538a6b1d Mon Sep 17 00:00:00 2001 From: Su Yang Date: Mon, 31 Aug 2026 06:32:06 +0800 Subject: [PATCH] release: prepare 2026.08.31-r2 --- CHANGELOG.md | 31 ++++++++++++++++++++--- CONTRIBUTING.md | 2 +- Dockerfile | 2 +- README.md | 46 ++++++++++++++++++---------------- RELEASING.md | 31 ++++++++++++++++------- VERSIONING.md | 20 +++++++-------- scripts/validate-release.sh | 2 +- tests/test-validate-release.sh | 6 ++--- 8 files changed, 91 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 748a7ca..9e82617 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,31 @@ ## [Unreleased] -## [2026.08.30-r1] - 2026-08-30 +## [2026.08.31-r2] - 2026-08-31 + +### Fixed + +- Prepared a new immutable release revision after `2026.08.31-r1` stopped in + release preflight before any container image was built. The existing `r1` + tag and GitHub source release remain in place for audit history and are not + moved, deleted, or reused. +- Aligned the image version, validation examples, deployment examples, and + release documentation on the same `2026.08.31-r2` candidate. + +### Release notes + +- This revision contains the CalVer, SQLite Database Integration 3.0.1, + persistent-volume core updater, supply-chain evidence, and ARM test changes + recorded in the retained `2026.08.31-r1` source release below. + +## [2026.08.31-r1] - 2026-08-31 + +### Release status + +- The GitHub source release was created with a lightweight tag while its source + still declared `2026.08.30-r1`. The protected release workflow rejected it + during preflight and produced no container image for this exact tag. Do not + use `2026.08.31-r1` as a deployable image release. ### Added @@ -82,6 +106,7 @@ - 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.08.30-r1...HEAD -[2026.08.30-r1]: https://github.com/soulteary/docker-sqlite-wordpress/compare/7.1.0...2026.08.30-r1 +[Unreleased]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.08.31-r2...HEAD +[2026.08.31-r2]: https://github.com/soulteary/docker-sqlite-wordpress/compare/2026.08.31-r1...2026.08.31-r2 +[2026.08.31-r1]: https://github.com/soulteary/docker-sqlite-wordpress/compare/7.1.0...2026.08.31-r1 [7.1.0]: https://github.com/soulteary/docker-sqlite-wordpress/compare/7.0.2-plugin-v3.0.0-rc.8...7.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f88572..435ccfa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -102,7 +102,7 @@ bash tests/test-validate-release.sh 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 -./scripts/validate-release.sh 2026.08.30-r1 +./scripts/validate-release.sh 2026.08.31-r2 ``` To reproduce the remaining lint and configuration checks: diff --git a/Dockerfile b/Dockerfile index 95fb695..4e04763 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # 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.08.30-r1 +ARG IMAGE_VERSION=2026.08.31-r2 ARG IMAGE_REVISION=unknown ARG WORDPRESS_VERSION=7.1.0 ARG WORDPRESS_IMAGE=wordpress:7.1.0-php8.5-apache@sha256:6c56ffb8cc06577c604707e3164f7fe736a3db6855336804a2cd4d7c186d6502 diff --git a/README.md b/README.md index c86f026..88b0306 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,14 @@ WordPress with SQLite, ready to use out of the box. -> **Release availability:** `2026.08.30-r1` is prepared but is not published yet. -> Commands below that use this exact tag become available only after the -> protected tag workflow succeeds in both registries. Until then, build the -> current repository as shown in Quick Start; the existing `latest` alias does -> not represent all features documented for current `main`. +> **Container release availability:** `2026.08.31-r2` is prepared but is not published yet +> as a verified container image. The retained +> [`2026.08.31-r1` source release](https://github.com/soulteary/docker-sqlite-wordpress/releases/tag/2026.08.31-r1) +> failed release preflight before any image was built and must not be used as a +> container release. Until the protected annotated `r2` tag succeeds in both +> registries, build the current repository as shown in Quick Start; the +> existing `latest` alias does not represent all features documented for +> current `main`. - Based on [official image](https://hub.docker.com/_/wordpress), Easier and more sustainable solution. - DockerHub Page: https://hub.docker.com/r/soulteary/sqlite-wordpress @@ -58,7 +61,7 @@ docker exec -it ls -l /var/www/html/wp-content/mu-plugins/ ## Quick Start -Until `2026.08.30-r1` is published, build current `main` locally: +Until `2026.08.31-r2` is published, build current `main` locally: ```bash docker build -t sqlite-wordpress:main . @@ -71,11 +74,11 @@ convenience or the immutable CalVer release for reproducible deployments: # Docker Hub: use latest docker pull soulteary/sqlite-wordpress # Docker Hub: use an immutable release -docker pull soulteary/sqlite-wordpress:2026.08.30-r1 +docker pull soulteary/sqlite-wordpress:2026.08.31-r2 # GHCR: use latest docker pull ghcr.io/soulteary/sqlite-wordpress:latest # GHCR: use an immutable release -docker pull ghcr.io/soulteary/sqlite-wordpress:2026.08.30-r1 +docker pull ghcr.io/soulteary/sqlite-wordpress:2026.08.31-r2 ``` Launch the locally built image on port `8080`: @@ -113,16 +116,17 @@ Use the quick 1-minute initial installation, enjoy. ## Image Versions and Supply-chain Evidence -Image releases use CalVer such as `2026.08.30-r1`; WordPress and SQLite +Image releases use CalVer such as `2026.08.31-r2`; WordPress and SQLite Integration keep their own component versions. Exact `YYYY.MM.DD-rN` tags are immutable, while the date-only tag and `latest` are verified mutable aliases. Pin an exact tag or manifest digest in production. See [VERSIONING.md](./VERSIONING.md) for the complete policy. -Every release includes an SPDX SBOM, maximum-mode SLSA provenance, the source -commit in OCI `org.opencontainers.image.revision`, and a keyless Sigstore -signature on each Docker Hub and GHCR manifest. Verification commands and the -expected GitHub Actions identity are documented in +Every successfully published container release includes an SPDX SBOM, +maximum-mode SLSA provenance, the source commit in OCI +`org.opencontainers.image.revision`, and a keyless Sigstore signature on each +Docker Hub and GHCR manifest. Verification commands and the expected GitHub +Actions identity are documented in [RELEASING.md](./RELEASING.md). The repository and bundled-component license inventory is in [LICENSES.md](./LICENSES.md). @@ -218,7 +222,7 @@ chmod 600 secrets/site-url-update-token services: wordpress: - image: soulteary/sqlite-wordpress:2026.08.30-r1 + image: soulteary/sqlite-wordpress:2026.08.31-r2 ports: - 127.0.0.1:8080:80 environment: @@ -248,7 +252,7 @@ export WORDPRESS_SITE_URL_UPDATE_PASSWORD="$(openssl rand -base64 24)" services: wordpress: - image: soulteary/sqlite-wordpress:2026.08.30-r1 + image: soulteary/sqlite-wordpress:2026.08.31-r2 ports: - 127.0.0.1:8080:80 environment: @@ -276,7 +280,7 @@ docker run --rm -it \ --volume "$(pwd)/secrets/site-url-update-token:/run/secrets/site-url-update-token:ro" \ --env WORDPRESS_SITE_URL_UPDATE_TOOL_ENABLED=true \ --env WORDPRESS_SITE_URL_UPDATE_TOKEN_FILE=/run/secrets/site-url-update-token \ - soulteary/sqlite-wordpress:2026.08.30-r1 + soulteary/sqlite-wordpress:2026.08.31-r2 ``` For PASSWORD, export a fresh value and pass only the variable name so the shell @@ -290,7 +294,7 @@ docker run --rm -it \ --volume "$(pwd)/wordpress:/var/www/html" \ --env WORDPRESS_SITE_URL_UPDATE_TOOL_ENABLED=true \ --env WORDPRESS_SITE_URL_UPDATE_PASSWORD \ - soulteary/sqlite-wordpress:2026.08.30-r1 + soulteary/sqlite-wordpress:2026.08.31-r2 ``` After the update, stop this temporary container and start the normal deployment @@ -429,7 +433,7 @@ docker run --rm --user 0:0 \ --mount type=bind,source="$(pwd)/wordpress",target=/source,readonly \ --mount type=bind,source="$(pwd)/backups",target=/backup \ --env "BACKUP_NAME=${backup_name}" \ - soulteary/sqlite-wordpress:2026.08.30-r1 \ + soulteary/sqlite-wordpress:2026.08.31-r2 \ -Eeuo pipefail -c ' [[ -n "${BACKUP_NAME}" && "${BACKUP_NAME}" != */* ]] archive="/backup/${BACKUP_NAME}" @@ -464,7 +468,7 @@ docker run --rm --user 0:0 \ --mount "type=volume,source=${wordpress_volume},target=/source,readonly" \ --mount type=bind,source="$(pwd)/backups",target=/backup \ --env "BACKUP_NAME=${backup_name}" \ - soulteary/sqlite-wordpress:2026.08.30-r1 \ + soulteary/sqlite-wordpress:2026.08.31-r2 \ -Eeuo pipefail -c ' [[ -n "${BACKUP_NAME}" && "${BACKUP_NAME}" != */* ]] archive="/backup/${BACKUP_NAME}" @@ -497,7 +501,7 @@ docker run --rm --user 0:0 \ --mount type=bind,source="$(pwd)/wordpress",target=/source \ --mount type=bind,source="$(pwd)/backups",target=/backup,readonly \ --env "BACKUP_NAME=${backup_name}" \ - soulteary/sqlite-wordpress:2026.08.30-r1 \ + soulteary/sqlite-wordpress:2026.08.31-r2 \ -Eeuo pipefail -c ' [[ -n "${BACKUP_NAME}" && "${BACKUP_NAME}" != */* ]] archive="/backup/${BACKUP_NAME}" @@ -535,7 +539,7 @@ docker run --rm --user 0:0 \ --mount "type=volume,source=${wordpress_volume},target=/source" \ --mount type=bind,source="$(pwd)/backups",target=/backup,readonly \ --env "BACKUP_NAME=${backup_name}" \ - soulteary/sqlite-wordpress:2026.08.30-r1 \ + soulteary/sqlite-wordpress:2026.08.31-r2 \ -Eeuo pipefail -c ' [[ -n "${BACKUP_NAME}" && "${BACKUP_NAME}" != */* ]] archive="/backup/${BACKUP_NAME}" diff --git a/RELEASING.md b/RELEASING.md index a485ff7..73d9c88 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -24,8 +24,9 @@ authoritative control. ## Prepare -1. Choose the UTC release date and revision. Use `r1` for the first release on - a date, then increment it for every changed image artifact or evidence set. +1. Choose the `Asia/Shanghai` release date and revision. Use `r1` for the first + release on a date, then increment it for every changed image artifact or + evidence set. Check that the exact tag is absent from Git, Docker Hub, and GHCR. 2. Update the pinned WordPress base digest, `WORDPRESS_VERSION`, SQLite Integration version/ref, README and Compose examples, and `CHANGELOG.md` in a @@ -38,7 +39,7 @@ authoritative control. 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 - ./scripts/validate-release.sh 2026.08.30-r1 + ./scripts/validate-release.sh 2026.08.31-r2 ``` 4. Let pull-request CI test amd64, native arm64, and the 32-bit ARM pure-PHP @@ -56,15 +57,17 @@ Do not let the GitHub Release form create a lightweight tag. ```bash git switch main git pull --ff-only -git tag -a 2026.08.30-r1 -m "Release 2026.08.30-r1" -git push origin refs/tags/2026.08.30-r1 +release=2026.08.31-r2 +git tag -a "${release}" -m "Release ${release}" +test "$(git cat-file -t "refs/tags/${release}")" = tag +git push origin "refs/tags/${release}" ``` 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.08.30-r1` -- `ghcr.io/soulteary/sqlite-wordpress:2026.08.30-r1` +- `soulteary/sqlite-wordpress:2026.08.31-r2` +- `ghcr.io/soulteary/sqlite-wordpress:2026.08.31-r2` BuildKit emits an SPDX SBOM and maximum-mode SLSA provenance for each platform. The merged index receives OCI version, source, revision, and license @@ -74,7 +77,7 @@ succeeds. Afterward, the serialized `Promote latest` workflow selects the numerically newest complete CalVer release whose two registry indexes match. It promotes -both the date alias (for example `2026.08.30`) and `latest` without rebuilding. +both the date alias (for example `2026.08.31`) and `latest` without rebuilding. If the newest Git tag is incomplete, promotion scans backward to the newest complete release rather than blocking all promotion. @@ -82,12 +85,22 @@ Manual `Release` dispatch is allowed only when the selected workflow ref is an unpublished annotated CalVer tag. Running it from a branch fails preflight. Manual `Promote latest` dispatch from `main` can reconcile mutable aliases. +### Recover from a failed preflight + +Do not move, delete, or reuse a public exact CalVer tag after a failed release. +A rerun cannot turn a lightweight tag into an annotated tag or make a tag name +match a different `IMAGE_VERSION`. Keep the failed tag and source release for +audit history, correct the ruleset and source version through a pull request, +increment the revision, and publish a new annotated protected tag. A workflow +that stopped in preflight did not reach the image build or registry publication +jobs. + ## Verify and announce Set the exact tag once for all commands: ```bash -release=2026.08.30-r1 +release=2026.08.31-r2 ``` 1. Confirm both registries expose the same five runtime platforms, SBOM, and diff --git a/VERSIONING.md b/VERSIONING.md index 86309fb..6805e4b 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -14,7 +14,7 @@ Immutable releases use: YYYY.MM.DD-rN ``` -- `YYYY.MM.DD` is the release date in UTC. +- `YYYY.MM.DD` is the project release date in `Asia/Shanghai` (UTC+08:00). - `rN` is a positive revision beginning at `r1`. - Leading zeroes are required for month and day. - The date must be a real calendar date. @@ -22,16 +22,16 @@ YYYY.MM.DD-rN Examples: ```text -2026.08.30-r1 -2026.08.30-r2 +2026.08.31-r1 +2026.08.31-r2 2026.09.04-r1 ``` -Use another revision on the same UTC date whenever any published image content -or release evidence changes, including a WordPress or plugin update, a base -image rebuild, project code, labels, SBOM/provenance, or a packaging fix. Start -at `r1` again on a new date. Documentation-only changes do not require an image -release. +Use another revision on the same project release date whenever any published +image content or release evidence changes, including a WordPress or plugin +update, a base image rebuild, project code, labels, SBOM/provenance, or a +packaging fix. Start at `r1` again on a new date. Documentation-only changes do +not require an image release. The release date identifies when the artifact is prepared for publication; it does not claim that every bundled component was released on that date. Publish @@ -41,8 +41,8 @@ late fixes under their actual release date, and never reuse or move a tag. | Tag | Example | Mutability | Intended use | | --- | --- | --- | --- | -| Exact release | `2026.08.30-r1` | Immutable | Deployments, rollback, audit, and signatures | -| Date alias | `2026.08.30` | Mutable within that date | Follow the newest revision published for one date | +| Exact release | `2026.08.31-r2` | Immutable | Deployments, rollback, audit, and signatures | +| Date alias | `2026.08.31` | Mutable within that date | Follow the newest revision published for one date | | Rolling alias | `latest` | Mutable | Follow the newest complete release | Production deployments should pin an exact release tag, or preferably its diff --git a/scripts/validate-release.sh b/scripts/validate-release.sh index d133a6b..f8128ac 100755 --- a/scripts/validate-release.sh +++ b/scripts/validate-release.sh @@ -4,7 +4,7 @@ set -euo pipefail release_version="${1:-}" if [[ ! "${release_version}" =~ ^[0-9]{4}\.(0[1-9]|1[0-2])\.(0[1-9]|[12][0-9]|3[01])-r[1-9][0-9]*$ ]]; then - echo "release version must use YYYY.MM.DD-rN CalVer (for example, 2026.08.30-r1)" >&2 + echo "release version must use YYYY.MM.DD-rN CalVer (for example, 2026.08.31-r2)" >&2 exit 1 fi diff --git a/tests/test-validate-release.sh b/tests/test-validate-release.sh index d36ab1f..77f9ff4 100755 --- a/tests/test-validate-release.sh +++ b/tests/test-validate-release.sh @@ -32,20 +32,20 @@ pinned_digest="${wordpress_image##*@}" PATH="${fake_bin}:${PATH}" \ FAKE_EXPECTED_REF="${base_image}" \ FAKE_MANIFEST_DIGEST="${pinned_digest}" \ - ./scripts/validate-release.sh 2026.08.30-r1 --verify-upstream >/dev/null + ./scripts/validate-release.sh 2026.08.31-r2 --verify-upstream >/dev/null mismatch_digest="sha256:0000000000000000000000000000000000000000000000000000000000000000" if PATH="${fake_bin}:${PATH}" \ FAKE_EXPECTED_REF="${base_image}" \ FAKE_MANIFEST_DIGEST="${mismatch_digest}" \ - ./scripts/validate-release.sh 2026.08.30-r1 --verify-upstream \ + ./scripts/validate-release.sh 2026.08.31-r2 --verify-upstream \ >/dev/null 2>"${fake_bin}/mismatch.log"; then echo "digest mismatch unexpectedly passed" >&2 exit 1 fi grep -Fq "not pinned digest ${pinned_digest}" "${fake_bin}/mismatch.log" -for invalid_version in 7.1.0 2026.8.30-r1 2026.02.30-r1 2026.08.30-r0; do +for invalid_version in 7.1.0 2026.8.31-r1 2026.02.30-r1 2026.08.31-r0; do if ./scripts/validate-release.sh "${invalid_version}" >/dev/null 2>"${fake_bin}/invalid.log"; then echo "invalid release version unexpectedly passed: ${invalid_version}" >&2 exit 1