From GitHub Actions
Get started
GitHub
Attach screenshots to a PR from GitHub Actions
One comment per PR, updated on every run.
What you get #
Add one step to a workflow, and every run posts its screenshots and artifacts to the pull request. The CLI authenticates with its own token, so it doesn’t depend on which GitHub token the job holds. A CI job can:
- Post screenshots from a Playwright or Cypress run to the pull request.
- Attach non-image artifacts, like a test report or a log, to the same comment.
- Update one comment on each run instead of adding a new one.
Set up the token #
Create a service token for the workflow. A service token belongs to the workspace, not to a member, so it keeps working when people join or leave. A workspace admin creates it in the workspace settings, under Settings → Service tokens:
- Give the token a label such as
CI. Files the workflow uploads are attributed to this label. - Set access to Read & write, and choose an expiry.
- Copy the token. It starts with
ups_<workspace>_.
Save it as a repository secret named UPLOADS_TOKEN. The CLI reads the token and its workspace from
that variable.
A service token can post to repos that are already linked to the workspace, but it cannot link a new repo. If this is the first time the workspace posts to the repo, link it once from your own machine with a personal login:
uploads github link --repo <owner>/<repo>Any workspace admin can revoke a service token on the same settings page. A personal token from your account settings also works, but it belongs to the member who creates it: files are attributed to them, and the token stops working if they leave the workspace.
Add the workflow step #
Add a step after the job that writes your screenshots:
on: pull_request
permissions: contents: read pull-requests: write
jobs: screenshots: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # …build the app and write screenshots to ./shots - run: npm install -g @buildinternet/uploads - run: uploads put ./shots/*.png --pr ${{ github.event.pull_request.number }} env: UPLOADS_TOKEN: ${{ secrets.UPLOADS_TOKEN }} GH_TOKEN: ${{ github.token }}The files get stable URLs keyed to the pull request. The attachments comment posts as
uploads-sh[bot] when the GitHub App is installed. Without the App, the CLI
posts the comment with gh, which uses GH_TOKEN.
Want a screenshot of a URL without a test runner? Use uploads screenshot —
see Capture & annotate →.
FAQ #
- How do I post screenshots from GitHub Actions to a pull request?
- Upload them with uploads put and the PR number in a workflow step. The files get stable URLs, and one attachments comment on the PR lists them. Later runs update that comment instead of adding new ones.
- Can I attach test reports and logs, not only images?
- Yes. PDFs, logs, CSV, JSON, Markdown, and zip files are listed in the same comment, with their type and size.
- Does this work for pull requests from forks?
- Only if the workflow can read the UPLOADS_TOKEN secret. GitHub does not pass repository secrets to workflows triggered by pull requests from forks.