Skip to content

Instantly share code, notes, and snippets.

@phoolish
Forked from clayallsopp/circle-lock.sh
Created July 16, 2018 19:02
Show Gist options
  • Select an option

  • Save phoolish/0dd8f636330e5a095f4a19a3e8e6b445 to your computer and use it in GitHub Desktop.

Select an option

Save phoolish/0dd8f636330e5a095f4a19a3e8e6b445 to your computer and use it in GitHub Desktop.

Revisions

  1. @clayallsopp clayallsopp created this gist Aug 12, 2017.
    114 changes: 114 additions & 0 deletions circle-lock.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,114 @@
    #!/usr/bin/env bash

    set -o xtrace -o errexit -o pipefail -o nounset

    ########################################################################################
    # CircleCI's current recommendation for roughly serializing a subset
    # of build commands for a given branch
    #
    # circle discussion thread - https://discuss.circleci.com/t/serializing-deployments/153
    # Code from - https://github.com/bellkev/circle-lock-test
    ########################################################################################


    # sets $branch, $job_name, $tag, $rest
    parse_args() {
    while [[ $# -gt 0 ]]; do
    case $1 in
    -b|--branch) branch="$2" ;;
    -j|--job-name) job_name="$2" ;;
    -t|--tag) tag="$2" ;;
    *) break ;;
    esac
    shift 2
    done
    rest=("$@")
    }

    # reads $branch, $tag, $commit_message
    should_skip() {
    if [[ "$branch" && "$CIRCLE_BRANCH" != "$branch" ]]; then
    echo "Not on branch $branch. Skipping..."
    return 0
    fi

    if [[ "$job_name" && "$CIRCLE_JOB" != "$job_name" ]]; then
    echo "Not running $job_name. Skipping..."
    return 0
    fi

    if [[ "$tag" && "$commit_message" != *\[$tag\]* ]]; then
    echo "No [$tag] commit tag found. Skipping..."
    return 0
    fi

    return 1
    }

    # reads $branch, $job_name, $tag
    # sets $jq_prog
    make_jq_prog() {
    local jq_filters=""

    if [[ $branch ]]; then
    jq_filters+=" and .branch == \"$branch\""
    fi

    if [[ $job_name ]]; then
    jq_filters+=" and .workflows?.job_name? == \"$job_name\""
    fi

    if [[ $tag ]]; then
    jq_filters+=" and (.subject | contains(\"[$tag]\"))"
    fi

    jq_prog=".[] | select(.build_num < $CIRCLE_BUILD_NUM and (.status | test(\"running|pending|queued\")) $jq_filters) | .build_num"
    jq_later_builds_prog=".[] | select(.build_num > $CIRCLE_BUILD_NUM and (.status | test(\"running|pending|queued\")) $jq_filters) | .build_num"
    }


    if [[ "$0" != *bats* ]]; then
    set -e
    set -u
    set -o pipefail

    branch=""
    tag=""
    job_name=""
    rest=()
    api_url="https://circleci.com/api/v1/project/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME?circle-token=$CIRCLE_TOKEN&limit=100"
    if [[ $branch ]]; then
    api_url="https://circleci.com/api/v1/project/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$branch?circle-token=$CIRCLE_TOKEN&limit=100"
    fi

    parse_args "$@"
    commit_message=$(git log -1 --pretty=%B)
    if should_skip; then exit 0; fi
    make_jq_prog

    echo "Checking for running builds..."

    while true; do
    builds=$(curl -s -H "Accept: application/json" "$api_url" | jq "$jq_prog")
    later_builds=$(curl -s -H "Accept: application/json" "$api_url" | jq "$jq_later_builds_prog")
    if [[ $later_builds ]]; then
    echo "Later builds detected, bailing"
    echo "$later_builds"
    exit 0
    fi
    if [[ $builds ]]; then
    echo "Waiting on builds:"
    echo "$builds"
    else
    break
    fi
    echo "Retrying in 10 seconds..."
    sleep 10
    done

    echo "Acquired lock"

    if [[ "${#rest[@]}" -ne 0 ]]; then
    "${rest[@]}"
    fi
    fi