name: CI on: push: branches: [ "main" ] pull_request: branches: [ "main" ] permissions: contents: read env: PYTHON_VERSION: "3.11" # 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 # Detect runner flavor and pick cache mode - 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 # (Only needed for local cache on act_runner) - name: Prepare local Buildx cache dir if: ${{ env.ACT == 'true' }} run: mkdir -p /tmp/.buildx-cache - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: # optional: helps debugging cache issues buildkitd-flags: --debug - name: Build image (no push) uses: docker/build-push-action@v5 with: context: . tags: keywarden:ci push: false # or true, if you want to push load: false # set true if you need the image in the job afterward cache-from: ${{ env.CACHE_FROM }} cache-to: ${{ env.CACHE_TO }}