agentleFS
greglas75greglas75/zuvo/skills/ci-audit/SKILL.md

ci-audit

Skill7 starsChanged 27 days agoMITView on GitHub

CI/CD pipeline audit for speed, cost, reliability, and security. 10 dimensions (CI1-CI10): caching, parallelism, conditional execution, artifacts, secret handling, action pinning, timeouts, Docker optimization, test integration, and pipeline speed. Primary support: GitHub Actions. Detection-level: GitLab CI, CircleCI. Switches: zuvo:ci-audit full | [path] | --speed-only | --security-only

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

15 rules. About 0 are common, 9 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈9

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When to use: After changing CI workflows, when pipelines are slow, before release hardening, when CI costs are high, quarterly optimization.

    line 57
  2. Distinctive:

    Read every file below before starting.

    line 64
  3. Distinctive:

    If any file is MISSING, STOP.

    line 74
  4. Very specific:

    Use the deterministic preload helper FIRST: Run ~/.zuvo/compute-preload ci-audit "$PWD".

    line 121
  5. Very specific:

    If a [path] argument is provided:

    line 137
  6. Distinctive:

    If no argument: auto-detect from project root.

    line 141
  7. Distinctive:

    If no CI config found: report error and suggest checking file locations.

    line 143
  8. Distinctive:

    All workflow files from inventory are covered

    line 403
  9. Very specific:

    If gate_status = FAIL → VERDICT = INCOMPLETE.

    line 448
  10. Distinctive:

    Run: <ISO-8601-Z> ci-audit <project> <N-critical> <N-total> <VERDICT> - <N>-dimensions <NOTES> <BRANCH> <SHA7> <INCLUDES> <TIER>

    line 456
  11. Very specific:

    Follow the retrospective protocol from retrospective.md.

    line 461
  12. Distinctive:

    If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

    line 463
  13. Very specific:

    After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

    line 465
  14. Distinctive:

    All search commands use the resolved CI target path from Phase 0

    line 474
  15. Very specific:

    If gh run list is accessible, pipeline speed analysis can be supplemented with actual run durations

    line 480

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

zuvo:ci-audit

Audit CI/CD pipelines for wasted time, insecure practices, and reliability gaps. Single-pass execution, no sub-agents needed.

Primary support: GitHub Actions (full coverage of all 10 dimensions). Detection-level: GitLab CI, CircleCI (adapted patterns, unsupported checks scored as N/A).

When to use: After changing CI workflows, when pipelines are slow, before release hardening, when CI costs are high, quarterly optimization. When NOT to use: Application security (/security-audit), test quality (/test-audit), test runner config (/tests-performance).

Mandatory File Loading

Read every file below before starting. Print the checklist.

CORE FILES LOADED:
  1. ../../shared/includes/codesift-setup.md   -- [READ | MISSING -> STOP]
  2. ../../shared/includes/env-compat.md        -- [READ | MISSING -> STOP]
  3. ../../shared/includes/run-logger.md        -- [READ | MISSING -> STOP]
  4. ../../shared/includes/retrospective.md        -- [READ | MISSING -> STOP]

If any file is MISSING, STOP. Do not proceed from memory.


Argument Parsing

TokenBehavior
(empty) or fullAll 10 dimensions, auto-detect CI config
[path]Audit specific workflow file or CI config directory
--speed-onlyCI1, CI7, CI9, CI10 only -- focus on pipeline duration
--security-onlyCI5, CI6 only -- focus on secret handling and action pinning

Safety Gate

This audit is read-only. The only write target is zuvo/audits/.

FORBIDDEN:

  • Modifying any workflow or pipeline file
  • Running CI pipelines or triggering builds
  • Modifying secrets or environment variables
  • Installing CI plugins or actions

MANDATORY TOOL CALLS — CI Audit Validity Gate

INVALID if any tool below is skipped. "DEFERRED", "N/A" NOT valid reasons.

ToolTriggerSkip allowed?
get_file_treeAlwaysNO — locate .github/workflows/, .gitlab-ci.yml, .circleci/
search_textAlwaysNO — YAML scan: cache hits, action versions, secrets refs
search_patternsAlwaysNO — CI5 secret leaks, CI6 unpinned actions, CI3 missing if
scan_secretsAlwaysNO — CI5 hardcoded credentials in workflow YAML
audit_scanAlwaysNO — compound check

Forbidden: same as above (DEFERRED, codesift unavailable when deferred, retrospective skipped — all REJECTED).

POSTAMBLE: report on disk → retro appended → ~/.zuvo/append-runlog exit 0. Every CI finding needs path/to/file.ext:LINE (verify-audit gate).

Mandatory-tools-acknowledgment: I will run get_file_tree + search_text + search_patterns + scan_secrets + audit_scan for this CI audit. Every CI finding will cite a `path/to/file.ext:LINE` resolving in the current tree.

Use the deterministic preload helper FIRST. Run ~/.zuvo/compute-preload ci-audit "$PWD". Math gate enforced.


Phase 0: Detect and Scope

0.1 Platform Detection

Detect the CI platform and set scan targets.

SignalPlatform
.github/workflows/*.yml or uses: patternGitHub Actions
.gitlab-ci.yml or stages: / include: patternGitLab CI
.circleci/config.yml or orbs: / jobs: patternCircleCI

If a [path] argument is provided:

  • File: scan that file, detect platform from content
  • Directory: find CI config within, detect platform

If no argument: auto-detect from project root.

If no CI config found: report error and suggest checking file locations.

0.2 Workflow Inventory

List all CI workflows/jobs with their trigger events.

Print:

CI PIPELINE INVENTORY
------------------------------------
Platform:    [GitHub Actions / GitLab CI / CircleCI]
Scope:       [auto-detected / user-specified path]
Workflows:   [N]
Total jobs:  [N]
Docker builds: [Y/N]
------------------------------------

Phase 1: Dimension Analysis (CI1-CI10)

Single-pass inline execution. No sub-agents required.

CI1: Caching Strategy -- Weight 15, Max 15

CheckGoodBadSeverity
Dependency cacheCache configured for package managerNo caching, full install every runHIGH
Cache key includes lockfile hashKey derived from lockfile content (hashFiles)Static key or no keyMEDIUM
Build cacheTurbo/nx cache, Docker layer cacheRebuild from scratch every runHIGH
Cache restore fallbackFallback keys for partial cache hitsCache miss = full rebuildLOW

What to search for:

  • GitHub Actions: actions/cache, setup-node with cache:, hashFiles, restore-keys
  • GitLab CI: cache: sections, key: with $CI_COMMIT or lockfile reference
  • CircleCI: save_cache / restore_cache, checksum

Score 0-15 based on coverage.

CI2: Parallelism and Job Structure -- Weight 12, Max 12

Dispatch follows ../../shared/includes/execution-policy.md through env-compat. Reuse existing authorization within that policy; session restrictions take precedence. Run each required gate and report its actual independence or an unmet requirement.

CheckGoodBadSeverity
Independent jobs in parallelJobs without dependencies run simultaneouslyEverything sequentialHIGH
Matrix strategyMulti-version/platform via matrixDuplicated jobs per versionMEDIUM
Fan-out/fan-inParallel test shards with final mergeSingle monolithic test jobMEDIUM

What to search for:

  • needs: / dependencies: / requires: chains
  • strategy: / matrix: / parallel: blocks

CI3: Conditional Execution -- Weight 8, Max 8

CheckGoodBadSeverity
Path filtersTriggers filtered by changed filesEvery push triggers every workflowHIGH
Skip conditionsDraft PRs and skip labels handledDraft PRs run full pipelineMEDIUM
Reusable workflowsShared logic via templatesCopy-paste across workflowsMEDIUM
Concurrency controlCancel stale runs on new pushDuplicate runs pile upMEDIUM

What to search for:

  • paths: / paths-ignore:, only: / except: / rules:, filters:
  • if: conditions, workflow_call (reusable)
  • concurrency: with cancel-in-progress, interruptible:

CI4: Artifact Management -- Weight 5, Max 5

CheckGoodBadSeverity
Selective uploadsOnly needed artifacts uploadedEverything uploadedMEDIUM
Retention policyShort retention days configuredDefault retention (90 days)LOW
Download scopeJobs download only what they needAll artifacts pulled into every jobLOW

CI5: Secret Handling -- Weight 12, Max 12, Critical Gate

CheckGoodBadSeverity
Secret accessSecrets referenced via env: blockSecrets interpolated directly in run: scriptsHIGH
Environment scopingSecrets scoped to environment (prod/staging)All secrets available to all jobsMEDIUM
OIDC usageKeyless auth where possible (cloud providers)Long-lived credentialsMEDIUM
PermissionsMinimal permissions: declaredDefault write-all permissionsHIGH
Hardcoded secretsZero hardcoded secretsSecrets in workflow YAMLCRITICAL

Critical gate: hardcoded secrets or secrets likely logged → triggers FAIL. The gate fires on that FINDING; a CI5 score of 0 also fires it but is not required.

Verification: For each secret reference found, read the surrounding step to check whether it is set via env: block (safe) or inlined in run: script (can leak to logs).

CI6: Action Pinning -- Weight 10, Max 10, Critical Gate

GitHub Actions only. GitLab CI / CircleCI: score N/A.

CheckGoodBadSeverity
SHA pinningAll actions pinned to commit SHAActions pinned to @main or @masterCRITICAL
Trusted sourcesOnly actions/* namespace or verified publishersUnknown third-party actionsHIGH
DependabotDependabot configured for github-actions updatesNo automated update mechanismMEDIUM
Tag pinningFirst-party actions at @vN (acceptable)Third-party at @vN (risky)MEDIUM

Critical gate: unverified actions from unknown sources → triggers FAIL. The gate fires on that FINDING; a CI6 score of 0 also fires it but is not required.

CI7: Timeout and Resource Config -- Weight 8, Max 8

CheckGoodBadSeverity
Job timeoutsEvery job has timeout-minutesNo timeouts, stuck jobs run until cancelledHIGH
Runner sizingAppropriate runner labels for workloadOversized runners for simple tasksMEDIUM
Resource limitsSelf-hosted runners have resource constraintsSelf-hosted without limitsMEDIUM

CI8: Docker Optimization -- Weight 8, Max 8, N/A if no Docker

CheckGoodBadSeverity
Multi-stage buildsSeparate build and runtime stagesSingle-stage with build tools in prod imageHIGH
.dockerignoreExists with meaningful exclusionsMissing or emptyHIGH
Base image pinningSpecific version tag or digestFROM node:latestHIGH
Layer caching in CIcache-from / cache-to configuredFull rebuild on every pushMEDIUM

CI9: Test Integration -- Weight 12, Max 12, Critical Gate

CheckGoodBadSeverity
Tests in pipelineTest command runs in CINo tests in CI at allCRITICAL
Coverage gateThreshold enforced, build fails below minimumCoverage reported but not gatedHIGH
Lint/typecheck separationLint and typecheck run as separate early stepsMixed into test step or absentMEDIUM
Test shardingLarge suites split across parallel runnersSingle long-running test jobMEDIUM

Coverage gate detection: Finding codecov or coveralls alone is NOT a gate -- it is just reporting. A gate requires a threshold that fails the build (e.g., --coverageThreshold, fail_under, Codecov threshold in config).

Critical gate: no tests in CI → triggers FAIL. The gate fires on that FINDING; a CI9 score of 0 also fires it but is not required.

CI10: Pipeline Speed -- Weight 10, Max 10

Evaluated from workflow structure analysis, not by running pipelines.

CheckGoodBadSeverity
Critical path depth<= 3 sequential jobs> 5 sequential job chainHIGH
Repeated installsShared setup step, cached depsnpm install in every jobHIGH
Trigger scopeHeavy jobs only on merge to mainEverything runs on every pushMEDIUM
Stale cancellationcancel-in-progress: trueDuplicate runs stack upMEDIUM

Critical path estimation: Trace the longest chain of needs: dependencies. Each link adds one sequential step.


Phase 2: Scoring

CI1  = [0-15]   Caching Strategy
CI2  = [0-12]   Parallelism
CI3  = [0-8]    Conditional Execution
CI4  = [0-5]    Artifact Management
CI5  = [0-12]   Secret Handling              (critical gate)
CI6  = [0-10]   Action Pinning               (critical gate, N/A if not GHA)
CI7  = [0-8]    Timeout & Resources
CI8  = [0-8]    Docker Optimization          (N/A if no Docker)
CI9  = [0-12]   Test Integration             (critical gate)
CI10 = [0-10]   Pipeline Speed

N/A handling: CI6 = N/A if not GitHub Actions. CI8 = N/A if no Docker. Excluded from both score and max.

Score = sum / applicable_max x 100

Critical gates — any ONE of these findings triggers FAIL, whatever the numeric score:

GateFires on
CI5any hardcoded secret in a workflow, or a secret reaching the log
CI6any unverified/unpinned action from an unknown source (GitHub Actions only; N/A elsewhere)
CI9no tests run in CI

These gates fire on the FINDING, not on an aggregate score of zero. Read as "the dimension scored 0" they are nearly unreachable, because every one of them spreads several checks over its weight: CI5 spreads its checks across its full weight, so one hardcoded secret beside several passing checks scores well above zero. The named condition in each parenthesis IS the trigger — a dimension score of 0 remains sufficient to fire the gate, it is simply not necessary.

GradePercentage
HEALTHY>= 80%
NEEDS ATTENTION>= 60% and < 80%
AT RISK>= 40% and < 60%
CRITICAL< 40%

Phase 3: Report

Save to: zuvo/audits/ci-audit-[YYYY-MM-DD].md — at the project root (zuvo/ resolves via git rev-parse --show-toplevel; override $ZUVO_OUTPUT_DIR. See ../../shared/includes/report-output-location.md).

Report Structure

# CI/CD Pipeline Audit Report

## Metadata
| Field | Value |
|-------|-------|
| Project | [name] |
| Date | [YYYY-MM-DD] |
| Platform | [GitHub Actions / GitLab CI / CircleCI] |
| Scope | [auto / user path] |
| Workflows | [N] |
| Total jobs | [N] |

## Executive Summary

**Score: [N] / 100** -- [HEALTHY / NEEDS ATTENTION / AT RISK / CRITICAL]

| Metric | Count |
|--------|-------|
| CRITICAL findings | N |
| HIGH findings | N |
| MEDIUM findings | N |

[2-3 sentence summary]

## Dimension Scores

| # | Dimension | Score | Max | Notes |
|---|-----------|-------|-----|-------|
| CI1 | Caching | [N] | 15 | |
| CI2 | Parallelism | [N] | 12 | |
| CI3 | Conditional Execution | [N] | 8 | |
| CI4 | Artifacts | [N] | 5 | |
| CI5 | Secret Handling | [N] | 12 | |
| CI6 | Action Pinning | [N] | 10 | |
| CI7 | Timeouts & Resources | [N] | 8 | |
| CI8 | Docker | [N] | 8 | |
| CI9 | Test Integration | [N] | 12 | |
| CI10 | Pipeline Speed | [N] | 10 | |
| **Total** | | **[N]** | **[M]** | |

## Findings (sorted by severity)
[Per finding: dimension, severity, file:line, description, fix]

## Optimization Roadmap

### Quick Wins (< 1 hour)
### Short-term (1 day)
### Medium-term (1 week)

Report Validation

After writing, verify:

  • Dimension scores sum to total in Executive Summary
  • Finding counts match Executive Summary
  • All workflow files from inventory are covered

Phase 4: Next-Step Routing

RECOMMENDED NEXT ACTION
------------------------------------
CI5 CRITICAL (secrets)    -> /security-audit --static
CI9 = 0 (no tests)       -> add test step to pipeline
CI6 = 0 (unpinned actions)-> pin all actions to SHA + add Dependabot
CI1 < 5 (no caching)     -> add dependency + build caching
Score < 60%              -> prioritize quick wins, re-audit in 1 week
Score >= 80%             -> schedule next audit in 3 months
------------------------------------

CI-AUDIT COMPLETE

Score: [N] / 100 -- [grade] Platform: [GitHub Actions / GitLab CI / CircleCI] Dimensions: [N scored] | Critical gates: [PASS/FAIL] Findings: [N critical] / [N total]

Validity Gate (REQUIRED — print BEFORE Run line, AFTER retro append + append-runlog)

VALIDITY GATE
  triggers_held: platform=<github|gitlab|circle>
  required_tool_calls:
    get_file_tree: [<N> CI configs found | NOT_CALLED — VIOLATES_TRIGGER]
    search_text: [<N> yaml refs | NOT_CALLED — VIOLATES_TRIGGER]
    search_patterns: [<N> hits | NOT_CALLED — VIOLATES_TRIGGER]
    scan_secrets: [<N> hits | NOT_CALLED — VIOLATES_TRIGGER]
    audit_scan: [<N> findings | NOT_CALLED — VIOLATES_TRIGGER]
  postamble:
    retros_log_appended: [yes(bytes_added=N) | NOT_APPENDED]
    retros_md_appended: [yes(entry_count=N) | NOT_APPENDED]
    verify_audit_pass: [yes(<verified>/<total>) | NOT_RUN | REJECTED]
  gate_status: [PASS | FAIL — <which gates missing>]

If gate_status = FAIL → VERDICT = INCOMPLETE.

Append the Run line via the retro-gated wrapper (NOT direct >> runs.log):

printf '%b\n' "$RUN_LINE" | ~/.zuvo/append-runlog

Run: <ISO-8601-Z> ci-audit <project> <N-critical> <N-total> <VERDICT> - <N>-dimensions <NOTES> <BRANCH> <SHA7> <INCLUDES> <TIER>

Retrospective (REQUIRED)

Follow the retrospective protocol from retrospective.md. Gate check → structured questions → TSV emit → markdown append. If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

VERDICT: PASS (0 critical findings), WARN (1-3 critical), FAIL (4+ critical).


Execution Notes

  • Single-pass inline execution, no sub-agents required
  • All search commands use the resolved CI target path from Phase 0
  • GitHub Actions: full coverage of all 10 dimensions
  • GitLab CI: CI1-CI5, CI7-CI10 supported; CI6 = N/A
  • CircleCI: CI1-CI5, CI7-CI10 supported; CI6 = N/A
  • Dimensions checking project-root files (Dockerfile, .dockerignore, dependabot.yml) reference the project root explicitly
  • If gh run list is accessible, pipeline speed analysis can be supplemented with actual run durations
  • CodeSift is not heavily used in this skill (CI files are YAML, not code), but codesift-setup.md is still loaded for consistency with other audit skills

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.