Skip to content

Commit fffbfa4

Browse files
committed
[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 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. This routes cpu-build and cpu-test through the same gate as hifi-build and vision-build so all four run on fork exports, and adds export-checks-start/export-checks-finish to 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.
1 parent 24d8bab commit fffbfa4

1 file changed

Lines changed: 101 additions & 5 deletions

File tree

.github/workflows/build-cadence-runner.yml

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ jobs:
4848
echo "run=${run}" >> "${GITHUB_OUTPUT}"
4949
5050
cpu-build:
51-
if: github.event_name != 'pull_request_target'
51+
needs: gate
52+
if: needs.gate.outputs.run-cadence == 'true'
5253
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
5354
permissions:
5455
id-token: write
@@ -58,7 +59,7 @@ jobs:
5859
runner: linux.2xlarge
5960
docker-image: ci-image:executorch-ubuntu-22.04-clang12
6061
submodules: recursive
61-
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
62+
ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}
6263
timeout: 90
6364
upload-artifact: cadence-runner-build
6465
script: |
@@ -74,14 +75,14 @@ jobs:
7475
cp cmake-out/backends/cadence/cadence_runner "${RUNNER_ARTIFACT_DIR}/"
7576
7677
cpu-test:
77-
needs: cpu-build
78-
if: github.event_name != 'pull_request_target'
78+
needs: [gate, cpu-build]
79+
if: needs.gate.outputs.run-cadence == 'true'
7980
permissions:
8081
id-token: write
8182
contents: read
8283
uses: ./.github/workflows/_test_cadence.yml
8384
with:
84-
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
85+
ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}
8586

8687
# Cross-compile cadence_executor_runner for each Cadence Xtensa core, one job
8788
# per backend so they show as separate lines (no matrix grouping). Shared logic
@@ -108,3 +109,98 @@ jobs:
108109
with:
109110
backend: vision
110111
ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}
112+
113+
# Fork exports run via pull_request_target, whose native check runs attach to
114+
# the base SHA and never surface on the PR. Mirror per-job check runs onto the
115+
# PR head SHA so each cadence job shows up as its own check on the export PR,
116+
# linking to its logs. Same-repo PRs run via pull_request and report natively.
117+
export-checks-start:
118+
needs: gate
119+
if: github.event_name == 'pull_request_target' && needs.gate.outputs.run-cadence == 'true'
120+
runs-on: ubuntu-latest
121+
permissions:
122+
checks: write
123+
outputs:
124+
ids: ${{ steps.create.outputs.ids }}
125+
steps:
126+
- id: create
127+
uses: actions/github-script@v7
128+
with:
129+
script: |
130+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
131+
const jobs = ['cpu-build', 'cpu-test', 'hifi-build', 'vision-build'];
132+
const ids = {};
133+
for (const job of jobs) {
134+
const res = await github.rest.checks.create({
135+
owner: context.repo.owner,
136+
repo: context.repo.repo,
137+
name: `cadence (export) / ${job}`,
138+
head_sha: context.payload.pull_request.head.sha,
139+
status: 'in_progress',
140+
details_url: runUrl,
141+
output: {
142+
title: 'Running on the export workflow run',
143+
summary: `Mirrored from the pull_request_target run (native checks attach to the base SHA). See ${runUrl}`,
144+
},
145+
});
146+
ids[job] = res.data.id;
147+
// Persist after each create so a mid-loop failure still propagates
148+
// partial IDs to the finish job (which then updates, not duplicates).
149+
core.setOutput('ids', JSON.stringify(ids));
150+
}
151+
152+
export-checks-finish:
153+
needs: [gate, cpu-build, cpu-test, hifi-build, vision-build, export-checks-start]
154+
if: always() && github.event_name == 'pull_request_target' && needs.gate.outputs.run-cadence == 'true'
155+
runs-on: ubuntu-latest
156+
permissions:
157+
checks: write
158+
actions: read
159+
steps:
160+
- uses: actions/github-script@v7
161+
env:
162+
NEEDS: ${{ toJSON(needs) }}
163+
IDS: ${{ needs.export-checks-start.outputs.ids }}
164+
with:
165+
script: |
166+
const needs = JSON.parse(process.env.NEEDS);
167+
const ids = JSON.parse(process.env.IDS || '{}');
168+
const owner = context.repo.owner;
169+
const repo = context.repo.repo;
170+
const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`;
171+
const jobs = ['cpu-build', 'cpu-test', 'hifi-build', 'vision-build'];
172+
// Link each check to its inner reusable-workflow job for a direct log
173+
// link; fall back to the run page when a job name is not matchable.
174+
const { data } = await github.rest.actions.listJobsForWorkflowRun({
175+
owner, repo, run_id: context.runId, per_page: 100,
176+
});
177+
const urlFor = (job) => {
178+
const m = data.jobs.find(j => j.name === job || j.name.startsWith(`${job} /`));
179+
return m ? m.html_url : runUrl;
180+
};
181+
// Valid check-run conclusions; anything unexpected fails closed.
182+
const allowed = ['success', 'failure', 'cancelled', 'skipped', 'timed_out'];
183+
for (const job of jobs) {
184+
const result = (needs[job] && needs[job].result) || 'unknown';
185+
const conclusion = allowed.includes(result) ? result : 'failure';
186+
const fields = {
187+
owner,
188+
repo,
189+
status: 'completed',
190+
conclusion,
191+
details_url: urlFor(job),
192+
output: {
193+
title: `${job}: ${result}`,
194+
summary: `Result mirrored from the export workflow run: ${runUrl}`,
195+
},
196+
};
197+
if (ids[job]) {
198+
await github.rest.checks.update({ ...fields, check_run_id: ids[job] });
199+
} else {
200+
await github.rest.checks.create({
201+
...fields,
202+
name: `cadence (export) / ${job}`,
203+
head_sha: context.payload.pull_request.head.sha,
204+
});
205+
}
206+
}

0 commit comments

Comments
 (0)