Skip to content

Commit

Permalink
Merge pull request #345 from buildkite-plugins/toote_validate_tags_is…
Browse files Browse the repository at this point in the history
…sue-233

Validate tags
  • Loading branch information
pzeballos authored Oct 12, 2022
2 parents 9a55963 + 14f1640 commit 0cbd316
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 28 deletions.
54 changes: 27 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The following pipeline will run `test.sh` inside a `app` service container using
steps:
- command: test.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
```
Expand All @@ -28,7 +28,7 @@ through if you need:
steps:
- command: test.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
config: docker-compose.tests.yml
env:
Expand All @@ -41,7 +41,7 @@ or multiple config files:
steps:
- command: test.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
config:
- docker-compose.yml
Expand All @@ -56,7 +56,7 @@ env:
steps:
- command: test.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
```

Expand All @@ -65,7 +65,7 @@ If you want to control how your command is passed to docker-compose, you can use
```yml
steps:
- plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
command: ["custom", "command", "values"]
```
Expand All @@ -79,15 +79,15 @@ steps:
- plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: app
image-repository: index.docker.io/myorg/myrepo
- wait
- command: test.sh
plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
```

Expand All @@ -104,7 +104,7 @@ steps:
- command: generate-dist.sh
artifact_paths: "dist/*"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
```

Expand All @@ -122,7 +122,7 @@ steps:
- command: generate-dist.sh
artifact_paths: "dist/*"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
volumes:
- "./dist:/app/dist"
Expand All @@ -146,7 +146,7 @@ this plugin offers a `environment` block of its own:
steps:
- command: generate-dist.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
env:
- BUILDKITE_BUILD_NUMBER
Expand All @@ -164,7 +164,7 @@ Alternatively, you can have the plugin add all environment variables defined for
steps:
- command: use-vars.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
propagate-environment: true
```
Expand All @@ -179,7 +179,7 @@ Alternatively, if you want to set build arguments when pre-building an image, th
steps:
- command: generate-dist.sh
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: app
image-repository: index.docker.io/myorg/myrepo
args:
Expand All @@ -196,7 +196,7 @@ If you have multiple steps that use the same service/image (such as steps that r
steps:
- label: ":docker: Build"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: app
image-repository: index.docker.io/myorg/myrepo
Expand All @@ -206,7 +206,7 @@ steps:
command: test.sh
parallelism: 25
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: app
```

Expand All @@ -222,7 +222,7 @@ steps:
agents:
queue: docker-builder
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build:
- app
- tests
Expand All @@ -234,7 +234,7 @@ steps:
command: test.sh
parallelism: 25
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: tests
```

Expand All @@ -246,7 +246,7 @@ If you want to push your Docker images ready for deployment, you can use the `pu
steps:
- label: ":docker: Push"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
push: app
```

Expand All @@ -256,7 +256,7 @@ To push multiple images, you can use a list:
steps:
- label: ":docker: Push"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
push:
- first-service
- second-service
Expand All @@ -268,7 +268,7 @@ If you want to push to a specific location (that's not defined as the `image` in
steps:
- label: ":docker: Push"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
push:
- app:index.docker.io/myorg/myrepo/myapp
- app:index.docker.io/myorg/myrepo/myapp:latest
Expand All @@ -282,14 +282,14 @@ A newly spawned agent won't contain any of the docker caches for the first run w
steps:
- label: ":docker: Build an image"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: app
image-repository: index.docker.io/myorg/myrepo
cache-from: app:index.docker.io/myorg/myrepo/myapp:latest
- wait
- label: ":docker: Push to final repository"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
push:
- app:index.docker.io/myorg/myrepo/myapp
- app:index.docker.io/myorg/myrepo/myapp:latest
Expand All @@ -303,7 +303,7 @@ This plugin allows for the value of `cache-from` to be a string or a list. If it
steps:
- label: ":docker Build an image"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: app
image-repository: index.docker.io/myorg/myrepo
cache-from:
Expand All @@ -312,7 +312,7 @@ steps:
- wait
- label: ":docker: Push to final repository"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
push:
- app:index.docker.io/myorg/myrepo/myapp
- app:index.docker.io/myorg/myrepo/myapp:my-branch
Expand All @@ -326,7 +326,7 @@ Adding a grouping tag to the end of a cache-from list item allows this plugin to
steps:
- label: ":docker: Build Intermediate Image"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: myservice_intermediate # docker-compose.yml is the same as myservice but has `target: intermediate`
image-name: buildkite-build-${BUILDKITE_BUILD_NUMBER}
image-repository: index.docker.io/myorg/myrepo/myservice_intermediate
Expand All @@ -336,7 +336,7 @@ steps:
- wait
- label: ":docker: Build Final Image"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: myservice
image-name: buildkite-build-${BUILDKITE_BUILD_NUMBER}
image-repository: index.docker.io/myorg/myrepo
Expand Down Expand Up @@ -380,7 +380,7 @@ A basic pipeline similar to the following:
steps:
- label: ":docker: Run & Push"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
run: myservice
push: myservice
```
Expand All @@ -395,7 +395,7 @@ A basic pipeline similar to the following:
steps:
- label: ":docker: Build & Push"
plugins:
- docker-compose#v4.0.0:
- docker-compose#v4.1.1:
build: myservice
push: myservice
```
Expand Down
13 changes: 13 additions & 0 deletions commands/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ if [[ "$(plugin_read_config NO_CACHE "false")" == "false" ]] ; then
IFS=':' read -r -a tokens <<< "$line"
service_name=${tokens[0]}
service_image=$(IFS=':'; echo "${tokens[*]:1:2}")
service_tag=${tokens[2]}

if ! validate_tag "$service_tag"; then
echo "🚨 cache-from ${service_image} has an invalid tag so it will be ignored"
continue
fi

cache_from_group_name=$(IFS=':'; echo "${tokens[*]:3}")
if [[ -z "$cache_from_group_name" ]]; then
cache_from_group_name=":default:"
Expand Down Expand Up @@ -90,6 +97,12 @@ fi
service_idx=0
for service_name in $(plugin_read_list BUILD) ; do
image_name=$(build_image_name "${service_name}" "${service_idx}")

if ! validate_tag "$image_name"; then
echo "🚨 ${image_name} is not a valid tag name"
exit 1
fi

service_idx=$((service_idx+1))

if [[ -n "$image_repository" ]] ; then
Expand Down
8 changes: 8 additions & 0 deletions commands/push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ for line in $(plugin_read_list PUSH) ; do
service_name=${tokens[0]}
service_image=$(compose_image_for_service "$service_name")

# push in the form of service:repo:tag
if [[ ${#tokens[@]} -gt 2 ]]; then
if ! validate_tag "${tokens[2]}"; then
echo "🚨 specified image to push ${line} has an invalid tag so it will be ignored"
continue
fi
fi

# Pull down prebuilt image if one exists
if prebuilt_image=$(get_prebuilt_image "$service_name") ; then

Expand Down
10 changes: 10 additions & 0 deletions lib/shared.bash
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,13 @@ function is_windows() {
function is_macos() {
[[ "$OSTYPE" =~ ^(darwin) ]]
}

function validate_tag {
local tag=$1

if [[ "$tag" =~ ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ ]]; then
return 0
else
return 1
fi
}
2 changes: 1 addition & 1 deletion plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ configuration:
image-repository:
type: string
image-name:
type: string
type: [ string, array ]
pull-retries:
type: integer
push-retries:
Expand Down
61 changes: 61 additions & 0 deletions tests/build.bats
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,27 @@ load '../lib/shared'
unstub docker-compose
}

@test "Build with an invalid cache-from tag" {
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG="tests/composefiles/docker-compose.v3.2.yml"
export BUILDKITE_JOB_ID=1111
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_BUILD_0=helloworld
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CACHE_FROM_0=helloworld:my.repository/myservice_cache:-latest
export BUILDKITE_PIPELINE_SLUG=test
export BUILDKITE_BUILD_NUMBER=1

stub docker-compose \
"-f tests/composefiles/docker-compose.v3.2.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml build --pull helloworld : echo built helloworld"

run "$PWD"/hooks/command

assert_success
refute_output --partial "pulled cache image"
refute_output --partial "- my.repository/myservice_cache:-latest"
assert_output --partial "invalid tag so it will be ignored"
assert_output --partial "built helloworld"
unstub docker-compose
}

@test "Build with several cache-from images for one service" {
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG="tests/composefiles/docker-compose.v3.2.yml"
export BUILDKITE_JOB_ID=1111
Expand Down Expand Up @@ -599,6 +620,46 @@ load '../lib/shared'
unstub buildkite-agent
}

@test "Build with an invalid image-name (start with hyphen) " {
export BUILDKITE_JOB_ID=1111
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_BUILD=myservice
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_NAME=-llamas-image
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_REPOSITORY=my.repository/llamas
export BUILDKITE_BUILD_NUMBER=1

run "$PWD"/hooks/command

assert_failure
assert_output --partial "-llamas-image is not a valid tag name"
}

@test "Build with an invalid image-name (start with period) " {
export BUILDKITE_JOB_ID=1111
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_BUILD=myservice
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_NAME=.llamas-image
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_REPOSITORY=my.repository/llamas
export BUILDKITE_BUILD_NUMBER=1

run "$PWD"/hooks/command

assert_failure
assert_output --partial ".llamas-image is not a valid tag name"
}

@test "Build with an invalid image-name (too long) " {
export BUILDKITE_JOB_ID=1111
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_BUILD=myservice
# numbers from 1 to 69 result in 129 characters
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_NAME="$(seq 69 | tr -d "\n")"
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_REPOSITORY=my.repository/llamas
export BUILDKITE_BUILD_NUMBER=1

run "$PWD"/hooks/command

assert_failure
assert_output --partial "is not a valid tag name"
}

@test "Build with a custom image-name and a config" {
export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG="tests/composefiles/docker-compose.v3.2.yml"
export BUILDKITE_JOB_ID=1111
Expand Down
Loading

0 comments on commit 0cbd316

Please sign in to comment.