Skip to content

Commit f2b4ab0

Browse files
authored
Merge pull request #99 from buildkite-plugins/toote_compression_refactoring
Compression refactoring
2 parents 0fc5b9f + 9ca2ee2 commit f2b4ab0

File tree

13 files changed

+167
-126
lines changed

13 files changed

+167
-126
lines changed

.buildkite/pipeline.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ steps:
1010
- hooks/**
1111
- lib/**
1212
- backends/**
13+
- compression/**
1314
options: "-x"
1415

1516
- label: ":sparkles: Lint"

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ Setting the `BUILDKITE_PLUGIN_S3_CACHE_ONLY_SHOW_ERRORS` environment variable wi
6969

7070
Allows for the cached file/folder to be saved/restored as a single file. You will need to make sure to use the same compression when saving and restoring or it will cause a cache miss.
7171

72-
Assuming the underlying executables are available, the allowed values are:
72+
The value `none` is equivalent to not specifying a compression. Any other value (`X`) will assume that an executable wrapper script exists in the agent's `PATH` to handle both compression and decompression with the following protocol:
73+
* `X_wrapper compress SOURCE TARGET`: compress the file/folder `SOURCE` into the `TARGET` file
74+
* `X_wrapper decompress SOURCE TARGET`: decompress the artifact `SOURCE` into `TARGET` destination
75+
76+
The plugin includes wrappers to provide both examples and backwards-compatibility:
7377
* `tgz`: `tar` with gzip compression
7478
* `zip`: `(un)zip` compression
7579

compression/tgz_wrapper

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
OPERATION=${1?Operation not specified}
4+
SOURCE=${2?Source not specified}
5+
TARGET=${3?Target not specified}
6+
7+
is_absolute_path() {
8+
[ "${1:0:1}" = "/" ]
9+
}
10+
11+
if [ "${OPERATION}" = "compress" ]; then
12+
TAR_OPTS='cz'
13+
if is_absolute_path "${SOURCE}"; then
14+
TAR_OPTS="${TAR_OPTS}"P
15+
fi
16+
17+
tar "${TAR_OPTS}"f "${TARGET}" "${SOURCE}"
18+
elif [ "${OPERATION}" = "decompress" ]; then
19+
TAR_OPTS='xz'
20+
if is_absolute_path "${TARGET}"; then
21+
TAR_OPTS="${TAR_OPTS}"P
22+
fi
23+
24+
tar "${TAR_OPTS}"f "${SOURCE}" "${TARGET}"
25+
else
26+
echo "Invalid operation"
27+
exit 1
28+
fi

compression/zip_wrapper

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash
2+
3+
OPERATION=${1?Operation not specified}
4+
SOURCE=${2?Source not specified}
5+
TARGET=${3?Target not specified}
6+
7+
is_absolute_path() {
8+
[ "${1:0:1}" = "/" ]
9+
}
10+
11+
if [ "${OPERATION}" = "compress" ]; then
12+
if is_absolute_path "${SOURCE}"; then
13+
COMPRESS_DIR="$(dirname "${SOURCE}")"
14+
( # subshell to avoid changing the working directory
15+
# shellcheck disable=SC2164 # we will exit anyway
16+
cd "${COMPRESS_DIR}"
17+
# because ZIP complains if the file does not end with .zip
18+
zip -r "${TARGET}.zip" "${SOURCE}"
19+
mv "${TARGET}.zip" "${TARGET}"
20+
)
21+
else
22+
# because ZIP complains if the file does not end with .zip
23+
zip -r "${TARGET}.zip" "${SOURCE}"
24+
mv "${TARGET}.zip" "${TARGET}"
25+
fi
26+
elif [ "${OPERATION}" = "decompress" ]; then
27+
if is_absolute_path "${TARGET}"; then
28+
RESTORE_DIR="$(dirname "${TARGET}")"
29+
( # subshell to avoid changing the working directory
30+
mkdir -p "${RESTORE_DIR}"
31+
# shellcheck disable=SC2164 # we will exit anyway
32+
cd "${RESTORE_DIR}"
33+
mv "${SOURCE}" "${RESTORE_DIR}/compressed.zip"
34+
unzip -o "compressed.zip"
35+
rm "compressed.zip"
36+
)
37+
else
38+
# because ZIP complains if the file does not end with .zip
39+
mv "${SOURCE}" "${SOURCE}.zip"
40+
unzip -o "${SOURCE}.zip"
41+
fi
42+
else
43+
echo "Invalid operation"
44+
exit 1
45+
fi

hooks/post-command

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ if [ -z "${CACHE_PATH}" ] ; then
2222
fi
2323

2424
COMPRESS=$(plugin_read_config COMPRESSION 'none')
25-
if ! validate_compression "${COMPRESS}"; then
26-
echo "+++ 🚨 Invalid value for compression option"
27-
exit 1
28-
fi
2925

3026
if ! plugin_read_list_into_result SAVE; then
3127
echo 'Cache not setup for saving'

hooks/pre-command

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ elif [ "${MAX_LEVEL}" = 'file' ] && [ -z "$(plugin_read_config MANIFEST)" ]; the
2525
fi
2626

2727
COMPRESS=$(plugin_read_config COMPRESSION 'none')
28-
if ! validate_compression "${COMPRESS}"; then
29-
echo "+++ 🚨 Invalid value for compression option"
30-
exit 1
31-
fi
3228

3329
build_key "${MAX_LEVEL}" "${RESTORE_PATH}" >/dev/null # to validate the level
3430

@@ -46,7 +42,7 @@ for CURRENT_LEVEL in "${SORTED_LEVELS[@]}"; do
4642
if compression_active; then
4743
TEMP_PATH=$(mktemp)
4844
backend_exec get "${KEY}" "${TEMP_PATH}"
49-
uncompress "${TEMP_PATH}" "${RESTORE_PATH}"
45+
decompress "${TEMP_PATH}" "${RESTORE_PATH}"
5046
if [ "$(plugin_read_config KEEP_COMPRESSED_ARTIFACTS 'false')" = 'false' ]; then
5147
rm -rf "${TEMP_PATH}"
5248
fi

lib/compression.bash

Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,6 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
55
# shellcheck source=lib/plugin.bash
66
. "${DIR}/plugin.bash"
77

8-
validate_compression() {
9-
local COMPRESSION="$1"
10-
11-
VALID_COMPRESSIONS=(none tgz zip)
12-
for VALID in "${VALID_COMPRESSIONS[@]}"; do
13-
if [ "${COMPRESSION}" = "${VALID}" ]; then
14-
return 0
15-
fi
16-
done
17-
18-
return 1
19-
}
20-
218
compression_active() {
229
local COMPRESSION=''
2310
COMPRESSION="$(plugin_read_config COMPRESSION 'none')"
@@ -32,71 +19,21 @@ compress() {
3219
local COMPRESSION=''
3320
COMPRESSION="$(plugin_read_config COMPRESSION 'none')"
3421

35-
echo "Compressing ${COMPRESSED_FILE} with ${COMPRESSION}..."
36-
37-
if [ "${COMPRESSION}" = 'tgz' ]; then
38-
TAR_OPTS='cz'
39-
if is_absolute_path "${COMPRESSED_FILE}"; then
40-
TAR_OPTS="${TAR_OPTS}"P
41-
fi
42-
43-
tar "${TAR_OPTS}"f "${FILE}" "${COMPRESSED_FILE}"
44-
elif [ "${COMPRESSION}" = 'zip' ]; then
45-
if is_absolute_path "${COMPRESSED_FILE}"; then
46-
local COMPRESS_DIR
47-
COMPRESS_DIR="$(dirname "${COMPRESSED_FILE}")"
48-
( # subshell to avoid changing the working directory
49-
# shellcheck disable=SC2164 # we will exit anyway
50-
cd "${COMPRESS_DIR}"
51-
# because ZIP complains if the file does not end with .zip
52-
zip -r "${FILE}.zip" "${COMPRESSED_FILE}"
53-
mv "${FILE}.zip" "${FILE}"
54-
)
55-
else
56-
# because ZIP complains if the file does not end with .zip
57-
zip -r "${FILE}.zip" "${COMPRESSED_FILE}"
58-
mv "${FILE}.zip" "${FILE}"
59-
fi
22+
if [ "${COMPRESSION}" != 'none' ]; then
23+
echo "Compressing ${COMPRESSED_FILE} with ${COMPRESSION}..."
24+
PATH="${PATH}:${DIR}/../compression" "${COMPRESSION}_wrapper" "compress" "${COMPRESSED_FILE}" "${FILE}"
6025
fi
6126
}
6227

63-
uncompress() {
28+
decompress() {
6429
local FILE="$1"
6530
local RESTORE_PATH="$2"
6631

6732
local COMPRESSION=''
6833
COMPRESSION="$(plugin_read_config COMPRESSION 'none')"
6934

70-
echo "Cache is compressed, uncompressing with ${COMPRESSION}..."
71-
72-
if [ "${COMPRESSION}" = 'tgz' ]; then
73-
TAR_OPTS='xz'
74-
if is_absolute_path "${RESTORE_PATH}"; then
75-
TAR_OPTS="${TAR_OPTS}"P
76-
fi
77-
78-
tar "${TAR_OPTS}"f "${FILE}" "${RESTORE_PATH}"
79-
elif [ "${COMPRESSION}" = 'zip' ]; then
80-
if is_absolute_path "${RESTORE_PATH}"; then
81-
local RESTORE_DIR
82-
RESTORE_DIR="$(dirname "${RESTORE_PATH}")"
83-
( # subshell to avoid changing the working directory
84-
mkdir -p "${RESTORE_DIR}"
85-
# shellcheck disable=SC2164 # we will exit anyway
86-
cd "${RESTORE_DIR}"
87-
mv "${FILE}" "${RESTORE_DIR}/compressed.zip"
88-
unzip -o "compressed.zip"
89-
rm "compressed.zip"
90-
)
91-
else
92-
# because ZIP complains if the file does not end with .zip
93-
mv "${FILE}" "${FILE}.zip"
94-
unzip -o "${FILE}.zip"
95-
fi
35+
if [ "${COMPRESSION}" != 'none' ]; then
36+
echo "Cache is compressed, decompressing with ${COMPRESSION}..."
37+
PATH="${PATH}:${DIR}/../compression" "${COMPRESSION}_wrapper" "decompress" "${FILE}" "${RESTORE_PATH}"
9638
fi
9739
}
98-
99-
is_absolute_path() {
100-
local FILEPATH="${1}"
101-
[ "${FILEPATH:0:1}" = "/" ]
102-
}

plugin.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ configuration:
1717
type: string
1818
compression:
1919
type: string
20-
enum:
21-
- zip
22-
- tar
23-
- tgz
2420
force:
2521
type: boolean
2622
keep-compressed-artifacts:

tests/compression.bats

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,83 @@
11
#!/usr/bin/env bats
22

33
# To debug stubs, uncomment these lines:
4-
# export HASH_STUB_DEBUG=/dev/tty
4+
# export DUMMY_COMPRESS_WRAPPER_STUB_DEBUG=/dev/tty
5+
# export DUMMY_DECOMPRESS_WRAPPER_STUB_DEBUG=/dev/tty
56

67
setup() {
78
load "${BATS_PLUGIN_PATH}/load.bash"
89

10+
# prevent a warning when using flags on run
11+
bats_require_minimum_version 1.5.0
12+
913
source "${PWD}/lib/compression.bash"
1014
}
1115

12-
@test 'validate_compression works' {
13-
run validate_compression none
16+
# TODO: Add tests for wrappers
17+
#TODO: change plugin.yml and README
18+
19+
@test 'compression_active works' {
20+
# default value
21+
run compression_active
22+
assert_failure
23+
24+
# turned off
25+
export BUILDKITE_PLUGIN_CACHE_COMPRESSION=none
26+
run compression_active
27+
assert_failure
1428

29+
# any other value
30+
export BUILDKITE_PLUGIN_CACHE_COMPRESSION=something_else
31+
run compression_active
1532
assert_success
33+
}
1634

17-
run validate_compression tgz
35+
@test 'compress works' {
36+
# default value does nothing
37+
run compress SOURCE TARGET
1838
assert_success
39+
refute_output 'Compressiong SOURCE with'
40+
41+
# define a compression
42+
export BUILDKITE_PLUGIN_CACHE_COMPRESSION=dummy_compress
43+
# -127 prevents a warning due to command not found
44+
run -127 compress SOURCE TARGET
45+
assert_failure
46+
assert_output --partial 'Compressing SOURCE with dummy_compress'
47+
assert_output --partial 'dummy_compress_wrapper: command not found'
48+
49+
# using an existing compression
50+
stub dummy_compress_wrapper \
51+
"compress \* \* : echo Compressed wrapper \$2 with dummy_compress"
1952

20-
run validate_compression zip
53+
run compress SOURCE TARGET
2154
assert_success
55+
assert_output --partial 'Compressing SOURCE with dummy_compress'
2256

23-
run validate_compression invalid
57+
unstub dummy_compress_wrapper
58+
}
59+
60+
@test 'decompress works' {
61+
# default value does nothing
62+
run decompress SOURCE TARGET
63+
assert_success
64+
refute_output 'uncompressing with'
65+
66+
# define a compression
67+
export BUILDKITE_PLUGIN_CACHE_COMPRESSION=dummy_decompress
68+
# -127 prevents a warning due to command not found
69+
run -127 decompress SOURCE TARGET
2470
assert_failure
71+
assert_output --partial 'decompressing with dummy_decompress'
72+
assert_output --partial 'dummy_decompress_wrapper: command not found'
73+
74+
# using an existing compression
75+
stub dummy_decompress_wrapper \
76+
"decompress \* \* : echo Decompressing wrapper \$2 with dummy_decompress"
77+
78+
run decompress SOURCE TARGET
79+
assert_success
80+
assert_output --partial 'decompressing with dummy_decompress'
81+
82+
unstub dummy_decompress_wrapper
2583
}

tests/post-command.bats

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,6 @@ teardown() {
6363
assert_output --partial 'Invalid levels in the save list'
6464
}
6565

66-
@test "Invalid compression level fails" {
67-
export BUILDKITE_PLUGIN_CACHE_SAVE=all
68-
export BUILDKITE_PLUGIN_CACHE_COMPRESSION=invalid
69-
70-
run "$PWD/hooks/post-command"
71-
72-
assert_failure
73-
assert_output --partial 'Invalid value for compression option'
74-
}
75-
7666
@test "File-based cache with no manifest fails" {
7767
export BUILDKITE_PLUGIN_CACHE_SAVE=file
7868

0 commit comments

Comments
 (0)