From a3cf747183dc8ff4ce8347c7cfcae2fff73ecad2 Mon Sep 17 00:00:00 2001 From: Gerald Pinder Date: Sat, 4 Jan 2025 10:45:32 -0500 Subject: [PATCH] feat: Support arm64 and amd64 builds of nushell --- .github/workflows/build.yml | 3 ++ Containerfile | 8 +++-- build.nu | 71 +++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 18 deletions(-) mode change 100644 => 100755 build.nu diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0be5bec..d7b95f8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,6 +21,9 @@ jobs: - uses: docker/setup-buildx-action@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: diff --git a/Containerfile b/Containerfile index 7681194..b934f97 100644 --- a/Containerfile +++ b/Containerfile @@ -1,10 +1,12 @@ -FROM ubuntu:20.04 as cached +FROM ubuntu:22.04 as cached RUN apt-get update && apt-get install -y wget FROM cached as build -ARG URL=https://github.com/nushell/nushell/releases/download/0.98.0/nu-0.98.0-x86_64-unknown-linux-gnu.tar.gz +ARG VERSION=0.99.1 +ARG DOWNLOAD_ARCH=x86_64 +ARG URL=https://github.com/nushell/nushell/releases/download/${VERSION}/nu-${VERSION}-${DOWNLOAD_ARCH}-unknown-linux-musl.tar.gz RUN wget -O /tmp/archive.tar.gz "$URL" && \ mkdir /tmp/extract/ && \ @@ -13,4 +15,4 @@ RUN wget -O /tmp/archive.tar.gz "$URL" && \ FROM scratch -COPY --from=build /nu/ /nu/ \ No newline at end of file +COPY --from=build /nu/ /nu/ diff --git a/build.nu b/build.nu old mode 100644 new mode 100755 index 3c5410e..c29adc2 --- a/build.nu +++ b/build.nu @@ -4,12 +4,23 @@ # version to be tagged with `default` and used by BlueBuild modules const DEFAULT_VERSION = "0.99.1" +# architectures to build and the corresponding download arch string +const BUILD_ARCHS = [ + { + docker: "linux/amd64", + download: "x86_64", + }, + { + docker: "linux/arm64", + download: "aarch64", + } +] + print $"(ansi green_bold)Gathering images" let images = http get https://api.github.com/repos/nushell/nushell/releases | enumerate | each { |arrayEl| let release = $arrayEl.item - let url = ($release.assets | where name ends-with "x86_64-unknown-linux-musl.tar.gz").browser_download_url.0 let version = $release.name let tags = ( @@ -32,7 +43,6 @@ let images = http get https://api.github.com/repos/nushell/nushell/releases | en print $"(ansi cyan)Found version & generated tags:(ansi reset) ($tags | str join ' ')" { - url: $url version: $version tags: $tags } @@ -41,22 +51,53 @@ let images = http get https://api.github.com/repos/nushell/nushell/releases | en print $"(ansi green_bold)Starting image build(ansi reset)" $images | each { |img| + let base_image = $"($env.REGISTRY)/nushell-image" - print $"(ansi cyan)Building image for version:(ansi reset) ($img.version)" - (docker build . - -f ./Containerfile - ...($img.tags | each { |tag| ["-t", $"($env.REGISTRY)/nushell-image:($tag)"] } | flatten) # generate and spread list of tags - --build-arg $"URL=($img.url)") + $BUILD_ARCHS | each { |arch| + print $"(ansi cyan)Building image for version:(ansi reset) ($img.version)" -} + let tag = $"($base_image):($img.version)-($arch.download)" + + try { + (docker build . + -f ./Containerfile + --platform $arch.docker + -t $tag + --build-arg $"VERSION=($img.version)" + --build-arg $"DOWNLOAD_ARCH=($arch.download)") + + print $"(ansi cyan)Pushing image for platform ($arch.download) and version ($img.version):(ansi reset) ($tag)" + docker push $tag + } catch { + print $"(ansi red_bold)Failed to build image(ansi reset) ($tag)" + exit 1 + } + } + + $img.tags | each { |tag| + let final_image = $"($base_image):($tag)" + + try { + print $"(ansi cyan)Creating multi-platform manifest:(ansi reset) ($final_image)" + (docker manifest create $final_image + ...($BUILD_ARCHS | each { |arch| + ["--amend", $"($base_image):($img.version)-($arch.download)"] + } | flatten)) + + print $"(ansi cyan)Pushing multi-platform manifest:(ansi reset) ($final_image)" + docker manifest push $final_image -print $"(ansi cyan)Pushing images:(ansi reset)" -let digest = ( - docker push --all-tags $"($env.REGISTRY)/nushell-image" - | split row "\n" | last | split row " " | get 2 # parse push output to get digest for signing -) + (docker manifest inspect $final_image | from json).manifests | each { |manifest| + let digest_image = $"($base_image)@($manifest.digest)" -print $"(ansi cyan)Signing image:(ansi reset) ($env.REGISTRY)/nushell-image@($digest)" -cosign sign -y --key env://COSIGN_PRIVATE_KEY $"($env.REGISTRY)/nushell-image@($digest)" + print $"(ansi cyan)Signing image:(ansi reset) ($digest_image)" + cosign sign -y --key env://COSIGN_PRIVATE_KEY $digest_image + } + } catch { + print $"(ansi red_bold)Failed to create and sign manifest(ansi reset) ($final_image)" + exit 1 + } + } +} print $"(ansi green_bold)DONE!(ansi reset)"