stages: - lint - test - build - deploy variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" # ---------- Backend ---------- backend:lint: stage: lint image: python:3.12-slim script: - cd backend - pip install ruff - ruff check app backend:test: stage: test image: python:3.12-slim services: - postgres:16-alpine variables: POSTGRES_USER: opora POSTGRES_PASSWORD: opora POSTGRES_DB: opora_test DATABASE_URL: postgresql+psycopg://opora:opora@postgres:5432/opora_test script: - cd backend - pip install -r requirements.txt pytest - pytest -q # ---------- Frontend ---------- frontend:lint: stage: lint image: node:20-alpine script: - cd frontend - npm install - npm run lint || true frontend:build: stage: build image: node:20-alpine script: - cd frontend - npm install - npm run build artifacts: paths: - frontend/dist # ---------- Docker images ---------- build:images: stage: build image: docker:27 services: - docker:27-dind script: - docker build -t $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHORT_SHA ./backend - docker build -t $CI_REGISTRY_IMAGE/web:$CI_COMMIT_SHORT_SHA ./frontend - docker build -t $CI_REGISTRY_IMAGE/bot:$CI_COMMIT_SHORT_SHA ./bot rules: - if: $CI_COMMIT_BRANCH == "main" # ---------- Deploy ---------- deploy:prod: stage: deploy image: alpine:3.20 before_script: - apk add --no-cache openssh-client - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - - mkdir -p ~/.ssh && ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts script: - ssh "$DEPLOY_USER@$DEPLOY_HOST" "cd /opt/opora && git pull && docker compose up -d --build" rules: - if: $CI_COMMIT_BRANCH == "main" when: manual