diff --git a/.dockerignore b/.dockerignore index e53007c..864179f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,2 @@ * !entrypoint.sh -.env* diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index 2b3d6d2..0000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Pull request -on: pull_request - -jobs: - commitsar: - runs-on: ubuntu-latest - name: Verify commit messages - steps: - - uses: actions/checkout@v1 - - name: Run commitsar - uses: docker://aevea/commitsar@sha256:caf5539dd03309a539906c7ad45c2ecc0ae86a1ee2bf5dc538d7986c523526f3 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 3260341..63f8c97 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -9,19 +9,11 @@ jobs: - uses: actions/checkout@master - name: GitHub Package Registry - uses: aevea/action-kaniko@master + uses: ohioit/action-kaniko@master with: - registry: docker.pkg.github.com + registry: ghcr.io password: ${{ secrets.GITHUB_TOKEN }} image: kaniko cache: true cache_registry: cache - - name: Dockerhub - uses: aevea/action-kaniko@master - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_PASSWORD }} - image: aevea/kaniko - cache: true - cache_registry: aevea/cache diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c749523..c8300c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,36 +1,28 @@ -name: Release -on: - push: - tags: - - "v*" +# name: Release +# on: +# push: +# tags: +# - "v*" -jobs: - release-notes: - name: Release Notes - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v1 +# jobs: +# release-notes: +# name: Release Notes +# runs-on: ubuntu-latest +# steps: +# - name: Check out code +# uses: actions/checkout@v1 - - name: Release Notary Action - uses: docker://aevea/release-notary@sha256:5eef3c539deb5397457a6acf001ef80df6004ec52bc4b8a0eac0577ad92759d0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# - name: Release Notary Action +# uses: docker://aevea/release-notary@sha256:5eef3c539deb5397457a6acf001ef80df6004ec52bc4b8a0eac0577ad92759d0 +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: GitHub Package Registry - uses: aevea/action-kaniko@master - with: - registry: docker.pkg.github.com - password: ${{ secrets.GITHUB_TOKEN }} - image: kaniko - cache: true - cache_registry: cache +# - name: GitHub Package Registry +# uses: ohioit/action-kaniko@master +# with: +# registry: ghcr.io +# password: ${{ secrets.GITHUB_TOKEN }} +# image: kaniko +# cache: true +# cache_registry: cache - - name: Dockerhub - uses: aevea/action-kaniko@master - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_PASSWORD }} - image: aevea/kaniko - cache: true - cache_registry: aevea/cache diff --git a/.gitignore b/.gitignore index f81b0aa..d45be4f 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ $RECYCLE.BIN/ .direnv .envrc .env +ais-build.yaml \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 445159b..f2f8893 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,12 +15,16 @@ RUN wget -O /kaniko/jq \ wget -O /crane.tar.gz \ https://github.com/google/go-containerregistry/releases/download/v0.1.1/go-containerregistry_Linux_x86_64.tar.gz && \ tar -xvzf /crane.tar.gz crane -C /kaniko && \ - rm /crane.tar.gz + rm /crane.tar.gz && \ + wget -O /yq_linux_386.tar.gz https://github.com/mikefarah/yq/releases/download/v4.15.1/yq_linux_386.tar.gz && \ + tar -zxvf /yq_linux_386.tar.gz ./yq_linux_386 -C /kaniko && \ + mv /kaniko/yq_linux_386 /kaniko/yq && \ + rm /yq_linux_386.tar.gz COPY entrypoint.sh / COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt ENTRYPOINT ["/entrypoint.sh"] -LABEL repository="https://github.com/aevea/action-kaniko" \ - maintainer="Alex Viscreanu " +LABEL repository="https://github.com/ohioit/action-kaniko" \ + maintainer="Ohio University" diff --git a/Makefile b/Makefile index dcf9cdd..197a730 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ build: - docker build -t aevea/kaniko . + docker build -t ohioit/kaniko . run: build docker run \ @@ -15,10 +15,10 @@ run: build -e INPUT_CACHE_REGISTRY \ -e INPUT_STRIP_TAG_PREFIX \ -e INPUT_SKIP_UNCHANGED_DIGEST \ - aevea/kaniko + ohioit/kaniko shell: build docker run \ -ti \ --entrypoint sh \ - aevea/kaniko + ohioit/kaniko diff --git a/README.md b/README.md index a09a7ca..4d9f71b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Kaniko image builder +**This is a fork that will build a list of images specified in a file.** + This Action uses the [kaniko](https://github.com/GoogleContainerTools/kaniko) executor instead of the docker daemon. Kaniko builds the image by extracting the filesystem of the base image, making the changes in the user space, snapshotting any change and appending it to the base image filesystem. @@ -21,7 +23,7 @@ jobs: - name: Kaniko build uses: aevea/action-kaniko@master with: - image: aevea/kaniko + image: ohioit/action-kaniko username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} cache: true @@ -56,6 +58,33 @@ the most used values. So, technically there is a single required argument | path | Path to the build context. Defaults to `.` | false | . | | tag_with_latest | Tags the built image with additional latest tag | false | | | target | Sets the target stage to build | false | | +| image_list | Comma separated list of images to build. The list has the following format: context image_name:tag | false | | +| image_list_file | Newline separated list of images to build. The list has the following format: context image_name tag | false | | + + +### image_list example + +Each element in the list must have the following format `build_context image_name:image_tag` or `build_context image_name image_tag`. + +```yaml +with: + image: ohioit/action-kaniko + image_list: . my_image_name:v1.0.0,resource my_image_name_2:v1.2.4 +``` + +### image_list_file example + +```yaml +with: + image: ohioit/action-kaniko + image_list: images +``` + +The content of the `images` file is shown below. Each line in the file must have the format `build_context image_name image_tag name_dockerfile`. +```prose +. my_image_name v1.0.0 Dockerfile +resource my_image_name_2 v1.2.4 Dockerfile.dev +``` **Here is where it gets specific, as the optional arguments become required depending on the registry targeted** @@ -66,7 +95,7 @@ In this case, the authentication credentials need to be passed via GitHub Action ```yaml with: - image: aevea/kaniko + image: ohioit/action-kaniko username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} ``` @@ -76,14 +105,14 @@ doesn't work. If you want to use caching with Dockerhub, create a `cache` reposi ```yaml with: - image: aevea/kaniko + image: ohioit/action-kaniko username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} cache: true cache_registry: aevea/cache ``` -### [docker.pkg.github.com](https://github.com/features/packages) +### [ghcr.io](https://github.com/features/packages) GitHub's docker registry is a bit special. It doesn't allow top-level images, so this action will prefix any image with the GitHub namespace. If you want to push your image like `aevea/action-kaniko/kaniko`, you'll only need to pass `kaniko` to this action. @@ -93,7 +122,7 @@ passed by default, it will have to be explicitly set up. ```yaml with: - registry: docker.pkg.github.com + registry: ghcr.io password: ${{ secrets.GITHUB_TOKEN }} image: kaniko ``` @@ -104,7 +133,7 @@ cache layers to that image instead ```yaml with: - registry: docker.pkg.github.com + registry: ghcr.io password: ${{ secrets.GITHUB_TOKEN }} image: kaniko cache: true @@ -129,7 +158,7 @@ with: registry: registry.gitlab.com username: ${{ secrets.GL_REGISTRY_USERNAME }} password: ${{ secrets.GL_REGISTRY_PASSWORD }} - image: aevea/kaniko + image: ohioit/action-kaniko ``` > NOTE: As GitLab's registry does support namespacing, Kaniko can natively push cached layers to it, so only `cache: true` is necessary to be @@ -140,7 +169,7 @@ with: registry: registry.gitlab.com username: ${{ secrets.GL_REGISTRY_USERNAME }} password: ${{ secrets.GL_REGISTRY_PASSWORD }} - image: aevea/kaniko + image: ohioit/action-kaniko cache: true ``` @@ -167,7 +196,7 @@ Example: ```yaml with: - registry: docker.pkg.github.com + registry: ghcr.io password: ${{ secrets.GITHUB_TOKEN }} image: kaniko strip_tag_prefix: pre- diff --git a/action.yml b/action.yml index bc41cfb..d81a65c 100644 --- a/action.yml +++ b/action.yml @@ -1,5 +1,5 @@ # kaniko.yml -name: "Kaniko builder" +name: "Ohio University Kaniko builder" description: "Build and push docker images using Kaniko" branding: icon: anchor @@ -19,8 +19,16 @@ inputs: description: "Password used for authentication to the Docker registry" required: false image: - description: "Image name" - required: true + description: "Image name. If specified the ais build config will be ignored." + required: false + image_list_file: + description: "A file containing a list of images to build. If this is specified the image, tag, and path parameters will be ignored." + required: false + build_config: + description: | + Path to a ais build config file. + required: false + default: './ais-build.yaml' tag: description: "Image tag" required: false diff --git a/entrypoint.sh b/entrypoint.sh index 0ea868c..0b80b55 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,77 +1,136 @@ #!/busybox/sh set -e pipefail +set +x -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_LATEST=${INPUT_TAG_WITH_LATEST:+"$IMAGE:latest"} -export IMAGE=$IMAGE:$TAG -export CONTEXT_PATH=${INPUT_PATH} +# Process a newline separted list of images where each line has the following format: +# context image_name tag dockerfile_name +# +# context - the kaniko image build context +# image_name - the image name +# tag - the tag to use for the image +# dockerfile_name - name of the Dockerfile +# e.g. +# resource cad/coi-resource v3.4.0 Dockerfile +# ui cad/coi-uiv 3.4.0 Dockerfile.ui +# +# All image will be pushed to the same registry +# function ensure() { if [ -z "${1}" ]; then - echo >&2 "Unable to find the ${2} variable. Did you set with.${2}?" + echo >&2 "Unable to find the ${2} variable. Did you set with: ${2}?" exit 1 fi } +function trim() { + local var="$*" + # remove leading whitespace characters + var="${var#"${var%%[![:space:]]*}"}" + # remove trailing whitespace characters + var="${var%"${var##*[![:space:]]}"}" + printf '%s' "$var" +} + +export REGISTRY=${INPUT_REGISTRY:-"docker.io"} +export USERNAME=${INPUT_USERNAME:-$GITHUB_ACTOR} +export PASSWORD=${INPUT_PASSWORD:-$GITHUB_TOKEN} + ensure "${REGISTRY}" "registry" ensure "${USERNAME}" "username" ensure "${PASSWORD}" "password" -ensure "${IMAGE}" "image" -ensure "${TAG}" "tag" -ensure "${CONTEXT_PATH}" "path" - -if [ "$REGISTRY" == "docker.pkg.github.com" ]; then - IMAGE_NAMESPACE="$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')" - export IMAGE="$IMAGE_NAMESPACE/$IMAGE" - export REPOSITORY="$IMAGE_NAMESPACE/$REPOSITORY" - - if [ ! -z $IMAGE_LATEST ]; then - export IMAGE_LATEST="$IMAGE_NAMESPACE/$IMAGE_LATEST" - fi - - if [ ! -z $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 [ ! -z $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 $GITHUB_WORKSPACE/$CONTEXT_PATH" -export DOCKERFILE="--dockerfile $CONTEXT_PATH/${INPUT_BUILD_FILE:-Dockerfile}" -export TARGET=${INPUT_TARGET:+"--target=$INPUT_TARGET"} -if [ ! -z $INPUT_SKIP_UNCHANGED_DIGEST ]; then - export DESTINATION="--digest-file digest --no-push --tarPath image.tar --destination $IMAGE" -else - export DESTINATION="--destination $IMAGE" - if [ ! -z $IMAGE_LATEST ]; then - export DESTINATION="$DESTINATION --destination $IMAGE_LATEST" +export BRANCH=$(echo ${GITHUB_REF} | sed -E "s/refs\/(heads|tags)\///g" | sed -e "s/\//-/g") + + +if [ -z "${INPUT_IMAGE_LIST_FILE:+x}" ] +then + export INPUT_IMAGE_LIST_FILE="${GITHUB_WORKSPACE}/.images.${$}" + + if [ ! -z "${INPUT_IMAGE:+x}" ] + then + echo "Using INPUT_IMAGE for list of images" + export TAG=${INPUT_TAG:-$([[ "$BRANCH" == "master" || "$BRANCH" == "main" ]] && echo latest || echo $BRANCH)} + export TAG=${TAG:-"latest"} + export TAG=${TAG#$INPUT_STRIP_TAG_PREFIX} + + echo "${INPUT_PATH} ${INPUT_IMAGE} ${TAG} ${INPUT_BUILD_FILE:-Dockerfile}" > ${INPUT_IMAGE_LIST_FILE} + else + echo "Using ais build image config" + yq eval '.images[] | .context + " " + .imageName + " " + .imageTag + " " + (.docker.dockerfile // "Dockerfile")' ais-build.yaml \ + > ${INPUT_IMAGE_LIST_FILE} fi +else + echo "Using INPUT_IMAGE_LIST_FILE for list of images" fi -export ARGS="$CACHE $CONTEXT $DOCKERFILE $TARGET $DESTINATION $INPUT_EXTRA_ARGS" +while read -r INPUT_PATH INPUT_IMAGE INPUT_TAG INPUT_DOCKERFILE +do + INPUT_PATH=$(trim ${INPUT_PATH}) + INPUT_IMAGE=$(trim ${INPUT_IMAGE}) + INPUT_TAG=$(trim ${INPUT_TAG}) + INPUT_DOCKERFILE=$(trim ${INPUT_DOCKERFILE}) -cat </kaniko/.docker/config.json + echo "Processing: context: [${INPUT_PATH}] image: [${INPUT_IMAGE}] tag: [${INPUT_TAG}] dockerfile: [${INPUT_DOCKERFILE}]" + + export IMAGE=${INPUT_IMAGE} + export TAG=${INPUT_TAG:-$([ "$BRANCH" == "master" ] && echo latest || echo $BRANCH)} + export TAG=${TAG:-"latest"} + export TAG=${TAG#$INPUT_STRIP_TAG_PREFIX} + export REPOSITORY=$IMAGE + export IMAGE_LATEST=${INPUT_TAG_WITH_LATEST:+"$IMAGE:latest"} + export IMAGE=$IMAGE:$TAG + export CONTEXT_PATH=${INPUT_PATH} + + ensure "${IMAGE}" "image" + ensure "${TAG}" "tag" + ensure "${CONTEXT_PATH}" "path" + + if [ "$REGISTRY" == "ghcr.io" ]; then + IMAGE_NAMESPACE="$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')" + export IMAGE="$IMAGE_NAMESPACE/$IMAGE" + export REPOSITORY="$IMAGE_NAMESPACE/$REPOSITORY" + + if [ ! -z $IMAGE_LATEST ]; then + export IMAGE_LATEST="$IMAGE_NAMESPACE/$IMAGE_LATEST" + fi + + if [ ! -z $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 [ ! -z $IMAGE_LATEST ]; then + export IMAGE_LATEST="$REGISTRY/$IMAGE_LATEST" + fi + fi + + export CONTEXT="--context $GITHUB_WORKSPACE/$CONTEXT_PATH" + export DOCKERFILE="--dockerfile $CONTEXT_PATH/${INPUT_DOCKERFILE}" + export TARGET=${INPUT_TARGET:+"--target=$INPUT_TARGET"} + + if [ ! -z $INPUT_SKIP_UNCHANGED_DIGEST ]; then + export DESTINATION="--digest-file digest --no-push --tarPath image.tar --destination $IMAGE" + else + export DESTINATION="--destination $IMAGE" + if [ ! -z $IMAGE_LATEST ]; then + export DESTINATION="$DESTINATION --destination $IMAGE_LATEST" + fi + fi + + export ARGS="$CACHE $CONTEXT $DOCKERFILE $TARGET $DESTINATION $INPUT_EXTRA_ARGS" + + cat </kaniko/.docker/config.json { "auths": { "https://${REGISTRY}": { @@ -82,34 +141,35 @@ cat </kaniko/.docker/config.json } EOF -# https://github.com/GoogleContainerTools/kaniko/issues/1349 -/kaniko/executor --reproducible --force $ARGS + # https://github.com/GoogleContainerTools/kaniko/issues/1349 + /kaniko/executor --reproducible --force $ARGS -if [ ! -z $INPUT_SKIP_UNCHANGED_DIGEST ]; then - export DIGEST=$(cat digest) + if [ ! -z $INPUT_SKIP_UNCHANGED_DIGEST ]; then + export DIGEST=$(cat digest) - if [ "$REGISTRY" == "docker.pkg.github.com" ]; then - wget -q -O manifest --header "Authorization: Basic $(echo -n $USERNAME:$PASSWORD | base64)" https://docker.pkg.github.com/v2/$REPOSITORY/manifests/latest || true - export REMOTE="sha256:$(cat manifest | sha256sum | awk '{ print $1 }')" - else - export REMOTE=$(reg digest -u $USERNAME -p $PASSWORD $REGISTRY/$REPOSITORY | tail -1) - fi + if [ "$REGISTRY" == "ghcr.io" ]; then + wget -q -O manifest --header "Authorization: Basic $(echo -n $USERNAME:$PASSWORD | base64)" https://ghcr.io/v2/$REPOSITORY/manifests/latest || true + export REMOTE="sha256:$(cat manifest | sha256sum | awk '{ print $1 }')" + else + export REMOTE=$(reg digest -u $USERNAME -p $PASSWORD $REGISTRY/$REPOSITORY | tail -1) + fi - if [ "$DIGEST" == "$REMOTE" ]; then - echo "Digest hasn't changed, skipping, $DIGEST" + if [ "$DIGEST" == "$REMOTE" ]; then + echo "Digest hasn't changed, skipping, $DIGEST" + echo "Done 🎉️" + exit 0 + fi + + echo "Pushing image..." + + /kaniko/crane auth login $REGISTRY -u $USERNAME -p $PASSWORD + /kaniko/crane push image.tar $IMAGE + + if [ ! -z $IMAGE_LATEST ]; then + echo "Tagging latest..." + /kaniko/crane tag $IMAGE latest + fi + echo "Done 🎉️" - exit 0 fi - - echo "Pushing image..." - - /kaniko/crane auth login $REGISTRY -u $USERNAME -p $PASSWORD - /kaniko/crane push image.tar $IMAGE - - if [ ! -z $IMAGE_LATEST ]; then - echo "Tagging latest..." - /kaniko/crane tag $IMAGE latest - fi - - echo "Done 🎉️" -fi +done < ${INPUT_IMAGE_LIST_FILE} diff --git a/renovate.json b/renovate.json deleted file mode 100644 index f45d8f1..0000000 --- a/renovate.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": [ - "config:base" - ] -} diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..3e5f8b9 --- /dev/null +++ b/run.sh @@ -0,0 +1,10 @@ +# Use this to build and run the docker image locally + +set -e +WORKSPACE_DIR=/workspace +docker build -t action-kaniko ./ +docker run --rm \ + -w ${WORKSPACE_DIR} \ + -v $PWD/ais-build.yaml:${WORKSPACE_DIR}/ais-build.yaml \ + --env-file .env \ + action-kaniko \ No newline at end of file