Files
Louis King 3593d14878 feat(api): make Redis a required cache dependency
Redis becomes mandatory infrastructure (PostgreSQL-parity): the
REDIS_ENABLED flag, NullCache backend, and every conditional caching
code path are removed. /health/ready reports not_ready (503) when
Redis is unreachable and cached endpoints return 503 instead of
silently degrading; invalidation helpers never raise after a
committed write.

The bundled redis container joins the core profile only via
docker-compose.dev.yml (production points REDIS_* at an external
instance, same no-shadowing pattern as postgres), the backend suite
runs against real Redis (test-redis on 127.0.0.1:55433, CI redis:8
service container, per-xdist-worker key prefixes), and operator docs
describe the required-dependency setup (upgrading.md gains the
v0.20.0 section).
2026-08-30 21:51:51 +01:00

258 lines
6.1 KiB
YAML

name: CI
on:
push:
branches: [main]
paths-ignore:
- "**/*.md"
- "docs/**"
- ".env.example"
- "LICENSE"
- "FUNDING.yml"
pull_request:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version-file: ".python-version"
cache: pip
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- name: Install frontend deps
run: npm ci
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
frontend:
name: Frontend
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- name: Install dependencies
run: npm ci
- name: Typecheck
run: npx tsc --noEmit
- name: Unit tests
run: npm run test:frontend
- name: Upload test results
uses: actions/upload-artifact@v7
if: always()
with:
name: vitest-results
path: vitest-junit.xml
retention-days: 14
- name: Build
run: npm run build
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 30
services:
postgres:
# Pinned to match the bundled postgres:17-alpine in docker-compose.yml
image: postgres:17
env:
POSTGRES_USER: meshcorehub
POSTGRES_PASSWORD: meshcorehub-test
POSTGRES_DB: meshcorehub_test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U meshcorehub -d meshcorehub_test"
--health-interval 5s
--health-timeout 5s
--health-retries 10
redis:
# Pinned to match the bundled redis:8-alpine in docker-compose.yml
image: redis:8
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 5s
--health-retries 10
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version-file: ".python-version"
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run tests with pytest
env:
TEST_POSTGRES_URL: postgresql+psycopg2://meshcorehub:meshcorehub-test@localhost:5432/meshcorehub_test
TEST_REDIS_URL: redis://localhost:6379/0
run: |
pytest -nauto --cov=meshcore_hub --cov-report=xml --cov-report=term-missing --junitxml=junit.xml -o junit_family=legacy
- name: Upload test results
uses: actions/upload-artifact@v7
if: always()
with:
name: pytest-results
path: |
junit.xml
coverage.xml
retention-days: 14
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v7
if: always()
with:
files: ./coverage.xml
fail_ci_if_error: false
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
uses: codecov/codecov-action@v7
if: ${{ !cancelled() }}
with:
report_type: test_results
token: ${{ secrets.CODECOV_TOKEN }}
e2e:
name: E2E (Playwright)
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version-file: ".python-version"
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- name: Install frontend deps
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Set up Python env for mint_session.py
run: |
python -m venv .venv
.venv/bin/pip install itsdangerous
- name: Build e2e stack
run: docker compose -f e2e/docker-compose.test.yml build
- name: Start e2e stack
run: docker compose -f e2e/docker-compose.test.yml up -d --wait
- name: Run E2E tests
run: npm run test:e2e
- name: Upload Playwright report
uses: actions/upload-artifact@v7
if: always()
with:
name: playwright-report
path: |
e2e/playwright-report/
e2e/test-results/
e2e/junit.xml
retention-days: 14
build:
name: Build Package
runs-on: ubuntu-latest
timeout-minutes: 15
needs: [lint, test]
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version-file: ".python-version"
cache: pip
- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
name: dist
path: dist/
summary:
name: Summary
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [lint, frontend, test, e2e, build]
if: ${{ !cancelled() }}
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version-file: ".python-version"
- name: Download artifacts
uses: actions/download-artifact@v8
continue-on-error: true
with:
path: results
- name: Render CI summary
env:
NEEDS_JSON: ${{ toJson(needs) }}
run: python .github/scripts/ci_summary.py