diff --git a/Dockerfile b/Dockerfile index 477ef39..47de0ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ LABEL "maintainer"="Lars Gohr" RUN apk update \ && apk upgrade \ - && apk add --no-cache git + && apk add --no-cache git sudo ADD entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] @@ -14,6 +14,7 @@ RUN apk add --no-cache coreutils bats ADD test.bats /test.bats ADD mock.sh /usr/local/bin/docker ADD mock.sh /usr/bin/date +ADD mock.sh /usr/bin/sudo RUN /test.bats FROM runtime diff --git a/README.md b/README.md index 3b8b9c7..59af6dd 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,17 @@ with: no_push: ${{ github.event_name == 'push' }} ``` +### platforms +Use `platforms` when you want to build a multi-platform image (separated by comma). + +```yaml +with: + name: myDocker/repository + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + platforms: linux/amd64,linux/arm64 +``` + ### Tags This action supports multiple options that tags are handled. diff --git a/action.yml b/action.yml index 290d2ee..b819a96 100644 --- a/action.yml +++ b/action.yml @@ -44,6 +44,9 @@ inputs: tags: description: 'Use tags when you want to bring your own tags (separated by comma)' required: false + platforms: + description: 'Use platforms to build multi-platform images (separated by comma)' + required: false tag_names: description: 'Use tag_names when you want to push tags/release by their git name' required: false diff --git a/entrypoint.sh b/entrypoint.sh index 8b8aa9c..fddcc66 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -16,6 +16,10 @@ main() { sanitize "${INPUT_PASSWORD}" "password" fi + if uses "${INPUT_PLATFORMS}"; then + enableExperimentalDocker + fi + registryToLower nameToLower @@ -84,6 +88,11 @@ sanitize() { fi } +enableExperimentalDocker() { + echo $'{"experimental": true}' | sudo dd status=none of=/etc/docker/daemon.json + sudo service docker restart +} + registryToLower(){ INPUT_REGISTRY=$(echo "${INPUT_REGISTRY}" | tr '[A-Z]' '[a-z]') } @@ -190,7 +199,12 @@ build() { for TAG in ${TAGS}; do BUILD_TAGS="${BUILD_TAGS}-t ${INPUT_NAME}:${TAG} " done - docker build ${INPUT_BUILDOPTIONS} ${BUILDPARAMS} ${BUILD_TAGS} ${CONTEXT} + if uses "${INPUT_PLATFORMS}"; then + local PLATFORMS="--platform ${INPUT_PLATFORMS}" + docker buildx build ${PLATFORMS} ${INPUT_BUILDOPTIONS} ${BUILDPARAMS} ${BUILD_TAGS} ${CONTEXT} + else + docker build ${INPUT_BUILDOPTIONS} ${BUILDPARAMS} ${BUILD_TAGS} ${CONTEXT} + fi } push() { diff --git a/test.bats b/test.bats index e95172f..94b34b2 100755 --- a/test.bats +++ b/test.bats @@ -6,6 +6,7 @@ setup(){ declare -A -p MOCK_RETURNS=( ['/usr/local/bin/docker']="" + ['sudo']="" ) > mockReturns export GITHUB_REF='refs/heads/master' @@ -20,6 +21,7 @@ teardown() { unset INPUT_DOCKERFILE unset INPUT_REGISTRY unset INPUT_CACHE + unset INPUT_PLATFORMS unset GITHUB_SHA unset INPUT_PULL_REQUESTS unset MOCK_ERROR_CONDITION @@ -654,6 +656,24 @@ teardown() { /usr/local/bin/docker logout" } +@test "it supports building multiple platforms" { + export GITHUB_REF='refs/heads/main' + export INPUT_PLATFORMS='linux/amd64,linux/arm64' + + run /entrypoint.sh + + expectStdOutContains "::set-output name=tag::latest" + + expectMockCalledContains "/usr/bin/sudo dd status=none of=/etc/docker/daemon.json +/usr/bin/sudo service docker restart +/usr/local/bin/docker login -u USERNAME --password-stdin +/usr/local/bin/docker buildx build --platform linux/amd64,linux/arm64 -t my/repository:latest . +/usr/local/bin/docker push my/repository:latest +/usr/local/bin/docker inspect --format={{index .RepoDigests 0}} my/repository:latest +/usr/local/bin/docker logout" + expectMockArgs '/usr/bin/sudo {"experimental": true}' +} + expectStdOutIs() { local expected=$(echo "${1}" | tr -d '\n') local got=$(echo "${output}" | tr -d '\n')