重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
shellcheck-cicd-2025 by josiahsiegel/claude-plugin-marketplace
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill shellcheck-cicd-2025强制规定:在 Windows 上始终对文件路径使用反斜杠
在 Windows 上使用编辑或写入工具时,必须在文件路径中使用反斜杠(\),而不是正斜杠(/)。
示例:
D:/repos/project/file.tsxD:\repos\project\file.tsx这适用于:
除非用户明确要求,否则切勿创建新的文档文件。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
ShellCheck 现在被认为是现代 bash 工作流中强制要求的(2025 年最佳实践):
新增内容:
${| cmd; } 和 source -p)# Ubuntu/Debian
apt-get install shellcheck
# macOS
brew install shellcheck
# Alpine (Docker)
apk add shellcheck
# Windows (WSL/Git Bash)
choco install shellcheck
# 或下载二进制文件
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/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 # 或:tty, json, checkstyle
scandir: './scripts'
# 任何问题都导致失败
ignore_paths: 'node_modules'
# 失败时阻止合并
- 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 验证失败。请在合并前修复问题。'
})
# 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: '安装 ShellCheck'
- script: |
find . -name "*.sh" -type f | xargs shellcheck --format=gcc --severity=warning
displayName: '运行 ShellCheck'
failOnStderr: true
- task: PublishTestResults@2
condition: always()
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/shellcheck-results.xml'
failTaskOnFailedTests: true
# .git/hooks/pre-commit
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# 查找所有暂存的 .sh 文件
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 "正在对暂存文件运行 ShellCheck..."
# 运行 ShellCheck
shellcheck --format=gcc --severity=warning "${STAGED_SH[@]}"
if [ $? -ne 0 ]; then
echo "⛔ ShellCheck 失败。请在提交前修复问题。"
exit 1
fi
echo "✅ ShellCheck 通过"
exit 0
安装预提交钩子:
chmod +x .git/hooks/pre-commit
# 或使用 pre-commit 框架
# .pre-commit-config.yaml
repos:
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.0
hooks:
- id: shellcheck
args: ['--severity=warning']
# 安装
pip install pre-commit
pre-commit install
// .vscode/settings.json
{
"shellcheck.enable": true,
"shellcheck.run": "onType",
"shellcheck.executablePath": "/usr/local/bin/shellcheck",
"shellcheck.exclude": ["SC1090", "SC1091"], // 可选排除项
"shellcheck.customArgs": [
"-x", // 跟踪源文件
"--severity=warning"
]
}
# 包含 ShellCheck 验证的 Dockerfile
FROM alpine:3.19 AS builder
# 安装 ShellCheck
RUN apk add --no-cache shellcheck bash
# 复制脚本
COPY scripts/ /scripts/
# 在继续之前验证所有脚本
RUN find /scripts -name "*.sh" -type f -exec shellcheck --severity=warning {} +
# 最终阶段
FROM alpine:3.19
COPY --from=builder /scripts/ /scripts/
RUN chmod +x /scripts/*.sh
ENTRYPOINT ["/scripts/entrypoint.sh"]
# ❌ 错误 - 捕获组可能无法按预期工作
if [[ "$string" =~ ([0-9]+)\.([0-9]+) ]]; then
echo "$1" # 错误:$1 是脚本参数,不是捕获组
fi
# ✅ 正确 - 使用 BASH_REMATCH 数组
if [[ "$string" =~ ([0-9]+)\.([0-9]+) ]]; then
echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
fi
# ❌ 错误 - eval 破坏了数组的安全性
eval "command ${array[@]}"
# ✅ 正确 - 直接使用数组
command "${array[@]}"
# ❌ 错误
echo "${var-$default}" # $default 未引用
# ✅ 正确
echo "${var-"$default"}"
# ❌ 错误
file=$1
cat $file # 如果文件名包含空格会失败
# ✅ 正确
file=$1
cat "$file"
# ❌ 错误
for file in $(find . -name "*.txt"); do
echo $file
done
# ✅ 正确
find . -name "*.txt" -print0 | while IFS= read -r -d '' file; do
echo "$file"
done
# ❌ 错误
local result=$(command) # 隐藏了命令的退出码
# ✅ 正确
local result
result=$(command)
# ❌ 错误
cd /some/directory
./script.sh # 如果 cd 失败,会在错误的目录中运行
# ✅ 正确
cd /some/directory || exit 1
./script.sh
2025 年建议:保持脚本在 50 行以内:
# ❌ 错误:500 行的单一脚本
#!/usr/bin/env bash
# ... 500 行代码 ...
# ✅ 正确:每个模块化脚本 < 50 行
# lib/logging.sh (20 行)
log_info() { echo "[INFO] $*"; }
log_error() { echo "[ERROR] $*" >&2; }
# lib/validation.sh (30 行)
validate_input() { ... }
check_dependencies() { ... }
# main.sh (40 行)
source "$(dirname "$0")/lib/logging.sh"
source "$(dirname "$0")/lib/validation.sh"
main() {
validate_input "$@"
check_dependencies
# ... 核心逻辑 ...
}
main "$@"
# 严格强制执行
- name: ShellCheck (严格)
run: |
shellcheck --severity=warning scripts/*.sh
# 退出码 1 导致构建失败
# 仅建议(警告但不失败)
- name: ShellCheck (建议)
run: |
shellcheck --severity=warning scripts/*.sh || true
# 记录警告但不导致失败
# JSON 格式用于解析
shellcheck --format=json scripts/*.sh > shellcheck-report.json
# GitHub 注释格式
shellcheck --format=gcc scripts/*.sh
# 人类可读格式
shellcheck --format=tty scripts/*.sh
始终与 ShellCheck 验证一起使用:
#!/usr/bin/env bash
# 现代错误处理(2025 年不容妥协)
set -o errexit # 命令失败时退出
set -o nounset # 未定义变量时退出
set -o pipefail # 管道失败时退出
# ShellCheck 批准
main() {
local config_file="${1:?需要配置文件}"
if [[ ! -f "$config_file" ]]; then
echo "错误:未找到配置文件:$config_file" >&2
return 1
fi
# 安全的命令执行
local result
result=$(process_config "$config_file")
echo "$result"
}
main "$@"
每周安装次数
66
仓库
GitHub 星标数
21
首次出现
2026 年 1 月 24 日
安全审计
安装于
claude-code53
opencode49
gemini-cli48
codex46
cursor44
github-copilot42
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
Examples:
D:/repos/project/file.tsxD:\repos\project\file.tsxThis applies to:
NEVER create new documentation files unless explicitly requested by the user.
ShellCheck is now considered mandatory in modern bash workflows (2025 best practices):
What's New:
${| cmd; } and source -p)# 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/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-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/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
Install Pre-Commit Hook:
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
// .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"
]
}
# 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"]
# ❌ 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
# ❌ Bad - eval defeats array safety
eval "command ${array[@]}"
# ✅ Good - Direct array usage
command "${array[@]}"
# ❌ Bad
echo "${var-$default}" # $default not quoted
# ✅ Good
echo "${var-"$default"}"
# ❌ Bad
file=$1
cat $file # Fails if filename has spaces
# ✅ Good
file=$1
cat "$file"
# ❌ 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
# ❌ Bad
local result=$(command) # Hides command exit code
# ✅ Good
local result
result=$(command)
# ❌ Bad
cd /some/directory
./script.sh # Runs in wrong dir if cd fails
# ✅ Good
cd /some/directory || exit 1
./script.sh
2025 recommendation: Keep scripts under 50 lines:
# ❌ 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 "$@"
# 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
Always use with ShellCheck validation:
#!/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 "$@"
Weekly Installs
66
Repository
GitHub Stars
21
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubWarnSocketPassSnykWarn
Installed on
claude-code53
opencode49
gemini-cli48
codex46
cursor44
github-copilot42
Azure 升级评估与自动化工具 - 轻松迁移 Functions 计划、托管层级和 SKU
111,700 周安装