trunk-merge/pr-106380/c25d1bc2-cb62-4e5a-85ac-178e2a839002 #13196
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: Desktop React Doctor | |
| # Advisory only: posts a sticky PR comment with findings for changed desktop | |
| # files and never fails the PR. The source repo's --blocking enforcement step | |
| # is deliberately not ported. | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| # Workflow-level paths only work because react-doctor is not a required | |
| # check. If it ever becomes required, move the skip into a gate job like | |
| # desktop-ci.yml, or path-skipped PRs will wait on it forever. | |
| paths: | |
| - 'products/desktop/**/*.ts' | |
| - 'products/desktop/**/*.tsx' | |
| - 'products/desktop/**/*.jsx' | |
| - '.github/workflows/desktop-react-doctor.yml' | |
| - '.github/scripts/desktop/react-doctor-comment.mjs' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| concurrency: | |
| group: desktop-react-doctor-${{ github.head_ref || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| react-doctor: | |
| runs-on: depot-ubuntu-24.04 | |
| timeout-minutes: 15 | |
| # Skipped on trunk-merge/** heads: merge-queue PRs are ephemeral and every | |
| # constituent PR already ran this in full. | |
| if: ${{ !startsWith(github.head_ref, 'trunk-merge/') }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| filter: blob:none | |
| persist-credentials: false | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 22 | |
| package-manager-cache: false | |
| - id: scan | |
| name: Run react-doctor on changed desktop files | |
| shell: bash | |
| working-directory: products/desktop | |
| env: | |
| NO_COLOR: '1' | |
| REACT_DOCTOR_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| # -e omitted: exit codes are captured and inspected explicitly. | |
| set -uo pipefail | |
| CHANGED="${RUNNER_TEMP}/react-doctor-changed-files.txt" | |
| # --relative: react-doctor runs from products/desktop, so the changed | |
| # file list must be relative to it, not to the repo root. | |
| if ! git diff --name-only --relative --diff-filter=ACMR "${REACT_DOCTOR_BASE_SHA}...${HEAD_SHA}" -- . > "$CHANGED"; then | |
| echo "Could not diff ${REACT_DOCTOR_BASE_SHA}...${HEAD_SHA}; failing rather than skipping the scan." >&2 | |
| echo "exit-code=1" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| if [ ! -s "$CHANGED" ]; then | |
| echo "No changed files; nothing for react-doctor to scan." | |
| echo "exit-code=0" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| REPORT="${RUNNER_TEMP}/react-doctor-report.json" | |
| status=0 | |
| # Pinned: products/desktop/.npmrc's minimum release age makes @latest | |
| # intermittently unresolvable in CI. Bump deliberately, not via latest. | |
| npx --yes react-doctor@0.9.1 . --blocking error --changed-files-from "$CHANGED" --json --json-compact --no-telemetry > "$REPORT" || status=$? | |
| echo "exit-code=$status" >> "$GITHUB_OUTPUT" | |
| echo "report=$REPORT" >> "$GITHUB_OUTPUT" | |
| if [ "$status" -ne 0 ]; then | |
| echo "react-doctor exited with status ${status}; advisory only, not failing the job." >&2 | |
| cat "$REPORT" >&2 || true | |
| fi | |
| - name: Render report summary | |
| id: render | |
| if: ${{ always() && steps.scan.outputs.report != '' }} | |
| shell: bash | |
| env: | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| GITHUB_SERVER_URL: ${{ github.server_url }} | |
| REACT_DOCTOR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| REACT_DOCTOR_PATH_PREFIX: products/desktop | |
| REPORT: ${{ steps.scan.outputs.report }} | |
| run: | | |
| set -euo pipefail | |
| BODY="${RUNNER_TEMP}/react-doctor-comment.md" | |
| node "${GITHUB_WORKSPACE}/.github/scripts/desktop/react-doctor-comment.mjs" "$REPORT" "$BODY" | |
| cat "$BODY" >> "$GITHUB_STEP_SUMMARY" | |
| echo "body-path=$BODY" >> "$GITHUB_OUTPUT" | |
| - name: Upsert sticky PR comment | |
| # Fork PRs only get a read-only token, so the upsert would fail there; | |
| # skip it explicitly instead of failing silently. Fork contributors | |
| # still get the report via the job summary above. | |
| if: ${{ always() && steps.render.outputs.body-path != '' && github.event.pull_request.head.repo.full_name == github.repository }} | |
| continue-on-error: true | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| BODY: ${{ steps.render.outputs.body-path }} | |
| run: | | |
| set -uo pipefail | |
| jq -Rs '{body: .}' "$BODY" > "${RUNNER_TEMP}/react-doctor-payload.json" | |
| marker="<!-- desktop-react-doctor:summary -->" | |
| existing=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate \ | |
| --jq ".[] | select(.body | startswith(\"${marker}\")) | .id" | head -n1 || true) | |
| if [ -n "$existing" ]; then | |
| gh api -X PATCH "repos/${GITHUB_REPOSITORY}/issues/comments/${existing}" --input "${RUNNER_TEMP}/react-doctor-payload.json" >/dev/null | |
| else | |
| gh api -X POST "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --input "${RUNNER_TEMP}/react-doctor-payload.json" >/dev/null | |
| fi |