Skip to content

CI: warm Ghostty cache on main so PRs share it #177

@dhilgaertner

Description

@dhilgaertner

Problem

The CI workflow builds and caches the Ghostty framework keyed by the submodule SHA, but the cache is only populated on pull_request runs. Because of GitHub Actions cache scoping, each PR branch gets its own isolated cache namespace — so a Ghostty build done on PR A is not visible to PR B, even when both PRs target the same Ghostty SHA.

Every PR's first CI run is therefore a cold build of Ghostty on a macos-15 runner, which is the most expensive step in the pipeline.

Background: cache scope in GitHub Actions

A workflow run can restore caches from:

  1. Its own ref (branch/PR), and
  2. The repository's default branch (main).

Caches created on other feature branches or PR refs are NOT accessible. This is why PR-only cache writes don't help sibling PRs — but a cache written on main is readable by every PR targeting main.

Reference: https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/cache-dependencies#restrictions-for-accessing-a-cache

Current state

.github/workflows/ci.yml triggers only on pull_request: [main]. Main never runs the build, so the shared cache slot on main is always empty. Every PR pays the Ghostty build cost on its first run.

Proposal

Add a push: branches: [main] trigger (or a dedicated cache-warm workflow) that runs after each merge and populates the Ghostty cache on main. Keep the existing cache key (ghostty-\${os}-\${arch}-\${sha}) so PRs with an unchanged submodule SHA get a hit.

Two options:

  1. Add push: main to ci.yml — simplest; main re-runs the full build+test after each merge, repopulating the cache. Cost is one extra macOS run per merge to main.

  2. Dedicated cache-warm.yml on push: main — only does checkout + make ghostty + cache save; skips swift build and tests. Cheaper than option 1, and only actually builds on Ghostty SHA changes (cache hit short-circuits). Probably the right tradeoff.

Since the cache key is keyed on the submodule SHA, option 2 is basically free on merges that don't bump Ghostty.

Impact

Eliminates the cold Ghostty build on every first PR CI run where the Ghostty submodule hasn't changed — which is the common case. Should cut typical PR CI time significantly and reduce macOS runner minutes.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions