2222 screenshots :
2323 name : Checking Component Screenshots
2424 runs-on : ubuntu-latest
25- continue-on-error : true # TODO(hediet): Remove once screenshot pipeline is stable
2625 steps :
2726 - name : Checkout
2827 uses : actions/checkout@v6
7877 if (!errs.length) { console.log('No fixture errors.'); process.exit(0); }
7978 console.log(errs.length + ' fixture(s) with errors:');
8079 for (const f of errs) {
81- console.log('::error::' + f.fixtureId + ': ' + (f.error || 'unknown error'));
80+ const msg = f.error?.message || (typeof f.error === 'string' ? f.error : null) || 'unknown error';
81+ console.log('::error::' + f.fixtureId + ': ' + msg);
82+ if (f.error?.stack) { console.log(' stack: ' + f.error.stack); }
8283 if (f.events?.length) {
8384 for (const e of f.events) { console.log(' event: ' + JSON.stringify(e)); }
8485 }
8889
8990 - name : Check blocks-ci screenshots
9091 id : blocks-ci
92+ # The service URL is baked into the committed blocks-ci-screenshots.md
93+ # as `` (see
94+ # build/lib/screenshotBlocksCi.ts). It is passed here so the script
95+ # regenerates the markdown using the same URL prefix; otherwise the
96+ # equality check against the committed file would always fail. No HTTP
97+ # call is made — the URL is purely a string written into the markdown.
9198 run : |
9299 node build/lib/screenshotBlocksCi.ts \
93100 test/componentFixtures/.screenshots/current/manifest.json \
@@ -104,19 +111,34 @@ jobs:
104111 echo "BLOCKS_CI_EOF" >> "$GITHUB_OUTPUT"
105112 }
106113
107- - name : Upload screenshots
114+ - name : Upload screenshots as artifact
108115 uses : actions/upload-artifact@v7
109116 with :
110117 name : screenshots
111118 path : test/componentFixtures/.screenshots/current/
112119
113- - name : Skip notice (fork PR)
114- if : github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
115- run : echo "::notice::Skipping screenshot upload and diff — OIDC is not available for fork PRs"
120+ - name : Determine base SHA
121+ id : base
122+ run : |
123+ if [ "${{ github.event_name }}" = "pull_request" ]; then
124+ # For PRs, diff against the merge-base with the target branch.
125+ # This isolates the visual effect of just this PR's divergence
126+ # from target. Using pull_request.base.sha would be wrong: it's
127+ # the target-branch tip at PR creation time and can be stale,
128+ # causing unrelated target-branch commits to show up as diffs.
129+ TARGET_REF="origin/${{ github.event.pull_request.base.ref }}"
130+ git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.ref }}"
131+ BASE_SHA=$(git merge-base "${{ github.sha }}" "$TARGET_REF")
132+ else
133+ # For push events, diff against the parent commit.
134+ BASE_SHA=$(git rev-parse "${{ github.sha }}^")
135+ fi
136+ echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
137+ echo "Using base SHA: $BASE_SHA (base for ${{ github.sha }})"
116138
117- - name : Get OIDC token
139+ - name : Get OIDC token (non-fork only)
118140 id : oidc
119- if : github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
141+ if : github.event_name == 'push' || ( github.event_name == 'pull_request' && github. event.pull_request.head.repo.full_name == github.repository)
120142 run : |
121143 TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
122144 "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://hediet-screenshots.azurewebsites.net" \
@@ -129,38 +151,63 @@ jobs:
129151 run : |
130152 cd test/componentFixtures/.screenshots/current
131153 zip -qr "$GITHUB_WORKSPACE/screenshots.zip" .
132- curl -sS -f -X POST "https://hediet-screenshots.azurewebsites.net/upload" \
154+ # Tolerate service outages: warn instead of failing the step so the
155+ # rest of the workflow (and CI) is not blocked when the screenshot
156+ # service is unreachable.
157+ set +e
158+ STATUS=$(curl -sS -o /tmp/screenshot-upload.out -w '%{http_code}' \
159+ -X POST "https://hediet-screenshots.azurewebsites.net/upload" \
133160 -H "Content-Type: application/zip" \
134161 -H "Authorization: Bearer $SCREENSHOT_SERVICE_TOKEN" \
135- --data-binary @"$GITHUB_WORKSPACE/screenshots.zip"
162+ --data-binary @"$GITHUB_WORKSPACE/screenshots.zip")
163+ CURL_EXIT=$?
164+ set -e
165+ if [ "$CURL_EXIT" -ne 0 ]; then
166+ echo "::warning::Screenshot service unreachable (curl exit $CURL_EXIT) -- skipping upload."
167+ elif [ "${STATUS:0:1}" != "2" ]; then
168+ echo "::warning::Screenshot service returned HTTP $STATUS -- skipping upload."
169+ cat /tmp/screenshot-upload.out || true
170+ else
171+ echo "Uploaded screenshots (HTTP $STATUS)."
172+ fi
136173 env :
137174 SCREENSHOT_SERVICE_TOKEN : ${{ steps.oidc.outputs.token }}
138175
139- - name : Diff screenshots against merge base
140- id : diff
141- if : steps.oidc.outputs.token
176+ - name : Fetch base commit manifest
177+ id : base_manifest
178+ env :
179+ BASE_SHA : ${{ steps.base.outputs.base_sha }}
142180 run : |
143- if [ "${{ github.event_name }}" = "pull_request" ]; then
144- # For PRs, diff against the merge-base with the target branch.
145- # This isolates the visual effect of just this PR's divergence
146- # from target. Using pull_request.base.sha would be wrong: it's
147- # the target-branch tip at PR creation time and can be stale,
148- # causing unrelated target-branch commits to show up as diffs.
149- TARGET_REF="origin/${{ github.event.pull_request.base.ref }}"
150- git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.ref }}"
151- BASE_SHA=$(git merge-base "${{ github.sha }}" "$TARGET_REF")
181+ BASE_MANIFEST=/tmp/base-manifest.json
182+ URL="https://hediet-screenshots.azurewebsites.net/commits/${{ github.repository_owner }}/${{ github.event.repository.name }}/$BASE_SHA"
183+ # Tolerate service outages: bash `set -e` would otherwise abort this
184+ # step if curl can't connect (since the `STATUS=$(...)` substitution
185+ # propagates the non-zero exit). Capture the exit code explicitly
186+ # and emit a warning instead.
187+ set +e
188+ STATUS=$(curl -sS -o "$BASE_MANIFEST" -w '%{http_code}' "$URL")
189+ CURL_EXIT=$?
190+ set -e
191+ if [ "$CURL_EXIT" -ne 0 ]; then
192+ echo "::warning::Screenshot service unreachable (curl exit $CURL_EXIT) -- skipping diff."
193+ elif [ "$STATUS" = "200" ]; then
194+ echo "path=$BASE_MANIFEST" >> "$GITHUB_OUTPUT"
195+ echo "Fetched base manifest for $BASE_SHA"
152196 else
153- # For push events, diff against the parent commit.
154- BASE_SHA=$(git rev-parse "${{ github.sha }}^")
197+ echo "::warning::Base manifest unavailable (HTTP $STATUS) -- skipping diff."
198+ cat "$BASE_MANIFEST" || true
155199 fi
156- echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
157- echo "Using base SHA: $BASE_SHA (base for ${{ github.sha }})"
200+
201+ - name : Diff screenshots
202+ id : diff
203+ if : steps.base_manifest.outputs.path
204+ run : |
158205 BODY=$(node build/lib/screenshotDiffReport.ts \
159206 https://hediet-screenshots.azurewebsites.net \
160- ${{ github.repository_owner }} \
161- ${{ github.event.repository.name }} \
162- "$BASE_SHA " \
163- ${{ github.sha }} )
207+ " ${{ steps.base.outputs.base_sha }}" \
208+ ${{ github.sha }} \
209+ "${{ steps.base_manifest.outputs.path }} " \
210+ test/componentFixtures/.screenshots/current/manifest.json )
164211 if [ -n "$BODY" ]; then
165212 echo "has_changes=true" >> "$GITHUB_OUTPUT"
166213 echo "body<<SCREENSHOT_EOF" >> "$GITHUB_OUTPUT"
@@ -170,13 +217,11 @@ jobs:
170217 echo "No screenshot changes to report."
171218 fi
172219 if [ -f .tmp/screenshotDiffReport.json ]; then
173- echo "::group::Compare response JSON"
220+ echo "::group::Diff JSON"
174221 cat .tmp/screenshotDiffReport.json
175222 echo "::endgroup::"
176223 fi
177224 continue-on-error : true
178- env :
179- SCREENSHOT_SERVICE_TOKEN : ${{ steps.oidc.outputs.token }}
180225
181226 - name : Write job summary
182227 if : steps.diff.outputs.has_changes == 'true' || steps.blocks-ci.outputs.match == 'false'
@@ -195,8 +240,8 @@ jobs:
195240 COMMENT_BODY : ${{ steps.diff.outputs.body }}
196241 BLOCKS_CI_CONTENT : ${{ steps.blocks-ci.outputs.content }}
197242
198- - name : Post PR comment
199- if : github.event_name == 'pull_request'
243+ - name : Post PR comment (non-fork PR only)
244+ if : github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
200245 uses : actions/github-script@v9
201246 with :
202247 script : |
@@ -262,26 +307,18 @@ jobs:
262307 env :
263308 COMMENT_BODY : ${{ steps.diff.outputs.body }}
264309 BLOCKS_CI_CONTENT : ${{ steps.blocks-ci.outputs.content }}
265- BASE_SHA : ${{ steps.diff .outputs.base_sha }}
310+ BASE_SHA : ${{ steps.base .outputs.base_sha }}
266311 CURRENT_SHA : ${{ github.sha }}
267312
268313 - name : Fail if blocks-ci hashes changed
269314 if : steps.blocks-ci.outputs.match == 'false'
270315 run : |
271- echo "::error::blocks-ci screenshot hashes do not match committed file. See PR comment for updated content."
316+ echo "::error::blocks-ci screenshot hashes do not match committed file. See PR comment or job summary for the updated content."
272317 echo ""
273318 echo "Diff between committed and expected blocks-ci-screenshots.md:"
274319 diff -u test/componentFixtures/blocks-ci-screenshots.md /tmp/blocks-ci-updated.md || true
275320 exit 1
276321
277- # - name: Compare screenshots
278- # id: compare
279- # run: |
280- # ./node_modules/.bin/component-explorer screenshot:compare \
281- # --project ./test/componentFixtures \
282- # --report ./test/componentFixtures/.screenshots/report
283- # continue-on-error: true
284-
285322 # - name: Prepare explorer artifact
286323 # run: |
287324 # mkdir -p /tmp/explorer-artifact/screenshot-report
@@ -296,14 +333,6 @@ jobs:
296333 # name: component-explorer
297334 # path: /tmp/explorer-artifact/
298335
299- # - name: Upload screenshot report
300- # if: steps.compare.outcome == 'failure'
301- # uses: actions/upload-artifact@v7
302- # with:
303- # name: screenshot-diff
304- # path: |
305- # test/componentFixtures/.screenshots/current/
306- # test/componentFixtures/.screenshots/report/
307336
308337 # - name: Set check title
309338 # env:
@@ -339,29 +368,3 @@ jobs:
339368 # {"state":"$STATE","target_url":"$DETAILS_URL","description":"$TITLE","context":"Component Screenshots"}
340369 # EOF
341370
342- # - name: Post PR comment
343- # if: github.event_name == 'pull_request'
344- # env:
345- # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
346- # run: |
347- # COMMENT_MARKER="<!-- screenshot-report -->"
348- # BODY="$COMMENT_MARKER"$'\n'
349- #
350- # if [ -f test/componentFixtures/.screenshots/report.md ]; then
351- # BODY+=$(cat test/componentFixtures/.screenshots/report.md)
352- # BODY+=$'\n\n'
353- # BODY+="📦 [Download the \`screenshot-diff\` artifact](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) to review images."
354- # else
355- # BODY+="## Screenshots ✅"$'\n\n'
356- # BODY+="No visual changes detected."
357- # fi
358- #
359- # # Find existing comment
360- # EXISTING=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \
361- # --paginate --jq ".[] | select(.body | startswith(\"$COMMENT_MARKER\")) | .id" | head -1)
362- #
363- # if [ -n "$EXISTING" ]; then
364- # gh api "repos/${{ github.repository }}/issues/comments/$EXISTING" -X PATCH -f body="$BODY"
365- # else
366- # gh pr comment "${{ github.event.pull_request.number }}" --body "$BODY"
367- # fi
0 commit comments