Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 75 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,41 +92,96 @@ jobs:
bandit-report.json
safety-report.json

framework-integration:
name: Framework Integration Tests
atomic-design-validation:
name: Atomic Design Standards
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Pixi
uses: prefix-dev/[email protected]

- name: Install framework
run: pixi install --environment dev

- name: Test framework installation
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.12"

- name: Install dependencies
run: |
pixi run install
pixi run uckn --version
python -m pip install --upgrade pip
pip install -e .[dev]

- name: Test project initialization
- name: Validate UCKN atomic structure
run: |
mkdir test-project
cd test-project
pixi run --environment dev init-project
ls -la
echo "🏗️ Validating atomic design structure..."

# Check atomic directory structure
test -d "src/uckn/core/atoms" || (echo "❌ Missing atoms directory" && exit 1)
test -d "src/uckn/core/molecules" || (echo "❌ Missing molecules directory" && exit 1)
test -d "src/uckn/core/organisms" || (echo "❌ Missing organisms directory" && exit 1)
echo "✅ Atomic directory structure valid"

# Check file size constraints (200-500 lines)
python << 'EOF'
import os
import sys

violations = []
for root, dirs, files in os.walk("src/uckn"):
for file in files:
if file.endswith(".py") and file != "__init__.py":
filepath = os.path.join(root, file)
with open(filepath, 'r') as f:
line_count = sum(1 for line in f)

if line_count > 500:
violations.append(f"{filepath}: {line_count} lines (exceeds 500)")

- name: Test knowledge analysis
if violations:
print("❌ File size violations:")
for violation in violations:
print(f" {violation}")
sys.exit(1)
else:
print("✅ All files within size constraints")
EOF

- name: Test UCKN framework integration
run: |
cd test-project
pixi run --environment dev analyze-project
echo "🔧 Testing UCKN framework integration..."
python << 'EOF'
# Test main imports
try:
from src.uckn import KnowledgeManager, SemanticSearch, UnifiedKnowledgeManager
print("✅ Main imports working")
except ImportError as e:
print(f"❌ Import error: {e}")
exit(1)

# Test initialization
try:
km = KnowledgeManager()
health = km.get_health_status()
print(f"✅ KnowledgeManager: {health}")
except Exception as e:
print(f"❌ KnowledgeManager error: {e}")
exit(1)

# Test unified interface
try:
ukm = UnifiedKnowledgeManager()
capabilities = ukm.get_capabilities()
print(f"✅ UnifiedKnowledgeManager: {len(capabilities)} capabilities")
except Exception as e:
print(f"❌ UnifiedKnowledgeManager error: {e}")
exit(1)

print("🎉 UCKN integration tests passed!")
EOF

build:
name: Build Package
runs-on: ubuntu-latest
needs: [test, lint, security]
needs: [test, lint, security, atomic-design-validation]

steps:
- name: Checkout code
Expand Down
245 changes: 245 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
name: Pull Request Checks

on:
pull_request:
branches: [ main, develop ]
types: [opened, synchronize, reopened, ready_for_review]

jobs:
pr-quality-gate:
name: PR Quality Gate
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Get full history for diff analysis

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.12"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]

- name: Quick lint check (changed files only)
run: |
echo "🔍 Quick lint check on changed files..."

# Get changed Python files
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- '*.py' | tr '\n' ' ')

if [ -n "$CHANGED_FILES" ]; then
echo "Changed files: $CHANGED_FILES"
ruff check $CHANGED_FILES --output-format=github
ruff format --check $CHANGED_FILES
echo "✅ Lint check passed"
else
echo "No Python files changed"
fi

- name: Run tests on changed modules
run: |
echo "🧪 Running tests for changed modules..."

# Get changed Python files and find corresponding test files
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- 'src/**/*.py')

if [ -n "$CHANGED_FILES" ]; then
# Run all tests since dependencies might be complex
pytest tests/ -v --tb=short
echo "✅ Tests passed"
else
echo "No source files changed, skipping tests"
fi

- name: Validate atomic design on changes
run: |
echo "🏗️ Validating atomic design on changed files..."

python << 'EOF'
import os
import subprocess
import sys

# Get changed files
result = subprocess.run(['git', 'diff', '--name-only', 'origin/${{ github.base_ref }}...HEAD', '--', 'src/**/*.py'],
capture_output=True, text=True)
changed_files = result.stdout.strip().split('\n') if result.stdout.strip() else []

violations = []
for file_path in changed_files:
if file_path and os.path.exists(file_path) and file_path.endswith('.py'):
with open(file_path, 'r') as f:
line_count = sum(1 for line in f)

if line_count > 500:
violations.append(f"{file_path}: {line_count} lines (exceeds 500-line limit)")

# Check if file is in correct atomic location
if 'src/uckn/core/' in file_path:
if not any(atomic in file_path for atomic in ['atoms/', 'molecules/', 'organisms/']):
violations.append(f"{file_path}: not in atomic structure (atoms/molecules/organisms)")

if violations:
print("❌ Atomic design violations in changed files:")
for violation in violations:
print(f" {violation}")
sys.exit(1)
else:
print("✅ Changed files comply with atomic design")
EOF

- name: Check imports and dependencies
run: |
echo "🔍 Checking import structure..."

python << 'EOF'
import os
import ast
import sys

def check_imports(file_path):
"""Check for proper import structure"""
violations = []

try:
with open(file_path, 'r') as f:
tree = ast.parse(f.read())

for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom):
if node.module and 'framework.' in node.module:
violations.append(f"Legacy framework import: {node.module}")
except:
pass # Skip files that can't be parsed

return violations

all_violations = []
for root, dirs, files in os.walk("src/uckn"):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
violations = check_imports(file_path)
all_violations.extend([f"{file_path}: {v}" for v in violations])

if all_violations:
print("❌ Import violations:")
for violation in all_violations:
print(f" {violation}")
sys.exit(1)
else:
print("✅ Import structure is clean")
EOF

pr-coverage:
name: Coverage Check
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.12"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]

- name: Generate coverage report
run: |
echo "📊 Generating coverage report..."
pytest tests/ --cov=src/uckn --cov-report=json --cov-report=term

# Check coverage threshold
python << 'EOF'
import json

with open('coverage.json', 'r') as f:
coverage_data = json.load(f)

total_coverage = coverage_data['totals']['percent_covered']
print(f"Total coverage: {total_coverage:.1f}%")

if total_coverage < 70:
print(f"❌ Coverage below threshold: {total_coverage:.1f}% < 70%")
exit(1)
else:
print(f"✅ Coverage meets threshold: {total_coverage:.1f}% >= 70%")
EOF

pr-docs:
name: Documentation Check
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Check documentation updates
run: |
echo "📚 Checking documentation..."

# Check if significant changes need doc updates
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
SRC_CHANGES=$(echo "$CHANGED_FILES" | grep -E '^src/' | wc -l)
DOC_CHANGES=$(echo "$CHANGED_FILES" | grep -E '\.(md|rst)$' | wc -l)

echo "Source file changes: $SRC_CHANGES"
echo "Documentation changes: $DOC_CHANGES"

if [ "$SRC_CHANGES" -gt 5 ] && [ "$DOC_CHANGES" -eq 0 ]; then
echo "⚠️ Significant source changes detected but no documentation updates"
echo "Consider updating documentation for major changes"
else
echo "✅ Documentation status acceptable"
fi

pr-summary:
name: PR Summary
runs-on: ubuntu-latest
needs: [pr-quality-gate, pr-coverage, pr-docs]
if: always()

steps:
- name: Generate PR summary
run: |
echo "## 🎯 Pull Request Quality Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ needs.pr-quality-gate.result }}" == "success" ]; then
echo "✅ **Quality Gate**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Quality Gate**: Failed" >> $GITHUB_STEP_SUMMARY
fi

if [ "${{ needs.pr-coverage.result }}" == "success" ]; then
echo "✅ **Coverage**: Acceptable" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Coverage**: Below threshold" >> $GITHUB_STEP_SUMMARY
fi

if [ "${{ needs.pr-docs.result }}" == "success" ]; then
echo "✅ **Documentation**: Checked" >> $GITHUB_STEP_SUMMARY
else
echo "⚠️ **Documentation**: Needs attention" >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "### UCKN Framework Standards" >> $GITHUB_STEP_SUMMARY
echo "- Atomic design structure enforced" >> $GITHUB_STEP_SUMMARY
echo "- File size limits validated (≤500 lines)" >> $GITHUB_STEP_SUMMARY
echo "- Import structure verified" >> $GITHUB_STEP_SUMMARY
echo "- Test coverage maintained" >> $GITHUB_STEP_SUMMARY
Loading