Skip to content
Esc
  • Type what you're looking for in your own words: “Slack”, “503”, “price”.

CI recipes

Complete workflows to copy — GitHub Actions on a preview and on production, GitLab CI with JUnit, Vercel then wait, the Monday-morning script.

Updated on 17 September 2026

On this page

Four situations, four ready-made files. Everywhere, the key comes from a secret (POSTSHIP_TOKEN) and the project id from a committed ./.postship.json (postship init) or a POSTSHIP_PROJECT variable. Never a key in clear text, never as an argument.

GitHub Actions: a pull request's preview

Check the preview URL before merging, with a threshold, and see the failures annotated on the pull request. check counts one check per URL toward the quota.

name: PostShip
on: [pull_request]
jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: titilyonnais/postship-check@v1
        with:
          url: ${{ steps.preview.outputs.url }}
          token: ${{ secrets.POSTSHIP_TOKEN }}
          min-score: 80

steps.preview.outputs.url is the address your preview deployment step produced (Vercel, Netlify…). Without the action, the same thing in two lines:

      - run: npm i -g postship
      - run: postship check --url "${{ steps.preview.outputs.url }}" --min-score 80
        env:
          POSTSHIP_TOKEN: ${{ secrets.POSTSHIP_TOKEN }}

GitHub Actions: production, after a deployment

Wait until PostShip has checked this commit in production, then decide. Nothing is consumed: wait and gate are reads.

  production:
    runs-on: ubuntu-latest
    needs: deploy
    steps:
      - uses: actions/checkout@v4
      - run: npm i -g postship
      - run: postship wait --sha "$GITHUB_SHA" --timeout 600
        env:
          POSTSHIP_TOKEN: ${{ secrets.POSTSHIP_TOKEN }}
      - run: postship gate --min-score 80
        env:
          POSTSHIP_TOKEN: ${{ secrets.POSTSHIP_TOKEN }}

The project comes from the committed ./.postship.json. wait exits 2 if ten minutes pass without a concluded ship — the job fails, but not because the site is broken: steps.<id>.outcome tells the two apart if you want to let a 2 through.

GitLab CI: the JUnit report

--junit writes a report that GitLab's Tests tab displays, one line per check.

postship:
  image: node:20
  script:
    - npm i -g postship
    - postship check --url "$CI_ENVIRONMENT_URL" --min-score 80 --junit postship.xml
  artifacts:
    when: always
    reports:
      junit: postship.xml

POSTSHIP_TOKEN is a masked and protected CI/CD variable (Settings → CI/CD → Variables).

Vercel from the command line, then wait

A deployment started by hand, and the certainty it was checked before you close the terminal.

vercel deploy --prod
postship wait --sha "$(git rev-parse HEAD)" --timeout 600 && postship open

postship open opens the project's Overview in the browser.

The Monday-morning script

A glance at every site without opening the app — and an exit code 1 that can ring something else.

#!/usr/bin/env bash
set -euo pipefail
postship projects --fail-if-red
for id in $(postship projects --json | jq -r '.projects[].id'); do
  postship incidents -p "$id" --fail-if-open
done

See also

The postship command — every command · postship check · postship wait · postship gate · Checking from your CI — the same thing with curl, nothing to install.

CI recipes — Docs — PostShip