github.com/spg/deis@v1.7.3/builder/rootfs/etc/confd/templates/builder (about) 1 #!/usr/bin/env bash 2 # 3 # builder hook called on every git receive-pack 4 # NOTE: this script must be run as root (for docker access) 5 # 6 set -eo pipefail 7 8 ARGS=3 9 10 indent() { 11 echo " $@" 12 } 13 14 puts-step() { 15 echo "-----> $@" 16 } 17 18 puts-step-sameline() { 19 echo -n "-----> $@" 20 } 21 22 puts-warn() { 23 echo " ! $@" 24 } 25 26 usage() { 27 echo "Usage: $0 <user> <repo> <sha>" 28 } 29 30 parse-string(){ 31 # helper to avoid the single quote escape 32 # occurred in command substitution 33 local args=() idx=0 IFS=' ' c 34 for c; do printf -v args[idx++] '%s ' "$c"; done 35 printf "%s\n" "${args[*]}" 36 } 37 38 if [ $# -ne $ARGS ]; then 39 usage 40 exit 1 41 fi 42 43 USER=$1 44 REPO=$2 45 GIT_SHA=$3 46 SHORT_SHA=${GIT_SHA:0:8} 47 APP_NAME="${REPO%.*}" 48 49 cd $(dirname $0) # ensure we are in the root dir 50 51 ROOT_DIR=$(pwd) 52 DOCKERFILE_SHIM="/usr/local/share/shim.dockerfile" 53 REPO_DIR="${ROOT_DIR}/${REPO}" 54 BUILD_DIR="${REPO_DIR}/build" 55 CACHE_DIR="${REPO_DIR}/cache" 56 57 # define image names 58 IMAGE_NAME="$APP_NAME:git-$SHORT_SHA" 59 TMP_IMAGE="{{ getv "/deis/registry/host" }}:{{ getv "/deis/registry/port" }}/$IMAGE_NAME" 60 61 # create app directories 62 mkdir -p $BUILD_DIR $CACHE_DIR 63 # create temporary directory inside the build dir for this push 64 TMP_DIR=$(mktemp -d -p $BUILD_DIR) 65 66 cd $REPO_DIR 67 git archive $GIT_SHA | tar -xmC $TMP_DIR 68 69 # switch to app context 70 cd $TMP_DIR 71 72 USING_DOCKERFILE=false 73 74 if [ -f Dockerfile ]; then 75 USING_DOCKERFILE=true 76 fi 77 78 # pull config from controller to be used during build 79 URL="{{ getv "/deis/controller/protocol" }}://{{ getv "/deis/controller/host" }}:{{ getv "/deis/controller/port" }}/v1/hooks/config" 80 RESPONSE=$(get-app-config -url="$URL" -key="{{ getv "/deis/controller/builderKey" }}" -user=$USER -app=$APP_NAME) 81 CODE=$? 82 83 if [ $CODE -ne 0 ]; then 84 puts-warn $RESPONSE 85 exit 1 86 fi 87 88 BUILD_OPTS=() 89 BUILD_OPTS+='/usr/bin/docker' 90 BUILD_OPTS+=' run -v /etc/environment_proxy:/etc/environment_proxy' 91 # get application configuration 92 BUILD_OPTS+=$(echo $RESPONSE | get-app-values) 93 94 # if no Dockerfile is present, use slugbuilder to compile a heroku slug 95 # and write out a Dockerfile to use that slug 96 if [ ! -f Dockerfile ]; then 97 # run in the background, we'll attach to it to retrieve logs 98 BUILD_OPTS+=' -d' 99 BUILD_OPTS+=' -v ' 100 BUILD_OPTS+=$(echo $TMP_DIR) 101 BUILD_OPTS+=':/tmp/app' 102 BUILD_OPTS+=' -v ' 103 BUILD_OPTS+=$(echo $CACHE_DIR) 104 BUILD_OPTS+=':/tmp/cache:rw' 105 # give slug group ownership of TMP_DIR and CACHE_DIR. 106 chown -R :2000 $TMP_DIR 107 chown :2000 $CACHE_DIR 108 # TMP_DIR is created using mktemp, which sets permissions to 700. Since 109 # we share this with the slug group, the slug group needs to be able to 110 # work with it. 111 chmod g+rwx $TMP_DIR $CACHE_DIR 112 113 BUILD_OPTS+=' deis/slugbuilder' 114 115 # build the application and attach to the process 116 JOB=$(eval $(parse-string "${BUILD_OPTS[@]}") ) 117 docker attach $JOB 118 119 # copy out the compiled slug 120 docker cp $JOB:/tmp/slug.tgz $TMP_DIR 121 # copy over the Dockerfile shim to the build dir 122 cp $DOCKERFILE_SHIM ./Dockerfile 123 fi 124 125 # force newline 126 echo "" >> Dockerfile 127 # inject builder-specific environment variables into the application environment 128 echo "ENV GIT_SHA $GIT_SHA" >> Dockerfile 129 130 echo 131 puts-step "Building Docker image" 132 docker build -t $TMP_IMAGE . 2>&1 133 puts-step "Pushing image to private registry" 134 docker push $TMP_IMAGE &>/dev/null 135 echo 136 137 # use Procfile if provided, otherwise try default process types from ./release 138 if [ -f Procfile ]; then 139 PROCFILE=$(cat Procfile | yaml2json-procfile) 140 elif [ -f $TMP_DIR/slug.tgz ]; then 141 # Sometimes, the buildpack will generate a Procfile instead of populating /bin/release 142 # /bin/release was unofficially deprecated for declaring default process types 143 if tar -tf $TMP_DIR/slug.tgz ./Procfile &> /dev/null; 144 then 145 PROCFILE="$(tar --to-stdout -xf $TMP_DIR/slug.tgz ./Procfile | yaml2json-procfile)" 146 else 147 PROCFILE=$(tar --to-stdout -xf $TMP_DIR/slug.tgz ./.release | extract-types) 148 fi 149 else 150 PROCFILE="{}" 151 fi 152 153 puts-step "Launching... " 154 URL="{{ getv "/deis/controller/protocol" }}://{{ getv "/deis/controller/host" }}:{{ getv "/deis/controller/port" }}/v1/hooks/build" 155 DATA=$(generate-buildhook "$SHORT_SHA" "$USER" "$APP_NAME" "$APP_NAME" "$PROCFILE" "$USING_DOCKERFILE") 156 PUBLISH_RELEASE=$(echo "$DATA" | publish-release-controller -url=$URL -key={{ getv "/deis/controller/builderKey" }}) 157 158 CODE=$? 159 if [ $CODE -ne 0 ]; then 160 puts-warn "ERROR: Failed to launch container" 161 puts-warn $PUBLISH_RELEASE 162 exit 1 163 fi 164 165 RELEASE=$(echo $PUBLISH_RELEASE | extract-version) 166 DOMAIN=$(echo $PUBLISH_RELEASE | extract-domain) 167 indent "done, $APP_NAME:v$RELEASE deployed to Deis" 168 echo 169 indent "http://$DOMAIN" 170 echo 171 indent "To learn more, use \`deis help\` or visit http://deis.io" 172 echo 173 174 # cleanup 175 cd $REPO_DIR 176 git gc &>/dev/null 177 if [ -n "$JOB" ]; then 178 docker rm -f $JOB &>/dev/null 179 fi