From 506fe14ab4b79cf2809769d97e2c52e8803ec99e Mon Sep 17 00:00:00 2001 From: Maximilian Date: Fri, 24 Apr 2026 14:43:10 +0200 Subject: [PATCH] feat(ci): smoke-test the action surface on every PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new `smoke-action` job to ci.yml that invokes the public action.yml + src/index.js wrapper the way a user's `uses: buildrush/setup-php@v1` would — previously not covered anywhere in CI. Coverage gap this closes: - ci.yml::pipeline exercises phpup as a CLI inside bare-ubuntu containers (bundle build + fixture probe). It bypasses the composite-action entry point entirely. - A PR that broke action.yml (typo an input name, wrong output binding, etc.) or src/index.js (input parsing regression, misresolved cache path) would pass every existing job and still ship a broken action. How the new job runs the PR's phpup, not a released one: src/index.js:runMain() checks existsSync($RUNNER_TOOL_CACHE/ buildrush-bin/phpup) before hitting the network. We `go build` the PR's phpup binary directly into that cache path, then invoke `uses: ./` — the wrapper finds the binary, skips the release download, and the end-to-end path is: PR's action.yml → PR's src/index.js → PR's phpup. Zero changes to src/index.js were needed; the cache-hit path was the right hook. Matrix is deliberately narrower than `pipeline`: - 2 OS (jammy, noble) × 2 arch (amd64, arm64) × 1 PHP (8.4) = 4 cells - Wrapper is OS-invariant and arch-variant; 4 cells catch the real regressions without multiplying the existing 20-cell `pipeline` cost. Assertions per cell: - php -v succeeds (smoke) - extension_loaded("redis") + extension_loaded("intl") (extensions input was honored + extensions loaded at runtime) - ini_get("memory_limit") == "256M" (ini-values input was parsed + applied) Wiring: - smoke-action needs: pipeline (fails fast if the CLI side broke) - publish needs: [pipeline, smoke-action] (a broken wrapper on main would otherwise publish a bundle the action can't use) v2 drop-in compat (the coverage lost when compat-harness.yml was deleted in PR #60) is deferred to a follow-up PR — this one keeps the change surface small and easy to revert. --- .github/workflows/ci.yml | 69 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b81edbd..0271993 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,9 +121,76 @@ jobs: path: out/oci-layout retention-days: 7 + smoke-action: + name: "Smoke action surface (${{ matrix.os }}/${{ matrix.arch }})" + needs: pipeline + # Exercises the public action.yml + src/index.js wrapper end-to-end + # the way a user's `uses: buildrush/setup-php@v1` would, against the + # PR's HEAD binary. `runMain()` in src/index.js short-circuits the + # GitHub-release download when the expected cache path already + # contains a binary — so we build phpup from the PR and drop it at + # that exact path *before* invoking `uses: ./`. + # + # Matrix is deliberately narrower than `pipeline` (which covers 20 + # OS/arch/PHP combos at the CLI level): the wrapper itself is thin + # and OS-invariant, so 2 OS × 2 arch × 1 PHP catches wrapper + # regressions without multiplying CI time. + strategy: + fail-fast: false + matrix: + include: + - os: jammy + arch: amd64 + runner: ubuntu-22.04 + - os: noble + arch: amd64 + runner: ubuntu-24.04 + - os: jammy + arch: arm64 + runner: ubuntu-22.04-arm + - os: noble + arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Prepare embedded lockfile + run: cp bundles.lock cmd/phpup/bundles.lock + - name: Build phpup from PR HEAD into the runner cache + # src/index.js:runMain() resolves its cached binary path as + # $RUNNER_TOOL_CACHE/buildrush-bin/phpup (linux) and skips the + # release-asset download when existsSync() returns true. That's + # the hook we use to run the wrapper against *this PR's* phpup + # binary rather than whatever the latest release carries. + run: | + mkdir -p "$RUNNER_TOOL_CACHE/buildrush-bin" + go build -o "$RUNNER_TOOL_CACHE/buildrush-bin/phpup" ./cmd/phpup + chmod +x "$RUNNER_TOOL_CACHE/buildrush-bin/phpup" + - name: Invoke action (uses ./) + uses: ./ + with: + php-version: "8.4" + extensions: "redis, intl" + ini-values: "memory_limit=256M" + - name: Assert PHP is installed + inputs honored + run: | + set -euo pipefail + php -v + php -r 'exit(extension_loaded("redis") ? 0 : 1);' \ + || { echo "::error::redis extension not loaded"; exit 1; } + php -r 'exit(extension_loaded("intl") ? 0 : 1);' \ + || { echo "::error::intl extension not loaded"; exit 1; } + memlim=$(php -r 'echo ini_get("memory_limit");') + test "$memlim" = "256M" \ + || { echo "::error::memory_limit=$memlim, want 256M"; exit 1; } + echo "smoke-action: action surface OK" + publish: name: Publish to GHCR - needs: pipeline + needs: [pipeline, smoke-action] if: github.ref == 'refs/heads/main' runs-on: ubuntu-24.04 steps: