CI workflow (thedotmack/claude-mem)
The CI workflow from thedotmack/claude-mem, explained and optimized by Latchkey.
CI health: D - needs work
Point runs-on at Latchkey and get caching, run de-duplication, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the thedotmack/claude-mem repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
build:
name: typecheck · build · test · bundle-size
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Bun (worker runtime + test runner)
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
# The repo intentionally gitignores package-lock.json (.gitignore), so
# `cache: 'npm'` and `npm ci` (both require a committed lockfile) cannot
# be used here - matches windows.yml / npm-publish.yml, which install the
# same way.
- name: Install dependencies
run: npm install --no-audit --no-fund
- name: Typecheck
run: npm run typecheck
# `npm run build` runs scripts/build-hooks.js, which enforces the worker
# bundle-size guardrail (WORKER_SERVICE_MAX_BYTES, see #2584) and the MCP
# server budget. A bundle that grows past threshold fails here → fails CI.
- name: Build (includes bundle-size guardrails)
run: npm run build
# The in-process server-runtime smoke test (tests/server/server-runtime-smoke.test.ts,
# #2550) runs here with no Docker: it boots the server HTTP surface in
# process, loads a mode, creates a key, makes an authed request, and
# checks the viewer responds. This gives every PR real server-runtime
# coverage. The full pg+redis e2e is the docker-gated job below.
- name: Test
run: bun test
clean-room-deps:
name: clean-room dependency closure smoke
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Bun (worker runtime + test runner)
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
# See note in the build job: no committed root lockfile, so npm install.
- name: Install dependencies
run: npm install --no-audit --no-fund
# Run the frozen-lockfile drift check against the COMMITTED tree BEFORE
# `npm run build` regenerates plugin/package.json + plugin/bun.lock (via
# gen-plugin-lockfile.cjs). If a contributor changed plugin deps (through
# scripts/build-hooks.js) but committed a stale plugin/bun.lock, the
# committed pair is out of sync and --frozen-lockfile fails here.
- name: Verify plugin lockfile is in sync (frozen-lockfile drift check)
working-directory: plugin
run: bun install --frozen-lockfile --ignore-scripts
- name: Build
run: npm run build
# Clean-room install + import smoke test (plan-10): installs the packed
# tarball into a throwaway dir and verifies the dependency closure resolves
# and imports outside the dev tree.
- name: Clean-room dependency closure smoke
run: npm run smoke:clean-room
server-runtime-e2e-docker:
name: server-runtime e2e (docker · pg + valkey)
runs-on: ubuntu-latest
timeout-minutes: 30
# Docker is available on ubuntu-latest GitHub runners. This job runs the
# full server-runtime e2e (#2550): real Postgres + Valkey, queue durability,
# restart recovery, and revoked-key denial. It does not gate PRs from the
# `build` job; a failure here surfaces a server-runtime regression before a
# user can file one (plan-07 test matrix).
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
# See note in the build job: no committed lockfile, so npm install.
- name: Install dependencies
run: npm install --no-audit --no-fund
- name: Verify Docker is available
run: docker compose version
- name: Server-runtime Docker e2e
run: npm run e2e:server:docker
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: CI on: pull_request: push: branches: [main] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: name: typecheck · build · test · bundle-size runs-on: latchkey-small timeout-minutes: 25 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: '20' - name: Install Bun (worker runtime + test runner) uses: oven-sh/setup-bun@v2 with: bun-version: latest # The repo intentionally gitignores package-lock.json (.gitignore), so # `cache: 'npm'` and `npm ci` (both require a committed lockfile) cannot # be used here - matches windows.yml / npm-publish.yml, which install the # same way. - name: Install dependencies run: npm install --no-audit --no-fund - name: Typecheck run: npm run typecheck # `npm run build` runs scripts/build-hooks.js, which enforces the worker # bundle-size guardrail (WORKER_SERVICE_MAX_BYTES, see #2584) and the MCP # server budget. A bundle that grows past threshold fails here → fails CI. - name: Build (includes bundle-size guardrails) run: npm run build # The in-process server-runtime smoke test (tests/server/server-runtime-smoke.test.ts, # #2550) runs here with no Docker: it boots the server HTTP surface in # process, loads a mode, creates a key, makes an authed request, and # checks the viewer responds. This gives every PR real server-runtime # coverage. The full pg+redis e2e is the docker-gated job below. - name: Test run: bun test clean-room-deps: name: clean-room dependency closure smoke runs-on: latchkey-small timeout-minutes: 25 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: '20' - name: Install Bun (worker runtime + test runner) uses: oven-sh/setup-bun@v2 with: bun-version: latest # See note in the build job: no committed root lockfile, so npm install. - name: Install dependencies run: npm install --no-audit --no-fund # Run the frozen-lockfile drift check against the COMMITTED tree BEFORE # `npm run build` regenerates plugin/package.json + plugin/bun.lock (via # gen-plugin-lockfile.cjs). If a contributor changed plugin deps (through # scripts/build-hooks.js) but committed a stale plugin/bun.lock, the # committed pair is out of sync and --frozen-lockfile fails here. - name: Verify plugin lockfile is in sync (frozen-lockfile drift check) working-directory: plugin run: bun install --frozen-lockfile --ignore-scripts - name: Build run: npm run build # Clean-room install + import smoke test (plan-10): installs the packed # tarball into a throwaway dir and verifies the dependency closure resolves # and imports outside the dev tree. - name: Clean-room dependency closure smoke run: npm run smoke:clean-room server-runtime-e2e-docker: name: server-runtime e2e (docker · pg + valkey) runs-on: latchkey-small timeout-minutes: 30 # Docker is available on ubuntu-latest GitHub runners. This job runs the # full server-runtime e2e (#2550): real Postgres + Valkey, queue durability, # restart recovery, and revoked-key denial. It does not gate PRs from the # `build` job; a failure here surfaces a server-runtime regression before a # user can file one (plan-07 test matrix). steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: '20' - name: Install Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest # See note in the build job: no committed lockfile, so npm install. - name: Install dependencies run: npm install --no-audit --no-fund - name: Verify Docker is available run: docker compose version - name: Server-runtime Docker e2e run: npm run e2e:server:docker
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Cache dependency installs on the setup step so they are served from cache.
1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
- End-to-end and browser tests
This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.