[Workaround] Auto-cancel redundant builds on the default branch

By design the “Auto-cancel redundant builds” functionality does not apply to your project’s default branch.

This workaround can also be used if for any reason you prefer not to enable the “Auto-cancel redundant builds” functionality at the project-level.

Below is a set of instructions that will allow you to auto-cancel redundant workflows on any branch (including the default branch).
You can either:

  • Put the commands into a script within your repository and call it at the start of the workflow (either within a separate job or at the start of the first existing job in the workflow)
  • Add the commands within a job (new or existing) or as pre-steps to another job.

Note that you’ll need to add a personal API key as an environment variable MyToken .

#!/bin/bash

## Get the name of the workflow
WF_NAME=$(curl --header "Circle-Token: $MyToken" --request GET "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}"|jq -r .name)

## Get the IDs of pipelines created by the current user on the same branch
PIPE_IDS=$(curl --header "Circle-Token: $MyToken" --request GET "https://circleci.com/api/v2/project/gh/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pipeline?branch=$CIRCLE_BRANCH"|jq -r --arg CIRCLE_USERNAME "$CIRCLE_USERNAME" '.items[]|select(.state == "created")|select(.trigger.actor.login == $CIRCLE_USERNAME).id')

## Get the IDs of currently running/on_hold workflows with the same name except the current workflow ID
if [ ! -z "$PIPE_IDS" ]; then
  for PIPE_ID in $PIPE_IDS
  do
    curl --header "Circle-Token: $MyToken" --request GET "https://circleci.com/api/v2/pipeline/${PIPE_ID}/workflow"|jq -r --arg CIRCLE_WORKFLOW_ID "$CIRCLE_WORKFLOW_ID" --arg WF_NAME "${WF_NAME}" '.items[]|select(.status == "on_hold" or .status == "running")|select(.name == $WF_NAME)|select(.id != $CIRCLE_WORKFLOW_ID)|.id' >> WF_to_cancel.txt
  done
fi

## Cancel any currently running/on_hold workflow with the same name
if [ -s WF_to_cancel.txt ]; then
  echo "Cancelling the following workflow(s):"
  cat WF_to_cancel.txt 
  while read WF_ID;
    do
      curl --header "Circle-Token: $MyToken" --request POST https://circleci.com/api/v2/workflow/$WF_ID/cancel
    done < WF_to_cancel.txt
  ## Allowing some time to complete the cancellation
  sleep 2
  else
    echo "Nothing to cancel"
fi

In case you wish to auto-cancel redundant builds regardless of the user, replace:

PIPE_IDS=$(curl --header "Circle-Token: $MyToken" --request GET "https://circleci.com/api/v2/project/gh/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pipeline?branch=$CIRCLE_BRANCH"|jq -r --arg CIRCLE_USERNAME "$CIRCLE_USERNAME" '.items[]|select(.state == "created")|select(.trigger.actor.login == $CIRCLE_USERNAME).id')

with

PIPE_IDS=$(curl --header "Circle-Token: $MyToken" --request GET "https://circleci.com/api/v2/project/gh/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pipeline?branch=$CIRCLE_BRANCH"|jq -r '.items[]|select(.state == "created").id')
2 Likes

Is there any way to generate a token that only has access to a specific project? If I have multiple projects in CircleCI and generate a key it’d effectively give people access to all of my projects, even if they only have access to certain projects

@JakeBooher,

The above solution leverages CircleCI API v2, and project API tokens are currently not supported by API v2.

The only workaround I can suggest is to create a machine user for each project, and generate a personal API token for each.

…or one machine user with appropriate access to specific projects.

This isn’t really good enough tbh.

if you have two workflows that run close enough together it’s actually possible for them to cancel each other.

1 Like

There’s still no way to accomplish this without such a script. It’s ridiculous that this isn’t a checkbox (EG: Enable on all branches).

1 Like

I think this is a business choice that CircleCi made to make more money… I also think it is ridiculous that I have to pay for these redundant builds for default branch that do not add any value to our testing process!

To CircleCi admins: please make a checkbox for cancelling redundant builds for default branch also

1 Like

Throwing in my vote for this too

3 Likes

using a script for simple operational things like this seems overly complex…

+1 for a checkbox

2 Likes

This should clearly be an option in the UI.

Is there a way to list the branches that we’d want to not auto-cancel? Right now, it’s the default branch, however integration branches, particularly the top-level integration branch (like ‘develop’), would want all builds to continue.

:wave: Hi @frey,

At the moment, this is not possible. But what you can do is disable the feature altogether, and use the same logic as that in this workaround, with a condition on the branch name.

You could, for example, add a case statement at the start of the script to condition its execution on the CIRCLE_BRANCH built-in environment variable having specific values.

I would also encourage you to add a vote to this feature request.

Thanks for the reply. Has someone built an orb that implements this script?

@frey , there’s no certified/CircleCI-branded orb. As for a third-party orb, you’d need to look into the orb registry.