Skip to content

Instantly share code, notes, and snippets.

@sonodar
Last active March 31, 2022 08:32
Show Gist options
  • Save sonodar/667a142158ecfae3f5213e1213ea161d to your computer and use it in GitHub Desktop.
Save sonodar/667a142158ecfae3f5213e1213ea161d to your computer and use it in GitHub Desktop.
Wait for AWS CodeBuild jobs to complete while also outputting logs
#!/bin/bash
# aws-cli, jq, GNU-sed are required
set -euC -o pipefail
# Shortcut for get-log-events command.
get_log_events() {
local cmdArgs="--start-from-head --limit 100 --log-group-name ${1} --log-stream-name ${2}"
[[ -n ${3:-} ]] && cmdArgs="${cmdArgs} --next-token ${3}"
aws logs get-log-events ${cmdArgs}
}
# Since a log stream is created for each job, there is no problem with outputting all the logs in the stream.
print_log_events() {
local logEvents=$(get_log_events "${1}" "${2}" "${3:-}")
# Escape newlines so that they do not disappear when `echo` is executed.
local messages=$(echo "${logEvents}" | jq -r .events[].message | sed -z 's/\n\+/\\n/g')
# The `nextForwardToken` will have a value whether or not the next log is present.
local nextToken=$(echo "${logEvents}" | jq -r .nextForwardToken)
# Log output to the end will be `events: []`. Therefore, the message will be an empty string.
while [[ -n ${messages} ]]; do
echo -e "${messages}"
logEvents=$(get_log_events "${1}" "${2}" "${nextToken}")
messages=$(echo "${logEvents}" | jq -r .events[].message | sed -z 's/\n\+/\\n/g')
nextToken=$(echo "${logEvents}" | jq -r .nextForwardToken)
done
}
get_current_build_status_and_print_logs() {
local buildStatus=$(aws codebuild batch-get-builds --ids "${1}" | jq .builds[0])
local logGroup=$(echo "${buildStatus}" | jq -r .logs.groupName)
local logStream=$(echo "${buildStatus}" | jq -r .logs.streamName)
if [[ ${logGroup} != "null" ]] && [[ ${logStream} != "null" ]]; then
print_log_events "${logGroup}" "${logStream}" >&2
fi
echo "${buildStatus}"
}
wait_for_build_complete() {
local id=${1}
declare -i timeoutTime=$(date -d "${2:-900} seconds" +%s)
while true; do
buildStatus=$(get_current_build_status_and_print_logs "${id}")
isCompleted=$(echo "${buildStatus}" | jq -r .buildComplete)
currentStatus=$(echo "${buildStatus}" | jq -r .buildStatus)
if [[ ${isCompleted} == "true" ]]; then
echo "${currentStatus}"
[[ ${currentStatus} != "SUCCEEDED" ]] || return 1
return 0
fi
if [[ $(date +%s) -ge ${timeoutTime} ]]; then
echo "Waiting for build completion timed out" >&2
return 124
fi
sleep 10s
done
}
wait_for_build_complete "${@}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment