chore: update KB index [skip ci]
This commit is contained in:
43
.github/workflows/kb-index-update.yml
vendored
Normal file
43
.github/workflows/kb-index-update.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Update KB Index
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'kb/**/*.md'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
update:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate index
|
||||
run: |
|
||||
chmod +x kb/scripts/generate-index.sh
|
||||
./kb/scripts/generate-index.sh
|
||||
|
||||
- name: Check for changes
|
||||
id: check
|
||||
run: |
|
||||
if git diff --quiet kb/_index.md; then
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit changes
|
||||
if: steps.check.outputs.changed == 'true'
|
||||
run: |
|
||||
git config user.name "Gitea Actions"
|
||||
git config user.email "actions@gitea.io"
|
||||
git add kb/_index.md
|
||||
git commit -m "chore: update KB index [skip ci]" || exit 0
|
||||
git push
|
||||
|
||||
165
.github/workflows/kb-lint.yml
vendored
Normal file
165
.github/workflows/kb-lint.yml
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
name: KB Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'kb/**/*.md'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'kb/**/*.md'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Validate KB Files
|
||||
run: |
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo "Validating KB files..."
|
||||
|
||||
# Find all KB files that changed
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
# For pull requests, check changed files
|
||||
changed_files=$(git diff --name-only --diff-filter=ACMR origin/${{ github.base_ref }}...HEAD -- 'kb/**/*.md' || true)
|
||||
else
|
||||
# For push, check all KB files
|
||||
changed_files=$(git diff --name-only --diff-filter=ACMR HEAD~1...HEAD -- 'kb/**/*.md' || find kb -type f -name "*.md" 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [ -z "$changed_files" ]; then
|
||||
echo "No KB files changed, skipping validation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
errors=0
|
||||
|
||||
# Process each changed file
|
||||
while IFS= read -r file; do
|
||||
# Skip empty lines
|
||||
[ -z "$file" ] && continue
|
||||
|
||||
# Skip if file doesn't exist (deleted files)
|
||||
[ ! -f "$file" ] && continue
|
||||
|
||||
# Skip special directories and files
|
||||
if [[ "$file" == *"/_guides/"* ]] || \
|
||||
[[ "$file" == *"/_templates/"* ]] || \
|
||||
[[ "$file" == "kb/README.md" ]] || \
|
||||
[[ "$file" == "kb/_index.md" ]] || \
|
||||
[[ "$file" == "kb/CHANGELOG.md" ]]; then
|
||||
echo -e "${YELLOW}⏭️ Skipping: $file (excluded from validation)${NC}"
|
||||
continue
|
||||
fi
|
||||
|
||||
filename=$(basename "$file")
|
||||
relative_path="${file#kb/}"
|
||||
file_errors=0
|
||||
|
||||
echo -e "\n${GREEN}Validating: $file${NC}"
|
||||
|
||||
# Validate filename pattern
|
||||
if ! [[ "$filename" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}--[a-z0-9-]+--(idea|note|spec|decision|howto|retro|meeting)(--p[0-9]+)?\.md$ ]]; then
|
||||
echo -e "${RED}❌ ERROR: Invalid filename pattern${NC}"
|
||||
echo " Expected: YYYY-MM-DD--slug--type.md"
|
||||
echo " Got: $filename"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
|
||||
# Extract date and type from filename
|
||||
filename_date=$(echo "$filename" | sed -E 's/^([0-9]{4}-[0-9]{2}-[0-9]{2})--.*/\1/')
|
||||
filename_type=$(echo "$filename" | sed -E 's/.*--([a-z]+)(--p[0-9]+)?\.md$/\1/')
|
||||
|
||||
# Check frontmatter exists
|
||||
if ! grep -q "^---$" "$file"; then
|
||||
echo -e "${RED}❌ ERROR: Missing frontmatter delimiter${NC}"
|
||||
echo " File must start with '---'"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
|
||||
# Extract frontmatter
|
||||
frontmatter=$(sed -n '/^---$/,/^---$/p' "$file" | sed '1d;$d')
|
||||
|
||||
if [ -z "$frontmatter" ]; then
|
||||
echo -e "${RED}❌ ERROR: Empty frontmatter${NC}"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
|
||||
# Check required fields (14 base fields)
|
||||
REQUIRED_FIELDS=("title" "date" "author" "source" "project" "topics" "tags" "type" "status" "routing_hint" "proposed_path" "routing_confidence" "related" "summary")
|
||||
for field in "${REQUIRED_FIELDS[@]}"; do
|
||||
if ! echo "$frontmatter" | grep -q "^${field}:"; then
|
||||
echo -e "${RED}❌ ERROR: Missing required field: $field${NC}"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Validate date matches
|
||||
frontmatter_date=$(echo "$frontmatter" | grep "^date:" | sed -E 's/^date:[[:space:]]*["'\'']?([^"'\'']+)["'\'']?.*/\1/' | tr -d ' ' | head -1)
|
||||
if [ "$frontmatter_date" != "$filename_date" ]; then
|
||||
echo -e "${RED}❌ ERROR: Date mismatch${NC}"
|
||||
echo " Filename date: $filename_date"
|
||||
echo " Frontmatter date: $frontmatter_date"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
|
||||
# Validate type matches
|
||||
frontmatter_type=$(echo "$frontmatter" | grep "^type:" | sed -E 's/^type:[[:space:]]*["'\'']?([^"'\'']+)["'\'']?.*/\1/' | tr -d ' ' | head -1)
|
||||
if [ "$frontmatter_type" != "$filename_type" ]; then
|
||||
echo -e "${RED}❌ ERROR: Type mismatch${NC}"
|
||||
echo " Filename type: $filename_type"
|
||||
echo " Frontmatter type: $frontmatter_type"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
|
||||
# Validate routing_confidence
|
||||
routing_confidence=$(echo "$frontmatter" | grep "^routing_confidence:" | sed -E 's/^routing_confidence:[[:space:]]*([0-9.]+).*/\1/' | tr -d ' ' | head -1)
|
||||
if ! awk -v conf="$routing_confidence" 'BEGIN {if (conf < 0.0 || conf > 1.0 || conf == "") exit 1}' 2>/dev/null; then
|
||||
echo -e "${RED}❌ ERROR: Invalid routing_confidence value${NC}"
|
||||
echo " Value: $routing_confidence"
|
||||
echo " Must be numeric between 0.00 and 1.00"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
|
||||
# Enforce review queue policy
|
||||
if awk -v conf="$routing_confidence" 'BEGIN {exit !(conf < 0.60)}' 2>/dev/null; then
|
||||
if [[ "$file" != *"/_review_queue/"* ]]; then
|
||||
echo -e "${RED}❌ ERROR: File has routing_confidence < 0.60 but is not in kb/_review_queue/${NC}"
|
||||
echo " routing_confidence: $routing_confidence"
|
||||
echo " File path: $file"
|
||||
file_errors=$((file_errors + 1))
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $file_errors -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ Valid: $file${NC}"
|
||||
fi
|
||||
done <<< "$changed_files"
|
||||
|
||||
if [ $errors -gt 0 ]; then
|
||||
echo -e "\n${RED}Validation failed with $errors error(s)${NC}"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\n${GREEN}All KB files validated successfully${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user