Skip to content

Commit 42fe6b5

Browse files
authored
Merge pull request #459 from buildkite-plugins/SUP-2585
SUP-2585: Docker Cache Support
2 parents 7e27de1 + c8a1a19 commit 42fe6b5

File tree

7 files changed

+213
-37
lines changed

7 files changed

+213
-37
lines changed

README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ A list of images to attempt pulling before building in the format `service:CACHE
174174

175175
They will be mapped directly to `cache-from` elements in the build according to the spec so any valid format there should be allowed.
176176

177+
#### `cache-to` (build only, string or array)
178+
179+
A list of export locations to be used to share build cache with future builds in the format `service:CACHE-SPEC` to allow for layer re-use. Unsupported caches are ignored and do not prevent building images.
180+
181+
They will be mapped directly to `cache-to` elements in the build according to the spec so any valid format there should be allowed.
182+
177183
#### `target` (build only)
178184

179185
Allow for intermediate builds as if building with docker's `--target VALUE` options.
@@ -343,7 +349,7 @@ The default is `false`.
343349
To run the tests:
344350

345351
```bash
346-
docker-compose run --rm tests bats tests tests/v1
352+
docker compose run --rm tests bats tests tests/v1
347353
```
348354

349355
## License

commands/build.sh

+30-4
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,24 @@ get_caches_for_service() {
3535
fi
3636
}
3737

38+
get_caches_to_service() {
39+
local service="$1"
40+
41+
# Read any cache-to parameters provided
42+
for line in $(plugin_read_list CACHE_TO) ; do
43+
IFS=':' read -r -a tokens <<< "$line"
44+
service_name=${tokens[0]}
45+
service_image=$(IFS=':'; echo "${tokens[*]:1}")
46+
47+
if [ "${service_name}" == "${service}" ]; then
48+
echo "$service_image"
49+
fi
50+
done
51+
}
52+
53+
3854
# Run through all images in the build property, either a single item or a list
39-
# and build up a list of service name, image name and optional cache-froms to
55+
# and build up a list of service name, image name and optional cache-froms and cache-tos to
4056
# write into a docker-compose override file
4157
for service_name in $(plugin_read_list BUILD) ; do
4258
target="$(plugin_read_config TARGET "")"
@@ -47,19 +63,29 @@ for service_name in $(plugin_read_list BUILD) ; do
4763
cache_from+=("$cache_line")
4864
done
4965

66+
cache_to=()
67+
for cache_line in $(get_caches_to_service "$service_name"); do
68+
cache_to+=("$cache_line")
69+
done
70+
5071
labels=()
5172
while read -r label ; do
5273
[[ -n "${label:-}" ]] && labels+=("${label}")
5374
done <<< "$(plugin_read_list BUILD_LABELS)"
5475

55-
if [[ -n "${target}" ]] || [[ "${#labels[@]}" -gt 0 ]] || [[ "${#cache_from[@]}" -gt 0 ]]; then
76+
if [[ -n "${target}" ]] || [[ "${#labels[@]}" -gt 0 ]] || [[ "${#cache_to[@]}" -gt 0 ]] || [[ "${#cache_from[@]}" -gt 0 ]]; then
5677
build_images+=("$service_name" "${image_name}" "${target}")
57-
78+
5879
build_images+=("${#cache_from[@]}")
5980
if [[ "${#cache_from[@]}" -gt 0 ]]; then
6081
build_images+=("${cache_from[@]}")
6182
fi
62-
83+
84+
build_images+=("${#cache_to[@]}")
85+
if [[ "${#cache_to[@]}" -gt 0 ]]; then
86+
build_images+=("${cache_to[@]}")
87+
fi
88+
6389
build_images+=("${#labels[@]}")
6490
if [[ "${#labels[@]}" -gt 0 ]]; then
6591
build_images+=("${labels[@]}")

commands/run.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ for service_name in "${prebuilt_candidates[@]}" ; do
5252
fi
5353

5454
if [[ -n "$prebuilt_image" ]] ; then
55-
prebuilt_service_overrides+=("$service_name" "$prebuilt_image" "" 0 0)
55+
prebuilt_service_overrides+=("$service_name" "$prebuilt_image" "" 0 0 0)
5656
prebuilt_services+=("$service_name")
5757

5858
# If it's prebuilt, we need to pull it down

lib/shared.bash

+29-12
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,15 @@ function build_image_override_file() {
133133
"$(docker_compose_config_version)" "$@"
134134
}
135135

136-
# Checks that a specific version of docker-compose supports cache_from
137-
function docker_compose_supports_cache_from() {
136+
# Checks that a specific version of docker-compose supports cache_from and cache_to
137+
function docker_compose_supports_cache() {
138138
local version="$1"
139139
if [[ "$version" == 1* || "$version" =~ ^(2|3)(\.[01])?$ ]] ; then
140-
return 1
140+
echo "Unsupported Docker Compose config file version: $version"
141+
echo "The 'cache_from' option can only be used with Compose file versions 2.2 or 3.2 and above."
142+
echo "For more information on Docker Compose configuration file versions, see:"
143+
echo "https://docs.docker.com/compose/compose-file/compose-versioning/#versioning"
144+
exit 1
141145
fi
142146
}
143147

@@ -176,6 +180,16 @@ function build_image_override_file_with_version() {
176180
done
177181
fi
178182

183+
# load cache_to array
184+
cache_to_amt="${1:-0}"
185+
[[ -n "${1:-}" ]] && shift; # remove the value if not empty
186+
if [[ "${cache_to_amt}" -gt 0 ]]; then
187+
cache_to=()
188+
for _ in $(seq 1 "$cache_to_amt"); do
189+
cache_to+=( "$1" ); shift
190+
done
191+
fi
192+
179193
# load labels array
180194
labels_amt="${1:-0}"
181195
[[ -n "${1:-}" ]] && shift; # remove the value if not empty
@@ -186,7 +200,7 @@ function build_image_override_file_with_version() {
186200
done
187201
fi
188202

189-
if [[ -z "$image_name" ]] && [[ -z "$target" ]] && [[ "$cache_from_amt" -eq 0 ]] && [[ "$labels_amt" -eq 0 ]]; then
203+
if [[ -z "$image_name" ]] && [[ -z "$target" ]] && [[ "$cache_from_amt" -eq 0 ]] && [[ "$cache_to_amt" -eq 0 ]] && [[ "$labels_amt" -eq 0 ]]; then
190204
# should not print out an empty service
191205
continue
192206
fi
@@ -197,7 +211,7 @@ function build_image_override_file_with_version() {
197211
printf " image: %s\\n" "$image_name"
198212
fi
199213

200-
if [[ "$cache_from_amt" -gt 0 ]] || [[ -n "$target" ]] || [[ "$labels_amt" -gt 0 ]]; then
214+
if [[ "$cache_from_amt" -gt 0 ]] || [[ "$cache_to_amt" -gt 0 ]] || [[ -n "$target" ]] || [[ "$labels_amt" -gt 0 ]]; then
201215
printf " build:\\n"
202216
fi
203217

@@ -206,20 +220,23 @@ function build_image_override_file_with_version() {
206220
fi
207221

208222
if [[ "$cache_from_amt" -gt 0 ]] ; then
209-
if ! docker_compose_supports_cache_from "$version" ; then
210-
echo "Unsupported Docker Compose config file version: $version"
211-
echo "The 'cache_from' option can only be used with Compose file versions 2.2 or 3.2 and above."
212-
echo "For more information on Docker Compose configuration file versions, see:"
213-
echo "https://docs.docker.com/compose/compose-file/compose-versioning/#versioning"
214-
exit 1
215-
fi
223+
docker_compose_supports_cache "$version"
216224

217225
printf " cache_from:\\n"
218226
for cache_from_i in "${cache_from[@]}"; do
219227
printf " - %s\\n" "${cache_from_i}"
220228
done
221229
fi
222230

231+
if [[ "$cache_to_amt" -gt 0 ]] ; then
232+
docker_compose_supports_cache "$version"
233+
234+
printf " cache_to:\\n"
235+
for cache_to_i in "${cache_to[@]}"; do
236+
printf " - %s\\n" "${cache_to_i}"
237+
done
238+
fi
239+
223240
if [[ "$labels_amt" -gt 0 ]] ; then
224241
printf " labels:\\n"
225242
for label in "${labels[@]}"; do

plugin.yml

+6-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ configuration:
99
run:
1010
type: string
1111
build:
12-
type: [ string, array ]
12+
type: [string, array]
1313
minimum: 1
1414
push:
15-
type: [ string, array ]
15+
type: [string, array]
1616
minimum: 1
1717

1818
ansi:
@@ -35,6 +35,9 @@ configuration:
3535
cache-from:
3636
type: [ string, array ]
3737
minimum: 1
38+
cache-to:
39+
type: [ string, array ]
40+
minimum: 1
3841
cli-version:
3942
oneOf:
4043
- type: string
@@ -150,6 +153,7 @@ configuration:
150153
buildkit: [ build ]
151154
buildkit-inline-cache: [ build ]
152155
cache-from: [ build ]
156+
cache-to: [ build ]
153157
command: [ run ]
154158
dependencies: [ run ]
155159
entrypoint: [ run ]

tests/docker-compose-config.bats

+11-11
Original file line numberDiff line numberDiff line change
@@ -81,34 +81,34 @@ load '../lib/shared'
8181
assert_output "2.0"
8282
}
8383

84-
@test "Whether docker-compose supports cache_from directive" {
85-
run docker_compose_supports_cache_from ""
84+
@test "Whether docker-compose supports cache_from and cache_to directive" {
85+
run docker_compose_supports_cache ""
8686
assert_success
8787

88-
run docker_compose_supports_cache_from "1.0"
88+
run docker_compose_supports_cache "1.0"
8989
assert_failure
9090

91-
run docker_compose_supports_cache_from "2"
91+
run docker_compose_supports_cache "2"
9292
assert_failure
9393

94-
run docker_compose_supports_cache_from "2.1"
94+
run docker_compose_supports_cache "2.1"
9595
assert_failure
9696

97-
run docker_compose_supports_cache_from "2.2"
97+
run docker_compose_supports_cache "2.2"
9898
assert_success
9999

100-
run docker_compose_supports_cache_from "2.3"
100+
run docker_compose_supports_cache "2.3"
101101
assert_success
102102

103-
run docker_compose_supports_cache_from "3"
103+
run docker_compose_supports_cache "3"
104104
assert_failure
105105

106-
run docker_compose_supports_cache_from "3.1"
106+
run docker_compose_supports_cache "3.1"
107107
assert_failure
108108

109-
run docker_compose_supports_cache_from "3.2"
109+
run docker_compose_supports_cache "3.2"
110110
assert_success
111111

112-
run docker_compose_supports_cache_from "3.3"
112+
run docker_compose_supports_cache "3.3"
113113
assert_success
114114
}

0 commit comments

Comments
 (0)