191 lines
6.2 KiB
YAML
191 lines
6.2 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [ "main" ]
|
|
pull_request:
|
|
branches: [ "main" ]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
PYTHON_VERSION: "3.11"
|
|
IMAGE_NAME: keywarden-api
|
|
# Used by tests / alembic; matches docker compose environment
|
|
KEYWARDEN_POSTGRES_USER: postgres
|
|
KEYWARDEN_POSTGRES_PASSWORD: postgres
|
|
KEYWARDEN_POSTGRES_HOST: localhost
|
|
KEYWARDEN_POSTGRES_PORT: 5432
|
|
KEYWARDEN_POSTGRES_DB: keywarden
|
|
jobs:
|
|
lint:
|
|
name: Lint & Format
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install linters
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install ruff==0.6.4 black==24.8.0
|
|
# - name: Ruff (lint)
|
|
# run: ruff check .
|
|
|
|
# - name: Black (format check)
|
|
# run: black --check .
|
|
|
|
test:
|
|
name: Tests (Pytest + Alembic + Postgres)
|
|
runs-on: ubuntu-latest
|
|
needs: lint
|
|
services:
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
env:
|
|
POSTGRES_DB: keywarden
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd="pg_isready -U postgres -d keywarden"
|
|
--health-interval=10s
|
|
--health-timeout=5s
|
|
--health-retries=10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Cache pip
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/pip
|
|
key: pip-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/requirements*.txt', 'pyproject.toml') }}
|
|
restore-keys: |
|
|
pip-${{ runner.os }}-${{ env.PYTHON_VERSION }}-
|
|
|
|
- name: Install deps
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
# optional: extras/dev
|
|
if [ -f pyproject.toml ]; then pip install -e .[dev] || pip install -e . ; fi
|
|
|
|
- name: Set PYTHONPATH
|
|
run: echo "PYTHONPATH=${GITHUB_WORKSPACE}" >> $GITHUB_ENV
|
|
|
|
# Gitea ACT Runner needs this for some reason.
|
|
- name: Select Postgres host for runner
|
|
run: |
|
|
if [ "${ACT:-}" = "true" ]; then
|
|
echo "KEYWARDEN_POSTGRES_HOST=postgres" >> "$GITHUB_ENV" # Gitea (act_runner)
|
|
else
|
|
echo "KEYWARDEN_POSTGRES_HOST=127.0.0.1" >> "$GITHUB_ENV" # GitHub Actions
|
|
fi
|
|
|
|
- name: Echo DB target
|
|
run: echo "DB → ${KEYWARDEN_POSTGRES_HOST:-unset}:${{ env.KEYWARDEN_POSTGRES_PORT }}"
|
|
|
|
# Explicit wait (removes race on act_runner)
|
|
- name: Wait for Postgres
|
|
run: |
|
|
for i in {1..60}; do
|
|
python - <<'PY'
|
|
import os, socket, sys
|
|
h=os.environ.get("KEYWARDEN_POSTGRES_HOST","127.0.0.1"); p=int(os.environ.get("KEYWARDEN_POSTGRES_PORT","5432"))
|
|
s=socket.socket(); s.settimeout(1)
|
|
try:
|
|
s.connect((h,p)); print("Postgres is up:", h,p); sys.exit(0)
|
|
except Exception as e:
|
|
print("waiting:", e); sys.exit(1)
|
|
finally:
|
|
s.close()
|
|
PY
|
|
if [ $? -eq 0 ]; then break; fi
|
|
sleep 2
|
|
done
|
|
|
|
- name: Run Alembic migrations
|
|
env:
|
|
KEYWARDEN_POSTGRES_USER: ${{ env.KEYWARDEN_POSTGRES_USER }}
|
|
KEYWARDEN_POSTGRES_PASSWORD: ${{ env.KEYWARDEN_POSTGRES_PASSWORD }}
|
|
KEYWARDEN_POSTGRES_HOST: ${{ env.KEYWARDEN_POSTGRES_HOST }}
|
|
KEYWARDEN_POSTGRES_PORT: ${{ env.KEYWARDEN_POSTGRES_PORT }}
|
|
KEYWARDEN_POSTGRES_DB: ${{ env.KEYWARDEN_POSTGRES_DB }}
|
|
KEYWARDEN_POSTGRES_SSL: ${{ env.KEYWARDEN_POSTGRES_SSL }}
|
|
run: alembic upgrade head
|
|
|
|
- name: Pytest
|
|
env:
|
|
KEYWARDEN_POSTGRES_USER: ${{ env.KEYWARDEN_POSTGRES_USER }}
|
|
KEYWARDEN_POSTGRES_PASSWORD: ${{ env.KEYWARDEN_POSTGRES_PASSWORD }}
|
|
KEYWARDEN_POSTGRES_HOST: ${{ env.KEYWARDEN_POSTGRES_HOST }}
|
|
KEYWARDEN_POSTGRES_PORT: ${{ env.KEYWARDEN_POSTGRES_PORT }}
|
|
KEYWARDEN_POSTGRES_DB: ${{ env.KEYWARDEN_POSTGRES_DB }}
|
|
KEYWARDEN_POSTGRES_SSL: ${{ env.KEYWARDEN_POSTGRES_SSL }}
|
|
run: |
|
|
pytest -q tests
|
|
docker-build:
|
|
name: Docker Build
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
# Choose Buildx cache backend: gha on GitHub, local on act_runner
|
|
- name: Select Buildx cache backend
|
|
run: |
|
|
if [ "${ACT:-}" = "true" ]; then
|
|
echo "CACHE_TO=type=local,dest=/tmp/.buildx-cache,mode=max" >> $GITHUB_ENV
|
|
echo "CACHE_FROM=type=local,src=/tmp/.buildx-cache" >> $GITHUB_ENV
|
|
else
|
|
echo "CACHE_TO=type=gha,mode=max" >> $GITHUB_ENV
|
|
echo "CACHE_FROM=type=gha" >> $GITHUB_ENV
|
|
fi
|
|
|
|
- name: Prepare local cache dir (act_runner only)
|
|
if: ${{ env.ACT == 'true' }}
|
|
run: mkdir -p /tmp/.buildx-cache
|
|
|
|
- name: Set image reference (Gitea)
|
|
run: |
|
|
echo "GT_IMAGE=${{ secrets.GITEA_REGISTRY }}/${{ secrets.GITEA_NAMESPACE }}/${{ env.IMAGE_NAME }}" >> $GITHUB_ENV
|
|
|
|
- name: Set up QEMU (optional)
|
|
uses: docker/setup-qemu-action@v3
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Set image reference
|
|
run: echo "GT_IMAGE=${{ secrets.REGISTRY_HOST }}/${{ secrets.REGISTRY_NAMESPACE }}/${{ env.IMAGE_NAME }}" >> $GITHUB_ENV
|
|
|
|
- name: Login to registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ secrets.REGISTRY_HOST }}
|
|
username: ${{ secrets.REGISTRY_USER }}
|
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
|
|
|
- name: Build & push
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
push: true
|
|
tags: |
|
|
${{ env.GT_IMAGE }}:${{ github.ref_name }}
|
|
${{ env.GT_IMAGE }}:sha-${{ github.sha }}
|
|
${{ env.GT_IMAGE }}:latest |