diff --git a/.github/actions/download/action.yml b/.github/actions/download/action.yml new file mode 100644 index 00000000000..37056f4071c --- /dev/null +++ b/.github/actions/download/action.yml @@ -0,0 +1,25 @@ +name: 'Download artifact' +description: 'Donwload artifacts with normalized names' +inputs: + name: + required: true + type: string + path: + required: true + type: string + +runs: + using: "composite" + steps: + - name: Normalise name + run: | + name=${{ inputs.name }} + echo "NAME=${name//\//_}" >> "$GITHUB_ENV" + shell: bash + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.NAME }} + path: ${{ inputs.path }} + diff --git a/.github/actions/upload/action.yml b/.github/actions/upload/action.yml new file mode 100644 index 00000000000..927974ad581 --- /dev/null +++ b/.github/actions/upload/action.yml @@ -0,0 +1,33 @@ +name: 'Upload artifact' +description: 'Upload artifacts with normalized names' +inputs: + if-no-files-found: + default: 'error' + type: string + name: + required: true + type: string + path: + required: true + type: string + retention-days: + default: 0 + type: number + +runs: + using: "composite" + steps: + - name: Normalise name + run: | + name=${{ inputs.name }} + echo "NAME=${name//\//_}" >> "$GITHUB_ENV" + shell: bash + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: ${{ inputs.if-no-files-found }} + retention-days: ${{ inputs.retention-days }} + name: ${{ env.NAME }} + path: ${{ inputs.path }} + diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh new file mode 100644 index 00000000000..12da5adf837 --- /dev/null +++ b/.github/scripts/build.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +set -eux + +uname -a +uname -p +uname +pwd +env + +if [ "${RUNNER_OS}" = Windows ] ; then + ext=".exe" +else + ext="" +fi + +ghcup --no-verbose install ghc --set --install-targets "${GHC_TARGETS}" "${GHC_VERSION}" + +cabal update +cabal user-config diff +cabal user-config init -f +"ghc-${GHC_VERSION}" --info +"ghc" --info + +# shellcheck disable=SC2206 +args=( + -w "ghc-$GHC_VERSION" + --disable-profiling + --enable-executable-stripping + --project-file=cabal.release.project + ${ADD_CABAL_ARGS} +) + +cabal v2-build "${args[@]}" cabal-install + +mkdir -p "out" +# shellcheck disable=SC2154 +cp "$(cabal list-bin "${args[@]}" cabal-install:exe:cabal)" "out/cabal$ext" +cp dist-newstyle/cache/plan.json "out/plan.json" +cd "out/" + +# create tarball/zip +TARBALL_PREFIX="cabal-install-$("./cabal" --numeric-version)" +case "${TARBALL_EXT}" in + zip) + zip "${TARBALL_PREFIX}-${ARTIFACT}.${TARBALL_EXT}" "cabal${ext}" plan.json + ;; + tar.xz) + tar caf "${TARBALL_PREFIX}-${ARTIFACT}.${TARBALL_EXT}" "cabal${ext}" plan.json + ;; + *) + fail "Unknown TARBALL_EXT: ${TARBALL_EXT}" + ;; +esac + +rm "cabal${ext}" plan.json + diff --git a/.github/scripts/test.sh b/.github/scripts/test.sh new file mode 100644 index 00000000000..6704ec9ba53 --- /dev/null +++ b/.github/scripts/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -eux + +env +pwd +ls -lah + +cd out +case "${TARBALL_EXT}" in + zip) + unzip ./cabal-install-*-"${ARTIFACT}.${TARBALL_EXT}" + ;; + tar.xz) + tar xf ./cabal-install-*-"${ARTIFACT}.${TARBALL_EXT}" + ;; + *) + fail "Unknown TARBALL_EXT: ${TARBALL_EXT}" + ;; +esac +cd .. + +ghcup --no-verbose install ghc --set --install-targets "${GHC_TARGETS}" "${GHC_VERSION}" + +cabal update + +# TODO: we want to avoid building here... we should just +# be using the previously built 'cabal-tests' binary +cabal run ${ADD_CABAL_ARGS} cabal-testsuite:cabal-tests -- \ + --with-cabal "$(pwd)/out/cabal" \ + --intree-cabal-lib "$(pwd)" \ + --test-tmp "$(pwd)/testdb" \ + --skip-setup-tests \ + -j "$(nproc)" + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000000..26961c30cfa --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,54 @@ +name: Build and release + +on: + push: + branches: + - master + tags: + - 'v*' + - 'cabal-install-*' + pull_request: + branches: + - master + schedule: + - cron: '0 0 * * *' + +jobs: + release-workflow: + uses: ./.github/workflows/reusable-release.yml + with: + branches: '["${{ github.ref }}"]' + + release: + name: release + needs: [ "release-workflow" ] + runs-on: ubuntu-latest + if: ${{ startsWith(github.ref, 'refs/tags/') }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + merge-multiple: true + path: ./out + + - name: Install requirements + run: | + sudo apt-get update && sudo apt-get install -y tar xz-utils + shell: bash + + - name: build sdists + run: | + cabal sdist -o out all + shell: bash + + - name: Release + uses: softprops/action-gh-release@v1 + with: + draft: true + files: | + ./out/* + diff --git a/.github/workflows/reusable-release.yml b/.github/workflows/reusable-release.yml new file mode 100644 index 00000000000..1c20434644b --- /dev/null +++ b/.github/workflows/reusable-release.yml @@ -0,0 +1,839 @@ +name: Build and release + +on: + workflow_call: + inputs: + branches: + required: true + type: string + ghc: + type: string + default: 9.10.2 + # speed up installation by skipping docs + # starting with GHC 9.10.x, we also need to pass the 'install_extra' target + ghc_targets: + type: string + default: "install_bin install_lib update_package_db install_extra" + cabal: + type: string + default: 3.14.2.0 + test: + type: boolean + default: true + +env: + GHC_VERSION: ${{ inputs.ghc }} + GHC_TARGETS: ${{ inputs.ghc_targets }} + CABAL_VERSION: ${{ inputs.cabal }} + BOOTSTRAP_HASKELL_NONINTERACTIVE: 1 + BOOTSTRAP_HASKELL_MINIMAL: 1 + DEBIAN_FRONTEND: noninteractive + TZ: Asia/Singapore + +jobs: + tool-output: + runs-on: ubuntu-latest + outputs: + apt_tools: ${{ steps.gen_output.outputs.apt_tools }} + apt_tools_ncurses6: ${{ steps.gen_output.outputs.apt_tools_ncurses6 }} + rpm_tools: ${{ steps.gen_output.outputs.rpm_tools }} + apk_tools: ${{ steps.gen_output.outputs.apk_tools }} + xbps_tools: ${{ steps.gen_output.outputs.xbps_tools }} + env: + APT: "groff-base libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https gcc autoconf automake build-essential curl ghc gzip libffi-dev libncurses-dev patchelf" + RPM: "groff-base autoconf automake binutils bzip2 coreutils curl elfutils-devel elfutils-libs findutils gcc gcc-c++ git gmp gmp-devel jq lbzip2 make ncurses ncurses-compat-libs ncurses-devel openssh-clients patch perl pxz python3 sqlite sudo wget which xz zlib-devel patchelf" + APK: "groff binutils-gold curl gcc g++ gmp-dev libc-dev libffi-dev make musl-dev ncurses-dev perl tar xz autoconf automake bzip2 coreutils elfutils-dev findutils git jq bzip2-dev patch python3 sqlite sudo wget which zlib-dev patchelf zlib zlib-dev zlib-static" + XBPS: "groff ncurses-libtinfo-libs autoconf automake binutils bzip2 coreutils curl elfutils-devel elfutils findutils gcc gmp gmp-devel jq lbzip2 make ncurses ncurses-devel openssh patch perl python3 sqlite sudo wget which xz tar zlib-devel patchelf gzip" + steps: + - name: Generate output + id: gen_output + run: | + echo apt_tools="${{ env.APT }} libncurses5 libtinfo5" >> "$GITHUB_OUTPUT" + echo apt_tools_ncurses6="${{ env.APT }} libncurses6 libtinfo6" >> "$GITHUB_OUTPUT" + echo rpm_tools="${{ env.RPM }}" >> "$GITHUB_OUTPUT" + echo apk_tools="${{ env.APK }}" >> "$GITHUB_OUTPUT" + echo xbps_tools="${{ env.XBPS }}" >> "$GITHUB_OUTPUT" + + build-linux: + name: Build linux binaries + runs-on: ubuntu-latest + needs: ["tool-output"] + env: + TARBALL_EXT: tar.xz + ARCH: 64 + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + platform: [ { image: "debian:11" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Debian" + , ARTIFACT: "x86_64-linux-deb11" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "debian:12" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Debian" + , ARTIFACT: "x86_64-linux-deb12" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "ubuntu:20.04" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Ubuntu" + , ARTIFACT: "x86_64-linux-ubuntu20.04" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "ubuntu:22.04" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Ubuntu" + , ARTIFACT: "x86_64-linux-ubuntu22.04" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "ubuntu:24.04" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools_ncurses6 }}" + , DISTRO: "Ubuntu" + , ARTIFACT: "x86_64-linux-ubuntu24.04" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "fedora:33" + , installCmd: "dnf install -y" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Fedora" + , ARTIFACT: "x86_64-linux-fedora33" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "fedora:36" + , installCmd: "dnf install -y" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Fedora" + , ARTIFACT: "x86_64-linux-fedora36" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "fedora:38" + , installCmd: "dnf install -y" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Fedora" + , ARTIFACT: "x86_64-linux-fedora38" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "rockylinux:8" + , installCmd: "yum -y install epel-release && yum install -y --allowerasing" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-rocky8" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "alpine:3.20" + , installCmd: "apk update && apk add" + , toolRequirements: "${{ needs.tool-output.outputs.apk_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-unknown" + , ADD_CABAL_ARGS: "--enable-split-sections --enable-executable-static" + }, + { image: "alpine:3.12" + , installCmd: "apk update && apk add" + , toolRequirements: "${{ needs.tool-output.outputs.apk_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-alpine312" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "alpine:3.20" + , installCmd: "apk update && apk add" + , toolRequirements: "${{ needs.tool-output.outputs.apk_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-alpine320" + , ADD_CABAL_ARGS: "--enable-split-sections" + } + ] + container: + image: ${{ matrix.platform.image }} + steps: + - name: Install requirements + shell: sh + run: | + ${{ matrix.platform.installCmd }} curl bash git ${{ matrix.platform.toolRequirements }} + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: Run build + run: | + bash .github/scripts/build.sh + + env: + ARTIFACT: ${{ matrix.platform.ARTIFACT }} + DISTRO: ${{ matrix.platform.DISTRO }} + ADD_CABAL_ARGS: ${{ matrix.platform.ADD_CABAL_ARGS }} + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ matrix.platform.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + build-linux-32bit: + name: Build linux binaries (32bit) + needs: ["tool-output"] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + env: + TARBALL_EXT: tar.xz + ARCH: 32 + DISTRO: "Unknown" + ARTIFACT: "i386-linux-unknown" + ADD_CABAL_ARGS: "--enable-split-sections --enable-executable-static" + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: Run build (32 bit linux) + uses: docker://i386/alpine:3.20 + with: + args: sh -c "apk update && apk add curl bash git ${{ needs.tool-output.outputs.apk_tools }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup install cabal ${{ env.CABAL_VERSION }} && bash .github/scripts/build.sh" + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + build-arm: + name: Build ARM binary + needs: ["tool-output"] + runs-on: ubuntu-22.04-arm + env: + TARBALL_EXT: tar.xz + ADD_CABAL_ARGS: "" + ARCH: ARM64 + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + platform: [ { ARCH: "ARM64" + , DISTRO: "Debian" + , ARTIFACT: "aarch64-linux-deb10" + }, + { ARCH: "ARM64" + , DISTRO: "Alpine" + , ARTIFACT: "aarch64-linux-alpine" + } + ] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - if: matrix.platform.DISTRO == 'Debian' + uses: docker://arm64v8/debian:11 + name: Run build (aarch64 linux) + with: + args: sh -c "apt-get update && apt-get install -y curl bash git ${{ needs.tool-output.outputs.apt_tools }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup install cabal ${{ env.CABAL_VERSION }} && bash .github/scripts/build.sh" + env: + ARTIFACT: ${{ matrix.platform.ARTIFACT }} + DISTRO: ${{ matrix.platform.DISTRO }} + ADD_CABAL_ARGS: "" + + - if: matrix.platform.DISTRO == 'Alpine' + uses: docker://arm64v8/alpine:3.20 + name: Run build (aarch64 linux alpine) + with: + args: sh -c "apk update && apk add curl bash git ${{ needs.tool-output.outputs.apk_tools }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup install cabal ${{ env.CABAL_VERSION }} && bash .github/scripts/build.sh" + env: + ARTIFACT: ${{ matrix.platform.ARTIFACT }} + DISTRO: ${{ matrix.platform.DISTRO }} + ADD_CABAL_ARGS: "--enable-split-sections --enable-executable-static" + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ matrix.platform.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + build-mac-x86_64: + name: Build binary (Mac x86_64) + runs-on: macOS-13 + env: + MACOSX_DEPLOYMENT_TARGET: 10.13 + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-apple-darwin" + ARCH: 64 + TARBALL_EXT: tar.xz + DISTRO: na + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run build + run: | + brew install coreutils tree + bash .github/scripts/build.sh + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + build-mac-aarch64: + name: Build binary (Mac aarch64) + runs-on: macos-latest + env: + MACOSX_DEPLOYMENT_TARGET: 10.13 + ADD_CABAL_ARGS: "" + ARTIFACT: "aarch64-apple-darwin" + ARCH: ARM64 + TARBALL_EXT: tar.xz + DISTRO: na + HOMEBREW_CHANGE_ARCH_TO_ARM: 1 + GHCUP_INSTALL_BASE_PREFIX: ${{ github.workspace }} + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run build + run: | + brew install git coreutils autoconf automake tree + bash .github/scripts/build.sh + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + build-win: + name: Build binary (Win) + runs-on: windows-latest + env: + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-mingw64" + ARCH: 64 + TARBALL_EXT: "zip" + DISTRO: na + CABAL_DIR: "C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" + GHCUP_INSTALL_BASE_PREFIX: "/c" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: install windows deps + shell: pwsh + run: | + C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -Syuu" + C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -Syuu" + C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -S make mingw-w64-x86_64-clang curl autoconf mingw-w64-x86_64-pkgconf ca-certificates base-devel gettext autoconf make libtool automake python p7zip patch unzip zip git" + taskkill /F /FI "MODULES eq msys-2.0.dll" + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run build (windows) + run: | + $env:CHERE_INVOKING = 1 + $env:MSYS2_PATH_TYPE = "inherit" + $ErrorActionPreference = "Stop" + C:\msys64\usr\bin\bash -lc "bash .github/scripts/build.sh" + shell: pwsh + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + build-freebsd-x86_64: + name: Build FreeBSD x86_64 + runs-on: [self-hosted, FreeBSD, X64] + env: + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-portbld-freebsd" + ARCH: 64 + TARBALL_EXT: tar.xz + DISTRO: na + RUNNER_OS: FreeBSD + CABAL_DIR: ${{ github.workspace }}/.cabal + GHCUP_INSTALL_BASE_PREFIX: ${{ github.workspace }} + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run build + run: | + sudo sed -i.bak -e 's/quarterly/latest/' /etc/pkg/FreeBSD.conf + sudo pkg install -y ghc hs-cabal-install git bash misc/compat10x misc/compat11x misc/compat12x gmake llvm14 libiconv + sudo tzsetup Etc/GMT + sudo adjkerntz -a + bash .github/scripts/build.sh + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: | + ./out/* + + test-linux: + name: Test linux binaries + runs-on: ubuntu-latest + needs: ["tool-output", "build-linux"] + if: ${{ inputs.test }} + env: + TARBALL_EXT: tar.xz + ARCH: 64 + GHC_VERSION: 9.6.7 + GHC_TARGETS: "install_bin install_lib update_package_db" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + platform: [ { image: "debian:11" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Debian" + , ARTIFACT: "x86_64-linux-deb11" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "debian:12" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Debian" + , ARTIFACT: "x86_64-linux-deb12" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "ubuntu:20.04" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Ubuntu" + , ARTIFACT: "x86_64-linux-ubuntu20.04" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "ubuntu:22.04" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools }}" + , DISTRO: "Ubuntu" + , ARTIFACT: "x86_64-linux-ubuntu22.04" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "ubuntu:24.04" + , installCmd: "apt-get update && apt-get install -y" + , toolRequirements: "${{ needs.tool-output.outputs.apt_tools_ncurses6 }}" + , DISTRO: "Ubuntu" + , ARTIFACT: "x86_64-linux-ubuntu24.04" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "fedora:33" + , installCmd: "dnf install -y" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Fedora" + , ARTIFACT: "x86_64-linux-fedora33" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "fedora:36" + , installCmd: "dnf install -y" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Fedora" + , ARTIFACT: "x86_64-linux-fedora36" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "fedora:38" + , installCmd: "dnf install -y" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Fedora" + , ARTIFACT: "x86_64-linux-fedora38" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "rockylinux:8" + , installCmd: "yum -y install epel-release && yum install -y --allowerasing" + , toolRequirements: "${{ needs.tool-output.outputs.rpm_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-rocky8" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "alpine:3.20" + , installCmd: "apk update && apk add" + , toolRequirements: "${{ needs.tool-output.outputs.apk_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-unknown" + , ADD_CABAL_ARGS: "--enable-split-sections --enable-executable-static" + }, + { image: "alpine:3.12" + , installCmd: "apk update && apk add" + , toolRequirements: "${{ needs.tool-output.outputs.apk_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-alpine312" + , ADD_CABAL_ARGS: "--enable-split-sections" + }, + { image: "alpine:3.20" + , installCmd: "apk update && apk add" + , toolRequirements: "${{ needs.tool-output.outputs.apk_tools }}" + , DISTRO: "Unknown" + , ARTIFACT: "x86_64-linux-alpine320" + , ADD_CABAL_ARGS: "--enable-split-sections" + } + ] + container: + image: ${{ matrix.platform.image }} + steps: + - name: Install requirements + shell: sh + run: | + ${{ matrix.platform.installCmd }} curl bash git ${{ matrix.platform.toolRequirements }} + + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: git clone fix + run: git config --system --add safe.directory $GITHUB_WORKSPACE + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - uses: ./.github/actions/download + with: + name: artifacts-${{ matrix.platform.ARTIFACT }}-${{ matrix.branch }} + path: ./out + + - name: Run test + run: | + bash .github/scripts/test.sh + env: + ARTIFACT: ${{ matrix.platform.ARTIFACT }} + DISTRO: ${{ matrix.platform.DISTRO }} + ADD_CABAL_ARGS: ${{ matrix.platform.ADD_CABAL_ARGS }} + +# test-linux-32bit: +# name: Test linux binaries (32bit) +# runs-on: ubuntu-latest +# needs: ["build-linux-32bit"] +# if: $ {{ inputs.test }} +# env: +# TARBALL_EXT: tar.xz +# ARCH: 32 +# DISTRO: "Unknown" +# ARTIFACT: "i386-linux-unknown" +# ADD_CABAL_ARGS: "" +# strategy: +# fail-fast: false +# matrix: +# branch: ${{ fromJSON(inputs.branches) }} +# steps: +# - uses: actions/checkout@v4 +# with: +# ref: ${{ matrix.branch }} +# +# - uses: ./.github/actions/download +# with: +# name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} +# path: ./out +# +# - name: Run build (32 bit linux) +# uses: docker://i386/alpine:3.20 +# with: +# args: sh -c "apk update && apk add curl bash git ${{ needs.tool-output.outputs.apk_tools }} groff && git config --system --add safe.directory $GITHUB_WORKSPACE && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup install cabal ${{ env.CABAL_VERSION }} && bash .github/scripts/build.sh" + + test-arm: + name: Test ARM binary + runs-on: ubuntu-22.04-arm + needs: ["tool-output", "build-arm"] + if: ${{ inputs.test }} + env: + ADD_CABAL_ARGS: "" + TARBALL_EXT: tar.xz + ARCH: ARM64 + GHC_VERSION: 9.6.7 + GHC_TARGETS: "install_bin install_lib update_package_db" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + platform: [ { ARCH: "ARM64" + , DISTRO: "Debian" + , ARTIFACT: "aarch64-linux-deb10" + }, + { ARCH: "ARM64" + , DISTRO: "Alpine" + , ARTIFACT: "aarch64-linux-alpine" + } + ] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - uses: ./.github/actions/download + with: + name: artifacts-${{ matrix.platform.ARTIFACT }}-${{ matrix.branch }} + path: ./out + + - if: matrix.platform.DISTRO == 'Debian' + uses: docker://arm64v8/debian:11 + name: Run build (aarch64 linux) + with: + args: sh -c "apt-get update && apt-get install -y curl bash git groff-base ${{ needs.tool-output.outputs.apt_tools }} && git config --system --add safe.directory $GITHUB_WORKSPACE && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup install cabal ${{ env.CABAL_VERSION }} && bash .github/scripts/test.sh" + env: + ARTIFACT: ${{ matrix.platform.ARTIFACT }} + DISTRO: ${{ matrix.platform.DISTRO }} + + - if: matrix.platform.DISTRO == 'Alpine' + uses: docker://arm64v8/alpine:3.20 + name: Run build (aarch64 linux alpine) + with: + args: sh -c "apk update && apk add curl bash git groff ${{ needs.tool-output.outputs.apk_tools }} && git config --system --add safe.directory $GITHUB_WORKSPACE && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup install cabal ${{ env.CABAL_VERSION }} && bash .github/scripts/test.sh" + env: + ARTIFACT: ${{ matrix.platform.ARTIFACT }} + DISTRO: ${{ matrix.platform.DISTRO }} + + test-mac-x86_64: + name: Test binary (Mac x86_64) + runs-on: macOS-13 + needs: ["build-mac-x86_64"] + if: ${{ inputs.test }} + env: + ADD_CABAL_ARGS: "" + MACOSX_DEPLOYMENT_TARGET: 10.13 + ARTIFACT: "x86_64-apple-darwin" + ARCH: 64 + TARBALL_EXT: tar.xz + DISTRO: na + GHC_VERSION: 9.6.7 + GHC_TARGETS: "install_bin install_lib update_package_db" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - uses: ./.github/actions/download + with: + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: ./out + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run test + run: | + brew install git coreutils autoconf automake tree + bash .github/scripts/test.sh + + test-mac-aarch64: + name: Test binary (Mac aarch64) + runs-on: macos-latest + needs: ["build-mac-aarch64"] + if: ${{ inputs.test }} + env: + ADD_CABAL_ARGS: "" + MACOSX_DEPLOYMENT_TARGET: 10.13 + ARTIFACT: "aarch64-apple-darwin" + ARCH: ARM64 + TARBALL_EXT: tar.xz + DISTRO: na + HOMEBREW_CHANGE_ARCH_TO_ARM: 1 + GHCUP_INSTALL_BASE_PREFIX: ${{ github.workspace }} + GHC_VERSION: 9.6.7 + GHC_TARGETS: "install_bin install_lib update_package_db" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - uses: ./.github/actions/download + with: + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: ./out + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run test + run: | + brew install git coreutils autoconf automake tree + bash .github/scripts/test.sh + + test-win: + name: Test binary (Win) + runs-on: windows-latest + needs: ["build-win"] + if: ${{ inputs.test }} + env: + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-mingw64" + ARCH: 64 + TARBALL_EXT: "zip" + DISTRO: na + CABAL_DIR: "C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" + GHCUP_INSTALL_BASE_PREFIX: "/c" + GHC_VERSION: 9.6.7 + GHC_TARGETS: "install_bin install_lib update_package_db" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - name: install windows deps + shell: pwsh + run: | + C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -Syuu" + C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -Syuu" + C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -S make mingw-w64-x86_64-clang curl autoconf mingw-w64-x86_64-pkgconf ca-certificates base-devel gettext autoconf make libtool automake python p7zip patch unzip zip git" + taskkill /F /FI "MODULES eq msys-2.0.dll" + + - uses: ./.github/actions/download + with: + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: ./out + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run test (windows) + run: | + $env:CHERE_INVOKING = 1 + $env:MSYS2_PATH_TYPE = "inherit" + $ErrorActionPreference = "Stop" + C:\msys64\usr\bin\bash -lc "bash .github/scripts/test.sh" + shell: pwsh + + test-freebsd-x86_64: + name: Test FreeBSD x86_64 + runs-on: [self-hosted, FreeBSD, X64] + needs: ["build-freebsd-x86_64"] + if: ${{ inputs.test }} + env: + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-portbld-freebsd" + ARCH: 64 + TARBALL_EXT: tar.xz + DISTRO: na + RUNNER_OS: FreeBSD + CABAL_DIR: ${{ github.workspace }}/.cabal + GHCUP_INSTALL_BASE_PREFIX: ${{ github.workspace }} + GHC_VERSION: 9.6.7 + GHC_TARGETS: "install_bin install_lib update_package_db" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + + - uses: ./.github/actions/download + with: + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: ./out + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + + - name: Run test + run: | + sudo sed -i.bak -e 's/quarterly/latest/' /etc/pkg/FreeBSD.conf + sudo pkg install -y ghc hs-cabal-install git bash misc/compat10x misc/compat11x misc/compat12x gmake llvm14 libiconv groff autoconf automake + sudo tzsetup Etc/GMT + sudo adjkerntz -a + bash .github/scripts/test.sh + diff --git a/cabal-install-solver/cabal-install-solver.cabal b/cabal-install-solver/cabal-install-solver.cabal index 17e9938a46e..a222410efa0 100644 --- a/cabal-install-solver/cabal-install-solver.cabal +++ b/cabal-install-solver/cabal-install-solver.cabal @@ -107,7 +107,7 @@ library , containers >=0.5.6.2 && <0.9 , edit-distance ^>= 0.2.2 , directory >= 1.3.7.0 && < 1.4 - , filepath ^>=1.4.0.0 || ^>=1.5.0.0 + , filepath >= 1.3.0.1 && < 1.6 , mtl >=2.0 && <2.4 , network-uri >= 2.6.0.2 && < 2.7 , pretty ^>=1.1 diff --git a/cabal-testsuite/PackageTests/Backpack/T5634/setup.test.hs b/cabal-testsuite/PackageTests/Backpack/T5634/setup.test.hs index d897955dd74..d12ab76f136 100644 --- a/cabal-testsuite/PackageTests/Backpack/T5634/setup.test.hs +++ b/cabal-testsuite/PackageTests/Backpack/T5634/setup.test.hs @@ -1,5 +1,8 @@ import Test.Cabal.Prelude -main = setupAndCabalTest $ do +main = do + -- TODO: this might be a GHC bug that needs fixing + skipIfAlpine "bug #11041" + setupAndCabalTest $ do skipUnlessGhcVersion ">= 8.1" setup "configure" [] setup "build" [] diff --git a/cabal-testsuite/cabal-testsuite.cabal b/cabal-testsuite/cabal-testsuite.cabal index b59e8dbf8da..50ea756fcdf 100644 --- a/cabal-testsuite/cabal-testsuite.cabal +++ b/cabal-testsuite/cabal-testsuite.cabal @@ -75,6 +75,7 @@ library , network-uri >= 2.6.0.2 && < 2.7 , network-wait ^>= 0.1.2.0 || ^>= 0.2.0.0 , optparse-applicative ^>= 0.14.3.0 || ^>=0.15.1.0 || ^>=0.16.0.0 || ^>= 0.17.0.0 || ^>= 0.18.1.0 + , os-release ^>= 1.0.2.1 , process ^>= 1.2.1.0 || ^>= 1.4.2.0 || ^>= 1.6.1.0 , regex-base ^>= 0.94.0.1 , regex-tdfa ^>= 1.2.3.1 || ^>=1.3.1.0 diff --git a/cabal-testsuite/src/Test/Cabal/Prelude.hs b/cabal-testsuite/src/Test/Cabal/Prelude.hs index 3a12298608c..c85f1205fc7 100644 --- a/cabal-testsuite/src/Test/Cabal/Prelude.hs +++ b/cabal-testsuite/src/Test/Cabal/Prelude.hs @@ -75,6 +75,7 @@ import Control.Retry (exponentialBackoff, limitRetriesByCumulativeDelay) import Network.Wait (waitTcpVerbose) import System.Environment import qualified System.FilePath.Glob as Glob (globDir1, compile) +import qualified System.OsRelease as OSR import System.Process import System.IO import qualified System.FilePath.Posix as Posix @@ -1079,6 +1080,15 @@ isJavaScript = buildArch == JavaScript skipIfWindows :: String -> IO () skipIfWindows why = skipIfIO ("Windows " <> why) isWindows +skipIfAlpine :: String -> IO () +skipIfAlpine why = do + mres <- OSR.parseOsRelease + let b = case mres of + Just (OSR.OsReleaseResult { OSR.osRelease = OSR.OsRelease { OSR.id = osId } }) + | isLinux -> osId == "alpine" + _ -> False + skipIfIO ("Alpine " <> why) b + skipUnlessWindows :: IO () skipUnlessWindows = skipIfIO "Only interesting in Windows" (not isWindows) diff --git a/cabal.release.project b/cabal.release.project index db9c4f305e2..8fd3d83a188 100644 --- a/cabal.release.project +++ b/cabal.release.project @@ -7,7 +7,26 @@ index-state: hackage.haskell.org 2025-06-27T20:43:14Z -- never include this or its TH dependency in a release! package cabal-install - flags: -git-rev + flags: -git-rev -lukko package Cabal flags: -git-rev + +constraints: + -- don't use `-march=native` (for portability) + hashable -arch-native, + -- fixes unicode issues + tar >= 0.6.2.0, + -- https://github.com/haskell/directory/issues/170 + directory >= 1.3.8.3, + -- avoid deprecated versions + filepath == 1.4.101.0 || == 1.4.300.1 || == 1.4.300.2 || == 1.4.301.0 || >= 1.5.2.0 + +-- https://github.com/haskell/ghcup-hs/issues/1107 +-- https://github.com/haskell/unix/pull/318 +if arch(arm) || arch(i386) + constraints: unix >= 2.8.6.0 + +-- static linking +package zlib + flags: -pkg-config +bundled-c-zlib