Skip to content

ci: fail the PHP Unit build when a PHP extension fails to install - #41848

Merged
phil-davis merged 1 commit into
masterfrom
ci/setup-php-fail-fast
Sep 22, 2026
Merged

phil-davis merged 1 commit into
masterfrom
ci/setup-php-fail-fast

Conversation

@oc-tmueller

Copy link
Copy Markdown
Contributor

The failure this fixes the reporting of

On run 35615464136 (job 106384881315, a docs-only PR) the Oracle leg went red with:

In Install.php line 109:
  [InvalidArgumentException]
  Database <oci> is not supported.

That message is misleading. The actual failure was 36 seconds earlier, in a step that reported success:

==> Setup Extensions
✓ curl Enabled
...
✓ imagick Enabled
✗ oci8 Could not install oci8 on PHP 8.3.33     <-- 14:57:17

setup-php treats a failed extension as a warning and lets the step pass, so the job ran on to Install Server and died there at 14:57:53. maintenance:install validates --database against the list OC\Setup::getSupportedDatabases() builds from the loaded PHP extensions (oci is gated on is_callable('oci_connect'), lib/private/Setup.php), so a missing oci8 presents as a database misconfiguration rather than as the extension problem it is.

Setting setup-php's fail-fast makes the Setup PHP step itself fail, with the ✗ oci8 line as its last output.

Why the Oracle leg is exposed to this at all

setup-php's src/scripts/extensions/oci.sh has no cache, so on every Oracle job it:

  • downloads instantclient-basiclite-linuxx64.zip and instantclient-sdk-linuxx64.zip from download.oracle.com via unversioned "latest" URLs, and
  • compiles oci8 from the php/pecl-database-oci8 main branch,
  • both wrapped in >/dev/null 2>&1, which is why the log gives no reason for the failure.

~80 MB from Oracle plus a compile, per job, against two unpinned upstreams. That flakiness is not ours to fix; the misattribution is.

It was a flake, not a regression — the same pinned setup-php SHA and PHP version printed ✓ oci8 Installed and enabled on master 8 hours earlier, and the 10.16 sibling PR's Oracle job passed in the same minute. 12 of the last 13 Oracle jobs passed. A re-run cleared it.

Please note: two different fail-fast keys

php-unit.yml now contains both. They are unrelated and this PR does not touch the first:

key owner value meaning
strategy.fail-fast (line 22) GitHub matrix false, unchanged do not cancel sibling database legs — set deliberately by #41695
env.fail-fast (new) setup-php true fail the step if an extension fails to install

This is not a revert of #41695.

Not a new pattern

acceptance.yml:174-175 already sets env: fail-fast: true on its Setup PHP step, at the same pinned action SHA. php-unit.yml was inconsistent with it.

nightly.yml calls this same reusable workflow, so the nightly Oracle run picks the change up too.

How it was verified

  • Mechanism, against the real upstream script at the exact pinned SHA (f3e473d). src/install.ts maps the fail-fast input/env to process.env['fail_fast']; src/scripts/unix.sh reads it in read_env and enforces it in add_log. Executing that add_log directly:
    • fail_fast=false → prints ✗ oci8 …, exit 0, execution continues (today's behaviour, i.e. the bug),
    • fail_fast=true → prints ✗ oci8 …, exit 1,
    • fail_fast=true with a → exit 0, continues, so a successful install is unaffected.
  • No currently-green job relies on a tolerated . Checked the setup-php output of the sqlite, mysql:8.0, mariadb:10.6, mariadb:10.11 and postgres:10.21 legs of the run above: every line is . This makes real failures louder; it does not create new ones.
  • YAML parses, env placement and indentation match acceptance.yml.

No changelog entry, following the other workflow-only ci: commits (0f0098699c, d617d439d4).

Backport to 10.16 follows.

Known remaining gap

lint-and-codestyle.yml is now the only setup-php call site without fail-fast. Its risk is much lower — its extensions are core ones and a failure there surfaces quickly in the next step — so I left it out to keep this diff to the failure mode we actually hit. Happy to add it here if you would rather have all three consistent.

🤖 Generated with Claude Code

setup-php treats a failed extension as a warning, not an error: it prints
"✗ <ext> Could not install ..." and lets the step succeed. The job then runs on
until something misses the extension.

For the Oracle leg that produces a misleading failure. When oci8 fails to
install, the job dies half a minute later in Install Server with

  [InvalidArgumentException] Database <oci> is not supported.

because maintenance:install validates --database against the list that
OC\Setup::getSupportedDatabases() derives from the *loaded PHP extensions* - so
a missing oci8 presents as a database misconfiguration rather than as the
extension problem it is. The real cause is further up the log, in a step that
reported success.

Setting fail-fast makes the Setup PHP step itself fail, with the "✗ oci8" line
as its last output. acceptance.yml already sets it the same way.

This is setup-php's own fail-fast option, read from the step environment. It is
unrelated to, and does not change, the matrix-level strategy.fail-fast that
governs whether sibling database legs keep running.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com>
@phil-davis
phil-davis merged commit 50dd405 into master Sep 22, 2026
31 checks passed
@phil-davis
phil-davis deleted the ci/setup-php-fail-fast branch September 22, 2026 03:00
phil-davis pushed a commit that referenced this pull request Sep 22, 2026
….16] (#41849)

Backport of #41848.

setup-php treats a failed extension as a warning, not an error: it prints
"✗ <ext> Could not install ..." and lets the step succeed. The job then runs on
until something misses the extension.

For the Oracle leg that produces a misleading failure. When oci8 fails to
install, the job dies half a minute later in Install Server with

  [InvalidArgumentException] Database <oci> is not supported.

because maintenance:install validates --database against the list that
OC\Setup::getSupportedDatabases() derives from the *loaded PHP extensions* - so
a missing oci8 presents as a database misconfiguration rather than as the
extension problem it is. The real cause is further up the log, in a step that
reported success.

Setting fail-fast makes the Setup PHP step itself fail, with the "✗ oci8" line
as its last output.

Unlike master, this branch still has the matrix strategy.fail-fast set to true -
#41695 was never backported - so the two settings compose here: a Setup PHP
failure cancels the sibling database legs. The comment records why that is
tolerable for the way ci.yml calls this workflow today, oci8 being the only
extension in the list that downloads anything and Oracle already having a
single-database call of its own.

Signed-off-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com>
Co-authored-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants