quality-gates-enforcer について
quality-gates-enforcerは、コードのマージ前に最低限の品質基準を設ける開発チーム向けのスキルです。カバレッジ、Lint、型チェック、セキュリティ、バンドルサイズのCI例と、ステータスチェックやレポートを扱います。
主な機能
- 01カバレッジしきい値のチェック
- 02Lintと型チェックのゲート
- 03セキュリティスキャン設定例
- 04バンドルサイズのチェック
- 05ステータスチェックと品質レポート
活用シーン
- 01プルリクエストに必須チェックを設定
- 02カバレッジしきい値未満の変更をブロック
- 03CIでセキュリティとバンドルを検査
- 04コード品質レポートを生成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ patricio0312rev/ skills --skill quality-gates-enforcerインストール後、Claude Code で/quality-gates-enforcerを入力して読み込まれたか確認します。
詳細
品質ゲートの強制
コードをマージする前に、最低限の品質基準を適用します。
カバレッジ要件
# .github/workflows/quality-gates.yml
name: Quality Gates
on:
pull_request:
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- name: Run tests with coverage
run: npm test -- --coverage
- name: Check coverage threshold
run: |
COVERAGE=$(node -p "require('./coverage/coverage-summary.json').total.lines.pct")
THRESHOLD=80
if (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then
echo "❌ Coverage $COVERAGE% is below threshold $THRESHOLD%"
exit 1
fi
echo "✅ Coverage $COVERAGE% meets threshold $THRESHOLD%"
- name: Comment coverage on PR
uses: romeovs/[email protected]
with:
lcov-file: ./coverage/lcov.info
github-token: ${{ secrets.GITHUB_TOKEN }}
delete-old-comments: true
Jest の設定
// jest.config.js
module.exports = {
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
"./src/critical/": {
branches: 90,
functions: 90,
lines: 90,
statements: 90,
},
},
};
Lint ゲート
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- name: Run ESLint
run: npm run lint -- --max-warnings 0
- name: Check formatting
run: npm run format:check
型チェックゲート
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- name: TypeScript check
run: npx tsc --noEmit
セキュリティスキャン
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk security scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Audit dependencies
run: npm audit --audit-level=moderate
- name: Check for outdated dependencies
run: |
OUTDATED=$(npm outdated || true)
if [ ! -z "$OUTDATED" ]; then
echo "⚠️ Outdated dependencies found:"
echo "$OUTDATED"
fi
バンドルサイズゲート
bundle-size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm run build
- name: Check bundle size
uses: andresz1/size-limit-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
skip_step: install
必須のステータスチェック
# .github/workflows/required-checks.yml
name: Required Checks
on:
pull_request:
jobs:
required:
runs-on: ubuntu-latest
needs: [lint, typecheck, test, coverage, security]
if: always()
steps:
- name: Check all required jobs passed
run: |
if [ "${{ contains(needs.*.result, 'failure') }}" == "true" ]; then
echo "❌ Required checks failed"
exit 1
fi
echo "✅ All required checks passed"
品質しきい値
// quality-thresholds.ts
export const QUALITY_GATES = {
coverage: {
lines: 80,
branches: 80,
functions: 80,
statements: 80,
},
linting: {
maxWarnings: 0,
maxErrors: 0,
},
bundleSize: {
maxSize: "200kb",
maxGzipSize: "100kb",
},
performance: {
maxLighthouseScore: 90,
},
security: {
maxVulnerabilities: 0,
maxSeverity: "moderate",
},
dependencies: {
maxOutdated: 5,
},
};
ブランチ保護ルール
# Configure via GitHub settings or API
{
"required_status_checks":
{
"strict": true,
"contexts":
["lint", "typecheck", "test", "coverage", "security", "bundle-size"],
},
"required_pull_request_reviews":
{
"required_approving_review_count": 1,
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true,
},
"enforce_admins": true,
"restrictions": null,
}
品質レポート
- name: Generate quality report
run: |
cat > quality-report.md << EOF
# Quality Report
## Coverage
- Lines: $(node -p "require('./coverage/coverage-summary.json').total.lines.pct")%
- Branches: $(node -p "require('./coverage/coverage-summary.json').total.branches.pct")%
- Functions: $(node -p "require('./coverage/coverage-summary.json').total.functions.pct")%
## Linting
- ESLint warnings: $(npm run lint 2>&1 | grep -c warning || echo 0)
- ESLint errors: $(npm run lint 2>&1 | grep -c error || echo 0)
## Type Safety
- TypeScript errors: $(npx tsc --noEmit 2>&1 | grep -c error || echo 0)
## Security
- Vulnerabilities: $(npm audit --json | jq '.metadata.vulnerabilities.total')
## Bundle Size
- Main bundle: $(ls -lh dist/main.js | awk '{print $5}')
EOF
- name: Comment report on PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('quality-report.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: report
});
しきい値未達時の自動失敗
- name: Check all quality gates
run: |
EXIT_CODE=0
# Coverage
COVERAGE=$(node -p "require('./coverage/coverage-summary.json').total.lines.pct")
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "❌ Coverage below 80%"
EXIT_CODE=1
fi
# Lint warnings
WARNINGS=$(npm run lint 2>&1 | grep -c warning || echo 0)
if [ "$WARNINGS" -gt 0 ]; then
echo "❌ Found $WARNINGS lint warnings"
EXIT_CODE=1
fi
# TypeScript errors
if ! npx tsc --noEmit; then
echo "❌ TypeScript errors found"
EXIT_CODE=1
fi
# Security vulnerabilities
if ! npm audit --audit-level=moderate; then
echo "❌ Security vulnerabilities found"
EXIT_CODE=1
fi
exit $EXIT_CODE
ベストプラクティス
- 厳格なしきい値:品質に妥協しません
- 迅速なフィードバック:CI の早い段階でチェックを実行します
- 明確なメッセージ:チェックに失敗した理由を説明します
- 段階的な改善:しきい値を段階的に引き上げます
- バイパス手段:緊急時のみ使用します
- ローカルでのコミット前チェック:プッシュ前に問題を検出します
- チームの合意:基準を統一します
出力チェックリスト
- カバレッジのしきい値を適用(80% 以上)
- 警告ゼロでリンティング
- 型チェックを必須化
- セキュリティスキャンを有効化
- バンドルサイズをチェック
- ブランチ保護ルールを設定
- 品質レポートを生成
- PR コメントを自動化
コメント
Markdown 対応