name: π€ Copilot-Assisted Development Validation
on:
pull_request:
branches: [ main, develop ]
push:
branches: [ main, develop ]
issues:
types: [opened, edited]
jobs:
validate-copilot-issues:
name: Validate Copilot-Ready Issues
runs-on: ubuntu-latest
if: github.event_name == 'issues'
steps:
- name: Check for Copilot-Ready Label
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const labels = issue.labels.map(label => label.name);
if (labels.includes('copilot-ready') || labels.includes('copilot-task')) {
console.log('β
Issue is marked as Copilot-ready');
// Check for required sections
const body = issue.body || '';
const requiredSections = [
'Implementation Specifications',
'Code Context',
'Success Criteria'
];
const missingSections = requiredSections.filter(section =>
!body.includes(section)
);
if (missingSections.length > 0) {
console.log('β οΈ Missing sections:', missingSections.join(', '));
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `π€ **Copilot Optimization Check**\n\nThis issue is missing some sections that help AI assistants:\n\n${missingSections.map(s => `- ${s}`).join('\n')}\n\nConsider adding these sections for better AI assistance. See our issue templates for examples.`
});
} else {
console.log('β
All required sections present');
}
}
test-mcp-server:
name: Test MCP Server
runs-on: windows-latest
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest pytest-asyncio
- name: Test server imports
run: |
python -c "import server; print('β
Server imports successfully')"
- name: Test MCP server creation
run: |
python -c "from server import mcp; print(f'β
MCP server created: {mcp.name}')"
- name: Run feature tests
run: |
python test_features.py
continue-on-error: true
- name: Test PowerShell availability
run: |
powershell -Command "Write-Host 'β
PowerShell is available'"
- name: Validate templates
run: |
python -c "
import os
templates_dir = 'templates'
if os.path.exists(templates_dir):
templates = [f for f in os.listdir(templates_dir) if f.endswith('.ps1')]
print(f'β
Found {len(templates)} PowerShell templates')
for template in templates:
print(f' - {template}')
else:
print('β οΈ Templates directory not found')
"
lint-and-format:
name: Code Quality Check
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install linting tools
run: |
python -m pip install --upgrade pip
pip install black isort flake8 mypy
pip install -e .
- name: Check code formatting with Black
run: |
black --check --diff server.py
continue-on-error: true
- name: Check import sorting with isort
run: |
isort --check-only --diff server.py
continue-on-error: true
- name: Lint with flake8
run: |
flake8 server.py --max-line-length=100 --extend-ignore=E203,W503
continue-on-error: true
- name: Type check with mypy
run: |
mypy server.py --ignore-missing-imports
continue-on-error: true
security-scan:
name: Security Scan
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install security tools
run: |
python -m pip install --upgrade pip
pip install bandit safety
pip install -e .
- name: Run Bandit security scan
run: |
bandit -r server.py -f json -o bandit-report.json
continue-on-error: true
- name: Check dependencies for vulnerabilities
run: |
safety check --json --output safety-report.json
continue-on-error: true
- name: Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: |
bandit-report.json
safety-report.json
documentation-check:
name: Documentation Validation
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Check README exists and is updated
run: |
if [ -f "README.md" ]; then
echo "β
README.md exists"
# Check if README mentions new features (basic check)
if grep -q "MCP" README.md; then
echo "β
README mentions MCP"
else
echo "β οΈ README might need MCP documentation updates"
fi
else
echo "β README.md missing"
exit 1
fi
- name: Check for docstrings in Python files
run: |
python -c "
import ast
import sys
def check_docstrings(filename):
with open(filename, 'r') as f:
tree = ast.parse(f.read())
functions = [node for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)]
missing_docs = []
for func in functions:
if not ast.get_docstring(func) and not func.name.startswith('_'):
missing_docs.append(func.name)
if missing_docs:
print(f'β οΈ Functions missing docstrings: {missing_docs}')
else:
print('β
All public functions have docstrings')
check_docstrings('server.py')
"
copilot-readiness-check:
name: Copilot Readiness Assessment
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Check code structure for Copilot optimization
run: |
echo "π€ Checking code structure for Copilot readiness..."
# Check for type hints
if grep -q "def.*:" server.py && grep -q "import.*typing" server.py; then
echo "β
Type hints are used"
else
echo "β οΈ Consider adding more type hints for better Copilot suggestions"
fi
# Check for comprehensive docstrings
if grep -q '""".*Args:.*Returns:' server.py; then
echo "β
Comprehensive docstrings found"
else
echo "β οΈ Consider adding Args/Returns sections to docstrings"
fi
# Check for error handling patterns
if grep -q "try:" server.py && grep -q "except" server.py; then
echo "β
Error handling patterns found"
else
echo "β οΈ Consider adding error handling patterns"
fi
# Check for async patterns
if grep -q "async def" server.py && grep -q "await" server.py; then
echo "β
Async patterns are used"
else
echo "β οΈ Consider using async patterns for I/O operations"
fi
echo "π― Copilot readiness assessment complete"
generate-development-summary:
name: Generate Development Summary
runs-on: ubuntu-latest
needs: [test-mcp-server, lint-and-format, security-scan, documentation-check, copilot-readiness-check]
if: always() && (github.event_name == 'pull_request' || github.event_name == 'push')
steps:
- uses: actions/checkout@v4
- name: Create development summary
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Get job results
const jobs = [
{ name: 'test-mcp-server', result: '${{ needs.test-mcp-server.result }}' },
{ name: 'lint-and-format', result: '${{ needs.lint-and-format.result }}' },
{ name: 'security-scan', result: '${{ needs.security-scan.result }}' },
{ name: 'documentation-check', result: '${{ needs.documentation-check.result }}' },
{ name: 'copilot-readiness-check', result: '${{ needs.copilot-readiness-check.result }}' }
];
const summary = [
'# π€ Development Validation Summary',
'',
'## Job Results',
''
];
jobs.forEach(job => {
const icon = job.result === 'success' ? 'β
' : job.result === 'failure' ? 'β' : 'β οΈ';
summary.push(`- ${icon} **${job.name}**: ${job.result}`);
});
summary.push('');
summary.push('## Copilot Optimization Status');
summary.push('');
summary.push('This project includes:');
summary.push('- π€ Copilot-optimized issue templates');
summary.push('- π Comprehensive documentation and examples');
summary.push('- π Type hints and structured code patterns');
summary.push('- β
Automated validation for code quality');
summary.push('');
summary.push('Ready for AI-assisted development! π');
console.log(summary.join('\n'));
// Save summary to step output
core.setOutput('summary', summary.join('\n'));
- name: Comment on PR (if applicable)
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const summary = `${{ steps.create-development-summary.outputs.summary }}`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: summary
});