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
86 changes: 81 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,54 @@
name: CI

on:
workflow_dispatch:
pull_request:
branches: [main, develop]
push:
branches: [main, develop]

env:
JWT_SECRET: ci-test-secret-key-1234567890
ENCRYPTION_KEY: ci-test-encryption-key-1234567890abcdef

jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

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

- name: Run Ruff
run: python -m ruff check backend tests

- name: Run mypy
run: python -m mypy backend

- name: Run dependency audit
run: python -m pip_audit

- name: Export OpenAPI spec
run: python scripts/export_openapi.py

#- name: Set up Helm
# uses: azure/setup-helm@v4

#- name: Lint Helm chart
# run: helm lint ./helm/graphql-meter --set secret.jwtSecret=ci-chart-secret-1234567890

test:
runs-on: ubuntu-latest
needs: quality
strategy:
matrix:
python-version: ["3.12", "3.13", "3.14"]
Expand All @@ -19,6 +59,7 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip

- name: Install dependencies
run: |
Expand All @@ -27,9 +68,6 @@ jobs:

- name: Run tests
run: python -m pytest tests/ -q --tb=short
env:
JWT_SECRET: ci-test-secret-key-1234567890
ENCRYPTION_KEY: ci-test-encryption-key-1234567890abcdef

build:
runs-on: ubuntu-latest
Expand All @@ -41,13 +79,19 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

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

- name: Download vendor libraries
run: python -c "from backend.vendor_manager import ensure_vendor_libs; ensure_vendor_libs()"

- name: Export OpenAPI spec
run: python scripts/export_openapi.py

- name: Build wheel and sdist
run: python -m build

Expand All @@ -62,4 +106,36 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
path: |
dist/
reference/openapi.json

trivy-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Install dependencies (for lock generation)
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Generate pip freeze lock
run: pip freeze > requirements.lock

- name: Run Trivy vulnerability scan (filesystem)
uses: aquasecurity/trivy-action@v0.35.0
with:
scan-type: fs
scan-ref: .
format: table
exit-code: "1"
severity: CRITICAL,HIGH
ignore-unfixed: true
scanners: vuln
87 changes: 66 additions & 21 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Release

on:
workflow_dispatch:
push:
tags:
- "v*"
Expand All @@ -9,9 +10,12 @@ permissions:
contents: write
packages: write

env:
JWT_SECRET: ci-test-secret-key-1234567890
ENCRYPTION_KEY: ci-test-encryption-key-1234567890abcdef

jobs:
# ── Validate ──────────────────────────────────────────────
test:
quality-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -20,19 +24,24 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

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

- name: Run Ruff
run: python -m ruff check backend tests

- name: Run dependency audit
run: python -m pip_audit

- name: Run tests
run: python -m pytest tests/ -q --tb=short
env:
JWT_SECRET: ci-test-secret-key-1234567890
ENCRYPTION_KEY: ci-test-encryption-key-1234567890abcdef

# ── Build artifacts ───────────────────────────────────────
build-wheel:
needs: test
needs: quality-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -41,13 +50,19 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

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

- name: Download vendor libraries
run: python -c "from backend.vendor_manager import ensure_vendor_libs; ensure_vendor_libs()"

- name: Export OpenAPI spec
run: python scripts/export_openapi.py

- name: Build
run: python -m build

Expand All @@ -60,10 +75,12 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
path: |
dist/
reference/openapi.json

build-windows:
needs: test
needs: quality-check
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -72,10 +89,11 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -e ".[dev]"
pip install pyinstaller

- name: Download vendor libraries
Expand All @@ -90,8 +108,8 @@ jobs:
name: windows-exe
path: dist/graphql-meter.exe

# ── Publish GitHub Release ────────────────────────────────
publish-github:
if: startsWith(github.ref, 'refs/tags/')
needs: [build-wheel, build-windows]
runs-on: ubuntu-latest
steps:
Expand All @@ -107,22 +125,34 @@ jobs:
name: windows-exe
path: windows/

- name: Set up Helm
uses: azure/setup-helm@v4

- name: Package Helm chart
run: |
VERSION="${GITHUB_REF_NAME#v}"
sed -i "s/^version: .*/version: ${VERSION}/" helm/graphql-meter/Chart.yaml
sed -i "s/^appVersion: .*/appVersion: \"${VERSION}\"/" helm/graphql-meter/Chart.yaml
mkdir -p release-assets
helm package ./helm/graphql-meter --destination release-assets/

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
dist/*
windows/graphql-meter.exe
release-assets/*.tgz


# ── Publish Docker ────────────────────────────────────────
publish-docker:
needs: test
if: startsWith(github.ref, 'refs/tags/')
needs: quality-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

# 1. Add QEMU for multi-platform support (REQUIRED)
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand All @@ -145,7 +175,7 @@ jobs:
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
type=raw,value=latest
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}

- name: Build and push
uses: docker/build-push-action@v6
Expand All @@ -155,7 +185,22 @@ jobs:
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
#cache-from: type=gha
#cache-to: type=gha,mode=max
#cache-from: type=gha
#cache-to: type=gha,mode=max
cache-from: type=gha
cache-to: type=gha,mode=max

#publish-pypi:
# if: ${{ secrets.PYPI_API_TOKEN != '' }}
# needs: build-wheel
# runs-on: ubuntu-latest
# permissions:
# contents: read
# steps:
# - uses: actions/download-artifact@v4
# with:
# name: dist
# path: dist/

# - name: Publish to PyPI
# uses: pypa/gh-action-pypi-publish@release/v1
# with:
# password: ${{ secrets.PYPI_API_TOKEN }}
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.13
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-merge-conflict
8 changes: 5 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# ── Stage 1: k6 binary ──────────────────────────────────────
FROM grafana/k6:0.54.0 AS k6

# ── Stage 2: Build wheels ───────────────────────────────────
# ── Stage 2: Build runtime env from pyproject ───────────────
FROM python:3.12-slim AS builder

WORKDIR /tmp
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY pyproject.toml README.md ./
COPY backend/ backend/
COPY frontend/ frontend/
RUN pip install --no-cache-dir .

# ── Stage 3: Runtime ────────────────────────────────────────
FROM python:3.12-slim
Expand Down
38 changes: 38 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.PHONY: install run test lint typecheck security openapi build clean lock migrate

PYTHON ?= .venv/bin/python
PIP_AUDIT ?= $(PYTHON) -m pip_audit

install:
$(PYTHON) -m pip install --upgrade pip
$(PYTHON) -m pip install -e ".[dev]"

run:
$(PYTHON) backend/app.py

test:
$(PYTHON) -m pytest tests/ -q --tb=short

lint:
$(PYTHON) -m ruff check backend tests

typecheck:
$(PYTHON) -m mypy backend

security:
$(PIP_AUDIT)

openapi:
$(PYTHON) scripts/export_openapi.py

build:
$(PYTHON) -m build

clean:
find . -type d \( -name __pycache__ -o -name .pytest_cache -o -name .ruff_cache \) -prune -exec rm -rf {} +

lock:
$(PYTHON) -m pip freeze > requirements.lock

migrate:
$(PYTHON) -m alembic upgrade head
Loading
Loading