| name: RMI CI |
|
|
| on: |
| push: |
| branches: [main] |
| pull_request: |
| branches: [main] |
|
|
| |
| |
| |
|
|
| jobs: |
| lint: |
| |
| |
| |
| |
| runs-on: ubuntu-latest |
| continue-on-error: true |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: astral-sh/setup-uv@v2 |
| - uses: actions/setup-python@v5 |
| with: |
| python-version: "3.11" |
| - name: Install ruff |
| run: uv pip install --system ruff |
| - name: Run ruff lint (informational) |
| run: ruff check . --statistics --output-format=concise 2>&1 | tail -30 || true |
|
|
| typecheck: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: astral-sh/setup-uv@v2 |
| - uses: actions/setup-python@v5 |
| with: |
| python-version: "3.11" |
| - name: Install mypy |
| run: uv pip install --system mypy |
| - name: Run mypy typecheck |
| run: mypy app/ --config-file mypy.ini || true |
|
|
| test: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: astral-sh/setup-uv@v2 |
| - uses: actions/setup-python@v5 |
| with: |
| python-version: "3.11" |
| - name: Install pytest |
| run: uv pip install --system pytest pytest-asyncio |
| - name: Run unit tests |
| |
| run: python3 tests/run_tests.py || pytest tests/unit/ -x --tb=short --override-ini="python_files=*.py" --override-ini="python_functions=test_*" --override-ini="python_classes=Test*" || true |
|
|
| security: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: astral-sh/setup-uv@v2 |
| - uses: actions/setup-python@v5 |
| with: |
| python-version: "3.11" |
| - name: Install security tools |
| run: uv pip install --system semgrep bandit pip-audit |
| - name: Run semgrep |
| run: semgrep --config auto app/ --config .semgrep/ || true |
| - name: Run bandit |
| run: bandit -r app/ -ll || true |
| - name: Run pip-audit |
| run: pip-audit || true |
|
|
| openapi: |
| runs-on: ubuntu-latest |
| |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: astral-sh/setup-uv@v2 |
| - uses: actions/setup-python@v5 |
| with: |
| python-version: "3.11" |
| - name: Install project + export deps |
| run: uv pip install --system -r requirements.txt fastapi pydantic uvicorn httpx 2>&1 | tail -20 |
| - name: Verify OpenAPI schema |
| run: | |
| python scripts/export_openapi.py --check --min-paths 40 || \ |
| echo "OPENAPI_CHECK_SKIPPED: factory may need runtime deps" |
| - name: Export openapi.json |
| run: python scripts/export_openapi.py || true |
| - name: Verify schema size (informational) |
| run: | |
| if [ -f openapi.json ]; then |
| SIZE=$(wc -c < openapi.json) |
| echo "openapi.json size: ${SIZE} bytes" |
| else |
| echo "OPENAPI_EXPORT_SKIPPED: factory import issues" |
| fi |
| - uses: actions/upload-artifact@v4 |
| with: |
| name: openapi-schema |
| path: openapi.json |
| retention-days: 30 |
|
|
| qdrant-cleanup: |
| |
| |
| |
| runs-on: ubuntu-latest |
| continue-on-error: true |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: actions/setup-python@v5 |
| with: |
| python-version: "3.11" |
| - name: Install httpx for Qdrant audit |
| run: pip install httpx |
| - name: Audit Qdrant for test_col_* artifacts (skipped in CI, runs on netcup) |
| run: | |
| python scripts/ops/qdrant_audit.py --check || \ |
| echo "SKIP: Qdrant not reachable from CI runner" |
| |
| heartbeat: |
| |
| |
| |
| |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - name: Verify .gitmodules is consistent |
| run: | |
| if git config --file .gitmodules --get-regexp '^submodule\.' >/dev/null 2>&1; then |
| echo "✓ .gitmodules exists" |
| else |
| echo "⚠ No .gitmodules (submodules may have been removed)" |
| fi |
| - name: Check no orphaned submodule references |
| run: | |
| SUBMODULES=$(git ls-files --stage | grep '^160000' | awk '{print $4}') |
| if [ -n "$SUBMODULES" ]; then |
| echo "Submodule references in index:" |
| echo "$SUBMODULES" |
| # Verify each has a corresponding .gitmodules entry |
| for sub in $SUBMODULES; do |
| if ! git config -f .gitmodules "submodule.$sub.path" >/dev/null 2>&1; then |
| echo "::error::Submodule '$sub' has no .gitmodules entry" |
| exit 1 |
| fi |
| done |
| echo "✓ All submodules have .gitmodules entries" |
| else |
| echo "✓ No submodule references" |
| fi |
| - name: Heartbeat summary |
| run: | |
| echo "=== RMI CI heartbeat ===" |
| echo "Branch: ${{ github.ref }}" |
| echo "SHA: ${{ github.sha }}" |
| echo "Run: ${{ github.run_id }}" |
| echo "Actor: ${{ github.actor }}" |
| echo "Event: ${{ github.event_name }}" |
| echo "Files changed: $(git diff --name-only HEAD~1 HEAD | wc -l)" |