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
198 changes: 198 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
name: CI Quality Gates

on:
push:
branches: [ main, develop, 'feat/*', 'fix/*' ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# Stage 1: Release & Link Integrity Gate
release-verification:
name: Stage 1 - Release & Link Integrity Gate
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Run Version Synchronization & Link Integrity Gate
run: python3 scripts/verify_release.py --ci

# Stage 2A: Backend Build, Tests & Coverage
test-backend:
name: Stage 2A - Backend Build, Tests & Coverage (Python 3.12)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt pytest-cov

- name: Run Pytest Suite with Coverage
env:
AUTH_ENABLED: "false"
VECTOR_STORE_PROVIDER: "chroma"
CHROMA_STORAGE_PATH: "/tmp/chroma_test"
LOCAL_STORAGE_PATH: "/tmp/storage_test"
run: |
pytest -v --cov=app --cov-report=xml:coverage/python-coverage.xml --cov-report=term-missing

- name: Upload Backend Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: backend-coverage-report
path: coverage/python-coverage.xml

# Stage 2B: Frontend Quality, Lint & Tests
test-frontend:
name: Stage 2B - Frontend Quality & Layout (Node 22)
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
run: npm ci

- name: Run Linter
run: npm run lint

- name: Run TypeScript Type Check
run: npx tsc -b

- name: Build Frontend Bundle
run: npm run build

- name: Run Vitest Unit & Component Tests
run: npm run test:coverage

- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium

- name: Run Playwright Layout Inspector Audits
run: npm run test:layout

# Stage 2C: Documentation Quality & VitePress Build
test-docs:
name: Stage 2C - Documentation Quality & VitePress Build (Node 22)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
cache-dependency-path: package-lock.json

- name: Install dependencies
run: npm ci

- name: Build VitePress Documentation
run: npm run docs:build

# Stage 3: Fullstack Integration Smoke Gate
smoke:
name: Stage 3 - Fullstack Integration Smoke Gate
runs-on: ubuntu-latest
needs: [release-verification, test-backend, test-frontend, test-docs]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'

- name: Set up Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install backend dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Install and build frontend
run: |
cd frontend
npm ci
npm run build
cd ..

- name: Start ContextCortex Server & Probe Health
env:
AUTH_ENABLED: "false"
VECTOR_STORE_PROVIDER: "chroma"
CHROMA_STORAGE_PATH: "/tmp/smoke_chroma"
LOCAL_STORAGE_PATH: "/tmp/smoke_storage"
DATABASE_URL: "sqlite:////tmp/smoke_cache.db"
run: |
python3 main.py &
SERVER_PID=$!
echo "Started ContextCortex server with PID $SERVER_PID"

echo "Polling health check endpoint..."
SUCCESS=0
for i in {1..30}; do
if curl -s -f http://localhost:3000/healthz > /tmp/health_response.json; then
echo "✅ Health check responded with HTTP 200:"
cat /tmp/health_response.json
SUCCESS=1
break
fi
echo "Waiting for server to become ready ($i/30)..."
sleep 1
done

if [ $SUCCESS -ne 1 ]; then
echo "❌ Health check timed out!"
kill -9 $SERVER_PID 2>/dev/null || true
exit 1
fi

echo "Verifying RFC 9728 OAuth discovery endpoint..."
curl -s -f http://localhost:3000/.well-known/oauth-protected-resource || exit 1
echo "✅ RFC 9728 metadata verified."

echo "Gracefully terminating smoke server..."
kill $SERVER_PID 2>/dev/null || true
wait $SERVER_PID 2>/dev/null || true
echo "🎉 Stage 3 Fullstack Smoke Gate passed successfully."
37 changes: 37 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: CodeQL Analysis

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: CodeQL Security Analysis
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
strategy:
fail-fast: false
matrix:
language: [ 'python', 'javascript-typescript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
60 changes: 60 additions & 0 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Deploy VitePress Documentation to GitHub Pages

on:
push:
branches: [main]
paths:
- 'docs/**'
- 'package.json'
- '.github/workflows/deploy-docs.yml'
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Setup Pages
uses: actions/configure-pages@v5

- name: Install Dependencies
run: npm ci

- name: Build VitePress Documentation
run: npm run docs:build

- name: Upload Pages Artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/.vitepress/dist

deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ venv/
.pytest_cache/
htmlcov/
*.log
node_modules/
.vitepress/dist/
.vitepress/cache/
dist/
7 changes: 7 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -556,3 +556,10 @@ erDiagram
AST_SYMBOLS ||--o{ AST_RELATIONSHIPS : "source"
```

---

## 📚 Documentation Reference

This architecture specification complies with the **ASD-STE100 Simplified Technical English (Issue 9)** standard.

Interactive system design diagrams, sequence flows, and component layouts are available on the [VitePress Documentation Site](https://spelech.github.io/contextcortex/architecture/).
12 changes: 12 additions & 0 deletions DEVELOPER_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ python3 scripts/generate_requirements.py
pytest -v tests/backend/test_requirements_sync.py
```

### VitePress Documentation Site (ASD-STE100 Compliant)
```bash
# Start local documentation dev server
npm run docs:dev

# Build production static documentation site
npm run docs:build

# Preview built production documentation site
npm run docs:preview
```

---

## ⚙️ Configuration Variables
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,13 @@ curl -X POST http://localhost:3000/admin/api/auth/keys \

## 📚 Documentation & Specifications

- [**Software Requirements Specification (`REQUIREMENTS.md`)**](REQUIREMENTS.md): Authoritative functional and non-functional requirements with test-traceability matrix and Mermaid ERD data models.
The documentation follows the **ASD-STE100 Simplified Technical English (Issue 9)** standard for maximum clarity and technical precision.

- [**Interactive Documentation Site (VitePress)**](https://spelech.github.io/contextcortex/): Complete user guide with component screenshots, interactive Mermaid architecture diagrams, REST API reference, and software requirements specification.
- Run locally: `npm run docs:dev`
- Build static site: `npm run docs:build`
- Preview production build: `npm run docs:preview`
- [**Software Requirements Specification (`REQUIREMENTS.md`)**](REQUIREMENTS.md): Authoritative functional and non-functional requirements with test traceability matrix and Mermaid ERD data models.
- [**System Architecture (`ARCHITECTURE.md`)**](ARCHITECTURE.md): FastMCP 2.0 transport topologies, component interaction diagrams, SQLAlchemy 2.0 schema ERD, and vector store data models.
- [**Developer Documentation (`DEVELOPER_DOCS.md`)**](DEVELOPER_DOCS.md): Setup, configuration, development workflow, and testing guidelines.
- [**Test Coverage Reports (`docs/TEST_COVERAGE.md`)**](docs/TEST_COVERAGE.md): Pytest, Vitest, and Playwright verification metrics.
Expand Down
8 changes: 8 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@

if "QDRANT_URL" not in os.environ:
os.environ["QDRANT_URL"] = "http://localhost:8010"


@pytest.fixture(autouse=True)
def stop_background_poller():
from app.services.poller import stop_poller_daemon
stop_poller_daemon()
yield
stop_poller_daemon()
Loading
Loading