-
Notifications
You must be signed in to change notification settings - Fork 23
184 lines (159 loc) · 6.12 KB
/
tessl-review.yml
File metadata and controls
184 lines (159 loc) · 6.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
name: Tessl Skill Review
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
tessl-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: tesslio/setup-tessl@v2
- name: Detect changed skills
id: detect
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
# Build list of all skill directories (parents of SKILL.md)
ALL_SKILL_DIRS=$(find skills -name SKILL.md -exec dirname {} \; | sort)
# For each changed file, find which skill directory it belongs to
DIRS=""
for changed_file in $CHANGED_FILES; do
for skill_dir in $ALL_SKILL_DIRS; do
case "$changed_file" in
"$skill_dir"/*)
# Check not already added
case " $DIRS " in
*" $skill_dir "*) ;;
*) DIRS="$DIRS $skill_dir" ;;
esac
break
;;
esac
done
done
DIRS=$(echo "$DIRS" | xargs) # trim whitespace
# Check for unmatched changes under skills/
UNMATCHED=false
for changed_file in $CHANGED_FILES; do
case "$changed_file" in
skills/*)
MATCHED=false
for skill_dir in $ALL_SKILL_DIRS; do
case "$changed_file" in
"$skill_dir"/*) MATCHED=true; break ;;
esac
done
if [ "$MATCHED" = "false" ]; then
UNMATCHED=true
break
fi
;;
esac
done
if [ "$UNMATCHED" = "true" ]; then
echo "Unmatched changes under skills/ detected — reviewing all skills"
DIRS=$(find skills -name SKILL.md -exec dirname {} \; 2>/dev/null | tr "\n" " " | xargs)
fi
if [ -z "$DIRS" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "No skill files changed."
else
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "dirs=$DIRS" >> "$GITHUB_OUTPUT"
echo "Changed skills: $DIRS"
fi
else
# Push to main: review all skills
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "dirs=" >> "$GITHUB_OUTPUT"
echo "Push to main — will review all skills."
fi
- name: Post skip summary
if: steps.detect.outputs.skip == 'true'
run: |
echo "## Skill Review" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "No skills changed — review skipped." >> "$GITHUB_STEP_SUMMARY"
- name: Review skills
if: steps.detect.outputs.skip != 'true'
run: |
THRESHOLD=50
PASS=0
FAIL=0
SUMMARY_FILE=$(mktemp)
ERRORS_FILE=$(mktemp)
SKILL_DIRS_INPUT="${{ steps.detect.outputs.dirs }}"
SKILL_LIST_FILE=$(mktemp)
trap 'rm -f "$SKILL_LIST_FILE" "$SUMMARY_FILE" "$ERRORS_FILE"' EXIT
if [ -z "$SKILL_DIRS_INPUT" ]; then
# Push to main or no filter: review all skills
find skills -name SKILL.md -exec dirname {} \; > "$SKILL_LIST_FILE"
else
# PR mode: use detected skill dirs
printf '%s\n' $SKILL_DIRS_INPUT > "$SKILL_LIST_FILE"
fi
while IFS= read -r dir; do
[ -z "$dir" ] && continue
SKILL_NAME=$(basename "$dir")
echo "::group::Reviewing $SKILL_NAME"
EXIT_CODE=0
OUTPUT=$(tessl skill review "$dir" 2>&1) || EXIT_CODE=$?
echo "$OUTPUT"
echo "::endgroup::"
if [ "$EXIT_CODE" -ne 0 ]; then
echo "::warning::tessl skill review failed for $SKILL_NAME (exit code $EXIT_CODE)"
FAIL=$((FAIL + 1))
echo "| $SKILL_NAME | error | ❌ |" >> "$SUMMARY_FILE"
continue
fi
SCORE=$(echo "$OUTPUT" | grep -oE '[0-9]+%' | tail -1 | tr -d '%')
if [ -z "$SCORE" ]; then
echo "::warning::Could not parse score for $SKILL_NAME"
SCORE=0
fi
if [ "$SCORE" -lt "$THRESHOLD" ]; then
FAIL=$((FAIL + 1))
echo " ❌ $SKILL_NAME: ${SCORE}% (below ${THRESHOLD}%)" >> "$ERRORS_FILE"
echo "| $SKILL_NAME | ${SCORE}% | ❌ |" >> "$SUMMARY_FILE"
else
PASS=$((PASS + 1))
echo "| $SKILL_NAME | ${SCORE}% | ✅ |" >> "$SUMMARY_FILE"
fi
done < "$SKILL_LIST_FILE"
TOTAL=$((PASS + FAIL))
# Fail if no skills were reviewed (push to main only)
if [ "$TOTAL" -eq 0 ] && [ "${{ github.event_name }}" != "pull_request" ]; then
echo "::error::No skills were reviewed — expected at least one"
exit 1
fi
# Write GitHub Step Summary
{
echo "## Skill Review"
echo ""
echo "| Skill | Score | Status |"
echo "|-------|-------|--------|"
cat "$SUMMARY_FILE"
echo "| **Total** | **$PASS/$TOTAL passed** | $([ "$FAIL" -eq 0 ] && echo '✅' || echo '❌') |"
} >> "$GITHUB_STEP_SUMMARY"
# Stdout summary for logs
echo ""
echo "============================="
echo " Skill Review Summary"
echo "============================="
echo " Total: $TOTAL"
echo " Passed: $PASS"
echo " Failed: $FAIL"
if [ -s "$ERRORS_FILE" ]; then
echo ""
echo " Failed skills:"
cat "$ERRORS_FILE"
fi
echo "============================="
if [ "$FAIL" -gt 0 ]; then
echo "::error::$FAIL skill(s) scored below ${THRESHOLD}%"
exit 1
fi