关于 shellcheck-cicd-2025
为 Bash 开发者提供 ShellCheck 与 CI/CD 集成及脚本规范指导,涵盖 GitHub Actions、Azure DevOps、Git hooks、VS Code 和 Docker 构建。
主要功能
- 01配置 GitHub Actions 检查
- 02集成 Azure DevOps 流水线
- 03通过 Git hooks 执行检查
- 04在 VS Code 中启用 ShellCheck
- 05生成多种格式的检查报告
适用场景
- 01在合并前检查 Bash 脚本
- 02在提交时拦截脚本问题
- 03将 ShellCheck 纳入 Docker 构建
- 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 Hooks(提交前)
# .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 风格指南(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
现代错误处理三件套(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)
- 在 CI/CD 中运行 ShellCheck(必备)
- 使用提交前钩子,及早发现问题
- 将脚本控制在 50 行以内(Google 风格指南)
- 使用现代错误处理三件套(errexit、nounset、pipefail)
- 合并前修复所有警告
- 说明禁用任何规则的原因
- 集成到 IDE 中,获取实时反馈
资源
评论
支持 Markdown