Drone CI doesn’t just run your code; it runs it when you tell it to. The secret sauce for that "when" is the trigger section in your .drone.yml. Most folks think triggers are just about branch or event, but the real power comes from how those events interact with your repository’s state.
Let’s see it in action. Imagine a simple pipeline that builds and tests your Go application.
kind: pipeline
type: docker
name: default
steps:
- name: build
image: golang:1.20
commands:
- go build
- go test
trigger:
event:
- push
- pull_request
This pipeline will run on every push to any branch and on every pull_request targeting any branch. Pretty standard. But what if you only want to run tests on a specific branch, say main, but build on any push?
kind: pipeline
type: docker
name: default
steps:
- name: build
image: golang:1.20
commands:
- go build
- go test
trigger:
event:
- push
- pull_request
branch:
- main
This configuration is a bit misleading. It looks like it will only trigger for push and pull_request events on the main branch. That’s not quite right. When you specify multiple event types and multiple branch types, Drone uses an OR logic between the event types and then applies the branch filter to all of them.
Here’s the mental model:
-
Event First: Drone first checks if the incoming event is one of the types you’ve listed (
push,pull_request,tag,deployment,cron, etc.). If the event isn’t in youreventlist, the pipeline won’t run, regardless of the branch. -
Branch Filter (If Applicable): If the event is one of the allowed types, Drone then checks the
branchfilter.- If you have only specified
branchfilters (e.g.,branch: [main, develop]), the pipeline will trigger for any of the allowed events on any of those branches. - If you have only specified
eventfilters (e.g.,event: [push]), the pipeline will trigger for that event on any branch. - The tricky part: When you specify both
eventandbranchfilters, Drone applies thebranchfilter to all events listed in theeventsection.
- If you have only specified
Let’s break down the second example again:
trigger:
event:
- push
- pull_request
branch:
- main
This means:
- Trigger on
pushevents if the branch ismain. - Trigger on
pull_requestevents if the branch ismain.
This is not what most people expect. They often want "push to main OR push to any other branch".
To achieve that common scenario – run on pushes to main and also on pushes to any other branch – you need to be more explicit and use separate trigger configurations or leverage the all keyword.
Here’s how you’d correctly configure "push to main OR push to any other branch":
kind: pipeline
type: docker
name: default
steps:
- name: build
image: golang:1.20
commands:
- go build
- go test
trigger:
event:
- push
branch:
- main
This pipeline will run on push events to the main branch. But it won’t run on pushes to other branches. To include pushes to any branch, you need another entry:
kind: pipeline
type: docker
name: default
steps:
- name: build
image: golang:1.20
commands:
- go build
- go test
trigger:
event:
- push
branch:
- main
- +* # This is the key for "any other branch"
The +* pattern is a wildcard that matches any branch not already explicitly listed. So, branch: [main, +*] means "the main branch OR any other branch".
Now, let’s talk about pull_request events. If you want to run on pull_request events targeting main, but not on pull_request events targeting other branches, you’d add that specifically:
kind: pipeline
type: docker
name: default
steps:
- name: build
image: golang:1.20
commands:
- go build
- go test
trigger:
event:
- push
branch:
- main
- +*
- pull_request:
target: main
Here, pull_request: { target: main } tells Drone to only trigger this pipeline for pull requests where the target branch is main. If you wanted to run on all pull requests, you’d simply use event: [pull_request].
The trigger section is incredibly powerful because it allows you to define complex conditional logic for when your pipelines should execute. You can combine event, branch, tag, deployment, and cron triggers, and even use regular expressions for branch and tag matching.
One of the most underutilized features is the ability to specify multiple event types and combine them with branch filters that apply differently. For example, you might want to build on any push, but only test on pushes to main or develop. This requires separate pipeline definitions or a more nuanced trigger structure. The trigger section itself is an OR between its top-level components. So, trigger: { event: [push], branch: [main] } is one rule, and trigger: { event: [pull_request] } is another, and the pipeline runs if either rule matches.
When you see trigger: { event: [push, pull_request], branch: [main] }, it’s interpreted as (push AND main) OR (pull_request AND main). To achieve (push AND main) OR (push AND NOT main), you need to list push twice, or use the wildcard: trigger: { event: [push], branch: [main, +*] }.
Understanding this implicit OR between top-level trigger configurations and the AND within a single configuration block is crucial for mastering Drone’s trigger system.
The next common hurdle is managing secrets that are only available for certain trigger events or branches.