claude-devkit-cli 1.0.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/bin/devkit.js +3 -0
- package/package.json +36 -0
- package/src/cli.js +72 -0
- package/src/commands/check.js +33 -0
- package/src/commands/diff.js +90 -0
- package/src/commands/init.js +232 -0
- package/src/commands/list.js +50 -0
- package/src/commands/remove.js +74 -0
- package/src/commands/upgrade.js +108 -0
- package/src/lib/detector.js +93 -0
- package/src/lib/hasher.js +21 -0
- package/src/lib/installer.js +175 -0
- package/src/lib/logger.js +16 -0
- package/src/lib/manifest.js +79 -0
- package/templates/.claude/CLAUDE.md +74 -0
- package/templates/.claude/commands/challenge.md +210 -0
- package/templates/.claude/commands/commit.md +97 -0
- package/templates/.claude/commands/fix.md +95 -0
- package/templates/.claude/commands/plan.md +141 -0
- package/templates/.claude/commands/review.md +109 -0
- package/templates/.claude/commands/test.md +99 -0
- package/templates/.claude/hooks/comment-guard.js +114 -0
- package/templates/.claude/hooks/file-guard.js +120 -0
- package/templates/.claude/hooks/glob-guard.js +96 -0
- package/templates/.claude/hooks/path-guard.sh +73 -0
- package/templates/.claude/hooks/self-review.sh +29 -0
- package/templates/.claude/hooks/sensitive-guard.sh +214 -0
- package/templates/.claude/settings.json +68 -0
- package/templates/docs/WORKFLOW.md +231 -0
- package/templates/docs/specs/.gitkeep +0 -0
- package/templates/docs/test-plans/.gitkeep +0 -0
- package/templates/scripts/build-test.sh +260 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# build-test.sh — Universal test runner with auto-detection
|
|
3
|
+
# Detects project language/framework and runs the appropriate test command.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash scripts/build-test.sh # run all tests
|
|
7
|
+
# bash scripts/build-test.sh --filter "Auth" # filter by pattern
|
|
8
|
+
# bash scripts/build-test.sh --list # show detected project type
|
|
9
|
+
# bash scripts/build-test.sh --ci # machine-readable output
|
|
10
|
+
#
|
|
11
|
+
# Supports: Swift (SPM/Xcode), Node (Vitest/Jest), Python (pytest/unittest),
|
|
12
|
+
# Rust (cargo), Go, Java (Gradle/Maven), C# (.NET), Ruby (RSpec/Minitest)
|
|
13
|
+
#
|
|
14
|
+
# Exit codes:
|
|
15
|
+
# 0 — all tests passed
|
|
16
|
+
# 1 — tests failed
|
|
17
|
+
# 2 — no project detected or missing tooling
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
# ─── Argument parsing ───────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
FILTER=""
|
|
24
|
+
CI_MODE=false
|
|
25
|
+
LIST_ONLY=false
|
|
26
|
+
|
|
27
|
+
while [[ $# -gt 0 ]]; do
|
|
28
|
+
case "$1" in
|
|
29
|
+
--filter) FILTER="${2:-}"; shift 2 ;;
|
|
30
|
+
--ci) CI_MODE=true; shift ;;
|
|
31
|
+
--list) LIST_ONLY=true; shift ;;
|
|
32
|
+
--help|-h) sed -n '2,16p' "$0"; exit 0 ;;
|
|
33
|
+
*) FILTER="$1"; shift ;; # bare arg = filter
|
|
34
|
+
esac
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
# ─── Output helpers ─────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
info() { echo "[INFO] $*"; }
|
|
40
|
+
pass() { echo "[PASS] $*"; }
|
|
41
|
+
fail() { echo "[FAIL] $*"; }
|
|
42
|
+
skip() { echo "[SKIP] $*"; }
|
|
43
|
+
|
|
44
|
+
# ─── Language detectors ─────────────────────────────────────────────
|
|
45
|
+
# Each function returns 0 if detected, 1 otherwise.
|
|
46
|
+
# Sets LANG_NAME and TEST_CMD as side effects.
|
|
47
|
+
|
|
48
|
+
detect_swift_spm() {
|
|
49
|
+
[[ -f "Package.swift" ]] || return 1
|
|
50
|
+
LANG_NAME="Swift (SPM)"
|
|
51
|
+
if [[ -n "$FILTER" ]]; then
|
|
52
|
+
TEST_CMD="swift test --filter '$FILTER'"
|
|
53
|
+
else
|
|
54
|
+
TEST_CMD="swift test"
|
|
55
|
+
fi
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
detect_swift_xcode() {
|
|
59
|
+
local project=""
|
|
60
|
+
local flag=""
|
|
61
|
+
|
|
62
|
+
if compgen -G "*.xcworkspace" > /dev/null 2>&1; then
|
|
63
|
+
project=$(compgen -G "*.xcworkspace" | head -1)
|
|
64
|
+
flag="-workspace"
|
|
65
|
+
elif compgen -G "*.xcodeproj" > /dev/null 2>&1; then
|
|
66
|
+
project=$(compgen -G "*.xcodeproj" | head -1)
|
|
67
|
+
flag="-project"
|
|
68
|
+
else
|
|
69
|
+
return 1
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
local scheme
|
|
73
|
+
scheme=$(xcodebuild "$flag" "$project" -list 2>/dev/null \
|
|
74
|
+
| sed -n '/Schemes:/,/^$/p' | tail -n +2 | head -1 | xargs) || return 1
|
|
75
|
+
|
|
76
|
+
[[ -z "$scheme" ]] && return 1
|
|
77
|
+
|
|
78
|
+
LANG_NAME="Swift (Xcode: $scheme)"
|
|
79
|
+
TEST_CMD="xcodebuild test $flag '$project' -scheme '$scheme' -destination 'platform=macOS,arch=arm64'"
|
|
80
|
+
if [[ -n "$FILTER" ]]; then
|
|
81
|
+
TEST_CMD="$TEST_CMD -only-testing:'$FILTER'"
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
detect_node() {
|
|
86
|
+
[[ -f "package.json" ]] || return 1
|
|
87
|
+
|
|
88
|
+
# Detect package manager
|
|
89
|
+
local runner="npx"
|
|
90
|
+
[[ -f "pnpm-lock.yaml" ]] && runner="pnpm exec"
|
|
91
|
+
[[ -f "bun.lockb" || -f "bun.lock" ]] && runner="bunx"
|
|
92
|
+
|
|
93
|
+
if [[ -f "vitest.config.ts" || -f "vitest.config.js" || -f "vitest.config.mts" ]] \
|
|
94
|
+
|| grep -q '"vitest"' package.json 2>/dev/null; then
|
|
95
|
+
LANG_NAME="Node (Vitest)"
|
|
96
|
+
if [[ -n "$FILTER" ]]; then
|
|
97
|
+
TEST_CMD="$runner vitest run '$FILTER'"
|
|
98
|
+
else
|
|
99
|
+
TEST_CMD="$runner vitest run"
|
|
100
|
+
fi
|
|
101
|
+
elif [[ -f "jest.config.ts" || -f "jest.config.js" || -f "jest.config.mjs" ]] \
|
|
102
|
+
|| grep -q '"jest"' package.json 2>/dev/null; then
|
|
103
|
+
LANG_NAME="Node (Jest)"
|
|
104
|
+
if [[ -n "$FILTER" ]]; then
|
|
105
|
+
TEST_CMD="$runner jest '$FILTER' --no-cache"
|
|
106
|
+
else
|
|
107
|
+
TEST_CMD="$runner jest --no-cache"
|
|
108
|
+
fi
|
|
109
|
+
elif grep -q '"test"' package.json 2>/dev/null; then
|
|
110
|
+
LANG_NAME="Node (npm test)"
|
|
111
|
+
TEST_CMD="npm test"
|
|
112
|
+
else
|
|
113
|
+
return 1
|
|
114
|
+
fi
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
detect_python() {
|
|
118
|
+
[[ -f "pyproject.toml" || -f "setup.py" || -f "pytest.ini" || -f "setup.cfg" ]] \
|
|
119
|
+
|| { [[ -d "tests" && -f "requirements.txt" ]]; } \
|
|
120
|
+
|| return 1
|
|
121
|
+
|
|
122
|
+
if command -v pytest &>/dev/null || python3 -m pytest --version &>/dev/null 2>&1; then
|
|
123
|
+
LANG_NAME="Python (pytest)"
|
|
124
|
+
if [[ -n "$FILTER" ]]; then
|
|
125
|
+
TEST_CMD="python3 -m pytest -xvs -k '$FILTER'"
|
|
126
|
+
else
|
|
127
|
+
TEST_CMD="python3 -m pytest -x"
|
|
128
|
+
fi
|
|
129
|
+
else
|
|
130
|
+
LANG_NAME="Python (unittest)"
|
|
131
|
+
TEST_CMD="python3 -m unittest discover -s tests"
|
|
132
|
+
fi
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
detect_rust() {
|
|
136
|
+
[[ -f "Cargo.toml" ]] || return 1
|
|
137
|
+
LANG_NAME="Rust (cargo)"
|
|
138
|
+
if [[ -n "$FILTER" ]]; then
|
|
139
|
+
TEST_CMD="cargo test '$FILTER'"
|
|
140
|
+
else
|
|
141
|
+
TEST_CMD="cargo test"
|
|
142
|
+
fi
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
detect_go() {
|
|
146
|
+
[[ -f "go.mod" ]] || return 1
|
|
147
|
+
LANG_NAME="Go"
|
|
148
|
+
if [[ -n "$FILTER" ]]; then
|
|
149
|
+
TEST_CMD="go test -race -run '$FILTER' ./..."
|
|
150
|
+
else
|
|
151
|
+
TEST_CMD="go test -race ./..."
|
|
152
|
+
fi
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
detect_gradle() {
|
|
156
|
+
[[ -f "build.gradle" || -f "build.gradle.kts" ]] || return 1
|
|
157
|
+
LANG_NAME="Java/Kotlin (Gradle)"
|
|
158
|
+
if [[ -n "$FILTER" ]]; then
|
|
159
|
+
TEST_CMD="./gradlew test --tests '$FILTER'"
|
|
160
|
+
else
|
|
161
|
+
TEST_CMD="./gradlew test"
|
|
162
|
+
fi
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
detect_maven() {
|
|
166
|
+
[[ -f "pom.xml" ]] || return 1
|
|
167
|
+
LANG_NAME="Java (Maven)"
|
|
168
|
+
if [[ -n "$FILTER" ]]; then
|
|
169
|
+
TEST_CMD="mvn test -Dtest='$FILTER'"
|
|
170
|
+
else
|
|
171
|
+
TEST_CMD="mvn test"
|
|
172
|
+
fi
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
detect_dotnet() {
|
|
176
|
+
compgen -G "*.sln" > /dev/null 2>&1 || compgen -G "*.csproj" > /dev/null 2>&1 || return 1
|
|
177
|
+
LANG_NAME="C# (.NET)"
|
|
178
|
+
if [[ -n "$FILTER" ]]; then
|
|
179
|
+
TEST_CMD="dotnet test --filter '$FILTER'"
|
|
180
|
+
else
|
|
181
|
+
TEST_CMD="dotnet test"
|
|
182
|
+
fi
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
detect_ruby() {
|
|
186
|
+
[[ -f "Gemfile" ]] || return 1
|
|
187
|
+
if grep -q 'rspec' Gemfile 2>/dev/null; then
|
|
188
|
+
LANG_NAME="Ruby (RSpec)"
|
|
189
|
+
if [[ -n "$FILTER" ]]; then
|
|
190
|
+
TEST_CMD="bundle exec rspec --tag '$FILTER'"
|
|
191
|
+
else
|
|
192
|
+
TEST_CMD="bundle exec rspec"
|
|
193
|
+
fi
|
|
194
|
+
else
|
|
195
|
+
LANG_NAME="Ruby (Minitest)"
|
|
196
|
+
TEST_CMD="bundle exec rake test"
|
|
197
|
+
fi
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# ─── Detection order (first match wins) ────────────────────────────
|
|
201
|
+
|
|
202
|
+
DETECTORS=(
|
|
203
|
+
detect_swift_spm
|
|
204
|
+
detect_swift_xcode
|
|
205
|
+
detect_node
|
|
206
|
+
detect_python
|
|
207
|
+
detect_rust
|
|
208
|
+
detect_go
|
|
209
|
+
detect_gradle
|
|
210
|
+
detect_maven
|
|
211
|
+
detect_dotnet
|
|
212
|
+
detect_ruby
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
LANG_NAME=""
|
|
216
|
+
TEST_CMD=""
|
|
217
|
+
|
|
218
|
+
for detector in "${DETECTORS[@]}"; do
|
|
219
|
+
if $detector; then
|
|
220
|
+
break
|
|
221
|
+
fi
|
|
222
|
+
done
|
|
223
|
+
|
|
224
|
+
# ─── No project detected ───────────────────────────────────────────
|
|
225
|
+
|
|
226
|
+
if [[ -z "$LANG_NAME" ]]; then
|
|
227
|
+
fail "No supported project detected in $(pwd)"
|
|
228
|
+
info "Supported: Swift (SPM/Xcode), Node (Vitest/Jest), Python (pytest),"
|
|
229
|
+
info " Rust (cargo), Go, Java (Gradle/Maven), C# (.NET), Ruby"
|
|
230
|
+
exit 2
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
# ─── List mode ──────────────────────────────────────────────────────
|
|
234
|
+
|
|
235
|
+
if $LIST_ONLY; then
|
|
236
|
+
if $CI_MODE; then
|
|
237
|
+
echo "$LANG_NAME"
|
|
238
|
+
else
|
|
239
|
+
info "Detected: $LANG_NAME"
|
|
240
|
+
info "Command: $TEST_CMD"
|
|
241
|
+
fi
|
|
242
|
+
exit 0
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
# ─── Run tests ──────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
info "Detected: $LANG_NAME"
|
|
248
|
+
info "Running: $TEST_CMD"
|
|
249
|
+
echo ""
|
|
250
|
+
|
|
251
|
+
if eval "$TEST_CMD"; then
|
|
252
|
+
echo ""
|
|
253
|
+
pass "All tests passed ($LANG_NAME)"
|
|
254
|
+
exit 0
|
|
255
|
+
else
|
|
256
|
+
STATUS=$?
|
|
257
|
+
echo ""
|
|
258
|
+
fail "Tests failed ($LANG_NAME, exit code: $STATUS)"
|
|
259
|
+
exit 1
|
|
260
|
+
fi
|