スキル一覧に戻る
Kaakati

code-quality-gates

by Kaakati

Enterprise-grade Rails development workflow with multi-agent orchestration, beads task tracking, and quality gates. Generic and portable across any Rails project.

2🍴 0📅 2026年1月24日
GitHubで見るManusで実行

SKILL.md


name: code-quality-gates description: "Expert quality gate decisions for iOS/tvOS: which gates matter for your project size, threshold calibration that catches bugs without blocking velocity, SwiftLint rule selection, and CI integration patterns. Use when setting up linting, configuring CI pipelines, or calibrating coverage thresholds. Trigger keywords: SwiftLint, SwiftFormat, coverage, CI, quality gate, lint, static analysis, pre-commit, threshold, warning" version: "3.0.0"

Code Quality Gates — Expert Decisions

Expert decision frameworks for quality gate choices. Claude knows linting tools — this skill provides judgment calls for threshold calibration and rule selection.


Decision Trees

Which Quality Gates for Your Project

Project stage?
├─ Greenfield (new project)
│  └─ Enable ALL gates from day 1
│     • SwiftLint (strict)
│     • SwiftFormat
│     • SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
│     • Coverage > 80%
│
├─ Brownfield (legacy, no gates)
│  └─ Adopt incrementally:
│     1. SwiftLint with --baseline (ignore existing)
│     2. Format new files only
│     3. Gradually increase thresholds
│
└─ Existing project with some gates
   └─ Team size?
      ├─ Solo/Small (1-3) → Lint + Format sufficient
      └─ Medium+ (4+) → Full pipeline
         • Add coverage gates
         • Add static analysis
         • Add security scanning

Coverage Threshold Selection

What type of code?
├─ Domain/Business Logic
│  └─ 90%+ coverage required
│     • Business rules must be tested
│     • Silent bugs are expensive
│
├─ Data Layer (Repositories, Mappers)
│  └─ 85% coverage
│     • Test mapping edge cases
│     • Test error handling
│
├─ Presentation (ViewModels)
│  └─ 70-80% coverage
│     • Test state transitions
│     • Skip trivial bindings
│
└─ Views (SwiftUI)
   └─ Don't measure coverage
      • Snapshot tests or manual QA
      • Unit testing views has poor ROI

SwiftLint Rule Strategy

Starting fresh?
├─ YES → Enable opt_in_rules aggressively
│  └─ Easier to disable than enable later
│
└─ NO → Adopting on existing codebase
   └─ Use baseline approach:
      1. Run: swiftlint lint --reporter json > baseline.json
      2. Configure: baseline_path: baseline.json
      3. New violations fail, existing ignored
      4. Chip away at baseline over time

NEVER Do

Threshold Anti-Patterns

NEVER set coverage to 100%:

# ❌ Blocks legitimate PRs, encourages gaming
MIN_COVERAGE: 100

# ✅ Realistic threshold with room for edge cases
MIN_COVERAGE: 80

NEVER use zero-tolerance for warnings initially on legacy code:

# ❌ 500 warnings = blocked pipeline forever
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES  # On day 1 of legacy project

# ✅ Incremental adoption
# 1. First: just report warnings
SWIFT_TREAT_WARNINGS_AS_ERRORS = NO

# 2. Then: require no NEW warnings
swiftlint lint --baseline existing-violations.json

# 3. Finally: zero tolerance (after cleanup)
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES

NEVER skip gates on "urgent" PRs:

# ❌ Creates precedent, gates become meaningless
if: github.event.pull_request.labels.contains('urgent')
  run: echo "Skipping quality gates"

# ✅ Gates are non-negotiable
# If code can't pass gates, it shouldn't ship

SwiftLint Anti-Patterns

NEVER disable rules project-wide without documenting why:

# ❌ Mystery disabled rules
disabled_rules:
  - force_unwrapping
  - force_cast
  - line_length

# ✅ Document the reasoning
disabled_rules:
  # line_length: Configured separately with custom thresholds
  # force_unwrapping: Using force_unwrapping opt-in rule instead (stricter)

NEVER use inline disables without explanation:

// ❌ No context
// swiftlint:disable force_unwrapping
let value = optionalValue!
// swiftlint:enable force_unwrapping

// ✅ Explain why exception is valid
// swiftlint:disable force_unwrapping
// Reason: fatalError path for corrupted bundle resources that should crash
let value = optionalValue!
// swiftlint:enable force_unwrapping

NEVER silence all warnings in a file:

// ❌ Nuclear option hides real issues
// swiftlint:disable all

// ✅ Disable specific rules for specific lines
// swiftlint:disable:next identifier_name
let x = calculateX()  // Math convention

CI Anti-Patterns

NEVER run expensive gates first:

# ❌ Slow feedback — tests run even if lint fails
jobs:
  test:  # 10 minutes
    ...
  lint:  # 30 seconds
    ...

# ✅ Fast feedback — fail fast on cheap checks
jobs:
  lint:
    runs-on: macos-14
    steps: [swiftlint, swiftformat]

  build:
    needs: lint  # Only if lint passes
    ...

  test:
    needs: build  # Only if build passes
    ...

NEVER run quality gates only on PR:

# ❌ Main branch can have violations
on:
  pull_request:
    branches: [main]

# ✅ Protect main branch too
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

Essential Configurations

Minimal SwiftLint (Start Here)

# .swiftlint.yml — Essential rules only

excluded:
  - Pods
  - .build
  - DerivedData

# Most impactful opt-in rules
opt_in_rules:
  - force_unwrapping          # Catches crashes
  - implicitly_unwrapped_optional
  - empty_count               # Performance
  - first_where               # Performance
  - contains_over_first_not_nil
  - fatal_error_message       # Debugging

# Sensible limits
line_length:
  warning: 120
  error: 200
  ignores_urls: true
  ignores_function_declarations: true

function_body_length:
  warning: 50
  error: 80

cyclomatic_complexity:
  warning: 10
  error: 15

type_body_length:
  warning: 300
  error: 400

file_length:
  warning: 500
  error: 800

Minimal SwiftFormat

# .swiftformat — Essentials only

--swiftversion 5.9
--exclude Pods,.build,DerivedData

--indent 4
--maxwidth 120
--wraparguments before-first
--wrapparameters before-first

# Non-controversial rules
--enable sortedImports
--enable trailingCommas
--enable redundantSelf
--enable redundantReturn
--enable blankLinesAtEndOfScope

# Disable controversial rules
--disable acronyms
--disable wrapMultilineStatementBraces

Xcode Build Settings (Quality Enforced)

# QualityGates.xcconfig

// Fail on warnings
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
GCC_TREAT_WARNINGS_AS_ERRORS = YES

// Strict concurrency (Swift 6 prep)
SWIFT_STRICT_CONCURRENCY = complete

// Static analyzer
RUN_CLANG_STATIC_ANALYZER = YES
CLANG_STATIC_ANALYZER_MODE = deep

CI Patterns

GitHub Actions (Minimal Effective)

name: Quality Gates

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  # Fast gates first
  lint:
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4
      - run: brew install swiftlint swiftformat
      - run: swiftlint lint --strict --reporter github-actions-logging
      - run: swiftformat . --lint

  # Build only if lint passes
  build:
    needs: lint
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4
      - name: Build with strict warnings
        run: |
          xcodebuild build \
            -scheme App \
            -destination 'platform=iOS Simulator,name=iPhone 15' \
            SWIFT_TREAT_WARNINGS_AS_ERRORS=YES

  # Test only if build passes
  test:
    needs: build
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4
      - name: Test with coverage
        run: |
          xcodebuild test \
            -scheme App \
            -destination 'platform=iOS Simulator,name=iPhone 15' \
            -enableCodeCoverage YES \
            -resultBundlePath TestResults.xcresult

      - name: Check coverage threshold
        run: |
          COVERAGE=$(xcrun xccov view --report --json TestResults.xcresult | \
            jq '.targets[] | select(.name | contains("App")) | .lineCoverage * 100')
          echo "Coverage: ${COVERAGE}%"
          if (( $(echo "$COVERAGE < 80" | bc -l) )); then
            echo "❌ Coverage below 80%"
            exit 1
          fi

Pre-commit Hook (Local Enforcement)

#!/bin/bash
# .git/hooks/pre-commit

echo "Running pre-commit quality gates..."

# SwiftLint (fast)
if ! swiftlint lint --strict --quiet 2>/dev/null; then
    echo "❌ SwiftLint failed"
    exit 1
fi

# SwiftFormat check (fast)
if ! swiftformat . --lint 2>/dev/null; then
    echo "❌ Code formatting issues. Run: swiftformat ."
    exit 1
fi

echo "✅ Pre-commit checks passed"

Threshold Calibration

Finding the Right Coverage Threshold

Step 1: Measure current coverage
$ xcodebuild test -enableCodeCoverage YES ...
$ xcrun xccov view --report TestResults.xcresult

Step 2: Set threshold slightly below current
Current: 73% → Set threshold: 70%
Prevents regression without blocking

Step 3: Ratchet up over time
Week 1: 70%
Week 4: 75%
Week 8: 80%
Stop at: 80-85% (diminishing returns above)

SwiftLint Warning Budget

# Start permissive, tighten over time
# Week 1
MAX_WARNINGS: 100

# Week 4
MAX_WARNINGS: 50

# Week 8
MAX_WARNINGS: 20

# Target (after cleanup sprint)
MAX_WARNINGS: 0

Quick Reference

Gate Priority Order

PriorityGateTimeROI
1SwiftLint~30sHigh — catches bugs
2SwiftFormat~15sMedium — consistency
3Build (0 warnings)~2-5mHigh — compiler catches issues
4Unit Tests~5-15mHigh — catches regressions
5Coverage Check~1mMedium — enforces testing
6Static Analysis~5-10mMedium — deep issues

Red Flags

SmellProblemFix
Gates disabled for "urgent" PRCulture problemGates are non-negotiable
100% coverage requirementGaming metrics80-85% is optimal
All SwiftLint rules enabledToo noisyCurate impactful rules
Pre-commit takes > 30sDevs skip itOnly fast checks locally
Different rules in CI vs localSurprisesSame config everywhere

SwiftLint Rules Worth Enabling

RuleWhy
force_unwrappingPrevents crashes
implicitly_unwrapped_optionalPrevents crashes
empty_countPerformance (O(1) vs O(n))
first_wherePerformance
fatal_error_messageBetter crash logs
unowned_variable_capturePrevents crashes
unused_closure_parameterCode hygiene

SwiftLint Rules to Avoid

RuleWhy Avoid
explicit_type_interfaceSwift has inference for a reason
file_types_orderTeam preference varies
prefixed_toplevel_constantOutdated convention
extension_access_modifierRarely adds value

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です