.claude-plugin/skills/github-actions-ci-speedup/SKILL.md
# Skill: github-actions-ci-speedup ## Overview | Field | Value | |-----------|-------| | Date | 2026-02-20 | | Issue | #787 | | PR | #835 | | Objective | Reduce GitHub Actions CI from 7+ minutes to ~2 minutes by fixing broken pixi caching, caching pre-commit environments, and running pre-commit on changed files only for PRs | | Outcome | Success — all changes committed and pushed; expected 5–6 min savings per job on cache hits | ## When to Use - CI/CD pipeline is taking
npx skillsauth add homericintelligence/projectscylla .claude-plugin/skills/github-actions-ci-speedupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Field | Value | |-----------|-------| | Date | 2026-02-20 | | Issue | #787 | | PR | #835 | | Objective | Reduce GitHub Actions CI from 7+ minutes to ~2 minutes by fixing broken pixi caching, caching pre-commit environments, and running pre-commit on changed files only for PRs | | Outcome | Success — all changes committed and pushed; expected 5–6 min savings per job on cache hits |
setup-pixi built-in cache: true is failing with HTTP 400 or Saved cache with ID -1--all-files even on PRs that touch only a few filessetup-pixi Built-in CacheThe prefix-dev/setup-pixi action's built-in cache: true option is unreliable in some environments. Symptoms:
##[warning]Failed to restore: Cache service responded with 400
Cache miss
...
##[warning]Failed to save: Our services aren't available right now
Saved cache with ID `-1`
This causes a full pixi install (~6 minutes) on every single run. The fix is to remove cache: true and use actions/cache@v4 explicitly.
Look for these patterns in CI logs:
Install pixi step taking 5–7 minutesFailed to restore: Cache service responded with 400Saved cache with ID -1Remove cache: true from setup-pixi and add an explicit actions/cache@v4 step after setup-pixi:
- name: Install pixi
uses: prefix-dev/[email protected]
with:
pixi-version: v0.62.2
# DO NOT use: cache: true (broken — always fails with 400)
- name: Cache pixi environments
uses: actions/cache@v4
with:
path: |
.pixi
~/.cache/rattler/cache
key: pixi-${{ runner.os }}-${{ hashFiles('pixi.lock') }}
restore-keys: |
pixi-${{ runner.os }}-
Key points:
pixi.lock hash — invalidated only when dependencies changerestore-keys prefix allows partial cache hits when the lock changes.pixi (environments) and ~/.cache/rattler/cache (package cache) must be cachedpixi.lockFor the pre-commit job, also add environments: lint to setup-pixi:
- name: Install pixi
uses: prefix-dev/[email protected]
with:
pixi-version: v0.62.2
environments: lint
Pre-commit downloads and installs hooks (Node.js for markdownlint, yamllint, shellcheck) on every run. Add a second cache step:
- name: Cache pre-commit environments
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-${{ runner.os }}-
- name: Run pre-commit
env:
EVENT_NAME: ${{ github.event_name }}
BASE_REF: ${{ github.base_ref }}
run: |
pixi install --environment lint
if [ "$EVENT_NAME" = "push" ]; then
pixi run --environment lint pre-commit run --all-files --show-diff-on-failure
else
pixi run --environment lint pre-commit run --from-ref "origin/$BASE_REF" --to-ref HEAD --show-diff-on-failure
fi
Security note: github.base_ref must go through an env: variable (not inline ${{ }} in run:). This is the safe pattern per GitHub's injection guidance.
- name: Upload coverage
if: matrix.test-group.name == 'unit'
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
flags: ${{ matrix.test-group.name }}
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
After pushing:
Cache saved successfully appears (not Failed to save)cache: true and just upgrading setup-pixi versionWhat happened: The cache: true option in setup-pixi calls the GitHub Actions cache service under the hood, and the 400 error comes from the cache service itself, not the action version. Upgrading the action doesn't fix it.
Fix: Remove cache: true entirely and replace with explicit actions/cache@v4.
github.base_ref directly inline in run: stepWhat happened: The security pre-tool-use hook blocked the edit with a warning about using ${{ github.base_ref }} directly inside a run: block (potential injection risk if the ref were attacker-controlled in a fork PR).
Fix: Move it to an env: block and reference via $BASE_REF. This is the safe and correct pattern regardless of actual injection risk.
.pixi without ~/.cache/rattler/cacheWhat happened: The rattler package cache (~/.cache/rattler/cache) contains downloaded conda packages. Without caching it, pixi must re-download packages even with a valid environment, reducing the cache hit benefit.
Fix: Always cache both paths together.
| Metric | Before | After (cache hit) | |--------|--------|-------------------| | pixi install (test job) | ~6m21s | ~10-20s | | pixi install (pre-commit job) | ~6m16s | ~10-20s | | pre-commit hook setup | ~32s | ~3-5s | | Total CI wall-clock | ~7m30s | ~2 min | | Percentage wasted on install | 85% | ~10% |
Configuration used:
# Cache key pattern
key: pixi-${{ runner.os }}-${{ hashFiles('pixi.lock') }}
restore-keys: |
pixi-${{ runner.os }}-
# Pre-commit cache key pattern
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-${{ runner.os }}-
When CI is slow due to dependency installation:
Install pixi step duration — if >2 min, caching is brokenFailed to restore: Cache service responded with 400Saved cache with ID -1cache: true is set on setup-pixi (remove it)actions/cache@v4 is being used (not v3 or v2).pixi AND ~/.cache/rattler/cache are in the cache path:pixi.lock hashdevelopment
# Skill: docs-status-fix ## Overview | Field | Value | |------------|----------------------------------------------------| | Date | 2026-02-19 | | Category | documentation | | Objective | Fix stale "Current Status" in CLAUDE.md | | Issue | #753 | | PR | #810
tools
# Skill: preflight-closing-issues-fix ## Overview | Field | Value | |-------|-------| | Date | 2026-02-21 | | Issue | #802 | | PR | #912 | | Category | tooling | | Objective | Fix `preflight_check.sh` Check 3 false positives caused by free-text PR search matching issue numbers in unrelated PR titles/bodies | | Outcome | Success — 6 bash tests pass, all pre-commit hooks green, PR created with auto-merge | ## When to Use Trigger this skill when: - A preflight/guard script uses `gh pr list --s
tools
# Preflight Check Skill Propagation ## Overview | Field | Value | |-------|-------| | Date | 2026-02-21 | | Issue | #803 | | Objective | Add preflight check to `worktree-create` skill so developers bypassing `gh-implement-issue` still run the 6-check safety gate | | Outcome | Success — PR #917 created, auto-merge enabled | | Files Changed | `tests/claude-code/shared/skills/worktree/worktree-create/SKILL.md` | ## When to Use Use this pattern when: - A safety/quality gate exists in one entry-
tools
# Orphan Config Detection ## Overview | Field | Value | |------------|-----------------------------------------------------------------| | Date | 2026-02-20 | | Issue | #777 | | PR | #824 | | Objective | Warn when a `config/models/*.yaml` file