mcpField
S
shellcheck-cicd-2025

shellcheck-cicd-2025

github.com/josiahsiegelテスト・品質59159 回インストール19 週間前に更新
リポジトリ

shellcheck-cicd-2025 について

Bash 開発者向けに、ShellCheck の CI/CD 導入とスクリプトの規約を解説するガイドです。GitHub Actions、Azure DevOps、Git hooks、VS Code、Docker ビルドでの利用例を扱います。

主な機能

  1. 01GitHub Actions でのチェック設定
  2. 02Azure DevOps パイプラインとの統合
  3. 03Git hooks によるチェック実行
  4. 04VS Code での ShellCheck 有効化
  5. 05複数形式でのレポート生成

活用シーン

  1. 01マージ前の Bash スクリプト検査
  2. 02コミット時のスクリプト問題の検出
  3. 03Docker ビルドへの ShellCheck 導入
  4. 04チームのスクリプト品質規約の策定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill shellcheck-cicd-2025

インストール後、Claude Code で/shellcheck-cicd-2025を入力して読み込まれたか確認します。

詳細

🚨 重要なガイドライン

Windows のファイルパス要件

必須:Windows ではファイルパスに必ずバックスラッシュを使用してください

Windows で Edit または Write ツールを使用する場合、ファイルパスにはスラッシュ(/)ではなく、必ずバックスラッシュ(\)を使用してください。

例:

  • ❌ 誤り:D:/repos/project/file.tsx
  • ✅ 正しい:D:\repos\project\file.tsx

これは次に適用されます。

  • Edit ツールの file_path パラメーター
  • Write ツールの file_path パラメーター
  • Windows システム上のすべてのファイル操作
ドキュメント作成ガイドライン

ユーザーから明示的に依頼されない限り、新しいドキュメントファイルは作成しないでください。

  • 優先事項:新しいドキュメントを作成するのではなく、既存の README.md ファイルを更新してください
  • リポジトリの整理:ユーザーから別途依頼されない限り、リポジトリのルートには README.md のみを置き、整理された状態を保ってください
  • スタイル:ドキュメントは簡潔で直接的、かつプロフェッショナルな表現にし、AI が生成したような文体は避けてください
  • ユーザーの希望:ユーザーがドキュメント作成を具体的に依頼した場合にのみ、追加の .md ファイルを作成してください

ShellCheck の CI/CD 統合(2025)

ShellCheck:2025 年に欠かせないツール

ShellCheck は現在、最新の bash ワークフローにおいて必須とされています(2025 年のベストプラクティス)。

最新バージョン:v0.11.0(2025 年 8 月)

新機能:

  • Bash 5.3 を完全サポート(${| cmd; } および source -p)
  • 新しい警告:SC2327/SC2328(キャプチャグループの問題)
  • POSIX.1-2024 準拠:SC3013 を削除(-ot/-nt/-ef が POSIX 標準になりました)
  • 静的解析機能を強化
  • パフォーマンスと精度を向上
なぜ必須なのか?
  • 本番環境に反映される前に、見つけにくいバグを検出します
  • よくあるセキュリティ上の脆弱性を防ぎます
  • 一貫したコード品質を徹底します
  • ほとんどの DevOps チームで必須です
  • エンタープライズ環境の標準です
  • 最新の POSIX.1-2024 標準をサポートします

インストール

# Ubuntu/Debian
apt-get install shellcheck

# macOS
brew install shellcheck

# Alpine (Docker)
apk add shellcheck

# Windows (WSL/Git Bash)
choco install shellcheck

# Or download binary
wget https://github.com/koalaman/shellcheck/releases/latest/download/shellcheck-stable.linux.x86_64.tar.xz
tar -xf shellcheck-stable.linux.x86_64.tar.xz
sudo cp shellcheck-stable/shellcheck /usr/local/bin/

GitHub Actions との統合

マージ前の必須チェック
# .github/workflows/shellcheck.yml
name: ShellCheck

on:
  pull_request:
    paths:
      - '**.sh'
      - '**Dockerfile'
  push:
    branches: [main]

jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Run ShellCheck
      uses: ludeeus/action-shellcheck@master
      with:
        severity: warning
        format: gcc  # or: tty, json, checkstyle
        scandir: './scripts'
        # Fail on any issues
        ignore_paths: 'node_modules'

    # Block merge on failures
    - name: Annotate PR
      if: failure()
      uses: actions/github-script@v6
      with:
        script: |
          github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: '⛔ ShellCheck validation failed. Fix issues before merging.'
          })

Azure DevOps との統合

# azure-pipelines.yml
trigger:
- main

pr:
- main

stages:
- stage: Validate
  jobs:
  - job: ShellCheck
    pool:
      vmImage: 'ubuntu-24.04'

    steps:
    - script: |
        sudo apt-get install -y shellcheck
      displayName: 'Install ShellCheck'

    - script: |
        find . -name "*.sh" -type f | xargs shellcheck --format=gcc --severity=warning
      displayName: 'Run ShellCheck'
      failOnStderr: true

    - task: PublishTestResults@2
      condition: always()
      inputs:
        testResultsFormat: 'JUnit'
        testResultsFiles: '**/shellcheck-results.xml'
        failTaskOnFailedTests: true

Git フック(コミット前)

# .git/hooks/pre-commit
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

# Find all staged .sh files
mapfile -t STAGED_SH < <(git diff --cached --name-only --diff-filter=ACMR | grep '\.sh$' || true)

if [ ${#STAGED_SH[@]} -eq 0 ]; then
  exit 0
fi

echo "Running ShellCheck on staged files..."

# Run ShellCheck
shellcheck --format=gcc --severity=warning "${STAGED_SH[@]}"

if [ $? -ne 0 ]; then
  echo "⛔ ShellCheck failed. Fix issues before committing."
  exit 1
fi

echo "✅ ShellCheck passed"
exit 0

コミット前フックをインストール:

chmod +x .git/hooks/pre-commit

# Or use pre-commit framework
# .pre-commit-config.yaml
repos:
- repo: https://github.com/shellcheck-py/shellcheck-py
  rev: v0.11.0.0
  hooks:
  - id: shellcheck
    args: ['--severity=warning']

# Install
pip install pre-commit
pre-commit install

VS Code との統合

// .vscode/settings.json
{
  "shellcheck.enable": true,
  "shellcheck.run": "onType",
  "shellcheck.executablePath": "/usr/local/bin/shellcheck",
  "shellcheck.exclude": ["SC1090", "SC1091"],  // Optional excludes
  "shellcheck.customArgs": [
    "-x",  // Follow source files
    "--severity=warning"
  ]
}

Docker ビルドとの統合

# Dockerfile with ShellCheck validation
FROM alpine:3.19 AS builder

# Install ShellCheck
RUN apk add --no-cache shellcheck bash

# Copy scripts
COPY scripts/ /scripts/

# Validate all scripts before continuing
RUN find /scripts -name "*.sh" -type f -exec shellcheck --severity=warning {} +

# Final stage
FROM alpine:3.19
COPY --from=builder /scripts/ /scripts/
RUN chmod +x /scripts/*.sh

ENTRYPOINT ["/scripts/entrypoint.sh"]

よく使われる ShellCheck ルール(2025)

v0.11.0 の新機能:SC2327/SC2328 - キャプチャグループ
# ❌ Bad - Capture groups may not work as expected
if [[ "$string" =~ ([0-9]+)\.([0-9]+) ]]; then
  echo "$1"  # Wrong: $1 is script arg, not capture group
fi

# ✅ Good - Use BASH_REMATCH array
if [[ "$string" =~ ([0-9]+)\.([0-9]+) ]]; then
  echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
fi
SC2294:eval は配列の利点を損ないます(新規)
# ❌ Bad - eval defeats array safety
eval "command ${array[@]}"

# ✅ Good - Direct array usage
command "${array[@]}"
SC2295:${} 内の展開を引用符で囲む
# ❌ Bad
echo "${var-$default}"  # $default not quoted

# ✅ Good
echo "${var-"$default"}"
SC2086:変数を引用符で囲む
# ❌ Bad
file=$1
cat $file  # Fails if filename has spaces

# ✅ Good
file=$1
cat "$file"
SC2046:コマンド置換を引用符で囲む
# ❌ Bad
for file in $(find . -name "*.txt"); do
  echo $file
done

# ✅ Good
find . -name "*.txt" -print0 | while IFS= read -r -d '' file; do
  echo "$file"
done
SC2155:宣言と代入を分ける
# ❌ Bad
local result=$(command)  # Hides command exit code

# ✅ Good
local result
result=$(command)
SC2164:cd || exit を使用する
# ❌ Bad
cd /some/directory
./script.sh  # Runs in wrong dir if cd fails

# ✅ Good
cd /some/directory || exit 1
./script.sh

Google Shell Style Guide(50 行制限)

2025 年の推奨事項:スクリプトは 50 行未満に保ってください。

# ❌ Bad: 500-line monolithic script
#!/usr/bin/env bash
# ... 500 lines of code ...

# ✅ Good: Modular scripts < 50 lines each

# lib/logging.sh (20 lines)
log_info() { echo "[INFO] $*"; }
log_error() { echo "[ERROR] $*" >&2; }

# lib/validation.sh (30 lines)
validate_input() { ... }
check_dependencies() { ... }

# main.sh (40 lines)
source "$(dirname "$0")/lib/logging.sh"
source "$(dirname "$0")/lib/validation.sh"

main() {
  validate_input "$@"
  check_dependencies
  # ... core logic ...
}

main "$@"

CI/CD で徹底する

問題があればビルドを失敗させる
# Strict enforcement
- name: ShellCheck (Strict)
  run: |
    shellcheck --severity=warning scripts/*.sh
  # Exit code 1 fails the build

# Advisory only (warnings but don't fail)
- name: ShellCheck (Advisory)
  run: |
    shellcheck --severity=warning scripts/*.sh || true
  # Logs warnings but doesn't fail
レポートを生成する
# JSON format for parsing
shellcheck --format=json scripts/*.sh > shellcheck-report.json

# GitHub annotations format
shellcheck --format=gcc scripts/*.sh

# Human-readable
shellcheck --format=tty scripts/*.sh

最新のエラーハンドリング 3 点セット(2025)

必ず ShellCheck の検証と併用してください。

#!/usr/bin/env bash

# Modern error handling (non-negotiable in 2025)
set -o errexit   # Exit on command failure
set -o nounset   # Exit on undefined variable
set -o pipefail  # Exit on pipe failure

# ShellCheck approved
main() {
  local config_file="${1:?Config file required}"

  if [[ ! -f "$config_file" ]]; then
    echo "Error: Config file not found: $config_file" >&2
    return 1
  fi

  # Safe command execution
  local result
  result=$(process_config "$config_file")

  echo "$result"
}

main "$@"

ベストプラクティス(2025)

  1. CI/CD で ShellCheck を実行する(必須)
  2. コミット前フックを使用して問題を早期に検出する
  3. スクリプトを 50 行未満に保つ(Google Style Guide)
  4. 最新のエラーハンドリング 3 点セットを使用する(errexit、nounset、pipefail)
  5. マージ前にすべての警告を修正する
  6. 無効にしたルールとその理由を記録する
  7. IDE に統合してリアルタイムでフィードバックを得る

リソース

コメント