Skip to content

Fix the typer error in the CI #21

Fix the typer error in the CI

Fix the typer error in the CI #21

Workflow file for this run

# SpecMem CI Pipeline
# Runs linting, type checking, and tests on every push and PR
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PYTHON_VERSION: "3.11"
FORCE_COLOR: "1"
jobs:
# ===========================================================================
# Lint & Format Check
# ===========================================================================
lint:
name: Lint & Format
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff
- name: Run Ruff linter
run: ruff check --output-format=github .
continue-on-error: true
- name: Run Ruff formatter check
run: ruff format --check .
continue-on-error: true
# ===========================================================================
# Type Checking
# ===========================================================================
typecheck:
name: Type Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run MyPy
run: mypy specmem --ignore-missing-imports
continue-on-error: true
# ===========================================================================
# Unit Tests
# ===========================================================================
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run unit tests
run: |
pytest tests/unit -v --tb=short -m "not slow" --ignore=tests/unit/test_embeddings.py || true
continue-on-error: true
- name: Run property tests
run: |
pytest tests/property -v --tb=short --hypothesis-seed=42 --ignore=tests/property/test_embedding_props.py || true
continue-on-error: true
# ===========================================================================
# Build Package
# ===========================================================================
build:
name: Build Package
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: python -m build
- name: Check package
run: twine check dist/*
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7
# ===========================================================================
# SpecMem Analysis (dogfooding - run on ourselves)
# ===========================================================================
specmem:
name: Spec Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install SpecMem from source
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run Spec Coverage
id: cov
run: |
echo "::group::Spec Coverage"
specmem cov --robot > cov.json 2>&1 || true
cat cov.json
echo "::endgroup::"
# Extract coverage percentage
COV=$(python3 -c "import json; d=json.load(open('cov.json')); print(d.get('coverage_percentage', 0))" 2>/dev/null || echo "0")
echo "coverage=$COV" >> $GITHUB_OUTPUT
continue-on-error: true
- name: Run Spec Health
id: health
run: |
echo "::group::Spec Health"
specmem health --robot > health.json 2>&1 || true
cat health.json
echo "::endgroup::"
# Extract health grade and score
GRADE=$(python3 -c "import json; d=json.load(open('health.json')); print(d.get('letter_grade', 'N/A'))" 2>/dev/null || echo "N/A")
SCORE=$(python3 -c "import json; d=json.load(open('health.json')); print(d.get('overall_score', 0))" 2>/dev/null || echo "0")
echo "grade=$GRADE" >> $GITHUB_OUTPUT
echo "score=$SCORE" >> $GITHUB_OUTPUT
continue-on-error: true
- name: Run Spec Validation
id: validate
run: |
echo "::group::Spec Validation"
specmem validate --robot > validate.json 2>&1 || true
cat validate.json
echo "::endgroup::"
# Extract error count
ERRORS=$(python3 -c "import json; d=json.load(open('validate.json')); print(len(d.get('errors', [])))" 2>/dev/null || echo "0")
echo "errors=$ERRORS" >> $GITHUB_OUTPUT
continue-on-error: true
- name: Create Summary
run: |
COV="${{ steps.cov.outputs.coverage }}"
GRADE="${{ steps.health.outputs.grade }}"
SCORE="${{ steps.health.outputs.score }}"
ERRORS="${{ steps.validate.outputs.errors }}"
# Determine status emojis
COV_STATUS="⚠️"
[[ $(echo "$COV >= 80" | bc -l 2>/dev/null || echo 0) -eq 1 ]] && COV_STATUS="✅"
[[ $(echo "$COV < 50" | bc -l 2>/dev/null || echo 0) -eq 1 ]] && COV_STATUS="❌"
HEALTH_STATUS="⚠️"
[[ "$GRADE" == "A" || "$GRADE" == "B" ]] && HEALTH_STATUS="✅"
[[ "$GRADE" == "D" || "$GRADE" == "F" ]] && HEALTH_STATUS="❌"
VAL_STATUS="✅"
[[ "$ERRORS" != "0" ]] && VAL_STATUS="❌"
cat >> $GITHUB_STEP_SUMMARY << EOF
## 📊 SpecMem Analysis
| Metric | Value | Status |
|--------|-------|--------|
| Spec Coverage | ${COV}% | ${COV_STATUS} |
| Health Grade | ${GRADE} (${SCORE}/100) | ${HEALTH_STATUS} |
| Validation Errors | ${ERRORS} | ${VAL_STATUS} |
---
*SpecMem dogfooding - analyzing our own specs!*
EOF
- name: Post PR Comment
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const cov = '${{ steps.cov.outputs.coverage }}' || '0';
const grade = '${{ steps.health.outputs.grade }}' || 'N/A';
const score = '${{ steps.health.outputs.score }}' || '0';
const errors = '${{ steps.validate.outputs.errors }}' || '0';
const covStatus = parseFloat(cov) >= 80 ? '✅' : parseFloat(cov) >= 50 ? '⚠️' : '❌';
const healthStatus = ['A', 'B'].includes(grade) ? '✅' : grade === 'C' ? '⚠️' : '❌';
const valStatus = errors === '0' ? '✅' : '❌';
const body = `## 📊 SpecMem Analysis
| Metric | Value | Status |
|--------|-------|--------|
| Spec Coverage | ${cov}% | ${covStatus} |
| Health Grade | ${grade} (${score}/100) | ${healthStatus} |
| Validation Errors | ${errors} | ${valStatus} |
---
*SpecMem dogfooding - analyzing our own specs!*`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.includes('SpecMem Analysis'));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
continue-on-error: true
# ===========================================================================
# All Checks Summary
# ===========================================================================
summary:
name: CI Summary
runs-on: ubuntu-latest
needs: [lint, typecheck, test, build, specmem]
if: always()
steps:
- name: Summary
run: |
echo "## CI Results" >> $GITHUB_STEP_SUMMARY
echo "- Lint: ${{ needs.lint.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Type Check: ${{ needs.typecheck.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Tests: ${{ needs.test.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Build: ${{ needs.build.result }}" >> $GITHUB_STEP_SUMMARY
echo "- SpecMem: ${{ needs.specmem.result }}" >> $GITHUB_STEP_SUMMARY
echo ""
echo "Build job must pass for CI to succeed."
if [[ "${{ needs.build.result }}" != "success" ]]; then
echo "Build failed!"
exit 1
fi
echo "CI completed successfully!"