2121jobs :
2222 upload :
2323 runs-on : ubuntu-latest
24- # Only run on manual dispatch,
25- # OR if the parent run succeeded and was triggered by a PR from
26- # a branch in the main repo (not a fork)
24+ permissions :
25+ statuses : write
26+ # Only run on manual dispatch,
27+ # OR if the parent run succeeded and was triggered by a PR.
28+ # Fork PRs run through so we can post a "skipped" commit status to the PR
29+ # head and log why; the actual upload steps are guarded by fork-check so no
30+ # dev build is published for fork PRs (they lack DEV_DEPLOY_APP access).
2731 if : |
2832 github.event_name == 'workflow_dispatch' ||
2933 (
30- github.event_name == 'workflow_run' &&
34+ github.event_name == 'workflow_run' &&
3135 github.event.workflow_run.event == 'pull_request' &&
32- github.event.workflow_run.conclusion == 'success' &&
33- github.event.workflow_run.head_repository.full_name == github.repository
36+ github.event.workflow_run.conclusion == 'success'
3437 )
3538 steps :
39+ - name : Check if PR is from a fork
40+ id : fork-check
41+ env :
42+ HEAD_REPO : ${{ github.event.workflow_run.head_repository.full_name }}
43+ REPO : ${{ github.repository }}
44+ run : |
45+ if [ -n "${HEAD_REPO}" ] && [ "${HEAD_REPO}" != "${REPO}" ]; then
46+ echo "::notice::Dev-build upload skipped: PR is from a fork (${HEAD_REPO}). Dev builds are only uploaded for PRs from branches within ${REPO}. A maintainer can trigger a build manually via workflow_dispatch with the PR number as input."
47+ echo "is_fork=true" >> "$GITHUB_OUTPUT"
48+ else
49+ echo "is_fork=false" >> "$GITHUB_OUTPUT"
50+ fi
51+
3652 - name : Get required metadata (PR number, commit SHA, workflow run ID containing artifacts)
3753 id : get-metadata
54+ if : steps.fork-check.outputs.is_fork == 'false'
3855 env :
3956 GH_TOKEN : ${{ github.token }}
4057 GH_EVENT_NAME : ${{ github.event_name }}
91108
92109 - name : Download build artifact
93110 id : download-artifact
111+ if : steps.fork-check.outputs.is_fork == 'false'
94112 uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
95113 with :
96114 name : dist # uploaded by publish-dist.yml > publish-dist
@@ -100,6 +118,7 @@ jobs:
100118
101119 - name : Prepare folders
102120 id : setup-metadata
121+ if : steps.fork-check.outputs.is_fork == 'false'
103122 env :
104123 GH_TOKEN : ${{ github.token }}
105124 PR_NUM : ${{ steps.get-metadata.outputs.PR_NUM }}
@@ -124,6 +143,7 @@ jobs:
124143
125144 - name : Generate GitHub App token
126145 id : generate-token
146+ if : steps.fork-check.outputs.is_fork == 'false'
127147 uses : actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
128148 with :
129149 client-id : ${{ vars.DEV_DEPLOY_APP_ID }}
@@ -132,6 +152,7 @@ jobs:
132152 repositories : plotly.js-dev-builds
133153
134154 - name : Check out plotly.js-dev-builds repo
155+ if : steps.fork-check.outputs.is_fork == 'false'
135156 uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
136157 with :
137158 repository : plotly/plotly.js-dev-builds
@@ -140,6 +161,7 @@ jobs:
140161
141162 - name : Commit and push files
142163 id : commit-and-push
164+ if : steps.fork-check.outputs.is_fork == 'false'
143165 env :
144166 PR_NUM : ${{ steps.get-metadata.outputs.PR_NUM }}
145167 SHORT_SHA : ${{ steps.get-metadata.outputs.SHORT_SHA }}
@@ -172,6 +194,7 @@ jobs:
172194 fi
173195
174196 - name : Generate summary
197+ if : steps.fork-check.outputs.is_fork == 'false'
175198 env :
176199 PR_NUM : ${{ steps.get-metadata.outputs.PR_NUM }}
177200 SHORT_SHA : ${{ steps.get-metadata.outputs.SHORT_SHA }}
@@ -182,3 +205,46 @@ jobs:
182205 echo "- Latest build for this PR: [${BASE_URL}/latest/plotly.min.js](${BASE_URL}/latest/plotly.min.js)" >> $GITHUB_STEP_SUMMARY
183206 echo "- Build for this commit: [${BASE_URL}/${SHORT_SHA}/plotly.min.js](${BASE_URL}/${SHORT_SHA}/plotly.min.js)" >> $GITHUB_STEP_SUMMARY
184207 echo "The above links should start working a minute or two after this job completes." >> $GITHUB_STEP_SUMMARY
208+
209+ - name : Report dev-build outcome to PR head
210+ # Post a commit status on the PR head SHA so a row appears in the PR
211+ # merge-box widget. Statuses are keyed by (sha, context) with
212+ # last-write-wins semantics, so a maintainer-triggered dispatch that
213+ # follows an earlier "Skipped" status updates the same row in place.
214+ if : |
215+ always() && (
216+ (github.event_name == 'workflow_run' && github.event.workflow_run.head_sha != '') ||
217+ (github.event_name == 'workflow_dispatch' && steps.get-metadata.outputs.SHA != '')
218+ )
219+ env :
220+ GH_TOKEN : ${{ github.token }}
221+ REPO : ${{ github.repository }}
222+ SHA : ${{ github.event.workflow_run.head_sha || steps.get-metadata.outputs.SHA }}
223+ IS_FORK : ${{ steps.fork-check.outputs.is_fork }}
224+ PR_NUM : ${{ steps.get-metadata.outputs.PR_NUM }}
225+ UPLOAD_OUTCOME : ${{ steps.commit-and-push.outcome }}
226+ RUN_ID : ${{ github.run_id }}
227+ run : |
228+ RUN_URL="https://github.com/${REPO}/actions/runs/${RUN_ID}"
229+ CONTRIBUTING_URL="https://github.com/${REPO}/blob/master/CONTRIBUTING.md#live-links-to-dev-builds"
230+
231+ if [ "${IS_FORK}" == "true" ]; then
232+ STATE="success"
233+ DESCRIPTION="Skipped — PR is from a fork. Ask a maintainer to trigger a build."
234+ TARGET_URL="${CONTRIBUTING_URL}"
235+ elif [ "${UPLOAD_OUTCOME}" == "success" ]; then
236+ STATE="success"
237+ DESCRIPTION="Latest dev builds for PR #${PR_NUM}"
238+ TARGET_URL="https://plotly.github.io/plotly.js-dev-builds/${UPLOAD_DIR_NAME}/pr-${PR_NUM}/latest"
239+ else
240+ STATE="failure"
241+ DESCRIPTION="Upload failed — see workflow run for details."
242+ TARGET_URL="${RUN_URL}"
243+ fi
244+
245+ jq -n \
246+ --arg state "${STATE}" \
247+ --arg description "${DESCRIPTION}" \
248+ --arg target_url "${TARGET_URL}" \
249+ '{state: $state, target_url: $target_url, description: $description, context: "Upload Dev Build"}' \
250+ | gh api --method POST --input - "repos/${REPO}/statuses/${SHA}"
0 commit comments