docs/github-actions.mdx
The instructions below are specific to GitHub Actions, but the same concepts can be used with other CI systems.
<Tip> Check out our new [GitHub integration](/github-integration) for automatic deployments, without adding any GitHub Actions workflows. </Tip>This simple GitHub action workflow will deploy your Trigger.dev tasks when new code is pushed to the main branch.
name: Deploy to Trigger.dev (prod)
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: "20.x"
- name: Install dependencies
run: npm install
- name: 🚀 Deploy Trigger.dev
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
run: |
npx trigger.dev@latest deploy --external-id ${{ github.sha }}
name: Deploy to Trigger.dev (staging)
# Requires manually calling the workflow from a branch / commit to deploy to staging
on:
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: "20.x"
- name: Install dependencies
run: npm install
- name: 🚀 Deploy Trigger.dev
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
run: |
npx trigger.dev@latest deploy --env staging --external-id ${{ github.sha }}
If you already have a GitHub action file, you can just add the final step "🚀 Deploy Trigger.dev" to your existing file.
The --external-id ${{ github.sha }} above tags the deployment with the commit it was built from. That is the first half of version skew protection: to complete it, give your running application the same value so it sends that id when it triggers.
# In your application's runtime environment, for the release built from this commit
TRIGGER_EXTERNAL_DEPLOYMENT_ID=<the-same-commit-sha>
Every task triggered by that release is then pinned to the deployment built from the same commit — and runs triggered before the task build finishes wait for it rather than executing on the previous version.
<Note> Tagging the deployment is harmless on its own: if nothing sends a matching id, runs behave exactly as they do today. `--external-id` also makes repeat deploys idempotent — re-running the workflow for a commit that is already deployed reports the existing version instead of building again.Two things follow from that. Because no build runs, a re-run after changing a synced environment
variable won't pick the new value up — make an empty commit, or pass --force. And if you add a
paths: filter to this workflow, ${{ github.sha }} stops being a safe id: commits that don't
touch your tasks never produce a deployment carrying that SHA, so every run from those releases
expires. See when nothing ever
lands.
</Note>
To deploy to preview branches from Pull Requests and have them archived when PRs are merged or closed, use a workflow that runs on pull_request with all four types including closed:
name: Deploy to Trigger.dev (preview branches)
on:
pull_request:
types: [opened, synchronize, reopened, closed]
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: "20.x"
- name: Install dependencies
run: npm install
- name: Deploy preview branch
run: npx trigger.dev@latest deploy --env preview --external-id ${{ github.event.pull_request.head.sha }}
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
On pull_request, github.sha is the merge commit GitHub creates for the PR, not the commit your
app was built from. Use github.event.pull_request.head.sha so the id matches the one your preview
deployment sends.
The CLI and @trigger.dev/* package versions need to be in sync with the trigger.dev CLI, otherwise there will be errors and unpredictable behavior. Hence, the deploy command will automatically fail during CI on any version mismatches.
Tip: add the trigger.dev CLI to your devDependencies and the deploy command to your package.json file to keep versions managed in the same place. For example:
{
"scripts": {
"deploy:trigger-prod": "trigger deploy",
"deploy:trigger": "trigger deploy --env staging"
},
"devDependencies": {
"trigger.dev": "4.0.2"
}
}
Your workflow file will follow the version specified in the package.json script, like so:
- name: 🚀 Deploy Trigger.dev
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
run: |
npm run deploy:trigger
You should use the version you run locally during dev and manual deploy. The current version is displayed in the banner, but you can also check it by appending --version to any command.
When self-hosting, you need to:
TRIGGER_API_URL environment variable pointing to your webapp domain, for example: https://trigger.example.comname: Deploy to Trigger.dev (self-hosted)
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: "20.x"
- name: Install dependencies
run: npm install
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🚀 Deploy Trigger.dev
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
TRIGGER_API_URL: ${{ secrets.TRIGGER_API_URL }}
run: |
npx trigger.dev@latest deploy