@hybridlabor-api/aos 4.7.2 → 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.
Files changed (166) hide show
  1. package/.agents/agents.md +1 -1
  2. package/.agents/nodes.json +1 -1
  3. package/.agents/vendor-manifest.json +23 -1
  4. package/.claude/agents/godmode-media-eventtech.md +1 -1
  5. package/.claude/hooks/conventional-commits.mjs +125 -0
  6. package/.claude/hooks/env-file-protection.mjs +105 -0
  7. package/.claude/hooks/go-gate.mjs +101 -81
  8. package/.claude/settings.json +13 -0
  9. package/.opencode/agents/godmode-media-eventtech.md +1 -1
  10. package/.opencode/plugins/bdb-aos.js +31 -4
  11. package/README.de.md +1 -1
  12. package/README.md +1 -1
  13. package/README.pt.md +1 -1
  14. package/THIRD_PARTY_NOTICES.md +88 -0
  15. package/docs/skills_table.md +1 -1
  16. package/installer.js +309 -101
  17. package/package.json +6 -2
  18. package/packages/aos-cli/README.md +80 -0
  19. package/packages/aos-cli/bin/aos-cli.mjs +134 -0
  20. package/packages/aos-cli/core-skills.json +12 -0
  21. package/packages/aos-cli/extensions/aos.ts +321 -0
  22. package/packages/aos-cli/package-lock.json +1923 -0
  23. package/packages/aos-cli/package.json +29 -0
  24. package/packages/aos-cli/scripts/check-theme.mjs +63 -0
  25. package/packages/aos-cli/themes/aos.json +97 -0
  26. package/scripts/build-plugin-manifest.mjs +131 -0
  27. package/scripts/validate-skills.mjs +81 -6
  28. package/skills/basic/ao-orchestrator/SKILL.md +116 -0
  29. package/skills/global_config/agenttrail/SKILL.md +6 -1
  30. package/skills/global_config/ask-tim/SKILL.md +4 -4
  31. package/skills/global_config/bash-script-generator/SKILL.md +201 -0
  32. package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
  33. package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
  34. package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
  35. package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
  36. package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
  37. package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
  38. package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
  39. package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
  40. package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
  41. package/skills/global_config/bash-script-validator/SKILL.md +249 -0
  42. package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
  43. package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
  44. package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
  45. package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
  46. package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
  47. package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
  48. package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
  49. package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
  50. package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
  51. package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
  52. package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
  53. package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
  54. package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
  55. package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
  56. package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
  57. package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
  58. package/skills/global_config/ci-pipeline/SKILL.md +135 -0
  59. package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
  60. package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
  61. package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
  62. package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
  63. package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
  64. package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
  65. package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
  66. package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
  67. package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
  68. package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
  69. package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
  70. package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
  71. package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
  72. package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
  73. package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
  74. package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
  75. package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
  76. package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
  77. package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
  78. package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
  79. package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
  80. package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
  81. package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
  82. package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
  83. package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
  84. package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
  85. package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
  86. package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
  87. package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
  88. package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
  89. package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
  90. package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
  91. package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
  92. package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
  93. package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
  94. package/skills/global_config/github-actions-generator/SKILL.md +353 -0
  95. package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
  96. package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
  97. package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
  98. package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
  99. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
  100. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
  101. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
  102. package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
  103. package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
  104. package/skills/global_config/github-actions-generator/examples/README.md +147 -0
  105. package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
  106. package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
  107. package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
  108. package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
  109. package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
  110. package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
  111. package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
  112. package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
  113. package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
  114. package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
  115. package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
  116. package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
  117. package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
  118. package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
  119. package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
  120. package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
  121. package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
  122. package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
  123. package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
  124. package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
  125. package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
  126. package/skills/global_config/github-actions-templates/SKILL.md +7 -0
  127. package/skills/global_config/github-actions-validator/SKILL.md +576 -0
  128. package/skills/global_config/github-actions-validator/examples/README.md +88 -0
  129. package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
  130. package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
  131. package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
  132. package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
  133. package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
  134. package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
  135. package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
  136. package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
  137. package/skills/global_config/github-actions-validator/references/runners.md +317 -0
  138. package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
  139. package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
  140. package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
  141. package/skills/global_config/makefile-generator/SKILL.md +614 -0
  142. package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
  143. package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
  144. package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
  145. package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
  146. package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
  147. package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
  148. package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
  149. package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
  150. package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
  151. package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
  152. package/skills/global_config/makefile-validator/SKILL.md +244 -0
  153. package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
  154. package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
  155. package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
  156. package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
  157. package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
  158. package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
  159. package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
  160. package/skills/global_config/{MCP_Manage → mcp-manage}/SKILL.md +3 -3
  161. package/skills/global_config/requesting-code-review/SKILL.md +98 -0
  162. package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
  163. package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
  164. package/skills/global_config/verification-before-completion/SKILL.md +123 -0
  165. package/skills/global_config/writing-plans/SKILL.md +126 -46
  166. package/skills/global_config/writing-plans-legacy/SKILL.md +139 -0
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Deterministic CI validation entrypoint for bash-script-generator.
4
+ # Runs:
5
+ # 1) bash -n syntax checks
6
+ # 2) shellcheck -x checks (optional or required)
7
+ # 3) regression tests (scripts/test_generator.sh)
8
+ #
9
+
10
+ set -euo pipefail
11
+
12
+ readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
+ readonly SKILL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
14
+ readonly TEST_RUNNER="${SCRIPT_DIR}/test_generator.sh"
15
+
16
+ usage() {
17
+ cat <<EOF
18
+ Usage: ${0##*/} [OPTIONS]
19
+
20
+ Run deterministic checks for bash-script-generator.
21
+
22
+ Options:
23
+ --require-shellcheck Fail if shellcheck is unavailable.
24
+ --skip-shellcheck Skip shellcheck stage.
25
+ --skip-regression-tests Skip scripts/test_generator.sh.
26
+ -h, --help Show this help message.
27
+
28
+ Environment:
29
+ SHELLCHECK_BIN Override shellcheck binary/path (default: shellcheck)
30
+ CI=true|1 Defaults to --require-shellcheck unless explicitly overridden
31
+ EOF
32
+ }
33
+
34
+ is_true() {
35
+ local value="$1"
36
+ [[ "$value" == "true" || "$value" == "1" ]]
37
+ }
38
+
39
+ command_is_available() {
40
+ local command_name="$1"
41
+ if [[ "$command_name" == */* ]]; then
42
+ [[ -x "$command_name" ]]
43
+ else
44
+ command -v "$command_name" >/dev/null 2>&1
45
+ fi
46
+ }
47
+
48
+ collect_shell_files() {
49
+ SHELL_FILES=()
50
+ while IFS= read -r file; do
51
+ SHELL_FILES+=("$file")
52
+ done < <(
53
+ {
54
+ find "${SCRIPT_DIR}" -maxdepth 1 -type f -name "*.sh"
55
+ find "${SKILL_DIR}/examples" -maxdepth 1 -type f -name "*.sh"
56
+ find "${SKILL_DIR}/assets/templates" -maxdepth 1 -type f -name "*.sh"
57
+ } | LC_ALL=C sort
58
+ )
59
+
60
+ if [[ "${#SHELL_FILES[@]}" -eq 0 ]]; then
61
+ echo "Error: No shell files found to validate." >&2
62
+ return 1
63
+ fi
64
+ }
65
+
66
+ run_syntax_checks() {
67
+ echo "[1/3] bash -n syntax checks"
68
+ local shell_file
69
+ for shell_file in "${SHELL_FILES[@]}"; do
70
+ bash -n "${shell_file}"
71
+ done
72
+ echo " PASS: bash -n succeeded for ${#SHELL_FILES[@]} file(s)"
73
+ }
74
+
75
+ run_shellcheck_checks() {
76
+ local shellcheck_bin="$1"
77
+ local require_shellcheck="$2"
78
+ local skip_shellcheck="$3"
79
+
80
+ if [[ "$skip_shellcheck" -eq 1 ]]; then
81
+ echo "[2/3] shellcheck -x checks"
82
+ echo " SKIP: shellcheck stage disabled via --skip-shellcheck"
83
+ return 0
84
+ fi
85
+
86
+ echo "[2/3] shellcheck -x checks"
87
+ if ! command_is_available "$shellcheck_bin"; then
88
+ if [[ "$require_shellcheck" -eq 1 ]]; then
89
+ echo "Error: shellcheck is required but not available (${shellcheck_bin})." >&2
90
+ return 1
91
+ fi
92
+ echo " SKIP: shellcheck unavailable (${shellcheck_bin}); continuing without shellcheck"
93
+ return 0
94
+ fi
95
+
96
+ local shell_file
97
+ for shell_file in "${SHELL_FILES[@]}"; do
98
+ "$shellcheck_bin" -x "${shell_file}"
99
+ done
100
+ echo " PASS: shellcheck succeeded for ${#SHELL_FILES[@]} file(s)"
101
+ }
102
+
103
+ run_regression_tests() {
104
+ local skip_regression_tests="$1"
105
+
106
+ echo "[3/3] regression tests"
107
+ if [[ "$skip_regression_tests" -eq 1 ]]; then
108
+ echo " SKIP: regression suite disabled via --skip-regression-tests"
109
+ return 0
110
+ fi
111
+
112
+ bash "${TEST_RUNNER}"
113
+ }
114
+
115
+ main() {
116
+ local require_shellcheck=0
117
+ local skip_shellcheck=0
118
+ local skip_regression_tests=0
119
+ local shellcheck_mode_overridden=0
120
+ local shellcheck_bin="${SHELLCHECK_BIN:-shellcheck}"
121
+
122
+ while [[ $# -gt 0 ]]; do
123
+ case "$1" in
124
+ --require-shellcheck)
125
+ require_shellcheck=1
126
+ skip_shellcheck=0
127
+ shellcheck_mode_overridden=1
128
+ ;;
129
+ --skip-shellcheck)
130
+ skip_shellcheck=1
131
+ require_shellcheck=0
132
+ shellcheck_mode_overridden=1
133
+ ;;
134
+ --skip-regression-tests)
135
+ skip_regression_tests=1
136
+ ;;
137
+ -h|--help)
138
+ usage
139
+ exit 0
140
+ ;;
141
+ *)
142
+ echo "Error: Unknown option: $1" >&2
143
+ usage
144
+ exit 1
145
+ ;;
146
+ esac
147
+ shift
148
+ done
149
+
150
+ if [[ "$shellcheck_mode_overridden" -eq 0 ]] && is_true "${CI:-}"; then
151
+ require_shellcheck=1
152
+ fi
153
+
154
+ if [[ "$skip_shellcheck" -eq 1 && "$require_shellcheck" -eq 1 ]]; then
155
+ echo "Error: --skip-shellcheck and --require-shellcheck cannot be used together." >&2
156
+ exit 1
157
+ fi
158
+
159
+ export LC_ALL=C
160
+ export LANG=C
161
+ export TZ=UTC
162
+
163
+ collect_shell_files
164
+ run_syntax_checks
165
+ run_shellcheck_checks "$shellcheck_bin" "$require_shellcheck" "$skip_shellcheck"
166
+ run_regression_tests "$skip_regression_tests"
167
+
168
+ echo ""
169
+ echo "All configured CI checks passed."
170
+ }
171
+
172
+ main "$@"
@@ -0,0 +1,413 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Regression test suite for bash-script-generator
4
+ #
5
+ # Tests:
6
+ # 1. generate_script_template.sh — argument handling and file generation
7
+ # 2. log-analyzer.sh — functional behaviour
8
+ # 3. run_ci_checks.sh — deterministic validation wiring
9
+ #
10
+ # Exit 0 when all assertions pass; non-zero on any failure.
11
+ #
12
+
13
+ set -euo pipefail
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ readonly SCRIPT_DIR
17
+ GENERATOR="$SCRIPT_DIR/generate_script_template.sh"
18
+ CI_RUNNER="$SCRIPT_DIR/run_ci_checks.sh"
19
+ LOG_ANALYZER="$SCRIPT_DIR/../examples/log-analyzer.sh"
20
+
21
+ PASS=0
22
+ FAIL=0
23
+
24
+ # ─── helpers ────────────────────────────────────────────────────────────────
25
+
26
+ pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
27
+ fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
28
+
29
+ # Run a command silently and return its exit code without aborting this script.
30
+ run_exit_code() {
31
+ local exit_code=0
32
+ "$@" >/dev/null 2>&1 || exit_code=$?
33
+ echo "$exit_code"
34
+ }
35
+
36
+ assert_exit_code() {
37
+ local label="$1"
38
+ local expected="$2"
39
+ shift 2
40
+
41
+ local actual
42
+ actual=$(run_exit_code "$@")
43
+
44
+ if [[ "$actual" -eq "$expected" ]]; then
45
+ pass "$label (exit $actual)"
46
+ else
47
+ fail "$label — expected exit $expected, got $actual"
48
+ echo " --- command output ---"
49
+ "$@" 2>&1 | sed 's/^/ /' || true
50
+ echo " --- end output ---"
51
+ fi
52
+ }
53
+
54
+ # Assert that a pattern IS present in the combined stdout+stderr of a command.
55
+ assert_output_contains() {
56
+ local label="$1"
57
+ local pattern="$2"
58
+ shift 2
59
+
60
+ local output
61
+ output=$("$@" 2>&1 || true)
62
+
63
+ if echo "$output" | grep -qE "$pattern"; then
64
+ pass "$label"
65
+ else
66
+ fail "$label — pattern not found: $pattern"
67
+ echo " --- command output ---"
68
+ echo "$output" | sed 's/^/ /'
69
+ echo " --- end output ---"
70
+ fi
71
+ }
72
+
73
+ # Assert that a pattern is NOT present in the combined stdout+stderr of a command.
74
+ assert_output_not_contains() {
75
+ local label="$1"
76
+ local pattern="$2"
77
+ shift 2
78
+
79
+ local output
80
+ output=$("$@" 2>&1 || true)
81
+
82
+ if echo "$output" | grep -qE "$pattern"; then
83
+ fail "$label — unexpected pattern found: $pattern"
84
+ echo " --- command output ---"
85
+ echo "$output" | sed 's/^/ /'
86
+ echo " --- end output ---"
87
+ else
88
+ pass "$label"
89
+ fi
90
+ }
91
+
92
+ # ─── setup ──────────────────────────────────────────────────────────────────
93
+
94
+ TEMP_DIR=$(mktemp -d)
95
+ trap 'rm -rf "${TEMP_DIR}"' EXIT
96
+
97
+ # Fixture log file used by log-analyzer tests
98
+ LOG_FILE="${TEMP_DIR}/app.log"
99
+ cat > "$LOG_FILE" << 'EOF'
100
+ 2024-01-15 10:00:01 INFO: App started
101
+ 2024-01-15 10:00:02 DEBUG: Loading config
102
+ 2024-01-15 10:00:03 ERROR: Connection refused to database
103
+ 2024-01-15 10:00:04 ERROR: Connection refused to database
104
+ 2024-01-15 10:00:05 WARN: Retry attempt
105
+ 2024-01-15 10:00:06 ERROR: Timeout on upstream request
106
+ 2024-01-15 10:00:07 INFO: Request complete
107
+ 2024-01-15 10:00:08 FATAL: Critical failure
108
+ EOF
109
+
110
+ echo "Running bash-script-generator tests..."
111
+
112
+ # ─── generate_script_template.sh: argument handling ─────────────────────────
113
+
114
+ echo ""
115
+ echo "[generate_script_template.sh — argument handling]"
116
+
117
+ assert_exit_code \
118
+ "no args exits non-zero" \
119
+ 1 \
120
+ bash "$GENERATOR"
121
+
122
+ assert_exit_code \
123
+ "--help exits 0" \
124
+ 0 \
125
+ bash "$GENERATOR" --help
126
+
127
+ assert_exit_code \
128
+ "-h exits 0" \
129
+ 0 \
130
+ bash "$GENERATOR" -h
131
+
132
+ assert_exit_code \
133
+ "unknown template exits non-zero" \
134
+ 1 \
135
+ bash "$GENERATOR" nonexistent-template
136
+
137
+ assert_exit_code \
138
+ "too many args exits non-zero" \
139
+ 1 \
140
+ bash "$GENERATOR" standard out.sh extra-arg
141
+
142
+ assert_exit_code \
143
+ "traversal template_type payload is rejected" \
144
+ 1 \
145
+ bash "$GENERATOR" ../templates/standard
146
+
147
+ assert_output_contains \
148
+ "traversal payload shows invalid template_type error" \
149
+ "Invalid TEMPLATE_TYPE" \
150
+ bash "$GENERATOR" ../templates/standard
151
+
152
+ assert_exit_code \
153
+ "slash and dot traversal payload is rejected" \
154
+ 1 \
155
+ bash "$GENERATOR" standard/../../evil
156
+
157
+ assert_output_contains \
158
+ "slash and dot traversal payload shows invalid template_type error" \
159
+ "Invalid TEMPLATE_TYPE" \
160
+ bash "$GENERATOR" standard/../../evil
161
+
162
+ assert_output_contains \
163
+ "no-args error mentions TEMPLATE_TYPE" \
164
+ "TEMPLATE_TYPE" \
165
+ bash "$GENERATOR"
166
+
167
+ assert_output_contains \
168
+ "unknown template error lists available templates" \
169
+ "Available templates" \
170
+ bash "$GENERATOR" nonexistent-template
171
+
172
+ # ─── generate_script_template.sh: file generation ───────────────────────────
173
+
174
+ echo ""
175
+ echo "[generate_script_template.sh — file generation]"
176
+
177
+ OUTPUT="${TEMP_DIR}/generated.sh"
178
+ assert_exit_code \
179
+ "standard template with explicit output exits 0" \
180
+ 0 \
181
+ bash "$GENERATOR" standard "$OUTPUT"
182
+
183
+ if [[ -f "$OUTPUT" ]]; then
184
+ pass "output file was created"
185
+ else
186
+ fail "output file was not created"
187
+ fi
188
+
189
+ if [[ -x "$OUTPUT" ]]; then
190
+ pass "output file is executable (chmod u+x applied)"
191
+ else
192
+ fail "output file is not executable"
193
+ fi
194
+
195
+ assert_output_contains \
196
+ "generated file has bash shebang" \
197
+ "#!/usr/bin/env bash" \
198
+ cat "$OUTPUT"
199
+
200
+ assert_output_contains \
201
+ "generated file has strict mode" \
202
+ "set -euo pipefail" \
203
+ cat "$OUTPUT"
204
+
205
+ assert_output_contains \
206
+ "generated file has numeric LOG_LEVEL" \
207
+ "LOG_LEVEL=1" \
208
+ cat "$OUTPUT"
209
+
210
+ # Syntax check: the generated script must be parseable by bash
211
+ if bash -n "$OUTPUT" 2>/dev/null; then
212
+ pass "generated file passes bash -n syntax check"
213
+ else
214
+ fail "generated file has syntax errors"
215
+ fi
216
+
217
+ # Overwrite: generating into an existing path must succeed silently
218
+ assert_exit_code \
219
+ "overwriting existing output file exits 0" \
220
+ 0 \
221
+ bash "$GENERATOR" standard "$OUTPUT"
222
+
223
+ # Nested directories must be created automatically
224
+ NESTED="${TEMP_DIR}/a/b/c/nested.sh"
225
+ assert_exit_code \
226
+ "output into non-existent nested directory exits 0" \
227
+ 0 \
228
+ bash "$GENERATOR" standard "$NESTED"
229
+
230
+ if [[ -f "$NESTED" ]]; then
231
+ pass "nested output file was created"
232
+ else
233
+ fail "nested output file was not created"
234
+ fi
235
+
236
+ # Default output path: when no OUTPUT_FILE is given the file lands in CWD
237
+ ORIG_DIR="$(pwd)"
238
+ WORK_DIR="${TEMP_DIR}/workspace"
239
+ mkdir -p "$WORK_DIR"
240
+ cd "$WORK_DIR"
241
+ assert_exit_code \
242
+ "default output path (no output arg) exits 0" \
243
+ 0 \
244
+ bash "$GENERATOR" standard
245
+ if [[ -f "${WORK_DIR}/standard-script.sh" ]]; then
246
+ pass "default output file ./standard-script.sh was created"
247
+ else
248
+ fail "default output file ./standard-script.sh was not created"
249
+ fi
250
+
251
+ TRAVERSAL_TARGET="${TEMP_DIR}/templates/standard-script.sh"
252
+ rm -rf "${TEMP_DIR}/templates"
253
+ assert_exit_code \
254
+ "traversal payload with default output exits non-zero" \
255
+ 1 \
256
+ bash "$GENERATOR" ../templates/standard
257
+ if [[ ! -e "$TRAVERSAL_TARGET" ]]; then
258
+ pass "traversal payload did not create file outside current directory"
259
+ else
260
+ fail "traversal payload created unexpected file: $TRAVERSAL_TARGET"
261
+ fi
262
+ cd "$ORIG_DIR"
263
+
264
+ # ─── log-analyzer.sh: argument handling ─────────────────────────────────────
265
+
266
+ echo ""
267
+ echo "[log-analyzer.sh — argument handling]"
268
+
269
+ assert_exit_code \
270
+ "no file arg exits non-zero" \
271
+ 1 \
272
+ bash "$LOG_ANALYZER"
273
+
274
+ assert_exit_code \
275
+ "-h exits 0" \
276
+ 0 \
277
+ bash "$LOG_ANALYZER" -h
278
+
279
+ assert_exit_code \
280
+ "nonexistent file exits non-zero" \
281
+ 1 \
282
+ bash "$LOG_ANALYZER" /nonexistent/file.log
283
+
284
+ assert_exit_code \
285
+ "invalid report type exits non-zero" \
286
+ 1 \
287
+ bash "$LOG_ANALYZER" -t badtype "$LOG_FILE"
288
+
289
+ # ─── log-analyzer.sh: functional behaviour ──────────────────────────────────
290
+
291
+ echo ""
292
+ echo "[log-analyzer.sh — functional behaviour]"
293
+
294
+ assert_exit_code \
295
+ "summary report exits 0" \
296
+ 0 \
297
+ bash "$LOG_ANALYZER" "$LOG_FILE"
298
+
299
+ assert_output_contains \
300
+ "summary report shows total lines" \
301
+ "Total lines" \
302
+ bash "$LOG_ANALYZER" "$LOG_FILE"
303
+
304
+ assert_output_contains \
305
+ "summary shows ERROR count" \
306
+ "ERROR" \
307
+ bash "$LOG_ANALYZER" "$LOG_FILE"
308
+
309
+ assert_output_contains \
310
+ "summary shows FATAL count" \
311
+ "FATAL" \
312
+ bash "$LOG_ANALYZER" "$LOG_FILE"
313
+
314
+ assert_exit_code \
315
+ "errors report exits 0" \
316
+ 0 \
317
+ bash "$LOG_ANALYZER" -t errors "$LOG_FILE"
318
+
319
+ assert_output_contains \
320
+ "errors report shows total errors" \
321
+ "Total errors" \
322
+ bash "$LOG_ANALYZER" -t errors "$LOG_FILE"
323
+
324
+ # Multi-word error messages must not be truncated
325
+ assert_output_contains \
326
+ "errors report preserves multi-word message (Connection refused to database)" \
327
+ "Connection refused to database" \
328
+ bash "$LOG_ANALYZER" -t errors "$LOG_FILE"
329
+
330
+ assert_output_contains \
331
+ "errors report preserves multi-word message (Timeout on upstream request)" \
332
+ "Timeout on upstream request" \
333
+ bash "$LOG_ANALYZER" -t errors "$LOG_FILE"
334
+
335
+ # Repeated errors should show correct count (2 for "Connection refused to database")
336
+ assert_output_contains \
337
+ "errors report shows count 2 for repeated error" \
338
+ "Connection refused to database.*2" \
339
+ bash "$LOG_ANALYZER" -t errors "$LOG_FILE"
340
+
341
+ # Output to file
342
+ REPORT="${TEMP_DIR}/report.txt"
343
+ assert_exit_code \
344
+ "output-to-file exits 0" \
345
+ 0 \
346
+ bash "$LOG_ANALYZER" -o "$REPORT" "$LOG_FILE"
347
+
348
+ if [[ -f "$REPORT" ]]; then
349
+ pass "report file was created by -o flag"
350
+ else
351
+ fail "report file was not created by -o flag"
352
+ fi
353
+
354
+ assert_output_contains \
355
+ "-o flag prints confirmation message to stdout" \
356
+ "Report saved to" \
357
+ bash "$LOG_ANALYZER" -o "${TEMP_DIR}/report2.txt" "$LOG_FILE"
358
+
359
+ assert_output_not_contains \
360
+ "report file content excludes confirmation message" \
361
+ "Report saved to" \
362
+ cat "$REPORT"
363
+
364
+ # ─── run_ci_checks.sh: determinism and shellcheck gating ───────────────────
365
+
366
+ echo ""
367
+ echo "[run_ci_checks.sh — deterministic validation]"
368
+
369
+ SHELLCHECK_STUB="${TEMP_DIR}/shellcheck-stub.sh"
370
+ cat > "$SHELLCHECK_STUB" <<'EOF'
371
+ #!/usr/bin/env bash
372
+ exit 0
373
+ EOF
374
+ chmod +x "$SHELLCHECK_STUB"
375
+
376
+ assert_exit_code \
377
+ "ci runner --help exits 0" \
378
+ 0 \
379
+ bash "$CI_RUNNER" --help
380
+
381
+ assert_exit_code \
382
+ "ci runner succeeds when shellcheck is required and stubbed" \
383
+ 0 \
384
+ env SHELLCHECK_BIN="$SHELLCHECK_STUB" \
385
+ bash "$CI_RUNNER" --require-shellcheck --skip-regression-tests
386
+
387
+ assert_exit_code \
388
+ "ci runner fails when required shellcheck is unavailable" \
389
+ 1 \
390
+ env SHELLCHECK_BIN="${TEMP_DIR}/missing-shellcheck" \
391
+ bash "$CI_RUNNER" --require-shellcheck --skip-regression-tests
392
+
393
+ assert_output_contains \
394
+ "required-shellcheck failure message is explicit" \
395
+ "shellcheck is required but not available" \
396
+ env SHELLCHECK_BIN="${TEMP_DIR}/missing-shellcheck" \
397
+ bash "$CI_RUNNER" --require-shellcheck --skip-regression-tests
398
+
399
+ assert_exit_code \
400
+ "CI=true defaults to requiring shellcheck" \
401
+ 1 \
402
+ env CI=true SHELLCHECK_BIN="${TEMP_DIR}/missing-shellcheck" \
403
+ bash "$CI_RUNNER" --skip-regression-tests
404
+
405
+ # ─── summary ────────────────────────────────────────────────────────────────
406
+
407
+ echo ""
408
+ echo "Results: $PASS passed, $FAIL failed"
409
+ echo ""
410
+
411
+ if [[ $FAIL -gt 0 ]]; then
412
+ exit 1
413
+ fi