Skip to content

Commit 35a459b

Browse files
Copilotjcmrs
andcommitted
Add Smart Workflows and validation infrastructure
Co-authored-by: jcmrs <[email protected]>
1 parent 1568a73 commit 35a459b

16 files changed

+529
-3
lines changed

.claude-plugin/plugin.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
],
1919
"dependencies": {
2020
"python": ">=3.9"
21-
// Add any required pip packages below, for example:
22-
// "requests": ">=2.0.0",
23-
// "pyyaml": ">=6.0"
2421
},
2522
"tools": [
2623
"Write",
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Lint Markdown and Mermaid
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- '**/*.md'
8+
- '**/*.mermaid'
9+
- '**/*.mmd'
10+
- '.github/workflows/lint-markdown-mermaid.yml'
11+
pull_request:
12+
branches: [ main, develop ]
13+
paths:
14+
- '**/*.md'
15+
- '**/*.mermaid'
16+
- '**/*.mmd'
17+
- '.github/workflows/lint-markdown-mermaid.yml'
18+
19+
jobs:
20+
lint-markdown:
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- name: Set up Node.js
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: '20'
30+
31+
- name: Install markdownlint-cli
32+
run: npm install -g markdownlint-cli
33+
34+
- name: Create markdownlint config
35+
run: |
36+
cat > .markdownlint.json << 'EOF'
37+
{
38+
"default": true,
39+
"MD013": false,
40+
"MD033": false,
41+
"MD041": false
42+
}
43+
EOF
44+
45+
- name: Lint Markdown files
46+
run: |
47+
markdownlint '**/*.md' --ignore node_modules || exit 0
48+
echo "✓ Markdown linting complete (warnings only)"
49+
50+
validate-mermaid:
51+
runs-on: ubuntu-latest
52+
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- name: Set up Python
57+
uses: actions/setup-python@v5
58+
with:
59+
python-version: '3.9'
60+
61+
- name: Validate Mermaid syntax
62+
run: |
63+
python3 << 'EOF'
64+
import os
65+
import re
66+
import sys
67+
68+
def validate_mermaid_file(filepath):
69+
"""Basic Mermaid syntax validation"""
70+
with open(filepath, 'r') as f:
71+
content = f.read().strip()
72+
73+
if not content:
74+
print(f" ✗ File is empty")
75+
return False
76+
77+
# Check for basic Mermaid diagram types
78+
diagram_types = [
79+
'graph', 'flowchart', 'sequenceDiagram', 'classDiagram',
80+
'stateDiagram', 'erDiagram', 'gantt', 'pie', 'journey',
81+
'gitGraph', 'mindmap', 'timeline', 'quadrantChart'
82+
]
83+
84+
has_diagram_type = any(dtype in content for dtype in diagram_types)
85+
86+
if not has_diagram_type:
87+
print(f" ⚠ Warning: No recognized diagram type found")
88+
return True # Warning only
89+
90+
print(f" ✓ Valid basic syntax")
91+
return True
92+
93+
print("Checking Mermaid diagram syntax...")
94+
all_valid = True
95+
96+
# Find all .mermaid and .mmd files
97+
for root, dirs, files in os.walk('.'):
98+
for file in files:
99+
if file.endswith('.mermaid') or file.endswith('.mmd'):
100+
filepath = os.path.join(root, file)
101+
print(f"Validating: {filepath}")
102+
if not validate_mermaid_file(filepath):
103+
all_valid = False
104+
105+
if all_valid:
106+
print("\n✓ All Mermaid diagrams have valid basic syntax")
107+
sys.exit(0)
108+
else:
109+
print("\n✗ Some Mermaid diagrams have syntax issues")
110+
sys.exit(1)
111+
EOF

.github/workflows/python-lint.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Python Lint
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- 'spec-kit-partner/src/**/*.py'
8+
- '.github/workflows/python-lint.yml'
9+
pull_request:
10+
branches: [ main, develop ]
11+
paths:
12+
- 'spec-kit-partner/src/**/*.py'
13+
- '.github/workflows/python-lint.yml'
14+
15+
jobs:
16+
lint:
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: '3.9'
26+
27+
- name: Install linting dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install flake8 pylint
31+
32+
- name: Lint with flake8
33+
run: |
34+
# Stop the build if there are Python syntax errors or undefined names
35+
flake8 spec-kit-partner/src --count --select=E9,F63,F7,F82 --show-source --statistics
36+
# Exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
37+
flake8 spec-kit-partner/src --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
38+
39+
- name: Lint with pylint
40+
run: |
41+
pylint spec-kit-partner/src --exit-zero --max-line-length=127

.github/workflows/python-tests.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Python Tests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- 'spec-kit-partner/src/**/*.py'
8+
- 'tests/**/*.py'
9+
- '.github/workflows/python-tests.yml'
10+
pull_request:
11+
branches: [ main, develop ]
12+
paths:
13+
- 'spec-kit-partner/src/**/*.py'
14+
- 'tests/**/*.py'
15+
- '.github/workflows/python-tests.yml'
16+
17+
jobs:
18+
test:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Set up Python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.9'
28+
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
# Install pytest if using it in the future
33+
pip install pytest
34+
35+
- name: Run basic tests
36+
run: |
37+
python tests/test_basic.py
38+
39+
- name: Run pytest (if test files exist)
40+
run: |
41+
if ls tests/test_*.py 1> /dev/null 2>&1; then
42+
pytest tests/ -v || true
43+
fi
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Validate Referenced Assets
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- '.claude-plugin/**'
8+
- 'assets/**'
9+
- '.github/workflows/validate-assets.yml'
10+
pull_request:
11+
branches: [ main, develop ]
12+
paths:
13+
- '.claude-plugin/**'
14+
- 'assets/**'
15+
- '.github/workflows/validate-assets.yml'
16+
17+
jobs:
18+
validate:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Set up Python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.9'
28+
29+
- name: Validate assets referenced in plugin.json
30+
run: |
31+
python3 << 'EOF'
32+
import json
33+
import os
34+
import sys
35+
36+
errors = []
37+
38+
with open('.claude-plugin/plugin.json', 'r') as f:
39+
plugin_data = json.load(f)
40+
41+
# Check icon
42+
if 'icon' in plugin_data:
43+
icon_path = plugin_data['icon']
44+
if not os.path.exists(icon_path):
45+
errors.append(f"Icon not found: {icon_path}")
46+
else:
47+
print(f"✓ Icon found: {icon_path}")
48+
49+
# Check readme
50+
if 'readme' in plugin_data:
51+
readme_path = plugin_data['readme']
52+
if not os.path.exists(readme_path):
53+
errors.append(f"README not found: {readme_path}")
54+
else:
55+
print(f"✓ README found: {readme_path}")
56+
57+
if errors:
58+
print("\nErrors found:")
59+
for error in errors:
60+
print(f" - {error}")
61+
sys.exit(1)
62+
63+
print("\n✓ All assets referenced in plugin.json exist")
64+
EOF
65+
66+
- name: Validate assets referenced in marketplace.json
67+
run: |
68+
python3 << 'EOF'
69+
import json
70+
import os
71+
import sys
72+
73+
errors = []
74+
75+
with open('.claude-plugin/marketplace.json', 'r') as f:
76+
marketplace_data = json.load(f)
77+
78+
# Check icon
79+
if 'icon' in marketplace_data:
80+
icon_path = marketplace_data['icon']
81+
if not os.path.exists(icon_path):
82+
errors.append(f"Icon not found: {icon_path}")
83+
else:
84+
print(f"✓ Icon found: {icon_path}")
85+
86+
# Check screenshots
87+
if 'screenshots' in marketplace_data:
88+
for screenshot in marketplace_data['screenshots']:
89+
if not os.path.exists(screenshot):
90+
errors.append(f"Screenshot not found: {screenshot}")
91+
else:
92+
print(f"✓ Screenshot found: {screenshot}")
93+
94+
if errors:
95+
print("\nErrors found:")
96+
for error in errors:
97+
print(f" - {error}")
98+
sys.exit(1)
99+
100+
print("\n✓ All assets referenced in marketplace.json exist")
101+
EOF
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Validate Plugin Manifests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- '.claude-plugin/plugin.json'
8+
- '.claude-plugin/marketplace.json'
9+
- '.github/workflows/validate-manifests.yml'
10+
pull_request:
11+
branches: [ main, develop ]
12+
paths:
13+
- '.claude-plugin/plugin.json'
14+
- '.claude-plugin/marketplace.json'
15+
- '.github/workflows/validate-manifests.yml'
16+
17+
jobs:
18+
validate:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Set up Python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.9'
28+
29+
- name: Validate plugin.json exists and is valid JSON
30+
run: |
31+
if [ ! -f .claude-plugin/plugin.json ]; then
32+
echo "Error: .claude-plugin/plugin.json not found"
33+
exit 1
34+
fi
35+
python -m json.tool .claude-plugin/plugin.json > /dev/null
36+
echo "✓ plugin.json is valid JSON"
37+
38+
- name: Validate marketplace.json exists and is valid JSON
39+
run: |
40+
if [ ! -f .claude-plugin/marketplace.json ]; then
41+
echo "Error: .claude-plugin/marketplace.json not found"
42+
exit 1
43+
fi
44+
python -m json.tool .claude-plugin/marketplace.json > /dev/null
45+
echo "✓ marketplace.json is valid JSON"
46+
47+
- name: Check required fields in plugin.json
48+
run: |
49+
python3 << 'EOF'
50+
import json
51+
import sys
52+
53+
required_fields = ['name', 'version', 'description', 'author', 'license']
54+
55+
with open('.claude-plugin/plugin.json', 'r') as f:
56+
data = json.load(f)
57+
58+
missing = [field for field in required_fields if field not in data]
59+
60+
if missing:
61+
print(f"Error: Missing required fields in plugin.json: {', '.join(missing)}")
62+
sys.exit(1)
63+
64+
print("✓ All required fields present in plugin.json")
65+
EOF
66+
67+
- name: Check required fields in marketplace.json
68+
run: |
69+
python3 << 'EOF'
70+
import json
71+
import sys
72+
73+
required_fields = ['display_name', 'summary', 'description', 'categories', 'icon', 'publisher', 'license', 'version']
74+
75+
with open('.claude-plugin/marketplace.json', 'r') as f:
76+
data = json.load(f)
77+
78+
missing = [field for field in required_fields if field not in data]
79+
80+
if missing:
81+
print(f"Error: Missing required fields in marketplace.json: {', '.join(missing)}")
82+
sys.exit(1)
83+
84+
print("✓ All required fields present in marketplace.json")
85+
EOF

0 commit comments

Comments
 (0)