Skip to content

Instantly share code, notes, and snippets.

@rolebi
Last active May 8, 2018 12:08
Show Gist options
  • Save rolebi/2986d0899a526fd6cfe6 to your computer and use it in GitHub Desktop.
Save rolebi/2986d0899a526fd6cfe6 to your computer and use it in GitHub Desktop.
Travis AWS codedeploy fail build if deployment fail
env:
global:
# implement your own logic in get_env_for_git_reference.sh
- TARGET_ENV="`test $TRAVIS_TAG && ./get_target_env_for_git_reference.sh $TRAVIS_TAG`"
# ENV integration
- AWS_INTEGRATION_APPLICATION=xxxx
- AWS_INTEGRATION_DEPLOYMENT_GROUP=xxxx
- AWS_INTEGRATION_REGION=xxxx
#AWS_INTEGRATION_ACCESS_KEY
- secure: "xxxx"
# AWS_INTEGRATION_ACCESS_SECRET
- secure: "xxxx"
# each target environment must have its own configuration ...
cache:
directories:
- $HOME/.local/bin
before_script:
- export PATH=$PATH:$HOME/.local/bin
after_deploy:
- ./ensure_deployment.sh "$TARGET_ENV" "$TRAVIS_TAG" || travis_terminate 1;
deploy:
# INTEGRATION
- provider: codedeploy
region: xxxx
access_key_id:
secure: "xxxx"
secret_access_key:
secure: "xxxx"
application: xxxx
deployment_group: xxxx
revision_type: github
on:
tags: true
condition: '"$TARGET_ENV" == "integration"'
# each target environment must have its own configuration ...
#!/bin/bash
set -e
function aws_call()
{
AWS_ACCESS_KEY_ID="$ACCESS_KEY" AWS_SECRET_ACCESS_KEY="$ACCESS_SECRET" aws "$@"
}
function get_git_commit_for_reference()
{
git rev-parse "$1"
}
function get_deployments_names_since()
{
aws_call deploy list-deployments \
--application-name "$APPLICATION" \
--deployment-group-name "$DEPLOYMENT_GROUP" \
--region "$REGION" \
--create-time-range start="$1" | jq .deployments[] | sed s/\"//g | tr '\r\n' ' '
}
function get_deployment_data()
{
aws_call deploy get-deployment \
--deployment-id "$1" \
--region "$REGION" | jq .deploymentInfo
}
function get_deployments_datum()
{
aws_call deploy batch-get-deployments \
--deployment-ids "$@" \
--region "$REGION" | jq .deploymentsInfo
}
function get_deployment_name()
{
local FAIL_AFTER=$1
local LOOKUP=$2
local REFERENCE=$3
local TIMER=0
local CURRENT_COMMIT=`get_git_commit_for_reference "$REFERENCE"`
local DEPLOYMENT_DATA=''
while [ 42 -eq 42 ]
do
local DEPLOYMENT_NAMES=`get_deployments_names_since $(($STARTING_TIME - $LOOKUP))`
if [ "$DEPLOYMENT_NAMES" ]
then
# get deployment data for commit if exists
DEPLOYMENT_DATA=`get_deployments_datum $DEPLOYMENT_NAMES | jq '.[] | {((.createTime|tostring + " ") + .deploymentId + " " + .revision.gitHubLocation.commitId|tostring): .status}' | sed 's/[{}":.]//g; s/^ *//; s/ *$//; /^$/d; /^\s*$/d' | sort -s -n -r -k 1,1 | grep "$CURRENT_COMMIT" | head -1`
if [ "$DEPLOYMENT_DATA" ]
then
echo "$DEPLOYMENT_DATA" | cut -d' ' -f2
return 0
fi
fi
if [ "$TIMER" -gt "$FAIL_AFTER" ]
then
echo "Unable to retrieve deployment data for $REFERENCE to $TARGET_ENV" 1>&2
exit 1
fi
sleep "$FETCH_RATE"
((TIMER+=$FETCH_RATE))
done
}
function get_deployment_status_from_data()
{
echo "$1" | jq '.status' | sed 's/"//g'
}
function get_deployment_errors_from_data()
{
echo "$1" | jq '.errorInformation | {(.code): .message}' | sed 's/[{}":.]//g; s/^ *//; s/ *$//; /^$/d; /^\s*$/d'
}
function ensure_deployment_is_successful()
{
local DEPLOYMENT_NAME=$1
local TIMER=0
while [ 42 -eq 42 ]
do
DEPLOYMENT_DATA=`get_deployment_data "$DEPLOYMENT_NAME"`
STATUS=`get_deployment_status_from_data "$DEPLOYMENT_DATA"`
case "$STATUS" in
Succeeded)
echo "Deployment of $REFERENCE on $TARGET_ENV is finished"
break
;;
Stopped)
echo "Deployment of $REFERENCE on $TARGET_ENV has been stopped" 1>&2
exit 1
;;
Failed)
echo "Deployment of $REFERENCE on $TARGET_ENV has failed" 1>&2
echo "Errors:" 1>&2
get_deployment_errors_from_data "$DEPLOYMENT_DATA" 1>&2
exit 1
;;
esac
echo "`date +"%T"` Current status of $DEPLOYMENT_NAME: $STATUS"
sleep "$FETCH_RATE"
((TIMER+=$FETCH_RATE))
if [[ "$TIMER" > 180 && "$TIMER" < $((180 + $FETCH_RATE)) ]]
then
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
echo " Codedeploy is taking an abnormal amount of time to deploy the application."
echo " The Codedeploy agent on $TARGET_ENV may be stopped."
echo " To restart it, you can use this command:"
echo
echo " ssh xxxx xxxxxx"
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
fi
done
}
############### INITIALIZATION ###############
STARTING_TIME=`date +%s`
FETCH_RATE=15 # Look every x seconds
NAME_FAIL_AFTER=90 # Fail after 90s if build is not created
NAME_SEARCH_LOOKUP=90 # look 90s before this command start in CodeDeploy history to find current build
DIR="$(cd "$(dirname "$0")" && pwd)"
TARGET_ENV=$1
REFERENCE=$2
if [ -z "$REFERENCE" -o -z "$TARGET_ENV" ]
then
echo "usage: $0 target_env reference" 1>&2
exit 1
fi
echo "Retrieving AWS credentials for $TARGET_ENV"
ACCESS_KEY='' ACCESS_SECRET='' REGION='' DEPLOYMENT_GROUP='' APPLICATION=''
for VAR_NAME in REGION ACCESS_KEY ACCESS_SECRET DEPLOYMENT_GROUP APPLICATION
do
ENV_VAR_NAME=`echo "AWS_${TARGET_ENV^^}_$VAR_NAME" | tr '-' '_'`
declare "$VAR_NAME=${!ENV_VAR_NAME}"
if [ -z "${!VAR_NAME}" ]
then
echo "Unable to find s3 ${VAR_NAME,,} for env $TARGET_ENV. Please ensure that ${ENV_VAR_NAME} env variable is available" 1>&2
exit 1
fi
done
############### START HERE ###############
echo
echo "Target: $TARGET_ENV@$REFERENCE"
echo
echo "Checking/installing dependencies"
/bin/bash "$DIR/install_aws.sh"
/bin/bash "$DIR/install_jq.sh"
echo "Getting deployment name"
DEPLOYMENT_NAME=`get_deployment_name "$NAME_FAIL_AFTER" "$NAME_SEARCH_LOOKUP" "$REFERENCE"`
echo "Found $DEPLOYMENT_NAME for deployment of $REFERENCE on $TARGET_ENV"
echo "Waiting for deployment of $DEPLOYMENT_NAME"
# Not required anymore. See https://github.com/travis-ci/dpl/pull/269 (not documented ATM)
ensure_deployment_is_successful "$DEPLOYMENT_NAME"
echo "Waiting to ensure that codedeploy actions are all completed..."
sleep 60 # wait ensuring that everything is really finished on codedeploy side
echo
echo "Checking application status of $REFERENCE on $TARGET_ENV"
echo
# implement your own logic here
#!/bin/bash
set -e
if [ -z "`which aws || echo`" ]
then
echo "Installing AWS CLI dependency"
pip install --user awscli 1> /dev/null
fi
#!/bin/bash
set -e
if [ -z "`which jq || echo`" ]
then
echo "installing JSON parser"
wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-1.5.tar.gz
tar -xzf jq-1.5.tar.gz
rm -f jq-1.5.tar.gz
cd jq-1.5
go_back() {
cd ..
}
trap go_back EXIT
autoreconf -i
./configure --disable-maintainer-mode
make
sudo make install
mv jq "$HOME/.local/bin/"
trap - EXIT
cd ..
rm -Rf jq-1.5
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment