Repository navigation
fix(desktop): log the error class, not the raw error, in the generation console warnings #2648
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: 🔎 Quality | |
| # ────────────────────────────────────────────────────────────────────── | |
| # Advisory quality + perf (consolidated from quality/rust-quality/benchmark). | |
| # None blocks merge. | |
| # JS/docs (PR): typos · links (lychee) · knip (dead code) · i18n key drift · jsx-a11y | |
| # Rust (PR): cargo-hack (each-feature) · cargo-mutants (--in-diff) | |
| # Perf : criterion export-render benchmark — records the baseline on | |
| # push-to-main (Rust changes only); never runs on PRs — opt in | |
| # per branch via workflow_dispatch. | |
| # The benchmark job is the ONLY one with elevated permissions (contents: write + | |
| # the deploy key + the Pages PAT); per-job `permissions:`/`if:` keep every other | |
| # job least-privilege and PR-scoped. A `changes` gate preserves the Rust-only | |
| # filter for benchmark. | |
| # ────────────────────────────────────────────────────────────────────── | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| # File-level least privilege; only the benchmark job widens this. | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: quality-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Path gate so the perf benchmark only runs when Rust actually changed | |
| # (mirrors the former benchmark.yml paths filter, now per-job). | |
| changes: | |
| name: 🧭 Detect Changes | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| rust: ${{ steps.filter.outputs.rust }} | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🧭 Path filter | |
| id: filter | |
| uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 | |
| with: | |
| filters: | | |
| rust: | |
| - 'apps/desktop/src-tauri/**' | |
| - '.github/workflows/quality.yml' | |
| # ── JS / docs quality (PR + manual; never on push-to-main) ─────────────────── | |
| typos: | |
| name: 🔤 Typos | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🧰 Install typos | |
| id: install-typos | |
| continue-on-error: true | |
| uses: taiki-e/install-action@4cef1412cce204788f482e778a0b9187f9626a29 # v2 | |
| with: | |
| tool: typos | |
| # Advisory: run typos ourselves so the findings land in the job Summary | |
| # (the crate-ci action only emits inline annotations). Never fails the job. | |
| - name: 🔤 Spell check (advisory) | |
| continue-on-error: true | |
| run: | | |
| set +e | |
| if ! command -v typos >/dev/null 2>&1; then | |
| { | |
| echo "## 🔤 Typos" | |
| echo "⚠️ typos binary unavailable — check skipped." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| fi | |
| typos --format brief > "$RUNNER_TEMP/typos.txt" 2>&1 | |
| code=$? | |
| { | |
| echo "## 🔤 Typos" | |
| if [ "$code" -eq 0 ]; then | |
| echo "✅ No typos found." | |
| else | |
| echo "Advisory — does not block merge. Possible typos:" | |
| echo "" | |
| echo '```' | |
| cat "$RUNNER_TEMP/typos.txt" | |
| echo '```' | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| links: | |
| name: 🔗 Link Check | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🔗 Lychee link check (advisory) | |
| uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0 | |
| with: | |
| args: "--no-progress 'README.md' 'docs/**/*.md'" | |
| fail: false | |
| knip: | |
| name: 🧹 Knip (dead code) | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 📦 Setup Node + pnpm | |
| uses: ./.github/actions/setup-node-pnpm | |
| # Advisory: knip's markdown reporter writes a readable table to the job | |
| # Summary. Never fails the job. | |
| - name: 🧹 Run knip (advisory) | |
| continue-on-error: true | |
| run: | | |
| set +e | |
| pnpm exec knip --reporter markdown > "$RUNNER_TEMP/knip.md" 2>&1 | |
| code=$? | |
| { | |
| echo "## 🧹 Knip (dead code)" | |
| if [ "$code" -eq 0 ]; then | |
| echo "✅ No dead code found." | |
| else | |
| echo "Advisory — does not block merge." | |
| echo "" | |
| cat "$RUNNER_TEMP/knip.md" | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| i18n: | |
| name: 🌐 i18n Keys | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 📦 Setup Node + pnpm | |
| uses: ./.github/actions/setup-node-pnpm | |
| # i18next-cli rewrites the locale files from t() usage; a non-empty diff | |
| # means missing keys (or sort drift). Advisory: report, then restore. | |
| - name: 🌐 Check translation keys (advisory) | |
| continue-on-error: true | |
| run: | | |
| pnpm --filter @ajh/translations i18n:extract | |
| if git diff --quiet -- packages/translations/src/locales; then | |
| echo "Locale files are in sync with t() usage." | |
| else | |
| echo "::warning::i18next-cli would change the locale files (missing keys / sort drift):" | |
| git --no-pager diff -- packages/translations/src/locales | |
| git checkout -- packages/translations/src/locales | |
| fi | |
| a11y-lint: | |
| name: ♿ a11y Lint | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 📦 Setup Node + pnpm | |
| uses: ./.github/actions/setup-node-pnpm | |
| # jsx-a11y via a SEPARATE config so the strict main lint is unaffected. | |
| # Advisory: capture the ESLint report into the job Summary. Never fails. | |
| - name: ♿ ESLint jsx-a11y (advisory) | |
| continue-on-error: true | |
| run: | | |
| set +e | |
| pnpm exec eslint --config eslint.a11y.config.mjs 'apps/desktop/src/renderer/**/*.tsx' 'packages/ui/src/**/*.tsx' -f stylish > "$RUNNER_TEMP/a11y.txt" 2>&1 | |
| code=$? | |
| { | |
| echo "## ♿ a11y Lint (jsx-a11y)" | |
| if [ "$code" -eq 0 ]; then | |
| echo "✅ No accessibility problems." | |
| else | |
| echo "Advisory — does not block merge." | |
| echo "" | |
| echo '```' | |
| cat "$RUNNER_TEMP/a11y.txt" | |
| echo '```' | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| # ── Non-Linux compile checks (PR + manual; never on push-to-main) ─────────── | |
| # Every other Rust job runs on ubuntu-latest, and before these jobs `macos-` | |
| # and `windows-` appeared in no workflow but release.yml. So any code behind a | |
| # macOS- or Windows-specific cfg compiled NOWHERE until a release was cut, | |
| # which is the most expensive place to find a break. Cargo.toml already | |
| # carries a comment about being burned by exactly this. | |
| # | |
| # Precisely: `cfg(unix)` / `cfg(not(windows))` branches ARE already compiled by | |
| # the ubuntu jobs — the gap was only ever `#[cfg(target_os = "macos")]`, | |
| # `#[cfg(windows)]` and other platform-exclusive predicates. | |
| # | |
| # Check only — no bundling, no tests — so these stay cheap (the macOS runner | |
| # bills at 10x, Windows at 2x). | |
| cargo-check-macos: | |
| name: 🍎 macOS compile check | |
| if: github.event_name != 'push' | |
| runs-on: macos-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🦀 Setup Rust (Tauri) | |
| uses: ./.github/actions/setup-rust | |
| - name: 🦀 cargo check (all targets) | |
| working-directory: apps/desktop/src-tauri | |
| run: cargo check --all-targets --locked | |
| cargo-check-windows: | |
| name: 🪟 Windows compile check | |
| if: github.event_name != 'push' | |
| runs-on: windows-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🦀 Setup Rust (Tauri) | |
| uses: ./.github/actions/setup-rust | |
| - name: 🦀 cargo check (all targets) | |
| working-directory: apps/desktop/src-tauri | |
| run: cargo check --all-targets --locked | |
| # This job is `check` only (see the comment above), so `std::fs::rename` | |
| # over an EXISTING file (postings::InteractionStore::save's write-then- | |
| # rename) was never actually EXECUTED on Windows — rename-over-existing | |
| # has different underlying semantics per platform (MoveFileExW needs | |
| # MOVEFILE_REPLACE_EXISTING; POSIX rename(2) replaces unconditionally), | |
| # and this repo has a recorded history of platform-exclusive code | |
| # compiling nowhere until release. One narrowly-targeted `cargo test`, | |
| # not the whole suite — the point is this ONE rename call, not Windows | |
| # test coverage generally, which would cost real runner minutes (billed | |
| # at 2x) for no new signal on everything else already proven on Linux. | |
| - name: 🪟 Atomic file-replace test (Windows rename-over-existing) | |
| working-directory: apps/desktop/src-tauri | |
| run: cargo test --lib postings::interactions::tests::persistence::save_replaces_the_file_atomically_and_leaves_no_temp_file --locked | |
| # ── MCP stdio smoke (PR + manual; never on push-to-main) ───────────────────── | |
| # ADR-040 named macOS/Linux smoke of `ajh-tauri agent mcp` as its open gap. | |
| # LINUX IS NOT IN THIS MATRIX ON PURPOSE: `tests/mcp_smoke.rs` is an ordinary | |
| # integration test, so the gating ubuntu `tests` job in ci-pipeline.yml | |
| # already runs it. This job adds the two platforms nothing else executes on. | |
| # | |
| # Unlike the two compile-check jobs above, this one LINKS the binary | |
| # (`CARGO_BIN_EXE_ajh-tauri`), which is why it gets its own timeout rather | |
| # than sharing theirs. It needs no frontend dist: a debug build is dev-mode, | |
| # and tauri-codegen embeds empty assets when a devUrl is configured. | |
| # | |
| # A debug binary is console-subsystem, so this does NOT prove the release | |
| # Windows GUI-subsystem stdout path (`platform/windows_console.rs`) — the | |
| # stdio discipline it proves is the console-subsystem one. | |
| # | |
| # ADVISORY, like every other extra-signal step in this workflow: a real | |
| # regression here fails the gating ubuntu `tests` job too (same test file), | |
| # so blocking a PR on the two EXTRA platforms would buy nothing but flake — | |
| # this job spawns a child process and drives it over pipes, on the runners | |
| # with the least predictable process timing. | |
| mcp-smoke: | |
| name: 🔌 MCP stdio smoke (${{ matrix.os }}) | |
| if: github.event_name != 'push' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [macos-latest, windows-latest] | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🦀 Setup Rust (Tauri) | |
| uses: ./.github/actions/setup-rust | |
| - name: 🔌 Scripted MCP stdio sessions (advisory) | |
| continue-on-error: true | |
| working-directory: apps/desktop/src-tauri | |
| run: cargo test --test mcp_smoke --locked | |
| # ── Rust test-quality (PR + manual; never on push-to-main) ─────────────────── | |
| cargo-hack: | |
| name: 🦀 Feature combinations | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 1 | |
| - name: 🦀 Setup Rust (Tauri) | |
| uses: ./.github/actions/setup-rust | |
| - name: 🧰 Install cargo-hack | |
| uses: taiki-e/install-action@4cef1412cce204788f482e778a0b9187f9626a29 # v2 | |
| with: | |
| tool: cargo-hack | |
| - name: 🦀 Check each feature (advisory) | |
| continue-on-error: true | |
| working-directory: apps/desktop/src-tauri | |
| run: cargo hack --each-feature check --all-targets | |
| cargo-mutants: | |
| name: 🦀 Mutation testing (PR diff) | |
| if: github.event_name != 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 # full history so the merge-base diff for --in-diff resolves | |
| - name: 🦀 Setup Rust (Tauri) | |
| uses: ./.github/actions/setup-rust | |
| - name: 🧰 Install cargo-mutants | |
| uses: taiki-e/install-action@4cef1412cce204788f482e778a0b9187f9626a29 # v2 | |
| with: | |
| tool: cargo-mutants | |
| - name: 🦀 Mutation testing on the diff (advisory) | |
| continue-on-error: true | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| run: | | |
| if [ "${{ github.event_name }}" != "pull_request" ]; then | |
| echo "Manual run — full-crate mutation testing is slow; this job only runs --in-diff on PRs." | |
| exit 0 | |
| fi | |
| git -C "$GITHUB_WORKSPACE/apps/desktop/src-tauri" diff --relative "$BASE_SHA...HEAD" > "$RUNNER_TEMP/mutants.diff" || true | |
| if [ ! -s "$RUNNER_TEMP/mutants.diff" ]; then | |
| echo "No Rust changes under apps/desktop/src-tauri in this PR — skipping mutation testing." | |
| exit 0 | |
| fi | |
| cd apps/desktop/src-tauri | |
| cargo mutants --in-diff "$RUNNER_TEMP/mutants.diff" --timeout 180 || true | |
| - name: 📊 Upload mutants report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: mutants-${{ github.run_id }} | |
| path: apps/desktop/src-tauri/mutants.out/ | |
| retention-days: 7 | |
| if-no-files-found: ignore | |
| # ── Perf benchmark — push-to-main baseline; opt-in elsewhere ───────────────── | |
| # The ONLY elevated job: commits the refreshed dashboard back to main (deploy | |
| # key) and kicks the Pages deploy (PAT). Runs on push-to-main when Rust changed | |
| # (the `changes` gate) and on manual dispatch. NEVER on pull_request events — | |
| # to benchmark a PR, run this workflow via workflow_dispatch on the PR branch | |
| # (Actions → Quality → Run workflow). | |
| benchmark: | |
| name: 📈 Export render | |
| needs: changes | |
| if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && needs.changes.outputs.rust == 'true') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: write # commit benchmark history to apps/landing/public/benchmarks on main (push runs) | |
| pull-requests: write # comment on a PR when a result regresses | |
| steps: | |
| - name: 🛡️ Harden Runner | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| # Full history + the release deploy key so the push-to-main run can | |
| # commit the refreshed dashboard back to main. PR runs check out WITHOUT | |
| # the key (and without persisted credentials): `cargo bench` executes PR | |
| # code, which must never see a secret that can push to main. | |
| - name: 📥 Checkout Repository (push/dispatch — with deploy key) | |
| if: github.event_name != 'pull_request' | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| ssh-key: ${{ secrets.RELEASE_DEPLOY_KEY }} | |
| - name: 📥 Checkout Repository (PR — no credentials) | |
| if: github.event_name == 'pull_request' | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: 🦀 Setup Rust (Tauri) | |
| uses: ./.github/actions/setup-rust | |
| - name: 📈 Run export benchmarks | |
| working-directory: apps/desktop/src-tauri | |
| run: cargo bench --bench export_render --locked -- --output-format bencher | tee output.txt | |
| - name: 📊 Store result & alert on regression (advisory) | |
| uses: benchmark-action/github-action-benchmark@4322e5726e6334590d251fc4f92bec0efafc45dc # v1.22.2 | |
| continue-on-error: true | |
| with: | |
| name: Export render | |
| tool: cargo | |
| output-file-path: apps/desktop/src-tauri/output.txt | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| gh-pages-branch: main | |
| benchmark-data-dir-path: apps/landing/public/benchmarks | |
| skip-fetch-gh-pages: true | |
| auto-push: false | |
| # Bound the series. Without this the action appends forever: 199 entries | |
| # had accumulated over 76 days (~2.6/day at ~7.7 KB each, because every | |
| # entry embeds a full commit object for three benches), making data.js | |
| # 1.5 MB and growing ~20 KB/day — and it is committed to main on every | |
| # run, so the cost compounds in git history rather than replacing. | |
| # | |
| # 100 entries is ~5 weeks at the current cadence, far more resolution | |
| # than the /mission-control sparkline or the regression alert needs, | |
| # and it halves the file on the next run. The alert compares against the | |
| # previous entry, so trimming old points cannot weaken it. | |
| max-items-in-chart: 100 | |
| comment-on-alert: true | |
| alert-threshold: '150%' | |
| fail-on-alert: false | |
| alert-comment-cc-users: '@saeedkolivand' | |
| - name: 📤 Commit benchmark data | |
| id: commit | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| if [ -z "$(git log origin/main..HEAD --oneline)" ]; then | |
| echo "Benchmark data unchanged — nothing to push." | |
| exit 0 | |
| fi | |
| git commit --amend -m "chore: update export benchmark data [skip ci]" | |
| remote="git@github.com:saeedkolivand/ai-job-hunter-app.git" | |
| # origin/main can advance during the ~16-min bench run, so a plain push | |
| # races and is rejected. Rebase the single [skip ci] benchmark commit | |
| # onto the latest origin/main and retry the push a few times. | |
| for attempt in 1 2 3 4 5; do | |
| git fetch origin main | |
| if ! git rebase origin/main; then | |
| git rebase --abort || true | |
| echo "::error::benchmark commit failed to rebase onto origin/main" | |
| exit 1 | |
| fi | |
| if git push "$remote" HEAD:main; then | |
| echo "committed=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "push rejected (attempt $attempt/5) — origin/main moved, retrying after backoff" | |
| sleep $((attempt * 5)) | |
| done | |
| echo "::error::failed to push benchmark data to main after 5 attempts" | |
| exit 1 | |
| - name: 🌐 Trigger Pages deploy | |
| if: steps.commit.outputs.committed == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
| run: gh workflow run pages.yml --ref main |