patternMinor
Jenkins & Bitbucket; cancel previous build if new commit made to same branch?
Viewed 0 times
commitpreviousmadenewsamejenkinscancelbitbucketbranchbuild
Problem
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?
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?
Solution
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
If the state is
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:
This approach avoids wasting unit test resources and can easily be adjusted even for more than one but still limited resources.
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 IDvalues 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.
Context
StackExchange DevOps Q#2820, answer score: 3
Revisions (0)
No revisions yet.