Repository navigation
jetpack-screenshot skill: attach images with gh --attach instead of pushing a screenshots ref - #52901
Conversation
Upload screenshots as user-attachments assets through gh pr edit --attach instead of pushing a screenshots/<branch> ref to origin.
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! |
|
|
||
| If a side-by-side composite was produced, offer that markdown variant instead. | ||
|
|
||
| ### 7. Attach to the PR |
There was a problem hiding this comment.
This step now writes the screenshots block into the PR body. Before, the skill only printed markdown to paste. The reason is that gh --attach uploads a file only when it posts the body or comment. There is no flag that only uploads and returns the URL. The marker comments let a second run replace the block, so the body does not collect copies.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The workflow can overwrite a PR body after a failed fetch, and attachment uploads are not reliably redirect-safe.
Review effort: Balanced
Findings: 1
Open (3)
What changed in this PR
Replaces screenshot-ref publishing with GitHub user attachments and repeatable PR-body updates.
Changes:
- Uploads screenshots using
gh --attach. - Replaces marker-delimited screenshot blocks on reruns.
- Adds direct asset uploads for review comments.
| File | Description |
|---|---|
.agents/skills/jetpack-screenshot.md |
Updates screenshot publishing and attachment workflows. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Save the PR body before filtering it, so a failed gh pr view cannot replace the description with only the screenshot block. Allowlist the grep, cut, sort, cat, echo and Write calls the skill makes.
…screenshot gh --attach stays the default. When it is missing, the skill picks the first route the environment supports instead of stopping.
xavier-lc
left a comment
There was a problem hiding this comment.
Summary
This fixes the problem we found on #52629 and #52643. The skill stops pushing a screenshots/<branch> ref and hosts the images as user-attachments instead.
- Route 1 (
gh --attach) is sound. It was merged in cli/cli#14183 and ships in gh v2.99.0 and later. It rewrites./file.pngreferences in the body and requires write access to the repo. - Route 2 (upload with
gh api) uploads fine, but its check of the result always fails. The skill then says to upload again, and uploads can't be deleted. - Neither route says what to do with an image over the size limit.
Findings
-
[blocker] Route 2's URL check always fails, and the skill then says to upload again.
- Where:
jetpack/.agents/skills/jetpack-screenshot.md
Lines 166 to 170 in ea67575
- What happens: the check uses an anonymous
curl -sL. GitHub serves an upload that no published body references yet only to authenticated requests; anonymous requests get 404. - Tested: I uploaded a PNG with the skill's own command (gh 2.45,
gho_token) and got a URL back. Anonymous requests returned404 text/plain, and requests with the token returned200 image/png. An image already referenced in a PR body returned 200 anonymously. - Impact: every route-2 upload looks like a failure, and "mint it again" repeats it, each time storing a copy that can't be deleted. This route triggers on gh older than v2.99 and always for review or inline comments.
- Fix: authenticate the check with
curl -sL -H "Authorization: Bearer $(gh auth token)" …. With that header, the download matched the uploaded file.
- Where:
-
[suggestion] Route 2 saves the body with the command that silently fails on older gh.
- Where: , which says to rerun step 7 without
jetpack/.agents/skills/jetpack-screenshot.md
Line 173 in ea67575
--attach, meaninggh pr edit --body-file. - What happens: route 2 exists for older gh. On gh 2.45 that command prints a "Projects (classic)" GraphQL warning and leaves the body unchanged, so the run reports success with no screenshots in the PR.
- Fix: use
gh api -X PATCH repos/Automattic/jetpack/pulls/$PR -F body=@body.md, then read the body back to confirm it changed.
- Where:
-
[suggestion] The skill doesn't say what to do with a screenshot over 10 MiB.
- Where:
jetpack/.agents/skills/jetpack-screenshot.md
Line 155 in ea67575
- Tested: the limit is 10 MiB on both routes; a 10,481,193-byte PNG was accepted and an 11.1 MiB one was rejected.
- Route 1: gh refuses the file locally, before looking up the PR or uploading anything:
images must be at most 10.0 MB, exit 1. The body is left untouched. - Route 2: the server returns
422 Validation Failed("Yowza that's a big file… less than 10MB") and stores nothing. Following the skill's "mint it again" just repeats the 422.
- Route 1: gh refuses the file locally, before looking up the PR or uploading anything:
- When it happens: 1440×900 viewport shots are well under the limit. The realistic case is a side-by-side composite at HiDPI (5760×1800) of an image-heavy page.
- Fix: one line in the skill: "If a PNG is over 10 MiB, downscale it or convert it to JPEG, or attach the before and after images separately instead of the composite."
- Where:
-
[suggestion] A failed upload partway through goes unnoticed.
- Where:
jetpack/.agents/skills/jetpack-screenshot.md
Lines 150 to 151 in ea67575
- What happens: gh checks every file before uploading, so an oversized file can't cause this. A network error or rate limit partway through still can. gh stops at that file but writes the body if any earlier upload succeeded. The failed references keep their
./before-<slug>.pngpath and show as broken images; cli/cli#14181 says this is expected. - Fix: after the edit, read the body with
gh pr view --json bodyand fail if it still contains](./.
- Where:
-
[suggestion] A lone start marker deletes the rest of the PR body.
- Where:
jetpack/.agents/skills/jetpack-screenshot.md
Line 148 in ea67575
- What happens: if the
jetpack-screenshot:endmarker was edited out, the awk skips everything after the start marker, andgh pr editsaves the shortened body. The original stays inoriginal-body.md, but nothing tells anyone to look there. - Fix: remove the block only when both markers are present; otherwise stop and ask.
- Where:
-
[suggestion]
allowed-toolspre-approves more than the skill needs.- Where:
- What happens:
Bash(gh api:*)pre-approves any API write, andBash(curl:*)allows any network request. With uploads that can't be undone, and finding 1's retry loop, a permission prompt before the upload is a useful brake. - Fix: narrow both patterns. The step 7 subshell starts with
(, so it matches no pattern and prompts anyway, which is probably not deliberate.
-
[suggestion] The URL check writes to
/tmp/asset.png.- Where:
jetpack/.agents/skills/jetpack-screenshot.md
Line 170 in ea67575
- What happens: the path is shared, so parallel runs can overwrite each other's file.
- Fix: use
"$OUT/check.png".
- Where:
Testing done
- Route 1: run with gh v2.101.0. The size check was confirmed against a PR number that doesn't exist, so nothing was posted. Reference rewriting and the write-access check were verified from gh's source and PR notes, not by running them. A full end-to-end run would need a PR to post to.
- Route 2: run with gh 2.45.0 against Automattic/jetpack. The upload, the anonymous-vs-authenticated responses, and the 422 for oversized files were all observed. Nothing was posted.
Verdict
Needs changes before merge. Route 2's URL check (finding 1) makes the skill upload copies that can't be deleted, in a loop. Findings 2–5 are about the skill reporting success, or failing with no next step, when the PR body isn't what it should be. The confidentiality check, the confirm-before-upload step, the privacy note, and the order of fallback routes all look fine.
Authenticate the minted-URL check, save the body over REST on older gh, keep a lone start marker from dropping the body, note the 10 MiB limit, read the body back for unrewritten ./ paths, and narrow allowed-tools.
|
Thank you for testing both routes against the real endpoint. I applied all seven fixes:
I kept the |
xavier-lc
left a comment
There was a problem hiding this comment.
Thanks, all seven findings are addressed in 56901e9. I reran the new URL check exactly as written against an asset I had uploaded, and it returns 200 image/png with a byte-identical file, so route 2 no longer treats a good upload as a failure.
One optional follow-up, not blocking: the marker rule in step 7 is prose only, so an agent that copies the command still gets the old behaviour. If the end marker was deleted by hand, the awk drops everything after the start marker and gh pr edit saves the shortened body. A guard inside the chain would stop it before the edit:
gh pr view "$PR" -R Automattic/jetpack --json body --jq .body > original-body.md &&
[ "$(grep -c 'jetpack-screenshot:start' original-body.md)" = "$(grep -c 'jetpack-screenshot:end' original-body.md)" ] &&
awk '…' original-body.md > body.md &&|
Thank you for checking the new URL check again. I added the marker guard to the step 7 command, so the chain now stops before |


Fixes N/A
Proposed changes
jetpack-screenshotskill published images by force-pushing ascreenshots/<branch>ref toorigin. Every run left a branch on the public repository that nothing merged or cleaned up.gh pr edit --attach(orgh pr create --attach). GitHub stores each file as auser-attachmentsasset and rewrites the./before-<slug>.pngreferences in the body to the uploaded URLs, so no branch is pushed.--attachuploads only while it posts, the skill now writes the screenshots block into the PR body itself instead of printing markdown to paste. The block sits between two marker comments, so a second run replaces it instead of adding a second copy.--attach, the skill mints asset URLs through theuser-attachmentsupload endpoint without posting anything.Related product discussion/links
Does this pull request change what data or activity we track or use?
No.
Testing instructions
gh pr edit --helplists--attach./jetpack-screenshotand confirm the Before/After table renders in the body withuser-attachmentsimage URLs.git ls-remote origin 'refs/heads/screenshots/*'shows no new ref for your branch.