81

To put it in "BDD" terms:

Background:
Given I'm contributing to a GH repo

When I create a pull request
Then Travis should build the latest commit

When I push to an existing pull request
Then Travis should build the latest commit

When I merge a pull request to master
Then Travis should build master

I was confused by Travis-CI's "build pushes" and "build PRs" settings, as:

  • Enabling both causes each Pull Request to be build twice by Travis
    • once for the commit on that branch
    • and once again for the merge commit of that branch into its destination
  • Enabling just "build PRs" causes PRs to be built, but doesn't result in post-merge builds (i.e. on master).
  • Enabling "pushes" brute-force satisfies the above criteria by building all pushes to the repo. You can try to finagle things by white- & black-listing branches, but that will probably bite you unless you're rigorously disciplined with branch names.

This is explained more in Travis-CI docs and GH issue #3241.

Anyone know a configuration that satisfies the above criteria?

Brian Gerstle
  • 3,643
  • 3
  • 22
  • 22
  • The branch build and the PR build are different builds, and can have different results. The branch build is simply the tip of the branch. The PR build is the tip of the branch merged to master. This is effectively what would happen if you were to merge the branch to master at that point. If other things have been merged to master since the branch was opened, so no fast-forward merge is possible, this will be different from the branch build. – Daniel Stevens Apr 28 '19 at 19:31

6 Answers6

110

I eventually found another GH issue (#2111) which gave me the idea to try enabling both PRs & pushes, but with a whitelist to restrict pushes to a specific branch. This seems to satisfy the criteria for my workflow. Here's what I did:

  1. Enable both PRs & branch pushes in the Travis settings for the repo:

travis push/pr settings enabled

  1. Change .travis.yml to white-list master branch (i.e. only build pushes to master):
branches:
  only: 
    - master
  1. Test it by creating a PR with the .travis.yml change, and another PR with some empty commits to verify it works for forks too.

  2. Verify successful merge commit build from master.

build result of merge to master

Saugat
  • 1,309
  • 14
  • 22
Brian Gerstle
  • 3,643
  • 3
  • 22
  • 22
  • Confirming this work. See this [pull request](https://github.com/blbradley/kafka-cryptocoin/pull/3). – Brandon Bradley Jan 23 '16 at 01:08
  • 5
    Does this still work for sub-feature-branch PRs that are pointed at something other than `master`? I believe this relies on a weird quirk with Travis's PR build env vars and would not work for that case. – fotinakis Aug 17 '16 at 16:24
  • I believe it should, as it's configured to build all pull requests (regardless of the base branch), but limited to only build *pushes* to `master`. – Brian Gerstle Aug 18 '16 at 18:02
  • @fotinakis - there are three options in GitHub that correspond to three different types of merges. Select the option that retains all the sub branches/features to include them in the push. Then you may need to work on the travis.yml, i guess, to get at specific branches/features or exclude – user2347763 Jul 19 '17 at 20:45
  • 1
    This doesn't work for pull requests that don't target master - they simply won't build. – Corey Noel Jun 12 '19 at 15:57
18

Just found in travis docs

Add to .travis.yml

if: type = push

alternatively:

if: type = pull_request
grosser
  • 14,707
  • 7
  • 57
  • 61
14

Assuming you want to build all PRs, something like the following will do the trick. Enable both branch and PR builds on the settings page, and put this line as the first line in your travis.yml:

if: (type = push AND branch IN (master, dev)) OR (type = pull_request AND NOT branch =~ /no-ci/)

This will attempt a push build on all pushes and a PR build on all pushes to an open PR, but will filter out any that don't meet the condition. You might need to modify this a bit - the clause about not building branches with no-ci somewhere in their name is obviously optional, and you may not have two branches that you always want to run builds on.

You can read more on conditions and conditional builds on Travis's site.

Corey Noel
  • 403
  • 4
  • 7
4

The whitelist approach described in the accepted answer has some significant limitations. In particular, it doesn't support non-redundantly building arbitrary branches without opening a PR.

I opened an issue asking for a better solution.

John
  • 29,546
  • 11
  • 78
  • 79
2

You can use next workflow if you want to test not only master branch but some others branches too:

  • Keep both "Build pushes" and "Build pull requests" ON
  • Add branches:except directive to your .travis.yml:

    branches:
      except:
        - /^pr\..*/
    

In this configuration:

  • any commit to branch feature-A will trigger the build
  • any commit to branch pr.feature-A will not trigger the build
  • if branch pr.feature-A is used in opened pull request then build will be triggered

Workflow example

  • temporary WIP branch shared between several developers: wip.feature-A, any commit to this branch will trigger the build
  • when branch is ready to be merged to master you can rename it from wip.feature-A to pr.feature-A and open pull request
  • if while reviewing pull request you want to apply new fixes, just push to pr.feature-A

On all the steps above only one build will be triggered.

1

For one of the repositories, I was working with, here is what I wanted:

There is an origin repo which is the main repo which does all the releases.

I wanted that all the pull requests coming to master branch of origin should be built with Travis only once irrespective of the fact that it comes from a forked repo or any other branch of the origin itself.

For this case, this works like a charm

if: (type == push) OR (type == pull_request AND fork == true)

sarthakgupta072
  • 451
  • 6
  • 13