diff --git a/.circleci/config.yml b/.circleci/config.yml index ef91144..b21946f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,4 +42,4 @@ workflows: requires: [orb-tools/publish] filters: tags: - only: /.*/ \ No newline at end of file + only: /.*/ diff --git a/.circleci/test-deploy.yml b/.circleci/test-deploy.yml index 7dc8138..b1908b2 100644 --- a/.circleci/test-deploy.yml +++ b/.circleci/test-deploy.yml @@ -11,11 +11,16 @@ promotion_requires: &promotion_requires test-credentials-store-docker, test-credentials-store-machine, test-credentials-store-macos, + test-credentials-store-docker-custom-tag, + test-credentials-store-machine-custom-tag, + test-credentials-store-macos-custom-tag, + test-hadolint-install, publish-machine, publish-docker-cache, publish-docker-cache-not-found, publish-docker-with-buildkit, publish-docker-multiple-tags, + publish-docker-env-var-image-param, test-pull, test-install-docker-tools-docker-latest, test-install-docker-tools-docker-old, @@ -23,19 +28,25 @@ promotion_requires: &promotion_requires test-install-docker-tools-macos-old, test-install-docker-tools-machine-latest, test-install-docker-tools-machine-old, + test-install-docker-tools-machine-arm, + test-install-docker-compose-with-checksums, + test-install-docker-compose-with-sha256, + test-install-docker-compose-with-checksums-and-sha256, test-docker-latest, test-docker-old, test-macos-latest, test-macos-old, test-machine-latest, test-machine-old, - test-build-command-workspace + test-build-command-workspace, + test-build-with-args, + test-build-bash-substitution ] filters: &filters tags: only: /.*/ - + orbs: build-tools: circleci/build-tools@3.0.0 docker: circleci/docker@dev:<> @@ -82,12 +93,17 @@ jobs: debug: type: boolean default: false + goss-architecture: + type: enum + default: amd64 + enum: [ amd64, arm64 ] executor: <> steps: - checkout - jq/install - docker/install-docker-tools: install-goss-dgoss: << parameters.install-goss >> + goss-architecture: << parameters.goss-architecture >> test-pull: executor: docker-latest steps: @@ -125,10 +141,14 @@ jobs: type: env_var_name docker-password: type: env_var_name + release-tag: + type: string + default: "" executor: <> steps: - docker/install-docker-credential-helper: helper-name: <> + release-tag: <> - docker/configure-docker-credentials-store: helper-name: <> - run: @@ -179,6 +199,30 @@ jobs: ls exit 1 fi + test-build-with-args: + docker: + - image: cimg/base:stable + steps: + - checkout + - setup_remote_docker + - docker/build: + dockerfile: test3.Dockerfile + image: cpeorbtesting/docker-orb-test + tag: $CIRCLE_BUILD_NUM-$CIRCLE_SHA1 + extra_build_args: --build-arg COMMIT_HASH=$CIRCLE_SHA1 + test-build-bash-substitution: + docker: + - image: cimg/base:stable + environment: + DOCKER_ACCOUNT: CPEOrbTesting + DOCKER_REPO: docker_orb_test + steps: + - checkout + - setup_remote_docker + - docker/build: + dockerfile: test3.Dockerfile + image: ${DOCKER_ACCOUNT,,}/${DOCKER_REPO/_/-} + tag: ${CIRCLE_BUILD_NUM}-${CIRCLE_SHA1:0:10} test-dockerlint: docker: - image: cimg/node:17.7.2 @@ -198,7 +242,54 @@ jobs: debug: <> dockerfile: <> treat-warnings-as-errors: <> + test-install-docker-compose: + parameters: + docker-compose-version: + type: string + default: latest + description: > + Version of `docker-compose` to install, defaults to the latest stable release. + If specifying a version other than latest, provide a full release tag, + as listed at https://github.com/docker/compose/releases or + https://api.github.com/repos/docker/compose/releases, e.g., `1.23.1`. + + install-dir: + type: string + default: /usr/local/bin + description: > + Directory in which to install `docker-compose` + executor: + type: executor + executor: << parameters.executor >> + + steps: + - docker/install-docker + - docker/install-docker-compose: + version: << parameters.docker-compose-version>> + install-dir: << parameters.install-dir>> + + test-hadolint-install: + parameters: + executor: + type: executor + executor: << parameters.executor >> + steps: + - checkout + - docker/hadolint: + dockerfiles: test.Dockerfile + ignore-rules: DL4005,DL3008,DL3009,DL3015 + trusted-registries: docker.io,my-company.com:5000 + - run: + name: Verifying hadolint install + command: | + if ! command -v hadolint; then + echo "hadolint not installed" + exit 1 + else + echo "hadolint installed successfully" + exit 0 + fi workflows: test-deploy: jobs: @@ -207,6 +298,13 @@ workflows: ignore-rules: DL4005,DL3008,DL3009,DL3015,DL3059 trusted-registries: docker.io,my-company.com:5000 dockerfiles: test.Dockerfile:test2.Dockerfile + failure-threshold: none + filters: *filters + - test-hadolint-install: + name: test-install-hadolint-<< matrix.executor >> + matrix: + parameters: + executor: [docker-latest, machine-arm, macos-latest] filters: *filters - test-dockerlint: name: dockerlint @@ -221,6 +319,25 @@ workflows: requires: - test-create-workspace filters: *filters + - test-build-with-args: + filters: *filters + + # begin test-install-docker-compose + - test-install-docker-compose: + name: test-install-docker-compose-with-checksums + executor: docker-latest + filters: *filters + - test-install-docker-compose: + name: test-install-docker-compose-with-sha256 + docker-compose-version: v2.0.1 + executor: docker-latest + filters: *filters + - test-install-docker-compose: + name: test-install-docker-compose-with-checksums-and-sha256 + docker-compose-version: v2.9.0 + executor: docker-latest + filters: *filters + # end test-install-docker-compose # begin test-check-command - test-check-command: @@ -276,6 +393,33 @@ workflows: pre-steps: - docker/install-docker filters: *filters + - test-credentials-store: + name: test-credentials-store-docker-custom-tag + executor: docker-latest + context: CPE-orb-docker-testing + helper-name: pass + docker-username: DOCKER_USER + docker-password: DOCKER_PASS + release-tag: "v0.6.4" + filters: *filters + - test-credentials-store: + name: test-credentials-store-machine-custom-tag + executor: machine-latest + context: CPE-orb-docker-testing + docker-username: DOCKER_USER + docker-password: DOCKER_PASS + release-tag: "v0.6.4" + filters: *filters + - test-credentials-store: + name: test-credentials-store-macos-custom-tag + executor: macos-latest + context: CPE-orb-docker-testing + docker-username: DOCKER_USER + docker-password: DOCKER_PASS + release-tag: "v0.6.4" + pre-steps: + - docker/install-docker + filters: *filters # end test-credentials-store # begin docker/publish @@ -375,6 +519,42 @@ workflows: docker-password: DOCKER_PASS use-docker-credentials-store: true filters: *filters + - docker/publish: + pre-steps: + - run: echo 'export DOCKER_USERNAME=cpeorbtesting' >> $BASH_ENV + - run: echo 'export DOCKER_NAME=docker-orb-test' >> $BASH_ENV + name: publish-docker-env-var-image-param + executor: docker-latest + context: CPE-orb-docker-testing + use-remote-docker: true + dockerfile: test.Dockerfile + image: $DOCKER_USERNAME/$DOCKER_NAME + tag: $CIRCLE_SHA1,$CIRCLE_BUILD_NUM + docker-username: DOCKER_USER + docker-password: DOCKER_PASS + use-docker-credentials-store: true + filters: *filters + - docker/publish: + pre-steps: + - run: + name: Export env vars + command: | + echo 'export DOCKER_USERNAME=cpeorbtesting' >> $BASH_ENV + echo 'export DOCKER_NAME=docker-orb-test' >> $BASH_ENV + echo 'export DOCKERFILE=test.Dockerfile' >> $BASH_ENV + echo 'export REGISTRY=docker.io' >> $BASH_ENV + name: publish-docker-env-var-all-params + executor: docker-latest + context: CPE-orb-docker-testing + use-remote-docker: true + dockerfile: $DOCKERFILE + image: $DOCKER_USERNAME/$DOCKER_NAME + tag: $CIRCLE_SHA1,$CIRCLE_BUILD_NUM + docker-username: DOCKER_USER + docker-password: DOCKER_PASS + use-docker-credentials-store: true + registry: $REGISTRY + filters: *filters # end docker/publish # begin test-install-docker-tools @@ -383,6 +563,14 @@ workflows: matrix: parameters: executor: [docker-latest, docker-old, machine-latest, machine-old] + goss-architecture: [amd64] + filters: *filters + - test-install-docker-tools: + name: test-install-docker-tools-<< matrix.executor >> + matrix: + parameters: + executor: [machine-arm] + goss-architecture: [arm64] filters: *filters - test-install-docker-tools: name: test-install-docker-tools-<< matrix.executor >> @@ -392,7 +580,7 @@ workflows: install-goss: false filters: *filters # end test-install-docker-tools - + # begin test - test: name: test-<< matrix.executor >> @@ -427,10 +615,10 @@ workflows: executors: macos-old: macos: - xcode: 10.3.0 + xcode: 11.7.0 macos-latest: macos: - xcode: 13.1.0 + xcode: 14.0.0 docker-old: docker: - image: cimg/base:2020.08-20.04 @@ -443,3 +631,9 @@ executors: machine-latest: machine: image: ubuntu-2004:current + machine-arm: + resource_class: arm.medium + machine: + image: ubuntu-2004:202101-01 + +# VS Code Extension Version: 1.3.0 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index acdbb28..b8bc0b9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # Ping these folks when changes are made to this repository -* @CircleCI-Public/cpeng +* @CircleCI-Public/orb-publishers diff --git a/src/@orb.yml b/src/@orb.yml index 7d76978..187784c 100644 --- a/src/@orb.yml +++ b/src/@orb.yml @@ -8,6 +8,5 @@ display: source_url: https://github.com/CircleCI-Public/docker-orb orbs: - bt: circleci/build-tools@2.6.3 - jq: circleci/jq@2.0 - orb-tools: circleci/orb-tools@9.1 + bt: circleci/build-tools@3.0 + jq: circleci/jq@2.2 diff --git a/src/commands/build.yml b/src/commands/build.yml index 9d4fd1c..8f1a40c 100644 --- a/src/commands/build.yml +++ b/src/commands/build.yml @@ -112,6 +112,11 @@ steps: steps: - run: echo 'export DOCKER_BUILDKIT=1' >> $BASH_ENV + - when: + condition: <> + steps: + - run: echo 'PARAM_EXTRA_BUILD_ARGS="<>"' >> $BASH_ENV + - when: condition: <> steps: @@ -126,9 +131,9 @@ steps: PARAM_DOCKER_CONTEXT: <> PARAM_DOCKERFILE_NAME: <> PARAM_DOCKERFILE_PATH: <> - PARAM_EXTRA_BUILD_ARGS: <> PARAM_IMAGE: <> PARAM_REGISTRY: <> PARAM_TAG: <> PARAM_USE_BUILDKIT: <> + SCRIPT_UTILS: <> command: <> diff --git a/src/commands/check.yml b/src/commands/check.yml index b9b31ea..4732cc9 100644 --- a/src/commands/check.yml +++ b/src/commands/check.yml @@ -29,12 +29,6 @@ parameters: This option is only supported on Ubuntu/Debian/macOS platforms. steps: - - orb-tools/check-env-var-param: - param: <> - - - orb-tools/check-env-var-param: - param: <> - - when: condition: <> steps: @@ -47,4 +41,5 @@ steps: PARAM_REGISTRY: <> PARAM_DOCKER_USERNAME: <> PARAM_DOCKER_PASSWORD: <> + SCRIPT_UTILS: <> command: <> diff --git a/src/commands/configure-docker-credentials-store.yml b/src/commands/configure-docker-credentials-store.yml index 87b58fa..a7e9195 100644 --- a/src/commands/configure-docker-credentials-store.yml +++ b/src/commands/configure-docker-credentials-store.yml @@ -24,4 +24,5 @@ steps: environment: PARAM_HELPER_NAME: "<>" PARAM_DOCKER_CONFIG_PATH: "<>" + SCRIPT_UTILS: <> command: <> diff --git a/src/commands/dockerlint.yml b/src/commands/dockerlint.yml index d6ff984..6023b1b 100644 --- a/src/commands/dockerlint.yml +++ b/src/commands/dockerlint.yml @@ -30,4 +30,5 @@ steps: PARAM_DEBUG: <> PARAM_TREAT_WARNING_AS_ERRORS: <> PARAM_DOCKERFILE: <> + SCRIPT_UTILS: <> command: <> diff --git a/src/commands/hadolint.yml b/src/commands/hadolint.yml index 8459c1f..812d4e0 100644 --- a/src/commands/hadolint.yml +++ b/src/commands/hadolint.yml @@ -1,6 +1,6 @@ description: > - Lint a given Dockerfile using a hadolint Docker image: - https://hub.docker.com/r/hadolint/hadolint + Lint a given Dockerfile using hadolint. If the hadolint docker image + is not used, hadolint will be installed. parameters: dockerfiles: @@ -28,6 +28,14 @@ parameters: `docker.io,my-company.com:5000`); if set, return an error if Dockerfiles use any images from registries not included in this list + failure-threshold: + type: enum + default: "info" + description: > + Hadolint threshold level to fail on. Exit with failure code only when rules + with a severity equal to or above THRESHOLD are violated + enum: [ "error", "warning", "info", "style", "ignore", "none" ] + steps: - run: name: Lint <> with hadolint @@ -35,4 +43,6 @@ steps: PARAM_DOCKERFILES: <> PARAM_IGNORE_RULES: <> PARAM_TRUSTED_REGISTRIES: <> + PARAM_FAILURE_THRESHOLD: <> + SCRIPT_UTILS: <> command: <> diff --git a/src/commands/install-docker-compose.yml b/src/commands/install-docker-compose.yml index 3afa327..6369e7f 100644 --- a/src/commands/install-docker-compose.yml +++ b/src/commands/install-docker-compose.yml @@ -10,7 +10,8 @@ parameters: Version of `docker-compose` to install, defaults to the latest stable release. If specifying a version other than latest, provide a full release tag, as listed at https://github.com/docker/compose/releases or - https://api.github.com/repos/docker/compose/releases, e.g., `1.23.1`. + https://api.github.com/repos/docker/compose/releases, e.g., `v2.10.0`. + Only versions equal or above v2.0.1 are supported. install-dir: type: string @@ -24,4 +25,5 @@ steps: environment: PARAM_DOCKER_COMPOSER_VERSION: << parameters.version >> PARAM_INSTALL_DIR: <> + SCRIPT_UTILS: <> command: <> diff --git a/src/commands/install-docker-credential-helper.yml b/src/commands/install-docker-credential-helper.yml index d613656..1fa9749 100644 --- a/src/commands/install-docker-credential-helper.yml +++ b/src/commands/install-docker-credential-helper.yml @@ -26,4 +26,5 @@ steps: environment: PARAM_HELPER_NAME: << parameters.helper-name >> PARAM_RELEASE_TAG: << parameters.release-tag >> + SCRIPT_UTILS: <> command: << include(scripts/install-docker-credential-helper.sh) >> diff --git a/src/commands/install-docker-tools.yml b/src/commands/install-docker-tools.yml index 7fa5c37..8a991e4 100644 --- a/src/commands/install-docker-tools.yml +++ b/src/commands/install-docker-tools.yml @@ -102,6 +102,13 @@ parameters: description: > Extra output for orb developers + goss-architecture: + type: enum + default: amd64 + enum: [ amd64, arm64 ] + description: > + Which Goss architecture to use. Supports `arm64` architecture from `v0.3.18` and newer. + steps: - when: condition: <> @@ -131,3 +138,4 @@ steps: version: <> install-dir: <> debug: <> + architecture: <> diff --git a/src/commands/install-docker.yml b/src/commands/install-docker.yml index be92c32..1f4d1e6 100644 --- a/src/commands/install-docker.yml +++ b/src/commands/install-docker.yml @@ -25,4 +25,5 @@ steps: environment: PARAM_VERSION: << parameters.version >> PARAM_INSTALL_DIR: << parameters.install-dir >> + SCRIPT_UTILS: <> command: << include(scripts/install-docker.sh) >> diff --git a/src/commands/install-dockerize.yml b/src/commands/install-dockerize.yml index 22e995c..4592248 100644 --- a/src/commands/install-dockerize.yml +++ b/src/commands/install-dockerize.yml @@ -23,4 +23,5 @@ steps: environment: PARAM_VERSION: << parameters.version >> PARAM_INSTALL_DIR: << parameters.install-dir >> + SCRIPT_UTILS: <> command: << include(scripts/install-dockerize.sh) >> diff --git a/src/commands/install-goss.yml b/src/commands/install-goss.yml index 5267650..7bc4da5 100644 --- a/src/commands/install-goss.yml +++ b/src/commands/install-goss.yml @@ -27,6 +27,13 @@ parameters: description: > Extra output for orb developers + architecture: + type: enum + default: amd64 + enum: [ amd64, arm64 ] + description: > + Which Goss architecture to use. Supports `arm64` architecture from `v0.3.18` and newer. + steps: - run: name: Install Goss and dgoss @@ -34,4 +41,6 @@ steps: PARAM_VERSION: <> PARAM_INSTALL_DIR: <> PARAM_DEBUG: <> + PARAM_ARCHITECTURE: <> + SCRIPT_UTILS: <> command: << include(scripts/install-goss.sh) >> diff --git a/src/commands/pull.yml b/src/commands/pull.yml index 53dbf83..939e539 100644 --- a/src/commands/pull.yml +++ b/src/commands/pull.yml @@ -19,4 +19,5 @@ steps: environment: PARAM_IMAGES: <> PARAM_IGNORE_DOCKER_PULL_ERROR: <> + SCRIPT_UTILS: <> command: << include(scripts/pull.sh) >> diff --git a/src/commands/push.yml b/src/commands/push.yml index da17bdc..2b20871 100644 --- a/src/commands/push.yml +++ b/src/commands/push.yml @@ -27,21 +27,12 @@ parameters: default: "" steps: - - deploy: + - run: name: <> environment: PARAM_REGISTRY: <> PARAM_IMAGE: <> PARAM_TAG: <> PARAM_DIGEST_PATH: <> - command: | - IFS="," read -ra DOCKER_TAGS \<<< "<< parameters.tag >>" - for tag in "${DOCKER_TAGS[@]}"; do - docker push <>/<< parameters.image>>:${tag} - done - - if [ -n "<>" ]; then - mkdir -p "$(dirname <>)" - IFS="," read -ra DOCKER_TAGS \<<< "<< parameters.tag >>" - docker image inspect --format="{{index .RepoDigests 0}}" <>/<< parameters.image>>:"${DOCKER_TAGS[0]}" > "<>" - fi + SCRIPT_UTILS: <> + command: << include(scripts/push.sh) >> diff --git a/src/commands/update-description.yml b/src/commands/update-description.yml index 6d5549f..9a58506 100644 --- a/src/commands/update-description.yml +++ b/src/commands/update-description.yml @@ -36,7 +36,8 @@ parameters: Name of environment variable storing your Docker password steps: - - deploy: + - jq/install + - run: name: Update description environment: PARAM_README: <> @@ -45,4 +46,5 @@ steps: PARAM_IMAGE: <> PARAM_DOCKER_USERNAME: <> PARAM_DOCKER_PASSWORD: <> + SCRIPT_UTILS: <> command: << include(scripts/update-description.sh) >> diff --git a/src/examples/with-bash-substitution.yml b/src/examples/with-bash-substitution.yml new file mode 100644 index 0000000..e49d215 --- /dev/null +++ b/src/examples/with-bash-substitution.yml @@ -0,0 +1,15 @@ +description: > + Build/publish a Docker image bash substitution + +usage: + version: 2.1 + + orbs: + docker: circleci/docker@x.y.z + + workflows: + build-docker-image-only: + jobs: + - docker/publish: + image: ${CIRCLE_PROJECT_USERNAME,,}/${CIRCLE_PROJECT_REPONAME/_/-} + tag: ${CIRCLE_SHA1:0:10} diff --git a/src/jobs/hadolint.yml b/src/jobs/hadolint.yml index 136e239..fcf893d 100644 --- a/src/jobs/hadolint.yml +++ b/src/jobs/hadolint.yml @@ -47,6 +47,14 @@ parameters: `docker.io,my-company.com:5000`); if set, return an error if Dockerfiles use any images from registries not included in this list + failure-threshold: + type: enum + default: "info" + description: > + Hadolint threshold level to fail on. Exit with failure code only when rules + with a severity equal to or above THRESHOLD are violated + enum: [ "error", "warning", "info", "style", "ignore", "none" ] + hadolint-tag: type: string default: latest-debian @@ -89,3 +97,4 @@ steps: dockerfiles: <> ignore-rules: <> trusted-registries: <> + failure-threshold: <> diff --git a/src/jobs/publish.yml b/src/jobs/publish.yml index ddc63cc..bc2e0a4 100644 --- a/src/jobs/publish.yml +++ b/src/jobs/publish.yml @@ -19,7 +19,7 @@ parameters: remote-docker-version: type: string - default: "17.09.0-ce" + default: "20.10.18" description: > Pick remote Docker engine version. Available versions can be found at: https://circleci.com/docs/2.0/building-docker-images/#docker-version. diff --git a/src/scripts/build.sh b/src/scripts/build.sh index 76816a7..d49167e 100644 --- a/src/scripts/build.sh +++ b/src/scripts/build.sh @@ -1,10 +1,14 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + DOCKER_TAGS_ARG="" parse_tags_to_docker_arg() { # Set comma as the new delimiter for the scope of this function. - local IFS="," + local IFS="," # Split tags into an array based on IFS delimiter. read -ra tags <<< "$PARAM_TAG" @@ -20,10 +24,8 @@ parse_tags_to_docker_arg() { done # Set IFS to null to stop "," from breaking bash substitution - local old_ifs="$IFS" local IFS= DOCKER_TAGS_ARG="$(eval echo $docker_arg)" - local IFS="$old_ifs" } pull_images_from_cache() { @@ -51,12 +53,13 @@ if [ -n "$PARAM_CACHE_FROM" ]; then fi build_args=( - "--file=$PARAM_DOCKERFILE_PATH/$PARAM_DOCKERFILE_NAME" - "$DOCKER_TAGS_ARG" + "--file=$PARAM_DOCKERFILE_PATH/$PARAM_DOCKERFILE_NAME" + "$DOCKER_TAGS_ARG" ) if [ -n "$PARAM_EXTRA_BUILD_ARGS" ]; then - build_args+=("$PARAM_EXTRA_BUILD_ARGS") + extra_build_args="$(eval echo "$PARAM_EXTRA_BUILD_ARGS")" + build_args+=("$extra_build_args") fi if [ -n "$PARAM_CACHE_FROM" ]; then @@ -74,6 +77,7 @@ old_ifs="$IFS" IFS=' ' set -x +# shellcheck disable=SC2048 # We want word splitting here. docker build ${build_args[*]} set +x diff --git a/src/scripts/check.sh b/src/scripts/check.sh index b6c61cf..8ec8de4 100644 --- a/src/scripts/check.sh +++ b/src/scripts/check.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -echo "${!PARAM_DOCKER_PASSWORD}" | docker login -u "${!PARAM_DOCKER_USERNAME}" --password-stdin "$PARAM_REGISTRY" \ No newline at end of file +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + +echo "${!PARAM_DOCKER_PASSWORD}" | docker login -u "${!PARAM_DOCKER_USERNAME}" --password-stdin "$PARAM_REGISTRY" diff --git a/src/scripts/configure-docker-credentials-store.sh b/src/scripts/configure-docker-credentials-store.sh index 2500dbe..8eb1606 100644 --- a/src/scripts/configure-docker-credentials-store.sh +++ b/src/scripts/configure-docker-credentials-store.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + HELPER_NAME="$PARAM_HELPER_NAME" DOCKER_CONFIG_PATH="$(eval echo ${PARAM_DOCKER_CONFIG_PATH})" @@ -22,4 +26,4 @@ cat "$DOCKER_CONFIG_PATH" | >/tmp/docker-config-credsstore-update.json cat /tmp/docker-config-credsstore-update.json > "$DOCKER_CONFIG_PATH" -rm /tmp/docker-config-credsstore-update.json \ No newline at end of file +rm /tmp/docker-config-credsstore-update.json diff --git a/src/scripts/dockerlint.sh b/src/scripts/dockerlint.sh index 872029d..d5ec5f1 100644 --- a/src/scripts/dockerlint.sh +++ b/src/scripts/dockerlint.sh @@ -1,11 +1,15 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + if [[ $EUID == 0 ]]; then SUDO=""; else SUDO="sudo"; fi if ! command -v dockerlint &> /dev/null; then - if ! command -v npm &> /dev/null; then + if ! command -v npm &> /dev/null; then echo "npm is required to install dockerlint."; - echo "Consider running this command with an image that has node available: https://circleci.com/developer/images/image/cimg/node"; + echo "Consider running this command with an image that has node available: https://circleci.com/developer/images/image/cimg/node"; echo "Alternatively, use dockerlint's docker image: https://github.com/RedCoolBeans/dockerlint#docker-image." exit 1 fi @@ -21,4 +25,4 @@ if [ "$PARAM_TREAT_WARNING_AS_ERRORS" = true ]; then dockerlint -f "$PARAM_DOCKERFILE" -p else dockerlint -f "$PARAM_DOCKERFILE" -fi \ No newline at end of file +fi diff --git a/src/scripts/hadolint.sh b/src/scripts/hadolint.sh index 44378ee..17f88ca 100644 --- a/src/scripts/hadolint.sh +++ b/src/scripts/hadolint.sh @@ -1,27 +1,66 @@ +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + +if [[ $EUID == 0 ]]; then export SUDO=""; else export SUDO="sudo"; fi + +Install_Hadolint() { + if uname -a | grep "Darwin"; then + SYS_ENV_PLATFORM="Darwin" + brew install hadolint + elif uname -a | grep "x86_64 GNU/Linux"; then + export SYS_ENV_PLATFORM=Linux-x86_64 + elif uname -a | grep "aarch64 GNU/Linux"; then + export SYS_ENV_PLATFORM=Linux-arm64 + else + echo "This platform appears to be unsupported." + uname -a + exit 1 + fi + + if [ "${SYS_ENV_PLATFORM}" != "Darwin" ]; then + $SUDO wget -O /bin/hadolint "https://github.com/hadolint/hadolint/releases/latest/download/hadolint-${SYS_ENV_PLATFORM}" + $SUDO chmod +x /bin/hadolint + fi +} + +if ! command -v hadolint &> /dev/null; then + Install_Hadolint +fi + if [ -n "$PARAM_IGNORE_RULES" ]; then - readonly ignore_rules=$(printf '%s' "--ignore ${PARAM_IGNORE_RULES//,/ --ignore }") + ignore_rules=$(printf '%s' "--ignore ${PARAM_IGNORE_RULES//,/ --ignore }") + readonly ignore_rules fi + if [ -n "$PARAM_TRUSTED_REGISTRIES" ]; then - readonly trusted_registries=$(printf '%s' "--trusted-registry ${PARAM_TRUSTED_REGISTRIES//,/ --trusted-registry }") + trusted_registries=$(printf '%s' "--trusted-registry ${PARAM_TRUSTED_REGISTRIES//,/ --trusted-registry }") + readonly trusted_registries fi +failure_threshold=$(printf '%s' "--failure-threshold ${PARAM_FAILURE_THRESHOLD}") +readonly failure_threshold + printf '%s\n' "Running hadolint with the following options..." printf '%s\n' "$ignore_rules" printf '%s\n' "$trusted_registries" +printf '%s\n' "$failure_threshold" # use colon delimiters to create array readonly old_ifs="$IFS" IFS=":" -read -ra dockerfiles <<< "$PARAM_DOCKERFILES" +read -ra dockerfiles <<< "$PARAM_DOCKERFILES" IFS="$old_ifs" for dockerfile in "${dockerfiles[@]}"; do + set -x hadolint \ + ${PARAM_FAILURE_THRESHOLD:+$failure_threshold} \ ${PARAM_IGNORE_RULES:+$ignore_rules} \ ${PARAM_TRUSTED_REGISTRIES:+$trusted_registries} \ $dockerfile - + set +x printf '%s\n' "Success! $dockerfile linted; no issues found" -done \ No newline at end of file +done diff --git a/src/scripts/install-docker-compose.sh b/src/scripts/install-docker-compose.sh index 2a82b4e..5676e9f 100644 --- a/src/scripts/install-docker-compose.sh +++ b/src/scripts/install-docker-compose.sh @@ -1,5 +1,16 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + +trap_exit() { + # clean-up + printf '%s\n' "Cleaning up..." + [ -f "$DOCKER_SHASUM_FILENAME" ] && rm -f "$DOCKER_SHASUM_FILENAME" +} +trap trap_exit EXIT + # checking for root user if [[ $(id -u) -eq 0 ]]; then SUDO="" @@ -29,7 +40,7 @@ if command -v docker-compose &> /dev/null; then exit 0 else echo "A different version of docker-compose is installed ($(docker-compose --version)); removing it" - $SUDO rm -f "$(command -v docker-compose)"1 + $SUDO rm -f "$(command -v docker-compose)" fi fi @@ -42,32 +53,45 @@ else fi DOCKER_COMPOSE_BASE_URL="https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION" -DOCKER_COMPOSE_SHASUM_URL="$DOCKER_COMPOSE_BASE_URL/docker-compose-$PLATFORM-x86_64.sha256" +DOCKER_COMPOSE_RELEASES_HTML="$(curl -Ls --fail --retry 3 "https://github.com/docker/compose/releases/tag/$DOCKER_COMPOSE_VERSION")" +DOCKER_COMPOSE_RELEASE="docker-compose-$PLATFORM-x86_64" +DOCKER_SHASUM_FILENAME="checksum.txt" -# download binary and shasum -curl -O \ - --silent --show-error --location --fail --retry 3 \ - "$DOCKER_COMPOSE_SHASUM_URL" +# since v2.10.0, docker-compose doesn't have a ".sha256" file +# so we need to use the "checksums.txt" file instead +if grep --quiet "checksums.txt" <<< "$DOCKER_COMPOSE_RELEASES_HTML"; then + printf '%s\n' "Downloading \"checksums.txt\" to verify the binary's integrity." -FILENAME=$(cat docker-compose-$PLATFORM-x86_64.sha256 | awk '{ print $NF }' | sed 's/^\*//') + curl -o "$DOCKER_SHASUM_FILENAME" \ + --silent --location --retry 3 \ + "$DOCKER_COMPOSE_BASE_URL/checksums.txt" +else + printf '%s\n' "Downloading \"$DOCKER_COMPOSE_RELEASE.sha256\" to verify the binary's integrity." + + curl -o "$DOCKER_SHASUM_FILENAME" \ + --silent --location --retry 3 \ + "$DOCKER_COMPOSE_BASE_URL/$DOCKER_COMPOSE_RELEASE.sha256" +fi -curl -O \ - --silent --show-error --location --fail --retry 3 \ - "$DOCKER_COMPOSE_BASE_URL/$FILENAME" +# download docker-compose binary +curl -o "$DOCKER_COMPOSE_RELEASE" \ + --location --retry 3 \ + "$DOCKER_COMPOSE_BASE_URL/$DOCKER_COMPOSE_RELEASE" +# verify binary integrity using SHA-256 checksum set +e -grep "$FILENAME" docker-compose-$PLATFORM-x86_64.sha256 | sha256sum -c - +grep "$DOCKER_COMPOSE_RELEASE" "$DOCKER_SHASUM_FILENAME" | sha256sum -c - SHASUM_SUCCESS=$? set -e if [[ "$SHASUM_SUCCESS" -ne 0 ]]; then - echo "Checksum validation failed for $FILENAME" + echo "Checksum validation failed for $DOCKER_COMPOSE_RELEASE" exit 1 fi # install docker-compose -$SUDO mv "$FILENAME" "$PARAM_INSTALL_DIR"/docker-compose +$SUDO mv "$DOCKER_COMPOSE_RELEASE" "$PARAM_INSTALL_DIR"/docker-compose $SUDO chmod +x "$PARAM_INSTALL_DIR"/docker-compose # verify version -echo "$(docker-compose --version) has been installed to $(command -v docker-compose)" \ No newline at end of file +echo "$(docker-compose --version) has been installed to $(command -v docker-compose)" diff --git a/src/scripts/install-docker-credential-helper.sh b/src/scripts/install-docker-credential-helper.sh index af1600e..7039209 100644 --- a/src/scripts/install-docker-credential-helper.sh +++ b/src/scripts/install-docker-credential-helper.sh @@ -1,12 +1,19 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + HELPER_NAME="$PARAM_HELPER_NAME" +if uname | grep -q "Darwin"; then platform="darwin" +else platform="linux" +fi + +# Infer helper name from the platform if [ -z "${HELPER_NAME}" ]; then - if uname | grep -q "Darwin"; then - HELPER_NAME="osxkeychain" - else - HELPER_NAME="pass" + if [ "$platform" = "darwin" ]; then HELPER_NAME="osxkeychain" + else HELPER_NAME="pass" fi fi @@ -55,17 +62,30 @@ echo "Downloading credential helper $HELPER_FILENAME" BIN_PATH="/usr/local/bin" mkdir -p "$BIN_PATH" RELEASE_TAG="$PARAM_RELEASE_TAG" -RELEASE_VERSION=$(curl -Ls --fail --retry 3 -o /dev/null -w '%{url_effective}' "https://github.com/docker/docker-credential-helpers/releases/latest" | sed 's:.*/::') +base_url="https://github.com/docker/docker-credential-helpers/releases" +RELEASE_VERSION=$(curl -Ls --fail --retry 3 -o /dev/null -w '%{url_effective}' "$base_url/latest" | sed 's:.*/::') if [ -n "${RELEASE_TAG}" ]; then RELEASE_VERSION="${RELEASE_TAG}" fi -DOWNLOAD_URL="https://github.com/docker/docker-credential-helpers/releases/download/${RELEASE_VERSION}/${HELPER_FILENAME}-${RELEASE_VERSION}-amd64.tar.gz" -echo "Downloading from url: $DOWNLOAD_URL" -curl -L -o "${HELPER_FILENAME}_archive" "$DOWNLOAD_URL" -tar xvf "./${HELPER_FILENAME}_archive" -chmod +x "./$HELPER_FILENAME" +# Starting from v0.7.0, the release file name is changed to docker-credential--.- +# At the moment of writing, the amd64 binary does not have a variant suffix. But this might change in the future. +# https://github.com/CircleCI-Public/docker-orb/pull/156#discussion_r977920812 +minor_version="$(echo "$RELEASE_VERSION" | cut -d. -f2)" +download_base_url="$base_url/download/${RELEASE_VERSION}/${HELPER_FILENAME}-${RELEASE_VERSION}" +if [ "$minor_version" -gt 6 ]; then + DOWNLOAD_URL="$download_base_url.$platform-amd64" + echo "Downloading from url: $DOWNLOAD_URL" + curl -L -o "${HELPER_FILENAME}" "$DOWNLOAD_URL" +else + DOWNLOAD_URL="$download_base_url-amd64.tar.gz" + echo "Downloading from url: $DOWNLOAD_URL" + curl -L -o "${HELPER_FILENAME}_archive" "$DOWNLOAD_URL" + tar xvf "./${HELPER_FILENAME}_archive" + rm "./${HELPER_FILENAME}_archive" +fi + +chmod +x "./$HELPER_FILENAME" $SUDO mv "./$HELPER_FILENAME" "$BIN_PATH/$HELPER_FILENAME" "$BIN_PATH/$HELPER_FILENAME" version -rm "./${HELPER_FILENAME}_archive" \ No newline at end of file diff --git a/src/scripts/install-docker.sh b/src/scripts/install-docker.sh index e7f8538..98aee48 100644 --- a/src/scripts/install-docker.sh +++ b/src/scripts/install-docker.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + if [[ $EUID == 0 ]]; then export SUDO=""; else export SUDO="sudo"; fi # grab Docker version @@ -73,4 +77,4 @@ do done # verify version -echo "$(docker --version) has been installed to $(command -v docker)" \ No newline at end of file +echo "$(docker --version) has been installed to $(command -v docker)" diff --git a/src/scripts/install-dockerize.sh b/src/scripts/install-dockerize.sh index 2fdfb50..0db53ac 100644 --- a/src/scripts/install-dockerize.sh +++ b/src/scripts/install-dockerize.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + if [[ $EUID == 0 ]]; then export SUDO=""; else export SUDO="sudo"; fi # grab dockerize version @@ -45,4 +49,4 @@ $SUDO mv dockerize "$PARAM_INSTALL_DIR" $SUDO chmod +x "$PARAM_INSTALL_DIR"/dockerize # verify version -echo "dockerize $(dockerize --version) has been installed to $(command -v dockerize)" \ No newline at end of file +echo "dockerize $(dockerize --version) has been installed to $(command -v dockerize)" diff --git a/src/scripts/install-goss.sh b/src/scripts/install-goss.sh index 6d5d2c9..1a0b489 100644 --- a/src/scripts/install-goss.sh +++ b/src/scripts/install-goss.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + if [[ $EUID == 0 ]]; then export SUDO=""; else export SUDO="sudo"; fi # determine specified version @@ -38,9 +42,9 @@ fi # download/install # goss curl -O --silent --show-error --location --fail --retry 3 \ - "https://github.com/aelsabbahy/goss/releases/download/$VERSION/goss-linux-amd64" + "https://github.com/aelsabbahy/goss/releases/download/$VERSION/goss-linux-$PARAM_ARCHITECTURE" -$SUDO mv goss-linux-amd64 "$PARAM_INSTALL_DIR"/goss +$SUDO mv goss-linux-$PARAM_ARCHITECTURE "$PARAM_INSTALL_DIR"/goss $SUDO chmod +rx /usr/local/bin/goss # test/verify goss @@ -69,4 +73,4 @@ if curl --output /dev/null --silent --head --fail "$DGOSS_URL"; then else echo "No dgoss wrapper found for the selected version of Goss ($VERSION)..." echo "Goss installation will proceed, but to use dgoss, please try again with a newer version" -fi \ No newline at end of file +fi diff --git a/src/scripts/pull.sh b/src/scripts/pull.sh index 741f167..148e4dc 100644 --- a/src/scripts/pull.sh +++ b/src/scripts/pull.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + echo "$PARAM_IMAGES" | sed -n 1'p' | tr ',' '\n' | while read -r image; do echo "Pulling ${image}"; @@ -8,4 +12,4 @@ echo "$PARAM_IMAGES" | sed -n 1'p' | tr ',' '\n' | while read -r image; do else docker pull "${image}"; fi -done \ No newline at end of file +done diff --git a/src/scripts/push.sh b/src/scripts/push.sh index 70efb22..e95da4d 100644 --- a/src/scripts/push.sh +++ b/src/scripts/push.sh @@ -1,13 +1,24 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + IFS="," read -ra DOCKER_TAGS <<< "$PARAM_TAG" -for tag in "${DOCKER_TAGS[@]}"; do - docker push "$PARAM_REGISTRY"/"$PARAM_IMAGE":${tag} +image="$(eval echo "$PARAM_IMAGE")" + +for docker_tag in "${DOCKER_TAGS[@]}"; do + tag=$(eval echo "$docker_tag") + + set -x + docker push "$PARAM_REGISTRY"/"$image":"$tag" + set +x done if [ -n "$PARAM_DIGEST_PATH" ]; then mkdir -p "$(dirname "$PARAM_DIGEST_PATH")" IFS="," read -ra DOCKER_TAGS <<< "$PARAM_TAG" - docker image inspect --format="{{index .RepoDigests 0}}" "$PARAM_REGISTRY"/"$PARAM_IMAGE":"${DOCKER_TAGS[0]}" > "$PARAM_DIGEST_PATH" -fi \ No newline at end of file + tag=$(eval echo "${DOCKER_TAGS[0]}") + docker image inspect --format="{{index .RepoDigests 0}}" "$PARAM_REGISTRY"/"$image":"$tag" > "$PARAM_DIGEST_PATH" +fi diff --git a/src/scripts/update-description.sh b/src/scripts/update-description.sh index a1006c9..c2409f5 100644 --- a/src/scripts/update-description.sh +++ b/src/scripts/update-description.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# Import "utils.sh". +eval "$SCRIPT_UTILS" +expand_env_vars_with_prefix "PARAM_" + if [ "$PARAM_REGISTRY" != "docker.io" ]; then echo "Registry is not set to Docker Hub. Exiting" exit 1 @@ -7,16 +11,17 @@ fi USERNAME=${!PARAM_DOCKER_USERNAME} PASSWORD=${!PARAM_DOCKER_PASSWORD} +IMAGE="$(eval echo "$PARAM_IMAGE")" DESCRIPTION="$PARAM_PATH/$PARAM_README" PAYLOAD="username=$USERNAME&password=$PASSWORD" JWT=$(curl -s -d "$PAYLOAD" https://hub.docker.com/v2/users/login/ | jq -r .token) HEADER="Authorization: JWT $JWT" -URL="https://hub.docker.com/v2/repositories/$PARAM_IMAGE/" -STATUS=$(curl -s -o /dev/null -w '%{http_code}' -X PATCH -H "$HEADER" --data-urlencode full_description@$DESCRIPTION $URL) +URL="https://hub.docker.com/v2/repositories/$IMAGE/" +STATUS=$(curl -s -o /dev/null -w '%{http_code}' -X PATCH -H "$HEADER" -H 'Content-type: application/json' --data "{\"full_description\": $(jq -Rs '.' $DESCRIPTION)}" $URL) if [ $STATUS -ne 200 ]; then echo "Could not update image description" echo "Error code: $STATUS" exit 1 -fi \ No newline at end of file +fi diff --git a/src/scripts/utils.sh b/src/scripts/utils.sh new file mode 100644 index 0000000..c430167 --- /dev/null +++ b/src/scripts/utils.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Public: Expand the value from environment variables with given prefix. +# +# Takes a prefix as an argument and expands the value of the environment variables +# starting with the prefix. The expansion is done by using the eval command. +# +# $1 - Prefix used to filter the envinronment variables. +# +# Examples +# +# expand_env_vars_with_prefix "ORB_PARAM_" +# expand_env_vars_with_prefix "PARAM_" +# +# Returns 1 if no argument is provided or no environment variables were found with prefix. +# Returns 0 if the expansion was successful. +expand_env_vars_with_prefix() { + if [ "$#" -eq 0 ]; then + >&2 printf '%s\n' "Please provide a prefix to filter the envinronment variables." + return 1 + fi + + # Fetch parameters from the environment variables. + local prefix="$1" + local env_vars + env_vars="$(printenv | grep "^$prefix")" + + if [ -z "$env_vars" ]; then + >&2 printf '%s\n' "No environment variables found with the prefix: \"$prefix\"." + return 1 + fi + + while IFS= read -ra line; do + # Split the line into key and value. + local var_value="${line#*=}" + local var_name="${line%="$var_value"}" + + # Expand the value. + local expanded_value + expanded_value="$(eval echo "$var_value")" + + # The -v option assignes the output to a variable rather than printing it. + printf -v "$var_name" "%s" "$expanded_value" + done <<< "$env_vars" + return 0 +} diff --git a/test3.Dockerfile b/test3.Dockerfile new file mode 100644 index 0000000..e0d8db5 --- /dev/null +++ b/test3.Dockerfile @@ -0,0 +1,22 @@ +# vim:set ft=dockerfile: +# +# The Ubuntu-based CircleCI Docker Image. Only use Ubuntu Long-Term Support +# (LTS) releases. + +FROM ubuntu:18.04 + +LABEL maintainer="CircleCI " + +ARG COMMIT_HASH + +# Change default shell from Dash to Bash +RUN rm /bin/sh && ln -s /bin/bash /bin/sh + +RUN if [[ "${COMMIT_HASH}" =~ ^[0-9a-f]{5,40}$ ]]; then \ + echo "Success: COMMIT_HASH is valid commit hash"; \ + else \ + echo "Error: COMMIT_HASH is invalid commit hash"; \ + exit 1; \ + fi + +WORKDIR /root/project