name: Проверка, сборка и развёртывание Magistr on: push: branches: - main tags: - 'v*' concurrency: group: magistr-production cancel-in-progress: false env: REGISTRY: gitea.zuev.company BACKEND_IMAGE: zuev/magistr-backend FRONTEND_IMAGE: zuev/magistr-frontend MAVEN_IMAGE: maven:3.9.9-eclipse-temurin-17@sha256:f58d59b6273e785ac0a4477f6e9b5ba1d7731c75b906c0f7b34076f1851318cc NODE_IMAGE: node:22-alpine3.23@sha256:8516dce0483394d5708d4b2ee6cacb79fb1d617ea4e2787c2120bcca92ce372e TRIVY_IMAGE: aquasec/trivy:0.63.0@sha256:6fb0646988fcd2fdf7bf123f7174945ebc2c9c72d1fa1567c8d7daeeb70f8037 jobs: checks: name: Обязательные проверки runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Получить исходный код uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Backend unit и component tests run: >- docker run --rm -v "${{ github.workspace }}/backend:/workspace" -w /workspace "${{ env.MAVEN_IMAGE }}" mvn -Dapi.version=1.44 '-Dtest=!*IntegrationTest' test - name: Frontend static и unit tests run: >- docker run --rm -v "${{ github.workspace }}/frontend:/workspace" -w /workspace "${{ env.NODE_IMAGE }}" sh -c "npm ci && npm run check" - name: Проверить Docker Compose env: POSTGRES_PASSWORD: ci-config-only JWT_SECRET: ci-only-secret-not-for-runtime-0123456789abcdef0123456789abcdef run: docker compose config --quiet - name: Проверить сценарий immutable rollout и rollback run: bash scripts/test-deploy-images.sh - name: Проверить закрепление артефактов и supply-chain gates run: bash scripts/test-artifact-pinning.sh build-and-push-backend: name: Собрать backend image needs: checks runs-on: ubuntu-latest timeout-minutes: 30 outputs: digest: ${{ steps.build.outputs.digest }} steps: - name: Получить исходный код uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Войти в Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.ZUEV_TOKEN }} - name: Сформировать immutable tags и labels id: meta uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0 with: images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE }} flavor: latest=false tags: | type=sha,format=long,prefix=sha- type=ref,event=tag - name: Собрать и опубликовать backend image id: build uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: ./backend push: true provenance: mode=max sbom: true tags: ${{ steps.meta.outputs.tags }} labels: | ${{ steps.meta.outputs.labels }} org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} build-and-push-frontend: name: Собрать frontend image needs: checks runs-on: ubuntu-latest timeout-minutes: 20 outputs: digest: ${{ steps.build.outputs.digest }} steps: - name: Получить исходный код uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Войти в Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.ZUEV_TOKEN }} - name: Сформировать immutable tags и labels id: meta uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0 with: images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE }} flavor: latest=false tags: | type=sha,format=long,prefix=sha- type=ref,event=tag - name: Собрать и опубликовать frontend image id: build uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: ./frontend push: true provenance: mode=max sbom: true tags: ${{ steps.meta.outputs.tags }} labels: | ${{ steps.meta.outputs.labels }} org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} security-scan: name: Проверить опубликованные образы needs: [build-and-push-backend, build-and-push-frontend] runs-on: ubuntu-latest timeout-minutes: 20 env: BACKEND_REF: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE }}@${{ needs.build-and-push-backend.outputs.digest }} FRONTEND_REF: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE }}@${{ needs.build-and-push-frontend.outputs.digest }} steps: - name: Войти в Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.ZUEV_TOKEN }} - name: Проверить backend на HIGH и CRITICAL уязвимости run: >- docker run --rm -v "$HOME/.docker:/root/.docker:ro" "${{ env.TRIVY_IMAGE }}" image --scanners vuln --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed "$BACKEND_REF" - name: Проверить frontend на HIGH и CRITICAL уязвимости run: >- docker run --rm -v "$HOME/.docker:/root/.docker:ro" "${{ env.TRIVY_IMAGE }}" image --scanners vuln --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed "$FRONTEND_REF" deploy-to-k8s: name: Развернуть проверенные digests needs: [build-and-push-backend, build-and-push-frontend, security-scan] runs-on: ubuntu-latest timeout-minutes: 15 environment: production env: BACKEND_REF: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE }}@${{ needs.build-and-push-backend.outputs.digest }} FRONTEND_REF: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE }}@${{ needs.build-and-push-frontend.outputs.digest }} KUBECTL_VERSION: v1.33.12 KUBECTL_SHA256: fe80ae4133b44fa2077db4af144e80765eb1b3b2eede55fbff6933c4374d8c6e steps: - name: Получить deploy-скрипт uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Создать kubeconfig env: KUBECONFIG_DATA: ${{ secrets.KUBECONFIG_DATA }} run: | install -d -m 700 "$HOME/.kube" printf '%s' "$KUBECONFIG_DATA" | base64 --decode > "$HOME/.kube/config" chmod 600 "$HOME/.kube/config" - name: Установить проверенный kubectl run: | curl --fail --show-error --silent --location --retry 3 \ --output kubectl \ "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" echo "${KUBECTL_SHA256} kubectl" | sha256sum --check --strict sudo install -m 0755 kubectl /usr/local/bin/kubectl - name: Применить digests и проверить rollout run: bash scripts/deploy-images.sh "$BACKEND_REF" "$FRONTEND_REF"