
Devops Pipeline
- 76 installs
- 102 repo stars
- Updated July 23, 2026
- luongnv89/skills
devops-pipeline is a Claude Code skill for devops & ci/cd.
About
devops-pipeline is a Claude Code skill for devops & ci/cd. It helps solo builders move faster with AI-assisted coding.
- devops-pipeline
- DevOps & CI/CD
- AI-coding skill
Devops Pipeline by the numbers
- 76 all-time installs (skills.sh)
- Ranked #605 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/luongnv89/skills --skill devops-pipelineAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 76 |
|---|---|
| repo stars | ★ 102 |
| Last updated | July 23, 2026 |
| Repository | luongnv89/skills ↗ |
How do I helps with devops & ci/cd tasks.?
Helps with devops & ci/cd tasks.
Who is it for?
Best when you're working on devops & ci/cd and need structured help with devops pipeline.
Skip if: Teams with no devops & ci/cd needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to helps with devops & ci/cd tasks., or when devops-pipeline is a claude code skill for devops & ci/cd.
What you get
Structured output aligned to devops-pipeline: devops-pipeline, DevOps & CI/CD.
Files
DevOps Pipeline
Implement comprehensive DevOps quality gates adapted to project type, with a shift-left philosophy: run as many checks as possible locally via pre-commit so developers get fast feedback and CI is a safety net rather than the primary gate.
Core principle: If a check can run locally in under ~60 seconds, it belongs in pre-commit. GitHub Actions should handle things that can't run locally: matrix version testing, secrets-based security scans, deployment, and reporting.
To stay within the agent's context budget, this SKILL keeps templates short and links to references/*.md for language-specific configs, workflow templates, and the CLI E2E script.
Repo Sync Before Edits (mandatory)
Before creating/updating/deleting files in an existing repository, sync the current branch with remote:
branch="$(git rev-parse --abbrev-ref HEAD)"
git fetch origin
git pull --rebase origin "$branch"If the working tree is not clean, stash first, sync, then restore:
git stash push -u -m "pre-sync"
branch="$(git rev-parse --abbrev-ref HEAD)"
git fetch origin && git pull --rebase origin "$branch"
git stash popIf origin is missing, pull is unavailable, or rebase/stash conflicts occur, stop and ask the user before continuing.
Workflow
1. Analyze Project
Detect project characteristics:
# Check for package files and configs
ls -la package.json pyproject.toml Cargo.toml go.mod pom.xml build.gradle *.csproj 2>/dev/null
ls -la .eslintrc* .prettierrc* tsconfig.json mypy.ini setup.cfg ruff.toml 2>/dev/null
ls -la .pre-commit-config.yaml .github/workflows/*.yml 2>/dev/nullIdentify:
- Languages: JS/TS, Python, Go, Rust, Java, C#, etc.
- Frameworks: React, Next.js, Django, FastAPI, etc.
- Build system: npm, yarn, pnpm, pip, poetry, cargo, go, maven, gradle
- Existing tooling: Linters, formatters, type checkers already configured
- Is this a CLI tool? — if yes, enumerate all commands/subcommands (check README,
--help,click/argparse/cobrasource) to build an E2E test suite
2. Configure Pre-commit Hooks (maximize local coverage)
Install pre-commit framework:
pip install pre-commit # or brew install pre-commitCreate .pre-commit-config.yaml based on detected stack. See references/precommit-configs.md for language-specific configurations.
What to put in pre-commit (run on every commit):
- Format checks (Prettier, Black/Ruff, gofmt, rustfmt)
- Lint (ESLint, Ruff, golangci-lint, Clippy)
- Type checks (tsc, mypy)
- Security scans that work offline (Bandit, cargo-audit, gosec,
detect-secrets) - Unit tests (fast, <10s) — always on
commitstage - Build/compile verification (catches import errors, compile failures early)
What to put in pre-commit on `push` stage (run on git push):
- Full test suite (unit + integration)
- End-to-end tests for every CLI command (see below)
- Coverage checks
- Slower linters (full golangci-lint ruleset)
What stays in GitHub Actions only:
- Matrix version testing (multiple Node/Python/Go versions)
- Secrets-based scans (Snyk, SAST tools needing tokens)
- Deployment / release workflows
- Flaky or environment-sensitive tests that need a clean VM
CLI End-to-End Testing
If the project is a CLI tool, create scripts/e2e_test.sh that exercises every command/subcommand to verify the CLI works end-to-end (not just compiles). Wire it into pre-commit on the push stage.
See references/cli-e2e.md for command discovery patterns, the script template, and the pre-commit hook snippet.
Install hooks:
pre-commit install
pre-commit install --hook-type pre-push # also install push-stage hooks
pre-commit run --all-files # Test on existing code3. Create GitHub Actions Workflows (lean CI)
Create .github/workflows/ci.yml — but keep it lean since pre-commit already catches most issues. See references/github-actions.md for workflow templates.
GitHub Actions responsibilities (things pre-commit can't do):
- Matrix testing across language versions (important for libraries)
- Upload coverage reports (Codecov, etc.)
- Deployment on merge to main
- PR status comments/badges
- Secrets-dependent scans
Since pre-commit already runs lint, format, type-check, unit tests, and E2E tests — the CI workflow can be simpler: install deps → run pre-commit → run tests with coverage upload → build artifact.
# Minimal CI when pre-commit covers everything locally:
- name: Run pre-commit
run: pre-commit run --all-files
- name: Run tests with coverage
run: <test-command> --cov --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v44. Verify Pipeline
# Test all pre-commit hooks (commit stage)
pre-commit run --all-files
# Test push-stage hooks (includes E2E)
pre-commit run --all-files --hook-stage push
# Verify the CLI E2E script directly
bash scripts/e2e_test.shIf all local checks pass, GitHub Actions becomes a thin verification layer, not the primary quality gate.
Tool Selection by Language
| Language | Formatter | Linter | Type Check | Security | Tests |
|---|---|---|---|---|---|
| JS/TS | Prettier | ESLint | tsc | npm audit | Jest/Vitest |
| Python | Ruff/Black | Ruff | mypy | Bandit + detect-secrets | pytest |
| Go | gofmt | golangci-lint | built-in | gosec | go test |
| Rust | rustfmt | Clippy | built-in | cargo-audit | cargo test |
| Java | google-java-format | Checkstyle | - | SpotBugs | mvn test |
What Runs Where
| Check | Pre-commit (commit) | Pre-commit (push) | GitHub Actions |
|---|---|---|---|
| Formatting | ✓ | — | — |
| Linting | ✓ | — | — |
| Type checking | ✓ | — | — |
| Security scan (offline) | ✓ | — | — |
| Unit tests (fast) | ✓ | — | — |
| Full test suite | — | ✓ | ✓ (coverage upload) |
| CLI E2E tests | — | ✓ | — |
| Multi-version matrix | — | — | ✓ |
| Deploy | — | — | ✓ |
Expected Output
After running the skill, the repository contains:
1. `.pre-commit-config.yaml` — hooks for formatting, linting, type-checking, and unit tests on commit stage; full test suite and E2E tests on push stage. 2. `.github/workflows/ci.yml` — lean CI that re-runs pre-commit and uploads coverage; no duplicate lint/format steps. 3. `scripts/e2e_test.sh` (CLI projects only) — executable script exercising every CLI command/subcommand.
Example .pre-commit-config.yaml snippet for a Python project:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
- id: ruff
stages: [commit]
- id: ruff-format
stages: [commit]
- repo: local
hooks:
- id: mypy
name: mypy type check
entry: mypy src/
language: system
stages: [commit]
- id: pytest-fast
name: fast unit tests
entry: pytest tests/unit -x -q
language: system
stages: [commit]
- id: pytest-full
name: full test suite
entry: pytest --cov=src --cov-report=xml
language: system
stages: [push]Acceptance Criteria
A run passes when all of the following are true:
- [ ]
.pre-commit-config.yamlexists at the repo root and lists at least one hook for the detected primary language (formatter, linter, or type checker). - [ ] All checks runnable locally in under ~60 seconds are configured in pre-commit, not GitHub Actions.
- [ ] At least one
.github/workflows/*.ymlexists and runs only the things pre-commit cannot (matrix builds, secret-scanning, deployment, or release). - [ ]
pre-commit run --all-filessucceeds (or its failures are surfaced explicitly to the user, not auto-suppressed). - [ ] For CLI projects, an E2E test step is wired into either pre-commit or CI per the language reference files.
- [ ] No duplication: the same check (e.g.,
eslint,ruff) does not run in both pre-commit and CI on the same trigger.
Edge Cases
- No package manager detected: Prompt the user for the language/build system before generating hooks; never guess silently.
- Pre-commit not installed: Emit the install command (
pip install pre-commitorbrew install pre-commit) and stop; don't generate config files for a tool that isn't present. - Existing `.pre-commit-config.yaml`: Merge new hooks into the existing file rather than overwriting; preserve user-defined hooks and pinned revs.
- Monorepo with multiple languages: Generate one config with per-language hook sections and
files:path filters so hooks only run on relevant subdirectories. - No `origin` remote: Skip the repo-sync step and inform the user; proceed with local-only setup.
- Tests take >60 seconds: Move slow tests to
pushstage or GitHub Actions only; note the decision explicitly in the generated config with a comment. - Windows-only repo: Substitute PowerShell-compatible hook entries and flag any Unix-specific commands.
Step Completion Reports
After completing each major step, output a status report in this format:
◆ [Step Name] ([step N of M] — [context])
··································································
[Check 1]: √ pass
[Check 2]: √ pass (note if relevant)
[Check 3]: × fail — [reason]
[Check 4]: √ pass
[Criteria]: √ N/M met
____________________________
Result: PASS | FAIL | PARTIALAdapt the check names to match what the step actually validates. Use √ for pass, × for fail, and — to add brief context. The "Criteria" line summarizes how many acceptance criteria were met. The "Result" line gives the overall verdict.
Skill-specific checks per phase
Phase: Project Analysis — checks: Project detection, Existing tooling scan, CLI detection, Command enumeration
Phase: Pre-commit Configuration — checks: Pre-commit setup, Hook installation, Push-stage hooks installed, E2E script created (if CLI)
Phase: GitHub Actions Setup — checks: GitHub Actions config, CI lean (pre-commit deduplication), Matrix testing configured
Phase: Pipeline Verification — checks: Commit-stage hooks pass, Push-stage hooks pass, E2E tests pass (if CLI)
Resources
- references/precommit-configs.md - Pre-commit configurations by language (with push-stage tests and E2E hooks)
- references/github-actions.md - GitHub Actions workflow templates (lean CI variants)
<!-- DO NOT READ THIS FILE — This README.md is for human catalog browsing only. It ships inside the .skill package but is NEVER auto-loaded into agent context. The runtime loader only reads SKILL.md + references/ + scripts/ + agents/ when the skill triggers. If you're an AI agent, read the SKILL.md file instead for skill instructions. -->
DevOps Pipeline
Set up pre-commit hooks and lean GitHub Actions — maximizing local test coverage to catch issues before they reach CI.
Highlights
- Detect project language and framework automatically
- Configure language-specific linters, formatters, type checkers, and security scanners
- Run unit tests on every commit, full test suite + E2E tests on push
- Enumerate all CLI commands and generate end-to-end smoke tests (for CLI tools)
- Keep GitHub Actions lean — matrix version testing and coverage upload only
When to Use
| Say this... | Skill will... |
|---|---|
| "Setup CI/CD" | Create full pipeline with pre-commit hooks and lean GitHub Actions |
| "Add pre-commit hooks" | Install and configure local quality gates with push-stage tests |
| "Reduce GitHub Actions dependency" | Shift tests left into pre-commit, slim down CI |
| "Add E2E tests for my CLI" | Enumerate commands and generate scripts/e2e_test.sh |
How It Works
graph TD
A["Detect Project + CLI Commands"] --> B["Configure Pre-commit Hooks"]
B --> C["Create E2E Test Script (if CLI)"]
C --> D["Create Lean GitHub Actions"]
D --> E["Verify Pipeline Locally"]
style A fill:#4CAF50,color:#fff
style E fill:#2196F3,color:#fffWhat Runs Where
| Check | Pre-commit commit | Pre-commit push | GitHub Actions |
|---|---|---|---|
| Format / lint / type check | ✓ | — | — |
| Unit tests (fast) | ✓ | — | — |
| Full test suite | — | ✓ | ✓ (coverage upload) |
| CLI end-to-end tests | — | ✓ | — |
| Multi-version matrix | — | — | ✓ |
| Deploy | — | — | ✓ |
Usage
/devops-pipelineResources
| Path | Description |
|---|---|
references/precommit-configs.md | Language-specific pre-commit configs with push-stage tests and E2E hooks |
references/github-actions.md | Lean CI workflow templates (pre-commit-first approach) |
Output
.pre-commit-config.yamlwith commit-stage and push-stage hooksscripts/e2e_test.shortests/e2e/test_cli.py(for CLI tools).github/workflows/ci.yml— lean CI that focuses on matrix testing and coverage- Configured and verified local pre-commit environment (both commit and push hooks)
CLI End-to-End Testing
Use this when the skill's target project is a CLI tool. The goal: verify the CLI actually works end-to-end, not just that the code compiles.
Discover all commands
# For Python click/typer apps:
python -m myapp --help
python -m myapp <subcommand> --help
# For Go cobra/urfave apps:
./myapp --help
./myapp <subcommand> --help
# For Node.js commander/yargs:
node cli.js --helpScript template
Create scripts/e2e_test.sh (or scripts/e2e_test.py for Python) that:
1. Builds/installs the CLI in a temp environment 2. Runs each command with representative inputs (including edge cases: empty input, invalid flags, --help) 3. Asserts exit codes and key output patterns 4. Cleans up temp artifacts
Example structure for a Python CLI:
#!/usr/bin/env bash
set -euo pipefail
echo "=== E2E: CLI smoke tests ==="
# Test each command/subcommand
python -m myapp --version
python -m myapp --help
python -m myapp subcommand1 --help
python -m myapp subcommand1 --input tests/fixtures/sample.txt
python -m myapp subcommand2 --flag value
# Test error paths
python -m myapp unknown-command 2>&1 | grep -q "Error" && echo "unknown command error path verified"
echo "=== E2E: All passed ==="Pre-commit wiring (push stage)
- repo: local
hooks:
- id: e2e-cli
name: CLI end-to-end tests
entry: bash scripts/e2e_test.sh
language: system
pass_filenames: false
stages: [push]GitHub Actions Workflow Templates
Philosophy: lean CI. Since pre-commit already handles format, lint, type-check, unit tests, and E2E tests locally, GitHub Actions only needs to do what can't run locally: multi-version matrix testing, coverage uploads, and deployment.
Table of Contents
- Minimal (pre-commit already covers everything)
- JavaScript/TypeScript
- Python
- Go
- Rust
- Java (Maven)
- Multi-language
- Common Additions
---
Minimal (pre-commit already covers everything)
If your pre-commit setup runs format, lint, type-check, unit tests, and E2E tests — CI can be extremely thin:
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
# Runs all pre-commit hooks (commit + push stages) on CI
env:
SKIP: "" # add hook IDs here to skip on CI if neededThis single job re-runs everything pre-commit does locally, ensuring the same checks pass in a clean environment.
---
JavaScript/TypeScript
Add matrix version testing — the part pre-commit can't do locally:
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
# Re-run pre-commit in CI (catches any env differences)
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
matrix-test:
runs-on: ubuntu-latest
# Only run matrix test on push to main (not every PR commit)
if: github.event_name == 'push'
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Upload coverage
uses: codecov/codecov-action@v4
if: matrix.node-version == 20 # upload once
with:
token: ${{ secrets.CODECOV_TOKEN }}With pnpm
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile---
Python
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install dependencies
run: pip install -e ".[dev]"
# Pre-commit re-runs all hooks (format, lint, type-check, tests, E2E)
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
matrix-test:
runs-on: ubuntu-latest
if: github.event_name == 'push'
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: pip install -e ".[dev]"
- name: Run tests with coverage
run: pytest --cov --cov-report=xml -q
- name: Upload coverage
uses: codecov/codecov-action@v4
if: matrix.python-version == '3.12'
with:
token: ${{ secrets.CODECOV_TOKEN }}With Poetry
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.7.1
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
run: poetry install --no-interaction---
Go
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
matrix-test:
runs-on: ubuntu-latest
if: github.event_name == 'push'
strategy:
matrix:
go-version: ['1.21', '1.22']
steps:
- uses: actions/checkout@v4
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true
- name: Run tests with coverage
run: go test -race -coverprofile=coverage.out ./...
- name: Build
run: go build ./...
- name: Upload coverage
uses: codecov/codecov-action@v4
if: matrix.go-version == '1.22'
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage.out---
Rust
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo
uses: Swatinem/rust-cache@v2
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
matrix-test:
runs-on: ubuntu-latest
if: github.event_name == 'push'
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
rust: [stable, beta]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup Rust ${{ matrix.rust }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Cache cargo
uses: Swatinem/rust-cache@v2
- name: Run tests
run: cargo test --all-features
- name: Build release
run: cargo build --release---
Java (Maven)
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'maven'
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
matrix-test:
runs-on: ubuntu-latest
if: github.event_name == 'push'
strategy:
matrix:
java-version: ['17', '21']
steps:
- uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java-version }}
distribution: 'temurin'
cache: 'maven'
- name: Run tests
run: mvn test -q
- name: Build
run: mvn package -DskipTests -q---
Multi-language
For monorepos, use path filters to only run relevant jobs:
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
changes:
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.changes.outputs.frontend }}
backend: ${{ steps.changes.outputs.backend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
frontend:
- 'frontend/**'
backend:
- 'backend/**'
frontend:
needs: changes
if: needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- name: Run pre-commit (frontend hooks)
uses: pre-commit/action@v3.0.1
backend:
needs: changes
if: needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install -e "backend/[dev]"
- name: Run pre-commit (backend hooks)
uses: pre-commit/action@v3.0.1---
Common Additions
Upload coverage to Codecov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}PR status comment
- name: Comment PR
uses: actions/github-script@v7
if: github.event_name == 'pull_request'
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '✅ All checks passed!'
})Deployment (on merge to main)
deploy:
needs: [quality, matrix-test]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Add deployment stepsSkipping specific pre-commit hooks in CI
Some hooks (like interactive formatters) may not make sense in CI. Skip them with the SKIP env var:
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
env:
SKIP: "no-commit-to-branch" # comma-separated hook IDs to skipPre-commit Configurations by Language
Philosophy: run as much as possible locally. Commit-stage hooks catch issues immediately; push-stage hooks run the full test suite and E2E tests before code leaves the machine. GitHub Actions becomes a thin safety net.
Table of Contents
JavaScript/TypeScript
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-added-large-files
- repo: local
hooks:
- id: prettier
name: prettier
entry: npx prettier --write --ignore-unknown
language: system
types: [text]
files: \.(js|jsx|ts|tsx|json|css|scss|md)$
- id: eslint
name: eslint
entry: npx eslint --fix
language: system
files: \.(js|jsx|ts|tsx)$
- id: typecheck
name: typecheck
entry: npx tsc --noEmit
language: system
pass_filenames: false
# Unit tests run on every commit (keep them fast)
- id: test-unit
name: unit tests
entry: npm run test:unit
language: system
pass_filenames: false
# Full test suite + E2E on push
- id: test-full
name: full test suite
entry: npm test
language: system
pass_filenames: false
stages: [push]
# If this is a CLI tool, add E2E hook on push stage:
# - id: e2e-cli
# name: CLI end-to-end tests
# entry: bash scripts/e2e_test.sh
# language: system
# pass_filenames: false
# stages: [push]Note on unit vs full tests: split your test script intotest:unit(fast, no I/O) andtest(all). If you can't split them, run all tests on commit — slow feedback is still better than no feedback.
Python
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [] # Add type stubs as needed
- repo: https://github.com/PyCQA/bandit
rev: 1.7.7
hooks:
- id: bandit
args: ["-c", "pyproject.toml"]
additional_dependencies: ["bandit[toml]"]
- repo: local
hooks:
# Unit tests on every commit
- id: pytest-unit
name: pytest unit tests
entry: pytest tests/unit -x -q
language: system
pass_filenames: false
# Full suite (unit + integration) on push
- id: pytest-full
name: pytest full suite
entry: pytest --tb=short -q
language: system
pass_filenames: false
stages: [push]
# CLI E2E tests on push (if this is a CLI tool)
# - id: e2e-cli
# name: CLI end-to-end tests
# entry: bash scripts/e2e_test.sh
# language: system
# pass_filenames: false
# stages: [push]Alternative: Black instead of Ruff formatter
- repo: https://github.com/psf/black
rev: 24.2.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isortGo
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: local
hooks:
- id: go-fmt
name: go fmt
entry: gofmt -w
language: system
types: [go]
- id: go-vet
name: go vet
entry: go vet ./...
language: system
pass_filenames: false
- id: golangci-lint
name: golangci-lint
entry: golangci-lint run --fix
language: system
types: [go]
pass_filenames: false
- id: gosec
name: gosec
entry: gosec ./...
language: system
pass_filenames: false
# Fast unit tests on every commit
- id: go-test-unit
name: go unit tests
entry: go test -short ./...
language: system
pass_filenames: false
# Full tests (including integration) on push
- id: go-test-full
name: go full test suite
entry: go test -race ./...
language: system
pass_filenames: false
stages: [push]
# CLI E2E on push (if this is a CLI tool)
# - id: e2e-cli
# name: CLI end-to-end tests
# entry: bash scripts/e2e_test.sh
# language: system
# pass_filenames: false
# stages: [push]Rust
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: system
types: [rust]
- id: cargo-clippy
name: cargo clippy
entry: cargo clippy --all-targets --all-features -- -D warnings
language: system
types: [rust]
pass_filenames: false
- id: cargo-audit
name: cargo audit
entry: cargo audit
language: system
pass_filenames: false
# Unit tests on every commit
- id: cargo-test-unit
name: cargo unit tests
entry: cargo test --lib
language: system
pass_filenames: false
# All tests (unit + integration + doc tests) on push
- id: cargo-test-full
name: cargo full test suite
entry: cargo test --all-features
language: system
pass_filenames: false
stages: [push]
# CLI E2E on push (if this is a CLI tool)
# - id: e2e-cli
# name: CLI end-to-end tests
# entry: bash scripts/e2e_test.sh
# language: system
# pass_filenames: false
# stages: [push]Java
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-xml
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.12.0
hooks:
- id: pretty-format-java
args: [--autofix]
- repo: local
hooks:
- id: checkstyle
name: checkstyle
entry: mvn checkstyle:check -q
language: system
pass_filenames: false
- id: spotbugs
name: spotbugs
entry: mvn spotbugs:check -q
language: system
pass_filenames: false
# Unit tests on commit
- id: test-unit
name: unit tests
entry: mvn test -pl . -Dtest="**/unit/**" -q
language: system
pass_filenames: false
# Full tests on push
- id: test-full
name: full test suite
entry: mvn test -q
language: system
pass_filenames: false
stages: [push]Multi-language
For monorepos or projects with multiple languages:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-toml
- id: check-added-large-files
- id: detect-private-key
# Add language-specific hooks from sections above
# Use `files:` patterns to scope hooks to specific directories
# Example: scope Go hooks to backend/, Node hooks to frontend/---
CLI End-to-End Testing
When the project is a CLI tool, create scripts/e2e_test.sh to smoke-test every command before pushing. This catches regressions that unit tests miss (argument parsing bugs, output format changes, exit code issues).
Discovering all CLI commands
# Python (click / typer / argparse):
python -m myapp --help
python -m myapp <subcommand> --help
# Go (cobra / urfave/cli):
./bin/myapp --help
./bin/myapp <subcommand> --help
# Node.js (commander / yargs / meow):
node cli.js --help
node cli.js <subcommand> --help
# Rust (clap):
./target/debug/myapp --help
./target/debug/myapp <subcommand> --helpE2E test script template (Bash)
#!/usr/bin/env bash
# scripts/e2e_test.sh — CLI end-to-end smoke tests
# Runs every command/subcommand with representative inputs.
# Exit code 0 = all passed. Non-zero = something broke.
set -euo pipefail
# Colors for output
RED='\033[0;31m'; GREEN='\033[0;32m'; NC='\033[0m'
PASS=0; FAIL=0
check() {
local desc="$1"; shift
if "$@" > /dev/null 2>&1; then
echo -e " ${GREEN}✓${NC} $desc"
((PASS++))
else
echo -e " ${RED}✗${NC} $desc (cmd: $*)"
((FAIL++))
fi
}
check_output() {
local desc="$1"; local pattern="$2"; shift 2
local out; out=$("$@" 2>&1)
if echo "$out" | grep -q "$pattern"; then
echo -e " ${GREEN}✓${NC} $desc"
((PASS++))
else
echo -e " ${RED}✗${NC} $desc — expected '$pattern' in output"
((FAIL++))
fi
}
echo "=== CLI E2E Tests ==="
# --- Version / help ---
check "--version flag" myapp --version
check "--help flag" myapp --help
check_output "--help output" "Usage" myapp --help
# --- Subcommand: list ---
check "list --help" myapp list --help
check "list (no args)" myapp list
check "list --format json" myapp list --format json
# --- Subcommand: create ---
check "create --help" myapp create --help
check "create with input" myapp create --name "e2e-test" --dry-run
# --- Error handling ---
check_output "unknown command exits non-zero" "error\|Error\|unknown" \
bash -c 'myapp totally-invalid-cmd 2>&1; true'
# --- Cleanup (if any temp artifacts were created) ---
# rm -rf /tmp/e2e-test-*
echo ""
echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
[ "$FAIL" -eq 0 ] || exit 1E2E test script template (Python)
For Python projects where bash scripting is awkward, use pytest with subprocess:
# tests/e2e/test_cli.py
import subprocess, sys, pytest
CLI = [sys.executable, "-m", "myapp"]
def run(*args, **kwargs):
return subprocess.run([*CLI, *args], capture_output=True, text=True, **kwargs)
def test_version():
r = run("--version")
assert r.returncode == 0
assert r.stdout.strip()
def test_help():
r = run("--help")
assert r.returncode == 0
assert "Usage" in r.stdout
def test_subcommand_list():
r = run("list", "--help")
assert r.returncode == 0
def test_subcommand_list_runs():
r = run("list")
assert r.returncode == 0
def test_subcommand_create_dry_run():
r = run("create", "--name", "e2e-test", "--dry-run")
assert r.returncode == 0
def test_unknown_command_exits_nonzero():
r = run("totally-invalid-command")
assert r.returncode != 0Wire this into pre-commit on push stage:
- id: e2e-cli
name: CLI end-to-end tests
entry: pytest tests/e2e/ -v
language: system
pass_filenames: false
stages: [push]---
Common Options
Run only on specific files
hooks:
- id: eslint
files: ^frontend/ # Only frontend directorySkip specific files
hooks:
- id: prettier
exclude: ^vendor/|\.min\.js$Run only on specific stages
hooks:
- id: pytest-full
stages: [push] # Only on git push, not commitInstall push-stage hooks
pre-commit install # install commit-msg and pre-commit hooks
pre-commit install --hook-type pre-push # also install push hooksRun push-stage hooks manually
pre-commit run --all-files --hook-stage pushRelated skills
FAQ
What does devops-pipeline do?
devops-pipeline is a Claude Code skill for devops & ci/cd.
When should I use devops-pipeline?
When you need to helps with devops & ci/cd tasks., or when devops-pipeline is a claude code skill for devops & ci/cd.
What are the main capabilities?
devops-pipeline; DevOps & CI/CD; AI-coding skill.