ci: ask the AppImage what it bundles, and whether it starts - #584
Merged
Conversation
PathGao
force-pushed
the
ci/appimage-checks
branch
from
August 11, 2026 12:49
9946443 to
3295c23
Compare
PathGao
force-pushed
the
ci/appimage-checks
branch
from
August 11, 2026 13:08
3295c23 to
d2a5339
Compare
Base automatically changed from
ci/restore-cache-key-and-package-list
to
master
August 11, 2026 13:33
PathGao
force-pushed
the
ci/appimage-checks
branch
from
August 11, 2026 13:33
d432237 to
75803b6
Compare
Stacked on ci/one-linux-dependency-list. Two questions about the Linux artifact that nothing has been answering, and one comment that was about to become false. `check-appimage-libraries.sh`, on every pull request. strip-appimage.sh proves its six libraries are gone afterwards; that is "we removed what we meant to", not "six is still the right number". What decides the right number is not in this repository -- `tauri build` fetches linuxdeploy-plugin-gtk from the tip of someone else's branch on every run, so the set copied into the AppDir can change with no commit here, no pull request and no notification. The script intersects what is bundled with the AppImage project's own excludelist and requires the result to equal the strip list exactly, in both directions. It reads that list out of strip-appimage.sh rather than restating it. It runs on the pull request build because that AppImage is the un-stripped one, which for this question is the right artifact rather than a worse one. It only became comparable when #580 moved this job to the release's Ubuntu. `smoke-appimage.sh`, on the release, after the re-sign and before the upload. strip-appimage.sh said a CI smoke test cannot catch this defect because the runner's Mesa is the one the libraries came from -- true of the runner, and only of the runner. A container is another distribution's userspace on the same kernel, which is a host that can disagree. The comment now says so. Liveness is not the check. #499 records that the GTK shell survives while WebKit's WebProcess aborts behind a blank window, so both defects this exists to catch would have passed a "is it still running" test. It greps for the abort, and keeps the liveness check as the backstop for a reworded one. Both scripts also run on pull requests, after a strip, and that is the point rather than thoroughness: smoke-appimage.sh would otherwise reach the release path having never run anywhere, and strip-appimage.sh has never run outside a release -- it failed in two of the three v2.7.2 release attempts. Roughly three minutes on a twelve-minute job. Also, one line in dependabot.yml: the github-actions ecosystem covers `uses:` and not `runs-on:`, so nothing proposes ubuntu-24.04 -> 26.04 and nobody should assume something is watching. Three assertions, each checked by mutation and each failing alone: smoking before the strip, dropping the release smoke, and restating the library list in the new script. 979 pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ing on it
The check's first run found something real and then drew the wrong conclusion
from it. Run 31493065830, on the pull request build:
Bundled libraries the excludelist says must come from the host:
libwayland-client.so.0
strip-appimage.sh removes a library nothing bundles any more:
libwayland-cursor.so.0 libwayland-egl.so.1 libwayland-server.so.0
libxcb-render.so.0 libxcb-shm.so.0
Those five are deliberate. #499 named libwayland-client.so.0 as necessary and
sufficient and added five more that "belong to the host graphics stack for the
same reason and are on the same excludelist" -- prophylaxis against the plugin
starting to bundle them, and `rm -f` costs nothing when they are absent. A build
not bundling them is not a defect, so it is a notice now. A seventh appearing is
still an error, which is the direction that matters.
Worth printing, though, because the two builds disagree and nobody knew. In the
release, `rm -v` reported all six removed in both v2.7.2 and v2.7.3 -- they were
all there. On the pull request's shorter package list, only one is. So the two
jobs have been producing different AppImages, and #581's package prune will
change what a release bundles rather than being the no-op its own message
claimed. The direction is right -- fewer host-coupled libraries is the goal --
but "no behaviour change" was verified against "it builds and produces three
bundles", not against the contents.
Which difference does it, the package list or the linuxdeploy build.yml
pre-downloads, is not isolated. Once both jobs install the same packages, the
next release's `removed` lines say.
The assertion holding the list to one home now exempts comments, the same way
the Ubuntu one does: the new comment names a library while explaining what was
measured, and tripped it. 979 pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rom a host First real run, on the pull request rather than on a release: host graphics stack: mesa 1:26.1.6-1 Markpad: error while loading shared libraries: libfontconfig.so.1 exit 127 Not the defect this is looking for. An AppImage deliberately does not carry libfontconfig -- it is on the same excludelist as the six strip-appimage.sh removes, and for the same reason -- so it expects the host to have it. A bare archlinux container is not a desktop and does not. fontconfig and a font go in beside xvfb and mesa. And a missing host library now says so, instead of being reported as the app quitting early: the two look identical at exit 127 and mean opposite things. Worth recording that the container's mesa is 1:26.1.6-1, which is the version #498 was reported on. The environment is the failing case, not an approximation of it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Naming the host's libraries individually is a round of CI each. Run 31494803899 wanted libfontconfig.so.1; with that added, run 31497012965 wanted libfribidi.so.0. There is no reason to think that was the last one. The set is not arbitrary. An AppImage deliberately does not carry these -- they are on the same excludelist as the six strip-appimage.sh removes, and for the same reason -- so what it needs from a host is GTK's own dependency closure, which is exactly what a machine that can run a GTK application has. Installing gtk3 asks for all of it in one go.
PathGao
force-pushed
the
ci/appimage-checks
branch
from
August 11, 2026 14:10
28dad09 to
4001ce8
Compare
This was referenced Aug 12, 2026
PathGao
added a commit
that referenced
this pull request
Aug 12, 2026
…660) * docs: bring the release runbook and the syntax reference up to 2.7.4 Four claims in the docs describe behaviour that PRs since 2.7.3 changed, and two features shipped without reaching the file that documents what Markpad can do. RELEASING.md - snapcraft.yaml no longer builds the app; it unpacks the release's own .deb (#579), so the `npm ci` note and the `rust-deps` troubleshooting row both described a file that no longer exists in that shape (#577). - The .deb/.rpm coverage note still said *Check for Updates…* offers an update and then fails to install it. #573 asks `self_update_supported` first, so it says where updates come from instead. - Adds the AppImage checks (#584, #658) as their own troubleshooting row, and notes that release builds are serialized (#612). README, README.zh-CN - The same pre-#573 claim, in both languages. The Chinese one also told .deb/.rpm users to update "through their distribution channels", which is the sentence #566 removed from the English one — there is no apt or dnf repository. snapcraft.yaml - The comment pointed at .github/workflows/test_snap.yml, deleted in #601. samples/markdown-syntax{,.zh-CN}.md - Lists: Enter continues the marker, Tab changes level, Enter on an empty item leaves the list (#636), and the three list chords (#652). - Tables: cell, row and column keys, why deleting a row has no chord (#645, #653). - Links: Ctrl/Cmd+K (#652). npm test 904 pass, vitest 365 pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(syntax): drop two design arguments that belong in the PRs, not here The syntax reference carries no issue numbers, no history and no defence of a decision anywhere in its 500 lines; where it does give a reason -- the three deliberate incompatibilities -- the reason tells the reader what to write instead. Two sentences I added argued for the design at the reader: that four other editors use Mod+K, and why deleting a row has no chord while deleting a column does. Neither changes anything the reader would type. What is left of the second is the part that was actually useful: to delete a row, delete its line. * docs(readme): drop the only issue number a reader ever sees #570 was the last issue number in either README, and it was one I added a few days ago. It is a closed bug report, and after #573 the sentence it was attached to describes ordinary behaviour -- so a reader asking "how does my .deb update" now clicks through to a fault that no longer exists. The half-sentence in front of it went for the same reason: "rather than offering one it cannot install" describes what the app used to do. What is left is what the reader needs -- .deb and .rpm are one-time installs, there is no apt or dnf repository, and Check for Updates says so. Both READMEs keep the Report a Bug link, which is the only issue link either of them had before. * docs(releasing): cut the post-mortems back out of the runbook This file is what you read on the day you cut a release. Over three days in August I turned it into a runbook with post-mortems threaded through it: which run pushed Chocolatey 2.7.2 at 15:37, that the snap served 2.6.11 for three months and six versions, which two of the three v2.7.2 attempts the AppImage strip failed in, how the 2.7.2/2.7.3 lock skew was found. All true, none of it changes what you do next, and it sits between you and step 5 while a build is running. Test applied to each one: can it change an action taken on release day. Gone: the "Why package managers publish after the release" section entirely -- its one operational sentence (workflow_dispatch works against a published tag, the only way to exercise snapcraft.yaml) moves into step 7, where you would need it. The failure histories in three troubleshooting rows, keeping the symptom and the fix. The placeholder-pubkey era. Two design defences. Kept: reasons that stop you doing the wrong thing -- why not to create anything at alecdotdev/Markpad, why the Cargo.lock bump is the one that gets forgotten. A prohibition without its reason gets deleted as superstition by whoever comes next. 1957 -> 1563 words. The version before I started was 883. --------- Co-authored-by: PathGao <gaoyanbo@gaoyanbodeMacBook-Air.local> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
Two questions about the Linux artifact that nothing has been answering, and one comment this makes false.
check-appimage-libraries.sh— is six still the right number?strip-appimage.shproves its six libraries are gone after the strip. That is "we removed what we meant to remove". It cannot say whether six is still the right list, and what decides that is not in this repository:tauri buildfetches the plugin that decides which libraries get copied into the AppDir from the tip of someone else's branch, on every run. It can change with no commit here, no pull request and no notification — the same shape as a runner image moving undermacos-latest, one repository further away.The script intersects what the AppImage bundles with the AppImage project's own excludelist and requires the result to equal the strip list exactly, in both directions:
It reads the list out of
strip-appimage.shrather than restating it. The excludelist is fetched rather than vendored — it growing is the signal, and a copy here would be a second thing to keep current. A failed fetch is a failed check, never a pass.On the pull request build, deliberately. That AppImage is the un-stripped one, which for this question is the right artifact rather than a worse one: it shows what linuxdeploy actually did before anything was taken back out. It only became comparable at all when #580 moved this job onto the release's Ubuntu.
smoke-appimage.sh— does it start?strip-appimage.shsaid:True of the runner, and only of the runner. A container is another distribution's userspace on the same kernel, which is a host that can disagree. The comment now says so.
Two things recorded in #463 and #498 make it testable:
LIBGL_ALWAYS_SOFTWARE,WEBKIT_DISABLE_DMABUF_RENDERERandWEBKIT_DISABLE_COMPOSITING_MODEwere all tried and none helped, so software rendering under Xvfb reproduces it.Could not create default EGL display: EGL_BAD_PARAMETER. Aborting...Liveness is not the check, and this is the part worth reading. #499: "the window comes up blank while the GTK shell survives". The main process stays up; WebKit's WebProcess is what aborts. A "is it still running" test would have passed through both defects this exists to catch. So it greps for the abort, and keeps liveness as the backstop for a reworded one.
On the release it sits after the re-sign, so it starts the bytes
latest.jsonpoints at, and before the upload, so a failure leaves the draft without a Linux artifact — andgenerate-update-feedrequiresbuildto have succeeded, so it does not run either. Nothing is published; nothing was ever installable.Both also run on pull requests, and that is the point
Not thoroughness. Without it:
smoke-appimage.shwould reach the release path having never run anywhere — the exact failure mode this series has been about;strip-appimage.shhas still never run outside a release, and it failed in two of the three v2.7.2 release attempts.The pull request now does what the release does, in the release's order: build → check what is bundled → strip → start it. Smoking before the strip would reproduce #498 rather than test for it, so the order is asserted.
Roughly three minutes on a twelve-minute job. If that stops being worth it, path-filter the two steps rather than deleting them.
Also
One line in
dependabot.yml: thegithub-actionsecosystem coversuses:and notruns-on:. Nothing proposesubuntu-24.04→ubuntu-26.04, and nobody should assume something is watching.Tests
Three assertions, each checked by mutation, each failing alone:
npm test— 979 pass.What this pull request cannot tell you
smoke-appimage.shhas never run anywhere. Its first execution is this pull request's own Linux job — which is precisely why it is on pull requests and not only on the release. If it is wrong, it is red here instead of red on a release.🤖 Generated with Claude Code