Merge pull request #17 from tuanductran/copilot/add-windows-installat… #49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Validate Rules | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| - name: Setup PNPM | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.28.2 | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Run linting | |
| run: pnpm lint | |
| - name: Validate referential integrity | |
| run: | | |
| #!/bin/bash | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' # No Color | |
| echo "🔍 Checking referential integrity..." | |
| echo "" | |
| # Track if any errors were found | |
| ERRORS_FOUND=0 | |
| # Find all SKILL.md files | |
| SKILL_FILES=$(find skills -name "SKILL.md") | |
| for skill_file in $SKILL_FILES; do | |
| skill_dir=$(dirname "$skill_file") | |
| skill_name=$(basename "$skill_dir") | |
| echo "Checking skill: $skill_name" | |
| # Find all rule files in the rules directory | |
| if [ -d "$skill_dir/rules" ]; then | |
| rule_files=$(find "$skill_dir/rules" -name "*.md" -type f) | |
| for rule_file in $rule_files; do | |
| rule_basename=$(basename "$rule_file") | |
| rule_name="${rule_basename%.md}" | |
| # Check if the rule is registered in SKILL.md | |
| if ! grep -q "(rules/$rule_basename)" "$skill_file"; then | |
| echo -e "${RED}❌ ERROR: Rule '$rule_name' exists but is not registered in $skill_file${NC}" | |
| ERRORS_FOUND=1 | |
| else | |
| echo -e "${GREEN}✓${NC} $rule_name" | |
| fi | |
| done | |
| fi | |
| echo "" | |
| done | |
| # Check for rules referenced in SKILL.md that don't exist | |
| for skill_file in $SKILL_FILES; do | |
| skill_dir=$(dirname "$skill_file") | |
| skill_name=$(basename "$skill_dir") | |
| # Extract rule references from markdown links like [rule-name](rules/rule-name.md) | |
| # Note: Uses grep -P (Perl regex) which is available on GitHub Actions Ubuntu runners | |
| referenced_rules=$(grep -oP '\[.*?\]\(rules/\K[^)]+(?=\))' "$skill_file" || true) | |
| if [ -n "$referenced_rules" ]; then | |
| echo "Validating referenced rules in $skill_name..." | |
| while IFS= read -r rule_ref; do | |
| rule_path="$skill_dir/rules/$rule_ref" | |
| if [ ! -f "$rule_path" ]; then | |
| echo -e "${RED}❌ ERROR: Rule referenced in $skill_file does not exist: $rule_path${NC}" | |
| ERRORS_FOUND=1 | |
| else | |
| echo -e "${GREEN}✓${NC} $(basename $rule_ref)" | |
| fi | |
| done <<< "$referenced_rules" | |
| echo "" | |
| fi | |
| done | |
| # Final result | |
| if [ $ERRORS_FOUND -eq 0 ]; then | |
| echo -e "${GREEN}✅ All referential integrity checks passed!${NC}" | |
| exit 0 | |
| else | |
| echo -e "${RED}❌ Referential integrity checks failed. Please fix the errors above.${NC}" | |
| exit 1 | |
| fi | |
| - name: Validate YAML frontmatter | |
| run: | | |
| #!/bin/bash | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| NC='\033[0m' | |
| echo "🔍 Validating YAML frontmatter in rule files..." | |
| echo "" | |
| ERRORS_FOUND=0 | |
| # Find all rule files | |
| rule_files=$(find skills/*/rules -name "*.md" -type f) | |
| for rule_file in $rule_files; do | |
| # Check if file has YAML frontmatter | |
| if ! head -n 1 "$rule_file" | grep -q "^---$"; then | |
| echo -e "${RED}❌ ERROR: Missing YAML frontmatter in $rule_file${NC}" | |
| ERRORS_FOUND=1 | |
| continue | |
| fi | |
| # Extract frontmatter | |
| frontmatter=$(awk '/^---$/{f=!f;next}f' "$rule_file" | head -n 20) | |
| # Check required fields | |
| required_fields=("title" "impact" "impactDescription" "type" "tags") | |
| for field in "${required_fields[@]}"; do | |
| if ! echo "$frontmatter" | grep -q "^$field:"; then | |
| echo -e "${RED}❌ ERROR: Missing required field '$field' in $rule_file${NC}" | |
| ERRORS_FOUND=1 | |
| fi | |
| done | |
| # Validate impact value | |
| impact_value=$(echo "$frontmatter" | grep "^impact:" | cut -d':' -f2 | tr -d ' ') | |
| if [[ ! "$impact_value" =~ ^(HIGH|MEDIUM|LOW)$ ]]; then | |
| echo -e "${RED}❌ ERROR: Invalid impact value '$impact_value' in $rule_file (must be HIGH, MEDIUM, or LOW)${NC}" | |
| ERRORS_FOUND=1 | |
| fi | |
| # Validate type value | |
| type_value=$(echo "$frontmatter" | grep "^type:" | cut -d':' -f2 | tr -d ' ') | |
| if [[ ! "$type_value" =~ ^(capability|efficiency)$ ]]; then | |
| echo -e "${RED}❌ ERROR: Invalid type value '$type_value' in $rule_file (must be capability or efficiency)${NC}" | |
| ERRORS_FOUND=1 | |
| fi | |
| # Check for Impact Line after H1 (skip all blank lines) | |
| line_after_h1=$(awk '/^# /{found=1; next} found && NF {print; exit}' "$rule_file") | |
| if ! echo "$line_after_h1" | grep -q '^\*\*Impact:'; then | |
| echo -e "${RED}❌ ERROR: Missing Impact Line after H1 title in $rule_file${NC}" | |
| ERRORS_FOUND=1 | |
| fi | |
| done | |
| if [ $ERRORS_FOUND -eq 0 ]; then | |
| echo -e "${GREEN}✅ All YAML frontmatter validations passed!${NC}" | |
| exit 0 | |
| else | |
| echo -e "${RED}❌ YAML frontmatter validation failed. Please fix the errors above.${NC}" | |
| exit 1 | |
| fi |