@hybridlabor-api/aos 4.8.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/{agents.md → AGENTS.md} +3 -1
- package/.agents/nodes.json +3 -1
- package/.agents/vendor-manifest.json +23 -1
- package/.claude/agents/godmode-media-eventtech.md +1 -1
- package/.claude/hooks/conventional-commits.mjs +125 -0
- package/.claude/hooks/env-file-protection.mjs +105 -0
- package/.claude/hooks/go-gate.mjs +101 -81
- package/.claude/hooks/memb-inject.mjs +29 -1
- package/.claude/settings.json +13 -0
- package/.claude/workflows/startcycle-dispatch.mjs +23 -1
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/CLAUDE.md +0 -571
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +126 -0
- package/bin/aos-doctor.mjs +1 -1
- package/docs/skills_table.md +1 -1
- package/installer.js +187 -55
- package/package.json +7 -3
- package/packages/aos-cli/README.md +80 -0
- package/packages/aos-cli/bin/aos-cli.mjs +134 -0
- package/packages/aos-cli/core-skills.json +12 -0
- package/packages/aos-cli/extensions/aos.ts +321 -0
- package/packages/aos-cli/package-lock.json +1923 -0
- package/packages/aos-cli/package.json +29 -0
- package/packages/aos-cli/scripts/check-theme.mjs +63 -0
- package/packages/aos-cli/themes/aos.json +97 -0
- package/scripts/build-plugin-manifest.mjs +131 -0
- package/scripts/validate-skills.mjs +81 -6
- package/skills/basic/ao-orchestrator/SKILL.md +116 -0
- package/skills/basic/bdb-eventagency-skill/SKILL.md +252 -0
- package/skills/basic/bdb-shipping-skill/SKILL.md +161 -0
- package/skills/basic/godmode-eventtech/SKILL.md +4 -1
- package/skills/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/aos-project-init/SKILL.md +2 -0
- package/skills/global_config/aos-project-init/assets/AGENTS.template.md +1 -1
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +1 -1
- package/skills/global_config/aos-setup/SKILL.md +1 -1
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +1 -1
- package/skills/global_config/ask-tim/SKILL.md +7 -7
- package/skills/global_config/bash-script-generator/SKILL.md +201 -0
- package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
- package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
- package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
- package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
- package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
- package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
- package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
- package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
- package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
- package/skills/global_config/bash-script-validator/SKILL.md +249 -0
- package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
- package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
- package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
- package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
- package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
- package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
- package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
- package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
- package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
- package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
- package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
- package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
- package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
- package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
- package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
- package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
- package/skills/global_config/ci-pipeline/SKILL.md +135 -0
- package/skills/global_config/deja-memory/SKILL.md +3 -1
- package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
- package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
- package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
- package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
- package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
- package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
- package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
- package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
- package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
- package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
- package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
- package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
- package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
- package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
- package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
- package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
- package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
- package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
- package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
- package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
- package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
- package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
- package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
- package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
- package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
- package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
- package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
- package/skills/global_config/github-actions-generator/SKILL.md +353 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
- package/skills/global_config/github-actions-generator/examples/README.md +147 -0
- package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
- package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
- package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
- package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
- package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
- package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
- package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
- package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
- package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
- package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
- package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
- package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
- package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
- package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
- package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
- package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
- package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
- package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
- package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
- package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
- package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
- package/skills/global_config/github-actions-templates/SKILL.md +7 -0
- package/skills/global_config/github-actions-validator/SKILL.md +576 -0
- package/skills/global_config/github-actions-validator/examples/README.md +88 -0
- package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
- package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
- package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
- package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
- package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
- package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
- package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
- package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
- package/skills/global_config/github-actions-validator/references/runners.md +317 -0
- package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
- package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
- package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
- package/skills/global_config/makefile-generator/SKILL.md +614 -0
- package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
- package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
- package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
- package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
- package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
- package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
- package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
- package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
- package/skills/global_config/makefile-validator/SKILL.md +244 -0
- package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
- package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
- package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
- package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
- package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
- package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
- package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
- package/skills/global_config/{MCP_Manage → mcp-manage}/SKILL.md +3 -3
- package/skills/global_config/plan-canvas/SKILL.md +9 -2
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +10 -2
- package/skills/global_config/plan-canvas/scripts/plan-canvas.js +1 -1
- package/skills/global_config/read-the-damn-docs/SKILL.md +175 -0
- package/skills/global_config/requesting-code-review/SKILL.md +98 -0
- package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
- package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
- package/skills/global_config/verification-before-completion/SKILL.md +123 -0
- package/skills/global_config/writing-plans/SKILL.md +126 -46
- package/skills/global_config/writing-plans-legacy/SKILL.md +152 -0
- package/.claude/CLAUDE.md +0 -12
- package/mcps/RhinoMCP/docs/content/docs/getting-started/gemini.md +0 -61
- /package/{GEMINI.md → RULES.md} +0 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# ShellCheck Reference Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
ShellCheck is a static analysis tool for shell scripts that provides warnings and suggestions for syntax and semantic issues to improve script quality and prevent errors.
|
|
6
|
+
|
|
7
|
+
**Official Website:** https://www.shellcheck.net/
|
|
8
|
+
**GitHub:** https://github.com/koalaman/shellcheck
|
|
9
|
+
**Wiki:** https://github.com/koalaman/shellcheck/wiki
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# macOS
|
|
15
|
+
brew install shellcheck
|
|
16
|
+
|
|
17
|
+
# Ubuntu/Debian
|
|
18
|
+
apt-get install shellcheck
|
|
19
|
+
|
|
20
|
+
# Fedora
|
|
21
|
+
dnf install shellcheck
|
|
22
|
+
|
|
23
|
+
# From source/binary
|
|
24
|
+
# See: https://github.com/koalaman/shellcheck#installing
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Basic Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Check a script
|
|
31
|
+
shellcheck script.sh
|
|
32
|
+
|
|
33
|
+
# Specify shell dialect
|
|
34
|
+
shellcheck -s bash script.sh
|
|
35
|
+
shellcheck -s sh script.sh
|
|
36
|
+
shellcheck -s ksh script.sh
|
|
37
|
+
shellcheck -s zsh script.sh
|
|
38
|
+
|
|
39
|
+
# Different output formats
|
|
40
|
+
shellcheck -f gcc script.sh # GCC-style (for editors)
|
|
41
|
+
shellcheck -f checkstyle script.sh # Checkstyle XML
|
|
42
|
+
shellcheck -f json script.sh # JSON
|
|
43
|
+
shellcheck -f tty script.sh # TTY (default, with colors)
|
|
44
|
+
|
|
45
|
+
# Check multiple files
|
|
46
|
+
shellcheck *.sh
|
|
47
|
+
|
|
48
|
+
# Exclude specific warnings
|
|
49
|
+
shellcheck -e SC2086,SC2046 script.sh
|
|
50
|
+
|
|
51
|
+
# Set minimum severity
|
|
52
|
+
shellcheck -S error script.sh # Only errors
|
|
53
|
+
shellcheck -S warning script.sh # Warnings and above
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Severity Levels
|
|
57
|
+
|
|
58
|
+
ShellCheck categorizes issues into four severity levels:
|
|
59
|
+
|
|
60
|
+
1. **error** - Critical issues that will cause failures
|
|
61
|
+
2. **warning** - Potential bugs or problematic patterns
|
|
62
|
+
3. **info** - Suggestions for improvement
|
|
63
|
+
4. **style** - Stylistic improvements
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Show only errors
|
|
67
|
+
shellcheck -S error script.sh
|
|
68
|
+
|
|
69
|
+
# Show errors and warnings
|
|
70
|
+
shellcheck -S warning script.sh
|
|
71
|
+
|
|
72
|
+
# Show everything (default)
|
|
73
|
+
shellcheck script.sh
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Common Error Codes
|
|
77
|
+
|
|
78
|
+
### Critical Errors (SC2xxx series)
|
|
79
|
+
|
|
80
|
+
#### SC2086: Quote Variables to Prevent Word Splitting
|
|
81
|
+
```bash
|
|
82
|
+
# Problematic
|
|
83
|
+
cp $file $destination
|
|
84
|
+
|
|
85
|
+
# Fixed
|
|
86
|
+
cp "$file" "$destination"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### SC2046: Quote Command Substitutions
|
|
90
|
+
```bash
|
|
91
|
+
# Problematic
|
|
92
|
+
for file in $(ls *.txt); do
|
|
93
|
+
|
|
94
|
+
# Fixed
|
|
95
|
+
for file in *.txt; do
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### SC2006: Use $() Instead of Backticks
|
|
99
|
+
```bash
|
|
100
|
+
# Problematic
|
|
101
|
+
result=`command`
|
|
102
|
+
|
|
103
|
+
# Fixed
|
|
104
|
+
result=$(command)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### SC2155: Declare and Assign Separately
|
|
108
|
+
```bash
|
|
109
|
+
# Problematic
|
|
110
|
+
local result=$(command) # Masks return value
|
|
111
|
+
|
|
112
|
+
# Fixed
|
|
113
|
+
local result
|
|
114
|
+
result=$(command)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### SC2164: Use || exit After cd
|
|
118
|
+
```bash
|
|
119
|
+
# Problematic
|
|
120
|
+
cd /some/directory
|
|
121
|
+
rm -rf *
|
|
122
|
+
|
|
123
|
+
# Fixed
|
|
124
|
+
cd /some/directory || exit
|
|
125
|
+
rm -rf *
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### SC2181: Check Exit Code Directly
|
|
129
|
+
```bash
|
|
130
|
+
# Problematic
|
|
131
|
+
command
|
|
132
|
+
if [ $? -eq 0 ]; then
|
|
133
|
+
|
|
134
|
+
# Fixed
|
|
135
|
+
if command; then
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### SC2068: Quote Array Expansions
|
|
139
|
+
```bash
|
|
140
|
+
# Problematic
|
|
141
|
+
command $@
|
|
142
|
+
|
|
143
|
+
# Fixed
|
|
144
|
+
command "$@"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### SC2116: Useless echo with $()
|
|
148
|
+
```bash
|
|
149
|
+
# Problematic
|
|
150
|
+
var=$(echo $value)
|
|
151
|
+
|
|
152
|
+
# Fixed
|
|
153
|
+
var=$value
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### SC2162: read Without -r
|
|
157
|
+
```bash
|
|
158
|
+
# Problematic
|
|
159
|
+
while read line; do
|
|
160
|
+
|
|
161
|
+
# Fixed
|
|
162
|
+
while IFS= read -r line; do
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### SC2005: Useless echo Piped to Command
|
|
166
|
+
```bash
|
|
167
|
+
# Problematic
|
|
168
|
+
echo "$var" | grep pattern
|
|
169
|
+
|
|
170
|
+
# Fixed
|
|
171
|
+
grep pattern <<< "$var"
|
|
172
|
+
# Or
|
|
173
|
+
printf '%s\n' "$var" | grep pattern
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Bashisms (SC3xxx series)
|
|
177
|
+
|
|
178
|
+
These warn about bash-specific features used in sh scripts:
|
|
179
|
+
|
|
180
|
+
#### SC3001: Using Bash [[ ]] in sh Script
|
|
181
|
+
```bash
|
|
182
|
+
# In #!/bin/sh script
|
|
183
|
+
if [[ condition ]]; then # Wrong
|
|
184
|
+
|
|
185
|
+
# Fixed
|
|
186
|
+
if [ condition ]; then
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### SC3037: Using Bash Arrays in sh Script
|
|
190
|
+
```bash
|
|
191
|
+
# In #!/bin/sh script
|
|
192
|
+
array=(one two) # Wrong
|
|
193
|
+
|
|
194
|
+
# No direct fix - arrays not in POSIX sh
|
|
195
|
+
# Use alternatives like positional parameters
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Disabling Checks
|
|
199
|
+
|
|
200
|
+
### Disable Specific Line
|
|
201
|
+
```bash
|
|
202
|
+
# shellcheck disable=SC2086
|
|
203
|
+
variable=$unquoted
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Disable for Entire File
|
|
207
|
+
```bash
|
|
208
|
+
# At top of file
|
|
209
|
+
# shellcheck disable=SC2086,SC2046
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Disable Next Line
|
|
213
|
+
```bash
|
|
214
|
+
# shellcheck disable=SC2086
|
|
215
|
+
variable=$unquoted
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Disable for Block
|
|
219
|
+
```bash
|
|
220
|
+
# shellcheck disable=SC2086
|
|
221
|
+
{
|
|
222
|
+
var1=$unquoted1
|
|
223
|
+
var2=$unquoted2
|
|
224
|
+
}
|
|
225
|
+
# shellcheck enable=SC2086
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## ShellCheck Directives
|
|
229
|
+
|
|
230
|
+
### Shell Directive
|
|
231
|
+
```bash
|
|
232
|
+
# Specify shell dialect (overrides shebang)
|
|
233
|
+
# shellcheck shell=bash
|
|
234
|
+
# or
|
|
235
|
+
# shellcheck shell=sh
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Source Directive
|
|
239
|
+
```bash
|
|
240
|
+
# Tell ShellCheck where to find sourced files
|
|
241
|
+
# shellcheck source=./lib/common.sh
|
|
242
|
+
. ./lib/common.sh
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### External Sources
|
|
246
|
+
```bash
|
|
247
|
+
# For dynamically sourced files
|
|
248
|
+
# shellcheck source=/dev/null
|
|
249
|
+
. "$config_file"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Configuration File
|
|
253
|
+
|
|
254
|
+
Create `.shellcheckrc` in project root or `~/.shellcheckrc`:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# Disable specific checks globally
|
|
258
|
+
disable=SC2086,SC2046,SC2068
|
|
259
|
+
|
|
260
|
+
# Enable optional checks
|
|
261
|
+
enable=all
|
|
262
|
+
enable=avoid-nullary-conditions
|
|
263
|
+
|
|
264
|
+
# Specify shell
|
|
265
|
+
shell=bash
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Integration with CI/CD
|
|
269
|
+
|
|
270
|
+
### GitHub Actions
|
|
271
|
+
```yaml
|
|
272
|
+
- name: Run ShellCheck
|
|
273
|
+
uses: ludeeus/action-shellcheck@master
|
|
274
|
+
with:
|
|
275
|
+
severity: warning
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### GitLab CI
|
|
279
|
+
```yaml
|
|
280
|
+
shellcheck:
|
|
281
|
+
script:
|
|
282
|
+
- shellcheck **/*.sh
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Pre-commit Hook
|
|
286
|
+
```yaml
|
|
287
|
+
# .pre-commit-config.yaml
|
|
288
|
+
- repo: https://github.com/shellcheck-py/shellcheck-py
|
|
289
|
+
rev: v0.9.0.2
|
|
290
|
+
hooks:
|
|
291
|
+
- id: shellcheck
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Common Patterns and Best Practices
|
|
295
|
+
|
|
296
|
+
### 1. Always Quote Variables
|
|
297
|
+
ShellCheck will flag unquoted variables in most contexts.
|
|
298
|
+
|
|
299
|
+
### 2. Use -r Flag with read
|
|
300
|
+
```bash
|
|
301
|
+
# Good
|
|
302
|
+
while IFS= read -r line; do
|
|
303
|
+
echo "$line"
|
|
304
|
+
done < file
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### 3. Check Command Existence
|
|
308
|
+
```bash
|
|
309
|
+
if command -v shellcheck >/dev/null 2>&1; then
|
|
310
|
+
echo "Found"
|
|
311
|
+
fi
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 4. Use || exit After cd
|
|
315
|
+
```bash
|
|
316
|
+
cd /directory || exit 1
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 5. Use [[ ]] in Bash, [ ] in sh
|
|
320
|
+
ShellCheck knows your shell and will warn appropriately.
|
|
321
|
+
|
|
322
|
+
### 6. Proper Array Usage
|
|
323
|
+
```bash
|
|
324
|
+
# Good (bash)
|
|
325
|
+
args=("first arg" "second arg")
|
|
326
|
+
command "${args[@]}"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### 7. Avoid Useless cat
|
|
330
|
+
```bash
|
|
331
|
+
# Instead of
|
|
332
|
+
cat file | grep pattern
|
|
333
|
+
|
|
334
|
+
# Use
|
|
335
|
+
grep pattern file
|
|
336
|
+
# or
|
|
337
|
+
< file grep pattern
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Advanced Features
|
|
341
|
+
|
|
342
|
+
### Optional Checks
|
|
343
|
+
Some checks are not enabled by default:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
# Enable all optional checks
|
|
347
|
+
# shellcheck enable=all
|
|
348
|
+
|
|
349
|
+
# Or specific ones
|
|
350
|
+
# shellcheck enable=avoid-nullary-conditions
|
|
351
|
+
# shellcheck enable=quote-safe-variables
|
|
352
|
+
# shellcheck enable=require-variable-braces
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Custom Severity
|
|
356
|
+
```bash
|
|
357
|
+
# Change severity of specific check
|
|
358
|
+
# shellcheck severity=warning SC2086
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## Exit Codes
|
|
362
|
+
|
|
363
|
+
- **0**: No issues found
|
|
364
|
+
- **1**: Some issues found
|
|
365
|
+
- **2**: Syntax errors that prevent parsing
|
|
366
|
+
- **3**: ShellCheck error (bad options, missing files)
|
|
367
|
+
- **4**: ShellCheck not installed
|
|
368
|
+
|
|
369
|
+
## Editor Integration
|
|
370
|
+
|
|
371
|
+
ShellCheck integrates with most editors:
|
|
372
|
+
|
|
373
|
+
- **VS Code**: ShellCheck extension
|
|
374
|
+
- **Vim**: via ALE, Syntastic, or vim-shellcheck
|
|
375
|
+
- **Emacs**: flycheck-shellcheck
|
|
376
|
+
- **Sublime Text**: SublimeLinter-shellcheck
|
|
377
|
+
- **Atom**: linter-shellcheck
|
|
378
|
+
|
|
379
|
+
## Resources
|
|
380
|
+
|
|
381
|
+
- **Main Website**: https://www.shellcheck.net/
|
|
382
|
+
- **Wiki with Error Codes**: https://github.com/koalaman/shellcheck/wiki
|
|
383
|
+
- **Try Online**: https://www.shellcheck.net/
|
|
384
|
+
- **GitHub Issues**: https://github.com/koalaman/shellcheck/issues
|
|
385
|
+
|
|
386
|
+
## Quick Reference Table
|
|
387
|
+
|
|
388
|
+
| Code | Issue | Fix |
|
|
389
|
+
|------|-------|-----|
|
|
390
|
+
| SC2086 | Unquoted variable | Add quotes: `"$var"` |
|
|
391
|
+
| SC2046 | Unquoted $() | Quote command substitution |
|
|
392
|
+
| SC2006 | Backticks | Use `$()` instead |
|
|
393
|
+
| SC2155 | Declare and assign together | Separate into two lines |
|
|
394
|
+
| SC2164 | cd without error check | Add `|| exit` |
|
|
395
|
+
| SC2181 | Checking $? | Check command directly |
|
|
396
|
+
| SC2068 | Unquoted $@ | Quote: `"$@"` |
|
|
397
|
+
| SC2162 | read without -r | Add `-r` flag |
|
|
398
|
+
| SC3001 | [[ in sh script | Use [ ] instead |
|
|
399
|
+
| SC3037 | Arrays in sh script | Use POSIX alternatives |
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Example of a poorly-written bash script with common mistakes
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
# Missing: set -euo pipefail
|
|
7
|
+
|
|
8
|
+
LOG_FILE=/tmp/example.log
|
|
9
|
+
|
|
10
|
+
# Function defined after use (will fail)
|
|
11
|
+
main
|
|
12
|
+
|
|
13
|
+
log_info() {
|
|
14
|
+
# Bad: unquoted variable
|
|
15
|
+
echo [INFO] $*
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Bad: using backticks instead of $()
|
|
19
|
+
result=`date`
|
|
20
|
+
|
|
21
|
+
process_file() {
|
|
22
|
+
file=$1 # Not local
|
|
23
|
+
|
|
24
|
+
# Bad: not quoting variable
|
|
25
|
+
if [ ! -f $file ]; then
|
|
26
|
+
echo "File not found"
|
|
27
|
+
return 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Bad: useless use of cat
|
|
31
|
+
cat $file | grep pattern
|
|
32
|
+
|
|
33
|
+
# Bad: eval with variable (security risk)
|
|
34
|
+
eval $user_command
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
main() {
|
|
38
|
+
# Bad: not checking if arguments provided
|
|
39
|
+
# Bad: unquoted $@
|
|
40
|
+
for file in $@; do
|
|
41
|
+
# Bad: not checking return value
|
|
42
|
+
cd /some/directory
|
|
43
|
+
rm -rf * # DANGEROUS!
|
|
44
|
+
|
|
45
|
+
process_file $file
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
# Bad: checking $? after multiple commands
|
|
49
|
+
if [ $? -eq 0 ]; then
|
|
50
|
+
echo "Success"
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Bad: calling main without "$@"
|
|
55
|
+
main $*
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
# Example of a poorly-written shell script with bashisms and other mistakes
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
# Bad: using bash-specific [[ ]]
|
|
7
|
+
if [[ -f /etc/passwd ]]; then
|
|
8
|
+
echo "File exists"
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
# Bad: using bash arrays in sh script
|
|
12
|
+
array=(one two three)
|
|
13
|
+
echo ${array[0]}
|
|
14
|
+
|
|
15
|
+
# Bad: using bash-specific function keyword
|
|
16
|
+
function process_data {
|
|
17
|
+
# Bad: using bash-specific 'local'
|
|
18
|
+
local data=$1
|
|
19
|
+
|
|
20
|
+
# Bad: unquoted variable
|
|
21
|
+
echo $data
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Bad: using 'source' instead of '.'
|
|
25
|
+
source /etc/profile
|
|
26
|
+
|
|
27
|
+
# Bad: using == instead of =
|
|
28
|
+
if [ "$var" == "value" ]; then
|
|
29
|
+
echo "match"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Bad: process substitution (bash-specific)
|
|
33
|
+
diff <(ls dir1) <(ls dir2)
|
|
34
|
+
|
|
35
|
+
# Bad: brace expansion (bash-specific)
|
|
36
|
+
echo {1..10}
|
|
37
|
+
|
|
38
|
+
# Bad: $RANDOM (bash-specific)
|
|
39
|
+
random_num=$RANDOM
|
|
40
|
+
|
|
41
|
+
# Bad: using [[ with regex (bash-specific)
|
|
42
|
+
if [[ "$string" =~ pattern ]]; then
|
|
43
|
+
echo "matches"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Bad: not quoting variables
|
|
47
|
+
file=/path/with spaces/file.txt
|
|
48
|
+
cat $file
|
|
49
|
+
|
|
50
|
+
# Bad: useless use of cat
|
|
51
|
+
cat file.txt | grep pattern
|
|
52
|
+
|
|
53
|
+
# Bad: using eval without sanitization
|
|
54
|
+
eval $user_input
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Example of a well-written bash script following best practices
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Constants
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
+
readonly SCRIPT_DIR
|
|
11
|
+
readonly LOG_FILE="/tmp/example.log"
|
|
12
|
+
|
|
13
|
+
# Functions
|
|
14
|
+
log_info() {
|
|
15
|
+
echo "[INFO] $*" | tee -a "$LOG_FILE"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
log_error() {
|
|
19
|
+
echo "[ERROR] $*" >&2 | tee -a "$LOG_FILE"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
cleanup() {
|
|
23
|
+
log_info "Cleaning up..."
|
|
24
|
+
rm -f "$temp_file"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
trap cleanup EXIT
|
|
28
|
+
|
|
29
|
+
process_file() {
|
|
30
|
+
local file="$1"
|
|
31
|
+
|
|
32
|
+
if [[ ! -f "$file" ]]; then
|
|
33
|
+
log_error "File not found: $file"
|
|
34
|
+
return 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
log_info "Processing file: $file"
|
|
38
|
+
|
|
39
|
+
# Good: using modern command substitution
|
|
40
|
+
local line_count
|
|
41
|
+
line_count=$(wc -l < "$file")
|
|
42
|
+
|
|
43
|
+
log_info "File has $line_count lines"
|
|
44
|
+
return 0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
main() {
|
|
48
|
+
log_info "Script started from $SCRIPT_DIR"
|
|
49
|
+
|
|
50
|
+
# Create temporary file
|
|
51
|
+
local temp_file
|
|
52
|
+
temp_file=$(mktemp)
|
|
53
|
+
|
|
54
|
+
# Good: proper argument handling
|
|
55
|
+
if [[ $# -eq 0 ]]; then
|
|
56
|
+
log_error "Usage: $0 <file1> [file2 ...]"
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Good: quoted "$@" preserves arguments
|
|
61
|
+
for file in "$@"; do
|
|
62
|
+
if ! process_file "$file"; then
|
|
63
|
+
log_error "Failed to process: $file"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
log_info "Script completed successfully"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
main "$@"
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
# Example of a well-written POSIX shell script
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
set -eu
|
|
7
|
+
|
|
8
|
+
# POSIX-compliant - no bashisms
|
|
9
|
+
|
|
10
|
+
readonly SCRIPT_NAME="${0##*/}"
|
|
11
|
+
readonly LOG_FILE="/tmp/example.log"
|
|
12
|
+
|
|
13
|
+
log_info() {
|
|
14
|
+
printf '[INFO] %s\n' "$*" | tee -a "$LOG_FILE"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
log_error() {
|
|
18
|
+
printf '[ERROR] %s\n' "$*" >&2
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
cleanup() {
|
|
22
|
+
log_info "Cleaning up..."
|
|
23
|
+
rm -f "$temp_file"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
trap cleanup EXIT INT TERM
|
|
27
|
+
|
|
28
|
+
process_file() {
|
|
29
|
+
file="$1"
|
|
30
|
+
|
|
31
|
+
# POSIX: using [ ] not [[ ]]
|
|
32
|
+
if [ ! -f "$file" ]; then
|
|
33
|
+
log_error "File not found: $file"
|
|
34
|
+
return 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
log_info "Processing file: $file"
|
|
38
|
+
|
|
39
|
+
# POSIX: command substitution with $()
|
|
40
|
+
line_count=$(wc -l < "$file")
|
|
41
|
+
|
|
42
|
+
log_info "File has $line_count lines"
|
|
43
|
+
return 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
main() {
|
|
47
|
+
log_info "Script started"
|
|
48
|
+
|
|
49
|
+
# Create temporary file
|
|
50
|
+
temp_file=$(mktemp)
|
|
51
|
+
|
|
52
|
+
# Proper argument handling
|
|
53
|
+
if [ $# -eq 0 ]; then
|
|
54
|
+
log_error "Usage: $SCRIPT_NAME <file1> [file2 ...]"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# POSIX: iterate over positional parameters
|
|
59
|
+
for file in "$@"; do
|
|
60
|
+
if ! process_file "$file"; then
|
|
61
|
+
log_error "Failed to process: $file"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
log_info "Script completed successfully"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main "$@"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Deterministic CI runner for bash-script-validator.
|
|
4
|
+
# Uses system shellcheck only and fails fast when unavailable.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
+
readonly SCRIPT_DIR
|
|
11
|
+
TEST_SCRIPT="$SCRIPT_DIR/test_validate.sh"
|
|
12
|
+
|
|
13
|
+
if ! command -v shellcheck >/dev/null 2>&1; then
|
|
14
|
+
echo "[ERROR] System shellcheck is required for deterministic CI checks." >&2
|
|
15
|
+
echo " Install shellcheck and re-run scripts/run_ci_checks.sh." >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
echo "[INFO] Running deterministic bash-script-validator regression suite..."
|
|
20
|
+
CI=1 \
|
|
21
|
+
VALIDATOR_REQUIRE_SHELLCHECK=1 \
|
|
22
|
+
VALIDATOR_SHELLCHECK_MODE=system \
|
|
23
|
+
bash "$TEST_SCRIPT"
|