AGENTS.md
Notes for AI coding agents (and humans) working on this repository.
What this repository is
AppImageHub, the catalog of AppImages at https://appimage.github.io, built by GitHub Pages (Jekyll) from this repository.
data/<Name>: one file per application, submitted by contributors in PRs. Its first line is a download URL or a GitHub repository URL; nothing else is read.database/<Name>/: generated by CI from the AppImage:.desktopfile (with an[AppImageHub]section ofX-AppImage-*keys), icon,screenshot.png, AppStream metainfo. Do not edit by hand.apps/<Name>.md: generated by CI; YAML front matter that the Jekyll templates render. Do not edit by hand._layouts/,_includes/(notablyapp_teaser.html,app_notes.html),feed.json,search.json: the site.app.htmlsetspost = page, so app templates usepost.desktop.AppImageHub.X-AppImage-*etc.
How testing a submission works
.github/workflows/test.yml(on PRs and pushes touchingdata/**) runscode/worker.sh data/<Name>for each added or changed file, under a per-apptimeout, on Xvfb:- downloads the AppImage (resolving GitHub repository URLs via the API),
checks its type, mounts it with a separate runtime (never executes the
AppImage’s own runtime), runs
appdir-lint.sh, finds the icon; code/check-libc.sh: does it need a compatible C library on the host? (X-AppImage-Libc=none|bundled|host,X-AppImage-Runtime,X-AppImage-Self-Contained,X-AppImage-Glibc-Required=GLIBC_2.xx, stored with the prefix because YAML would turn 2.40 into the number 2.4; an upper bound, as not every library in an AppImage is necessarily loaded);- runs the application in firejail without network, waits 30 s, takes a screenshot of the active window;
code/check-screenshot.sh: fails on an (almost) empty window or an error message found by OCR (tesseract);- writes
database/andapps/. On PRs it stops there; onmasterit commits the result ([ci skip]). Afterwards the workflow collects apr-resultartifact: PR number, screenshot (or screen capture on failure),code/diagnose.shhints and the excerpt of the log around the first error, and the libc flags.
- downloads the AppImage (resolving GitHub repository URLs via the API),
checks its type, mounts it with a separate runtime (never executes the
AppImage’s own runtime), runs
.github/workflows/publish-pr-screenshot.ymlruns onworkflow_runof “Test” (frommaster, with write permissions, because PRs come from forks whose runs have a read-only token) and posts or updates one comment on the PR, marked<!-- appimagehub-test-result -->. Screenshots are uploaded as GitHub attachments with theSCREENSHOT_UPLOAD_TOKENsecret (classic PAT), falling back to assets of theci-screenshotsrelease, which it prunes. Renewing the token: seeMAINTAINER.md.
Rules that are easy to get wrong
- The artifact is untrusted (it comes from a PR’s test run). In the publish
workflow never execute or
evalanything from it; cross-check the PR number against the tested commit; only accept hints listed bycode/diagnose.sh --listfrommaster, and values of known form; put log text only inside a code fence (four backticks, longer runs are neutralized). - workflow_run workflows always run from
master. Changes topublish-pr-screenshot.yml(and to the hint list it validates against) only take effect after merging; a PR cannot test them.workflows:takes the workflow name (Test), not its path. - Never let
worker.shleave background processes behind. Anything started with&inherits stdout, which is piped intotee; a survivor keeps the pipe open and the job hangs until the Actions timeout instead of failing. ThecleanupEXIT trap kills them and unmounts; redirect the output of new background processes, and wrap X11 calls intimeout. worker.shruns withset -v(and partlyset -x), so the log contains its own source lines and traces. Patterns incode/diagnose.shfor the worker’s own messages are anchored with^, and the excerpt drops lines that are verbatim lines ofworker.shor traces (^+).- The test runs without network (
firejail --net=none); many applications show “update check failed” and similar. That is why soft error words only warn. - Terminal applications (
Terminal=true) run with--helpin xterm; screenshot checks only warn for them. - Thresholds in
code/check-screenshot.shwere calibrated on the ~1500 screenshots indatabase/. When changing them, re-run over those screenshots (OMP_THREAD_LIMIT=1for tesseract, or it crawls when run in parallel) and report how many would change outcome. - Adding apt packages to
test.yml: bump the cacheversion:next to the list.
Testing changes
- Shell:
bash -n,shellcheck -S warning code/*.sh,actionlint .github/workflows/*.yml. code/diagnose.sh,code/check-screenshot.sh,code/check-libc.shcan be run locally on a saved log, a PNG, or an AppImage plus its extracted AppDir (unsquashfs -o <offset>, where the offset is the end of the runtime’s ELF section headers).- Site:
bundle install(Gemfile:github-pages), thenbundle exec jekyll buildon a copy with only a fewapps/*.mdfor speed. Note:feed.jsonis only valid JSON if the last page in permalink order is an app (pre-existing quirk of its comma logic). - PRs from forks must change exactly one file in
data/and nothing else (checked first intest.yml); PRs from branches in this repository are exempt. - End-to-end: the Test workflow only runs when the PR touches
data/**. Test in a separate throwaway PR (from a branch in this repository) that adds a throwaway change to adata/file (e.g., a trailing newline; only the first line is read) on top of your change; check the run and the PR comment, then close it. Doing this in the real PR leaves a test-result comment there that nothing removes once the PR no longer touchesdata/. New PR comments frommaster’s publish workflow appear only for PRs whose head is still the tested commit. - To re-test an existing contributor PR with new workflow code, close and reopen
it (a re-run would reuse the old workflow files).
code/retest-prs.shdoes this for all open PRs that change one file indata/and last tested green (-nto only list them).
Conventions
- Keep the shell style of the surrounding code (plain bash,
[ x"$A" == x... ]in old code is fine to leave). - Messages meant for contributors should say what to do, in plain words.
- Existing entries are not re-tested automatically; new checks and flags apply to PRs and to entries as they are updated.