chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:22 +08:00
commit 9963ea7ef7
410 changed files with 85021 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
# These are supported funding model platforms
github: NomenAK
patreon: # SuperClaude
open_collective: # Replace with a single Open Collective username
ko_fi: # superclaude
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+52
View File
@@ -0,0 +1,52 @@
# Pull Request
## Summary
<!-- Briefly describe the purpose of this PR -->
## Changes
<!-- List the main changes -->
-
## Related Issue
<!-- Reference related issue numbers if applicable -->
Closes #
## Checklist
### Git Workflow
- [ ] External contributors: Followed Fork → topic branch → upstream PR flow
- [ ] Collaborators: Used topic branch (no direct commits to main)
- [ ] Rebased on upstream/main (`git rebase upstream/main`, no conflicts)
- [ ] Commit messages follow Conventional Commits (`feat:`, `fix:`, `docs:`, etc.)
### Code Quality
- [ ] Changes are limited to a single purpose (not a mega-PR; aim for ~200 lines diff)
- [ ] Follows existing code conventions and patterns
- [ ] Added appropriate tests for new features/fixes
- [ ] Lint/Format/Typecheck all pass
- [ ] CI/CD pipeline succeeds (green status)
### Security
- [ ] No secrets or credentials committed
- [ ] Necessary files excluded via `.gitignore`
- [ ] No breaking changes, or if so: `!` commit + MIGRATION.md documented
### Documentation
- [ ] Updated documentation as needed (README, CLAUDE.md, docs/, etc.)
- [ ] Added comments for complex logic
- [ ] API changes are properly documented
## How to Test
<!-- Describe how to verify this PR works -->
## Screenshots (if applicable)
<!-- Attach screenshots for UI changes -->
## Notes
<!-- Anything you want reviewers to know, technical decisions, etc. -->
+158
View File
@@ -0,0 +1,158 @@
# GitHub Actions Workflows
This directory contains CI/CD workflows for SuperClaude Framework.
## Workflows
### 1. **test.yml** - Comprehensive Test Suite
**Triggers**: Push/PR to `master` or `integration`, manual dispatch
**Jobs**:
- **test**: Run tests on Python 3.10, 3.11, 3.12
- Install UV and dependencies
- Run full test suite
- Generate coverage report (Python 3.10 only)
- Upload to Codecov
- **lint**: Run ruff linter and format checker
- **plugin-check**: Verify pytest plugin loads correctly
- **doctor-check**: Run `superclaude doctor` health check
- **test-summary**: Aggregate results from all jobs
**Status Badge**:
```markdown
[![Tests](https://github.com/SuperClaude-Org/SuperClaude_Framework/actions/workflows/test.yml/badge.svg)](https://github.com/SuperClaude-Org/SuperClaude_Framework/actions/workflows/test.yml)
```
### 2. **quick-check.yml** - Fast PR Feedback
**Triggers**: Pull requests to `master` or `integration`
**Jobs**:
- **quick-test**: Fast check on Python 3.10 only
- Run unit tests only (faster)
- Run linter
- Check formatting
- Verify plugin loads
- 10 minute timeout
**Purpose**: Provide rapid feedback on PRs before running full test matrix.
### 3. **publish-pypi.yml** (Existing)
**Triggers**: Manual or release tags
**Purpose**: Publish package to PyPI
### 4. **readme-quality-check.yml** (Existing)
**Triggers**: Push/PR affecting README files
**Purpose**: Validate README quality and consistency
## Local Testing
Before pushing, run these commands locally:
```bash
# Run full test suite
uv run pytest -v
# Run with coverage
uv run pytest --cov=superclaude --cov-report=term
# Run linter
uv run ruff check src/ tests/
# Check formatting
uv run ruff format --check src/ tests/
# Auto-fix formatting
uv run ruff format src/ tests/
# Verify plugin loads
uv run pytest --trace-config | grep superclaude
# Run doctor check
uv run superclaude doctor --verbose
```
## CI/CD Pipeline
```
┌─────────────────────┐
│ Push/PR Created │
└──────────┬──────────┘
├─────────────────────────┐
│ │
┌──────▼──────┐ ┌───────▼────────┐
│ Quick Check │ │ Full Test │
│ (PR only) │ │ Matrix │
│ │ │ │
│ • Unit tests│ │ • Python 3.10 │
│ • Lint │ │ • Python 3.11 │
│ • Format │ │ • Python 3.12 │
│ │ │ • Coverage │
│ ~2-3 min │ │ • Lint │
└─────────────┘ │ • Plugin check │
│ • Doctor check │
│ │
│ ~5-8 min │
└────────────────┘
```
## Coverage Reporting
Coverage reports are generated for Python 3.10 and uploaded to Codecov.
To view coverage locally:
```bash
uv run pytest --cov=superclaude --cov-report=html
open htmlcov/index.html
```
## Troubleshooting
### Workflow fails with "UV not found"
- UV is installed in each job via `curl -LsSf https://astral.sh/uv/install.sh | sh`
- If installation fails, check UV's status page
### Tests fail locally but pass in CI (or vice versa)
- Check Python version: `python --version`
- Reinstall dependencies: `uv pip install -e ".[dev]"`
- Clear caches: `rm -rf .pytest_cache .venv`
### Plugin not loading in CI
- Verify entry point in `pyproject.toml`: `[project.entry-points.pytest11]`
- Check plugin is installed: `uv run pytest --trace-config`
### Coverage upload fails
- This is non-blocking (fail_ci_if_error: false)
- Check Codecov token in repository secrets
## Maintenance
### Adding a New Workflow
1. Create new `.yml` file in this directory
2. Follow existing structure (checkout, setup-python, install UV)
3. Add status badge to README.md if needed
4. Document in this file
### Updating Python Versions
1. Edit `matrix.python-version` in `test.yml`
2. Update `pyproject.toml` classifiers
3. Test locally with new version first
### Modifying Test Strategy
- **quick-check.yml**: For fast PR feedback (unit tests only)
- **test.yml**: For comprehensive validation (full matrix)
## Best Practices
1. **Keep workflows fast**: Use caching, parallel jobs
2. **Fail fast**: Use `-x` flag in pytest for quick-check
3. **Clear names**: Job and step names should be descriptive
4. **Version pinning**: Pin action versions (@v4, @v5)
5. **Matrix testing**: Test on multiple Python versions
6. **Non-blocking coverage**: Don't fail on coverage upload errors
7. **Manual triggers**: Add `workflow_dispatch` for debugging
## Resources
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [UV Documentation](https://github.com/astral-sh/uv)
- [Pytest Documentation](https://docs.pytest.org/)
- [SuperClaude Testing Guide](../../docs/developer-guide/testing-debugging.md)
+172
View File
@@ -0,0 +1,172 @@
name: Publish to PyPI
on:
# Trigger on new releases
release:
types: [published]
# Allow manual triggering
workflow_dispatch:
inputs:
target:
description: 'Publication target'
required: true
default: 'testpypi'
type: choice
options:
- testpypi
- pypi
# Restrict permissions for security
permissions:
contents: read
jobs:
build-and-publish:
name: Build and publish Python package
runs-on: ubuntu-latest
environment:
name: ${{ github.event_name == 'release' && 'pypi' || 'testpypi' }}
url: ${{ github.event_name == 'release' && 'https://pypi.org/p/SuperClaude' || 'https://test.pypi.org/p/SuperClaude' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
# Fetch full history for proper version detection
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build twine toml
- name: Verify package structure
run: |
echo "📦 Checking package structure..."
ls -la
echo "🔍 Checking SuperClaude package..."
ls -la src/superclaude/
echo "🔍 Verifying src directory..."
ls -la src/
# Verify version consistency
echo "📋 Checking version consistency..."
python -c "
import toml
import sys
sys.path.insert(0, 'src')
# Load pyproject.toml version
with open('pyproject.toml', 'r') as f:
pyproject = toml.load(f)
pyproject_version = pyproject['project']['version']
# Load package version
from superclaude import __version__
print(f'pyproject.toml version: {pyproject_version}')
print(f'Package version: {__version__}')
if pyproject_version != __version__:
print('❌ Version mismatch!')
sys.exit(1)
else:
print('✅ Versions match')
"
- name: Clean previous builds
run: |
rm -rf dist/ build/ *.egg-info/
- name: Build package
run: |
echo "🔨 Building package..."
python -m build
echo "📦 Built files:"
ls -la dist/
- name: Validate package
run: |
echo "🔍 Validating package..."
python -m twine check dist/*
# Upload to TestPyPI for testing (manual trigger or non-release)
- name: Upload to TestPyPI
if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'testpypi'
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
print-hash: true
# Upload to production PyPI (only on releases)
- name: Upload to PyPI
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'pypi')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
print-hash: true
- name: Create deployment summary
if: always()
run: |
echo "## 📦 SuperClaude Package Deployment" >> $GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Target | ${{ github.event_name == 'release' && 'PyPI (Production)' || github.event.inputs.target || 'TestPyPI' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Trigger | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY
echo "| Version | $(python -c 'import sys; sys.path.insert(0, \"src\"); from superclaude import __version__; print(__version__)') |" >> $GITHUB_STEP_SUMMARY
echo "| Commit | ${{ github.sha }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event_name }}" == "release" ]; then
echo "🎉 **Production release published to PyPI!**" >> $GITHUB_STEP_SUMMARY
echo "Install with: \`pip install SuperClaude\`" >> $GITHUB_STEP_SUMMARY
else
echo "🧪 **Test release published to TestPyPI**" >> $GITHUB_STEP_SUMMARY
echo "Test install with: \`pip install --index-url https://test.pypi.org/simple/ SuperClaude\`" >> $GITHUB_STEP_SUMMARY
fi
test-installation:
name: Test package installation
needs: build-and-publish
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'testpypi'
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Test installation from TestPyPI
run: |
echo "🧪 Testing installation from TestPyPI..."
# Wait a bit for the package to be available
sleep 30
# Install from TestPyPI
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
SuperClaude
# Test basic import
python -c "
import superclaude
print(f'✅ Successfully imported SuperClaude v{superclaude.__version__}')
# Test CLI entry point
import subprocess
result = subprocess.run(['SuperClaude', '--version'], capture_output=True, text=True)
print(f'✅ CLI version: {result.stdout.strip()}')
"
echo "✅ Installation test completed successfully!"
+140
View File
@@ -0,0 +1,140 @@
name: Pull Sync from Framework
on:
schedule:
- cron: '0 */6 * * *'
workflow_dispatch:
jobs:
sync-and-isolate:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout Plugin Repository (Target)
uses: actions/checkout@v4
with:
path: plugin-repo
- name: Check for Framework updates
id: check-updates
run: |
FRAMEWORK_HEAD=$(git ls-remote https://github.com/SuperClaude-Org/SuperClaude_Framework HEAD | cut -f1)
echo "Current framework HEAD: $FRAMEWORK_HEAD"
echo "framework-head=$FRAMEWORK_HEAD" >> $GITHUB_OUTPUT
LAST_SYNCED=""
if [ -f "plugin-repo/docs/.framework-sync-commit" ]; then
LAST_SYNCED=$(cat plugin-repo/docs/.framework-sync-commit)
echo "Last synced commit: $LAST_SYNCED"
else
echo "No previous sync state - will run sync"
fi
if [ "$FRAMEWORK_HEAD" = "$LAST_SYNCED" ] && [ "${{ github.event_name }}" != "workflow_dispatch" ]; then
echo "✅ Framework is up to date - skipping sync"
echo "has-updates=false" >> $GITHUB_OUTPUT
else
echo "🔄 Framework has updates - proceeding with sync"
echo "has-updates=true" >> $GITHUB_OUTPUT
fi
- name: Checkout Framework Repository (Source)
if: steps.check-updates.outputs.has-updates == 'true'
uses: actions/checkout@v4
with:
repository: SuperClaude-Org/SuperClaude_Framework
path: framework-src
- name: Set up Python
if: steps.check-updates.outputs.has-updates == 'true'
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Run Transformation & Sync Logic
if: steps.check-updates.outputs.has-updates == 'true'
run: |
cd plugin-repo
python3 scripts/sync_from_framework.py
- name: Verify protected files are unchanged
if: steps.check-updates.outputs.has-updates == 'true'
working-directory: plugin-repo
run: |
# Note: plugin.json removed from list as it is updated by the MCP merge script
PROTECTED=(
"README.md" "README-ja.md" "README-zh.md"
"BACKUP_GUIDE.md" "MIGRATION_GUIDE.md" "SECURITY.md"
"CLAUDE.md" "LICENSE" ".gitignore"
".claude-plugin/marketplace.json"
"core/" "modes/"
)
VIOLATIONS=()
for path in "${PROTECTED[@]}"; do
if git diff --name-only HEAD -- "$path" | grep -q .; then
VIOLATIONS+=("$path")
fi
done
if [ ${#VIOLATIONS[@]} -gt 0 ]; then
echo "🚨 PROTECTION VIOLATION: sync modified Plugin-owned files:"
for v in "${VIOLATIONS[@]}"; do echo " • $v"; done
echo ""
echo "Fix: check SYNC_MAPPINGS in scripts/sync_from_framework.py"
exit 1
fi
echo "🔒 Protection check passed — no Plugin-owned files were modified"
- name: Save framework sync state
if: steps.check-updates.outputs.has-updates == 'true'
run: |
echo "${{ steps.check-updates.outputs.framework-head }}" > plugin-repo/docs/.framework-sync-commit
echo "✅ Saved framework commit: ${{ steps.check-updates.outputs.framework-head }}"
- name: Commit Changes to Sync Branch
if: steps.check-updates.outputs.has-updates == 'true'
id: commit-changes
working-directory: plugin-repo
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
SYNC_BRANCH="framework-sync/$(date +'%Y-%m-%d-%H%M')"
git checkout -b "$SYNC_BRANCH"
git add commands/ agents/ .claude-plugin/plugin.json plugin.json
if [ -f "docs/.framework-sync-commit" ]; then
git add -f docs/.framework-sync-commit
fi
if ! git diff --cached --quiet; then
git commit -m "chore: automated sync from framework [${{ steps.check-updates.outputs.framework-head }}]"
git push origin "$SYNC_BRANCH"
echo "has-changes=true" >> $GITHUB_OUTPUT
echo "sync-branch=$SYNC_BRANCH" >> $GITHUB_OUTPUT
else
echo "No changes detected."
echo "has-changes=false" >> $GITHUB_OUTPUT
fi
- name: Create Pull Request for Review
if: steps.commit-changes.outputs.has-changes == 'true'
working-directory: plugin-repo
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr create \
--title "chore: framework sync ${{ steps.check-updates.outputs.framework-head }}" \
--body "## Automated Framework Sync
Synced from upstream framework commit: \`${{ steps.check-updates.outputs.framework-head }}\`
**Review required before merge.** This PR was created automatically by the framework sync workflow. Please review the changes to ensure no unexpected modifications were introduced.
---
*Auto-generated by pull-sync-framework workflow*" \
--base main \
--head "${{ steps.commit-changes.outputs.sync-branch }}"
+54
View File
@@ -0,0 +1,54 @@
name: Quick Check
on:
pull_request:
branches: [master, integration]
jobs:
quick-test:
name: Quick Test (Python 3.10)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install UV
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
- name: Run unit tests only
run: |
pytest tests/unit/ -v --tb=short -x
- name: Run linter
run: |
ruff check src/ tests/
- name: Check formatting
run: |
ruff format --check src/ tests/
- name: Verify pytest plugin
run: |
pytest --trace-config 2>&1 | grep -q "superclaude"
- name: Summary
if: success()
run: |
echo "✅ Quick checks passed!"
echo " - Unit tests: PASSED"
echo " - Linting: PASSED"
echo " - Formatting: PASSED"
echo " - Plugin: LOADED"
+312
View File
@@ -0,0 +1,312 @@
name: README Quality Check
on:
pull_request:
paths:
- 'README*.md'
- 'Docs/**/*.md'
push:
branches: [main, master, develop]
workflow_dispatch:
permissions:
contents: read
pull-requests: write
issues: write
jobs:
readme-quality-check:
name: Multi-language README Quality Assessment
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests beautifulsoup4 pyyaml
- name: Create quality checker script
run: |
cat > readme_checker.py << 'EOF'
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SuperClaude Multi-language README Quality Checker
Checks version sync, link validity, and structural consistency
"""
import os
import re
import requests
import json
from pathlib import Path
from urllib.parse import urljoin
class READMEQualityChecker:
def __init__(self):
self.readme_files = ['README.md', 'README-zh.md', 'README-ja.md', 'README-kr.md']
self.results = {
'structure_consistency': [],
'link_validation': [],
'translation_sync': [],
'overall_score': 0
}
def check_structure_consistency(self):
"""Check structural consistency"""
print("🔍 Checking structural consistency...")
structures = {}
for file in self.readme_files:
if os.path.exists(file):
with open(file, 'r', encoding='utf-8') as f:
content = f.read()
# Extract heading structure
headers = re.findall(r'^#{1,6}\s+(.+)$', content, re.MULTILINE)
structures[file] = len(headers)
# Compare structural differences
line_counts = [structures.get(f, 0) for f in self.readme_files if f in structures]
if line_counts:
max_diff = max(line_counts) - min(line_counts)
consistency_score = max(0, 100 - (max_diff * 5))
self.results['structure_consistency'] = {
'score': consistency_score,
'details': structures,
'status': 'PASS' if consistency_score >= 90 else 'WARN'
}
print(f"✅ Structural consistency: {consistency_score}/100")
for file, count in structures.items():
print(f" {file}: {count} headers")
def check_link_validation(self):
"""Check link validity"""
print("🔗 Checking link validity...")
all_links = {}
broken_links = []
for file in self.readme_files:
if os.path.exists(file):
with open(file, 'r', encoding='utf-8') as f:
content = f.read()
# Extract all links
links = re.findall(r'\[([^\]]+)\]\(([^)]+)\)', content)
all_links[file] = []
for text, url in links:
link_info = {'text': text, 'url': url, 'status': 'unknown'}
# Check local file links
if not url.startswith(('http://', 'https://', '#')):
if os.path.exists(url):
link_info['status'] = 'valid'
else:
link_info['status'] = 'broken'
broken_links.append(f"{file}: {url}")
# HTTP link check (simplified)
elif url.startswith(('http://', 'https://')):
try:
# Only check key links to avoid excessive requests
if any(domain in url for domain in ['github.com', 'pypi.org', 'npmjs.com']):
response = requests.head(url, timeout=10, allow_redirects=True)
link_info['status'] = 'valid' if response.status_code < 400 else 'broken'
else:
link_info['status'] = 'skipped'
except:
link_info['status'] = 'error'
else:
link_info['status'] = 'anchor'
all_links[file].append(link_info)
# Calculate link health score
total_links = sum(len(links) for links in all_links.values())
broken_count = len(broken_links)
link_score = max(0, 100 - (broken_count * 10)) if total_links > 0 else 100
self.results['link_validation'] = {
'score': link_score,
'total_links': total_links,
'broken_links': broken_count,
'broken_list': broken_links[:10], # Show max 10
'status': 'PASS' if link_score >= 80 else 'FAIL'
}
print(f"✅ Link validity: {link_score}/100")
print(f" Total links: {total_links}")
print(f" Broken links: {broken_count}")
def check_translation_sync(self):
"""Check translation sync"""
print("🌍 Checking translation sync...")
if not all(os.path.exists(f) for f in self.readme_files):
print("⚠️ Some README files are missing")
self.results['translation_sync'] = {
'score': 60,
'status': 'WARN',
'message': 'Some README files are missing'
}
return
# Check file modification times
mod_times = {}
for file in self.readme_files:
mod_times[file] = os.path.getmtime(file)
# Calculate time difference (seconds)
times = list(mod_times.values())
time_diff = max(times) - min(times)
# Score based on time diff (within 7 days = synced)
sync_score = max(0, 100 - (time_diff / (7 * 24 * 3600) * 20))
self.results['translation_sync'] = {
'score': int(sync_score),
'time_diff_days': round(time_diff / (24 * 3600), 2),
'status': 'PASS' if sync_score >= 80 else 'WARN',
'mod_times': {f: f"{os.path.getmtime(f):.0f}" for f in self.readme_files}
}
print(f"✅ Translation sync: {int(sync_score)}/100")
print(f" Max time difference: {round(time_diff / (24 * 3600), 1)} days")
def generate_report(self):
"""Generate quality report"""
print("\n📊 Generating quality report...")
# Calculate overall score
scores = [
self.results['structure_consistency'].get('score', 0),
self.results['link_validation'].get('score', 0),
self.results['translation_sync'].get('score', 0)
]
overall_score = sum(scores) // len(scores)
self.results['overall_score'] = overall_score
# Generate GitHub Actions summary
pipe = "|"
table_header = f"{pipe} Check {pipe} Score {pipe} Status {pipe} Details {pipe}"
table_separator = f"{pipe}----------|------|------|------|"
table_row1 = f"{pipe} 📐 Structure {pipe} {self.results['structure_consistency'].get('score', 0)}/100 {pipe} {self.results['structure_consistency'].get('status', 'N/A')} {pipe} {len(self.results['structure_consistency'].get('details', {}))} files {pipe}"
table_row2 = f"{pipe} 🔗 Links {pipe} {self.results['link_validation'].get('score', 0)}/100 {pipe} {self.results['link_validation'].get('status', 'N/A')} {pipe} {self.results['link_validation'].get('broken_links', 0)} broken {pipe}"
table_row3 = f"{pipe} 🌍 Translation {pipe} {self.results['translation_sync'].get('score', 0)}/100 {pipe} {self.results['translation_sync'].get('status', 'N/A')} {pipe} {self.results['translation_sync'].get('time_diff_days', 0)} days diff {pipe}"
summary_parts = [
"## 📊 README Quality Check Report",
"",
f"### 🏆 Overall Score: {overall_score}/100",
"",
table_header,
table_separator,
table_row1,
table_row2,
table_row3,
"",
"### 📋 Details",
"",
"**Structural consistency details:**"
]
summary = "\n".join(summary_parts)
for file, count in self.results['structure_consistency'].get('details', {}).items():
summary += f"\n- `{file}`: {count} headings"
if self.results['link_validation'].get('broken_links'):
summary += f"\n\n**Broken links:**\n"
for link in self.results['link_validation']['broken_list']:
summary += f"\n- ❌ {link}"
summary += f"\n\n### 🎯 Recommendations\n"
if overall_score >= 90:
summary += "✅ Excellent quality! Keep it up."
elif overall_score >= 70:
summary += "⚠️ Good quality with room for improvement."
else:
summary += "🚨 Needs improvement! Please review the issues above."
# Write GitHub Actions summary
github_step_summary = os.environ.get('GITHUB_STEP_SUMMARY')
if github_step_summary:
with open(github_step_summary, 'w', encoding='utf-8') as f:
f.write(summary)
# Save detailed results
with open('readme-quality-report.json', 'w', encoding='utf-8') as f:
json.dump(self.results, f, indent=2, ensure_ascii=False)
print("✅ Report generated")
# Determine exit code based on score
return 0 if overall_score >= 70 else 1
def run_all_checks(self):
"""Run all checks"""
print("🚀 Starting README quality check...\n")
self.check_structure_consistency()
self.check_link_validation()
self.check_translation_sync()
exit_code = self.generate_report()
print(f"\n🎯 Check complete! Score: {self.results['overall_score']}/100")
return exit_code
if __name__ == "__main__":
checker = READMEQualityChecker()
exit_code = checker.run_all_checks()
exit(exit_code)
EOF
- name: Run README quality check
run: python readme_checker.py
- name: Upload quality report
if: always()
uses: actions/upload-artifact@v4
with:
name: readme-quality-report
path: readme-quality-report.json
retention-days: 30
- name: Comment PR (if applicable)
if: github.event_name == 'pull_request' && always() && github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
if (fs.existsSync('readme-quality-report.json')) {
const report = JSON.parse(fs.readFileSync('readme-quality-report.json', 'utf8'));
const score = report.overall_score;
const emoji = score >= 90 ? '🏆' : score >= 70 ? '✅' : '⚠️';
const comment = `${emoji} **README Quality Check: ${score}/100**\n\n` +
`📐 Structural consistency: ${report.structure_consistency?.score || 0}/100\n` +
`🔗 Link validity: ${report.link_validation?.score || 0}/100\n` +
`🌍 Translation sync: ${report.translation_sync?.score || 0}/100\n\n` +
`See the Actions tab for the detailed report.`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
}
+175
View File
@@ -0,0 +1,175 @@
name: Tests
on:
push:
branches: [master, integration]
pull_request:
branches: [master, integration]
workflow_dispatch:
jobs:
test:
name: Test on Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install UV
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Verify UV installation
run: uv --version
- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
uv pip list --system
- name: Verify package installation
run: |
python -c "import superclaude; print(f'SuperClaude {superclaude.__version__} installed')"
python -c "import pytest_cov; print('pytest-cov is installed')"
- name: Run tests
run: |
pytest -v --tb=short --color=yes
- name: Run tests with coverage
if: matrix.python-version == '3.10'
run: |
pytest --cov=superclaude --cov-report=xml --cov-report=term
- name: Upload coverage to Codecov
if: matrix.python-version == '3.10'
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
lint:
name: Lint and Format Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install UV
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
- name: Run ruff linter
run: |
ruff check src/ tests/
- name: Check ruff formatting
run: |
ruff format --check src/ tests/
plugin-check:
name: Pytest Plugin Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install UV
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
- name: Verify pytest plugin loaded
run: |
pytest --trace-config 2>&1 | grep -q "superclaude" && echo "✅ Plugin loaded successfully" || (echo "❌ Plugin not loaded" && exit 1)
- name: Check available fixtures
run: |
pytest --fixtures | grep -E "(confidence_checker|self_check_protocol|reflexion_pattern|token_budget|pm_context)"
doctor-check:
name: SuperClaude Doctor Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install UV
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
- name: Run doctor command
run: |
superclaude doctor --verbose
test-summary:
name: Test Summary
runs-on: ubuntu-latest
needs: [test, lint, plugin-check, doctor-check]
if: always()
steps:
- name: Check test results
run: |
if [ "${{ needs.test.result }}" != "success" ]; then
echo "❌ Tests failed"
exit 1
fi
if [ "${{ needs.lint.result }}" != "success" ]; then
echo "❌ Linting failed"
exit 1
fi
if [ "${{ needs.plugin-check.result }}" != "success" ]; then
echo "❌ Plugin check failed"
exit 1
fi
if [ "${{ needs.doctor-check.result }}" != "success" ]; then
echo "❌ Doctor check failed"
exit 1
fi
echo "✅ All checks passed!"