Skip to content
Cyril Rohr edited this page Feb 13, 2026 · 19 revisions

Basic workflow with always-on branch

Unless stated otherwise, examples below use the default lightsail provider.
For Hetzner, add provider: hetzner and set both HCLOUD_TOKEN and HETZNER_CA_KEY in env:.

You can generate a temporary CA private key with:

ssh-keygen -t rsa -b 3072 -m PEM -N "" -f hetzner_ca_key

Add HETZNER_CA_KEY (the private key content, not .pub) to your repository secrets.

name: PullPreview
on:
  schedule:
    - cron: "30 */4 * * *"
  push:
    branches: [master]
  pull_request:
    types: [labeled, unlabeled, synchronize, closed, reopened, opened]

concurrency: ${{ github.ref }}

permissions:
  contents: read
  pull-requests: write

jobs:
  deploy:
    if: github.event_name == 'push' || (github.event.action != 'closed' && github.event.action != 'unlabeled' && (github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview')))
    runs-on: ubuntu-slim
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v5
      - uses: pullpreview/action@v6
        with:
          admins: "@collaborators/push"
          always_on: master
          app_path: .
          instance_type: micro
          ttl: 1h
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: us-east-1

Hetzner provider

name: PullPreview
on:
  schedule:
    - cron: "30 */4 * * *"
  push:
    branches: [master]
  pull_request:
    types: [labeled, unlabeled, synchronize, closed, reopened, opened]

jobs:
  deploy:
    if: github.event_name == 'schedule' || github.event_name == 'push' || github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview')
    runs-on: ubuntu-slim
    steps:
      - uses: actions/checkout@v5
      - uses: pullpreview/action@v6
        with:
          admins: "@collaborators/push"
          always_on: master
          provider: hetzner
          region: nbg1
          image: ubuntu-24.04
          instance_type: cpx21
          ttl: 1h
        env:
          HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}
          HETZNER_CA_KEY: ${{ secrets.HETZNER_CA_KEY }}

Automatic HTTPS with proxy_tls

- uses: pullpreview/action@v6
  with:
    app_path: .
    proxy_tls: web:8080
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Private registry images (GHCR)

- uses: pullpreview/action@v6
  with:
    app_path: .
    registries: docker://${{ secrets.GHCR_PAT }}@ghcr.io
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Multiple compose files

- uses: pullpreview/action@v6
  with:
    compose_files: docker-compose.yml,docker-compose.pullpreview.yml
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Clone this wiki locally