diff --git a/README.md b/README.md index d86ac03..91e3126 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,23 @@ with: workdir: mySubDirectory ``` +### buildargs +Use `buildargs` when you want to pass a list of environment variables as [build-args](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg). Identifiers are separated by comma. +All `buildargs` will be masked, so that they don't appear in the logs. + +```yaml +- name: Publish to Registry + uses: elgohr/Publish-Docker-Github-Action@master + env: + MY_FIRST: variableContent + MY_SECOND: variableContent + with: + name: myDocker/repository + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + buildargs: MY_FIRST,MY_SECOND +``` + ### cache Use `cache` when you have big images, that you would only like to build partially (changed layers). > CAUTION: This will cache the non changed parts forever. If you use this option, make sure that these parts will be updated by another job! diff --git a/entrypoint.sh b/entrypoint.sh index 0fbf07a..0cd1f19 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,76 +1,126 @@ #!/bin/sh set -e -echo "" # see https://github.com/actions/toolkit/issues/168 +function main() { + echo "" # see https://github.com/actions/toolkit/issues/168 -if [ -z "${INPUT_NAME}" ]; then - echo "Unable to find the repository name. Did you set with.name?" - exit 1 -fi + sanitize "${INPUT_NAME}" "name" + sanitize "${INPUT_USERNAME}" "username" + sanitize "${INPUT_PASSWORD}" "password" -if [ -z "${INPUT_USERNAME}" ]; then - echo "Unable to find the username. Did you set with.username?" - exit 1 -fi + translateDockerTag + DOCKERNAME="${INPUT_NAME}:${TAG}" -if [ -z "${INPUT_PASSWORD}" ]; then - echo "Unable to find the password. Did you set with.password?" - exit 1 -fi + if uses "${INPUT_WORKDIR}"; then + changeWorkingDirectory + fi -function translateTag() { - BRANCH=$(echo ${GITHUB_REF} | sed -e "s/refs\/heads\///g" | sed -e "s/\//-/g") - # if there is a tag inside the name already - if [ $(echo ${INPUT_NAME} | sed -e "s/://g") != ${INPUT_NAME} ]; then + echo ${INPUT_PASSWORD} | docker login -u ${INPUT_USERNAME} --password-stdin ${INPUT_REGISTRY} + + BUILDPARAMS="" + + if uses "${INPUT_DOCKERFILE}"; then + useCustomDockerfile + fi + if uses "${INPUT_BUILDARGS}"; then + addBuildArgs + fi + if uses "${INPUT_CACHE}"; then + useBuildCache + fi + + if uses "${INPUT_SNAPSHOT}"; then + pushWithSnapshot + else + pushWithoutSnapshot + fi + echo ::set-output name=tag::"${TAG}" + + docker logout +} + +function sanitize() { + if [ -z "${1}" ]; then + >&2 echo "Unable to find the ${2}. Did you set with.${2}?" + exit 1 + fi +} + +function translateDockerTag() { + local BRANCH=$(echo ${GITHUB_REF} | sed -e "s/refs\/heads\///g" | sed -e "s/\//-/g") + if hasCustomTag; then TAG=$(echo ${INPUT_NAME} | cut -d':' -f2) INPUT_NAME=$(echo ${INPUT_NAME} | cut -d':' -f1) - elif [ "${BRANCH}" = "master" ]; then + elif isOnMaster; then TAG="latest" - # if it's a tag - elif [ $(echo ${GITHUB_REF} | sed -e "s/refs\/tags\///g") != ${GITHUB_REF} ]; then + elif isGitTag; then TAG="latest" - # if it's a pull request - elif [ $(echo ${GITHUB_REF} | sed -e "s/refs\/pull\///g") != ${GITHUB_REF} ]; then + elif isPullRequest; then TAG="${GITHUB_SHA}" else TAG="${BRANCH}" fi; } -translateTag -DOCKERNAME="${INPUT_NAME}:${TAG}" +function hasCustomTag() { + [ $(echo ${INPUT_NAME} | sed -e "s/://g") != ${INPUT_NAME} ] +} -if [ ! -z "${INPUT_WORKDIR}" ]; then +function isOnMaster() { + [ "${BRANCH}" = "master" ] +} + +function isGitTag() { + [ $(echo ${GITHUB_REF} | sed -e "s/refs\/tags\///g") != ${GITHUB_REF} ] +} + +function isPullRequest() { + [ $(echo ${GITHUB_REF} | sed -e "s/refs\/pull\///g") != ${GITHUB_REF} ] +} + +function changeWorkingDirectory() { cd "${INPUT_WORKDIR}" -fi +} -echo ${INPUT_PASSWORD} | docker login -u ${INPUT_USERNAME} --password-stdin ${INPUT_REGISTRY} - -BUILDPARAMS="" - -if [ ! -z "${INPUT_DOCKERFILE}" ]; then +function useCustomDockerfile() { BUILDPARAMS="$BUILDPARAMS -f ${INPUT_DOCKERFILE}" -fi +} -if [ ! -z "${INPUT_CACHE}" ]; then +function addBuildArgs() { + for arg in $(echo "${INPUT_BUILDARGS}" | tr ',' '\n'); do + BUILDPARAMS="$BUILDPARAMS --build-arg ${arg}" + echo "::add-mask::${arg}" + done +} + +function useBuildCache() { if docker pull ${DOCKERNAME} 2>/dev/null; then BUILDPARAMS="$BUILDPARAMS --cache-from ${DOCKERNAME}" fi -fi +} -if [ "${INPUT_SNAPSHOT}" = "true" ]; then - TIMESTAMP=`date +%Y%m%d%H%M%S` - SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-6) - SNAPSHOT_TAG="${TIMESTAMP}${SHORT_SHA}" - SHA_DOCKER_NAME="${INPUT_NAME}:${SNAPSHOT_TAG}" +function uses() { + if [ ! -z "${1}" ]; then + return 0 + else + return 1 + fi +} + +function pushWithSnapshot() { + local TIMESTAMP=`date +%Y%m%d%H%M%S` + local SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-6) + local SNAPSHOT_TAG="${TIMESTAMP}${SHORT_SHA}" + local SHA_DOCKER_NAME="${INPUT_NAME}:${SNAPSHOT_TAG}" docker build $BUILDPARAMS -t ${DOCKERNAME} -t ${SHA_DOCKER_NAME} . docker push ${DOCKERNAME} docker push ${SHA_DOCKER_NAME} echo ::set-output name=snapshot-tag::"${SNAPSHOT_TAG}" -else +} + +function pushWithoutSnapshot() { docker build $BUILDPARAMS -t ${DOCKERNAME} . docker push ${DOCKERNAME} -fi -echo ::set-output name=tag::"${TAG}" +} -docker logout +main diff --git a/test.bats b/test.bats index cde3586..d6f00c0 100755 --- a/test.bats +++ b/test.bats @@ -259,12 +259,45 @@ Called /usr/local/bin/docker logout" [ "$output" = "$expected" ] } +@test "it uses buildargs for building, if configured" { + export INPUT_BUILDARGS='MY_FIRST,MY_SECOND' + + run /entrypoint.sh + + local expected=" +Called /usr/local/bin/docker login -u USERNAME --password-stdin +::add-mask::MY_FIRST +::add-mask::MY_SECOND +Called /usr/local/bin/docker build --build-arg MY_FIRST --build-arg MY_SECOND -t my/repository:latest . +Called /usr/local/bin/docker push my/repository:latest +::set-output name=tag::latest +Called /usr/local/bin/docker logout" + echo $output + [ "$output" = "$expected" ] +} + +@test "it uses buildargs for a single variable" { + export INPUT_BUILDARGS='MY_ONLY' + + run /entrypoint.sh + + local expected=" +Called /usr/local/bin/docker login -u USERNAME --password-stdin +::add-mask::MY_ONLY +Called /usr/local/bin/docker build --build-arg MY_ONLY -t my/repository:latest . +Called /usr/local/bin/docker push my/repository:latest +::set-output name=tag::latest +Called /usr/local/bin/docker logout" + echo $output + [ "$output" = "$expected" ] +} + @test "it errors when with.name was not set" { unset INPUT_NAME run /entrypoint.sh - local expected="Unable to find the repository name. Did you set with.name?" + local expected="Unable to find the name. Did you set with.name?" echo $output [ "$status" -eq 1 ] echo "$output" | grep "$expected"