diff --git a/.github/workflows/test-assert-image-size.yml b/.github/workflows/test-assert-image-size.yml new file mode 100644 index 0000000..8566a16 --- /dev/null +++ b/.github/workflows/test-assert-image-size.yml @@ -0,0 +1,19 @@ +name: Test assert-image-size action + +on: + workflow_call: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Test scripts + run: ./assert-image-size/test_scripts.sh + + - name: Run assert-image-size + uses: ./assert-image-size + with: + image: hazelcast/hazelcast:5.0.1-slim diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bb9c234..2b823ef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,10 @@ jobs: - name: Checkout uses: actions/checkout@v6 + test-assert-image-size: + uses: ./.github/workflows/test-assert-image-size.yml + secrets: inherit + test-check-base-images: uses: ./.github/workflows/test-check-base-images.yml @@ -44,6 +48,7 @@ jobs: assert-all-jobs-succeeded: runs-on: ubuntu-latest needs: + - test-assert-image-size - test-check-base-images - test-check-if-latest-lts-release - test-check-redhat-service-status diff --git a/assert-image-size/README.md b/assert-image-size/README.md new file mode 100644 index 0000000..0d90cda --- /dev/null +++ b/assert-image-size/README.md @@ -0,0 +1,9 @@ +# assert-image-size + +A GitHub Action that validates image isn't excessively large / wasting space using [`dive`](https://github.com/wagoodman/dive). + +Docker images are built of overlaid [layers](https://docs.docker.com/get-started/docker-concepts/building-images/understanding-image-layers), building on top of one-another. When downloading an image, each layer is downloaded. + +If one layer contains a file that is subsequently removed or modified in a subsequent layer, this intermediate state will still be present in the layer to be downloaded, bloating the overall image. An example of this occurred in . + +This action asserts that the amount of wasted space in an image is below a % threshold. diff --git a/assert-image-size/action.yml b/assert-image-size/action.yml new file mode 100644 index 0000000..19d39ae --- /dev/null +++ b/assert-image-size/action.yml @@ -0,0 +1,23 @@ +name: Test image size +description: Test image isn't excessively large / wasting space + +inputs: + image: + description: Image name to test + required: true + minimum_efficiency: + description: Minimum efficiency percentage required - 0-1 scale + required: false + default: 0.95 + +runs: + using: "composite" + steps: + - shell: bash + run: | + . ${GITHUB_ACTION_PATH}/assert-image-size.functions.sh + + assert_image_size "${IMAGE}" "${MINIMUM_EFFICIENCY}" + env: + IMAGE: ${{ inputs.image }} + MINIMUM_EFFICIENCY: ${{ inputs.minimum_efficiency }} diff --git a/assert-image-size/assert-image-size.functions.sh b/assert-image-size/assert-image-size.functions.sh new file mode 100644 index 0000000..6c85973 --- /dev/null +++ b/assert-image-size/assert-image-size.functions.sh @@ -0,0 +1,23 @@ +function assert_image_size() { + local image=$1 + local minimum_efficiency=$2 + + local config_file + config_file=$(mktemp) + + # https://github.com/wagoodman/dive/blob/main/README.md#ci-integration + yq eval -n " + .rules.lowestEfficiency = ${minimum_efficiency} | + .rules.highestWastedBytes = \"disabled\" | + .rules.highestUserWastedPercent = \"disabled\" + " > "${config_file}" + + docker run --rm \ + --env CI=true \ + --volume /var/run/docker.sock:/var/run/docker.sock \ + --volume "${config_file}:/.dive-ci" \ + docker.io/wagoodman/dive:latest \ + "${image}" + + return $? +} diff --git a/assert-image-size/assert-image-size.functions_tests.sh b/assert-image-size/assert-image-size.functions_tests.sh new file mode 100644 index 0000000..4369e2e --- /dev/null +++ b/assert-image-size/assert-image-size.functions_tests.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -eu ${RUNNER_DEBUG:+-x} + +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +# Source the latest version of assert.sh unit testing library and include in current shell +source /dev/stdin <<< "$(curl --silent https://raw.githubusercontent.com/hazelcast/assert.sh/main/assert.sh)" + +. "$SCRIPT_DIR"/assert-image-size.functions.sh + +TESTS_RESULT=0 + +function assert_assert_image_size { + local image=$1 + local minimum_efficiency=$2 + local expected_exit_code=$3 + assert_image_size "${image}" "${minimum_efficiency}" && true + local actual_exit_code=$? + local msg="Expected exit code for \"${image}\" / \"${minimum_efficiency}\"" + assert_eq "${expected_exit_code}" "${actual_exit_code}" "${msg}" && log_success "${msg}" || TESTS_RESULT=$? +} + +log_header "Tests for assert_image_size" +# expected efficiency: 99.8541 % +assert_assert_image_size hazelcast/hazelcast:5.0.1-slim 0.95 0 +assert_assert_image_size hazelcast/hazelcast:5.0.1-slim 0.99999999999 1 + +assert_eq 0 "$TESTS_RESULT" "All tests should pass" diff --git a/assert-image-size/test_scripts.sh b/assert-image-size/test_scripts.sh new file mode 100755 index 0000000..deb6bf2 --- /dev/null +++ b/assert-image-size/test_scripts.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +find "$SCRIPT_DIR" -name "*_tests.sh" -print0 | xargs -0 -n1 bash