fix(clients): add idempotent replay logic and handle malformed UUID #253
Workflow file for this run
This file contains hidden or 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
| name: CI | |
| on: | |
| push: | |
| branches: ["**"] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| actions: read | |
| jobs: | |
| backend: | |
| name: Backend (Maven) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| actions: write | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 | |
| with: | |
| distribution: temurin | |
| java-version: 25 | |
| cache: maven | |
| - name: Run backend tests | |
| run: mvn -B -ntp verify | |
| - name: Upload backend JaCoCo report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: backend-jacoco-report | |
| path: | | |
| target/site/jacoco/jacoco.xml | |
| target/site/jacoco-it/jacoco.xml | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| sonar-backend: | |
| name: SonarQube - backend | |
| runs-on: ubuntu-latest | |
| needs: [backend] | |
| if: > | |
| ((github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)) || | |
| (github.event_name == 'pull_request' && github.actor != 'dependabot[bot]')) | |
| outputs: | |
| sonar_skipped: ${{ steps.sonar-check.outputs.sonar_skipped }} | |
| env: | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} | |
| SONAR_ORGANIZATION: ${{ vars.SONAR_ORGANIZATION }} | |
| SONAR_PROJECT_KEY: ${{ vars.SONAR_PROJECT_KEY }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check Sonar configuration | |
| id: sonar-check | |
| run: | | |
| if [ -z "$SONAR_TOKEN" ]; then | |
| echo "sonar_skipped=true" >> "$GITHUB_OUTPUT" | |
| echo "SONAR_TOKEN not set; skipping backend analysis" | |
| exit 0 | |
| fi | |
| host_url="${SONAR_HOST_URL:-https://sonarcloud.io}" | |
| host_url="${host_url%/}" | |
| if [ "$host_url" = "https://sonarcloud.io" ] && [ -z "$SONAR_ORGANIZATION" ]; then | |
| echo "sonar_skipped=true" >> "$GITHUB_OUTPUT" | |
| echo "SONAR_ORGANIZATION not set for SonarCloud; skipping backend analysis" | |
| exit 0 | |
| fi | |
| echo "sonar_skipped=false" >> "$GITHUB_OUTPUT" | |
| echo "sonar_enabled=true" >> "$GITHUB_OUTPUT" | |
| - name: Set up JDK 25 | |
| if: steps.sonar-check.outputs.sonar_enabled == 'true' | |
| uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 | |
| with: | |
| distribution: temurin | |
| java-version: 25 | |
| cache: maven | |
| - name: Download backend JaCoCo report | |
| if: steps.sonar-check.outputs.sonar_enabled == 'true' | |
| continue-on-error: true | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: backend-jacoco-report | |
| path: coverage | |
| - name: Run SonarQube analysis (backend) | |
| if: steps.sonar-check.outputs.sonar_enabled == 'true' | |
| shell: bash | |
| env: | |
| REPO_NAME: ${{ github.event.repository.name }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| PR_HEAD_REF: ${{ github.head_ref }} | |
| PR_BASE_REF: ${{ github.base_ref }} | |
| run: | | |
| host_url="${SONAR_HOST_URL:-https://sonarcloud.io}" | |
| sonar_project_key="${SONAR_PROJECT_KEY:-$REPO_NAME}" | |
| report_paths="" | |
| if [ -d "coverage" ]; then | |
| report_paths=$(find coverage -type f -name "jacoco.xml" | paste -sd "," - || true) | |
| fi | |
| cmd=( | |
| mvn -B -ntp | |
| -Djacoco.skip=true | |
| -DskipTests | |
| verify | |
| sonar:sonar | |
| "-Dsonar.host.url=${host_url}" | |
| "-Dsonar.projectKey=${sonar_project_key}" | |
| "-Dsonar.token=${SONAR_TOKEN}" | |
| ) | |
| if [ -n "${report_paths}" ]; then | |
| cmd+=("-Dsonar.coverage.jacoco.xmlReportPaths=${report_paths}") | |
| else | |
| echo "JaCoCo XML report not found; Sonar will run without coverage input" | |
| fi | |
| if [ -n "${SONAR_ORGANIZATION}" ]; then | |
| cmd+=("-Dsonar.organization=${SONAR_ORGANIZATION}") | |
| fi | |
| if [ "${EVENT_NAME}" = "pull_request" ] && [ -n "${PR_NUMBER}" ] && [ -n "${PR_HEAD_REF}" ] && [ -n "${PR_BASE_REF}" ]; then | |
| cmd+=("-Dsonar.pullrequest.key=${PR_NUMBER}") | |
| cmd+=("-Dsonar.pullrequest.branch=${PR_HEAD_REF}") | |
| cmd+=("-Dsonar.pullrequest.base=${PR_BASE_REF}") | |
| fi | |
| "${cmd[@]}" | |
| - name: Locate backend Sonar report-task | |
| if: steps.sonar-check.outputs.sonar_enabled == 'true' | |
| id: report-task | |
| shell: bash | |
| run: | | |
| report_task=$(find . -type f \( -path "*/target/sonar/report-task.txt" -o -path "*/.scannerwork/report-task.txt" \) | head -1) | |
| if [ -z "$report_task" ]; then | |
| echo "Unable to find Sonar report-task.txt" >&2 | |
| exit 1 | |
| fi | |
| echo "path=${report_task}" >> "$GITHUB_OUTPUT" | |
| - name: Wait for Quality Gate and publish backend Sonar summary | |
| if: steps.sonar-check.outputs.sonar_enabled == 'true' | |
| shell: bash | |
| env: | |
| REPO_NAME: ${{ github.event.repository.name }} | |
| run: | | |
| sonar_project_key="${SONAR_PROJECT_KEY:-$REPO_NAME}" | |
| extra_args=() | |
| if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then | |
| extra_args+=("--allow-missing-new-code-metrics") | |
| fi | |
| python3 .github/scripts/sonar_quality_gate_report.py \ | |
| --component-name "backend" \ | |
| --project-key "${sonar_project_key}" \ | |
| --report-task-file "${{ steps.report-task.outputs.path }}" \ | |
| --timeout-seconds 900 \ | |
| "${extra_args[@]}" | |
| notify-telegram: | |
| name: Notify Telegram | |
| runs-on: ubuntu-latest | |
| needs: [backend, sonar-backend] | |
| if: ${{ always() }} | |
| permissions: | |
| contents: read | |
| env: | |
| TELEGRAM_TO: ${{ secrets.TELEGRAM_TO }} | |
| TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Compose Telegram message | |
| id: compose | |
| run: python3 .github/scripts/compose_telegram_message.py | |
| env: | |
| BACKEND_RESULT: ${{ needs.backend.result }} | |
| SONAR_BACKEND_RESULT: ${{ needs.sonar-backend.result }} | |
| SONAR_BACKEND_SKIPPED: ${{ needs.sonar-backend.outputs.sonar_skipped }} | |
| - name: Notify Telegram | |
| if: ${{ env.TELEGRAM_TO != '' && env.TELEGRAM_TOKEN != '' }} | |
| uses: appleboy/telegram-action@221e6b684967abe813051ee4a37dd61770a83ad3 # v1.0.1 | |
| with: | |
| to: ${{ secrets.TELEGRAM_TO }} | |
| token: ${{ secrets.TELEGRAM_TOKEN }} | |
| message: ${{ steps.compose.outputs.message }} | |
| format: html | |
| - name: Telegram skipped (missing secrets) | |
| if: ${{ env.TELEGRAM_TO == '' || env.TELEGRAM_TOKEN == '' }} | |
| run: echo "TELEGRAM_TO and/or TELEGRAM_TOKEN are not set. Skipping Telegram notification." |