@@ -20,9 +20,34 @@ concurrency:
2020 group : ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.event_name == 'workflow_dispatch' }}-${{ github.event_name == 'schedule' }}
2121 cancel-in-progress : true
2222
23+ permissions :
24+ contents : read
25+
2326jobs :
27+ changed-files :
28+ name : Get changed files
29+ uses : ./.github/workflows/_get-changed-files.yml
30+ with :
31+ include-push-diff : true
32+
33+ run-decision :
34+ name : CI run decision
35+ uses : ./.github/workflows/_ci-run-decision.yml
36+
2437 test-metal-builds :
2538 name : test-executorch-metal-build
39+ needs : [changed-files, run-decision]
40+ # Path-filtered: mirrors the workflow-level pull_request `paths:`
41+ # filter so push commits that don't touch metal-relevant paths skip
42+ # this job on non-sampled commits. See _ci-run-decision.yml for
43+ # the sampling policy.
44+ if : |
45+ contains(needs.changed-files.outputs.changed-files, 'backends/apple/metal') ||
46+ contains(needs.changed-files.outputs.changed-files, 'backends/aoti') ||
47+ contains(needs.changed-files.outputs.changed-files, 'examples/models/qwen3_5_moe') ||
48+ contains(needs.changed-files.outputs.changed-files, 'extension/llm/export') ||
49+ contains(needs.changed-files.outputs.changed-files, '.github/workflows/metal.yml') ||
50+ needs.run-decision.outputs.is-full-run == 'true'
2651 uses : pytorch/test-infra/.github/workflows/macos_job.yml@main
2752 with :
2853 default-packages : " "
4065
4166 test-metal-modules :
4267 name : test-metal-backend-modules
68+ needs : [changed-files, run-decision]
69+ if : |
70+ contains(needs.changed-files.outputs.changed-files, 'backends/apple/metal') ||
71+ contains(needs.changed-files.outputs.changed-files, 'backends/aoti') ||
72+ contains(needs.changed-files.outputs.changed-files, 'examples/models/qwen3_5_moe') ||
73+ contains(needs.changed-files.outputs.changed-files, 'extension/llm/export') ||
74+ contains(needs.changed-files.outputs.changed-files, '.github/workflows/metal.yml') ||
75+ needs.run-decision.outputs.is-full-run == 'true'
4376 uses : pytorch/test-infra/.github/workflows/macos_job.yml@main
4477 with :
4578 default-packages : " "
6598
6699 test-metal-qwen35-moe-tiny :
67100 name : test-metal-qwen35-moe-tiny
101+ needs : [changed-files, run-decision]
102+ if : |
103+ contains(needs.changed-files.outputs.changed-files, 'backends/apple/metal') ||
104+ contains(needs.changed-files.outputs.changed-files, 'backends/aoti') ||
105+ contains(needs.changed-files.outputs.changed-files, 'examples/models/qwen3_5_moe') ||
106+ contains(needs.changed-files.outputs.changed-files, 'extension/llm/export') ||
107+ contains(needs.changed-files.outputs.changed-files, '.github/workflows/metal.yml') ||
108+ needs.run-decision.outputs.is-full-run == 'true'
68109 uses : pytorch/test-infra/.github/workflows/macos_job.yml@main
69110 with :
70111 default-packages : " "
@@ -162,8 +203,21 @@ jobs:
162203
163204 export-model-metal-artifact :
164205 name : export-model-metal-artifact
165- # Skip this job if the pull request is from a fork (HuggingFace secrets are not available)
166- if : github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
206+ # Skip this job if the pull request is from a fork (HuggingFace secrets are not available).
207+ # Path-filtered on push: mirrors the workflow-level pull_request `paths:`
208+ # filter so push commits that don't touch metal-relevant paths skip
209+ # this job on non-sampled commits.
210+ needs : [changed-files, run-decision]
211+ if : |
212+ (github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request') &&
213+ (
214+ contains(needs.changed-files.outputs.changed-files, 'backends/apple/metal') ||
215+ contains(needs.changed-files.outputs.changed-files, 'backends/aoti') ||
216+ contains(needs.changed-files.outputs.changed-files, 'examples/models/qwen3_5_moe') ||
217+ contains(needs.changed-files.outputs.changed-files, 'extension/llm/export') ||
218+ contains(needs.changed-files.outputs.changed-files, '.github/workflows/metal.yml') ||
219+ needs.run-decision.outputs.is-full-run == 'true'
220+ )
167221 uses : pytorch/test-infra/.github/workflows/macos_job.yml@main
168222 secrets : inherit
169223 strategy :
@@ -234,7 +288,22 @@ jobs:
234288
235289 test-model-metal-e2e :
236290 name : test-model-metal-e2e
237- needs : export-model-metal-artifact
291+ # Same path filter as export-model-metal-artifact above. Also
292+ # explicitly gated on the export job succeeding — when needs: jobs
293+ # are *skipped* (e.g. fork PR), GitHub still evaluates this if:,
294+ # so without the explicit success-check this job would run and then
295+ # fail trying to download an artifact that was never produced.
296+ needs : [changed-files, export-model-metal-artifact, run-decision]
297+ if : |
298+ needs.export-model-metal-artifact.result == 'success' &&
299+ (
300+ contains(needs.changed-files.outputs.changed-files, 'backends/apple/metal') ||
301+ contains(needs.changed-files.outputs.changed-files, 'backends/aoti') ||
302+ contains(needs.changed-files.outputs.changed-files, 'examples/models/qwen3_5_moe') ||
303+ contains(needs.changed-files.outputs.changed-files, 'extension/llm/export') ||
304+ contains(needs.changed-files.outputs.changed-files, '.github/workflows/metal.yml') ||
305+ needs.run-decision.outputs.is-full-run == 'true'
306+ )
238307 uses : pytorch/test-infra/.github/workflows/macos_job.yml@main
239308 strategy :
240309 fail-fast : false
0 commit comments