From bff869fa9d93230b23969b6305a6f228cbdc8a7b Mon Sep 17 00:00:00 2001 From: IgorVolochay Date: Tue, 1 Sep 2026 14:55:02 +0300 Subject: [PATCH] Update GitHub CI piplines --- .../{app-actions.yml => backend-ci.yml} | 38 ++-- .github/workflows/deploy-main.yml | 166 ++++++++++++++++++ .github/workflows/frontend-ci.yml | 45 +++++ .github/workflows/prebuild-ci.yml | 134 ++++++++++++++ 4 files changed, 360 insertions(+), 23 deletions(-) rename .github/workflows/{app-actions.yml => backend-ci.yml} (78%) create mode 100644 .github/workflows/deploy-main.yml create mode 100644 .github/workflows/frontend-ci.yml create mode 100644 .github/workflows/prebuild-ci.yml diff --git a/.github/workflows/app-actions.yml b/.github/workflows/backend-ci.yml similarity index 78% rename from .github/workflows/app-actions.yml rename to .github/workflows/backend-ci.yml index 157f877..db551c2 100644 --- a/.github/workflows/app-actions.yml +++ b/.github/workflows/backend-ci.yml @@ -1,4 +1,4 @@ -name: app-actions +name: Backend CI on: workflow_dispatch: @@ -6,19 +6,24 @@ on: paths: - 'app/**' branches: - - main - app + - prebuild + - main pull_request: + paths: + - 'app/**' branches: + - app + - prebuild - main - jobs: mypy: + name: Backend Lint (mypy) runs-on: ubuntu-latest continue-on-error: true steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@v4 - name: Setup Python @@ -37,19 +42,20 @@ jobs: run: mypy --ignore-missing-imports ./app pytest: + name: Backend Tests (pytest) runs-on: ubuntu-latest env: MONGO_HOST: "127.0.0.1" MONGO_PORT: ${{ secrets.MONGO_PORT || '27017' }} - MONGO_USER: ${{ secrets.MONGO_USER }} - MONGO_PASS: ${{ secrets.MONGO_PASS }} + MONGO_USER: ${{ secrets.MONGO_USER || 'admin' }} + MONGO_PASS: ${{ secrets.MONGO_PASS || 'secret' }} RABBIT_HOST: "127.0.0.1" RABBIT_PORT: ${{ secrets.RABBIT_PORT || '5672' }} - RABBIT_USER: ${{ secrets.RABBIT_USER }} - RABBIT_PASS: ${{ secrets.RABBIT_PASS }} + RABBIT_USER: ${{ secrets.RABBIT_USER || 'guest' }} + RABBIT_PASS: ${{ secrets.RABBIT_PASS || 'guest' }} DEV_MODE: ${{ secrets.DEV_MODE || 'true' }} steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@v4 - name: Setup Python @@ -97,17 +103,3 @@ jobs: - name: Run pytest run: pytest -vs - - docker-build: - runs-on: ubuntu-latest - needs: [mypy, pytest] - if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Build backend image - run: docker build -f app/dockerfile.app -t tort-backend:ci ./app - - - name: Build bot image - run: docker build -f app/dockerfile.bot -t tort-tg-bot:ci ./app \ No newline at end of file diff --git a/.github/workflows/deploy-main.yml b/.github/workflows/deploy-main.yml new file mode 100644 index 0000000..5f7cdc0 --- /dev/null +++ b/.github/workflows/deploy-main.yml @@ -0,0 +1,166 @@ +name: Publish to GHCR (Main) + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: read + packages: write + +jobs: + frontend-test-build: + name: Frontend (Test & Build) + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + working-directory: ./frontend + run: npm ci + + - name: Run frontend tests + working-directory: ./frontend + run: npm test -- --watchAll=false + + - name: Build React app + working-directory: ./frontend + run: npm run build + + backend-mypy: + name: Backend Lint (mypy) + runs-on: ubuntu-latest + continue-on-error: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: app/requirements.txt + + - name: Install dependencies + run: | + pip install mypy + pip install -r app/requirements.txt + + - name: Run mypy + run: mypy --ignore-missing-imports ./app + + backend-pytest: + name: Backend Tests (pytest) + runs-on: ubuntu-latest + env: + MONGO_HOST: "127.0.0.1" + MONGO_PORT: ${{ secrets.MONGO_PORT || '27017' }} + MONGO_USER: ${{ secrets.MONGO_USER || 'admin' }} + MONGO_PASS: ${{ secrets.MONGO_PASS || 'secret' }} + RABBIT_HOST: "127.0.0.1" + RABBIT_PORT: ${{ secrets.RABBIT_PORT || '5672' }} + RABBIT_USER: ${{ secrets.RABBIT_USER || 'guest' }} + RABBIT_PASS: ${{ secrets.RABBIT_PASS || 'guest' }} + DEV_MODE: ${{ secrets.DEV_MODE || 'true' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: app/requirements.txt + + - name: Start MongoDB + run: | + docker run -d --name mongodb \ + -p "${MONGO_PORT}:27017" \ + -e "MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}" \ + -e "MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASS}" \ + mongodb/mongodb-community-server + for i in $(seq 1 30); do + docker exec mongodb mongosh \ + --username "${MONGO_USER}" --password "${MONGO_PASS}" \ + --eval "db.runCommand({ping:1})" && break + sleep 1 + done + + - name: Start RabbitMQ + run: | + docker run -d --name rabbitmq \ + -p "${RABBIT_PORT}:5672" \ + -e "RABBITMQ_DEFAULT_USER=${RABBIT_USER}" \ + -e "RABBITMQ_DEFAULT_PASS=${RABBIT_PASS}" \ + rabbitmq:3.13-alpine + for i in $(seq 1 30); do + docker exec rabbitmq rabbitmq-diagnostics -q ping && break + sleep 1 + done + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest==8.3.4 pytest-asyncio==0.25.3 httpx==0.28.1 + pip install -r app/requirements.txt + + - name: Setup moderated base cards + working-directory: ./app/tools + run: python3 _add_base_cards.py -a 2 -f data/base_cards.json + + - name: Run pytest + run: pytest -vs + + docker-publish-ghcr: + name: Build & Push Images to GHCR + runs-on: ubuntu-latest + needs: [frontend-test-build, backend-mypy, backend-pytest] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set lowercase repository owner + id: repo_owner + run: echo "OWNER_LC=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV" + + - name: Build and push Backend image + uses: docker/build-push-action@v6 + with: + context: ./app + file: ./app/dockerfile.app + push: true + tags: | + ghcr.io/${{ env.OWNER_LC }}/tort-backend:latest + ghcr.io/${{ env.OWNER_LC }}/tort-backend:${{ github.sha }} + + - name: Build and push Bot image + uses: docker/build-push-action@v6 + with: + context: ./app + file: ./app/dockerfile.bot + push: true + tags: | + ghcr.io/${{ env.OWNER_LC }}/tort-tg-bot:latest + ghcr.io/${{ env.OWNER_LC }}/tort-tg-bot:${{ github.sha }} diff --git a/.github/workflows/frontend-ci.yml b/.github/workflows/frontend-ci.yml new file mode 100644 index 0000000..7fb77c9 --- /dev/null +++ b/.github/workflows/frontend-ci.yml @@ -0,0 +1,45 @@ +name: Frontend CI + +on: + workflow_dispatch: + push: + paths: + - 'frontend/**' + branches: + - frontend + - prebuild + - main + pull_request: + paths: + - 'frontend/**' + branches: + - frontend + - prebuild + - main + +jobs: + frontend-test-build: + name: React Test & Build + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + working-directory: ./frontend + run: npm ci + + - name: Run frontend tests + working-directory: ./frontend + run: npm test -- --watchAll=false + + - name: Build React app + working-directory: ./frontend + run: npm run build diff --git a/.github/workflows/prebuild-ci.yml b/.github/workflows/prebuild-ci.yml new file mode 100644 index 0000000..764a71a --- /dev/null +++ b/.github/workflows/prebuild-ci.yml @@ -0,0 +1,134 @@ +name: Prebuild CI & Docker Test Build + +on: + workflow_dispatch: + push: + branches: + - prebuild + pull_request: + branches: + - prebuild + +jobs: + frontend-test-build: + name: Frontend (Test & Build) + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + working-directory: ./frontend + run: npm ci + + - name: Run frontend tests + working-directory: ./frontend + run: npm test -- --watchAll=false + + - name: Build React app + working-directory: ./frontend + run: npm run build + + backend-mypy: + name: Backend Lint (mypy) + runs-on: ubuntu-latest + continue-on-error: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: app/requirements.txt + + - name: Install dependencies + run: | + pip install mypy + pip install -r app/requirements.txt + + - name: Run mypy + run: mypy --ignore-missing-imports ./app + + backend-pytest: + name: Backend Tests (pytest) + runs-on: ubuntu-latest + env: + MONGO_HOST: "127.0.0.1" + MONGO_PORT: ${{ secrets.MONGO_PORT || '27017' }} + MONGO_USER: ${{ secrets.MONGO_USER || 'admin' }} + MONGO_PASS: ${{ secrets.MONGO_PASS || 'secret' }} + RABBIT_HOST: "127.0.0.1" + RABBIT_PORT: ${{ secrets.RABBIT_PORT || '5672' }} + RABBIT_USER: ${{ secrets.RABBIT_USER || 'guest' }} + RABBIT_PASS: ${{ secrets.RABBIT_PASS || 'guest' }} + DEV_MODE: ${{ secrets.DEV_MODE || 'true' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: app/requirements.txt + + - name: Start MongoDB + run: | + docker run -d --name mongodb \ + -p "${MONGO_PORT}:27017" \ + -e "MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}" \ + -e "MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASS}" \ + mongodb/mongodb-community-server + for i in $(seq 1 30); do + docker exec mongodb mongosh \ + --username "${MONGO_USER}" --password "${MONGO_PASS}" \ + --eval "db.runCommand({ping:1})" && break + sleep 1 + done + + - name: Start RabbitMQ + run: | + docker run -d --name rabbitmq \ + -p "${RABBIT_PORT}:5672" \ + -e "RABBITMQ_DEFAULT_USER=${RABBIT_USER}" \ + -e "RABBITMQ_DEFAULT_PASS=${RABBIT_PASS}" \ + rabbitmq:3.13-alpine + for i in $(seq 1 30); do + docker exec rabbitmq rabbitmq-diagnostics -q ping && break + sleep 1 + done + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest==8.3.4 pytest-asyncio==0.25.3 httpx==0.28.1 + pip install -r app/requirements.txt + + - name: Setup moderated base cards + working-directory: ./app/tools + run: python3 _add_base_cards.py -a 2 -f data/base_cards.json + + - name: Run pytest + run: pytest -vs + + docker-test-build: + name: Docker Images Test Build (No Push) + runs-on: ubuntu-latest + needs: [frontend-test-build, backend-mypy, backend-pytest] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build Docker images (dry-run test via docker compose) + run: docker compose build