Skip to content

Update Psalm baseline workflow crashes on pcntl_fork() and opens PRs that only change composer.lock #8122

Description

@maia-andre

The scheduled Update Psalm baseline workflow (.github/workflows/update-psalm-baseline.yml) has been failing on every run since around 2026-08-20, and the PRs it opens do not contain baseline changes.

What happens

  1. composer run psalm:update-baseline runs psalm --threads=$(nproc) --update-baseline .... With more than one thread, Psalm 6 forks workers with pcntl_fork(), and the PHP shipped on the ubuntu-latest runner lists pcntl_* in disable_functions. Psalm dies:

    Uncaught Error: Call to undefined function pcntl_fork() in .../vendor/vimeo/psalm/src/Psalm/Internal/Fork/ForkContext.php:85
    Script psalm --threads=$(nproc) --update-baseline --set-baseline=tests/psalm-baseline.xml handling the psalm:update-baseline event returned with error code 1
    

    (On the stable branches it is reported as pcntl_fork() is disabled by php configuration (disable_functions directive).)

  2. The step has continue-on-error: true, so the job keeps going as if the baseline had been updated.

  3. The previous step, composer require --dev nextcloud/ocp:dev-<branch>, had already rewritten composer.lock. peter-evans/create-pull-request is used without add-paths, so it commits everything that changed and opens a [branch] Update psalm-baseline.xml PR whose only content is the new nextcloud-deps/ocp reference in composer.lock (+4/−4). tests/psalm-baseline.xml is not touched.

  4. Finally team-reviewers: server-backend fails with Reviews may only be requested from collaborators, which is what marks the run as failed.

Runs: https://github.com/LibreSign/libresign/actions/runs/33243943681 (2026-08-29), https://github.com/LibreSign/libresign/actions/runs/33178796997 (2026-08-28).

PRs produced this way, all changing only composer.lock: #8052, #8064, #8083, #8084, #8093 (merged) and #8118, #8119 (open).

Fix

The repository already handles the same problem elsewhere: psalm.yml sets ini-values: disable_functions= on setup-php (and so do the phpunit/behat/playwright/infection workflows). The baseline workflow only needs:

  • ini-values: disable_functions= in its setup-php step, so Psalm can fork;
  • add-paths: tests/psalm-baseline.xml in create-pull-request, so the composer.lock churn from the nextcloud/ocp install is never committed.

team-reviewers: server-backend is a separate decision (the team is not a collaborator of this repository); the run will stay red until it is removed or points to an existing team.

Verification on a fork

I ran the workflow on my fork with workflow_dispatch, with the fork's main/stable32/stable33/stable34 synced to upstream, once as-is and once with the two changes above (plus a test-only step that prints git status after Psalm, and the PR step disabled because the fork has no COMMAND_BOT_PAT):

  • As-is (https://github.com/maia-andre/libresign/actions/runs/33266309373): Psalm crashed with Call to undefined function pcntl_fork() in all four jobs, exactly as upstream.
  • With the fix (https://github.com/maia-andre/libresign/actions/runs/33266307137): Psalm finished in all four jobs (Baseline saved to tests/psalm-baseline.xml.). What was left modified after Psalm:
    • main: only composer.lock — the baseline is already current, so with add-paths the action would open no PR at all;
    • stable32, stable33: only tests/psalm-baseline.xml (the psalm-version header, since the file on those branches was last written by a different Psalm version);
    • stable34: composer.lock and the same one-line header change in tests/psalm-baseline.xml.

So after the fix the PRs contain only the baseline, and are only opened when it actually changed.

I'll open the PR for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      4. to release

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions