Drone

Duplicate builds when pushing to branch with open pull request

Is there any way to prevent Drone from building for both the pull request and the push event?

My main use case is to prevent duplicate messages in Slack, which I’ve been able to partially solve using a lot of when: clauses, but the builds are still showing up in Drone’s UI.

This is what I’m trying to do:

  • When there is a push only to master, build it, report status to Slack.
    • Works with event: push and branch: master in a when: clause for a “build_master” pipeline step, which seems seems OK.
  • When there is a tag only in master, build and publish it, report status to Slack.
    • Works with event: tag and branch: master in a when: clause for a “publish” pipeline step, which also seems OK.
  • When there is a push to a pull request, build it, report status to Slack (and PR).
    • Always appears to build twice, once for the PR and once for the push.
    • The PR build incorrectly reports the branch as “master” in the Slack template.
    • The push build does not have the PR number available in the Slack template.
    • The push and PR builds share the same commit SHA.
    • I can filter out the push build using when: event: pull_request, but that reports the wrong branch name to Slack (always master), and silences Slack messages (using that same step) for the “build_master” and “publish” pipeline steps.
    • I can filter out the PR build likewise, but that doesn’t allow me to link the PR directly in the slack template.
    • Even when filtering out the Slack messages, there’s still builds in Drone.

Is there any good way to resolve this and just get a single build in every situation?

I can see in the PR there are two checks being made, which corresponds to the two events and builds:

Here’s a anonymized version of the template I’m using with org/repo substituted.

# Pipeline for multistage Dockerfile that includes tests
pipeline:
  # Build Dockerfile for master to report breakage in Slack
  build_master:
    dry_run: true  # Prevents publishing
    image: plugins/docker
    repo: org/repo
    when:
      branch: master
      event: push
  # Build Dockerfile for PRs to get status on PR and in Slack
  build_pull_request:
    dry_run: true  # Prevents publishing
    image: plugins/docker
    repo: org/repo
    when:
      branch:
        excludes: master
      event: pull_request
  # Build Dockerfile to publish to Docker Hub when tagging
  publish:
    image: plugins/docker
    secrets:
      - docker_username
      - docker_password
    repo: org/repo
    tags:
      - ${DRONE_COMMIT_SHA:0:8}
      - ${DRONE_COMMIT_BRANCH}
      - ${DRONE_TAG}
      - latest
    when:
      event: tag
  # Report status to Slack
  slack:
    image: plugins/slack
    webhook: ${SLACK_WEBHOOK}
    channel: drone-ci
    username: drone
    when:
      status:
        - success
        - failure
    template: >
      {{#success build.status}}
      :white_check_mark: Success!
      {{else}}
      :x: Failure:
      {{/success}}
      Build <{{build.link}}|#{{build.number}}> for 
      <https://github.com/{{repo.owner}}/{{repo.name}}|{{repo.name}}>
      {{#pull_request build.event}}
      (<https://github.com/{{repo.owner}}/{{repo.name}}/pull/{{build.pull}}|{{truncate build.commit 8}}>)
      {{else}}
      (<https://github.com/{{repo.owner}}/{{repo.name}}/commit/{{build.commit}}|{{truncate build.commit 8}}>)
      {{/pull_request}}
      (<https://github.com/{{repo.owner}}/{{repo.name}}/tree/{{build.branch}}|{{build.branch}}>) 
      by <https://github.com/{{build.author}}|{{build.author}}>
      in {{since build.started}}

Update:

We ended up just dropping builds on PRs entirely, and only using the Push event hook. It would be great if there was a way to make the above workflow work, but it seems like it’s not possible currently.

Please let me know if it is actually feasible.

We’re having a similar issue here, however, we’ve configured all build steps with this condition:
when:
branch: master
event:
- pull_request
- push

As a result, we do get our pull requests built, however, we also get an empty pipeline (except clone step) on the push action due to there being no other steps to perform.

My question is - is there a way to avoid publishing two branches. Let’s say, if PR is open, original branch would not show up in the UI.

2 Likes

If anyone else got here, you can use triggers to filter entire pipelines: https://docs.drone.io/user-guide/pipeline/triggers/

Unfortunately, last link from @rohit-smpx is broken.

Updated link: https://docker-runner.docs.drone.io/configuration/trigger/

Example confs (in case this link also stops working):

  • By event, this would only run the push build for the branch
kind: pipeline
type: docker
name: default

steps:
- name: build
  image: golang
  commands:
  - go build
  - go test

trigger:
  event:
    exclude:
    - pull_request

Or by branch:
This would run on push events on the master branch and on pull requests with base branch master (AFAIK).

kind: pipeline
type: docker
name: default

steps:
- name: build
  image: golang
  commands:
  - go build
  - go test

trigger:
  branch:
    - master