Skip to content

ci(release): install NASM on Windows, and prove the binaries have their drivers - #197

Merged
jasdeepkhalsa merged 3 commits into
masterfrom
claude/windows-build-resilience
Aug 31, 2026
Merged

jasdeepkhalsa merged 3 commits into
masterfrom
claude/windows-build-resilience

Conversation

@jasdeepkhalsa

Copy link
Copy Markdown
Member

The win32-x64 leg failed, which cancelled the remaining release jobs.

The failure

NASM not found - make sure it's installed and available on %PATH%
Failed module: library openssl builder for Windows

OpenSSL's Windows build assembles with NASM. It was present on the runner image until it wasn't, and spc doctor --auto-fix only repairs the prerequisites it knows about — so it reported a clean bill of health and the build died much later inside the openssl module, with nothing pointing at the real cause.

Unlike the musl failures, this is not transient. There is nothing to retry; it would have failed identically on every attempt. Installing NASM explicitly also puts the responsibility in this repo rather than on whatever the runner image ships next month.

The quieter problem in the same log

PHP Warning: copy(...\pgsql\lib\libpq.lib): No such file or directory
PHP Warning: copy(...\pgsql\include\libpq-fe.h): No such file or directory
PHP Warning: copy(...\pgsql\include\postgres_ext.h): No such file or directory

pdo_pgsql is built against libpq copied out of the postgresql-win archive, and every one of those copies failed. They are warnings, so the build carries on.

The smoke test was dbdiff --version, which passes whether or not a single database driver made it in. So a Postgres diff tool with no Postgres support would have built, smoke-tested green, and shipped.

The check

Point each driver at a closed port. PDO distinguishes the two cases precisely, with no live database needed:

condition PDO says
driver missing could not find driver
driver present, server unreachable SQLSTATE[08006] ... Connection refused

Confirmed against the real CLI:

$ dbdiff diff --server1-url "postgresql://u:p@127.0.0.1:1/x" ...
SQLSTATE[08006] [7] connection to server at "127.0.0.1", port 1 failed: Connection refused

Tested both directions locally — a working binary passes and exits 0; a stub emitting the missing-driver message is caught and exits 1, so CI fails rather than shipping it.

Applied to release-dry-run.yml too, so the dry run keeps testing what the release actually does.

Not addressed here

The underlying reason the libpq copies fail is upstream in static-php-cli's postgresql-win handling. This PR makes that condition loud rather than fixing it — worth a separate look, but a silent driverless release is the more urgent problem.

🤖 Generated with Claude Code

…ir drivers

The win32-x64 leg failed, which cancelled the rest of the release:

  NASM not found - make sure it's installed and available on %PATH%
  Failed module: library openssl builder for Windows

OpenSSL's Windows build assembles with NASM. It was present on the runner
image until it was not, and `spc doctor --auto-fix` only repairs the
prerequisites it knows about, so it reported a clean bill of health and the
build died much later inside the openssl module with nothing pointing at the
real cause. Installing it explicitly also puts the responsibility here rather
than on whatever the image ships next month.

Unlike the musl failures this is not transient, so there is nothing to retry:
it would have failed identically on every attempt.

The same log carried a quieter problem. pdo_pgsql is built against libpq
copied out of the postgresql-win archive, and every one of those copies had
failed:

  PHP Warning: copy(...\pgsql\lib\libpq.lib): No such file or directory
  PHP Warning: copy(...\pgsql\include\libpq-fe.h): No such file or directory

Warnings, not errors, so the build continues. The smoke test then ran
`--version`, which passes whether or not a single database driver made it in
— so a Postgres diff tool with no Postgres support would have shipped and
looked healthy.

The smoke test now points each driver at a closed port. PDO reports a missing
driver as exactly "could not find driver" and an unreachable server as a
connection error, which distinguishes the two without needing a live database.
Verified both ways locally: a working binary passes, and a stub that emits the
missing-driver message exits 1.

Applied to release-dry-run.yml as well, so the dry run keeps testing what the
release does.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added bug postgres Related to Postgres labels Aug 25, 2026
jasdeepkhalsa and others added 2 commits August 25, 2026 20:57
The patch that added the NASM step and the driver smoke tests located the end
of a step by searching forward for the next "- name:". The Windows smoke test
is the last step in its job, so that search ran past the end of the job and
the replacement swallowed everything up to the next step in the *following*
job — taking the artifact upload and a whole job with it.

actionlint caught it:

  job "publish-npm" needs job "github-release" which does not exist
  job "pr-comment" needs job "npm-dry-run" which does not exist

Both files are restored from master and re-patched by exact string match, so
nothing depends on where the next step happens to be. Job counts now match
master exactly (5 and 4), and the diff against master removes precisely the
two one-line `run:` commands it is meant to replace.

actionlint now runs clean across every workflow, checked locally rather than
discovered in CI.

Co-Authored-By: Claude <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@jasdeepkhalsa
jasdeepkhalsa merged commit 8d24831 into master Aug 31, 2026
68 checks passed
jasdeepkhalsa added a commit that referenced this pull request Sep 4, 2026
…er (#203)

The `3.0.0-rc.10` dry run built a `win32-x64` binary with **no
`pdo_pgsql`**. The driver smoke test from #197 caught it:

```
##[error]postgresql driver missing from the binary
```

## Root cause — upstream in static-php-cli 2.8.3

`unzipWithStrip()` drops an archive's single top-level directory. For
the EnterpriseDB Windows zip that directory is `pgsql`. Its
`postgresql_win` builder then copies from the level it just stripped:

```php
copy($this->source_dir . '\pgsql\lib\libpq.lib', ...);
```

```
copy(...\postgresql-win\pgsql\lib\libpq.lib): Failed to open stream
copy(...\postgresql-win\pgsql\include\libpq-fe.h): Failed to open stream
```

Every copy fails as a PHP **warning**, so the build carries on and
produces a Postgres diff tool that cannot reach Postgres — and
`--version` reports it as perfectly healthy.

## The fix

Re-create the stripped level as **junctions** after `spc download` — no
duplication, and it becomes a no-op the moment SPC fixes the path (it is
guarded on `pgsql` not already existing).

A following check then fails the build outright if `libpq.lib` is still
missing, and prints the tree. The next person to hit this gets evidence,
not a warning buried in 36,000 log lines.

Applied to `release-dry-run.yml` too, so the dry run keeps testing what
the release does.

## How this was found

Not by guessing. The dry run failed → the smoke test named the symptom →
SPC's `postgresql_win.php` showed the expected path → `unzipWithStrip()`
showed the actual one. The fix follows from the evidence rather than
preceding it.

Worth noting the sequence: #197's NASM fix made the Windows build
*succeed*, which is what allowed it to produce a silently broken binary
— and #197's smoke test is what stopped it shipping.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug postgres Related to Postgres

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant