chore(deps): bump dompurify from 3.4.12 to 3.4.13 in /frontend #1436
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: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| issue_comment: | |
| types: [created] | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event.issue.number || github.ref }} | |
| cancel-in-progress: true | |
| # Least-privilege default for every job. The `gate` and `report` jobs override | |
| # with the extra write scopes they need (checks / pull-requests). | |
| permissions: | |
| contents: read | |
| jobs: | |
| gate: | |
| name: Gate (automatic, /ci, or workflow_dispatch) | |
| # `/ci` checks out the PR head and runs its code with access to repo | |
| # secrets, so restrict it to org members/collaborators. Ordinary PR | |
| # CI still runs for everyone via the `pull_request` trigger above. | |
| if: | | |
| github.event_name == 'pull_request' || | |
| github.event_name == 'push' || | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request != null && | |
| startsWith(github.event.comment.body, '/ci') && | |
| (github.event.comment.author_association == 'OWNER' || | |
| github.event.comment.author_association == 'MEMBER' || | |
| github.event.comment.author_association == 'COLLABORATOR')) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| checks: write | |
| outputs: | |
| sha: ${{ steps.resolve.outputs.sha }} | |
| base_sha: ${{ steps.resolve.outputs.base_sha }} | |
| check_run_id: ${{ steps.check.outputs.id }} | |
| steps: | |
| - name: Resolve target SHA | |
| id: resolve | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if [[ "${{ github.event_name }}" == "issue_comment" ]]; then | |
| SHA=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} -q .head.sha) | |
| BASE_SHA=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} -q .base.sha) | |
| elif [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
| SHA="${{ github.event.pull_request.head.sha }}" | |
| BASE_SHA="${{ github.event.pull_request.base.sha }}" | |
| elif [[ "${{ github.event_name }}" == "push" ]]; then | |
| SHA="${{ github.sha }}" | |
| BASE_SHA="${{ github.event.before }}" | |
| else | |
| SHA="${{ github.sha }}" | |
| BASE_SHA="" | |
| fi | |
| echo "sha=$SHA" >> "$GITHUB_OUTPUT" | |
| echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT" | |
| - name: React to /ci comment | |
| if: github.event_name == 'issue_comment' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh api -X POST \ | |
| repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \ | |
| -f content=rocket | |
| - name: Create in-progress check run | |
| id: check | |
| if: github.event_name == 'issue_comment' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| ID=$(gh api -X POST repos/${{ github.repository }}/check-runs \ | |
| -f name="CI" \ | |
| -f head_sha="${{ steps.resolve.outputs.sha }}" \ | |
| -f status=in_progress \ | |
| -f "details_url=$RUN_URL" \ | |
| -q .id) | |
| echo "id=$ID" >> "$GITHUB_OUTPUT" | |
| changes: | |
| name: Determine changed areas | |
| needs: gate | |
| runs-on: ubuntu-latest | |
| outputs: | |
| backend: ${{ steps.filter.outputs.backend }} | |
| frontend: ${{ steps.filter.outputs.frontend }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ needs.gate.outputs.sha }} | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - name: Detect changed areas | |
| id: filter | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| BASE_SHA: ${{ needs.gate.outputs.base_sha }} | |
| TARGET_SHA: ${{ needs.gate.outputs.sha }} | |
| run: | | |
| if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then | |
| echo "backend=true" >> "$GITHUB_OUTPUT" | |
| echo "frontend=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [[ -z "$BASE_SHA" || "$BASE_SHA" =~ ^0+$ ]]; then | |
| echo "No usable base commit; running all checks." | |
| echo "backend=true" >> "$GITHUB_OUTPUT" | |
| echo "frontend=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| git diff --name-only "$BASE_SHA" "$TARGET_SHA" > changed-files.txt | |
| echo "Changed files:" | |
| cat changed-files.txt | |
| # Shared build/config/workflow changes can affect either side. | |
| if grep -qE '^(backend/|Makefile$|\.github/workflows/ci\.yml$)' changed-files.txt; then | |
| echo "backend=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "backend=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| if grep -qE '^(frontend/|Makefile$|\.github/workflows/ci\.yml$)' changed-files.txt; then | |
| echo "frontend=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "frontend=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| backend-check: | |
| name: Backend Check (ruff + mypy + pytest unit) | |
| needs: [gate, changes] | |
| if: needs.changes.outputs.backend == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 8 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ needs.gate.outputs.sha }} | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.12" | |
| enable-cache: true | |
| # Ephemeral runner — skip post-run `uv cache prune --ci` | |
| # which occasionally hangs on a concurrent lock and fails the job. | |
| prune-cache: false | |
| - name: Install backend | |
| run: make backend-install | |
| - name: Backend CI checks | |
| env: | |
| # Dummy env vars required because tests/conftest.py forces ENV_FOR_DYNACONF=test | |
| # which loads config.test.yaml, and that file uses @format {env[...]} for secrets. | |
| # Without these, dynaconf raises DynaconfFormatError during test collection. | |
| # Real e2e job (Task 9) overrides these with GitHub Secrets. | |
| CUBEPLEX_E2E_LLM_BASE_URL: http://dummy | |
| CUBEPLEX_E2E_LLM_API_KEY: dummy | |
| CUBEPLEX_E2E_LLM_MODEL_ID: dummy | |
| CUBEPLEX_SANDBOX__DOMAIN: dummy:9000 | |
| CUBEPLEX_SANDBOX__IMAGE: dummy:image | |
| CUBEPLEX_SANDBOX__API_KEY: dummy | |
| run: make backend-check-ci | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: backend-coverage | |
| path: backend/coverage.xml | |
| - name: Upload coverage to Codecov | |
| if: always() | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| files: backend/coverage.xml | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| fail_ci_if_error: false | |
| frontend-check: | |
| name: Frontend Check (eslint + prettier + type-check + vitest + build) | |
| needs: [gate, changes] | |
| if: needs.changes.outputs.frontend == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ needs.gate.outputs.sha }} | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| package_json_file: frontend/package.json | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: "20" | |
| cache: pnpm | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - name: Install frontend | |
| run: make frontend-install | |
| - name: Frontend CI checks | |
| run: make frontend-check-ci | |
| backend-e2e: | |
| name: Backend E2E (pytest, shard ${{ matrix.shard }}) | |
| needs: [gate, changes] | |
| if: needs.changes.outputs.backend == 'true' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [0, 1, 2, 3] | |
| # The complete suite contains more than 850 tests and took over 30 minutes | |
| # in a single process. Stable node-id sharding keeps full coverage while | |
| # giving every shard enough time to finish and report all failures. | |
| timeout-minutes: 30 | |
| env: | |
| ENV_FOR_DYNACONF: test | |
| CUBEPLEX_E2E_SHARD_INDEX: ${{ matrix.shard }} | |
| CUBEPLEX_E2E_SHARD_TOTAL: 4 | |
| CUBEPLEX_E2E_LLM_BASE_URL: ${{ secrets.CUBEPLEX_E2E_LLM_BASE_URL || 'http://127.0.0.1:9' }} | |
| CUBEPLEX_E2E_LLM_API_KEY: ${{ secrets.CUBEPLEX_E2E_LLM_API_KEY || 'ci-placeholder' }} | |
| CUBEPLEX_E2E_LLM_MODEL_ID: ${{ secrets.CUBEPLEX_E2E_LLM_MODEL_ID || 'ci-placeholder' }} | |
| CUBEPLEX_SANDBOX__DOMAIN: ${{ secrets.CUBEPLEX_SANDBOX__DOMAIN || '127.0.0.1:9' }} | |
| CUBEPLEX_SANDBOX__IMAGE: ${{ secrets.CUBEPLEX_SANDBOX__IMAGE || 'ci-placeholder' }} | |
| CUBEPLEX_SANDBOX__API_KEY: ${{ secrets.CUBEPLEX_SANDBOX__API_KEY || 'ci-placeholder' }} | |
| # Optional: gates the conversation-search E2E test. The test skips | |
| # cleanly when this secret isn't set in the repo, so PRs from forks | |
| # without the secret stay green; the real-network path runs in main. | |
| DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} | |
| # Test-only Fernet key for CI startup and vault E2E. Production must set its own key. | |
| CUBEPLEX_AUTH__VAULT_KEY: 1EwVRAtWccVJhdXX_2iepp7OlPfadfHpWNwVFpRzLBI= | |
| services: | |
| postgres: | |
| image: cubeplex/postgresql-pgroonga-pgvector:18.2-pgroonga4.0.6-pgvector0.8.2 | |
| env: | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: testpass | |
| POSTGRES_DB: cubeplex_test | |
| ports: ['5432:5432'] | |
| options: >- | |
| --health-cmd="pg_isready -U postgres" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=10 | |
| redis: | |
| image: redis:7-alpine | |
| ports: ['6379:6379'] | |
| options: >- | |
| --health-cmd="redis-cli ping" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=5 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ needs.gate.outputs.sha }} | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.12" | |
| enable-cache: true | |
| # Ephemeral runner — skip post-run `uv cache prune --ci` | |
| # which occasionally hangs on a concurrent lock and fails the job. | |
| prune-cache: false | |
| - name: Install backend | |
| run: make backend-install | |
| - name: Prepare RustFS data dirs | |
| run: | | |
| mkdir -p /tmp/rustfs/data /tmp/rustfs/logs | |
| sudo chown -R 10001:10001 /tmp/rustfs | |
| - name: Start RustFS | |
| run: | | |
| docker run -d --name rustfs \ | |
| -p 9000:9000 -p 9001:9001 \ | |
| -v /tmp/rustfs/data:/data \ | |
| -v /tmp/rustfs/logs:/logs \ | |
| rustfs/rustfs:1.0.0-alpha.97 | |
| # TCP/HTTP-level readiness; RustFS alpha lacks a unified /health endpoint. | |
| # Accept any 2xx/3xx/4xx HTTP response as ready. | |
| for i in {1..30}; do | |
| if curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:9000/ | grep -qE '^(2|3|4)'; then | |
| echo "RustFS ready" | |
| break | |
| fi | |
| sleep 2 | |
| done | |
| - name: Create RustFS test bucket | |
| env: | |
| AWS_ACCESS_KEY_ID: rustfsadmin | |
| AWS_SECRET_ACCESS_KEY: rustfsadmin | |
| run: | | |
| aws --endpoint-url http://127.0.0.1:9000 \ | |
| s3 mb s3://cubeplex-test --region us-east-1 | |
| - name: Alembic migrate | |
| run: make backend-migrate | |
| - name: Pytest e2e (fast lane — excludes real_llm) | |
| # The 10 `@pytest.mark.real_llm` tests (prompt-cache discipline, | |
| # journey middleware, send_message billing) run in nightly-real-llm.yml | |
| # against the live LLM gateway. Keeping them off the PR path saves | |
| # ~5-10× wall-clock per push and prevents vendor-rate-limit flakes | |
| # from blocking unrelated merges. | |
| # | |
| # -ci variant additionally writes coverage-e2e.xml: e2e tests are the | |
| # primary test type for business-flow code in this repo (see | |
| # docs/testing.md), so without this the Codecov patch-coverage gate | |
| # only ever sees the unit-test run and reports business logic as | |
| # untested even when it's covered here. | |
| run: make backend-test-e2e-ci | |
| - name: Pytest e2e (licensed lane) | |
| # The default environment has no optional package, so tests/e2e/licensed/ | |
| # skips itself there — which means the authorisation and validation | |
| # contracts for the relocated cost routes would otherwise be checked | |
| # nowhere. Runs on one shard only: it is a handful of tests and sharding | |
| # them would just install the package four times. Reuses the services this | |
| # job already stood up rather than duplicating postgres/redis/rustfs. | |
| # | |
| # Both sync flags: `--group` alone re-resolves and drops test deps. | |
| if: matrix.shard == 0 | |
| run: | | |
| cd backend | |
| uv sync --all-extras --group licensed | |
| uv run python scripts/dev/license_keygen.py dev-env --features multi_org \ | |
| >> "$GITHUB_ENV" | |
| - name: Pytest e2e (licensed lane — run) | |
| if: matrix.shard == 0 | |
| run: | | |
| cd backend | |
| # `env -u`, not blanking: the shard gate checks `is None`, so an empty | |
| # string gets past it and then fails int("") with a UsageError. | |
| # Both paths, explicitly: a licensed test directory that no command | |
| # names runs nowhere — importorskip hides it from the default lane too. | |
| env -u CUBEPLEX_E2E_SHARD_INDEX -u CUBEPLEX_E2E_SHARD_TOTAL \ | |
| uv run pytest tests/e2e/licensed/ tests/unit/licensed/ --no-cov -q | |
| - name: Cleanup leftover test sandboxes | |
| if: always() | |
| run: make backend-cleanup-sandboxes | |
| - name: Upload e2e coverage to Codecov | |
| if: always() | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| files: backend/coverage-e2e.xml | |
| flags: backend-e2e-shard-${{ matrix.shard }} | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| fail_ci_if_error: false | |
| frontend-e2e: | |
| name: Frontend E2E (playwright) | |
| needs: [gate, changes] | |
| if: needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| env: | |
| ENV_FOR_DYNACONF: test | |
| CUBEPLEX_E2E_LLM_BASE_URL: ${{ secrets.CUBEPLEX_E2E_LLM_BASE_URL || 'http://127.0.0.1:9' }} | |
| CUBEPLEX_E2E_LLM_API_KEY: ${{ secrets.CUBEPLEX_E2E_LLM_API_KEY || 'ci-placeholder' }} | |
| CUBEPLEX_E2E_LLM_MODEL_ID: ${{ secrets.CUBEPLEX_E2E_LLM_MODEL_ID || 'ci-placeholder' }} | |
| CUBEPLEX_E2E_REAL_LLM: ${{ secrets.CUBEPLEX_E2E_LLM_BASE_URL != '' && secrets.CUBEPLEX_E2E_LLM_API_KEY != '' && secrets.CUBEPLEX_E2E_LLM_MODEL_ID != '' }} | |
| CUBEPLEX_SANDBOX__DOMAIN: ${{ secrets.CUBEPLEX_SANDBOX__DOMAIN || '127.0.0.1:9' }} | |
| CUBEPLEX_SANDBOX__IMAGE: ${{ secrets.CUBEPLEX_SANDBOX__IMAGE || 'ci-placeholder' }} | |
| CUBEPLEX_SANDBOX__API_KEY: ${{ secrets.CUBEPLEX_SANDBOX__API_KEY || 'ci-placeholder' }} | |
| # Test-only Fernet key for CI startup and vault E2E. Production must set its own key. | |
| CUBEPLEX_AUTH__VAULT_KEY: 1EwVRAtWccVJhdXX_2iepp7OlPfadfHpWNwVFpRzLBI= | |
| # Frontend proxies to local backend:8001 (matches config.test.yaml) | |
| CUBEPLEX_API_URL: http://127.0.0.1:8001 | |
| services: | |
| postgres: | |
| image: cubeplex/postgresql-pgroonga-pgvector:18.2-pgroonga4.0.6-pgvector0.8.2 | |
| env: | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: testpass | |
| POSTGRES_DB: cubeplex_test | |
| ports: ['5432:5432'] | |
| options: >- | |
| --health-cmd="pg_isready -U postgres" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=10 | |
| redis: | |
| image: redis:7-alpine | |
| ports: ['6379:6379'] | |
| options: >- | |
| --health-cmd="redis-cli ping" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=5 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ needs.gate.outputs.sha }} | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.12" | |
| enable-cache: true | |
| # Ephemeral runner — skip post-run `uv cache prune --ci` | |
| # which occasionally hangs on a concurrent lock and fails the job. | |
| prune-cache: false | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| package_json_file: frontend/package.json | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: "20" | |
| cache: pnpm | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - name: Install backend | |
| run: make backend-install | |
| - name: Install frontend | |
| run: make frontend-install | |
| - name: Build @cubeplex/core | |
| run: make frontend-build-core | |
| - name: Prepare RustFS data dirs | |
| run: | | |
| mkdir -p /tmp/rustfs/data /tmp/rustfs/logs | |
| sudo chown -R 10001:10001 /tmp/rustfs | |
| - name: Start RustFS | |
| run: | | |
| docker run -d --name rustfs \ | |
| -p 9000:9000 -p 9001:9001 \ | |
| -v /tmp/rustfs/data:/data \ | |
| -v /tmp/rustfs/logs:/logs \ | |
| rustfs/rustfs:1.0.0-alpha.97 | |
| # TCP/HTTP-level readiness; RustFS alpha lacks a unified /health endpoint. | |
| # Accept any 2xx/3xx/4xx HTTP response as ready. | |
| for i in {1..30}; do | |
| if curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:9000/ | grep -qE '^(2|3|4)'; then | |
| echo "RustFS ready" | |
| break | |
| fi | |
| sleep 2 | |
| done | |
| - name: Create RustFS test bucket | |
| env: | |
| AWS_ACCESS_KEY_ID: rustfsadmin | |
| AWS_SECRET_ACCESS_KEY: rustfsadmin | |
| run: | | |
| aws --endpoint-url http://127.0.0.1:9000 \ | |
| s3 mb s3://cubeplex-test --region us-east-1 | |
| - name: Install the optional package and mint an ephemeral licence | |
| # admin-sso and admin-insights drive pages behind <EEGate>, and | |
| # admin-insights now calls cost endpoints the optional package serves, so | |
| # this backend needs both the package and a key. `--group` on its own | |
| # re-resolves and drops the test dependencies, hence both flags. The | |
| # keypair is generated here and thrown away: nothing is committed, and | |
| # there is no key that expires out from under CI later. | |
| run: | | |
| cd backend | |
| uv sync --all-extras --group licensed | |
| uv run python scripts/dev/license_keygen.py dev-env --features multi_org \ | |
| >> "$GITHUB_ENV" | |
| - name: Alembic migrate | |
| run: make backend-migrate | |
| - name: Start backend in background | |
| run: | | |
| nohup make backend-start > /tmp/backend-console.log 2>&1 & | |
| - name: Wait for backend ready | |
| run: | | |
| timeout 60 bash -c ' | |
| until curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8001/docs | grep -qE "^(2|3|4)"; do | |
| sleep 2 | |
| done | |
| ' | |
| - name: Install playwright browsers | |
| run: make frontend-install-browsers | |
| - name: Playwright e2e | |
| run: make frontend-test-e2e-ci | |
| - name: Cleanup leftover test sandboxes | |
| if: always() | |
| run: make backend-cleanup-sandboxes | |
| - name: Upload backend logs on failure | |
| if: failure() || cancelled() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: backend-log | |
| path: | | |
| /tmp/backend.log | |
| /tmp/backend-console.log | |
| - name: Upload playwright traces on failure | |
| if: failure() || cancelled() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: playwright-traces | |
| path: | | |
| frontend/test-results/ | |
| frontend/playwright-report/ | |
| report: | |
| name: Finalize CI check run | |
| if: | | |
| always() && | |
| needs.gate.result == 'success' && | |
| github.event_name == 'issue_comment' | |
| needs: [gate, changes, backend-check, frontend-check, backend-e2e, frontend-e2e] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| checks: write | |
| steps: | |
| - name: Compute conclusion and update check run | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| BACKEND_CHECK: ${{ needs.backend-check.result }} | |
| FRONTEND_CHECK: ${{ needs.frontend-check.result }} | |
| BACKEND_E2E: ${{ needs.backend-e2e.result }} | |
| FRONTEND_E2E: ${{ needs.frontend-e2e.result }} | |
| CHECK_ID: ${{ needs.gate.outputs.check_run_id }} | |
| run: | | |
| conclusion=success | |
| for r in "$BACKEND_CHECK" "$FRONTEND_CHECK" "$BACKEND_E2E" "$FRONTEND_E2E"; do | |
| case "$r" in | |
| failure|cancelled|timed_out) | |
| conclusion=failure | |
| ;; | |
| esac | |
| done | |
| summary="backend-check=$BACKEND_CHECK, frontend-check=$FRONTEND_CHECK, backend-e2e=$BACKEND_E2E, frontend-e2e=$FRONTEND_E2E" | |
| echo "Conclusion: $conclusion ($summary)" | |
| gh api -X PATCH repos/${{ github.repository }}/check-runs/$CHECK_ID \ | |
| -f status=completed \ | |
| -f conclusion=$conclusion \ | |
| -f "output[title]=CI ($conclusion)" \ | |
| -f "output[summary]=$summary" |