Workflow Examples
Basic Compose workflow
Unless stated otherwise, examples below use the default lightsail provider.
name: PullPreview on: schedule: - cron: "30 */4 * * *" pull_request: types: [labeled, unlabeled, synchronize, closed, reopened, opened] permissions: contents: read pull-requests: write jobs: deploy: if: github.event_name == 'schedule' || github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview') runs-on: ubuntu-slim timeout-minutes: 30 steps: - uses: actions/checkout@v6 - uses: pullpreview/action@v6 with: deployment_target: compose app_path: . admins: "@collaborators/push" 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
schedule is optional and only handles dangling deployment cleanup. For v6, create and update flows are driven by labeled pull request events, not direct branch pushes. See Migrating from v5 to v6 if you previously used always_on.
Hetzner Compose workflow
Generate an SSH CA key once:
ssh-keygen -t rsa -b 3072 -m PEM -N "" -f hetzner_ca_keyStore the private key contents as HETZNER_CA_KEY.
- uses: pullpreview/action@v6 with: provider: hetzner deployment_target: compose region: nbg1 image: ubuntu-24.04 instance_type: cpx21 ttl: 1h env: HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} HETZNER_CA_KEY: ${{ secrets.HETZNER_CA_KEY }}
Compose with automatic HTTPS
- uses: pullpreview/action@v6 with: deployment_target: compose proxy_tls: web:8080 dns: rev1.click env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Compose with private registry images
- uses: pullpreview/action@v6 with: deployment_target: compose 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 }}
Compose with multiple Compose files
- uses: pullpreview/action@v6 with: deployment_target: compose compose_files: docker-compose.yml,docker-compose.pullpreview.yml compose_options: --build,--remove-orphans env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Helm with a local chart on Hetzner
name: PullPreview Helm on: pull_request: types: [labeled, unlabeled, synchronize, closed, reopened, opened] jobs: deploy_helm: runs-on: ubuntu-slim if: github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview') timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: pullpreview/action@v6 with: provider: hetzner deployment_target: helm chart: ./charts/my-app chart_values: charts/my-app/values-preview.yaml chart_set: image.tag=${{ github.sha }},baseUrl={{ pullpreview_url }} proxy_tls: "{{ release_name }}-web:80" dns: rev2.click env: HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} HETZNER_CA_KEY: ${{ secrets.HETZNER_CA_KEY }}
Helm with a repo chart on Lightsail
name: PullPreview Lightsail Helm on: pull_request: types: [labeled, unlabeled, synchronize, closed, reopened, opened] jobs: deploy_lightsail_helm: runs-on: ubuntu-slim if: github.event.label.name == 'pullpreview-helm' || contains(github.event.pull_request.labels.*.name, 'pullpreview-helm') timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: pullpreview/action@v6 with: label: pullpreview-helm provider: lightsail region: us-east-1 deployment_target: helm chart: wordpress chart_repository: https://charts.bitnami.com/bitnami chart_set: service.type=ClusterIP proxy_tls: "{{ release_name }}-wordpress:80" instance_type: medium dns: rev3.click env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
See also: