Skip to content

Infra: PR preview workflow — per-PR web preview URL + Windows/macOS desktop builds #77

@petegordon

Description

@petegordon

Goal

Make every PR testable fully and in isolation, the way petegordon/tandemonium does it — a per-PR preview URL — but extended so the desktop app is testable too, not just the web build. Each PR should surface:

  • a hosted web preview URL (browser overlay, isolated per PR), and
  • downloadable Windows .exe and macOS .dmg/zip installer builds,

all posted into a single sticky PR comment, and torn down when the PR closes.

Reference: how tandemonium does it

tandemonium's PR Preview Deploy workflow (.github/workflows/pr-preview.yml):

  • Triggers on pull_request: [opened, synchronize, reopened, closed].
  • Stages the site into _site/, rewrites <base href> to /pr-preview/pr-<N>/, stamps a version string.
  • Uses rossjrw/pr-preview-action@v1 to publish to the gh-pages branch under umbrella-dir: pr-preview and auto-comments the preview URL; action: auto also cleans up the preview on close.
  • permissions: contents: write, pull-requests: write; concurrency: gh-pages-write.

That workflow is web-only. We additionally want the desktop installers.

The constraint (why this is an infra issue, not just a workflow drop-in)

rossjrw/pr-preview-action requires GitHub Pages to be served from the gh-pages branch. Our production site is currently served from the "GitHub Actions" Pages source with a custom domain (lab.usersfirst.games), via deploy-pages.yml (actions/configure-pagesupload-pages-artifactdeploy-pages). GitHub Pages supports only one source at a time, so we can't naively add the branch-based preview action without breaking the live deploy. There is no gh-pages branch today.

Options for the hosted web preview

  1. Migrate production Pages to branch-based (gh-pages) and have deploy-pages.yml publish the prod site to the branch root, with PR previews under /pr-preview/pr-<N>/. Most faithful to tandemonium; touches the live site, so needs care + a Pages settings change (manual, repo-admin).
  2. Host PR web previews on an external service (Cloudflare Pages / Netlify) — clean per-PR URLs, but adds an account + secrets.
  3. Ship the web preview as a downloadable _site artifact instead of a hosted URL — zero infra conflict, but not a click-to-open URL.
  4. Desktop-only first — skip the hosted web URL for now; deliver Win/macOS installer artifacts + sticky comment immediately (no Pages conflict), and resolve the web-URL hosting separately.

Desktop builds (no blocker)

Reuse the existing build-desktop.yml matrix (macOS universal zip+dmg, Windows squirrel+zip) but on pull_request. Surface the builds via either:

  • actions/upload-artifact + post the artifact-url outputs in the sticky comment (auto-expiring, isolated; requires GH login to download), or
  • a per-PR prerelease (tag pr-<N>), giving stable public download URLs, deleted on PR close.

Security note

On pull_request from forks, GITHUB_TOKEN is read-only and secrets aren't exposed, so release-publishing / gh-pages-writing previews won't work for fork PRs (and pull_request_target is unsafe with untrusted build code). PRs in this repo so far are internal branches, where it works — but external contributors (e.g. #74's reporter) may open fork PRs. Decide whether previews are internal-only.

Acceptance criteria

  • New .github/workflows/pr-preview.yml triggered on PR open/sync/reopen/close.
  • Builds Windows .exe + macOS .dmg/zip for the PR head.
  • (web preview option chosen + implemented per decision above)
  • Single sticky PR comment with the preview URL + desktop download links, updated on each push.
  • Preview/artifacts cleaned up (or expire) when the PR closes — true isolation.
  • Documented in apps/overlay/README.md / root README.md.

Open decisions (need owner input)

  1. Which web-preview hosting option (1–4 above)?
  2. Desktop delivery: expiring artifacts vs. per-PR prerelease?
  3. Internal-PRs-only, or support fork PRs too?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions