├── hooks ├── post-command └── command ├── docker-compose.yml ├── .editorconfig ├── tests ├── post-command.bats └── command.bats ├── plugin.yml ├── .github └── workflows │ └── test.yml ├── LICENSE └── README.md /hooks/post-command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ue 4 | 5 | echo "~~~ :heroku: Logging out of Heroku Docker Registry" 6 | docker logout registry.heroku.com 7 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | lint: 3 | image: buildkite/plugin-linter 4 | command: ["--id", "envato/heroku-container-deploy"] 5 | volumes: 6 | - ".:/plugin:ro" 7 | 8 | tests: 9 | image: buildkite/plugin-tester 10 | volumes: 11 | - ".:/plugin:ro" 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [COMMIT_EDITMSG] 16 | max_line_length = 80 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /tests/post-command.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load '/usr/local/lib/bats/load.bash' 4 | 5 | # Uncomment the following line to debug stub failures 6 | # export DOCKER_STUB_DEBUG=/dev/tty 7 | # export CURL_STUB_DEBUG=/dev/tty 8 | 9 | @test "Docker logout" { 10 | stub docker \ 11 | "logout registry.heroku.com : exit 0" 12 | 13 | run "$PWD/hooks/post-command" 14 | 15 | assert_success 16 | 17 | unstub docker 18 | } 19 | 20 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: Heroku Container Deploy 2 | description: Deploys prebuilt container images to Heroku 3 | author: https://github.com/envato/heroku-container-deploy-buildkite-plugin 4 | requirements: 5 | - docker 6 | - curl 7 | - jq 8 | configuration: 9 | properties: 10 | app: 11 | type: string 12 | key-name: 13 | type: string 14 | process-types: 15 | type: [string, array] 16 | minimum: 1 17 | process-type-images: 18 | type: [string, array] 19 | minimum: 1 20 | releasing: 21 | type: [string, array] 22 | additionalProperties: false 23 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: tests 3 | on: [push] 4 | jobs: 5 | plugin-tests: 6 | name: Tests 7 | runs-on: ubuntu-latest 8 | container: 9 | image: buildkite/plugin-tester:latest 10 | volumes: 11 | - "${{github.workspace}}:/plugin" 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: tests 15 | run: bats tests/ 16 | plugin-lint: 17 | name: Lint 18 | runs-on: ubuntu-latest 19 | container: 20 | image: buildkite/plugin-linter:latest 21 | volumes: 22 | - "${{github.workspace}}:/plugin" 23 | steps: 24 | - uses: actions/checkout@v2 25 | - name: lint 26 | run: lint --id envato/heroku-container-deploy 27 | plugin-shellcheck: 28 | name: Shellcheck 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v2 32 | - name: Run ShellCheck 33 | uses: ludeeus/action-shellcheck@master 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Envato 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Heroku Container Deploy 2 | 3 | Deploy pre-built docker images, typically with [docker-compose-buildkite-plugin](https://github.com/buildkite-plugins/docker-compose-buildkite-plugin), to using the Heroku Container Registry. It follows the official recommended steps [for Docker deploys on Heroku](https://devcenter.heroku.com/articles/container-registry-and-runtime). See [ecr-buildkite-plugin](https://github.com/buildkite-plugins/ecr-buildkite-plugin) for authenticating with AWS ECR. 4 | 5 | ## Design Decision 6 | 7 | [Heroku API](https://devcenter.heroku.com/articles/container-registry-and-runtime#api) is favoured over depending on the Heroku CLI. This helps to avoid problems with transitive npm dependencies causing CI blockage at scale. 8 | 9 | ## Example 10 | 11 | Deploy a pre-built images from ECR to heroku container registry. 12 | 13 | ```yml 14 | steps: 15 | - label: ":heroku: Deploy my-app app (web)" 16 | plugins: 17 | - envato/heroku-container-deploy#v1.3.0: 18 | app: my-app 19 | process-type-images: 20 | - web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web-${BUILDKITE_COMMIT} 21 | ``` 22 | 23 | Deploy multiple pre-built images from ECR to heroku container registry. 24 | 25 | ```yml 26 | steps: 27 | - label: ":heroku: Deploy my-app app (web and worker)" 28 | plugins: 29 | - envato/heroku-container-deploy#v1.3.0: 30 | app: my-app 31 | process-type-images: 32 | - web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web-${BUILDKITE_COMMIT} 33 | - worker:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker-${BUILDKITE_COMMIT} 34 | ``` 35 | 36 | Deploy multiple pre-built images including a [Release Phase](https://devcenter.heroku.com/articles/container-registry-and-runtime#release-phase) from ECR to heroku container registry. Plugin will stream the release output to Buildkite logs. 37 | 38 | ```yml 39 | steps: 40 | - label: ":heroku: Deploy my-app app (web, worker and release)" 41 | plugins: 42 | - envato/heroku-container-deploy#v1.3.0: 43 | app: my-app 44 | process-type-images: 45 | - web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web-${BUILDKITE_COMMIT} 46 | - worker:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker-${BUILDKITE_COMMIT} 47 | - release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release-${BUILDKITE_COMMIT} 48 | ``` 49 | 50 | ## Configuration 51 | 52 | ### `app` (Required, string) 53 | 54 | Heroku app name 55 | 56 | ### `key-name` (Optional, string) 57 | 58 | The name of the environment variable that contains the Heroku API key. Defaults to `HEROKU_API_KEY` 59 | 60 | ### `process-type-images` (Required, Array of string) 61 | 62 | List of process types and their image repository to deploy. 63 | 64 | ``` 65 | :: 66 | ``` 67 | 68 | ### `releasing` (Optional, Array of string) 69 | 70 | List of process type names to be released. It will allays pull, tag and push all images, but it will only patch the Heroku Formation API with these images. 71 | 72 | Default: All process types in `process-type-images` except one named `migrations` 73 | 74 | ## Developing 75 | 76 | Testing 77 | 78 | ```shell 79 | docker-compose run --rm tests 80 | ``` 81 | 82 | Linting 83 | 84 | ```shell 85 | docker-compose run --rm lint 86 | ``` 87 | -------------------------------------------------------------------------------- /hooks/command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ue 4 | 5 | retry_sleep=${RETRY_SLEEP:-2} 6 | 7 | 8 | function join_by { local IFS="$1"; shift; echo "$*"; } 9 | 10 | function plugin_read_list() { 11 | prefix_read_list "BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_$1" 12 | } 13 | 14 | function prefix_read_list() { 15 | local prefix="$1" 16 | local parameter="${prefix}_0" 17 | 18 | if [[ -n "${!parameter:-}" ]]; then 19 | local i=0 20 | local parameter="${prefix}_${i}" 21 | while [[ -n "${!parameter:-}" ]]; do 22 | echo "${!parameter}" 23 | i=$((i+1)) 24 | parameter="${prefix}_${i}" 25 | done 26 | elif [[ -n "${!prefix:-}" ]]; then 27 | echo "${!prefix}" 28 | fi 29 | } 30 | 31 | retry() { 32 | local retries=$1 33 | shift 34 | 35 | local count=0 36 | until "$@"; do 37 | exit=$? 38 | wait=$((retry_sleep ** count)) 39 | count=$((count + 1)) 40 | if [ $count -lt "$retries" ]; then 41 | echo "Retry $count/$retries exited $exit, retrying in $wait seconds..." 42 | sleep $wait 43 | else 44 | echo "Retry $count/$retries exited $exit, no more retries left." 45 | return $exit 46 | fi 47 | done 48 | return 0 49 | } 50 | 51 | heroku_registry_host="registry.heroku.com" 52 | 53 | function get_proc_type_image_tag() { 54 | echo "$heroku_registry_host/$app/$1:latest" 55 | } 56 | 57 | key_name=$(plugin_read_list KEY_NAME) 58 | key_name="${key_name:-HEROKU_API_KEY}" 59 | heroku_api_key=$(printf '%s\n' "${!key_name-}") 60 | 61 | if [ -z "${heroku_api_key}" ]; then 62 | echo "Missing heroku api key. Required HEROKU_API_KEY or \"key-name\"" 63 | exit 1 64 | fi 65 | 66 | app=$(plugin_read_list APP) 67 | 68 | process_type_images=() 69 | 70 | if [[ -n "$(plugin_read_list PROCESS_TYPE_IMAGES)" ]]; then 71 | for process_type_image in $(plugin_read_list PROCESS_TYPE_IMAGES); do 72 | process_type_images+=("$process_type_image") 73 | done 74 | fi 75 | 76 | if [ ${#process_type_images[@]} -eq 0 ]; then 77 | # Deprecated process-types in favour of process-type-images 78 | for process_type_image in $(plugin_read_list PROCESS_TYPES); do 79 | process_type_images+=("$process_type_image") 80 | done 81 | echo "Deprecated Warning: Please use process-type-images instead" 82 | fi 83 | 84 | releasing=() 85 | 86 | if [[ -n "$(plugin_read_list RELEASING)" ]]; then 87 | for image_name in $(plugin_read_list RELEASING); do 88 | releasing+=("$image_name") 89 | done 90 | fi 91 | 92 | # Defaults to releasing all proc types 93 | if [ ${#releasing[@]} -eq 0 ]; then 94 | for line in "${process_type_images[@]}"; do 95 | IFS=':' read -r -a tokens <<< "$line" 96 | # Exclude an image called migrations by default 97 | if [ "${tokens[0]}" != "migrations" ]; then 98 | releasing+=("${tokens[0]}") 99 | fi 100 | done 101 | fi 102 | 103 | ## 104 | ## Log in to the heroku registry early, in case the images are already there 105 | ## 106 | 107 | echo "~~~ :heroku: Logging into Heroku Docker Registry" 108 | echo "$heroku_api_key" | docker login --username=_ --password-stdin registry.heroku.com 109 | 110 | ## 111 | ## Pulling from owner container registry 112 | ## 113 | 114 | for line in "${process_type_images[@]}"; do 115 | IFS=':' read -r -a tokens <<< "$line" 116 | proc_type=${tokens[0]} 117 | proc_type_image=$(IFS=':'; echo "${tokens[*]:1}") 118 | proc_type_image_id=$(docker images -q "$proc_type_image") 119 | 120 | emoji=":docker:" 121 | if [[ "$proc_type_image" =~ $heroku_registry_host ]]; then 122 | emoji=":heroku:" 123 | fi 124 | 125 | echo "~~~ $emoji Pulling $proc_type image" 126 | if [ -z "${proc_type_image_id}" ]; then 127 | status=0 128 | if ! retry 3 docker pull "$proc_type_image"; then 129 | status=$((status + 1)) 130 | fi 131 | if [ $status -eq 0 ]; then 132 | echo "Pulled $proc_type_image" 133 | else 134 | echo "Failed pull $proc_type_image" 135 | exit 1 136 | fi 137 | else 138 | echo "Found $proc_type_image" 139 | fi 140 | done 141 | 142 | ## 143 | ## Tagging for heroku container registry 144 | ## 145 | 146 | for line in "${process_type_images[@]}"; do 147 | IFS=':' read -r -a tokens <<< "$line" 148 | proc_type=${tokens[0]} 149 | proc_type_image=$(IFS=':'; echo "${tokens[*]:1}") 150 | proc_type_tag=$(get_proc_type_image_tag "$proc_type") 151 | 152 | echo "~~~ :heroku: Tagging $app/${proc_type} image" 153 | docker tag "$proc_type_image" "$proc_type_tag" 154 | echo "Tagged $proc_type_image as $proc_type_tag" 155 | done 156 | 157 | ## 158 | ## Pushing to heroku container registry 159 | ## 160 | 161 | for line in "${process_type_images[@]}"; do 162 | IFS=':' read -r -a tokens <<< "$line" 163 | proc_type=${tokens[0]} 164 | proc_type_image=$(IFS=':'; echo "${tokens[*]:1}") 165 | proc_type_tag=$(get_proc_type_image_tag "$proc_type") 166 | 167 | echo "~~~ :heroku: Pushing $app/$proc_type image" 168 | status=0 169 | if ! retry 3 docker push "$proc_type_tag"; then 170 | status=$((status + 1)) 171 | fi 172 | if [ $status -eq 0 ]; then 173 | echo "Pushed $proc_type_tag" 174 | else 175 | echo "Failed push $proc_type_tag" 176 | exit 1 177 | fi 178 | done 179 | 180 | ## 181 | ## Releasing to heroku platform 182 | ## 183 | 184 | echo "+++ :heroku: Releasing ${releasing[*]} for $app" 185 | 186 | updates=() 187 | 188 | for line in "${process_type_images[@]}"; do 189 | IFS=':' read -r -a tokens <<< "$line" 190 | proc_type=${tokens[0]} 191 | proc_type_image=$(IFS=':'; echo "${tokens[*]:1}") 192 | proc_type_tag=$(get_proc_type_image_tag "$proc_type") 193 | 194 | # Based on https://devcenter.heroku.com/articles/container-registry-and-runtime#getting-a-docker-image-id 195 | image_id=$(docker inspect "$proc_type_tag" --format=\{\{.Id\}\}) 196 | 197 | # shellcheck disable=SC2076 198 | if [[ " ${releasing[*]} " =~ " ${proc_type} " ]]; then 199 | echo "Inspected $proc_type_tag identified as $image_id" 200 | updates+=("{\"type\":\"${proc_type}\",\"docker_image\":\"$image_id\"}") 201 | else 202 | echo "Skipping inspected $proc_type_tag identified as $image_id" 203 | fi 204 | done 205 | 206 | if [ ${#updates[@]} -eq 0 ]; then 207 | echo "There aren't images to release" 208 | exit 0 209 | fi 210 | 211 | payload=$(join_by , "${updates[@]}") 212 | 213 | echo "Updating formation" 214 | 215 | # Run the equivalant Heroku API as with the cli `heroku container:release` 216 | # Based on https://devcenter.heroku.com/articles/container-registry-and-runtime#api 217 | curl -sf -X PATCH "https://api.heroku.com/apps/$app/formation" \ 218 | -d "{\"updates\":[$payload]}" \ 219 | -H "Content-Type: application/json" \ 220 | -H "Accept: application/vnd.heroku+json; version=3.docker-releases" \ 221 | -H "Authorization: Bearer ${heroku_api_key:-}" \ 222 | -o /dev/null 223 | 224 | version="" 225 | 226 | function check_release() { 227 | local count=0 228 | local streamed=0 229 | local max_polling_retries=30 230 | while true; 231 | do 232 | count=$((count + 1)) 233 | 234 | # Get the most recent release data from the Heroku API 235 | # Based on https://github.com/heroku/cli/blob/960d10a4816d8d1215fb8e4b7bf5499a6c0c76c7/packages/container-registry-v5/commands/release.js#L86-L90 236 | local latest_release; latest_release=$(curl -sf "https://api.heroku.com/apps/$app/releases" \ 237 | -H "Content-Type: application/json" \ 238 | -H "Accept: application/vnd.heroku+json; version=3" \ 239 | -H "Range: version ..; max=1, order=desc" \ 240 | -H "Authorization: Bearer ${heroku_api_key:-}") 241 | 242 | version=$(echo "$latest_release" | jq -r '.[0].version') 243 | local current; current=$(echo "$latest_release" | jq -r '.[0].current') 244 | local status; status=$(echo "$latest_release" | jq -r '.[0].status') 245 | local output_stream_url; output_stream_url=$(echo "$latest_release" | jq -r '.[0].output_stream_url') 246 | local release_id; release_id=$(echo "$latest_release" | jq -r '.[0].id') 247 | local summary; summary="[heroku version=$version, current=$current, status=$status]" 248 | 249 | if [ $streamed -eq 0 ] && [ "$status" == "pending" ] && [ "$output_stream_url" != "null" ]; then 250 | # Prints the output stream to the current logs 251 | # Based on https://github.com/heroku/cli/blob/960d10a4816d8d1215fb8e4b7bf5499a6c0c76c7/packages/container-registry-v5/commands/release.js#L99-L100 252 | streamed=1 253 | echo "$summary releasing..." 254 | status=0 255 | # Retry necessary because this will 404 until it's eventually consistent 256 | # Based on https://github.com/heroku/cli/blob/960d10a4816d8d1215fb8e4b7bf5499a6c0c76c7/packages/container-registry-v5/lib/streamer.js#L15 257 | if ! retry 3 curl -sf "$output_stream_url" -H "Accept: text/event-stream" | grep -e "^data:"; then 258 | status=$((status + 1)) 259 | fi 260 | if [ $status -eq 0 ]; then 261 | continue; 262 | else 263 | echo "Continuing without streaming release output, url: $output_stream_url" 264 | echo "--> You can view the release logs in the heroku dashboard." 265 | echo "--> https://dashboard.heroku.com/apps/$app/activity/releases/$release_id" 266 | max_polling_retries=60 267 | fi 268 | fi 269 | 270 | if [ "$status" == "succeeded" ] && [ "$current" == "true" ]; then 271 | echo "$summary success" 272 | break; 273 | fi 274 | 275 | if [ "$status" == "failed" ]; then 276 | echo "$summary failure" 277 | exit 1 278 | fi 279 | 280 | if [ $count -gt $max_polling_retries ]; then 281 | echo "$summary timeout" 282 | exit 1 283 | fi 284 | 285 | echo "$summary waiting..." 286 | sleep "$retry_sleep"; 287 | done 288 | } 289 | 290 | check_release 291 | 292 | echo "Version $version is current." 293 | -------------------------------------------------------------------------------- /tests/command.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load '/usr/local/lib/bats/load.bash' 4 | 5 | # Uncomment the following line to debug stub failures 6 | # export DOCKER_STUB_DEBUG=/dev/tty 7 | # export CURL_STUB_DEBUG=/dev/tty 8 | 9 | @test "By process type pulls, tags and pushes to heroku" { 10 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 11 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 12 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 13 | export HEROKU_API_KEY=api-token 14 | 15 | stub docker \ 16 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 17 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 18 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 19 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 20 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 21 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 22 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 23 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 24 | "push registry.heroku.com/my-app/release:latest : exit 0" \ 25 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" \ 26 | "inspect registry.heroku.com/my-app/release:latest --format={{.Id}} : echo release_id" 27 | 28 | stub curl \ 29 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\,\{\"type\"\:\"release\"\,\"docker_image\"\:\"release_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 30 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 31 | 32 | run "$PWD/hooks/command" 33 | 34 | assert_success 35 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 36 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 37 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 38 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 39 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 40 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 41 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 42 | assert_output --partial "Pushed registry.heroku.com/my-app/release:latest" 43 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 44 | assert_output --partial "Inspected registry.heroku.com/my-app/release:latest identified as release_id" 45 | assert_output --partial "Version 100 is current" 46 | 47 | unstub docker 48 | unstub curl 49 | } 50 | 51 | @test "By process type finds, tags and pushes to heroku" { 52 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 53 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 54 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 55 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_KEY_NAME=MY_HEROKU_KEY 56 | export HEROKU_API_KEY=irrelevant 57 | export MY_HEROKU_KEY=api-token 58 | 59 | stub docker \ 60 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 61 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : echo web" \ 62 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : echo release" \ 63 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 64 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 65 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 66 | "push registry.heroku.com/my-app/release:latest : exit 0" \ 67 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" \ 68 | "inspect registry.heroku.com/my-app/release:latest --format={{.Id}} : echo release_id" 69 | 70 | stub curl \ 71 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\,\{\"type\"\:\"release\"\,\"docker_image\"\:\"release_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 72 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 73 | 74 | run "$PWD/hooks/command" 75 | 76 | assert_success 77 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 78 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 79 | refute_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 80 | refute_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 81 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 82 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 83 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 84 | assert_output --partial "Pushed registry.heroku.com/my-app/release:latest" 85 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 86 | assert_output --partial "Inspected registry.heroku.com/my-app/release:latest identified as release_id" 87 | assert_output --partial "Version 100 is current" 88 | 89 | unstub docker 90 | unstub curl 91 | } 92 | 93 | @test "Single process type pulls, tags and pushes to heroku" { 94 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 95 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 96 | export HEROKU_API_KEY=api-token 97 | 98 | stub docker \ 99 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 100 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : echo web" \ 101 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 102 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 103 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" 104 | 105 | stub curl \ 106 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 107 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 108 | 109 | run "$PWD/hooks/command" 110 | 111 | assert_success 112 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 113 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 114 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 115 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 116 | assert_output --partial "Version 100 is current" 117 | 118 | unstub docker 119 | unstub curl 120 | } 121 | 122 | @test "Supports deprecated process type attributes" { 123 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPES="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 124 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 125 | export HEROKU_API_KEY=api-token 126 | 127 | stub docker \ 128 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 129 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : echo web" \ 130 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 131 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 132 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" 133 | 134 | stub curl \ 135 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 136 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 137 | 138 | run "$PWD/hooks/command" 139 | 140 | assert_success 141 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 142 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 143 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 144 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 145 | assert_output --partial "Version 100 is current" 146 | 147 | unstub docker 148 | unstub curl 149 | } 150 | 151 | @test "Supports skipping formation patch per proc type" { 152 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 153 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="worker:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker" 154 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_2="migrations:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 155 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_RELEASING_0=web 156 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_RELEASING_1=worker 157 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 158 | export HEROKU_API_KEY=api-token 159 | 160 | stub docker \ 161 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 162 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 163 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 164 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker : exit 0" \ 165 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker : exit 0" \ 166 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations : exit 0" \ 167 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations : exit 0" \ 168 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 169 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker registry.heroku.com/my-app/worker:latest : exit 0" \ 170 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations registry.heroku.com/my-app/migrations:latest : exit 0" \ 171 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 172 | "push registry.heroku.com/my-app/worker:latest : exit 0" \ 173 | "push registry.heroku.com/my-app/migrations:latest : exit 0" \ 174 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" \ 175 | "inspect registry.heroku.com/my-app/worker:latest --format={{.Id}} : echo worker_id" \ 176 | "inspect registry.heroku.com/my-app/migrations:latest --format={{.Id}} : echo migrations_id" 177 | 178 | stub curl \ 179 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\},\{\"type\"\:\"worker\"\,\"docker_image\"\:\"worker_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 180 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 181 | 182 | run "$PWD/hooks/command" 183 | 184 | assert_success 185 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 186 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker" 187 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 188 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 189 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker" 190 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 191 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 192 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-worker as registry.heroku.com/my-app/worker:latest" 193 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations as registry.heroku.com/my-app/migrations:latest" 194 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 195 | assert_output --partial "Pushed registry.heroku.com/my-app/worker:latest" 196 | assert_output --partial "Pushed registry.heroku.com/my-app/migrations:latest" 197 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 198 | assert_output --partial "Inspected registry.heroku.com/my-app/worker:latest identified as worker_id" 199 | assert_output --partial "Skipping inspected registry.heroku.com/my-app/migrations:latest identified as migrations_id" 200 | assert_output --partial "Version 100 is current" 201 | 202 | unstub docker 203 | unstub curl 204 | } 205 | 206 | @test "Exits gracefully if all proc types are skipped" { 207 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES="migrations:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 208 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_RELEASING=web 209 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 210 | export HEROKU_API_KEY=api-token 211 | 212 | stub docker \ 213 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 214 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations : echo migrations" \ 215 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations registry.heroku.com/my-app/migrations:latest : exit 0" \ 216 | "push registry.heroku.com/my-app/migrations:latest : exit 0" \ 217 | "inspect registry.heroku.com/my-app/migrations:latest --format={{.Id}} : echo migrations_id" 218 | 219 | run "$PWD/hooks/command" 220 | 221 | assert_success 222 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 223 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations as registry.heroku.com/my-app/migrations:latest" 224 | assert_output --partial "Pushed registry.heroku.com/my-app/migrations:latest" 225 | assert_output --partial "Skipping inspected registry.heroku.com/my-app/migrations:latest identified as migrations_id" 226 | assert_output --partial "There aren't images to release" 227 | refute_output --partial "Version 100 is current" 228 | 229 | unstub docker 230 | } 231 | 232 | @test "Skips formation patch for migrations proc type by default" { 233 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 234 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="migrations:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 235 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 236 | export HEROKU_API_KEY=api-token 237 | 238 | stub docker \ 239 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 240 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 241 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 242 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations : exit 0" \ 243 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations : exit 0" \ 244 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 245 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations registry.heroku.com/my-app/migrations:latest : exit 0" \ 246 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 247 | "push registry.heroku.com/my-app/migrations:latest : exit 0" \ 248 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" \ 249 | "inspect registry.heroku.com/my-app/migrations:latest --format={{.Id}} : echo migrations_id" 250 | 251 | stub curl \ 252 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 253 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 254 | 255 | run "$PWD/hooks/command" 256 | 257 | assert_success 258 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 259 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 260 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 261 | refute_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations" 262 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 263 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-migrations as registry.heroku.com/my-app/migrations:latest" 264 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 265 | assert_output --partial "Pushed registry.heroku.com/my-app/migrations:latest" 266 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 267 | assert_output --partial "Skipping inspected registry.heroku.com/my-app/migrations:latest identified as migrations_id" 268 | assert_output --partial "Version 100 is current" 269 | 270 | unstub docker 271 | unstub curl 272 | } 273 | 274 | @test "Polls heroku releases, until success" { 275 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 276 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 277 | export HEROKU_API_KEY=api-token 278 | export RETRY_SLEEP=0 279 | 280 | stub docker \ 281 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 282 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : echo web" \ 283 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 284 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 285 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" 286 | 287 | stub curl \ 288 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 289 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false\}\]' \ 290 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false\}\]' \ 291 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true\}\]' 292 | 293 | run "$PWD/hooks/command" 294 | 295 | assert_success 296 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 297 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 298 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 299 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 300 | assert_output --partial "Version 100 is current" 301 | 302 | unstub docker 303 | unstub curl 304 | } 305 | 306 | @test "Polls heroku releases, until fail" { 307 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 308 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 309 | export HEROKU_API_KEY=api-token 310 | export RETRY_SLEEP=0 311 | 312 | stub docker \ 313 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 314 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : echo web" \ 315 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 316 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 317 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" 318 | 319 | stub curl \ 320 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 321 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false\}\]' \ 322 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false\}\]' \ 323 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"failed\",\"current\":false\}\]' 324 | 325 | run "$PWD/hooks/command" 326 | 327 | assert_failure 328 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 329 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 330 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 331 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 332 | refute_output --partial "Version 100 is current" 333 | 334 | unstub docker 335 | unstub curl 336 | } 337 | 338 | @test "Stream heroku release output" { 339 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 340 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 341 | export HEROKU_API_KEY=api-token 342 | export RETRY_SLEEP=0 343 | 344 | stub docker \ 345 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 346 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : echo release" \ 347 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 348 | "push registry.heroku.com/my-app/release:latest : exit 0" \ 349 | "inspect registry.heroku.com/my-app/release:latest --format={{.Id}} : echo release_id" 350 | 351 | stub curl \ 352 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"release\"\,\"docker_image\"\:\"release_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 353 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false,\"output_stream_url\":\"release_output_stream_url\"\}\]' \ 354 | '-sf release_output_stream_url -H "Accept: text/event-stream" : echo "id: 1" && echo "data: Release Output"' \ 355 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false,\"output_stream_url\":\"release_output_stream_url\"\}\]' \ 356 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true,\"output_stream_url\":\"release_output_stream_url\"\}\]' 357 | 358 | run "$PWD/hooks/command" 359 | 360 | assert_success 361 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 362 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 363 | assert_output --partial "Pushed registry.heroku.com/my-app/release:latest" 364 | assert_output --partial "Inspected registry.heroku.com/my-app/release:latest identified as release_id" 365 | assert_output --partial "data: Release Output" 366 | refute_output --partial "Continuing without streaming release output" 367 | assert_output --partial "Version 100 is current" 368 | 369 | unstub docker 370 | unstub curl 371 | } 372 | 373 | @test "Continue polling when stream heroku release output fails" { 374 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 375 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 376 | export HEROKU_API_KEY=api-token 377 | export RETRY_SLEEP=0 378 | 379 | stub docker \ 380 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 381 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : echo release" \ 382 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 383 | "push registry.heroku.com/my-app/release:latest : exit 0" \ 384 | "inspect registry.heroku.com/my-app/release:latest --format={{.Id}} : echo release_id" 385 | 386 | stub curl \ 387 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"release\"\,\"docker_image\"\:\"release_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 0' \ 388 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false,\"output_stream_url\":\"release_output_stream_url\"\}\]' \ 389 | '-sf release_output_stream_url -H "Accept: text/event-stream" : exit 1' \ 390 | '-sf release_output_stream_url -H "Accept: text/event-stream" : exit 1' \ 391 | '-sf release_output_stream_url -H "Accept: text/event-stream" : exit 1' \ 392 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"pending\",\"current\":false,\"output_stream_url\":\"release_output_stream_url\"\}\]' \ 393 | '-sf https://api.heroku.com/apps/my-app/releases -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Range: version ..; max=1, order=desc" -H "Authorization: Bearer api-token" : echo \[\{\"id\"\:\"app_id\",\"version\":100,\"status\"\:\"succeeded\",\"current\":true,\"output_stream_url\":\"release_output_stream_url\"\}\]' 394 | 395 | run "$PWD/hooks/command" 396 | 397 | assert_success 398 | assert_output --partial "Found XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 399 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 400 | assert_output --partial "Pushed registry.heroku.com/my-app/release:latest" 401 | assert_output --partial "Inspected registry.heroku.com/my-app/release:latest identified as release_id" 402 | assert_output --partial "Continuing without streaming release output" 403 | assert_output --partial "Version 100 is current" 404 | 405 | unstub docker 406 | unstub curl 407 | } 408 | 409 | @test "Fails when an image pull fails" { 410 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 411 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 412 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 413 | export HEROKU_API_KEY=api-token 414 | export RETRY_SLEEP=0 415 | 416 | stub docker \ 417 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 418 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 419 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 420 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 421 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 1" \ 422 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 1" \ 423 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 1" 424 | 425 | run "$PWD/hooks/command" 426 | 427 | assert_failure 428 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 429 | assert_output --partial "Failed pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 430 | 431 | unstub docker 432 | } 433 | 434 | @test "Fails when docker login fails" { 435 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 436 | export HEROKU_API_KEY=api-token 437 | 438 | stub docker \ 439 | "login --username=_ --password-stdin registry.heroku.com : exit 1" 440 | 441 | run "$PWD/hooks/command" 442 | 443 | assert_failure 444 | 445 | unstub docker 446 | } 447 | 448 | @test "Fails when docker login fails with specified key" { 449 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 450 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_KEY_NAME=MY_HEROKU_KEY 451 | export HEROKU_API_KEY=irrelevant 452 | export MY_HEROKU_KEY=api-token 453 | 454 | stub docker \ 455 | "login --username=_ --password-stdin registry.heroku.com : exit 1" 456 | 457 | run "$PWD/hooks/command" 458 | 459 | assert_failure 460 | 461 | unstub docker 462 | } 463 | 464 | @test "Fails when an image push fails" { 465 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 466 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 467 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 468 | export HEROKU_API_KEY=api-token 469 | export RETRY_SLEEP=0 470 | 471 | stub docker \ 472 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 473 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 474 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 475 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 476 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 477 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 478 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 479 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 480 | "push registry.heroku.com/my-app/release:latest : exit 1" \ 481 | "push registry.heroku.com/my-app/release:latest : exit 1" \ 482 | "push registry.heroku.com/my-app/release:latest : exit 1" 483 | 484 | run "$PWD/hooks/command" 485 | 486 | assert_failure 487 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 488 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 489 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 490 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 491 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 492 | assert_output --partial "Failed push registry.heroku.com/my-app/release:latest" 493 | 494 | unstub docker 495 | } 496 | 497 | 498 | @test "Fails release image lookup" { 499 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 500 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 501 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 502 | export HEROKU_API_KEY=api-token 503 | 504 | stub docker \ 505 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 506 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 507 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 508 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 509 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 510 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 511 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 512 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 513 | "push registry.heroku.com/my-app/release:latest : exit 0" \ 514 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" \ 515 | "inspect registry.heroku.com/my-app/release:latest --format={{.Id}} : exit 1" 516 | 517 | stub curl \ 518 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\,\{\"type\"\:\"release\"\,\"docker_image\"\:\"release_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 1' 519 | 520 | run "$PWD/hooks/command" 521 | 522 | assert_failure 523 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 524 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 525 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 526 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 527 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 528 | assert_output --partial "Pushed registry.heroku.com/my-app/release:latest" 529 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 530 | refute_output --partial "Inspected registry.heroku.com/my-app/release:latest identified as release_id" 531 | refute_output --partial "Version 100 is current" 532 | 533 | unstub docker 534 | } 535 | 536 | @test "Fails releasing" { 537 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_0="web:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 538 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_PROCESS_TYPE_IMAGES_1="release:XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 539 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_APP=my-app 540 | export HEROKU_API_KEY=api-token 541 | 542 | stub docker \ 543 | "login --username=_ --password-stdin registry.heroku.com : exit 0" \ 544 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 545 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web : exit 0" \ 546 | "images -q XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 547 | "pull XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release : exit 0" \ 548 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web registry.heroku.com/my-app/web:latest : exit 0" \ 549 | "tag XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release registry.heroku.com/my-app/release:latest : exit 0" \ 550 | "push registry.heroku.com/my-app/web:latest : exit 0" \ 551 | "push registry.heroku.com/my-app/release:latest : exit 0" \ 552 | "inspect registry.heroku.com/my-app/web:latest --format={{.Id}} : echo web_id" \ 553 | "inspect registry.heroku.com/my-app/release:latest --format={{.Id}} : echo release_id" 554 | 555 | stub curl \ 556 | '-sf -X PATCH https://api.heroku.com/apps/my-app/formation -d \{\"updates\"\:\[\{\"type\"\:\"web\"\,\"docker_image\"\:\"web_id\"\}\,\{\"type\"\:\"release\"\,\"docker_image\"\:\"release_id\"\}\]\} -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3.docker-releases" -H "Authorization: Bearer api-token" -o /dev/null : exit 1' 557 | 558 | run "$PWD/hooks/command" 559 | 560 | assert_failure 561 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web" 562 | assert_output --partial "Pulled XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release" 563 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-web as registry.heroku.com/my-app/web:latest" 564 | assert_output --partial "Tagged XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-repo:heroku-release as registry.heroku.com/my-app/release:latest" 565 | assert_output --partial "Pushed registry.heroku.com/my-app/web:latest" 566 | assert_output --partial "Pushed registry.heroku.com/my-app/release:latest" 567 | assert_output --partial "Inspected registry.heroku.com/my-app/web:latest identified as web_id" 568 | assert_output --partial "Inspected registry.heroku.com/my-app/release:latest identified as release_id" 569 | refute_output --partial "Version 100 is current" 570 | 571 | unstub docker 572 | } 573 | 574 | @test "Missing Heroku API Key" { 575 | run "$PWD/hooks/command" 576 | 577 | assert_failure 578 | assert_output --partial "Missing heroku api key. Required HEROKU_API_KEY or \"key-name\"" 579 | } 580 | 581 | @test "Missing Heroku API Key when specified" { 582 | export BUILDKITE_PLUGIN_HEROKU_CONTAINER_DEPLOY_KEY_NAME=MY_HEROKU_KEY 583 | export HEROKU_API_KEY=irrelevant 584 | 585 | run "$PWD/hooks/command" 586 | 587 | assert_failure 588 | assert_output --partial "Missing heroku api key. Required HEROKU_API_KEY or \"key-name\"" 589 | } 590 | --------------------------------------------------------------------------------