-
Notifications
You must be signed in to change notification settings - Fork 0
141 lines (133 loc) · 4.89 KB
/
Copy pathci-backend.yml
File metadata and controls
141 lines (133 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Backend CI — lint, strict type-check, unit + integration tests, coverage.
#
# Fast jobs (lint, type-check) run in parallel with the heavier test job so
# feedback on a PR is quick. The test job runs unit/in-memory tests first, then
# the testcontainers-backed integration suite (real Postgres in Docker), and
# merges coverage for Codecov.
name: Backend CI
on:
push:
branches: [master]
paths:
- 'backend/**'
- '.github/workflows/ci-backend.yml'
pull_request:
paths:
- 'backend/**'
- '.github/workflows/ci-backend.yml'
workflow_dispatch:
# Least privilege: this workflow only needs to read the repo.
permissions:
contents: read
# Cancel superseded runs on the same ref to save CI minutes.
concurrency:
group: backend-ci-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
working-directory: backend
env:
# create_app() runs at import time and refuses to boot outside DEBUG with the
# default SECRET_KEY; it also mkdir()s UPLOAD_DIR. These make it CI-bootable
# without a real secret or the non-writable /app/uploads default.
DEBUG: "true"
SECRET_KEY: "ci-not-a-real-secret-key-change-in-prod"
UPLOAD_DIR: /tmp/forum-uploads
jobs:
lint:
name: Ruff (lint + format)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: backend/uv.lock
- name: Install dependencies
run: uv sync --frozen
- name: Ruff lint
run: uv run ruff check --output-format=github .
- name: Ruff format check
run: uv run ruff format --check .
type-check:
name: Mypy (strict)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: backend/uv.lock
- name: Install dependencies
run: uv sync --frozen
- name: Mypy
run: uv run mypy app/
test:
name: Pytest + coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install libmagic (python-magic runtime dependency)
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libmagic1
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: backend/uv.lock
- name: Install dependencies (incl. dev/test group)
run: uv sync --frozen
- name: Unit & in-memory tests
run: >
uv run pytest -m "not integration"
--cov=app --cov-report=xml:coverage-unit.xml --cov-report=term-missing
--junitxml=junit-unit.xml -o junit_family=legacy
- name: Integration tests (testcontainers Postgres)
run: >
uv run pytest tests/integration -m integration
--cov=app --cov-append --cov-report=xml:coverage-integration.xml
--junitxml=junit-integration.xml -o junit_family=legacy
- name: Upload coverage to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: backend/coverage-unit.xml,backend/coverage-integration.xml
flags: backend
# Never fail the build because the coverage upload had a hiccup.
fail_ci_if_error: false
- name: Upload test results to Codecov (Test Analytics)
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: backend/junit-unit.xml,backend/junit-integration.xml
flags: backend
# Parse coverage + JUnit into a per-module Markdown summary. It is written
# to the run's job summary (visible in the Actions UI) and injected into
# README.md between the TEST-SUMMARY markers. coverage-integration.xml is
# cumulative (the integration step ran with --cov-append) so it carries
# both suites; if integration was skipped we fall back to the unit report.
- name: Generate test & coverage summary
if: ${{ !cancelled() }}
working-directory: ${{ github.workspace }}
run: |
COV=backend/coverage-integration.xml
[ -f "$COV" ] || COV=backend/coverage-unit.xml
python scripts/test_summary.py \
--coverage "$COV" \
--junit backend/junit-unit.xml backend/junit-integration.xml \
--readme README.md
- name: Upload summary + reports as artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: backend-test-summary
path: |
README.md
backend/coverage-unit.xml
backend/coverage-integration.xml
backend/junit-unit.xml
backend/junit-integration.xml
if-no-files-found: ignore