feat: show error when assessment attempt limit exceeded #10077
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created | |
# For more information see: https://github.com/actions/setup-java#publishing-using-gradle | |
name: doughnut CI | |
on: | |
push: | |
branches: | |
- main | |
env: | |
ARTIFACT: "doughnut" | |
VERSION: "0.0.1-SNAPSHOT" | |
GCS_BUCKET: "dough-01" | |
MYSQL_UT_DB: "doughnut_test" | |
MYSQL_E2E_DB: "doughnut_e2e_test" | |
MYSQL_DB_USER: ${{ secrets.DBUSER }} | |
MYSQL_DB_PASSWORD: ${{ secrets.DBPASSWORD }} | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} | |
GITHUB_FOR_ISSUES_API_TOKEN: ${{ secrets.GH_ISSUES_API_TOKEN }} | |
OPENAI_API_TOKEN: ${{ secrets.OPENAI_API_TOKEN }} | |
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
jobs: | |
Linting: | |
name: Backend + Frontend + Cypress Static Code Analysis | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: ./.github/setup_jdk_with_cache | |
with: | |
java_version: ${{ vars.JAVA_VERSION }} | |
- uses: ./.github/setup_nodejs | |
with: | |
node_version: ${{ vars.NODE_VERSION }} | |
pnpm_version: ${{ vars.PNPM_VERSION }} | |
- run: bash -c ./assert_generated_type_script_up_to_date.sh | |
- run: pnpm lint:all | |
Backend-unit-tests: | |
name: Backend Unit tests | |
runs-on: ${{ vars.RUNNER }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup MySQL DB Server | |
uses: ./.github/mysql_db | |
with: | |
mysql_version: ${{ vars.MYSQL_VERSION }} | |
mysql_db_host_port: ${{ vars.MYSQL_PORT }} | |
mysql_db_container_port: ${{ vars.MYSQL_PORT }} | |
mysql_db_instance: ${{ env.MYSQL_UT_DB }} | |
mysql_db_user: ${{ env.MYSQL_DB_USER }} | |
mysql_db_password: ${{ env.MYSQL_DB_PASSWORD }} | |
- uses: ./.github/setup_jdk_with_cache | |
with: | |
java_version: ${{ vars.JAVA_VERSION }} | |
- run: backend/gradlew -p backend migrateTestDB -Dspring.profiles.active=test | |
- run: backend/gradlew -p backend test -Dspring.profiles.active=test --parallel | |
Frontend-unit-tests: | |
name: Frontend Unit tests | |
runs-on: ${{ vars.RUNNER }} | |
env: | |
FRONTEND_UT_CONSOLE_OUTPUT_AS_FAILURE: true | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: ./.github/setup_nodejs | |
with: | |
node_version: ${{ vars.NODE_VERSION }} | |
pnpm_version: ${{ vars.PNPM_VERSION }} | |
- run: pnpm frontend:test | |
Package-artifacts: | |
name: Package backend & frontend artifacts for deployment | |
runs-on: ${{ vars.RUNNER }} | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: ./.github/setup_jdk_with_cache | |
with: | |
java_version: ${{ vars.JAVA_VERSION }} | |
- uses: ./.github/setup_nodejs | |
with: | |
node_version: ${{ vars.NODE_VERSION }} | |
pnpm_version: ${{ vars.PNPM_VERSION }} | |
- name: Compile & transform frontend assets for bundling with Backend | |
run: pnpm frontend:build | |
- name: Build application jar artifact | |
run: backend/gradlew -p backend build -x test -Dspring.profiles.active=prod --build-cache --parallel | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ env.ARTIFACT }}-${{ env.VERSION }}.jar | |
path: backend/build/libs/${{ env.ARTIFACT }}-${{ env.VERSION }}.jar | |
E2E-tests: | |
name: End-to-End tests with Database | |
runs-on: ${{ vars.RUNNER }} | |
strategy: | |
matrix: | |
spec: | |
- | | |
e2e_test/features/a*/** | |
e2e_test/features/b*/** | |
- | | |
e2e_test/features/c*/** | |
e2e_test/features/l*/** | |
- | | |
e2e_test/features/n*/** | |
- | | |
e2e_test/features/r*/** | |
- | | |
e2e_test/features/t*/** | |
e2e_test/features/u*/** | |
- | | |
e2e_test/features/w*/** | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: docker/login-action@v3 | |
with: | |
username: ${{ env.DOCKERHUB_USERNAME }} | |
password: ${{ env.DOCKERHUB_TOKEN }} | |
- uses: ./.github/mysql_db | |
with: | |
mysql_version: ${{ vars.MYSQL_VERSION }} | |
mysql_db_host_port: ${{ vars.MYSQL_PORT }} | |
mysql_db_container_port: ${{ vars.MYSQL_PORT }} | |
mysql_db_instance: ${{ env.MYSQL_E2E_DB }} | |
mysql_db_user: ${{ env.MYSQL_DB_USER }} | |
mysql_db_password: ${{ env.MYSQL_DB_PASSWORD }} | |
- name: Setup JDK with cache | |
uses: ./.github/setup_jdk_with_cache | |
with: | |
java_version: ${{ vars.JAVA_VERSION }} | |
- uses: ./.github/setup_nodejs | |
with: | |
node_version: ${{ vars.NODE_VERSION }} | |
pnpm_version: ${{ vars.PNPM_VERSION }} | |
- uses: cypress-io/github-action@v6 | |
with: | |
browser: chrome | |
config-file: e2e_test/config/ci.ts | |
build: pnpm frontend:build | |
start: pnpm run-p -clnr sut start:mb | |
wait-on: "http:https://127.0.0.1:9081/api/healthcheck" | |
wait-on-timeout: 150 | |
spec: ${{ matrix.spec }} | |
env: | |
GITHUB_FOR_ISSUES_API_TOKEN: ${{ env.GITHUB_FOR_ISSUES_API_TOKEN }} | |
- uses: actions/upload-artifact@v4 | |
if: failure() | |
with: | |
name: cypress-screenshots | |
path: e2e_test/screenshots | |
Deploy: | |
name: GCP MIG Rolling Update Deploy | |
runs-on: ${{ vars.RUNNER }} | |
needs: | |
[ | |
Linting, | |
Backend-unit-tests, | |
Frontend-unit-tests, | |
Package-artifacts, | |
E2E-tests, | |
] | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: ./.github/gcloud_auth_n_sdk | |
with: | |
credentials_json: ${{ env.GCP_CREDENTIALS }} | |
- name: Upload production application jar to Google Cloud Storage | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ env.ARTIFACT }}-${{ env.VERSION }}.jar | |
- uses: google-github-actions/upload-cloud-storage@v2 | |
with: | |
path: ./${{ env.ARTIFACT }}-${{ env.VERSION }}.jar | |
destination: ${{ env.GCS_BUCKET }}/backend_app_jar | |
- name: Perform rolling replace to GCP MIG doughnut-app-group | |
run: infra/gcp/scripts/perform-rolling-replace-app-mig.sh | |
Notify-on-failure: | |
name: Single slack/discord notification on CI/CD failure | |
runs-on: ${{ vars.RUNNER }} | |
needs: | |
[ | |
Linting, | |
Backend-unit-tests, | |
Frontend-unit-tests, | |
Package-artifacts, | |
E2E-tests, | |
Deploy, | |
] | |
if: always() | |
steps: | |
- uses: technote-space/workflow-conclusion-action@v3 | |
- uses: 8398a7/action-slack@v3 | |
if: env.WORKFLOW_CONCLUSION == 'failure' | |
with: | |
status: failure | |
fields: repo,commit,message,author,action,workflow,eventName | |
# - uses: nobrayner/discord-webhook@v1 | |
# if: env.WORKFLOW_CONCLUSION == 'failure' | |
# with: | |
# github-token: ${{ env.GITHUB_TOKEN }} | |
# discord-webhook: ${{ env.DISCORD_WEBHOOK_URL }} | |
# mobile-unit-test: | |
# runs-on: ${{ vars.RUNNER }} | |
# steps: | |
# - uses: actions/checkout@v4 | |
# - uses: subosito/flutter-action@v2 | |
# with: | |
# flutter-version: ${{ vars.FLUTTER_VERSION }} | |
# - run: flutter pub get | |
# working-directory: ./doughnut_mobile | |
# - run: flutter test | |
# working-directory: ./doughnut_mobile | |
# drive_ios: | |
# strategy: | |
# matrix: | |
# device: | |
# - "iPhone 15" | |
# fail-fast: false | |
# runs-on: ${{ vars.RUNNER }} | |
# steps: | |
# - name: List Simulators | |
# run: xcrun xctrace list devices | |
# - name: Start Simulator | |
# run: xcrun simctl boot "${{ matrix.device }}" | |
# - uses: actions/checkout@v4 | |
# - uses: ./.github/starting_backend_actions | |
# with: | |
# java_version: ${{ vars.JAVA_VERSION }} | |
# pnpm_version: ${{ vars.PNPM_VERSION }} | |
# mysql_version: ${{ vars.MYSQL_VERSION }} | |
# mysql_db_host_port: ${{ vars.MYSQL_PORT }} | |
# mysql_db_container_port: ${{ vars.MYSQL_PORT }} | |
# dbuser: ${{ secrets.DBUSER }} | |
# dbpassword: ${{ secrets.DBPASSWORD }} | |
# db_url: ${{ secrets.CI_E2E_DB_URL }} | |
# - uses: ./.github/mobile_actions | |
# with: | |
# flutter-version: ${{ vars.FLUTTER_VERSION }} | |
# - run: dart test_driver/app_test.dart | |
# working-directory: ./doughnut_mobile | |
# drive_android: | |
# runs-on: ${{ vars.RUNNER }} | |
# #creates a build matrix for your jobs | |
# strategy: | |
# #set of different configurations of the virtual environment. | |
# matrix: | |
# api-level: [34] | |
# steps: | |
# - uses: actions/checkout@v4 | |
# - uses: ./.github/starting_backend_actions | |
# with: | |
# java_version: ${{ vars.JAVA_VERSION }} | |
# pnpm_version: ${{ vars.PNPM_VERSION }} | |
# mysql_version: ${{ vars.MYSQL_VERSION }} | |
# mysql_db_host_port: ${{ vars.MYSQL_PORT }} | |
# mysql_db_container_port: ${{ vars.MYSQL_PORT }} | |
# dbuser: ${{ secrets.DBUSER }} | |
# dbpassword: ${{ secrets.DBPASSWORD }} | |
# db_url: ${{ secrets.CI_E2E_DB_URL }} | |
# - uses: ./.github/mobile_actions | |
# with: | |
# flutter-version: ${{ vars.FLUTTER_VERSION }} | |
# - name: Run Flutter Driver tests | |
# uses: reactivecircus/android-emulator-runner@v2 | |
# with: | |
# api-level: ${{ matrix.api-level }} | |
# script: | | |
# cd ./doughnut_mobile && dart test_driver/app_test.dart |