@hybridlabor-api/aos 4.8.0 → 4.9.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 +1 -1
- package/.agents/nodes.json +1 -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/settings.json +13 -0
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +88 -0
- package/docs/skills_table.md +1 -1
- package/installer.js +174 -46
- package/package.json +6 -2
- 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/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/ask-tim/SKILL.md +4 -4
- 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/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/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 +139 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Bash/Shell Script Validator
|
|
4
|
+
# Validates bash and shell scripts for syntax errors, best practices, security issues, and optimizations
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Colors for output
|
|
10
|
+
RED='\033[0;31m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
BLUE='\033[0;34m'
|
|
14
|
+
NC='\033[0m' # No Color
|
|
15
|
+
|
|
16
|
+
# Counters
|
|
17
|
+
ERROR_COUNT=0
|
|
18
|
+
WARNING_COUNT=0
|
|
19
|
+
INFO_COUNT=0
|
|
20
|
+
STYLE_COUNT=0
|
|
21
|
+
|
|
22
|
+
# Script path
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
|
|
25
|
+
# ShellCheck policy:
|
|
26
|
+
# - default strict in CI
|
|
27
|
+
# - override with VALIDATOR_REQUIRE_SHELLCHECK=0|1
|
|
28
|
+
REQUIRE_SHELLCHECK="${VALIDATOR_REQUIRE_SHELLCHECK:-}"
|
|
29
|
+
if [[ -z "$REQUIRE_SHELLCHECK" ]]; then
|
|
30
|
+
if [[ -n "${CI:-}" ]]; then
|
|
31
|
+
REQUIRE_SHELLCHECK=1
|
|
32
|
+
else
|
|
33
|
+
REQUIRE_SHELLCHECK=0
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# ShellCheck provider selection:
|
|
38
|
+
# - auto (default): system shellcheck, then wrapper fallback
|
|
39
|
+
# - system: require system shellcheck in PATH
|
|
40
|
+
# - wrapper: require wrapper script
|
|
41
|
+
# - disabled: skip ShellCheck stage
|
|
42
|
+
SHELLCHECK_MODE="${VALIDATOR_SHELLCHECK_MODE:-auto}"
|
|
43
|
+
if [[ "${VALIDATOR_DISABLE_SHELLCHECK:-0}" == "1" ]]; then
|
|
44
|
+
SHELLCHECK_MODE="disabled"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
usage() {
|
|
48
|
+
cat <<EOF
|
|
49
|
+
Usage: $0 <script-file>
|
|
50
|
+
|
|
51
|
+
Validates bash and shell scripts for:
|
|
52
|
+
- Syntax errors
|
|
53
|
+
- ShellCheck warnings
|
|
54
|
+
- Security issues
|
|
55
|
+
- Performance optimizations
|
|
56
|
+
- Portability concerns
|
|
57
|
+
|
|
58
|
+
Options:
|
|
59
|
+
-h, --help Show this help message
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
$0 myscript.sh
|
|
63
|
+
$0 /path/to/script.bash
|
|
64
|
+
EOF
|
|
65
|
+
exit 0
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
print_header() {
|
|
69
|
+
echo -e "${BLUE}========================================${NC}"
|
|
70
|
+
echo -e "${BLUE}$1${NC}"
|
|
71
|
+
echo -e "${BLUE}========================================${NC}"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
print_section() {
|
|
75
|
+
echo ""
|
|
76
|
+
echo -e "${BLUE}[$1]${NC}"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
print_error() {
|
|
80
|
+
echo -e "${RED}✗ $1${NC}"
|
|
81
|
+
((ERROR_COUNT++))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
print_warning() {
|
|
85
|
+
echo -e "${YELLOW}⚠ $1${NC}"
|
|
86
|
+
((WARNING_COUNT++))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
print_info() {
|
|
90
|
+
echo -e "${BLUE}ℹ $1${NC}"
|
|
91
|
+
((INFO_COUNT++))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
print_success() {
|
|
95
|
+
echo -e "${GREEN}✓ $1${NC}"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Detect shell type from shebang (returns shell:status format)
|
|
99
|
+
detect_shell() {
|
|
100
|
+
local file="$1"
|
|
101
|
+
local shebang
|
|
102
|
+
|
|
103
|
+
shebang=$(head -n 1 "$file")
|
|
104
|
+
|
|
105
|
+
# Check if shebang is present
|
|
106
|
+
if [[ ! "$shebang" =~ ^#! ]]; then
|
|
107
|
+
echo "bash:no-shebang"
|
|
108
|
+
return
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [[ "$shebang" =~ ^#!.*bash ]]; then
|
|
112
|
+
echo "bash"
|
|
113
|
+
elif [[ "$shebang" =~ ^#!/bin/sh([[:space:]]|$) ]] || \
|
|
114
|
+
[[ "$shebang" =~ ^#!/usr/bin/sh([[:space:]]|$) ]] || \
|
|
115
|
+
[[ "$shebang" =~ /env[[:space:]]+sh([[:space:]]|$) ]]; then
|
|
116
|
+
echo "sh"
|
|
117
|
+
elif [[ "$shebang" =~ ^#!.*zsh ]]; then
|
|
118
|
+
echo "zsh"
|
|
119
|
+
elif [[ "$shebang" =~ ^#!.*ksh ]]; then
|
|
120
|
+
echo "ksh"
|
|
121
|
+
elif [[ "$shebang" =~ ^#!.*dash ]]; then
|
|
122
|
+
echo "dash"
|
|
123
|
+
else
|
|
124
|
+
# Unknown shebang
|
|
125
|
+
echo "bash:unknown-shebang:$shebang"
|
|
126
|
+
fi
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Run syntax validation
|
|
130
|
+
validate_syntax() {
|
|
131
|
+
local file="$1"
|
|
132
|
+
local shell_type="$2"
|
|
133
|
+
|
|
134
|
+
print_section "SYNTAX CHECK"
|
|
135
|
+
|
|
136
|
+
case "$shell_type" in
|
|
137
|
+
bash)
|
|
138
|
+
if bash -n "$file" 2>/dev/null; then
|
|
139
|
+
print_success "No syntax errors found (bash -n)"
|
|
140
|
+
return 0
|
|
141
|
+
else
|
|
142
|
+
local errors
|
|
143
|
+
errors=$(bash -n "$file" 2>&1)
|
|
144
|
+
print_error "Syntax errors found:"
|
|
145
|
+
echo "$errors" | sed 's/^/ /'
|
|
146
|
+
return 1
|
|
147
|
+
fi
|
|
148
|
+
;;
|
|
149
|
+
sh|dash)
|
|
150
|
+
if sh -n "$file" 2>/dev/null; then
|
|
151
|
+
print_success "No syntax errors found (sh -n)"
|
|
152
|
+
return 0
|
|
153
|
+
else
|
|
154
|
+
local errors
|
|
155
|
+
errors=$(sh -n "$file" 2>&1)
|
|
156
|
+
print_error "Syntax errors found:"
|
|
157
|
+
echo "$errors" | sed 's/^/ /'
|
|
158
|
+
return 1
|
|
159
|
+
fi
|
|
160
|
+
;;
|
|
161
|
+
*)
|
|
162
|
+
print_info "Syntax check skipped for shell type: $shell_type"
|
|
163
|
+
return 0
|
|
164
|
+
;;
|
|
165
|
+
esac
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# Run shellcheck validation
|
|
169
|
+
run_shellcheck() {
|
|
170
|
+
local file="$1"
|
|
171
|
+
local shell_type="$2"
|
|
172
|
+
local shellcheck_mode="$SHELLCHECK_MODE"
|
|
173
|
+
|
|
174
|
+
print_section "SHELLCHECK"
|
|
175
|
+
|
|
176
|
+
local shell_name=""
|
|
177
|
+
case "$shell_type" in
|
|
178
|
+
bash) shell_name="bash" ;;
|
|
179
|
+
sh|dash) shell_name="sh" ;;
|
|
180
|
+
zsh) shell_name="zsh" ;;
|
|
181
|
+
ksh) shell_name="ksh" ;;
|
|
182
|
+
esac
|
|
183
|
+
|
|
184
|
+
# Determine which shellcheck to use
|
|
185
|
+
local -a shellcheck_cmd=()
|
|
186
|
+
local unavailable_reason="ShellCheck unavailable"
|
|
187
|
+
|
|
188
|
+
case "$shellcheck_mode" in
|
|
189
|
+
auto)
|
|
190
|
+
if command -v shellcheck &>/dev/null; then
|
|
191
|
+
shellcheck_cmd=("shellcheck")
|
|
192
|
+
elif [[ -x "$SCRIPT_DIR/shellcheck_wrapper.sh" ]]; then
|
|
193
|
+
shellcheck_cmd=("$SCRIPT_DIR/shellcheck_wrapper.sh" "--cache")
|
|
194
|
+
fi
|
|
195
|
+
;;
|
|
196
|
+
system)
|
|
197
|
+
if command -v shellcheck &>/dev/null; then
|
|
198
|
+
shellcheck_cmd=("shellcheck")
|
|
199
|
+
else
|
|
200
|
+
unavailable_reason="System shellcheck required (VALIDATOR_SHELLCHECK_MODE=system) but not found in PATH"
|
|
201
|
+
fi
|
|
202
|
+
;;
|
|
203
|
+
wrapper)
|
|
204
|
+
if [[ -x "$SCRIPT_DIR/shellcheck_wrapper.sh" ]]; then
|
|
205
|
+
shellcheck_cmd=("$SCRIPT_DIR/shellcheck_wrapper.sh" "--cache")
|
|
206
|
+
else
|
|
207
|
+
unavailable_reason="Shellcheck wrapper required (VALIDATOR_SHELLCHECK_MODE=wrapper) but scripts/shellcheck_wrapper.sh is missing or not executable"
|
|
208
|
+
fi
|
|
209
|
+
;;
|
|
210
|
+
disabled)
|
|
211
|
+
unavailable_reason="ShellCheck disabled by configuration"
|
|
212
|
+
;;
|
|
213
|
+
*)
|
|
214
|
+
print_error "Invalid VALIDATOR_SHELLCHECK_MODE='$shellcheck_mode'. Use one of: auto, system, wrapper, disabled"
|
|
215
|
+
return 2
|
|
216
|
+
;;
|
|
217
|
+
esac
|
|
218
|
+
|
|
219
|
+
if [[ ${#shellcheck_cmd[@]} -eq 0 ]]; then
|
|
220
|
+
if [[ "$REQUIRE_SHELLCHECK" == "1" ]]; then
|
|
221
|
+
print_error "$unavailable_reason; static analysis coverage is required"
|
|
222
|
+
echo " Install options:"
|
|
223
|
+
echo " 1. System-wide: brew install shellcheck (macOS)"
|
|
224
|
+
echo " apt-get install shellcheck (Debian/Ubuntu)"
|
|
225
|
+
echo " dnf install shellcheck (Fedora)"
|
|
226
|
+
echo " 2. Python venv: pip3 install shellcheck-py"
|
|
227
|
+
echo " 3. Wrapper auto-installs when python3 is available"
|
|
228
|
+
return 2
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
print_warning "$unavailable_reason. Static analysis coverage is partial."
|
|
232
|
+
echo " Install options:"
|
|
233
|
+
echo " 1. System-wide: brew install shellcheck (macOS)"
|
|
234
|
+
echo " apt-get install shellcheck (Debian/Ubuntu)"
|
|
235
|
+
echo " dnf install shellcheck (Fedora)"
|
|
236
|
+
echo " 2. Python venv: pip3 install shellcheck-py"
|
|
237
|
+
echo " 3. Wrapper auto-installs when python3 is available"
|
|
238
|
+
return 0
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
local -a shellcheck_args=()
|
|
242
|
+
if [[ -n "$shell_name" ]]; then
|
|
243
|
+
shellcheck_args+=("-s" "$shell_name")
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
local output
|
|
247
|
+
local shellcheck_exit=0
|
|
248
|
+
if output=$("${shellcheck_cmd[@]}" "${shellcheck_args[@]}" -f gcc "$file" 2>&1); then
|
|
249
|
+
print_success "No ShellCheck issues found"
|
|
250
|
+
return 0
|
|
251
|
+
else
|
|
252
|
+
shellcheck_exit=$?
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
if [[ "$shellcheck_exit" -eq 1 ]]; then
|
|
256
|
+
local error_lines warning_lines info_lines style_lines total_lines
|
|
257
|
+
|
|
258
|
+
error_lines=$(echo "$output" | grep -c ": error:" || true)
|
|
259
|
+
warning_lines=$(echo "$output" | grep -c ": warning:" || true)
|
|
260
|
+
info_lines=$(echo "$output" | grep -c ": note:" || true)
|
|
261
|
+
style_lines=$(echo "$output" | grep -c ": style:" || true)
|
|
262
|
+
total_lines=$((error_lines + warning_lines + info_lines + style_lines))
|
|
263
|
+
|
|
264
|
+
ERROR_COUNT=$((ERROR_COUNT + error_lines))
|
|
265
|
+
WARNING_COUNT=$((WARNING_COUNT + warning_lines))
|
|
266
|
+
INFO_COUNT=$((INFO_COUNT + info_lines))
|
|
267
|
+
STYLE_COUNT=$((STYLE_COUNT + style_lines))
|
|
268
|
+
|
|
269
|
+
# Keep validator non-green even if output format is unexpected.
|
|
270
|
+
if [[ "$total_lines" -eq 0 ]]; then
|
|
271
|
+
print_warning "ShellCheck reported issues, but no severity markers were parsed"
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
echo "$output"
|
|
275
|
+
echo ""
|
|
276
|
+
print_info "See https://www.shellcheck.net/wiki/ for detailed explanations"
|
|
277
|
+
return 1
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
print_error "ShellCheck execution failed (exit $shellcheck_exit)"
|
|
281
|
+
if [[ -n "$output" ]]; then
|
|
282
|
+
echo "$output"
|
|
283
|
+
fi
|
|
284
|
+
return 2
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
# Grep for a pattern in a file, excluding comment-only lines.
|
|
288
|
+
# A comment-only line is one whose first non-whitespace character is '#'.
|
|
289
|
+
# Returns 0 with output when non-comment matches exist; 1 with no output otherwise.
|
|
290
|
+
# Usage: grep_code [-E] 'pattern' file
|
|
291
|
+
grep_code() {
|
|
292
|
+
local ext_flag=""
|
|
293
|
+
if [[ "${1:-}" == "-E" ]]; then
|
|
294
|
+
ext_flag="-E"
|
|
295
|
+
shift
|
|
296
|
+
fi
|
|
297
|
+
local output
|
|
298
|
+
output=$(grep -n ${ext_flag:+$ext_flag} "$1" "$2" 2>/dev/null | awk '
|
|
299
|
+
{
|
|
300
|
+
colon = index($0, ":")
|
|
301
|
+
content = substr($0, colon + 1)
|
|
302
|
+
if (content !~ /^[[:space:]]*#/) print $0
|
|
303
|
+
}')
|
|
304
|
+
if [[ -n "$output" ]]; then
|
|
305
|
+
echo "$output"
|
|
306
|
+
return 0
|
|
307
|
+
else
|
|
308
|
+
return 1
|
|
309
|
+
fi
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
# Run custom security and optimization checks
|
|
313
|
+
run_custom_checks() {
|
|
314
|
+
local file="$1"
|
|
315
|
+
local shell_type="$2"
|
|
316
|
+
|
|
317
|
+
print_section "CUSTOM CHECKS"
|
|
318
|
+
|
|
319
|
+
local found_issues=0
|
|
320
|
+
|
|
321
|
+
# Security: Check for eval with variables
|
|
322
|
+
if grep_code -E 'eval.*\$' "$file" >/dev/null 2>&1; then
|
|
323
|
+
print_warning "Potential command injection: eval with variable found"
|
|
324
|
+
grep_code -E 'eval.*\$' "$file" | sed 's/^/ Line /'
|
|
325
|
+
found_issues=1
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
# Security: Check for unsafe use of rm -rf
|
|
329
|
+
if grep_code -E '(rm -(rf|fr).*\$|rm -(rf|fr) /)' "$file" >/dev/null 2>&1; then
|
|
330
|
+
print_warning "Dangerous rm -rf usage detected"
|
|
331
|
+
grep_code -E '(rm -(rf|fr).*\$|rm -(rf|fr) /)' "$file" | sed 's/^/ Line /'
|
|
332
|
+
found_issues=1
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
# Performance: Useless use of cat (UUOC)
|
|
336
|
+
# Match: cat <filename> | grep/awk/sed
|
|
337
|
+
# Use [^|]+ to match one or more non-pipe characters (the filename)
|
|
338
|
+
if grep_code -E 'cat[[:space:]]+[^|]+[[:space:]]*\|[[:space:]]*(grep|awk|sed)' "$file" >/dev/null 2>&1; then
|
|
339
|
+
print_info "Useless use of cat detected. Consider using redirection instead:"
|
|
340
|
+
grep_code -E 'cat[[:space:]]+[^|]+[[:space:]]*\|[[:space:]]*(grep|awk|sed)' "$file" | sed 's/^/ Line /'
|
|
341
|
+
found_issues=1
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
# Portability: Bash-specific features in sh scripts
|
|
345
|
+
if [[ "$shell_type" == "sh" ]]; then
|
|
346
|
+
# Check for [[ ]] (bash-specific)
|
|
347
|
+
if grep_code "\[\[" "$file" >/dev/null 2>&1; then
|
|
348
|
+
print_error "Bash-specific [[ ]] found in sh script. Use [ ] instead"
|
|
349
|
+
grep_code "\[\[" "$file" | sed 's/^/ Line /'
|
|
350
|
+
found_issues=1
|
|
351
|
+
fi
|
|
352
|
+
|
|
353
|
+
# Check for arrays (bash-specific)
|
|
354
|
+
if grep_code -E '(declare -a|array=\()' "$file" >/dev/null 2>&1; then
|
|
355
|
+
print_error "Bash-specific arrays found in sh script"
|
|
356
|
+
grep_code -E '(declare -a|array=\()' "$file" | sed 's/^/ Line /'
|
|
357
|
+
found_issues=1
|
|
358
|
+
fi
|
|
359
|
+
|
|
360
|
+
# Check for function keyword (bash-specific)
|
|
361
|
+
if grep_code -E '^[[:space:]]*function[[:space:]]' "$file" >/dev/null 2>&1; then
|
|
362
|
+
print_warning "Bash-specific 'function' keyword in sh script"
|
|
363
|
+
grep_code -E '^[[:space:]]*function[[:space:]]' "$file" | sed 's/^/ Line /'
|
|
364
|
+
found_issues=1
|
|
365
|
+
fi
|
|
366
|
+
|
|
367
|
+
# Check for source command (bash-specific, use . instead)
|
|
368
|
+
if grep_code -E '^[[:space:]]*source[[:space:]]' "$file" >/dev/null 2>&1; then
|
|
369
|
+
print_warning "Bash-specific 'source' command in sh script. Use '.' instead"
|
|
370
|
+
grep_code -E '^[[:space:]]*source[[:space:]]' "$file" | sed 's/^/ Line /'
|
|
371
|
+
found_issues=1
|
|
372
|
+
fi
|
|
373
|
+
fi
|
|
374
|
+
|
|
375
|
+
# Check for missing error handling
|
|
376
|
+
local has_error_handling=0
|
|
377
|
+
|
|
378
|
+
if grep_code -E '^[[:space:]]*set[[:space:]]+-[[:alpha:]]*e[[:alpha:]]*([[:space:]]|$)' "$file" >/dev/null 2>&1; then
|
|
379
|
+
has_error_handling=1
|
|
380
|
+
fi
|
|
381
|
+
if grep_code -E '^[[:space:]]*set[[:space:]]+-o[[:space:]]+errexit([[:space:]]|$)' "$file" >/dev/null 2>&1; then
|
|
382
|
+
has_error_handling=1
|
|
383
|
+
fi
|
|
384
|
+
if grep_code -E '^[[:space:]]*trap[[:space:]].*ERR([[:space:]]|$)' "$file" >/dev/null 2>&1; then
|
|
385
|
+
has_error_handling=1
|
|
386
|
+
fi
|
|
387
|
+
|
|
388
|
+
if [[ "$has_error_handling" -eq 0 ]]; then
|
|
389
|
+
print_info "Consider adding error handling (set -e/-o errexit or trap ERR)"
|
|
390
|
+
found_issues=1
|
|
391
|
+
fi
|
|
392
|
+
|
|
393
|
+
# Check for missing quotes around variables in dangerous contexts
|
|
394
|
+
if grep_code -E '\$[A-Za-z_][A-Za-z0-9_]*[[:space:]]*>' "$file" >/dev/null 2>&1; then
|
|
395
|
+
print_warning "Unquoted variables in redirection context"
|
|
396
|
+
grep_code -E '\$[A-Za-z_][A-Za-z0-9_]*[[:space:]]*>' "$file" | sed 's/^/ Line /'
|
|
397
|
+
found_issues=1
|
|
398
|
+
fi
|
|
399
|
+
|
|
400
|
+
if [[ $found_issues -eq 0 ]]; then
|
|
401
|
+
print_success "No custom issues found"
|
|
402
|
+
fi
|
|
403
|
+
|
|
404
|
+
return 0
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
# Print summary
|
|
408
|
+
print_summary() {
|
|
409
|
+
local file="$1"
|
|
410
|
+
local shell_type="$2"
|
|
411
|
+
|
|
412
|
+
echo ""
|
|
413
|
+
print_header "VALIDATION SUMMARY"
|
|
414
|
+
echo "File: $file"
|
|
415
|
+
echo "Detected Shell: $shell_type"
|
|
416
|
+
echo ""
|
|
417
|
+
|
|
418
|
+
if [[ $ERROR_COUNT -eq 0 && $WARNING_COUNT -eq 0 ]]; then
|
|
419
|
+
print_success "All checks passed! ✓"
|
|
420
|
+
else
|
|
421
|
+
echo -e "${RED}Errors:${NC} $ERROR_COUNT"
|
|
422
|
+
echo -e "${YELLOW}Warnings:${NC} $WARNING_COUNT"
|
|
423
|
+
echo -e "${BLUE}Info:${NC} $INFO_COUNT"
|
|
424
|
+
echo -e "Style: $STYLE_COUNT"
|
|
425
|
+
fi
|
|
426
|
+
|
|
427
|
+
echo ""
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
# Main validation function
|
|
431
|
+
validate_script() {
|
|
432
|
+
local file="$1"
|
|
433
|
+
|
|
434
|
+
# Check if file exists
|
|
435
|
+
if [[ ! -f "$file" ]]; then
|
|
436
|
+
echo "Error: File '$file' not found"
|
|
437
|
+
exit 1
|
|
438
|
+
fi
|
|
439
|
+
|
|
440
|
+
# Check if file is readable
|
|
441
|
+
if [[ ! -r "$file" ]]; then
|
|
442
|
+
echo "Error: File '$file' is not readable"
|
|
443
|
+
exit 1
|
|
444
|
+
fi
|
|
445
|
+
|
|
446
|
+
# Check if file is a text file (not binary)
|
|
447
|
+
# Using file command to detect binary files, or grep -I as fallback
|
|
448
|
+
if command -v file &>/dev/null; then
|
|
449
|
+
local file_type
|
|
450
|
+
file_type=$(file -b --mime-encoding "$file")
|
|
451
|
+
if [[ "$file_type" == "binary" ]]; then
|
|
452
|
+
echo "Error: File '$file' appears to be a binary file, not a text script"
|
|
453
|
+
exit 1
|
|
454
|
+
fi
|
|
455
|
+
elif ! grep -qI . "$file" 2>/dev/null; then
|
|
456
|
+
# Fallback: grep -I skips binary files, if it fails the file is likely binary
|
|
457
|
+
echo "Error: File '$file' appears to be a binary file, not a text script"
|
|
458
|
+
exit 1
|
|
459
|
+
fi
|
|
460
|
+
|
|
461
|
+
local shell_type_raw shell_type shell_status
|
|
462
|
+
shell_type_raw=$(detect_shell "$file")
|
|
463
|
+
|
|
464
|
+
# Parse shell type and status
|
|
465
|
+
shell_type="${shell_type_raw%%:*}"
|
|
466
|
+
shell_status="${shell_type_raw#*:}"
|
|
467
|
+
|
|
468
|
+
print_header "BASH/SHELL SCRIPT VALIDATOR"
|
|
469
|
+
echo "File: $file"
|
|
470
|
+
echo "Detected Shell: $shell_type"
|
|
471
|
+
|
|
472
|
+
# Print warnings for special cases
|
|
473
|
+
if [[ "$shell_status" == "no-shebang" ]]; then
|
|
474
|
+
print_warning "No shebang found. Defaulting to bash validation."
|
|
475
|
+
elif [[ "$shell_status" =~ ^unknown-shebang ]]; then
|
|
476
|
+
local unknown_shebang="${shell_status#unknown-shebang:}"
|
|
477
|
+
print_warning "Unknown shebang: $unknown_shebang. Defaulting to bash validation."
|
|
478
|
+
fi
|
|
479
|
+
|
|
480
|
+
echo ""
|
|
481
|
+
|
|
482
|
+
# Run validations
|
|
483
|
+
validate_syntax "$file" "$shell_type" || true
|
|
484
|
+
run_shellcheck "$file" "$shell_type" || true
|
|
485
|
+
run_custom_checks "$file" "$shell_type" || true
|
|
486
|
+
|
|
487
|
+
# Print summary
|
|
488
|
+
print_summary "$file" "$shell_type"
|
|
489
|
+
|
|
490
|
+
# Exit with appropriate code
|
|
491
|
+
if [[ $ERROR_COUNT -gt 0 ]]; then
|
|
492
|
+
exit 2
|
|
493
|
+
elif [[ $WARNING_COUNT -gt 0 ]]; then
|
|
494
|
+
exit 1
|
|
495
|
+
else
|
|
496
|
+
exit 0
|
|
497
|
+
fi
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
# Parse arguments
|
|
501
|
+
if [[ $# -eq 0 ]]; then
|
|
502
|
+
usage
|
|
503
|
+
fi
|
|
504
|
+
|
|
505
|
+
case "${1:-}" in
|
|
506
|
+
-h|--help)
|
|
507
|
+
usage
|
|
508
|
+
;;
|
|
509
|
+
*)
|
|
510
|
+
validate_script "$1"
|
|
511
|
+
;;
|
|
512
|
+
esac
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-pipeline
|
|
3
|
+
description: >-
|
|
4
|
+
Set up a complete CI/CD pipeline for a project. Detects the stack, then
|
|
5
|
+
generates and validates GitHub Actions workflows, a Dockerfile, and a
|
|
6
|
+
Makefile as one coherent pipeline. Use when asked to "set up CI", "add
|
|
7
|
+
pipeline", "create GitHub Actions", "ci/cd setup", "automate builds",
|
|
8
|
+
"containerize", or "add a Makefile".
|
|
9
|
+
category: engineering-method
|
|
10
|
+
risk: safe
|
|
11
|
+
source: community
|
|
12
|
+
date_added: "2026-09-25"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# CI/CD Pipeline Setup
|
|
16
|
+
|
|
17
|
+
**Announce at start:** "I'm using the ci-pipeline skill to set up the pipeline."
|
|
18
|
+
|
|
19
|
+
**Core principle:** Generate, then validate, then fix. A pipeline that was
|
|
20
|
+
never validated is not a pipeline — it is a guess that will fail on someone
|
|
21
|
+
else's machine.
|
|
22
|
+
|
|
23
|
+
This skill is the orchestrator. It does not write workflows, Dockerfiles, or
|
|
24
|
+
Makefiles itself — it detects the stack, calls the right generator, routes the
|
|
25
|
+
output through the matching validator, and reports the result.
|
|
26
|
+
|
|
27
|
+
## When to Use
|
|
28
|
+
|
|
29
|
+
"set up CI", "add pipeline", "create GitHub Actions", "ci/cd setup", "automate
|
|
30
|
+
builds", "add Docker", "containerize", "add Makefile".
|
|
31
|
+
|
|
32
|
+
Not for: debugging an existing pipeline that already runs (read it first), or
|
|
33
|
+
infrastructure provisioning — see *What NOT to do*.
|
|
34
|
+
|
|
35
|
+
## Stack Detection
|
|
36
|
+
|
|
37
|
+
Before generating anything, detect. Guessing here produces a pipeline that
|
|
38
|
+
builds the wrong thing correctly.
|
|
39
|
+
|
|
40
|
+
1. **Language/runtime** — `package.json`, `pyproject.toml`, `go.mod`,
|
|
41
|
+
`Cargo.toml`, `pom.xml`, `build.gradle`, `Gemfile`
|
|
42
|
+
2. **Existing CI** — `.github/workflows/`, `.gitlab-ci.yml`, `Jenkinsfile`,
|
|
43
|
+
`.circleci/`
|
|
44
|
+
3. **Docker** — `Dockerfile`, `docker-compose.yml`, `compose.yaml`
|
|
45
|
+
4. **Build tool** — `Makefile`, `package.json` scripts, `build.gradle`,
|
|
46
|
+
`Taskfile.yml`
|
|
47
|
+
|
|
48
|
+
Report what you found before generating. If detection is ambiguous — two
|
|
49
|
+
languages, a monorepo with per-package manifests — say so and ask which target
|
|
50
|
+
the pipeline should build, rather than picking one.
|
|
51
|
+
|
|
52
|
+
## Orchestration Flow
|
|
53
|
+
|
|
54
|
+
Run in this order. Stop on a hard failure; do not generate the next artifact on
|
|
55
|
+
top of a broken one.
|
|
56
|
+
|
|
57
|
+
### 1. GitHub Actions
|
|
58
|
+
|
|
59
|
+
Invoke `github-actions-generator` with the detected stack.
|
|
60
|
+
|
|
61
|
+
- **Validator:** `github-actions-validator` — must pass before continuing.
|
|
62
|
+
- **Output:** `.github/workflows/ci.yml`, plus `deploy.yml` if a deployment
|
|
63
|
+
target is detected.
|
|
64
|
+
|
|
65
|
+
### 2. Dockerfile
|
|
66
|
+
|
|
67
|
+
Only if no `Dockerfile` exists, or the user asked for one. Invoke
|
|
68
|
+
`dockerfile-generator`.
|
|
69
|
+
|
|
70
|
+
- **Validator:** `dockerfile-validator` — must pass before continuing.
|
|
71
|
+
- **Output:** `Dockerfile`, `.dockerignore`.
|
|
72
|
+
|
|
73
|
+
### 3. Makefile
|
|
74
|
+
|
|
75
|
+
Only if no `Makefile` exists. Invoke `makefile-generator`.
|
|
76
|
+
|
|
77
|
+
- **Output:** `Makefile` with the targets `build`, `test`, `lint`,
|
|
78
|
+
`docker-build`, `clean`.
|
|
79
|
+
|
|
80
|
+
### 4. Validation summary
|
|
81
|
+
|
|
82
|
+
Run every applicable validator once more against the final, combined output and
|
|
83
|
+
report the results. A generator that passed in isolation can still produce a set
|
|
84
|
+
of files that disagree with each other — the combined pass is what proves the
|
|
85
|
+
pipeline works, not the per-step passes.
|
|
86
|
+
|
|
87
|
+
## The Validation Loop
|
|
88
|
+
|
|
89
|
+
This is the part that matters, and it is not optional:
|
|
90
|
+
|
|
91
|
+
1. Run the generator.
|
|
92
|
+
2. Run the validator against what it produced.
|
|
93
|
+
3. On failure, feed the validator's errors back to the generator.
|
|
94
|
+
4. Repeat until clean. **Minimum one full pass** — generating and declaring
|
|
95
|
+
success without ever running a validator has produced a broken pipeline more
|
|
96
|
+
often than not.
|
|
97
|
+
|
|
98
|
+
If the validator cannot run in the current environment (no `actionlint`, no
|
|
99
|
+
Docker daemon), say that explicitly and report which checks were skipped. An
|
|
100
|
+
unavailable validator is not a passing validator.
|
|
101
|
+
|
|
102
|
+
## Output Checklist
|
|
103
|
+
|
|
104
|
+
Verify before calling this done:
|
|
105
|
+
|
|
106
|
+
- [ ] `.github/workflows/ci.yml` exists and passes `github-actions-validator`
|
|
107
|
+
- [ ] `Dockerfile` exists (if applicable) and passes `dockerfile-validator`
|
|
108
|
+
- [ ] `Makefile` exists and `make test` runs locally
|
|
109
|
+
- [ ] Every validator ran at least once, and its result is reported — passed,
|
|
110
|
+
failed, or skipped-with-reason
|
|
111
|
+
- [ ] No secrets, tokens, or environment values hardcoded in any generated file
|
|
112
|
+
- [ ] Generated files are ready to commit but **not** committed
|
|
113
|
+
|
|
114
|
+
## What NOT to do
|
|
115
|
+
|
|
116
|
+
- **Do not commit.** Leave the files staged for review. Committing and pushing
|
|
117
|
+
a pipeline is a separate, explicit request.
|
|
118
|
+
- **Do not overwrite existing `.github/workflows/` or an existing `Dockerfile`
|
|
119
|
+
without showing the diff first.** Existing pipelines usually encode a reason
|
|
120
|
+
— a private registry, a matrix, a self-hosted runner — that a regenerated file
|
|
121
|
+
silently drops.
|
|
122
|
+
- **Do not generate Terraform, Helm, or Kubernetes manifests** unless
|
|
123
|
+
explicitly asked. Deployment infrastructure is a different job with different
|
|
124
|
+
blast radius; `helm-generator` and the k8s skills exist for it.
|
|
125
|
+
- **Do not invent a validator result.** Report what ran and what did not.
|
|
126
|
+
- **Do not use `github-actions-templates`** for new work — it is superseded by
|
|
127
|
+
`github-actions-generator`.
|
|
128
|
+
|
|
129
|
+
## Related
|
|
130
|
+
|
|
131
|
+
- `bash-script-generator` / `bash-script-validator` — helper scripts the
|
|
132
|
+
pipeline calls, when the workflow needs more than a Makefile target
|
|
133
|
+
- `github-actions-templates` — superseded, kept for its existing patterns
|
|
134
|
+
- `vercel-deployment` — deployment specifics for Vercel targets
|
|
135
|
+
- `deploy-incus` — Forgejo-to-Incus push deployment
|