github.com/discordapp/buildkite-agent@v2.6.6+incompatible/templates/bootstrap.sh (about) 1 #!/bin/bash 2 3 # 4 # _ _ _ _ _ _ _ _ _ _ 5 # | | (_) | | | | (_) | | | | | | | 6 # | |__ _ _ _| | __| | | ___| |_ ___ | |__ ___ ___ | |_ ___| |_ _ __ __ _ _ __ 7 # | '_ \| | | | | |/ _` | |/ / | __/ _ \ | '_ \ / _ \ / _ \| __/ __| __| '__/ _` | '_ \ 8 # | |_) | |_| | | | (_| | <| | || __/ | |_) | (_) | (_) | |_\__ \ |_| | | (_| | |_) | 9 # |_.__/ \__,_|_|_|\__,_|_|\_\_|\__\___| |_.__/ \___/ \___/ \__|___/\__|_| \__,_| .__/ 10 # | | 11 # |_| 12 # https://github.com/buildkite/agent/blob/master/templates/bootstrap.sh 13 14 # It's possible for a hook or a build script to change things like `set -eou 15 # pipefail`, causing our bootstrap.sh to misbehave, so this function will set 16 # them back to what we expect them to be. 17 function buildkite-flags-reset { 18 # Causes this script to exit if a variable isn't present 19 set -u 20 21 # Ensure command pipes fail if any command fails (e.g. fail-cmd | success-cmd == fail) 22 set -o pipefail 23 24 # Turn off debugging 25 set +x 26 27 # If a command fails, don't exit, just keep on truckin' 28 set +e 29 } 30 31 buildkite-flags-reset 32 33 ############################################################## 34 # 35 # BOOTSTRAP FUNCTIONS 36 # These functions are used throughout the bootstrap.sh file 37 # 38 ############################################################## 39 40 BUILDKITE_PROMPT="\033[90m$\033[0m" 41 42 function buildkite-prompt { 43 # Output "$" prefix in a pleasant grey... 44 echo -ne "$BUILDKITE_PROMPT" 45 46 # ...each positional parameter with spaces and correct escaping for copy/pasting... 47 printf " %q" "$@" 48 49 # ...and a trailing newline. 50 echo 51 } 52 53 function buildkite-comment { 54 # Output a comment prefixed with a hash in grey 55 echo -ne "\033[90m" 56 echo "#" "$@" 57 echo -ne "\033[0m" 58 } 59 60 # Shows the command being run, and runs it 61 function buildkite-prompt-and-run { 62 buildkite-prompt "$@" 63 "$@" 64 } 65 66 # Shows the command about to be run, and exits if it fails 67 function buildkite-run { 68 buildkite-prompt-and-run "$@" || exit $? 69 } 70 71 function buildkite-debug { 72 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 73 echo "$@" 74 fi 75 } 76 77 function buildkite-debug-comment { 78 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 79 buildkite-comment "$@" 80 fi 81 } 82 83 function buildkite-prompt-debug { 84 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 85 buildkite-prompt "$@" 86 fi 87 } 88 89 # Runs the command, but only output what it's doing if we're in DEBUG mode 90 function buildkite-run-debug { 91 buildkite-prompt-debug "$@" 92 "$@" 93 } 94 95 # Show an error and exit 96 function buildkite-error { 97 echo -e "~~~ :rotating_light: \033[31mBuildkite Error\033[0m" 98 echo "$@" 99 echo "^^^ +++" 100 exit 1 101 } 102 103 # Show a warning 104 function buildkite-warning { 105 echo -ne "\033[33m⚠️ Buildkite Warning:\033[0m " 106 echo "$@" 107 echo "^^^ +++" 108 } 109 110 # Run a hook script. It won't exit on failure. It will store the hooks exit 111 # status in BUILDKITE_LAST_HOOK_EXIT_STATUS 112 export BUILDKITE_LAST_HOOK_EXIT_STATUS="" 113 function buildkite-hook { 114 HOOK_LABEL="$1" 115 HOOK_SCRIPT_PATH="$2" 116 117 if [[ -e "$HOOK_SCRIPT_PATH" ]]; then 118 # Print to the screen we're going to run the hook 119 echo "~~~ Running $HOOK_LABEL hook" 120 buildkite-prompt "$HOOK_SCRIPT_PATH" 121 122 # Run the script and store it's exit status. We don't run the hook in a 123 # subshell because we want the hook scripts to be able to modify the 124 # bootstrap's ENV variables. The only downside with this approach, is if 125 # they call `exit`, the bootstrap script will exit as well. We this is an 126 # acceptable tradeoff. 127 source "$HOOK_SCRIPT_PATH" 128 BUILDKITE_LAST_HOOK_EXIT_STATUS=$? 129 130 # Reset the bootstrap.sh flags 131 buildkite-flags-reset 132 else 133 # When in debug mode, show that we've skipped a hook 134 buildkite-debug "~~~ Running $HOOK_LABEL hook" 135 buildkite-debug-comment "Skipping, no hook script found at: $HOOK_SCRIPT_PATH" 136 fi 137 } 138 139 # Exit from the bootstrap.sh script if the hook exits with a non-0 exit status 140 function buildkite-hook-exit-on-error { 141 if [[ -n "$BUILDKITE_LAST_HOOK_EXIT_STATUS" ]] && [[ $BUILDKITE_LAST_HOOK_EXIT_STATUS -ne 0 ]]; then 142 buildkite-comment "Hook returned an exit status of $BUILDKITE_LAST_HOOK_EXIT_STATUS, exiting..." 143 exit $BUILDKITE_LAST_HOOK_EXIT_STATUS 144 fi 145 } 146 147 function buildkite-global-hook { 148 buildkite-hook "global $1" "$BUILDKITE_HOOKS_PATH/$1" 149 buildkite-hook-exit-on-error 150 } 151 152 function buildkite-local-hook { 153 if [[ -e ".buildkite/hooks/$1" ]] && [[ "${BUILDKITE_NO_LOCAL_HOOKS:-}" == "true" ]]; then 154 buildkite-error "Attempted to run .buildkite/hooks/$1, but BUILDKITE_NO_LOCAL_HOOKS is enabled" 155 fi 156 157 buildkite-hook "local $1" ".buildkite/hooks/$1" 158 buildkite-hook-exit-on-error 159 } 160 161 function buildkite-git-clean { 162 BUILDKITE_GIT_CLEAN_FLAGS=${BUILDKITE_GIT_CLEAN_FLAGS:--fdq} 163 buildkite-run git clean "$BUILDKITE_GIT_CLEAN_FLAGS" 164 165 if [[ -z "${BUILDKITE_DISABLE_GIT_SUBMODULES:-}" ]]; then 166 buildkite-run git submodule foreach --recursive git clean "$BUILDKITE_GIT_CLEAN_FLAGS" 167 fi 168 } 169 170 ############################################################## 171 # 172 # PATH DEFAULTS 173 # Come up with the paths used throughout the bootstrap.sh file 174 # 175 ############################################################## 176 177 # Add the $BUILDKITE_BIN_PATH to the $PATH 178 export PATH="$PATH:$BUILDKITE_BIN_PATH" 179 180 # Come up with the place that the repository will be checked out to 181 SANITIZED_AGENT_NAME=$(echo "$BUILDKITE_AGENT_NAME" | tr -d '"') 182 PROJECT_FOLDER_NAME="$SANITIZED_AGENT_NAME/$BUILDKITE_PROJECT_SLUG" 183 export BUILDKITE_BUILD_CHECKOUT_PATH="$BUILDKITE_BUILD_PATH/$PROJECT_FOLDER_NAME" 184 185 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 186 echo "~~~ Build environment variables" 187 env | grep -e "^BUILDKITE" | sort 188 fi 189 190 ############################################################## 191 # 192 # ENVIRONMENT SETUP 193 # A place for people to set up environment variables that 194 # might be needed for their build scripts, such as secret 195 # tokens and other information. 196 # 197 ############################################################## 198 199 buildkite-global-hook "environment" 200 201 ############################################################## 202 # 203 # REPOSITORY HANDLING 204 # Creates the build folder and makes sure we're running the 205 # build at the right commit. 206 # 207 ############################################################## 208 209 # Run the `pre-checkout` hook 210 buildkite-global-hook "pre-checkout" 211 212 # Remove the checkout folder if BUILDKITE_CLEAN_CHECKOUT is present 213 if [[ ! -z "${BUILDKITE_CLEAN_CHECKOUT:-}" ]] && [[ "$BUILDKITE_CLEAN_CHECKOUT" == "true" ]]; then 214 echo "~~~ Cleaning project checkout" 215 216 buildkite-run rm -rf "$BUILDKITE_BUILD_CHECKOUT_PATH" 217 fi 218 219 echo "~~~ Preparing build folder" 220 221 buildkite-run mkdir -p "$BUILDKITE_BUILD_CHECKOUT_PATH" 222 buildkite-run cd "$BUILDKITE_BUILD_CHECKOUT_PATH" 223 224 # If the user has specificed their own checkout hook 225 if [[ -e "$BUILDKITE_HOOKS_PATH/checkout" ]]; then 226 buildkite-global-hook "checkout" 227 else 228 # If enabled, automatically run an ssh-keyscan on the git ssh host, to prevent 229 # a yes/no promp from appearing when cloning/fetching 230 if [[ "${BUILDKITE_AUTO_SSH_FINGERPRINT_VERIFICATION:-false}" == "true" ]]; then 231 # Only bother running the keyscan if the SSH host has been provided by 232 # Buildkite. It won't be present if the host isn't using the SSH protocol 233 if [[ ! -z "${BUILDKITE_REPO_SSH_HOST:-}" ]]; then 234 : "${BUILDKITE_SSH_DIRECTORY:="$HOME/.ssh"}" 235 : "${BUILDKITE_SSH_KNOWN_HOST_PATH:="$BUILDKITE_SSH_DIRECTORY/known_hosts"}" 236 237 # Ensure the known_hosts file exists 238 mkdir -p "$BUILDKITE_SSH_DIRECTORY" 239 touch "$BUILDKITE_SSH_KNOWN_HOST_PATH" 240 241 # Only add the output from ssh-keyscan if it doesn't already exist in the 242 # known_hosts file (unhashed or hashed). 243 # 244 # Note: We can't rely on exit status. Older versions of ssh-keygen always 245 # exit successful. Only the presence of output is an indicator of whether 246 # the host key was found or not. 247 buildkite-prompt-debug ssh-keygen -f "$BUILDKITE_SSH_KNOWN_HOST_PATH" -F "$BUILDKITE_REPO_SSH_HOST" 248 if [ -z "$(ssh-keygen -f "$BUILDKITE_SSH_KNOWN_HOST_PATH" -F "$BUILDKITE_REPO_SSH_HOST")" ]; then 249 buildkite-prompt ssh-keyscan "$BUILDKITE_REPO_SSH_HOST" 250 ssh-keyscan "$BUILDKITE_REPO_SSH_HOST" >> "$BUILDKITE_SSH_KNOWN_HOST_PATH" || 251 buildkite-warning "Couldn't ssh key scan repository host $BUILDKITE_REPO_SSH_HOST into $BUILDKITE_SSH_KNOWN_HOST_PATH" 252 buildkite-debug-comment "Added \"$BUILDKITE_REPO_SSH_HOST\" to the list of known hosts at \"$BUILDKITE_SSH_KNOWN_HOST_PATH\"" 253 else 254 buildkite-debug-comment "Host \"$BUILDKITE_REPO_SSH_HOST\" already in list of known hosts at \"$BUILDKITE_SSH_KNOWN_HOST_PATH\"" 255 fi 256 else 257 buildkite-debug-comment "No repo host to scan for auto SSH fingerprint verification" 258 fi 259 else 260 buildkite-debug-comment "Skipping auto SSH fingerprint verification" 261 fi 262 263 # Disable any interactive Git/SSH prompting 264 export GIT_TERMINAL_PROMPT=0 265 266 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 267 buildkite-run git --version 268 fi 269 270 # Do we need to do a git checkout? 271 if [[ -d ".git" ]]; then 272 buildkite-run git remote set-url origin "$BUILDKITE_REPO" 273 else 274 BUILDKITE_GIT_CLONE_FLAGS=${BUILDKITE_GIT_CLONE_FLAGS:--v} 275 buildkite-run git clone "$BUILDKITE_GIT_CLONE_FLAGS" -- "$BUILDKITE_REPO" . 276 fi 277 278 # Git clean prior to checkout 279 buildkite-git-clean 280 281 # If a refspec is provided then use it instead. 282 # i.e. `refs/not/a/head` 283 if [[ -n "${BUILDKITE_REFSPEC:-}" ]]; then 284 buildkite-run git fetch -v origin "$BUILDKITE_REFSPEC" 285 buildkite-run git checkout -f "$BUILDKITE_COMMIT" 286 287 # GitHub has a special ref which lets us fetch a pull request head, whether 288 # or not there is a current head in this repository or another which 289 # references the commit. We presume a commit sha is provided. See: 290 # https://help.github.com/articles/checking-out-pull-requests-locally/#modifying-an-inactive-pull-request-locally 291 elif [[ "$BUILDKITE_PULL_REQUEST" != "false" ]] && [[ "$BUILDKITE_PROJECT_PROVIDER" == *"github"* ]]; then 292 buildkite-run git fetch -v origin "refs/pull/$BUILDKITE_PULL_REQUEST/head" 293 buildkite-comment "FETCH_HEAD is now $(git rev-parse FETCH_HEAD)" 294 buildkite-run git checkout -f "$BUILDKITE_COMMIT" 295 296 # If the commit is "HEAD" then we can't do a commit-specific fetch and will 297 # need to fetch the remote head and checkout the fetched head explicitly. 298 elif [[ "$BUILDKITE_COMMIT" == "HEAD" ]]; then 299 buildkite-run git fetch -v origin "$BUILDKITE_BRANCH" 300 buildkite-run git checkout -f FETCH_HEAD 301 302 # Otherwise fetch and checkout the commit directly. Some repositories don't 303 # support fetching a specific commit so we fall back to fetching all heads 304 # and tags, hoping that the commit is included. 305 else 306 # By default `git fetch origin` will only fetch tags which are reachable 307 # from a fetches branch. git 1.9.0+ changed `--tags` to fetch all tags in 308 # addition to the default refspec, but pre 1.9.0 it excludes the default 309 # refspec. 310 buildkite-prompt-and-run git fetch -v origin "$BUILDKITE_COMMIT" || 311 buildkite-run git fetch -v origin "$(git config remote.origin.fetch)" "+refs/tags/*:refs/tags/*" 312 buildkite-run git checkout -f "$BUILDKITE_COMMIT" 313 fi 314 315 if [[ -z "${BUILDKITE_DISABLE_GIT_SUBMODULES:-}" ]]; then 316 # `submodule sync` will ensure the .git/config matches the .gitmodules file. 317 # The command is only available in git version 1.8.1, so if the call fails, 318 # continue the bootstrap script, and show an informative error. 319 buildkite-prompt-and-run git submodule sync --recursive || { 320 buildkite-warning "Failed to recursively sync git submodules. This is most likely because you have an older version of git installed ($(git --version)) and you need version 1.8.1 and above. If you're using submodules, it's highly recommended you upgrade if you can." 321 buildkite-run git submodule sync 322 } 323 324 buildkite-prompt-and-run git submodule update --init --recursive --force || { 325 buildkite-warning "Failed to update git submodules forcibly. This is most likely because you have an older version of git installed ($(git --version)) and you need version 1.7.6 and above. If you're using submodules, it's highly recommended you upgrade if you can." 326 buildkite-run git submodule update --init --recursive 327 } 328 329 buildkite-run git submodule foreach --recursive git reset --hard 330 fi 331 332 # Git clean after checkout 333 buildkite-git-clean 334 335 # Grab author and commit information and send it back to Buildkite 336 buildkite-debug "~~~ Saving Git information" 337 338 # Check to see if the meta data exists before setting it 339 buildkite-debug-comment "Checking to see if Git data needs to be sent to Buildkite" 340 if ! buildkite-run-debug buildkite-agent meta-data exists "buildkite:git:commit"; then 341 buildkite-debug-comment "Sending Git commit information back to Buildkite" 342 buildkite-run-debug buildkite-agent meta-data set "buildkite:git:commit" "$(git show HEAD -s --format=fuller --no-color)" 343 buildkite-run-debug buildkite-agent meta-data set "buildkite:git:branch" "$(git branch --contains HEAD --no-color)" 344 fi 345 fi 346 347 # Store the current value of BUILDKITE_BUILD_CHECKOUT_PATH, so we can detect if 348 # one of the post-checkout hooks changed it. 349 PREVIOUS_BUILDKITE_BUILD_CHECKOUT_PATH=$BUILDKITE_BUILD_CHECKOUT_PATH 350 351 # Run the `post-checkout` hook 352 buildkite-global-hook "post-checkout" 353 354 # Now that we have a repo, we can perform a `post-checkout` local hook 355 buildkite-local-hook "post-checkout" 356 357 # If the working directory has been changed by a hook, log and switch to it 358 if [[ "$BUILDKITE_BUILD_CHECKOUT_PATH" != "$PREVIOUS_BUILDKITE_BUILD_CHECKOUT_PATH" ]]; then 359 echo "~~~ A post-checkout hook has changed the working directory to $BUILDKITE_BUILD_CHECKOUT_PATH" 360 361 if [ -d "$BUILDKITE_BUILD_CHECKOUT_PATH" ]; then 362 buildkite-run cd "$BUILDKITE_BUILD_CHECKOUT_PATH" 363 else 364 buildkite-error "Failed to switch to \"$BUILDKITE_BUILD_CHECKOUT_PATH\" as it doesn't exist" 365 fi 366 fi 367 368 ############################################################## 369 # 370 # RUN THE BUILD 371 # Determines how to run the build, and then runs it 372 # 373 ############################################################## 374 375 # Run the global `pre-command` hook 376 buildkite-global-hook "pre-command" 377 378 # Run the per-checkout `pre-command` hook 379 buildkite-local-hook "pre-command" 380 381 # If the user has specificed a local `command` hook 382 if [[ -e ".buildkite/hooks/command" ]]; then 383 if [[ "${BUILDKITE_NO_LOCAL_HOOKS:-}" == "true" ]]; then 384 buildkite-error "Attempted to run .buildkite/hooks/command, but BUILDKITE_NO_LOCAL_HOOKS is enabled" 385 fi 386 387 # Manually run the hook to avoid it from exiting on failure 388 buildkite-hook "local command" ".buildkite/hooks/command" 389 390 # Capture the exit status from the build script 391 export BUILDKITE_COMMAND_EXIT_STATUS=$BUILDKITE_LAST_HOOK_EXIT_STATUS 392 # Then check for a global hook path 393 elif [[ -e "$BUILDKITE_HOOKS_PATH/command" ]]; then 394 # Manually run the hook to avoid it from exiting on failure 395 buildkite-hook "global command" "$BUILDKITE_HOOKS_PATH/command" 396 397 # Capture the exit status from the build script 398 export BUILDKITE_COMMAND_EXIT_STATUS=$BUILDKITE_LAST_HOOK_EXIT_STATUS 399 else 400 # Make sure we actually have a command to run 401 if [[ -z "$BUILDKITE_COMMAND" ]]; then 402 buildkite-error "No command has been defined. Please go to \"Project Settings\" and configure your build step's \"Command\"" 403 fi 404 405 # Literal file paths are just executed as the command 406 # 407 # NOTE: There is a slight problem with this check - and it's with usage with 408 # Docker. If you specify a script to run inside the docker container, and that 409 # isn't on the file system at the same path, then it won't match, and it'll be 410 # treated as an eval. For example, you mount your repository at /app, and tell 411 # the agent run `app/ci.sh`, ci.sh won't exist on the filesytem at this point 412 # at app/ci.sh. The solution is to make sure the `WORKDIR` directroy of the 413 # docker container is at /app in that case. 414 if [[ -f "./$BUILDKITE_COMMAND" ]]; then 415 BUILDKITE_COMMAND_DESCRIPTION="Running command" 416 printf -v BUILDKITE_COMMAND_PROMPT "./%q" "$BUILDKITE_COMMAND" 417 BUILDKITE_COMMAND_PATH="$BUILDKITE_COMMAND" 418 419 # Otherwise we presume it is a shell script snippet 420 else 421 # Make sure the agent is even allowed to eval commands 422 if [[ "$BUILDKITE_COMMAND_EVAL" != "true" ]]; then 423 buildkite-error "This agent is not allowed to evaluate console commands. To allow this, re-run this agent without the \`--no-command-eval\` option, or specify a script within your repository to run instead (such as scripts/test.sh)." 424 fi 425 426 buildkite-debug "~~~ Preparing build script" 427 428 BUILDKITE_COMMAND_DESCRIPTION="Running build script" 429 BUILDKITE_COMMAND_PROMPT="$BUILDKITE_COMMAND" 430 BUILDKITE_COMMAND_PATH="buildkite-script-$BUILDKITE_JOB_ID" 431 432 # We'll actually run a temporary file with pipefail and exit-on-fail 433 # containing the full script body, printed literally through printf 434 printf "#!/bin/bash\nset -eo pipefail\n%s\n" "$BUILDKITE_COMMAND" > "$BUILDKITE_COMMAND_PATH" 435 436 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 437 buildkite-run cat "./$BUILDKITE_COMMAND_PATH" 438 fi 439 fi 440 441 # Make sure the command is executable 442 if [[ ! -x "./$BUILDKITE_COMMAND_PATH" ]]; then 443 buildkite-run-debug chmod +x "./$BUILDKITE_COMMAND_PATH" 444 fi 445 446 ## Docker 447 if [[ -n "${BUILDKITE_DOCKER:-}" ]]; then 448 DOCKER_CONTAINER="buildkite_${BUILDKITE_JOB_ID}_container" 449 DOCKER_IMAGE="buildkite_${BUILDKITE_JOB_ID}_image" 450 451 function docker-cleanup { 452 echo "~~~ Cleaning up Docker containers" 453 buildkite-prompt-and-run docker rm -f -v "$DOCKER_CONTAINER" 454 } 455 456 trap docker-cleanup EXIT 457 458 # Build the Docker image, namespaced to the job 459 echo "~~~ Building Docker image $DOCKER_IMAGE" 460 buildkite-run docker build -f "${BUILDKITE_DOCKER_FILE:-Dockerfile}" -t "$DOCKER_IMAGE" . 461 462 # Run the build script command in a one-off container 463 echo "~~~ $BUILDKITE_COMMAND_DESCRIPTION (in Docker container)" 464 buildkite-prompt-and-run docker run --name "$DOCKER_CONTAINER" "$DOCKER_IMAGE" "./$BUILDKITE_COMMAND_PATH" 465 466 # Capture the exit status from the build script 467 export BUILDKITE_COMMAND_EXIT_STATUS=$? 468 469 ## Docker Compose 470 elif [[ -n "${BUILDKITE_DOCKER_COMPOSE_CONTAINER:-}" ]]; then 471 # Compose strips dashes and underscores, so we'll remove them to match the docker container names 472 COMPOSE_PROJ_NAME="buildkite${BUILDKITE_JOB_ID//-}" 473 COMPOSE_COMMAND=(docker-compose) 474 IFS=":" read -ra COMPOSE_FILES <<< "${BUILDKITE_DOCKER_COMPOSE_FILE:-docker-compose.yml}" 475 for FILE in "${COMPOSE_FILES[@]}"; do 476 COMPOSE_COMMAND+=(-f "$FILE") 477 done 478 COMPOSE_COMMAND+=(-p "$COMPOSE_PROJ_NAME") 479 480 # Switch on verbose in debug mode 481 if [[ "$BUILDKITE_AGENT_DEBUG" == "true" ]]; then 482 COMPOSE_COMMAND+=(--verbose) 483 fi 484 485 function compose-cleanup { 486 if [[ "${BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES:-false}" == "true" ]]; then 487 REMOVE_VOLUME_FLAG="" 488 else 489 REMOVE_VOLUME_FLAG="-v" 490 fi 491 492 echo "~~~ Cleaning up Docker containers" 493 494 # Send them a friendly kill 495 buildkite-prompt-and-run "${COMPOSE_COMMAND[@]}" kill 496 497 if [[ "$(docker-compose --version)" == *version\ 1.6.* ]]; then 498 # 1.6 499 500 # There's no --all flag to remove adhoc containers 501 buildkite-prompt-and-run "${COMPOSE_COMMAND[@]}" rm --force "$REMOVE_VOLUME_FLAG" 502 503 # So now we remove the adhoc container 504 COMPOSE_CONTAINER_NAME="${COMPOSE_PROJ_NAME}_${BUILDKITE_DOCKER_COMPOSE_CONTAINER}" 505 buildkite-prompt-and-run docker rm -f "$REMOVE_VOLUME_FLAG" "${COMPOSE_CONTAINER_NAME}_run_1" 506 else 507 # 1.7+ 508 509 # `compose down` doesn't support force removing images, so we use `rm --force` 510 buildkite-prompt-and-run "${COMPOSE_COMMAND[@]}" rm --force --all "$REMOVE_VOLUME_FLAG" 511 512 # Stop and remove all the linked services and network 513 buildkite-prompt-and-run "${COMPOSE_COMMAND[@]}" down 514 fi 515 } 516 517 trap compose-cleanup EXIT 518 519 # Build the Docker images using Compose, namespaced to the job 520 echo "~~~ Building Docker images" 521 522 if [[ "${BUILDKITE_DOCKER_COMPOSE_BUILD_ALL:-false}" == "true" ]]; then 523 buildkite-run "${COMPOSE_COMMAND[@]}" build --pull 524 else 525 buildkite-run "${COMPOSE_COMMAND[@]}" build --pull "$BUILDKITE_DOCKER_COMPOSE_CONTAINER" 526 fi 527 528 # Run the build script command in the service specified in BUILDKITE_DOCKER_COMPOSE_CONTAINER 529 echo "~~~ $BUILDKITE_COMMAND_DESCRIPTION (in Docker Compose container)" 530 buildkite-prompt-and-run "${COMPOSE_COMMAND[@]}" run "$BUILDKITE_DOCKER_COMPOSE_CONTAINER" "./$BUILDKITE_COMMAND_PATH" 531 532 # Capture the exit status from the build script 533 export BUILDKITE_COMMAND_EXIT_STATUS=$? 534 535 ## Standard 536 else 537 echo "~~~ $BUILDKITE_COMMAND_DESCRIPTION" 538 echo -ne "$BUILDKITE_PROMPT " 539 echo "$BUILDKITE_COMMAND_PROMPT" 540 "./$BUILDKITE_COMMAND_PATH" 541 542 # Capture the exit status from the build script 543 export BUILDKITE_COMMAND_EXIT_STATUS=$? 544 545 # Reset the bootstrap.sh flags 546 buildkite-flags-reset 547 fi 548 fi 549 550 # Run the per-checkout `post-command` hook 551 buildkite-local-hook "post-command" 552 553 # Run the global `post-command` hook 554 buildkite-global-hook "post-command" 555 556 ############################################################## 557 # 558 # ARTIFACTS 559 # Uploads and build artifacts associated with this build 560 # 561 ############################################################## 562 563 if [[ -n "$BUILDKITE_ARTIFACT_PATHS" ]]; then 564 # Run the per-checkout `pre-artifact` hook 565 buildkite-local-hook "pre-artifact" 566 567 # Run the global `pre-artifact` hook 568 buildkite-global-hook "pre-artifact" 569 570 echo "~~~ Uploading artifacts" 571 if [[ -n "${BUILDKITE_ARTIFACT_UPLOAD_DESTINATION:-}" ]]; then 572 buildkite-prompt-and-run buildkite-agent artifact upload "$BUILDKITE_ARTIFACT_PATHS" "$BUILDKITE_ARTIFACT_UPLOAD_DESTINATION" 573 else 574 buildkite-prompt-and-run buildkite-agent artifact upload "$BUILDKITE_ARTIFACT_PATHS" 575 fi 576 577 # If the artifact upload fails, open the current group and exit with an error 578 if [[ $? -ne 0 ]]; then 579 buildkite-error "Unable to upload artifacts" 580 fi 581 582 # Run the per-checkout `post-artifact` hook 583 buildkite-local-hook "post-artifact" 584 585 # Run the global `post-artifact` hook 586 buildkite-global-hook "post-artifact" 587 fi 588 589 # Run the per-checkout `pre-exit` hook 590 buildkite-local-hook "pre-exit" 591 592 # Run the global `pre-exit` hook 593 buildkite-global-hook "pre-exit" 594 595 # Be sure to exit this script with the same exit status that the users build 596 # script exited with. 597 exit $BUILDKITE_COMMAND_EXIT_STATUS