From c36b77af823d3a83703c8937422efd8f1568e08a Mon Sep 17 00:00:00 2001 From: Brei0x Date: Wed, 28 Oct 2026 17:00:00 +0100 Subject: [PATCH 1/2] ci: push the latest tag last so GHCR shows it as the install command - The package page shows the most recently pushed tag; parallel merges let 8.4 win the race --- .github/workflows/publish.yml | 2 ++ CLAUDE.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7bfc22e..6d51e54 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -94,6 +94,8 @@ jobs: packages: write strategy: fail-fast: false + # One at a time in matrix order: the package page shows the last pushed tag, so LATEST_PHP must stay last. + max-parallel: 1 matrix: php: ["8.3", "8.4", "8.5"] diff --git a/CLAUDE.md b/CLAUDE.md index 1e58441..8109c25 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,7 +24,7 @@ docker run --rm php-cli-workspace php -m ## Release Pipeline -A pull request runs `.github/workflows/ci.yml`: every PHP version is built on each platform's native runner and `php -m` lists its extensions. A push to `main` runs `.github/workflows/publish.yml`: the matrix builds one image per PHP version and platform, a per-version `merge` job assembles the manifest list and applies the image tags, a `cleanup` job (`dataaxiom/ghcr-cleanup-action`) drops the untagged image trees left by earlier runs, then the shared `tekalib/.workflows` release job tags the commit from the Conventional Commits since the last `v*` tag (`feat` = minor, `fix` and the rest = patch, `!` = major) and publishes the GitHub release. No file holds the version: the last tag does. Published image tags: `8.3`, `8.4`, `8.5`, and `latest` (→ the version in the `LATEST_PHP` env var, currently `8.5`). The same workflow also runs every Monday (`schedule`) to rebuild every tag on fresh base images: the `release` job is skipped then, so no empty release is cut. No manual publish step needed. +A pull request runs `.github/workflows/ci.yml`: every PHP version is built on each platform's native runner and `php -m` lists its extensions. A push to `main` runs `.github/workflows/publish.yml`: the matrix builds one image per PHP version and platform, a per-version `merge` job assembles the manifest list and applies the image tags (`max-parallel: 1`, in matrix order: the GHCR package page shows the last pushed tag as its install command, so the `LATEST_PHP` version stays last in the matrix), a `cleanup` job (`dataaxiom/ghcr-cleanup-action`) drops the untagged image trees left by earlier runs, then the shared `tekalib/.workflows` release job tags the commit from the Conventional Commits since the last `v*` tag (`feat` = minor, `fix` and the rest = patch, `!` = major) and publishes the GitHub release. No file holds the version: the last tag does. Published image tags: `8.3`, `8.4`, `8.5`, and `latest` (→ the version in the `LATEST_PHP` env var, currently `8.5`). The same workflow also runs every Monday (`schedule`) to rebuild every tag on fresh base images: the `release` job is skipped then, so no empty release is cut. No manual publish step needed. The image is published for **`linux/arm64` and `linux/amd64`**, each built on its native runner (`ubuntu-24.04-arm`, `ubuntu-24.04`) so no QEMU emulation is involved. Every tag is a manifest list: `docker pull` fetches only the platform matching the host. The `arch` matrix axis and its `include` runner mapping live in both workflows; keep them identical. From 44563ee954dfa27d2a1b272aaef2c1b5bc1934e8 Mon Sep 17 00:00:00 2001 From: Brei0x Date: Wed, 28 Oct 2026 17:00:00 +0100 Subject: [PATCH 2/2] ci: build on Ubuntu 26.04 native runners - 26.04 is GA on x64 and arm64; explicit labels keep both arches on the same release --- .github/workflows/ci.yml | 4 ++-- .github/workflows/publish.yml | 4 ++-- CLAUDE.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18aae76..49296a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,9 @@ jobs: arch: [arm64, amd64] include: # same native runner per platform as publish.yml - arch: arm64 - runner: ubuntu-24.04-arm + runner: ubuntu-26.04-arm - arch: amd64 - runner: ubuntu-24.04 + runner: ubuntu-26.04 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6d51e54..e06d87d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -33,9 +33,9 @@ jobs: arch: [arm64, amd64] include: # each platform builds natively: no QEMU, the extensions compile at full speed - arch: arm64 - runner: ubuntu-24.04-arm + runner: ubuntu-26.04-arm - arch: amd64 - runner: ubuntu-24.04 + runner: ubuntu-26.04 steps: - name: Checkout diff --git a/CLAUDE.md b/CLAUDE.md index 8109c25..1e641b8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,7 +26,7 @@ docker run --rm php-cli-workspace php -m A pull request runs `.github/workflows/ci.yml`: every PHP version is built on each platform's native runner and `php -m` lists its extensions. A push to `main` runs `.github/workflows/publish.yml`: the matrix builds one image per PHP version and platform, a per-version `merge` job assembles the manifest list and applies the image tags (`max-parallel: 1`, in matrix order: the GHCR package page shows the last pushed tag as its install command, so the `LATEST_PHP` version stays last in the matrix), a `cleanup` job (`dataaxiom/ghcr-cleanup-action`) drops the untagged image trees left by earlier runs, then the shared `tekalib/.workflows` release job tags the commit from the Conventional Commits since the last `v*` tag (`feat` = minor, `fix` and the rest = patch, `!` = major) and publishes the GitHub release. No file holds the version: the last tag does. Published image tags: `8.3`, `8.4`, `8.5`, and `latest` (→ the version in the `LATEST_PHP` env var, currently `8.5`). The same workflow also runs every Monday (`schedule`) to rebuild every tag on fresh base images: the `release` job is skipped then, so no empty release is cut. No manual publish step needed. -The image is published for **`linux/arm64` and `linux/amd64`**, each built on its native runner (`ubuntu-24.04-arm`, `ubuntu-24.04`) so no QEMU emulation is involved. Every tag is a manifest list: `docker pull` fetches only the platform matching the host. The `arch` matrix axis and its `include` runner mapping live in both workflows; keep them identical. +The image is published for **`linux/arm64` and `linux/amd64`**, each built on its native runner (`ubuntu-26.04-arm`, `ubuntu-26.04`) so no QEMU emulation is involved. Every tag is a manifest list: `docker pull` fetches only the platform matching the host. The `arch` matrix axis and its `include` runner mapping live in both workflows; keep them identical. ## Architecture