-
-
Notifications
You must be signed in to change notification settings - Fork 0
153 lines (148 loc) · 5.8 KB
/
Copy pathserver-ci.yaml
File metadata and controls
153 lines (148 loc) · 5.8 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
142
143
144
145
146
147
148
149
150
151
152
153
name: server-ci
on:
push:
paths:
- "server/**"
- ".github/workflows/server-ci.yaml"
- "core/identity/src/test/resources/identity/**"
pull_request:
paths:
- "server/**"
- ".github/workflows/server-ci.yaml"
- "core/identity/src/test/resources/identity/**"
# Cancel superseded runs on the same branch / PR.
concurrency:
group: server-ci-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
mode: [full, sync_only, ai_only]
defaults:
run:
working-directory: server
env:
# Deploy mode matrix: each cell exports the env vars that gate the app.
# Tests that depend on a specific mode (lazy-imports, modes, readyz)
# parameterize their own expectations; mode-agnostic tests run in every
# cell to surface any regression that only shows up under a non-default
# configuration.
QUIRE_SERVER_PROGRESS_ENABLED: ${{ matrix.mode != 'ai_only' && 'true' || 'false' }}
QUIRE_SERVER_AI_ENABLED: ${{ matrix.mode != 'sync_only' && 'true' || 'false' }}
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
- name: Set up Python
run: uv python install 3.12
- name: Install
run: |
uv venv
uv pip install -e ".[dev]"
- name: Lint
if: matrix.mode == 'full'
run: uv run ruff check . && uv run ruff format --check .
- name: Install ripgrep (rename guard)
if: matrix.mode == 'full'
run: |
if ! command -v rg >/dev/null; then
sudo apt-get update && sudo apt-get install -y ripgrep
fi
- name: Rename guard self-test
if: matrix.mode == 'full'
working-directory: ${{ github.workspace }}
run: |
set -e
# Proves the rename-guard regex catches the previously-missed
# OPDS_SYNC_FOO pattern (the v1 plan's regex relied on \b after
# `_`, which is not a word boundary before letters).
tmp=$(mktemp /tmp/rename-guard-self-test-XXXX.txt)
printf 'OPDS_SYNC_AI_ENABLED: true\n' > "$tmp"
if ! rg -P '\bopds[-_]sync\b|(?<![A-Z0-9_])OPDS_SYNC_[A-Z0-9_]*' "$tmp" >/dev/null; then
echo "::error::Rename guard regex failed self-test (did NOT match OPDS_SYNC_AI_ENABLED)."
rm -f "$tmp"
exit 1
fi
rm -f "$tmp"
- name: Rename guard
if: matrix.mode == 'full'
working-directory: ${{ github.workspace }}
run: |
set -o pipefail
# Lock #20 allowlist:
# .claude/, CHANGELOG.md, server/migrations/versions/,
# root README.md, server/docker-compose*.yml,
# server/alembic.ini, server/.env.example (DB-name / deprecation refs).
# Defensive: tests/conftest.py + the import-graph regression test
# reference the legacy names by design.
if rg -n -P '\bopds[-_]sync\b|(?<![A-Z0-9_])OPDS_SYNC_[A-Z0-9_]*' \
-g '!.claude/**' \
-g '!CHANGELOG.md' \
-g '!server/migrations/versions/*.py' \
-g '!server/quire_server/config.py' \
-g '!server/docker-compose.yml' \
-g '!server/docker-compose.full.yml' \
-g '!server/alembic.ini' \
-g '!server/migrations/env.py' \
-g '!server/tests/conftest.py' \
-g '!server/tests/unit/test_no_stale_opds_sync_imports.py' \
. ; then
echo "::error::Rename guard found un-allowlisted OPDS_SYNC / opds-sync / opds_sync references."
exit 1
fi
- name: Test
run: uv run pytest -v
image:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
- uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: server
push: true
sbom: true
provenance: mode=max
tags: |
ghcr.io/${{ github.repository_owner }}/quire-server:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/quire-server:latest
scan:
# SARIF upload requires Code Scanning enabled, which is free on
# public repos and gated behind GitHub Advanced Security on private
# ones. Skip until the repo is public.
needs: image
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event.repository.visibility == 'public'
permissions:
contents: read
actions: read
packages: read
security-events: write
steps:
- uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0
with:
image-ref: ghcr.io/${{ github.repository_owner }}/quire-server:${{ github.sha }}
format: sarif
output: trivy.sarif
severity: HIGH,CRITICAL
ignore-unfixed: true
- uses: github/codeql-action/upload-sarif@7c1e4cf0b20d7c1872b26569c00ba908797a59bf # v4
with:
sarif_file: trivy.sarif