Cut the Gitea runner's repeat dependency downloads by pointing CI + the image build at persistent caches (no Verdaccio yet). Avoids actions/cache@v4, which times out on this runner (D-PROBE-04).
Changes
.gitea/workflows/ci.yml
All four pnpm install --frozen-lockfile steps (fast-checks, api, harness, security) now append --store-dir /pnpm-store --prefer-offline → installs hard-link/copy from a host-mounted store instead of re-downloading.
The harness job sets PLAYWRIGHT_BROWSERS_PATH=/ms-playwright (job-level env) so the WebKit/Chromium binaries persist across runs instead of re-downloading every run.
apps/api/Dockerfile
# syntax=docker/dockerfile:1 + BuildKit RUN --mount=type=cache,target=/pnpm-store,sharing=locked … --store-dir /pnpm-store on all three install stages (builder, pwa-builder, production), so the publish image build reuses a persistent pnpm store. sharing=locked because builder + pwa-builder run in parallel.
.gitea/workflows/publish.yml
DOCKER_BUILDKIT=1 on the build step — the publish path uses plain docker build, and the legacy builder would fail on the --mount syntax.
docs/DEVELOPMENT.md
Documents the two container cache paths and that they require act_runner config.yamlcontainer.optionshost mounts (a manual host change) — without them CI still works, just uncached.
## Summary
Cut the Gitea runner's repeat dependency downloads by pointing CI + the image build at **persistent caches** (no Verdaccio yet). Avoids `actions/cache@v4`, which times out on this runner (D-PROBE-04).
## Changes
**`.gitea/workflows/ci.yml`**
- All four `pnpm install --frozen-lockfile` steps (fast-checks, api, harness, security) now append `--store-dir /pnpm-store --prefer-offline` → installs hard-link/copy from a host-mounted store instead of re-downloading.
- The `harness` job sets `PLAYWRIGHT_BROWSERS_PATH=/ms-playwright` (job-level env) so the WebKit/Chromium binaries persist across runs instead of re-downloading every run.
**`apps/api/Dockerfile`**
- `# syntax=docker/dockerfile:1` + BuildKit `RUN --mount=type=cache,target=/pnpm-store,sharing=locked … --store-dir /pnpm-store` on all three install stages (builder, pwa-builder, production), so the publish image build reuses a persistent pnpm store. `sharing=locked` because builder + pwa-builder run in parallel.
**`.gitea/workflows/publish.yml`**
- `DOCKER_BUILDKIT=1` on the build step — the publish path uses plain `docker build`, and the legacy builder would fail on the `--mount` syntax.
**`docs/DEVELOPMENT.md`**
- Documents the two container cache paths and that they require act_runner `config.yaml` `container.options` **host mounts** (a manual host change) — without them CI still works, just uncached.
## Required host change (separate, not in this PR)
The act_runner `config.yaml` needs:
```
container:
options: "-v <host>/pnpm-store:/pnpm-store -v <host>/ms-playwright:/ms-playwright"
```
Until that lands, these caches no-op gracefully (ephemeral dirs) — CI stays green either way.
## Out of scope (deferred)
- Verdaccio / npm registry mirror.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- All four pnpm install steps now use --store-dir /pnpm-store --prefer-offline
- harness job env adds PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
- Updated stale D-PROBE-04 comments to reflect persistent store
- Playwright install step gets a comment noting the future runner-image optimization
- Add "CI dependency caches" subsection to CI Pipeline Overview
- Lists /pnpm-store and /ms-playwright container paths
- Notes act_runner config.yaml container.options host-mount requirement
- Clarifies that CI still works without the mounts (ephemeral fallback)
Add 'RUN --mount=type=cache,target=/pnpm-store' to all 3 pnpm install
stages (builder/pwa-builder/production) with --store-dir /pnpm-store, plus
the '# syntax=docker/dockerfile:1' directive. Set DOCKER_BUILDKIT=1 on the
publish build step so the legacy builder can't break on the mount syntax.
sharing=locked because builder and pwa-builder run in parallel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Cut the Gitea runner's repeat dependency downloads by pointing CI + the image build at persistent caches (no Verdaccio yet). Avoids
actions/cache@v4, which times out on this runner (D-PROBE-04).Changes
.gitea/workflows/ci.ymlpnpm install --frozen-lockfilesteps (fast-checks, api, harness, security) now append--store-dir /pnpm-store --prefer-offline→ installs hard-link/copy from a host-mounted store instead of re-downloading.harnessjob setsPLAYWRIGHT_BROWSERS_PATH=/ms-playwright(job-level env) so the WebKit/Chromium binaries persist across runs instead of re-downloading every run.apps/api/Dockerfile# syntax=docker/dockerfile:1+ BuildKitRUN --mount=type=cache,target=/pnpm-store,sharing=locked … --store-dir /pnpm-storeon all three install stages (builder, pwa-builder, production), so the publish image build reuses a persistent pnpm store.sharing=lockedbecause builder + pwa-builder run in parallel..gitea/workflows/publish.ymlDOCKER_BUILDKIT=1on the build step — the publish path uses plaindocker build, and the legacy builder would fail on the--mountsyntax.docs/DEVELOPMENT.mdconfig.yamlcontainer.optionshost mounts (a manual host change) — without them CI still works, just uncached.Required host change (separate, not in this PR)
The act_runner
config.yamlneeds:Until that lands, these caches no-op gracefully (ephemeral dirs) — CI stays green either way.
Out of scope (deferred)
🤖 Generated with Claude Code