name: CI/CD Pipeline on: push: branches: - dev - 'feature/**' - 'codex/**' pull_request: branches: - dev workflow_dispatch: concurrency: group: anal-front-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true env: WEB_IMAGE: 'anal-front-web' DEPLOY_DOMAIN: 'anal.dev.nii-ecos.ru' DEPLOY_PATH: '/opt/anal-front' jobs: quality: name: Quality Gate runs-on: [frontend, ubuntu-latest] timeout-minutes: 120 env: PLAYWRIGHT_BROWSERS_PATH: /root/.cache/ms-playwright steps: - name: Checkout code uses: actions/checkout@v4.2.2 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.9 - name: Cache Bun dependencies uses: actions/cache@v4 with: path: | /root/.bun/install/cache node_modules key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | ${{ runner.os }}-${{ runner.arch }}-bun- - name: Install dependencies run: bun install --frozen-lockfile - name: Generate API clients run: bun run apigen - name: Lint check run: bun run lint - name: Type check run: bun run typecheck - name: Unit tests run: bun run test:unit - name: Build run: bun run build - name: Resolve Playwright version id: playwright-version run: | version="$(bunx playwright --version | awk '{ print $2 }')" echo "version=${version}" >> "${GITHUB_OUTPUT}" - name: Cache Playwright browsers id: playwright-cache uses: actions/cache@v4 with: path: /root/.cache/ms-playwright key: ${{ runner.os }}-${{ runner.arch }}-playwright-${{ steps.playwright-version.outputs.version }} - name: Install Playwright system deps run: bunx playwright install-deps chromium - name: Install Playwright browsers if: steps.playwright-cache.outputs.cache-hit != 'true' run: bunx playwright install chromium - name: E2E env: CI: '1' PLAYWRIGHT_HTML_OPEN: never run: bun run test:e2e -- --reporter=line - name: Docker build run: docker build --pull -t analytical-panel-frontend:ci . deploy_dev: name: Build and Deploy Dev via Compose runs-on: [frontend, ubuntu-latest] timeout-minutes: 45 needs: [quality] if: | ( github.event_name == 'push' && github.ref == 'refs/heads/dev' && needs.quality.result == 'success' && !contains(github.event.head_commit.message, '#no_deploy') ) || ( github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/dev' && needs.quality.result == 'success' ) steps: - name: Checkout code run: | set -euo pipefail REPO_URL=$(echo "${GITHUB_SERVER_URL}" | sed "s|://|://oauth2:${{ gitea.token }}@|") BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" git -c core.hooksPath=/dev/null clone --depth=1 --branch="${BRANCH}" "${REPO_URL}/${GITHUB_REPOSITORY}.git" . git -c core.hooksPath=/dev/null checkout "${GITHUB_SHA}" - name: Build image on deployment host env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }} DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_SSH_KEY_B64: ${{ secrets.DEPLOY_SSH_KEY_B64 }} run: | set -euo pipefail SHA_SHORT="$(printf '%s' "${GITHUB_SHA}" | cut -c1-7)" WEB_REF="${WEB_IMAGE}:dev-${SHA_SHORT}" DEPLOY_HOST="${DEPLOY_HOST:-10.10.0.124}" DEPLOY_USER="${DEPLOY_USER:-ecos-deploy}" DEPLOY_PORT="${DEPLOY_PORT:-22}" mkdir -p ~/.ssh if [[ -n "${DEPLOY_SSH_KEY_B64:-}" ]]; then printf '%s' "$DEPLOY_SSH_KEY_B64" | base64 -d > ~/.ssh/ecos_deploy_key elif [[ -n "${DEPLOY_SSH_KEY:-}" ]]; then printf '%s' "$DEPLOY_SSH_KEY" > ~/.ssh/ecos_deploy_key elif [[ -f /root/.ssh/ci-key ]]; then cp /root/.ssh/ci-key ~/.ssh/ecos_deploy_key elif [[ -f ~/.ssh/ci-key ]]; then cp ~/.ssh/ci-key ~/.ssh/ecos_deploy_key else echo "Deploy SSH key is not configured" >&2 exit 1 fi chmod 0600 ~/.ssh/ecos_deploy_key ssh-keyscan -p "$DEPLOY_PORT" -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null ssh_base=( ssh -i ~/.ssh/ecos_deploy_key -p "$DEPLOY_PORT" "$DEPLOY_USER@$DEPLOY_HOST" ) scp_base=( scp -i ~/.ssh/ecos_deploy_key -P "$DEPLOY_PORT" ) "${ssh_base[@]}" "mkdir -p '$DEPLOY_PATH/releases'" "${scp_base[@]}" deploy/anal-front/compose.yml "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/compose.yml" "${scp_base[@]}" deploy/anal-front/deploy.sh "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/deploy.sh" tar \ --exclude=.git \ --exclude=node_modules \ --exclude=dist \ --exclude=playwright-report \ --exclude=test-results \ --exclude=.bun \ -cf - . \ | "${ssh_base[@]}" "rm -rf '$DEPLOY_PATH/build-src.tmp' && mkdir -p '$DEPLOY_PATH/build-src.tmp' && tar -xf - -C '$DEPLOY_PATH/build-src.tmp' && rm -rf '$DEPLOY_PATH/build-src' && mv '$DEPLOY_PATH/build-src.tmp' '$DEPLOY_PATH/build-src'" "${ssh_base[@]}" "chmod 0750 '$DEPLOY_PATH/deploy.sh' && cd '$DEPLOY_PATH/build-src' && docker build --pull --label 'org.opencontainers.image.revision=${GITHUB_SHA}' --tag '$WEB_REF' --tag '${WEB_IMAGE}:dev' . && '$DEPLOY_PATH/deploy.sh' '$WEB_REF'" - name: Verify public domain run: | set -euo pipefail curl -fsS "https://${DEPLOY_DOMAIN}/" >/dev/null