From 9a69b1b4c6dbb49fe655d4643f77af5e7c0d89db Mon Sep 17 00:00:00 2001 From: Rob Date: Sun, 14 Jul 2024 00:48:13 +0200 Subject: [PATCH] Added action, docker entrypoint and updated workflow --- .gitea/workflows/build-image.yml | 4 +- action.yml | 69 ++++++++++++++++ entrypoint.sh | 136 +++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 action.yml create mode 100644 entrypoint.sh diff --git a/.gitea/workflows/build-image.yml b/.gitea/workflows/build-image.yml index b4aeb6f..2e1940f 100644 --- a/.gitea/workflows/build-image.yml +++ b/.gitea/workflows/build-image.yml @@ -25,4 +25,6 @@ jobs: major-version: ${{ env.major }} minor-version: ${{ env.minor }} revision-version: ${{ env.revision }} - image-name: ${{ env.image-name }} \ No newline at end of file + image-name: ${{ env.image-name }} + dockerfile: Dockerfile + workspace-path: ${{ github.workspace }} \ No newline at end of file diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..ac1bc2c --- /dev/null +++ b/action.yml @@ -0,0 +1,69 @@ +# kaniko.yml +name: "Kaniko builder" +description: "Build and push docker images using Kaniko" +branding: + icon: anchor + color: orange +inputs: + path: + description: Path to the build context + required: false + default: "." + workspace: + description: Base path to the build context + required: false + registry: + description: "Docker registry where the image will be pushed" + required: false + username: + description: "Username used for authentication to the Docker registry" + required: false + password: + description: "Password used for authentication to the Docker registry" + required: false + image: + description: "Image name" + required: true + tag: + description: "Image tag" + required: false + cache: + description: "Enables build cache" + required: false + cache_ttl: + description: "How long the cache should be considered valid" + required: false + cache_registry: + description: "Docker registry meant to be used as cache" + required: false + cache_directory: + description: "Filesystem path meant to be used as cache" + required: false + build_file: + description: "Dockerfile filename" + required: false + strip_tag_prefix: + description: "Prefix to be stripped from the tag" + required: false + extra_args: + description: "Additional arguments to be passed to the kaniko executor" + required: false + skip_unchanged_digest: + description: "Avoids pushing the image if the build generated the same digest" + required: false + tag_with_latest: + description: "Tags the built image with additional latest tag" + required: false + target: + description: Sets the target stage to build + required: false + debug: + description: Enables trace for entrypoint.sh + required: false +outputs: + image: + description: "Full reference to the built image with registry and tag" +runs: + using: "docker" + entrypoint: "/entrypoint.sh" + image: "docker://gitea.thebobo.nl/gitea-projects/kaniko:0.0.1" diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..141dd40 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,136 @@ +#!/busybox/sh +set -e pipefail +if [ "$INPUT_DEBUG" = "true" ]; then + set -o xtrace +fi + +export REGISTRY="${INPUT_REGISTRY:-"docker.io"}" +export IMAGE="$INPUT_IMAGE" +export BRANCH=$(echo "$GITHUB_REF" | sed -E "s/refs\/(heads|tags)\///g" | sed -e "s/\//-/g") +export TAG=${INPUT_TAG:-$([ "$BRANCH" = "master" ] && echo latest || echo "$BRANCH")} +export TAG="${TAG:-"latest"}" +export TAG="${TAG#$INPUT_STRIP_TAG_PREFIX}" +export USERNAME="${INPUT_USERNAME:-$GITHUB_ACTOR}" +export PASSWORD="${INPUT_PASSWORD:-$GITHUB_TOKEN}" +export REPOSITORY="$IMAGE" +export IMAGE="${IMAGE}:${TAG}" +export CONTEXT_PATH="$INPUT_PATH" +export WORKSPACE_PATH = "${INPUT_WORKSPACE:'.'}" + +if [ "$INPUT_TAG_WITH_LATEST" = "true" ]; then + export IMAGE_LATEST="${REPOSITORY}:latest" +fi + +ensure() { + if [ -z "${1}" ]; then + echo >&2 "Unable to find the ${2} variable. Did you set with.${2}?" + exit 1 + fi +} + +ensure "${REGISTRY}" "registry" +ensure "${USERNAME}" "username" +ensure "${PASSWORD}" "password" +ensure "${IMAGE}" "image" +ensure "${TAG}" "tag" +ensure "${CONTEXT_PATH}" "context path" +ensure "${WORKSPACE_PATH}" "workspace path" + + +if [ "$REGISTRY" = "ghcr.io" ]; then + IMAGE_NAMESPACE="$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')" + # Set `/` separator, unless image is pre-fixed with dash or slash + [ -n "$REPOSITORY" ] && [[ ! "$REPOSITORY" =~ ^[-/] ]] && SEPARATOR="/" + export IMAGE="$IMAGE_NAMESPACE$SEPARATOR$IMAGE" + export REPOSITORY="$IMAGE_NAMESPACE$SEPARATOR$REPOSITORY" + + if [ -n "$IMAGE_LATEST" ]; then + export IMAGE_LATEST="${IMAGE_NAMESPACE}/${IMAGE_LATEST}" + fi + + if [ -n "$INPUT_CACHE_REGISTRY" ]; then + export INPUT_CACHE_REGISTRY="${REGISTRY}/${IMAGE_NAMESPACE}/${INPUT_CACHE_REGISTRY}" + fi +fi + +if [ "$REGISTRY" = "docker.io" ]; then + export REGISTRY="index.${REGISTRY}/v1/" +else + export IMAGE="${REGISTRY}/${IMAGE}" + + if [ -n "$IMAGE_LATEST" ]; then + export IMAGE_LATEST="${REGISTRY}/${IMAGE_LATEST}" + fi +fi + +export CACHE="${INPUT_CACHE:+"--cache=true"}" +export CACHE="$CACHE"${INPUT_CACHE_TTL:+" --cache-ttl=$INPUT_CACHE_TTL"} +export CACHE="$CACHE"${INPUT_CACHE_REGISTRY:+" --cache-repo=$INPUT_CACHE_REGISTRY"} +export CACHE="$CACHE"${INPUT_CACHE_DIRECTORY:+" --cache-dir=$INPUT_CACHE_DIRECTORY"} +export CONTEXT="--context $WORKSPACE_PATH/$CONTEXT_PATH" +export DOCKERFILE="--dockerfile $CONTEXT_PATH/${INPUT_BUILD_FILE:-Dockerfile}" +export TARGET=${INPUT_TARGET:+"--target=$INPUT_TARGET"} +export DIGEST="--digest-file /kaniko/digest --image-name-tag-with-digest-file=/kaniko/image-tag-digest" + +if [ -n "$INPUT_SKIP_UNCHANGED_DIGEST" ]; then + export DESTINATION="--no-push --tarPath image.tar --destination $IMAGE" +else + export DESTINATION="--destination $IMAGE" + if [ -n "$IMAGE_LATEST" ]; then + export DESTINATION="$DESTINATION --destination $IMAGE_LATEST" + fi +fi + +export ARGS="$CACHE $CONTEXT $DOCKERFILE $TARGET $DIGEST $DESTINATION $INPUT_EXTRA_ARGS" + +cat </kaniko/.docker/config.json +{ + "auths": { + "https://${REGISTRY}": { + "username": "${USERNAME}", + "password": "${PASSWORD}" + } + } +} +EOF + +# https://github.com/GoogleContainerTools/kaniko/issues/1803 +# https://github.com/GoogleContainerTools/kaniko/issues/1349 +export IFS='' +# Removes a trailing new line +ARGS=$(echo "${ARGS}" | sed 's/\n*$//') +kaniko_cmd="/kaniko/executor ${ARGS} --reproducible --force" +echo "Running kaniko command ${kaniko_cmd}" +eval "${kaniko_cmd}" + +echo "image=$IMAGE" >> "$GITHUB_OUTPUT" +echo "digest=$(cat /kaniko/digest)" >> "$GITHUB_OUTPUT" +echo "image-tag-digest=$(cat /kaniko/image-tag-digest)" >> "$GITHUB_OUTPUT" + + +if [ -n "$INPUT_SKIP_UNCHANGED_DIGEST" ]; then + export DIGEST="$(cat /kaniko/digest)" + + /kaniko/crane auth login "$REGISTRY" -u "$USERNAME" -p "$PASSWORD" + + export REMOTE=$(crane digest "${REGISTRY}/${REPOSITORY}:latest") + + if [ "$DIGEST" = "$REMOTE" ]; then + echo "refreshed=false" >> "$GITHUB_OUTPUT" + echo "Digest hasn't changed, skipping, $DIGEST" + echo "Done 🎉️" + exit 0 + fi + + echo "Pushing image..." + + /kaniko/crane push image.tar "$IMAGE" + + if [ -n "$IMAGE_LATEST" ]; then + echo "Tagging latest..." + /kaniko/crane tag "$IMAGE" latest + fi + + echo "refreshed=false" >> "$GITHUB_OUTPUT" + echo "Done 🎉️" +fi