Conversation
…ase tag is an ARG so a bump is one flag, and the php list line derived its suite from a hardcoded 'bookworm' — on any other base that installs the wrong distribution's packages or none. trixie publishes both php 8.5 (packages.sury.org) and llvm 20/21/22 (apt.llvm.org), checked before the bump, not assumed
…on a macOS runner: MC_GATE=1 stays the shorthand for both, but CI wants parity WITHOUT the fixpoint — that one is hours and answers a question only a bootstrap or a MemoryAbi VERSION bump can re-open. The macOS half is /etc/os-release, which is Linux-only; sw_vers covers the host line so the same definition serves both platforms instead of a workflow growing its own copy of the steps
…ate: ci.yml runs on push to main and on every PR, restores the compiler it built last time and self-hosts from it, so the Zend cold seed is the fallback a cache miss or a bootstrap gap falls into rather than the loop — gate.sh already validates a cache against arch+clang+php and escalates on its own, so a stale one costs a slow run, never a wrong answer. macOS runs the same gate.sh bare, because the two platforms diverge exactly where nobody is watching. nightly.yml becomes gate.yml: difftest weekly, the fixpoint only when asked for, since the tree has been at a fixpoint long enough that running it every night buys nothing
…ian dropped the package after bookworm, so the very first apt layer failed on the new base. llvm.sh stopped needing it in the same breath — on a new Debian it writes the deb822 source itself instead of calling add-apt-repository — but it does call wget by name, which the image did not carry: curl was next to it, and curl is not a stand-in for a script that hardcodes the other one
…ot just when it is called as bin/manticore: the three finders anchored on argv[0], which is what the caller typed — a bare "manticore" reached through $PATH has no slash in it at all, so they gave up and the compile died with 'prelude not found'. That is every shape a user meets: the container image (PATH=/opt/manticore/bin), a release tarball, /usr/local/bin/manticore as a symlink into a lib dir — while the dev tree stayed green because it always spells the path out. self_dir() resolves the real executable (realpath of a slashed argv[0], then /proc/self/exe, then a $PATH walk) and the finders hang off that; tools/install_smoke.sh compiles one str_pad program through all three entry points and fails on the pre-fix binary
… install_smoke: php was baked into every layer, but the compiler that ships is native and never asks for an interpreter — 'runtime' branches off a 'base' that carries clang and the -dev libraries alone, and 'toolchain' (php 8.5, the seed and the difftest oracle) stays what run_tests.sh and the workflows build. The runtime image calls 'manticore version' by the bare name during the build, which is exactly the shape that lost the prelude before self_dir(); gate.sh runs tools/install_smoke.sh for the same reason — the suite always calls bin/manticore by path, so it cannot see that class of break
…stall.sh takes them: release.yml builds the runtime image cold from the tagged source on both Linux arches (no cache is trusted for a release), checks the binary's own version against the tag, compiles a str_pad program THROUGH the image the way a user would, then pushes the two arch tags and merges them into one multi-arch manifest. macOS is cold-seeded on the runner and tarballed beside them. install.sh grew a published-build path in front of the source build — verified against SHA256SUMS, needs no php at all, and any miss (no build for the platform, no network, a checksum that disagrees) falls through to the bootstrap instead of failing
…file NAMED bin: 'cp -R <file> <missing dir>' creates the destination as a copy of the file, so the fallback that was supposed to catch it could never run — the first cp always succeeded and produced a tarball whose compiler could not find its own lib/
…: the manticorephp namespace on Docker Hub is an ORGANISATION, and an organisation there is a paid plan — while the same name already exists on GitHub's registry, costs nothing for a public package, and authenticates with the workflow's own token, so there is no registry secret to hand out, rotate or leak. Both push steps log in to ghcr with github.token and the two jobs carry packages: write
…s on alpine 3.23, run_tests.sh takes --alpine (its own image tag and its own compiler-cache volume — a glibc binary does not run in a musl container), and gate.yml carries it as an opt-in dispatch input marked continue-on-error. ★Alpine splits php far finer than Debian: 'php85' alone has no ctype, and the Zend seed dies on the first line of the bootstrap with 'Call to undefined function ctype_digit()' — docs/install.md's apk line was missing eight packages Debian's php8.5-cli happens to bundle. The toolchain image is 725 MB against the Debian one's 2.0 GB, which is the reason musl is worth keeping warm even before it is green
…de under lib/ is part of the SHIPPED layout, and a checkout never reads it — the compiler there resolves <exe>/../prelude, the source — so every self-hosted build left it at whatever the last COLD seed wrote and nothing local could notice. It surfaces only where lib/ travels without the tree: the CI compiler cache, tools/install_smoke.sh, a release tarball built from a warm compiler. Two lines, and the warm path now ships what it built
…nt tracks 13: glibc is backwards compatible and not forwards, so a binary linked against trixie's 2.41 refuses to start on bookworm's 2.36 — a release has to run on the distribution someone already has. One build arg in release.yml, since DEBIAN_TAG was already a knob. ★That immediately exposed the other half: software-properties-common exists on bookworm and NOT on trixie, and llvm.sh needs it on exactly the base where it exists (bookworm calls add-apt-repository; a newer Debian writes the deb822 source itself), so the package list now probes for it instead of naming it — dropping it unconditionally breaks 12, naming it unconditionally breaks 13, and both have now happened. docs/install.md also stopped claiming the output binaries are 'fully static … libc and nothing else', which they have never been
…es of 'rm: Permission denied': the cache directory is a host mount shared by two users — actions/cache restores the tree as the RUNNER, the container runs as uid 1000, and unlinking an entry needs write permission on the DIRECTORY that holds it, not on the file — so 'chmod 777 ci-cache' fixed the top level and left every restored subdirectory unremovable. The job passed regardless, the cache stayed at whatever the first run wrote, and every later run cold-seeded for ever while the warm path looked armed. Both halves: the workflows chmod -R, and save_compiler_cache now reports 'saved'/'NOT saved' instead of letting a dead cache pass for a live one
…ow whether Alpine builds should not drag difftest along for hours, so the glibc parity gate is behind a 'parity' input that the weekly schedule ignores (a schedule carries no inputs, so it tests github.event_name too — otherwise the one run that matters most would silently stop happening)
…res on a tag and CREATES the release, so clicking 'Create release' in the UI — which makes the tag first — would fire it into a 'release already exists' failure after every artifact had been built. It now uploads into an existing one and creates it only when there is none, so pushing the tag and using the UI both end the same way
…m pull requests: 'gh release create --generate-notes' lists merged PRs, and this tree is pushed to directly — 144 commits since v0.10.0, one of them through a PR — so the generated section would be empty and read as a release that changed nothing. The subjects here are written as '<what changed>: <why>', so the part before the first colon is already the summary line; the rationale stays in the log, which the notes link as a compare range. Needs fetch-depth: 0, since a depth-1 checkout has neither end of the range
…n still said two targets when there are four, and named no published image at all — it now leads with 'docker run ghcr.io/manticorephp/compiler', explains why -u $(id -u) is not decoration, and says why php lives in 'toolchain' and not in the image a user runs. The platform table stops calling musl supported and calls it prepared-not-gated, which is what it is. And the out-of-memory entry now carries the measured number rather than only the Zend memory_limit: the seed builds the whole compiler as one LLVM module and peaks just under 7 GiB — 6.83 on glibc, 6.94 on musl — so an 8 GB VM is at the edge and the libc is not the variable
…t full suite on Alpine named them: 1141/20 on a tree that is green everywhere else, and the failures came in three clean clusters — every date_* case (TzInfo.php reads /usr/share/zoneinfo, and Alpine ships no tz database at all), simplexml_*/dom_* (prelude/xml.php binds libxml2 through FFI and the dev package is what provides the linkable .so) and iconv_basic (musl keeps iconv inside libc and has no libiconv.so, while Iconv.php binds it by name). What is left over — the async reactor pair, array_recursive_merges, ref_cell_superglobal, http_sapi_bridge — is not packaging and is the real musl surface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three commits, all plumbing — no compiler change.
ARG DEBIAN_TAG=13), and the sury list line derives its suite from/etc/os-releaseinstead of a hardcodedbookworm. surydists/trixieand apt.llvm.org trixie 20/21/22 were checked before the bump; the first image build in this PR is the real proof.gate.sh:MC_DIFFTEST/MC_FIXPOINTsplit out ofMC_GATE(MC_GATE=1stays the shorthand for both, sorun_tests.sh --gateis unchanged), and it runs bare on a macOS runner —/etc/os-releaseis Linux-only,sw_verscovers the host line. One definition of the steps, three runners.ci.ymlarmed and WARM: push→main, every PR, dispatch; linux arm64 + amd64 in the container and macos-15 bare. Each job restores the compiler it built last time (~15 MB,actions/cache) and self-hosts from it; the Zend cold seed is what a cache miss or a bootstrap gap falls into, not the loop. gate.sh validates a cache against arch+clang+php and escalates on its own, so a stale one costs a slow run, never a wrong answer. Saved withif: always()— a red suite still leaves a compiler worth keeping.nightly.yml→gate.yml: difftest weekly, the fixpoint only when asked for. It is hours, and only a bootstrap or a MemoryAbi VERSION bump re-opens the question it answers.Verified locally: gate.sh bare on macOS with a warm cache — restore →
bin/build→ stdlib pass 2 (violations=0) → the filtered case green. actionlint clean.⚠ This PR's own run is the first time any of it has executed on GitHub, and the first time the trixie image has been built at all.