Skip to content

ci: build the standalone binary from one workflow - #344

Merged
lens0021 merged 4 commits into
mainfrom
ci/build-binary-on-pr
Aug 15, 2026
Merged

lens0021 merged 4 commits into
mainfrom
ci/build-binary-on-pr

Conversation

@lens0021

@lens0021 lens0021 commented Aug 15, 2026 •

Copy link
Copy Markdown
Collaborator

binary.yml now owns the standalone binary end to end. A pull request that touches the build inputs gets an x86_64 binary; release-please and nightly still call it through workflow_call, which builds the x86_64 + aarch64 matrix and does the attestation and the release upload. The tag input is what tells the two apart, the same way docker-image.yml does it.

That replaces the shape this PR started with, which split one artefact across build-binary.yml, a new binary-pr.yml, and a .github/actions/build-binary composite action. #354 has since landed and names workflows after what they build rather than when they run, and no single file can own the artefact's name while there are two. So build-binary.yml becomes binary.yml and the other two are deleted.

The job stays out of .tf/ruleset.tf. It is path-filtered, and a required check that never reports leaves a pull request unmergeable for good.

#337 (dunglas/frankenphp 1.12.4 → 1.12.6) is the first change this covers: it edits binary.Dockerfile and today gets no binary build at all.

The report step was hiding two failures

It ran the binary inside if out=$(./"$bin" version 2>&1); then, where set -euo pipefail does not fire, so a binary that builds but cannot execute still passed and merely printed "(version not reported)". Static linking fails at execution rather than at compilation, which is exactly the failure this check exists to catch, so version now fails the job.

Making it strict immediately surfaced the second one: php-cli --version exits 255 on this binary and always has. Embedding an app makes FrankenPHP resolve php-cli's first argument as a script path inside that app, so --version is looked up as a filename and PHP writes the fatal to stdout, where the old $(...) swallowed it. The PHP row has therefore read "(php-cli version not reported)" in every release to date. That second call is gone, and PHP's version now comes off the version line, which already carries it:

Field Value
FrankenPHP FrankenPHP v1.12.4 PHP 8.3.33 Caddy v2.11.4 h1:XKxk…
PHP 8.3.33

Verified against the nightly-2026-08-15 binary: version exits 0, php-cli --version and php-cli -v both exit 255, and the rewritten step produces the table above.

The English docs pick up the rename, plus the docker-build.yml → docker-image.yml mention #354 left behind. Translations are left to the translation workflow, so unit 23 of docs/Development/ko.wikitext will read as fuzzy until someone retranslates it.


Generated by Claude Code

@codecov

codecov Bot commented Aug 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@lens0021
lens0021 marked this pull request as ready for review August 15, 2026 14:33
@lens0021
lens0021 enabled auto-merge (squash) August 15, 2026 14:33
auto-merge was automatically disabled August 15, 2026 14:36

Head branch was modified

lens0021 added a commit that referenced this pull request Aug 15, 2026
A job id is the status check context. It is read in the ruleset's
required-checks list, next to `biome`, `phpcs`, `phpunit (master)` and
`typos`, where `build` and `build-and-check` say nothing about what ran.
#344 also showed the concrete cost: a second job named `build` put two
same-named check runs on one commit and made the required-check verdict
depend on which reported last. File names get the same treatment, so a
reader scanning `.github/workflows/` sees what each one runs.

Renames only, no behaviour change.

| what | old | new | required context |
| --- | --- | --- | --- |
| job in `docker-image.yml` | `build` | `docker-image` | yes |
| job in `smoke.yml` | `build-and-check` | `smoke` | yes |
| job in `deploy-docs.yml` | `build-and-deploy` | `deploy-pages` | no |
| file | `docker-build.yml` | `docker-image.yml` | n/a |
| file | `tf.yml` | `tofu.yml` | n/a |

`smoke.yml` bakes the docs site, asserts the output, then runs the
browser tests, so `bake` would have covered half of it. `deploy-pages`
is what the job actually does: publish to the `gh-pages` branch.
`tofu.yml` matches the workflow's own name and the tool it runs.

The `uses:` in `release-please.yml`, the path filter in `tofu.yml`, and
the two prose references in `smoke.yml` and `pr-preview.yml` follow the
file renames. Nothing references the three job ids.

Also drops `.github/workflows/dependencies`, a stray file from be87a48
holding a fragment of phan's Gadgets config. It has no extension, so
GitHub never treated it as a workflow.

## The required contexts live in Terraform

`.tf/ruleset.tf` declares the required checks, so it carries the renamed
contexts here rather than being clicked in the web UI.

Renaming a required context cannot be a single step: while the ruleset
still requires `build`, this pull request can never satisfy it, because
the job now reports as `docker-image`. So `build` and `build-and-check`
were dropped from the live ruleset through the API first, which is what
let this pull request go green. Applying this branch's `.tf` after merge
puts `docker-image` and `smoke` in their place and clears the drift.

Between those two moments the two gates are off. `deploy-pages` and
`binary` are not required contexts and need neither step.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lens0021 and others added 3 commits August 15, 2026 23:57
Nothing built binary.Dockerfile before merge. docker-build.yml and smoke.yml
only build the root Dockerfile, and the binary was compiled solely by
release-please.yml and nightly.yml, whose gate skips a run with no feat/fix
commit since the last nightly. A build(deps) digest bump of the static builder
therefore landed on main with no build behind it.

Move the build steps into a composite action and add binary-pr.yml, which runs
them on pull requests touching the binary, on one architecture, with no upload
and no attestation, and reports size, sha256 and the versions the binary answers
with into the step summary.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJtGZbbjBAHWmnC4QQyRUj
Only the non-required-check trap is worth writing down. The rest restated what
the workflow name, the path filter and the step names already say, and the
rationale belongs in the pull request, not in the file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJtGZbbjBAHWmnC4QQyRUj
`build` is a required status check context owned by docker-build.yml, so a
second job by that name put two same-named check runs on one commit and made the
required-check verdict depend on which reported last.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJtGZbbjBAHWmnC4QQyRUj
@lens0021
lens0021 force-pushed the ci/build-binary-on-pr branch from 4879572 to 1d1e975 Compare August 15, 2026 14:58
@lens0021 lens0021 changed the title ci: build the standalone binary on pull requests that touch it ci: build the standalone binary from one workflow Aug 15, 2026
binary.yml now owns the artefact end to end: a pull request that touches
the build inputs gets an x86_64 binary, and release-please and nightly
still call it for the full matrix, attestation and release upload.

Also stop the report step from swallowing a binary that builds but cannot
execute, which is how static linking usually fails. That turned up a
second bug it had been hiding: an embedded app makes php-cli read its
first argument as a script path, so `php-cli --version` has always exited
255 and the PHP row has always read "(php-cli version not reported)".
Take PHP's version off the `version` line, which already carries it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013HVqSpTstym5yySP1uFjAv
@lens0021
lens0021 force-pushed the ci/build-binary-on-pr branch from 823deea to 5264160 Compare August 15, 2026 15:21
@github-actions
github-actions Bot temporarily deployed to preview August 15, 2026 15:24 Destroyed
@lens0021
lens0021 merged commit d61f1f0 into main Aug 15, 2026
23 checks passed
@lens0021
lens0021 deleted the ci/build-binary-on-pr branch August 15, 2026 15:32
lens0021 pushed a commit that referenced this pull request Aug 15, 2026
…to static-builder-musl-1.12.6 (#337)

First bump to reach the standalone binary through a real build: #344 gave
binary.Dockerfile a pull-request job, so 1.12.6 was compiled and the
resulting binary run before this merged.
lens0021 added a commit that referenced this pull request Aug 15, 2026
The two shipped composite actions sat at the repo root as `action/` and
`action-check/`, sorting apart from each other and reading as leftovers.
They move to `actions/bake/` and `actions/check-translations/`, each
directory named after what the action does, the way #354 named the
workflows.

Breaking for anyone referencing `chaotic-ground/wikven/action@<ref>`:
that becomes `chaotic-ground/wikven/actions/bake@<ref>`. The docs
example moves with it. Still v0, so this is the moment to do it.

Renaming the paths meant auditing the config keyed on them, which turned
up two things that were already broken:

- release-please only listed `action/action.yml` as an extra file, so
the `x-release-please-version` pin in the check action has never been
stamped. Both are listed now.
- Dependabot

🤖 Generated with [Claude Code](https://claude.com/claude-code)'s
`github-actions` entry is `directory: /`, which scans
`.github/workflows` and a root `action.yml` only. Neither composite
action was ever in its view, and `git log --author=dependabot --
action/action.yml` is empty to prove it. It is `directories: [/,
/actions/*]` now, so the glob picks up whatever lands there next.

`pr-preview` and `deploy-docs` also gained `actions/bake/**` in their
path filters. The preview build is the only thing anywhere that runs
that action, and it was not watching it, which is the same shape of bug
#344 just fixed for the binary.

Verified: `yamllint --strict .` passes, the release-please config still
parses, and a repo-wide grep finds no surviving reference to the old
paths. Because this touches `docs/`, `pr-preview` runs on this PR and
exercises `./actions/bake` from its new location.

Not done here: `docs/Deploying/ko.wikitext` carries the old
`tree/main/action` link and will go fuzzy and 404 until someone updates
ko. Translating is not the code contributor's job. The check action is
still run by no CI anywhere, which is worth its own issue.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

No deployments
preview — 5264160a Deployed Aug 15, 2026 by github-actions[bot]
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.

1 participant