├── .gitignore ├── tests ├── fixtures │ └── config_with_image └── post-command.bats ├── docker-compose.yml ├── plugin.yml ├── .github └── workflows │ └── test.yml ├── LICENSE ├── README.md └── hooks └── post-command /.gitignore: -------------------------------------------------------------------------------- 1 | docker-compose.buildkite* -------------------------------------------------------------------------------- /tests/fixtures/config_with_image: -------------------------------------------------------------------------------- 1 | name: project 2 | services: 3 | my-service: 4 | image: xxxxxxxxxxxx.dkr.ecr.amazonaws.com/my-service:latest 5 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | lint: 3 | image: buildkite/plugin-linter 4 | command: ["--id", "envato/docker-size-annotation"] 5 | volumes: 6 | - ".:/plugin:ro" 7 | 8 | tests: 9 | image: buildkite/plugin-tester 10 | volumes: 11 | - ".:/plugin" 12 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: Docker Size Annotation 2 | description: Annotates the build with a docker image size 3 | author: https://github.com/envato/docker-size-annotation-buildkite-plugin 4 | requirements: 5 | - docker 6 | configuration: 7 | properties: 8 | annotate: 9 | type: [string, array] 10 | minimum: 1 11 | additionalProperties: false 12 | -------------------------------------------------------------------------------- /.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/docker-size-annotation 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 | # Docker size annotation 2 | 3 | Annotates the build with a docker image size. 4 | 5 | Supports [docker-compose-buildkite-plugin](docker-compose-buildkite-plugin) 6 | 7 | ## Example 8 | 9 | Add the following to your `pipeline.yml`: 10 | 11 | ```yml 12 | steps: 13 | - label: "Build My Service" 14 | plugins: 15 | - docker-compose#v5.9.0: 16 | build: my-service 17 | - envato/docker-size-annotation#v2.1.0: 18 | annotate: my-service 19 | ``` 20 | 21 | or 22 | 23 | ```yml 24 | steps: 25 | - label: "Build My Services" 26 | plugins: 27 | - docker-compose#v5.9.0: 28 | build: 29 | - my-service 30 | - my-service2 31 | - envato/docker-size-annotation#v2.1.0: 32 | annotate: 33 | - my-service 34 | - my-service2 35 | ``` 36 | 37 | ## Configuration 38 | 39 | `annotate` 40 | 41 | The name of a service(s) to annotate. Either a single service or multiple services can be provided as an array. 42 | 43 | ## Developing 44 | 45 | To run the lint: 46 | 47 | ```shell 48 | docker-compose run --rm lint 49 | ``` 50 | 51 | To run the tests: 52 | 53 | ```shell 54 | docker-compose run --rm tests 55 | ``` 56 | -------------------------------------------------------------------------------- /hooks/post-command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | BUILDKITE_JOB_ID="${BUILDKITE_JOB_ID:-}" 5 | 6 | function plugin_read_list() { 7 | prefix_read_list "BUILDKITE_PLUGIN_DOCKER_SIZE_ANNOTATION_$1" 8 | } 9 | 10 | function prefix_read_list() { 11 | local prefix="$1" 12 | local parameter="${prefix}_0" 13 | 14 | if [[ -n "${!parameter:-}" ]]; then 15 | local i=0 16 | local parameter="${prefix}_${i}" 17 | while [[ -n "${!parameter:-}" ]]; do 18 | echo "${!parameter}" 19 | i=$((i+1)) 20 | parameter="${prefix}_${i}" 21 | done 22 | elif [[ -n "${!prefix:-}" ]]; then 23 | echo "${!prefix}" 24 | fi 25 | } 26 | 27 | function compose_tag_for_service() { 28 | local service="$1" 29 | 30 | echo "buildkite${BUILDKITE_JOB_ID//-}-${service}" 31 | } 32 | 33 | function compose_image_for_service() { 34 | local service="$1" 35 | local image="" 36 | 37 | image=$(docker compose config \ 38 | | grep -E "^( [._[:alnum:]-]+:| image:)" \ 39 | | grep -E "( ${service}:)" -A 1 \ 40 | | grep -oE ' image: (.+)' \ 41 | | awk '{print $2}') 42 | 43 | echo "$image" 44 | } 45 | 46 | 47 | services=() 48 | 49 | if [[ -n "$(plugin_read_list ANNOTATE)" ]]; then 50 | for service_name in $(plugin_read_list ANNOTATE); do 51 | services+=("$service_name") 52 | done 53 | fi 54 | 55 | for service_name in "${services[@]}"; do 56 | context="image-size-${service_name}" 57 | 58 | tags=("$(compose_tag_for_service "$service_name")" "$(compose_image_for_service "$service_name")") 59 | 60 | for tag in "${tags[@]}" ; do 61 | echo "Checking for tag: ${tag}" 62 | message=$(docker images --format "**${BUILDKITE_LABEL}** - *${service_name}* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})" "$tag") 63 | if [ -n "$message" ]; then 64 | echo "${message:-Unknown}" | buildkite-agent annotate --style info --context "${context}" 65 | break; 66 | fi 67 | done 68 | done 69 | -------------------------------------------------------------------------------- /tests/post-command.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | load "$BATS_PLUGIN_PATH/load.bash" 5 | 6 | # Uncomment the following line to debug stub failures 7 | # export DOCKER_STUB_DEBUG=/dev/tty 8 | # export BUILDKITE_AGENT_STUB_DEBUG=/dev/tty 9 | } 10 | 11 | @test "Annotates a single build" { 12 | export BUILDKITE_LABEL="My Label" 13 | export BUILDKITE_JOB_ID=0123456789abcedf 14 | export BUILDKITE_PLUGIN_DOCKER_SIZE_ANNOTATION_ANNOTATE="my-service" 15 | 16 | stub docker \ 17 | "compose config : echo ." \ 18 | "images --format \"**${BUILDKITE_LABEL}** - *my-service* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})\" \"buildkite0123456789abcedf-my-service\" : echo 5MB" 19 | 20 | stub buildkite-agent \ 21 | "annotate --style info --context \"image-size-my-service\" : exit 0" 22 | 23 | run "$PWD/hooks/post-command" 24 | 25 | assert_success 26 | 27 | unstub docker 28 | unstub buildkite-agent 29 | } 30 | 31 | @test "Annotates a single build (via array)" { 32 | export BUILDKITE_LABEL="My Label" 33 | export BUILDKITE_JOB_ID=0123456789abcedf 34 | export BUILDKITE_PLUGIN_DOCKER_SIZE_ANNOTATION_ANNOTATE_0="my-service" 35 | 36 | stub docker \ 37 | "compose config : echo ." \ 38 | "images --format \"**${BUILDKITE_LABEL}** - *my-service* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})\" \"buildkite0123456789abcedf-my-service\" : echo 5MB" 39 | 40 | stub buildkite-agent \ 41 | "annotate --style info --context \"image-size-my-service\" : exit 0" 42 | 43 | run "$PWD/hooks/post-command" 44 | 45 | assert_success 46 | 47 | unstub docker 48 | unstub buildkite-agent 49 | } 50 | 51 | @test "Annotates many builds" { 52 | export BUILDKITE_LABEL="My Label" 53 | export BUILDKITE_JOB_ID=0123456789abcedf 54 | export BUILDKITE_PLUGIN_DOCKER_SIZE_ANNOTATION_ANNOTATE_0="my-service" 55 | export BUILDKITE_PLUGIN_DOCKER_SIZE_ANNOTATION_ANNOTATE_1="my-service2" 56 | 57 | stub docker \ 58 | "compose config : echo ." \ 59 | "images --format \"**${BUILDKITE_LABEL}** - *my-service* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})\" \"buildkite0123456789abcedf-my-service\" : echo 5MB" \ 60 | "compose config : echo ." \ 61 | "images --format \"**${BUILDKITE_LABEL}** - *my-service2* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})\" \"buildkite0123456789abcedf-my-service2\" : echo 10MB" 62 | 63 | stub buildkite-agent \ 64 | "annotate --style info --context \"image-size-my-service\" : exit 0" \ 65 | "annotate --style info --context \"image-size-my-service2\" : exit 0" 66 | 67 | run "$PWD/hooks/post-command" 68 | 69 | assert_success 70 | 71 | unstub docker 72 | unstub buildkite-agent 73 | } 74 | 75 | @test "Annotates a build with image config" { 76 | export BUILDKITE_LABEL="My Label" 77 | export BUILDKITE_JOB_ID=0123456789abcedf 78 | export BUILDKITE_PLUGIN_DOCKER_SIZE_ANNOTATION_ANNOTATE="my-service" 79 | 80 | stub docker \ 81 | "compose config : cat tests/fixtures/config_with_image" \ 82 | "images --format \"**${BUILDKITE_LABEL}** - *my-service* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})\" \"buildkite0123456789abcedf-my-service\" : exit 0" \ 83 | "images --format \"**${BUILDKITE_LABEL}** - *my-service* docker image is **{{.Size}}** (Tag {{.Tag}} ID {{.ID}})\" \"xxxxxxxxxxxx.dkr.ecr.amazonaws.com/my-service:latest\" : echo 5MB" 84 | 85 | stub buildkite-agent \ 86 | "annotate --style info --context \"image-size-my-service\" : exit 0" 87 | 88 | run "$PWD/hooks/post-command" 89 | 90 | assert_success 91 | 92 | unstub docker 93 | unstub buildkite-agent 94 | } 95 | --------------------------------------------------------------------------------