Skip to content

Commit

Permalink
Merge #93
Browse files Browse the repository at this point in the history
93: Add workflow as a queue target [semver:minor] r=eddiewebb a=soniqua

### Checklist

- [x] All new jobs, commands, executors, parameters have descriptions
- [x] Examples have been added for any significant new features
- [ ] README has been updated, if necessary

### Motivation, issues

This change allows users to wait for no occurrences of a target `workflow` to complete.

This enables pull-request style checks to be executed across multiple open PRs, without the workflows conflicting.

Relates to (but may not close) #76.

### Description

add `only-on-workflow` to the orb.
- Specify a `workflow` name here for the queue orb to wait for all occurrences of a workflow to finish.
- If specified in conjunction with `consider-branch: false` waits for all occurrences of a workflow across all branches to finish.


Co-authored-by: Matthew Rogers <matt.rogers@snyk.io>
Co-authored-by: Matt Rogers <matt.rogers@snyk.io>
  • Loading branch information
bors[bot] and soniqua committed Mar 31, 2023
2 parents 988b09b + 36e970c commit 944d963
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ commands:
circleci config pack src/ > packed.yml
circleci orb validate packed.yml
pr-comment:
description: add nessage to pr this build originated from
description: add message to pr this build originated from
steps:
- run:
name: Publish Version to PR
Expand Down
23 changes: 17 additions & 6 deletions src/commands/until_front_of_line.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ parameters:
type: string
default: "*"
description: "Only queue on specified branch"
only-on-workflow:
type: string
default: "*"
description: "Only queue on a specified workflow. Consider combining this with `consider-branch`:`false`."
vcs-type:
type: string
default: "github"
Expand Down Expand Up @@ -171,9 +175,16 @@ steps:
# falsey parameters are empty strings, so always compare against 'true'
if [ "<<parameters.block-workflow>>" = "true" ] ;then
echo "Orb parameter block-workflow is true."
echo "This job will block until no previous workflows have *any* jobs running."
oldest_running_build_num=`jq 'sort_by(.workflows.created_at)| .[0].build_num' /tmp/augmented_jobstatus.json`
oldest_commit_time=`jq 'sort_by(.workflows.created_at)| .[0].workflows.created_at' /tmp/augmented_jobstatus.json`
if [ "<<parameters.only-on-workflow>>" = "*" ]; then
echo "This job will block until no previous workflows have *any* jobs running."
oldest_running_build_num=`jq 'sort_by(.workflows.created_at)| .[0].build_num' /tmp/augmented_jobstatus.json`
oldest_commit_time=`jq 'sort_by(.workflows.created_at)| .[0].workflows.created_at' /tmp/augmented_jobstatus.json`
else
echo "Orb parameter only-on-workflow is true."
echo "This job will block until no previous occurrences of workflow <<parameters.only-on-workflow>> have *any* jobs running."
oldest_running_build_num=`jq ". | map(select(.workflows.workflow_name| test(\"<<parameters.only-on-workflow>>\";\"sx\"))) | sort_by(.workflows.created_at)| .[0].build_num" /tmp/augmented_jobstatus.json`
oldest_commit_time=`jq ". | map(select(.workflows.workflow_name| test(\"<<parameters.only-on-workflow>>\";\"sx\"))) | sort_by(.workflows.created_at)| .[0].workflows.created_at" /tmp/augmented_jobstatus.json`
fi
else
echo "Orb parameter block-workflow is false."
echo "Only blocking execution if running previous jobs matching this job: ${JOB_NAME}"
Expand All @@ -191,7 +202,7 @@ steps:
cat /tmp/jobstatus.json || exit 0
echo "All running jobs with created_at:"
cat /tmp/augmented_jobstatus.json || exit 0
echo "All worfklow details."
echo "All workflow details."
cat /tmp/workflow-*.json
exit 1
fi
Expand All @@ -202,7 +213,7 @@ steps:
}
cancel_current_build(){
echo "Cancelleing build ${CIRCLE_BUILD_NUM}"
echo "Cancelling build ${CIRCLE_BUILD_NUM}"
cancel_api_url_template="${CIRCLECI_BASE_URL}/api/v1.1/project/${VCS_TYPE}/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}/cancel?circle-token=${<< parameters.circleci-api-key >>}"
curl -s -X POST $cancel_api_url_template > /dev/null
}
Expand Down Expand Up @@ -245,7 +256,7 @@ steps:
echo "Oldest Workflow Timestamp: $oldest_commit_time"
if [[ ! -z "$my_commit_time" ]] && [[ "$oldest_commit_time" > "$my_commit_time" || "$oldest_commit_time" = "$my_commit_time" ]] ; then
# API returns Y-M-D HH:MM (with 24 hour clock) so alphabetical string compare is accurate to timestamp compare as well
# recent-jobs API does not include pending, so it is posisble we queried in between a workfow transition, and we;re NOT really front of line.
# recent-jobs API does not include pending, so it is possible we queried in between a workflow transition, and we;re NOT really front of line.
if [ $confidence -lt <<parameters.confidence>> ];then
# To grow confidence, we check again with a delay.
confidence=$((confidence+1))
Expand Down
5 changes: 5 additions & 0 deletions src/jobs/block_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ parameters:
type: string
default: "*"
description: "Only queue on specified branch. Default is to enforce serialization on all branches."
only-on-workflow:
type: string
default: "*"
description: "Only queue on a specified workflow. Consider combining this with `consider-branch`:`false`."
vcs-type:
type: string
default: "github"
Expand Down Expand Up @@ -50,6 +54,7 @@ steps:
block-workflow: <<parameters.block-workflow>>
time: <<parameters.time>>
dont-quit: <<parameters.dont-quit>>
only-on-workflow: <<parameters.only-on-workflow>>
only-on-branch: <<parameters.only-on-branch>>
vcs-type: <<parameters.vcs-type>>
confidence: <<parameters.confidence>>
Expand Down
12 changes: 12 additions & 0 deletions test/inputs/command-only-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
jobs:
build:
docker:
- image: circleci/node:10
working_directory: ~/repo
steps:
- queue/until_front_of_line:
# only on workflow
consider-branch: false
block-workflow: true
only-on-workflow: "build-deploy"
time: "1"
44 changes: 35 additions & 9 deletions test/test_expansion.bats
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function setup {

assert_contains_text "Max Queue Time: 1 minutes"
assert_contains_text "Max wait time exceeded"
assert_contains_text "Cancelleing build 2"
assert_contains_text "Cancelling build 2"
[[ "$status" == "1" ]]
}

Expand Down Expand Up @@ -157,7 +157,7 @@ function setup {
assert_contains_text "Rerunning check 1/1"
assert_contains_text "This build (${CIRCLE_BUILD_NUM}) is queued, waiting for build number (3) to complete."
assert_contains_text "Max wait time exceeded"
assert_contains_text "Cancelleing build 2"
assert_contains_text "Cancelling build 2"
[[ "$status" == "1" ]]
}

Expand Down Expand Up @@ -241,7 +241,7 @@ function setup {

assert_contains_text "Max Queue Time: 1 minutes"
assert_contains_text "Max wait time exceeded"
assert_contains_text "Cancelleing build 2"
assert_contains_text "Cancelling build 2"
[[ "$status" == "1" ]]
}

Expand Down Expand Up @@ -274,8 +274,6 @@ function setup {
[[ "$status" == "0" ]]
}



@test "Command: script will consider branch" {
# given
process_config_with test/inputs/command-non-default.yml
Expand All @@ -297,14 +295,43 @@ function setup {
export CIRCLE_PR_REPONAME=""
run bash ${BATS_TMPDIR}/script-${BATS_TEST_NUMBER}.bash


assert_contains_text "Max Queue Time: 1 minutes"
assert_contains_text "Orb parameter 'consider-branch' is false, will block previous builds on any branch"
assert_contains_text "Front of the line, WooHoo!, Build continuing"
[[ "$status" == "0" ]]

}

@test "Command: script will queue on same workflow when only-on-workflow is set" {
# given
process_config_with test/inputs/command-only-workflow.yml
export TESTING_MOCK_RESPONSE=test/api/jobs/onepreviousjob-differentname.json
export TESTING_MOCK_WORKFLOW_RESPONSES=test/api/workflows

# when
assert_jq_match '.jobs | length' 1 #only 1 job
assert_jq_match '.jobs["build"].steps | length' 1 #only 1 steps

jq -r '.jobs["build"].steps[0].run.command' $JSON_PROJECT_CONFIG > ${BATS_TMPDIR}/script-${BATS_TEST_NUMBER}.bash

export CIRCLE_BUILD_NUM="2"
export CIRCLE_BRANCH="somespecialbranch"
export CIRCLE_JOB="singlejob"
export CIRCLE_PROJECT_USERNAME="madethisup"
export CIRCLE_PROJECT_REPONAME="madethisup"
export CIRCLE_REPOSITORY_URL="madethisup"
export CIRCLE_BRANCH="madethisup"
export CIRCLE_PR_REPONAME=""
run bash ${BATS_TMPDIR}/script-${BATS_TEST_NUMBER}.bash

assert_contains_text "Orb parameter block-workflow is true."
assert_contains_text "Max Queue Time: 1 minutes"
assert_contains_text "This job will block until no previous occurrences of workflow build-deploy have *any* jobs running."
assert_contains_text "Max wait time exceeded"
assert_contains_text "Cancelling build 2"
[[ "$status" == "1" ]]
}


@test "Command: script will skip queueing on branches that don't match filter" {
# given
Expand Down Expand Up @@ -337,7 +364,7 @@ function setup {
@test "Command: script will consider branch default" {
# given
process_config_with test/inputs/command-defaults.yml
export TESTING_MOCK_RESPONSE=test/api/jobs/nopreviousjobs.json #branch filtereing handles by API, so return no matching builds
export TESTING_MOCK_RESPONSE=test/api/jobs/nopreviousjobs.json #branch filtering handled by API, so return no matching builds
export TESTING_MOCK_WORKFLOW_RESPONSES=test/api/workflows

# when
Expand Down Expand Up @@ -395,7 +422,6 @@ function setup {

}


@test "Command: script will skip queueing on forks" {
# given
process_config_with test/inputs/command-defaults.yml
Expand Down Expand Up @@ -443,4 +469,4 @@ function setup {

run bash ${BATS_TMPDIR}/script-${BATS_TEST_NUMBER}.bash
assert_contains_text "Orb parameter block-workflow is true."
}
}

0 comments on commit 944d963

Please sign in to comment.