diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a0e710c..81423ed 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,9 +13,9 @@ jobs: fail-fast: false matrix: os: - - ubuntu-22.04 - - macos-12 # Intel - - macos-13-xlarge # Apple silicon + - ubuntu-24.04 + - macos-13 # Intel + - macos-14 # Apple silicon - windows-2022 ghc-version: - "8.8" @@ -24,20 +24,22 @@ jobs: - "9.2" - "9.4" exclude: - - os: macos-12 + - os: macos-13 ghc-version: "8.10" - - os: macos-12 + - os: macos-13 ghc-version: "9.0" - - os: macos-12 + - os: macos-13 ghc-version: "9.2" - - os: macos-13-xlarge + - os: macos-14 ghc-version: "8.8" - - os: macos-13-xlarge + - os: macos-14 ghc-version: "8.10" - - os: macos-13-xlarge + - os: macos-14 ghc-version: "9.0" - - os: macos-13-xlarge + - os: macos-14 ghc-version: "9.2" + - os: windows-2022 + ghc-version: "8.8" - os: windows-2022 ghc-version: "8.10" - os: windows-2022 @@ -70,6 +72,10 @@ jobs: %APPDATA%\cabal\store %APPDATA%\stack key: stack-${{ matrix.os }}-ghc-${{ matrix.version }} + - name: Install dependencies (Linux) + if: "startsWith(matrix.os, 'ubuntu-')" + run: | + sudo apt install libbz2-dev - name: Install Haskell Stack (if not installed) shell: bash run: | @@ -121,14 +127,8 @@ jobs: matrix.ghc-version == '9.2' shell: bash run: | - curl -L -o /tmp/pandoc.deb \ - https://github.com/jgm/pandoc/releases/download/2.14.2/pandoc-2.14.2-1-amd64.deb - sudo dpkg -i /tmp/pandoc.deb - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64 - sudo add-apt-repository ppa:rmescandon/yq - sudo apt update - sudo apt-get install -y yq - bash scripts/haddock-prologue/build.sh + sudo apt-get install -y pandoc yq + PATH="/usr/bin:$PATH" bash scripts/haddock-prologue/build.sh - name: Copy docs if: >- startsWith(matrix.os, 'ubuntu-') && @@ -178,9 +178,9 @@ jobs: fail-fast: false matrix: os: - - ubuntu-22.04 - - macos-12 # Intel - - macos-13-xlarge # Apple silicon + - ubuntu-24.04 + - macos-13 # Intel + - macos-14 # Apple silicon - windows-2022 steps: - uses: actions/checkout@v4 @@ -266,12 +266,21 @@ jobs: image: name: Docker image - runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + os: + - ubuntu-24.04 + - ubuntu-24.04-arm + runs-on: ${{ matrix.os }} env: DOCKERHUB_IMAGE_NAME: seonbi outputs: image-ghcr: ghcr.io/${{ github.repository }}/bin@${{ steps.push-image.outputs.digest }} image-dockerhub: docker.io/${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}@${{ steps.push-image.outputs.digest }} + tag: ${{ steps.values.outputs.tag }} + labels: ${{ steps.values.outputs.labels }} + arch: ${{ steps.values.outputs.arch }} steps: - uses: actions/checkout@v4 with: @@ -303,6 +312,11 @@ jobs: else echo labels= >> "$GITHUB_OUTPUT" fi + if [[ "$RUNNER_ARCH" = "ARM64" ]]; then + echo arch=arm64 >> "$GITHUB_OUTPUT" + else + echo arch=amd64 >> "$GITHUB_OUTPUT" + fi - id: push-image uses: docker/build-push-action@v6 with: @@ -313,10 +327,39 @@ jobs: org.opencontainers.image.url=${{ github.event.repository.html_url }} ${{ steps.values.outputs.labels }} tags: | - ghcr.io/${{ github.repository }}/bin:${{ steps.values.outputs.tag }} - ${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}:${{ steps.values.outputs.tag }} + ghcr.io/${{ github.repository }}/bin:${{ steps.values.outputs.tag }}-${{ steps.values.outputs.arch }} + ${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}:${{ steps.values.outputs.tag }}-${{ steps.values.outputs.arch }} provenance: false # https://community.fly.io/t/deploying-to-fly-via-github-action-failing/10171/33 + image-manifest: + name: Create and push manifest images + if: github.event_name != 'pull_request' + needs: + - image + runs-on: ubuntu-24.04 + env: + DOCKERHUB_IMAGE_NAME: seonbi + steps: + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ github.token }} + - uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - uses: Noelware/docker-manifest-action@0.4.2 + with: + inputs: ghcr.io/${{ github.repository }}/bin:${{ needs.image.outputs.tag }} + images: ghcr.io/${{ github.repository }}/bin:${{ needs.image.outputs.tag }}-amd64,ghcr.io/${{ github.repository }}/bin:${{ needs.image.outputs.tag }}-arm64 + push: true + - uses: Noelware/docker-manifest-action@0.4.2 + with: + inputs: docker.io/${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}:${{ needs.image.outputs.tag }} + images: docker.io/${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}:${{ needs.image.outputs.tag }}-amd64,docker.io/${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}:${{ needs.image.outputs.tag }}-arm64 + push: true + fly: name: Deploy seonbi-api to Fly.io if: github.event_name == 'push' && github.ref == 'refs/heads/main' @@ -324,8 +367,8 @@ jobs: - image env: FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} - IMAGE: ${{ needs.image.outputs.image-ghcr }} - runs-on: ubuntu-22.04 + IMAGE: ghcr.io/${{ github.repository }}/bin:${{ needs.image.outputs.tag }}-amd64 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: superfly/flyctl-actions/setup-flyctl@master @@ -345,36 +388,54 @@ jobs: needs: - build - image - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: - name: binaries-macos-13-xlarge-ghc-9.4 + name: binaries-macos-14-ghc-9.4 path: /tmp/binaries-macos-arm64 - uses: actions/download-artifact@v4 with: - name: binaries-macos-12-ghc-9.4 + name: binaries-macos-13-ghc-9.4 path: /tmp/binaries-macos-x86_64 - uses: actions/download-artifact@v4 with: name: binaries-windows-2022-ghc-9.2 path: /tmp/binaries-windows + - uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 + - uses: docker/setup-buildx-action@v3 - run: | set -e mkdir -p /tmp/dists - # Linux - docker pull "$IMAGE" - mkdir -p /tmp/binaries-linux - docker run -i "$IMAGE" cat /usr/local/bin/seonbi \ - > /tmp/binaries-linux/seonbi - docker run -i "$IMAGE" cat /usr/local/bin/seonbi-api \ - > /tmp/binaries-linux/seonbi-api - pushd /tmp/binaries-linux + # Linux (amd64) + docker pull "$IMAGE-amd64" + mkdir -p /tmp/binaries-linux-amd64 + docker run -i "$IMAGE-amd64" cat /usr/local/bin/seonbi \ + > /tmp/binaries-linux-amd64/seonbi + docker run -i "$IMAGE-amd64" cat /usr/local/bin/seonbi-api \ + > /tmp/binaries-linux-amd64/seonbi-api + pushd /tmp/binaries-linux-amd64 chmod +x * cp "$GITHUB_WORKSPACE/"{LICENSE,README.md,CHANGES.md} ./ tar cvfj /tmp/dists/seonbi.linux-x86_64.tar.bz2 * popd + # Linux (arm64) + docker pull "$IMAGE-arm64" + mkdir -p /tmp/binaries-linux-arm64 + docker run -i --platform linux/arm64 "$IMAGE-arm64" \ + cat /usr/local/bin/seonbi \ + > /tmp/binaries-linux-arm64/seonbi + docker run -i --platform linux/arm64 "$IMAGE-arm64" \ + cat /usr/local/bin/seonbi-api \ + > /tmp/binaries-linux-arm64/seonbi-api + pushd /tmp/binaries-linux-arm64 + chmod +x * + cp "$GITHUB_WORKSPACE/"{LICENSE,README.md,CHANGES.md} ./ + tar cvfj /tmp/dists/seonbi.linux-arm64.tar.bz2 * + popd # macOS (Apple silicon) pushd /tmp/binaries-macos-arm64 chmod +x * @@ -393,7 +454,7 @@ jobs: zip /tmp/dists/seonbi.win64.zip * popd env: - IMAGE: ${{ needs.image.outputs.image-ghcr }} + IMAGE: ghcr.io/${{ github.repository }}/bin:${{ needs.image.outputs.tag }} - uses: actions/upload-artifact@v4 with: name: dists-untagged @@ -404,12 +465,12 @@ jobs: needs: - build - binaries - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: - name: sdist-ubuntu-22.04-ghc-9.4 + name: sdist-ubuntu-24.04-ghc-9.4 path: /tmp/sdist - uses: actions/download-artifact@v4 with: diff --git a/CHANGES.md b/CHANGES.md index 9b57ec6..3f5c448 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,13 @@ Version 0.5.0 To be released. + - Added prebuilt executable binaries for Linux ARM64 (linux-arm64). + + - The official Docker images are now multi-platform (linux/amd64 and + linux/arm64). [[#35]] + +[#35]: https://github.com/dahlia/seonbi/issues/35 + Version 0.4.0 ------------- diff --git a/Dockerfile b/Dockerfile index dabc925..bcdfa12 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # To correctly make a statically-linked binary, we use Alpine Linux. # The distro entirely uses musl instead of glibc which is unfriendly to be # statically linked. -FROM docker.io/amd64/alpine:3.19 AS build +FROM docker.io/alpine:3.19 AS build LABEL "org.opencontainers.image.title"="Seonbi" LABEL "org.opencontainers.image.licenses"="LGPL-2.1" @@ -11,9 +11,13 @@ RUN apk add --no-cache \ bzip2-dev=1.0.8-r6 \ ghc=9.4.7-r1 \ libbz2=1.0.8-r6 \ + xz=5.4.5-r0 \ zlib-dev=1.3.1-r0 \ zlib-static=1.3.1-r0 -RUN wget -qO- https://get.haskellstack.org/ | sh + +RUN wget -q "https://github.com/commercialhaskell/stack/releases/download/v3.3.1/stack-3.3.1-linux-$(uname -m)-bin" \ + && mv "stack-3.3.1-linux-$(uname -m)-bin" /usr/bin/stack \ + && chmod +x /usr/bin/stack RUN stack config set system-ghc --global true @@ -26,8 +30,9 @@ WORKDIR /src/seonbi # Docker will cache this command as a layer, freeing us up to # modify source code without re-installing dependencies # (unless the .cabal file changes!) -RUN stack setup +RUN stack setup --system-ghc RUN stack build \ + --system-ghc \ --only-snapshot \ --flag seonbi:iconv \ --flag seonbi:static @@ -36,11 +41,12 @@ COPY . /src/seonbi RUN cp /src/seonbi/stack-ghc-9.4.yaml /src/seonbi/stack.yaml RUN stack build \ + --system-ghc \ --flag seonbi:iconv \ --flag seonbi:static \ --copy-bins -FROM docker.io/amd64/alpine:3.14 +FROM docker.io/alpine:3.19 COPY --from=build /root/.local/bin/seonbi* /usr/local/bin/ ENV LANG=en_US.UTF-8 diff --git a/scripts/deno/mod.ts b/scripts/deno/mod.ts index 9514388..99be69e 100644 --- a/scripts/deno/mod.ts +++ b/scripts/deno/mod.ts @@ -143,7 +143,8 @@ const STABLE_DOWNLOAD_URLS: DownloadUrls = { linux: { x86_64: "https://github.com/dahlia/seonbi/releases/download/0.5.0/seonbi-0.5.0.linux-x86_64.tar.bz2", - aarch64: undefined, + aarch64: + "https://github.com/dahlia/seonbi/releases/download/0.5.0/seonbi-0.5.0.linux-arm64.tar.bz2", }, darwin: { x86_64: @@ -162,7 +163,8 @@ const NIGHTLY_DOWNLOAD_URLS: DownloadUrls = { linux: { x86_64: "https://dahlia.github.io/seonbi/dists/latest/seonbi.linux-x86_64.tar.bz2", - aarch64: undefined, + aarch64: + "https://dahlia.github.io/seonbi/dists/latest/seonbi.linux-arm64.tar.bz2", }, darwin: { x86_64: diff --git a/scripts/haddock-prologue/build.sh b/scripts/haddock-prologue/build.sh index ecee2f5..dc125fc 100755 --- a/scripts/haddock-prologue/build.sh +++ b/scripts/haddock-prologue/build.sh @@ -15,7 +15,11 @@ cp "$package" "$backup" cwd="$(pwd)" exit_code=1 { - yq write --inplace "$package" description "$description" + yq \ + -y \ + --arg description "$description" \ + '.description = $description' \ + "$backup" > "$package" cd "$root" stack haddock --no-haddock-deps cd "$(stack path --dist-dir)/doc/html/" diff --git a/setup/action.yaml b/setup/action.yaml index 533d68c..d67beb6 100644 --- a/setup/action.yaml +++ b/setup/action.yaml @@ -42,6 +42,7 @@ runs: suffixes = { ('Linux', 'X64'): 'linux-x86_64.tar.bz2', + ('Linux', 'ARM64'): 'linux-arm64.tar.bz2', ('macOS', 'X64'): 'macos-x86_64.tar.bz2', ('macOS', 'ARM64'): 'macos-arm64.tar.bz2', ('Windows', 'X64'): 'win64.zip', diff --git a/stack-ghc-9.4.yaml b/stack-ghc-9.4.yaml index a0e4455..c2fdfdb 100644 --- a/stack-ghc-9.4.yaml +++ b/stack-ghc-9.4.yaml @@ -1,4 +1,4 @@ -resolver: lts-21.25 +resolver: lts-21.21 packages: - . extra-deps: