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')
1 Like

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.