AGENTS.md

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: .desktop file (with an [AppImageHub] section of X-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/ (notably app_teaser.html, app_notes.html), feed.json, search.json: the site. app.html sets post = page, so app templates use post.desktop.AppImageHub.X-AppImage-* etc.

How testing a submission works

  1. .github/workflows/test.yml (on PRs and pushes touching data/**) runs code/worker.sh data/<Name> for each added or changed file, under a per-app timeout, 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/ and apps/. On PRs it stops there; on master it commits the result ([ci skip]). Afterwards the workflow collects a pr-result artifact: PR number, screenshot (or screen capture on failure), code/diagnose.sh hints and the excerpt of the log around the first error, and the libc flags.
  2. .github/workflows/publish-pr-screenshot.yml runs on workflow_run of “Test” (from master, 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 the SCREENSHOT_UPLOAD_TOKEN secret (classic PAT), falling back to assets of the ci-screenshots release, which it prunes. Renewing the token: see MAINTAINER.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 eval anything from it; cross-check the PR number against the tested commit; only accept hints listed by code/diagnose.sh --list from master, 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 to publish-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.sh leave background processes behind. Anything started with & inherits stdout, which is piped into tee; a survivor keeps the pipe open and the job hangs until the Actions timeout instead of failing. The cleanup EXIT trap kills them and unmounts; redirect the output of new background processes, and wrap X11 calls in timeout.
  • worker.sh runs with set -v (and partly set -x), so the log contains its own source lines and traces. Patterns in code/diagnose.sh for the worker’s own messages are anchored with ^, and the excerpt drops lines that are verbatim lines of worker.sh or 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 --help in xterm; screenshot checks only warn for them.
  • Thresholds in code/check-screenshot.sh were calibrated on the ~1500 screenshots in database/. When changing them, re-run over those screenshots (OMP_THREAD_LIMIT=1 for tesseract, or it crawls when run in parallel) and report how many would change outcome.
  • Adding apt packages to test.yml: bump the cache version: 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.sh can 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), then bundle exec jekyll build on a copy with only a few apps/*.md for speed. Note: feed.json is 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 in test.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 a data/ 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 touches data/. New PR comments from master’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.sh does this for all open PRs that change one file in data/ and last tested green (-n to 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.