7

We have Jenkins running unit tests when commits are made to our repo in Bitbucket. This is controlled by the Bitbucket Plugin, ie via a Bitbucket webhook.

Currently, if a commit is made to Branch A a unit test kicks off. If while that job is running a second commit is made to Branch A a second unit test will kick off, so there are now two unit tests on the same branch but with slightly different code.

Our preferred behavior is that the first commit's test would be aborted when the second test kicked off, so that only the most recent unit test is being run. Can this be achieved?

To clarify; We have many branches so we cannot just prevent concurrent builds, cancel the last as soon as the next starts, etc. Whatever method is used must specifically check if the branch already has a job running for it, not if the job in general is already running.

I've seen some trigger controls for Git, but not Bitbucket. I also found a script to check if the job's already running and cancel it if so, but as mentioned before that doesn't suit our use case. Am I missing something?

2
  • This becomes a lot easier if you use the Bitbucket Branch Source plugin, since every branch and PR of a repo in a Bitbucket project would have its own Jenkins job, and from there it's trivially easy to check if a job has a more recent build running and abort if so.
    – jayhendren
    Commented Dec 8, 2017 at 19:00
  • Have you found any solution ? Especially for bitbucket ?
    – user43968
    Commented Aug 23, 2018 at 19:06

1 Answer 1

3

Note: this answer comes from my background of building custom solutions, it's not a config-only one, which, if available, would obviously be preferable. But it's maybe something to consider otherwise.

You could teach the script executing the unit test job to persist a per-branch execution state.

When the script is launched it would need to obtain the branch name from its invocation parameters. It would then obtain the persisted state for the branch.

If the state is either missing or not running it would set it to running + job ID, execute the unit test and then set the state to not running (or delete it).

If the state is running + job ID it means another unit test is already running and you have the corresponding job ID. The script can then (gracefully?) terminate the already running job by its ID and take it's place, updating the state to running + new job ID.

But IMHO terminating a job in progress (which may be very close to completion) is not ideal - it leaves room for constantly killing jobs and launching news ones only to be, at their own turn, killed by subsequent jobs - all without actually completing any of them.

Instead I'd modify the logic to:

  • leave the job in progress alone and instead just record in the persisted state a pending job ID (either a unique value, overwritten to reflect the most recent pending job submitted or a list of all pending jobs, sorted by submission time)
  • when the job in progress completes it checks the pending job ID values and, if any, launches the most recent one (or the oldest one, or even follow some other selection logic, if using a list)

This approach avoids wasting unit test resources and can easily be adjusted even for more than one but still limited resources.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.