chore(deps): Bump @google/genai from 2.9.0 to 2.10.0 in the deps group #433
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: | |
| - main | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| paths-ignore: | |
| - 'docs/**' | |
| - 'poc/**' | |
| - '**/*.md' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| build_and_test: | |
| name: Build & Test | |
| runs-on: ubuntu-latest | |
| # 20 not 15: the SonarCloud quality-gate wait adds blocking time on top of build + e2e. | |
| timeout-minutes: 20 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.draft == false | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 # full history so SonarCloud has SCM blame — avoids the shallow-clone warning | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 26 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 | |
| with: | |
| version: 10 | |
| run_install: false | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Format Check | |
| run: make format-check | |
| - name: Lint | |
| run: make lint | |
| - name: Typecheck | |
| run: make typecheck | |
| - name: Resolve Playwright version | |
| id: pw | |
| # Key the browser cache on the exact installed version: a bump misses (fresh browsers), a | |
| # match restores them so a healthy run never reaches the network for the download. | |
| run: echo "version=$(node -p 'require("@playwright/test/package.json").version')" >> "$GITHUB_OUTPUT" | |
| - name: Cache Playwright browsers | |
| id: playwright-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ steps.pw.outputs.version }} | |
| - name: Install Playwright (chromium only) | |
| # The suite drives chromium only (vitest browser tests + e2e), so install just that — fewer | |
| # browsers and system libs to fetch. Bounded + retried: a transient apt/mirror hang must fail | |
| # THIS step fast and self-heal, not stall until the job timeout cancels the whole run (which | |
| # reads as a CI failure, not the infra flake it is). Browsers restore from the cache on a hit; | |
| # the apt system libs reinstall every run, so the retry is what guards the flaky part. | |
| timeout-minutes: 10 | |
| run: | | |
| set -euo pipefail | |
| for attempt in 1 2 3; do | |
| if timeout 180 pnpm exec playwright install --with-deps chromium; then | |
| exit 0 | |
| fi | |
| echo "::warning::playwright install attempt ${attempt} failed or timed out; retrying" | |
| sleep 10 | |
| done | |
| echo "::error::playwright install failed after 3 attempts" | |
| exit 1 | |
| - name: Unit Tests | |
| run: make test | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| slug: anchildress1/save-the-sun | |
| files: ./coverage/lcov.info | |
| - name: Upload test results to Codecov | |
| # Runs even when the suite failed, so Test Analytics still sees the failures. The standalone | |
| # test-results-action is deprecated (and still on Node 20); the coverage action now carries | |
| # test results too via report_type, so reuse it. | |
| if: ${{ !cancelled() }} | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| slug: anchildress1/save-the-sun | |
| files: ./test-report.junit.xml | |
| report_type: test_results | |
| - name: Build | |
| run: make build | |
| - name: E2E Tests | |
| run: make e2e | |
| - name: SonarQube Cloud Scan | |
| # The 40-char hex is the action's pinned commit SHA (per our SHA-pin convention), | |
| # not a SonarQube API key — suppress the generic secret matcher's false positive. | |
| # nosemgrep: generic.secrets.security.detected-sonarqube-docs-api-key.detected-sonarqube-docs-api-key | |
| uses: SonarSource/sonarqube-scan-action@713881670b6b3676cda39549040e2d88c70d582e # v8.2.0 | |
| env: | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| SONAR_HOST_URL: https://sonarcloud.io | |
| with: | |
| # Block until the Compute Engine finishes so the issue count below is final, not stale. | |
| # Bounded wait so a slow Sonar queue fails this step deterministically instead of via the | |
| # GitHub job timeout (which would read as an infra flake, not a gate failure). | |
| args: > | |
| -Dsonar.qualitygate.wait=true | |
| -Dsonar.qualitygate.timeout=600 | |
| - name: Enforce zero Sonar issues | |
| # Why this exists instead of a quality-gate condition: the free SonarCloud plan only allows | |
| # the built-in "Sonar way" gate (no custom gate can be created or assigned), and that gate | |
| # is rating-based — a MINOR issue keeps the maintainability rating at A, so it passes with | |
| # issues present. We want zero issues of ANY severity, so we assert it here from the issues | |
| # API. Runs after the scan's qualitygate.wait, so the analysis is computed and the count is | |
| # authoritative. Replace with a gate condition (new_violations > 0) if the plan is upgraded. | |
| env: | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$EVENT_NAME" = "pull_request" ]; then | |
| scope="pullRequest=${PR_NUMBER}" | |
| else | |
| scope="branch=main" | |
| fi | |
| api="https://sonarcloud.io/api/issues/search?componentKeys=anchildress1_save-the-sun&${scope}&resolved=false&ps=500" | |
| first=$(curl -sfSL -u "${SONAR_TOKEN}:" "${api}&p=1") | |
| count=$(echo "$first" | jq -r '.total') | |
| echo "Unresolved Sonar issues for ${scope}: ${count}" | |
| [ "${count}" = "0" ] && exit 0 | |
| # Page through ALL issues (ps=500 max) so the failure output annotates every offending | |
| # issue, not just the first page — debuggability when clearing a backlog. | |
| pages=$(( (count + 499) / 500 )) | |
| for p in $(seq 1 "${pages}"); do | |
| if [ "${p}" = "1" ]; then | |
| page="$first" | |
| else | |
| page=$(curl -sfSL -u "${SONAR_TOKEN}:" "${api}&p=${p}") | |
| fi | |
| echo "$page" | jq -r '.issues[] | "::error::[\(.severity)] \(.component | sub("^[^:]+:";"")):\(.textRange.startLine // 0) \(.rule) — \(.message)"' | |
| done | |
| echo "::error::SonarCloud reports ${count} unresolved issue(s); CI fails on any severity." | |
| exit 1 |