From 481dcac1ec9fa5fc322bea3d7d10f6fb161a7768 Mon Sep 17 00:00:00 2001 From: Ali Afzal Date: Thu, 18 Jun 2026 01:44:55 -0700 Subject: [PATCH 1/2] [cadence] Run build/test on fork exports and surface per-job checks on the PR The Cadence Build & Test workflow ran its credentialed build/test jobs only on same-repo PRs. On Meta-exported fork PRs (labeled meta-exported + CLA Signed) the cpu-build and cpu-test jobs were excluded from the fork (pull_request_target) path, and the jobs that did run there did not appear as checks on the PR because pull_request_target check runs attach to the base SHA. Each cadence job now carries an inlined run condition: push/schedule/workflow_dispatch, same-repo pull_request, or a fork pull_request_target labeled CLA Signed + meta-exported. There is no separate gate job; GitHub Actions has no YAML anchors and env is unavailable in job-level if, so the condition is duplicated per job. export-checks-start/export-checks-finish mirror per-job check runs onto the PR head SHA so each cadence job shows up as its own check on the export PR, linking to its logs. Same-repo PRs continue to run via pull_request and report checks natively. Authored with Claude Code. --- .github/workflows/build-cadence-runner.yml | 163 ++++++++++++++++----- 1 file changed, 127 insertions(+), 36 deletions(-) diff --git a/.github/workflows/build-cadence-runner.yml b/.github/workflows/build-cadence-runner.yml index 49f750eeea2..64a0da32e10 100644 --- a/.github/workflows/build-cadence-runner.yml +++ b/.github/workflows/build-cadence-runner.yml @@ -19,36 +19,19 @@ concurrency: cancel-in-progress: true jobs: - gate: - runs-on: ubuntu-latest - outputs: - run-cadence: ${{ steps.decide.outputs.run }} - steps: - - id: decide - env: - EVENT: ${{ github.event_name }} - IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }} - HAS_CLA: ${{ contains(github.event.pull_request.labels.*.name, 'CLA Signed') }} - HAS_EXPORT: ${{ contains(github.event.pull_request.labels.*.name, 'meta-exported') }} - run: | - run=false - case "${EVENT}" in - push|schedule|workflow_dispatch) - run=true - ;; - pull_request) - [ "${IS_FORK}" = "false" ] && run=true - ;; - pull_request_target) - if [ "${IS_FORK}" = "true" ] && [ "${HAS_CLA}" = "true" ] && [ "${HAS_EXPORT}" = "true" ]; then - run=true - fi - ;; - esac - echo "run=${run}" >> "${GITHUB_OUTPUT}" - + # The cadence build/test jobs run when: + # - push / schedule / workflow_dispatch, OR + # - a same-repo pull_request (head is this repo, not a fork), OR + # - a pull_request_target from a fork labeled CLA Signed + meta-exported + # (Meta-exported PRs; the only path that runs credentialed CI on fork code). + # GitHub Actions has no YAML anchors and env is unavailable in job-level if, so + # this condition is duplicated per job below; keep the copies in sync. cpu-build: - if: github.event_name != 'pull_request_target' + if: >- + github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || + (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && + contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main permissions: id-token: write @@ -58,7 +41,7 @@ jobs: runner: linux.2xlarge docker-image: ci-image:executorch-ubuntu-22.04-clang12 submodules: recursive - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }} timeout: 90 upload-artifact: cadence-runner-build script: | @@ -75,21 +58,28 @@ jobs: cpu-test: needs: cpu-build - if: github.event_name != 'pull_request_target' + if: >- + github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || + (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && + contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) permissions: id-token: write contents: read uses: ./.github/workflows/_test_cadence.yml with: - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }} # Cross-compile cadence_executor_runner for each Cadence Xtensa core, one job # per backend so they show as separate lines (no matrix grouping). Shared logic # lives in _xtensa_build.yml. fusion_g3 is omitted until the upstream fusion_g3 # <-> nnlib-FusionG3 API skew is fixed (its runner does not link). hifi-build: - needs: gate - if: needs.gate.outputs.run-cadence == 'true' + if: >- + github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || + (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && + contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) permissions: id-token: write contents: read @@ -99,8 +89,11 @@ jobs: ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }} vision-build: - needs: gate - if: needs.gate.outputs.run-cadence == 'true' + if: >- + github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || + (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && + contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) permissions: id-token: write contents: read @@ -108,3 +101,101 @@ jobs: with: backend: vision ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }} + + # Fork exports run via pull_request_target, whose native check runs attach to + # the base SHA and never surface on the PR. Mirror per-job check runs onto the + # PR head SHA so each cadence job shows up as its own check on the export PR, + # linking to its logs. Same-repo PRs run via pull_request and report natively. + export-checks-start: + if: >- + github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && + contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported') + runs-on: ubuntu-latest + permissions: + checks: write + outputs: + ids: ${{ steps.create.outputs.ids }} + steps: + - id: create + uses: actions/github-script@v7 + with: + script: | + const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; + const jobs = ['cpu-build', 'cpu-test', 'hifi-build', 'vision-build']; + const ids = {}; + for (const job of jobs) { + const res = await github.rest.checks.create({ + owner: context.repo.owner, + repo: context.repo.repo, + name: `cadence (export) / ${job}`, + head_sha: context.payload.pull_request.head.sha, + status: 'in_progress', + details_url: runUrl, + output: { + title: 'Running on the export workflow run', + summary: `Mirrored from the pull_request_target run (native checks attach to the base SHA). See ${runUrl}`, + }, + }); + ids[job] = res.data.id; + // Persist after each create so a mid-loop failure still propagates + // partial IDs to the finish job (which then updates, not duplicates). + core.setOutput('ids', JSON.stringify(ids)); + } + + export-checks-finish: + needs: [cpu-build, cpu-test, hifi-build, vision-build, export-checks-start] + if: >- + always() && github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && + contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported') + runs-on: ubuntu-latest + permissions: + checks: write + actions: read + steps: + - uses: actions/github-script@v7 + env: + NEEDS: ${{ toJSON(needs) }} + IDS: ${{ needs.export-checks-start.outputs.ids }} + with: + script: | + const needs = JSON.parse(process.env.NEEDS); + const ids = JSON.parse(process.env.IDS || '{}'); + const owner = context.repo.owner; + const repo = context.repo.repo; + const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`; + const jobs = ['cpu-build', 'cpu-test', 'hifi-build', 'vision-build']; + // Link each check to its inner reusable-workflow job for a direct log + // link; fall back to the run page when a job name is not matchable. + const { data } = await github.rest.actions.listJobsForWorkflowRun({ + owner, repo, run_id: context.runId, per_page: 100, + }); + const urlFor = (job) => { + const m = data.jobs.find(j => j.name === job || j.name.startsWith(`${job} /`)); + return m ? m.html_url : runUrl; + }; + // Valid check-run conclusions; anything unexpected fails closed. + const allowed = ['success', 'failure', 'cancelled', 'skipped', 'timed_out']; + for (const job of jobs) { + const result = (needs[job] && needs[job].result) || 'unknown'; + const conclusion = allowed.includes(result) ? result : 'failure'; + const fields = { + owner, + repo, + status: 'completed', + conclusion, + details_url: urlFor(job), + output: { + title: `${job}: ${result}`, + summary: `Result mirrored from the export workflow run: ${runUrl}`, + }, + }; + if (ids[job]) { + await github.rest.checks.update({ ...fields, check_run_id: ids[job] }); + } else { + await github.rest.checks.create({ + ...fields, + name: `cadence (export) / ${job}`, + head_sha: context.payload.pull_request.head.sha, + }); + } + } From 673fc64445fc05633940dc1548f9f2ec93c8465d Mon Sep 17 00:00:00 2001 From: Ali Afzal Date: Thu, 18 Jun 2026 02:59:47 -0700 Subject: [PATCH 2/2] [cadence][TEMP TEST] drop pull_request from builds; post results via Checks API only (will revert) --- .github/workflows/build-cadence-runner.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-cadence-runner.yml b/.github/workflows/build-cadence-runner.yml index 64a0da32e10..9ef08ffe08f 100644 --- a/.github/workflows/build-cadence-runner.yml +++ b/.github/workflows/build-cadence-runner.yml @@ -29,7 +29,6 @@ jobs: cpu-build: if: >- github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main @@ -60,7 +59,6 @@ jobs: needs: cpu-build if: >- github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) permissions: @@ -77,7 +75,6 @@ jobs: hifi-build: if: >- github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) permissions: @@ -91,7 +88,6 @@ jobs: vision-build: if: >- github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported')) permissions: @@ -107,9 +103,7 @@ jobs: # PR head SHA so each cadence job shows up as its own check on the export PR, # linking to its logs. Same-repo PRs run via pull_request and report natively. export-checks-start: - if: >- - github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && - contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported') + if: github.event_name == 'pull_request' # TEST: post API checks on pull_request to verify they surface on the PR runs-on: ubuntu-latest permissions: checks: write @@ -144,9 +138,7 @@ jobs: export-checks-finish: needs: [cpu-build, cpu-test, hifi-build, vision-build, export-checks-start] - if: >- - always() && github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && - contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported') + if: always() && github.event_name == 'pull_request' # TEST runs-on: ubuntu-latest permissions: checks: write