Skip to content
hurl.page/blog
CI

Your CI should hurl: live preview links in two lines of YAML

Bart PelleChief Hurler

· 2 min read

Every pull request that touches UI ends with the same comment: "can you post a screenshot?" Screenshots lie. Here's how to get a clickable, disposable preview on every CI run — with two lines of YAML and zero infrastructure on your side.

The two lines

The official action takes a .html file, a .zip, or a whole directory, hurls it at the API, and hands the live URL back as an output. It goes right after your build step:

.github/workflows/preview.yml

- uses: bitgate/hurl-page-action@v1  id: deploy  with:    path: dist

Fine — four lines once you count the id and the with. The point stands: there is nothing to configure, because there is no project to set up on the other side. Every run gets its own subdomain, and the step exposes url and slug outputs for whatever you want to do next.

A link nobody sees is a link nobody clicks. The cheapest surface is the job summary:

.github/workflows/preview.yml

- run: echo "### Preview: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY"

Prefer plain curl? The whole integration is one request — this is the same thing the action does under the hood:

publish-report.sh

URL=$(curl -fsS -X POST https://hurl.page/deploy \  -H "Content-Type: text/html" \  --data-binary @build/report.html | jq -r .url)echo "### Report: $URL" >> "$GITHUB_STEP_SUMMARY"

No tokens to rotate

Anonymous deploys need no auth at all — nothing to put in your repo secrets, nothing to leak. If your pipeline deploys more than 10 times a minute from one IP, add an API key and the limit becomes 120/min per account.

Previews that clean up after themselves

Preview links are disposable by definition, so let them dispose of themselves. Anonymous drops live 7 days by default; pass ?ttl=86400 and they're gone after a day — usually plenty for a review cycle. When the expiry hits, the drop serves a 410 and an hourly sweep deletes the files. No orphaned previews piling up in a bucket you forgot about, no cleanup job to write.

  • ttl is in seconds, minimum 60
  • Free drops cap at 7 days; subscribers can set anything (or nothing — no expiry)
  • Active drops expose their deadline via the x-drop-expires response header

Stable URLs for PRs

One thing random subdomains can't give you: the same URL across pushes. Reviewers bookmark the first link you post, then quietly review a stale build. Named drops fix that — deploy with ?name=pr-42 and the URL stays put while the content updates on every push. That one's covered in its own post.

Written by

Bart Pelle

Chief Hurler

Bart founded Bitgate and crowned himself Chief Hurler — a fancy title for “throws HTML at an API all day and occasionally writes about it.” If a build's on fire, he's the one who lit it. Usually on purpose.

Share

XHacker News