Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create multi-arch image in local #46

Merged
merged 2 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ buildx-5.6:
--build-arg SWIFT_LINT_REVISION=$(shell cat .github/matrix.json | jq -rc '.swiftlint_supported_version."5.6"') \
--tag $(DOCKER_USER)/$(IMAGE_NAME):5.6 \
.

arm64:
@scripts/build_and_push_arm64_image.sh $(DOCKER_USER) $(IMAGE_NAME)
100 changes: 100 additions & 0 deletions scripts/build_and_push_arm64_image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/zsh

if [[ $(arch) != "arm64" ]]; then
echo "\e[31mThis script must be run on an arm64 machine.\e[m"
exit 1
fi

local -A opthash
zparseopts -D -A opthash -- -help h -force f

if [[ -n $opthash[(i)--help] ]] || [[ -n $opthash[(i)-h] ]]; then
echo "Usage: $0 [options] DOCKER_USER IMAGE_NAME"
echo "Options:"
echo " --help -h: Show this help message"
echo " --force -f: Force to build and push images"
exit 0
fi

if [[ -n $opthash[(i)--force] ]] || [[ -n $opthash[(i)-f] ]]; then
FORCE=true
else
FORCE=false
fi

DOCKER_USER=$1
IMAGE_NAME=$2
REPO_ROOT=$(git rev-parse --show-toplevel)

MATRIX_JSON=$(cat "$REPO_ROOT"/.github/matrix.json | jq -rc .)
LATEST_VERSION=$(echo "$MATRIX_JSON" | jq -r '.swift_version[0]')

for version in $(echo "$MATRIX_JSON" | jq -r '.swift_version[]'); do
# Less than 5.6 doesn't support arm64
if [[ $(($version)) -lt 5.6 ]]; then
continue
fi

needs_update=$FORCE
if [[ $FORCE == false ]]; then
docker manifest rm "$DOCKER_USER/$IMAGE_NAME:$version" > /dev/null 2>/dev/null
docker manifest inspect "$DOCKER_USER/$IMAGE_NAME:$version" > /dev/null 2>/dev/null
if [[ $? -ne 0 ]]; then
needs_update=true
fi
fi
if [[ $needs_update == true ]]; then
# Pull amd64 image and re-tag
echo "\e[32mFetching amd64 image for $version started...\e[m"
docker pull --platform=linux/amd64 "$DOCKER_USER/$IMAGE_NAME:$version"
echo "\e[32mFetching amd64 image finished!\e[m"
AMD64_IMAGE_ID=$(docker images --format "{{.Repository}}:{{.Tag}} {{.ID}}" | grep "$DOCKER_USER/$IMAGE_NAME:$version" | grep -v arm64 | awk '{print $2}')
docker tag $AMD64_IMAGE_ID "$DOCKER_USER/$IMAGE_NAME:$version-amd64"
docker push "$DOCKER_USER/$IMAGE_NAME:$version-amd64"
echo "\e[32mRe-tagging amd64 image for $version finished!\e[m"

# Build arm64 image
echo "\e[32mBuilding arm64 image for $version started...\e[m"
swiftlint_version=$(echo "$MATRIX_JSON" | jq -r ".swiftlint_supported_version[\"$version\"]")
docker build --build-arg SWIFT_VERSION=$version --build-arg SWIFT_LINT_REVISION=$swiftlint_version -t "$DOCKER_USER/$IMAGE_NAME:$version-arm64" -f "$REPO_ROOT/Dockerfile" "$REPO_ROOT"
if [[ $? -eq 0 ]]; then
docker push "$DOCKER_USER/$IMAGE_NAME:$version-arm64"
echo "\e[32mBuilding arm64 image finished!\e[m"

# Create manifest
echo "\e[32mCreating manifest started...\e[m"
docker manifest create "$DOCKER_USER/$IMAGE_NAME:$version" \
--amend "$DOCKER_USER/$IMAGE_NAME:$version-amd64" \
--amend "$DOCKER_USER/$IMAGE_NAME:$version-arm64"
docker manifest push "$DOCKER_USER/$IMAGE_NAME:$version"
echo "\e[32mCreating manifest finished!\e[m"

# Create latest manifest
if [[ "$version" == "$LATEST_VERSION" ]]; then
echo "\e[32mCreating latest manifest...\e[m"
docker manifest create "$DOCKER_USER/${IMAGE_NAME}:latest" \
--amend "$DOCKER_USER/$IMAGE_NAME:$version-amd64" \
--amend "$DOCKER_USER/$IMAGE_NAME:$version-arm64"
docker manifest push "$DOCKER_USER/${IMAGE_NAME}:latest"
fi
else
echo "\e[31mBuilding arm64 image for $version failed!\e[m"
fi

# Clean up
docker image rm "$DOCKER_USER/$IMAGE_NAME:$version" \
"$DOCKER_USER/$IMAGE_NAME:$version-amd64" \
"$DOCKER_USER/$IMAGE_NAME:$version-arm64"

# Clean up on Docker Hub
DOCKER_HUB_TOKEN=`curl -s -H "Content-Type: application/json" -X POST -d "{\"username\": \"$DOCKER_USER\",\"password\": \"$DOCKER_HUB_PASSWORD\"}" "https://hub.docker.com/v2/users/login/" | jq -r .token`
curl -sS "https://hub.docker.com/v2/repositories/${DOCKER_USER}/${IMAGE_NAME}/tags/${version}-amd64/" \
-X DELETE \
-H "Authorization: JWT ${DOCKER_HUB_TOKEN}"
curl -sS "https://hub.docker.com/v2/repositories/${DOCKER_USER}/${IMAGE_NAME}/tags/${version}-arm64/" \
-X DELETE \
-H "Authorization: JWT ${DOCKER_HUB_TOKEN}"
else
echo "\e[32mSkipping for $version...\e[m"
fi
done