diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh index a6be991ef..d978318d4 100755 --- a/.github/scripts/build.sh +++ b/.github/scripts/build.sh @@ -10,11 +10,15 @@ git_describe download_cabal_cache "$HOME/.local/bin/cabal-cache" # install toolchain (if necessary) -ghcup -v install ghc --set --force "$GHC_VER" -ghcup -v install cabal --force "$CABAL_VER" -ghc --version -cabal --version -GHC="ghc-${GHC_VER}" +if [ "${OS}" = "OpenBSD" ] ; then + GHC="ghc-$(ghc --numeric-version)" +else + ghcup -v install ghc --set --force "$GHC_VER" + ghcup -v install cabal --force "$CABAL_VER" + ghc --version + cabal --version + GHC="ghc-${GHC_VER}" +fi # build ecabal update @@ -28,8 +32,12 @@ binary_opttest=$(cabal --project-file=cabal.project.release list-bin ghcup-optpa ver=$("${binary}" --numeric-version) strip_binary "${binary}" +# linking info if [ "${OS}" = "macOS" ] ; then - otool -L "${binary}" | grep libyaml && { echo "undesired libyaml linking" ; exit 5 ; } + otool -L "${binary}" + otool -L "${binary}" | grep libyaml && { echo "undesired libyaml linking" ; exit 5 ; } +else + ldd "${binary}" || true fi cp "${binary}" "out/${ARTIFACT}-${ver}${ext}" diff --git a/.github/scripts/common.sh b/.github/scripts/common.sh index 85a10a9f6..fbf9c60c1 100644 --- a/.github/scripts/common.sh +++ b/.github/scripts/common.sh @@ -51,7 +51,7 @@ eghcup() { } sha_sum() { - if [ "${OS}" = "FreeBSD" ] ; then + if [ "${OS}" = "FreeBSD" ] || [ "${OS}" = "OpenBSD" ] ; then sha256 "$@" else sha256sum "$@" diff --git a/.github/scripts/env.sh b/.github/scripts/env.sh index 61fd3c652..cecddd02f 100644 --- a/.github/scripts/env.sh +++ b/.github/scripts/env.sh @@ -13,6 +13,10 @@ if [ "${RUNNER_OS}" = "freebsd" ] ; then export RUNNER_OS=FreeBSD fi +if [ "${RUNNER_OS}" = "openbsd" ] ; then + export RUNNER_OS=OpenBSD +fi + export OS="$RUNNER_OS" export PATH="$HOME/.local/bin:$PATH" diff --git a/.github/scripts/test.sh b/.github/scripts/test.sh index 4f9cb1146..a3496086a 100644 --- a/.github/scripts/test.sh +++ b/.github/scripts/test.sh @@ -35,6 +35,10 @@ sha_sum "$(raw_eghcup --offline whereis ghcup)" ./"ghcup-test-optparse${ext}" rm "ghcup-test${ext}" "ghcup-test-optparse${ext}" +if [ "${OS}" = "OpenBSD" ] ; then + exit 0 +fi + ### manual cli based testing eghcup --numeric-version @@ -42,7 +46,7 @@ eghcup --numeric-version # test PATH on windows wrt msys2 # https://github.com/haskell/ghcup-hs/pull/992/checks if [ "${OS}" = "Windows" ] ; then - eghcup run -m -- sh -c 'echo $PATH' | sed 's/:/\n/' | grep '^/mingw64/bin$' + eghcup run -m -- sh -c 'echo $PATH' | sed 's/:/\n/' | grep '^/clang64/bin$' fi eghcup install ghc "${GHC_VER}" diff --git a/.github/workflows/bootstrap.yaml b/.github/workflows/bootstrap.yaml index d0299c96a..f386221c5 100644 --- a/.github/workflows/bootstrap.yaml +++ b/.github/workflows/bootstrap.yaml @@ -12,6 +12,10 @@ on: schedule: - cron: '0 2 * * *' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: bootstrap: name: bootstrap diff --git a/.github/workflows/cabal.project.yaml b/.github/workflows/cabal.project.yaml index 81e02e0a3..fe7f3ed24 100644 --- a/.github/workflows/cabal.project.yaml +++ b/.github/workflows/cabal.project.yaml @@ -12,6 +12,10 @@ on: schedule: - cron: '0 2 * * *' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: Build binary diff --git a/.github/workflows/cross.yaml b/.github/workflows/cross.yaml index 579442c10..a5fcddac1 100644 --- a/.github/workflows/cross.yaml +++ b/.github/workflows/cross.yaml @@ -12,6 +12,10 @@ on: schedule: - cron: '0 2 * * *' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: CABAL_CACHE_DISABLE: ${{ vars.CABAL_CACHE_DISABLE }} CABAL_CACHE_NONFATAL: yes @@ -21,13 +25,13 @@ jobs: name: Build linux binary runs-on: [self-hosted, Linux, X64, maerwald] env: - CABAL_VER: 3.10.3.0 + CABAL_VER: 3.14.2.0 JSON_VERSION: "0.0.8" AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} S3_HOST: ${{ secrets.S3_HOST }} ARTIFACT: "x86_64-linux-ghcup" - GHC_VER: 8.10.7 + GHC_VER: 9.6.7 ARCH: 64 steps: - name: Checkout code @@ -61,15 +65,15 @@ jobs: needs: "build" runs-on: [self-hosted, Linux, X64] container: - image: registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb12:a9297a370025101b479cfd4977f8f910814e03ab + image: registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb12:5df428b97c501f61f57587048d4bd15eba53e364 options: --user root env: - CABAL_VER: 3.10.3.0 + CABAL_VER: 3.14.2.0 BUILD_CONF_ARGS: "--enable-unregisterised" HADRIAN_FLAVOUR: "" JSON_VERSION: "0.0.8" - GHC_VER: 8.10.6 - GHC_TARGET_VERSION: "8.10.7" + GHC_VER: 9.6.7 + GHC_TARGET_VERSION: "9.6.7" ARCH: 64 DISTRO: Debian ARTIFACT: "x86_64-linux-ghcup" @@ -108,15 +112,15 @@ jobs: needs: "build" runs-on: [self-hosted, Linux, X64] container: - image: registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb12:a9297a370025101b479cfd4977f8f910814e03ab + image: registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb12:5df428b97c501f61f57587048d4bd15eba53e364 options: --user root env: CABAL_VER: 3.10.3.0 BUILD_CONF_ARGS: "" HADRIAN_FLAVOUR: "default+native_bignum" JSON_VERSION: "0.0.8" - GHC_VER: 9.6.2 - GHC_TARGET_VERSION: "9.6.2" + GHC_VER: 9.6.7 + GHC_TARGET_VERSION: "9.6.7" ARCH: 64 DISTRO: Debian ARTIFACT: "x86_64-linux-ghcup" @@ -139,6 +143,7 @@ jobs: sudo apt-get install -y 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 gzip git clone https://github.com/emscripten-core/emsdk.git cd emsdk + git checkout 3.1.74 ./emsdk install latest ./emsdk activate latest . ./emsdk_env.sh diff --git a/.github/workflows/hlint.yaml b/.github/workflows/hlint.yaml index 7f2a88fd9..b5c007e8e 100644 --- a/.github/workflows/hlint.yaml +++ b/.github/workflows/hlint.yaml @@ -10,6 +10,10 @@ on: branches: - master +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: hlint: name: hlint diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d2081af53..69bfc636a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -12,20 +12,27 @@ on: schedule: - cron: '0 2 * * *' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: CABAL_CACHE_DISABLE: ${{ vars.CABAL_CACHE_DISABLE }} CABAL_CACHE_NONFATAL: yes JSON_VERSION: "0.0.9" + GHC_VER: 9.6.7 + CABAL_VER: 3.14.2.0 + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + S3_HOST: ${{ secrets.S3_HOST }} + GHCUP_MSYS2_ENV: CLANG64 + MSYSTEM: CLANG64 + CHERE_INVOKING: 1 jobs: build-linux: name: Build linux binary runs-on: ${{ matrix.os }} - env: - CABAL_VER: 3.14.1.1 - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ secrets.S3_HOST }} strategy: fail-fast: true matrix: @@ -36,7 +43,6 @@ jobs: ARCH: 32 - os: ubuntu-latest ARTIFACT: "x86_64-linux-ghcup" - GHC_VER: 9.6.7 ARCH: 64 steps: - name: Checkout code @@ -66,7 +72,6 @@ jobs: env: ARTIFACT: ${{ matrix.ARTIFACT }} ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} DISTRO: Alpine AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} @@ -83,20 +88,11 @@ jobs: build-arm: name: Build ARM binary - runs-on: ${{ matrix.os }} + runs-on: ubuntu-24.04-arm env: - CABAL_VER: 3.14.1.1 - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ secrets.S3_HOST }} - strategy: - matrix: - include: - - os: [self-hosted, Linux, ARM64, maerwald] - ARTIFACT: "aarch64-linux-ghcup" - GHC_VER: 9.6.7 - ARCH: ARM64 - DISTRO: Alpine + ARTIFACT: "aarch64-linux-ghcup" + ARCH: ARM64 + DISTRO: Alpine steps: - name: git config run: | @@ -108,53 +104,35 @@ jobs: with: submodules: 'true' - - if: matrix.ARCH == 'ARM64' - uses: docker://hasufell/arm64v8-alpine-haskell:3.21 + - uses: docker://hasufell/arm64v8-alpine-haskell:3.21 name: Run build (aarch64 linux) with: args: sh -c ".github/scripts/build.sh '--ghc-options=-split-sections' '--enable-executable-static'" - env: - ARTIFACT: ${{ matrix.ARTIFACT }} - ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: ${{ matrix.DISTRO }} - AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ env.S3_HOST }} - if: always() name: Upload artifact uses: actions/upload-artifact@v4 with: - name: artifacts-${{ matrix.ARTIFACT }} + name: artifacts-${{ env.ARTIFACT }} path: | ./out/* - build-macwin: - name: Build binary (Mac/Win) + build-mac: + name: Build binary (Mac) runs-on: ${{ matrix.os }} env: - CABAL_VER: 3.14.1.1 MACOSX_DEPLOYMENT_TARGET: 10.13 - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ secrets.S3_HOST }} LLVM_VER: 16 + DISTRO: na strategy: fail-fast: false matrix: include: - - os: [self-hosted, macOS, ARM64] + - os: macOS-latest ARTIFACT: "aarch64-apple-darwin-ghcup" - GHC_VER: 9.6.7 ARCH: ARM64 - os: macOS-15-intel ARTIFACT: "x86_64-apple-darwin-ghcup" - GHC_VER: 9.6.7 - ARCH: 64 - - os: windows-latest - ARTIFACT: "x86_64-mingw64-ghcup" - GHC_VER: 9.6.7 ARCH: 64 steps: - name: Checkout code @@ -165,58 +143,59 @@ jobs: - name: Install GHCup uses: haskell/ghcup-setup@v1 - - if: matrix.ARCH == 'ARM64' && runner.os == 'macOS' - name: Run build + - name: Run build (mac aarch64) run: | - bash .github/scripts/brew.sh git coreutils autoconf automake - export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" + brew install git coreutils autoconf automake bash .github/scripts/build.sh env: ARTIFACT: ${{ matrix.ARTIFACT }} ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: na - AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ env.S3_HOST }} - HOMEBREW_CHANGE_ARCH_TO_ARM: 1 - - if: matrix.ARCH == '64' && runner.os == 'macOS' - name: Run build (windows/mac) - run: | - bash .github/scripts/brew.sh coreutils - export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" - bash .github/scripts/build.sh + - if: always() + name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: artifacts-${{ matrix.ARTIFACT }} + path: | + ./out/* + + build-win: + name: Build binary (Windows) + runs-on: windows-latest + env: + ARTIFACT: "x86_64-mingw64-ghcup" + ARCH: 64 + DISTRO: na + GHCUP_INSTALL_BASE_PREFIX: "C:\\" + defaults: + run: + shell: 'C:/msys64/usr/bin/bash.exe --login -e {0}' + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 env: - ARTIFACT: ${{ matrix.ARTIFACT }} - ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: na - AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ env.S3_HOST }} - HOMEBREW_CHANGE_ARCH_TO_ARM: 1 + GHCUP_MSYS2: 'C:/msys64' + + - name: Install msys2 dependencies + run: &msys2-install | + pacman --noconfirm -S --needed --overwrite '*' bash winpty git tar bsdtar unzip binutils autoconf make xz curl libtool automake p7zip patch ca-certificates python3 zip mingw-w64-clang-x86_64-toolchain mingw-w64-clang-x86_64-tools-git gzip mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-zlib - - if: runner.os == 'Windows' - name: Run build (windows/mac) + - name: Run build (windows) run: | - bash .github/scripts/brew.sh git coreutils autoconf automake + rm -f /c/Strawberry/perl/bin/pkg-config + rm /clang64/bin/zlib1.dll bash .github/scripts/build.sh - env: - ARTIFACT: ${{ matrix.ARTIFACT }} - ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: na - AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ env.S3_HOST }} - HOMEBREW_CHANGE_ARCH_TO_ARM: 1 - if: always() name: Upload artifact uses: actions/upload-artifact@v4 with: - name: artifacts-${{ matrix.ARTIFACT }} + name: artifacts-${{ env.ARTIFACT }} path: | ./out/* @@ -224,13 +203,7 @@ jobs: name: Build binary (FreeBSD) runs-on: [self-hosted, FreeBSD, X64] env: - CABAL_VER: 3.14.1.1 - MACOSX_DEPLOYMENT_TARGET: 10.13 - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - S3_HOST: ${{ secrets.S3_HOST }} ARTIFACT: "x86_64-portbld-freebsd-ghcup" - GHC_VER: 9.6.7 ARCH: 64 DISTRO: na RUNNER_OS: FreeBSD @@ -261,12 +234,43 @@ jobs: path: | ./out/* + build-openbsd: + name: Build binary (OpenBSD) + runs-on: [self-hosted, openbsd, X64] + env: + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + S3_HOST: ${{ secrets.S3_HOST }} + ARTIFACT: "x86_64-openbsd-ghcup" + ARCH: 64 + DISTRO: na + RUNNER_OS: OpenBSD + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: Install prerequisites + run: | + gcc_ver=$(pkg_info -Q gcc | grep '^gcc-[0-9]' | sort -u | head -1 | awk '{ print $1 }') + doas pkg_add -I ghc cabal-install git bash libiconv curl ${gcc_ver} gmp gmake libffi + + - name: Run build + run: bash .github/scripts/build.sh + + - if: always() + name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: artifacts-${{ env.ARTIFACT }} + path: | + ./out/* + test-linux: name: Test linux needs: "build-linux" runs-on: ${{ matrix.os }} - env: - CABAL_VER: 3.14.1.1 strategy: matrix: include: @@ -277,12 +281,10 @@ jobs: DISTRO: Alpine - os: ubuntu-latest ARTIFACT: "x86_64-linux-ghcup" - GHC_VER: 9.6.7 ARCH: 64 DISTRO: Alpine - os: ubuntu-latest ARTIFACT: "x86_64-linux-ghcup" - GHC_VER: 9.6.7 ARCH: 64 DISTRO: Ubuntu @@ -317,7 +319,6 @@ jobs: env: ARTIFACT: ${{ matrix.ARTIFACT }} ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} DISTRO: ${{ matrix.DISTRO }} - if: matrix.DISTRO != 'Alpine' @@ -328,7 +329,6 @@ jobs: env: ARTIFACT: ${{ matrix.ARTIFACT }} ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} DISTRO: ${{ matrix.DISTRO }} - if: failure() @@ -342,18 +342,11 @@ jobs: test-arm: name: Test ARM needs: "build-arm" - runs-on: ${{ matrix.os }} + runs-on: ubuntu-24.04-arm env: - CABAL_VER: 3.14.1.1 - strategy: - matrix: - include: - - os: [self-hosted, Linux, ARM64, maerwald] - ARTIFACT: "aarch64-linux-ghcup" - GHC_VER: 9.6.7 - ARCH: ARM64 - DISTRO: Alpine - + ARTIFACT: "aarch64-linux-ghcup" + ARCH: ARM64 + DISTRO: Alpine steps: - name: Checkout code uses: actions/checkout@v4 @@ -366,51 +359,35 @@ jobs: merge-multiple: true path: ./out - - if: matrix.ARCH == 'ARM64' - uses: docker://hasufell/arm64v8-alpine-haskell:3.21 + - uses: docker://hasufell/arm64v8-alpine-haskell:3.21 name: Run test (aarch64 alpine) with: args: sh .github/scripts/test.sh - env: - ARTIFACT: ${{ matrix.ARTIFACT }} - ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: ${{ matrix.DISTRO }} - if: failure() name: Upload artifact uses: actions/upload-artifact@v4 with: - name: testfiles-${{ matrix.ARTIFACT }} + name: testfiles-${{ env.ARTIFACT }} path: | ./test/ghcup-test/golden/unix/GHCupInfo*json - test-macwin: - name: Test Mac/Win - needs: "build-macwin" + test-mac: + name: Test Mac + needs: "build-mac" runs-on: ${{ matrix.os }} env: - CABAL_VER: 3.14.1.1 MACOSX_DEPLOYMENT_TARGET: 10.13 + DISTRO: na strategy: matrix: include: - - os: [self-hosted, macOS, ARM64] + - os: macOS-latest ARTIFACT: "aarch64-apple-darwin-ghcup" - GHC_VER: 9.6.7 ARCH: ARM64 - DISTRO: na - os: macOS-15-intel ARTIFACT: "x86_64-apple-darwin-ghcup" - GHC_VER: 9.6.7 - ARCH: 64 - DISTRO: na - - os: windows-latest - ARTIFACT: "x86_64-mingw64-ghcup" - GHC_VER: 9.6.7 ARCH: 64 - DISTRO: na - steps: - name: Checkout code uses: actions/checkout@v4 @@ -426,53 +403,72 @@ jobs: merge-multiple: true path: ./out - - if: runner.os == 'macOS' - name: Run test + - name: Run test (mac) run: | - bash .github/scripts/brew.sh coreutils - export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" + brew install coreutils bash .github/scripts/test.sh env: ARTIFACT: ${{ matrix.ARTIFACT }} ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: ${{ matrix.DISTRO }} - HOMEBREW_CHANGE_ARCH_TO_ARM: 1 - - - if: runner.os != 'macOS' - name: Run test - run: bash .github/scripts/test.sh - env: - ARTIFACT: ${{ matrix.ARTIFACT }} - ARCH: ${{ matrix.ARCH }} - GHC_VER: ${{ matrix.GHC_VER }} - DISTRO: ${{ matrix.DISTRO }} - HOMEBREW_CHANGE_ARCH_TO_ARM: 1 - - if: failure() && runner.os == 'Windows' - name: Upload artifact + - name: Upload artifact uses: actions/upload-artifact@v4 with: name: testfiles-${{ matrix.ARTIFACT }} path: | - ./test/ghcup-test/golden/windows/GHCupInfo*json + ./test/ghcup-test/golden/unix/GHCupInfo*json - - if: failure() && runner.os != 'Windows' - name: Upload artifact + test-win: + name: Test Win + needs: "build-win" + runs-on: windows-latest + env: + ARTIFACT: "x86_64-mingw64-ghcup" + ARCH: 64 + DISTRO: na + GHCUP_INSTALL_BASE_PREFIX: "C:\\" + defaults: + run: + shell: 'C:/msys64/usr/bin/bash.exe --login -e {0}' + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + env: + GHCUP_MSYS2: 'C:/msys64' + + - name: Install msys2 dependencies + run: *msys2-install + + - uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + merge-multiple: true + path: ./out + + - name: Run test (windows) + run: | + rm -f /c/Strawberry/perl/bin/pkg-config + rm /clang64/bin/zlib1.dll + bash .github/scripts/test.sh + + - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: testfiles-${{ matrix.ARTIFACT }} + name: testfiles-${{ env.ARTIFACT }} path: | - ./test/ghcup-test/golden/unix/GHCupInfo*json + ./test/ghcup-test/golden/windows/GHCupInfo*json + test-freebsd: name: Test FreeBSD needs: "build-freebsd" runs-on: [self-hosted, FreeBSD, X64] env: - CABAL_VER: 3.14.1.1 - MACOSX_DEPLOYMENT_TARGET: 10.13 ARTIFACT: "x86_64-portbld-freebsd-ghcup" - GHC_VER: 9.6.7 ARCH: 64 DISTRO: na RUNNER_OS: FreeBSD @@ -503,9 +499,48 @@ jobs: name: Upload artifact uses: actions/upload-artifact@v4 with: - name: testfiles-${{ matrix.ARTIFACT }} + name: testfiles-${{ env.ARTIFACT }} + path: | + ./test/ghcup-test/golden/unix/GHCupInfo*json + + test-openbsd: + name: Test OpenBSD + needs: "build-openbsd" + runs-on: [self-hosted, openbsd, X64] + env: + ARTIFACT: "x86_64-openbsd-ghcup" + ARCH: 64 + DISTRO: na + RUNNER_OS: OpenBSD + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: Install prerequisites + run: | + gcc_ver=$(pkg_info -Q gcc | grep '^gcc-[0-9]' | sort -u | head -1 | awk '{ print $1 }') + doas pkg_add -I ghc cabal-install git bash libiconv curl ${gcc_ver} gmp gmake libffi + + - uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + merge-multiple: true + path: ./out + + - name: Run test + run: | + bash .github/scripts/test.sh + + - if: failure() + name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: testfiles-${{ env.ARTIFACT }} path: | ./test/ghcup-test/golden/unix/GHCupInfo*json + hls: name: hls needs: build-linux @@ -539,7 +574,7 @@ jobs: release: name: release - needs: ["test-linux", "test-arm", "test-macwin", "test-freebsd", "hls"] + needs: ["test-linux", "test-arm", "test-mac", "test-win", "test-freebsd", "test-openbsd", "hls"] runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/v') steps: @@ -556,4 +591,3 @@ jobs: draft: true files: | ./out/* - diff --git a/.github/workflows/shellcheck.yaml b/.github/workflows/shellcheck.yaml index 7442300a0..e2cdbbfa0 100644 --- a/.github/workflows/shellcheck.yaml +++ b/.github/workflows/shellcheck.yaml @@ -10,6 +10,10 @@ on: branches: - master +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: shellcheck: name: shellcheck diff --git a/.github/workflows/shimgen.yaml b/.github/workflows/shimgen.yaml index 010cd3cae..0197d6eb5 100644 --- a/.github/workflows/shimgen.yaml +++ b/.github/workflows/shimgen.yaml @@ -6,6 +6,10 @@ on: pull_request: branches: [ master ] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build-shimgen: diff --git a/.github/workflows/stack.yaml b/.github/workflows/stack.yaml index 0ef11b37e..079563942 100644 --- a/.github/workflows/stack.yaml +++ b/.github/workflows/stack.yaml @@ -12,6 +12,10 @@ on: schedule: - cron: '0 2 * * *' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: Build binary diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index a418424b5..33464ff4b 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -197,7 +197,7 @@ Report bugs at |] -- logger interpreter logfile <- runReaderT initGHCupFileLogging dirs let loggerConfig = LoggerConfig - { lcPrintDebug = verbose settings + { lcPrintDebugLvl = Just (verbose settings) , consoleOutter = T.hPutStr stderr , fileOutter = case optCommand of @@ -252,7 +252,7 @@ Report bugs at |] #endif -- check for new tools _ - | Just False <- optVerbose -> pure () + | Just 0 <- optVerbose -> pure () | otherwise -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case Nothing -> void . flip runReaderT s' . runE @'[TagNotFound, DayNotFound, NextVerNotFound, NoToolVersionSet] $ do newTools <- lift checkForUpdates diff --git a/cabal.project.common b/cabal.project.common index f02fbbcb2..e3e058163 100644 --- a/cabal.project.common +++ b/cabal.project.common @@ -8,7 +8,8 @@ constraints: http-io-streams -brotli, bzlib >= 0.5.2.0, directory >= 1.3.8.3, filepath == 1.4.101.0 || == 1.4.300.2 || >= 1.5.2.0, - tar >= 0.6.2.0 + tar >= 0.6.2.0, + libarchive-clib >= 3.8.6.2 -- https://github.com/haskell/ghcup-hs/issues/1107 -- https://github.com/haskell/unix/pull/318 diff --git a/data/metadata b/data/metadata index 43437926a..c5e7e061c 160000 --- a/data/metadata +++ b/data/metadata @@ -1 +1 @@ -Subproject commit 43437926a38e1dd799f442c350d23f766b3cefc0 +Subproject commit c5e7e061ca9a1662d19dfb1cb8c0c845d862aa69 diff --git a/lib-opt/GHCup/OptParse.hs b/lib-opt/GHCup/OptParse.hs index 5cbc1d5b8..b50c85cae 100644 --- a/lib-opt/GHCup/OptParse.hs +++ b/lib-opt/GHCup/OptParse.hs @@ -75,7 +75,7 @@ import Data.Function ((&)) data Options = Options { -- global options - optVerbose :: Maybe Bool + optVerbose :: Maybe Int , optCache :: Maybe Bool , optMetaCache :: Maybe Integer , optMetaMode :: Maybe MetaMode @@ -120,11 +120,17 @@ data Command | PrintAppErrors +toVerbosity :: Maybe Bool -> Maybe Int +toVerbosity (Just True) = Just 1 +toVerbosity (Just False) = Just 0 +toVerbosity _ = Nothing + opts :: Parser Options opts = Options - <$> invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)") + <$> (fmap toVerbosity (invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)")) + <|> optional (option auto (long "verbosity" <> metavar "LEVEL" <> help "verbosity level (0 for off, 1 for 'verbose', 2 for extra)"))) <*> invertableSwitch "cache" (Just 'c') False (help "Cache downloads in ~/.ghcup/cache (default: disabled)") <*> optional (option auto (long "metadata-caching" <> metavar "SEC" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable")) <*> optional (option auto (long "metadata-fetching-mode" <> metavar "" <> help "Whether to fail on metadata download failure (Strict) or fall back to cached version (Lax (default))")) diff --git a/lib-opt/GHCup/OptParse/Common.hs b/lib-opt/GHCup/OptParse/Common.hs index a7b90782c..bc5039698 100644 --- a/lib-opt/GHCup/OptParse/Common.hs +++ b/lib-opt/GHCup/OptParse/Common.hs @@ -269,7 +269,7 @@ tagCompleter :: Tool -> [String] -> Completer tagCompleter tool add = listIOCompleter $ do dirs' <- liftIO getAllDirs let loggerConfig = LoggerConfig - { lcPrintDebug = False + { lcPrintDebugLvl = Nothing , consoleOutter = mempty , fileOutter = mempty , fancyColors = False @@ -297,7 +297,7 @@ versionCompleter' :: [ListCriteria] -> Tool -> (Version -> Bool) -> Completer versionCompleter' criteria tool filter' = listIOCompleter $ do dirs' <- liftIO getAllDirs let loggerConfig = LoggerConfig - { lcPrintDebug = False + { lcPrintDebugLvl = Nothing , consoleOutter = mempty , fileOutter = mempty , fancyColors = False diff --git a/lib-opt/GHCup/OptParse/Whereis.hs b/lib-opt/GHCup/OptParse/Whereis.hs index 43cb23b34..e97e1ccce 100644 --- a/lib-opt/GHCup/OptParse/Whereis.hs +++ b/lib-opt/GHCup/OptParse/Whereis.hs @@ -35,10 +35,10 @@ import Options.Applicative.Pretty.Shim ( text ) import Prelude hiding ( appendFile ) import System.Environment import System.Exit +import System.FilePath import qualified Data.Text as T import Control.Exception.Safe (MonadMask) -import System.FilePath (takeDirectory) import GHCup.Types.Optics @@ -273,7 +273,7 @@ whereis whereisCommand whereisOptions settings runAppState leanAppstate runLogge Dirs{ .. } <- runReaderT getDirs leanAppstate case (whereisCommand, whereisOptions) of (WhereisTool GHCup _, WhereisOptions{..}) -> do - loc <- liftIO (getExecutablePath >>= canonicalizePath ) + loc <- liftIO (getExecutablePath >>= canon ) if directory then liftIO $ putStr $ takeDirectory loc else liftIO $ putStr loc @@ -283,8 +283,8 @@ whereis whereisCommand whereisOptions settings runAppState leanAppstate runLogge runLeanWhereIs leanAppstate (do loc <- liftE $ whereIsTool tool v if directory - then pure $ takeDirectory loc - else pure loc + then canon $ takeDirectory loc + else canon loc ) >>= \case VRight r -> do @@ -297,8 +297,8 @@ whereis whereisCommand whereisOptions settings runAppState leanAppstate runLogge runLeanWhereIs leanAppstate (do loc <- liftE $ whereIsTool tool (mkTVer v) if directory - then pure $ takeDirectory loc - else pure loc + then canon $ takeDirectory loc + else canon loc ) >>= \case VRight r -> do @@ -313,8 +313,8 @@ whereis whereisCommand whereisOptions settings runAppState leanAppstate runLogge (v, _) <- liftE $ fromVersion whereVer guessMode tool loc <- liftE $ whereIsTool tool v if directory - then pure $ takeDirectory loc - else pure loc + then canon $ takeDirectory loc + else canon loc ) >>= \case VRight r -> do @@ -325,23 +325,29 @@ whereis whereisCommand whereisOptions settings runAppState leanAppstate runLogge pure $ ExitFailure 30 (WhereisBaseDir, _) -> do - liftIO $ putStr $ fromGHCupPath baseDir + liftIO $ putStr =<< canon (fromGHCupPath baseDir) pure ExitSuccess (WhereisBinDir, _) -> do - liftIO $ putStr binDir + liftIO $ putStr =<< canon binDir pure ExitSuccess (WhereisCacheDir, _) -> do - liftIO $ putStr $ fromGHCupPath cacheDir + liftIO $ putStr =<< canon (fromGHCupPath cacheDir) pure ExitSuccess (WhereisLogsDir, _) -> do - liftIO $ putStr $ fromGHCupPath logsDir + liftIO $ putStr =<< canon (fromGHCupPath logsDir) pure ExitSuccess (WhereisConfDir, _) -> do - liftIO $ putStr $ fromGHCupPath confDir + liftIO $ putStr =<< canon (fromGHCupPath confDir) pure ExitSuccess where + -- make sure we only have forward slashes on windows + canon fp = do + cfp <- liftIO $ canonicalizePath fp + pure $ map (\c -> if isPathSeparator c then '/' else c) cfp + guessMode = if guessVersion settings then GLaxWithInstalled else GStrict + diff --git a/lib-tui/GHCup/Brick/Actions.hs b/lib-tui/GHCup/Brick/Actions.hs index e1574dcdd..f5c1112e7 100644 --- a/lib-tui/GHCup/Brick/Actions.hs +++ b/lib-tui/GHCup/Brick/Actions.hs @@ -697,7 +697,7 @@ settings' :: IORef AppState {-# NOINLINE settings' #-} settings' = unsafePerformIO $ do dirs <- getAllDirs - let loggerConfig = LoggerConfig { lcPrintDebug = False + let loggerConfig = LoggerConfig { lcPrintDebugLvl = Nothing , consoleOutter = \_ -> pure () , fileOutter = \_ -> pure () , fancyColors = True diff --git a/lib/GHCup/Prelude/File.hs b/lib/GHCup/Prelude/File.hs index 393a7ee13..5689f99e0 100644 --- a/lib/GHCup/Prelude/File.hs +++ b/lib/GHCup/Prelude/File.hs @@ -45,7 +45,7 @@ module GHCup.Prelude.File ( ) where import GHCup.Utils.Dirs -import GHCup.Prelude.Logger.Internal (logInfo, logDebug) +import GHCup.Prelude.Logger.Internal (logInfo, logDebug, logDebug2) import GHCup.Prelude.Internal import GHCup.Prelude.File.Search #if IS_WINDOWS @@ -127,7 +127,7 @@ mergeFileTree sourceBase destBase tool v' copyOp = do logDebug "Starting merge" lift $ runConduitRes $ getDirectoryContentsRecursive sourceBase .| C.mapM_ (\f -> do lift $ copy f - logDebug $ T.pack "Recording installed file: " <> T.pack f + logDebug2 $ T.pack "Recording installed file: " <> T.pack f recordInstalledFile f recFile) where @@ -139,12 +139,12 @@ mergeFileTree sourceBase destBase tool v' copyOp = do logDebug "Deleting recorded files due to partial install" forM_ l $ \f -> do let dest = fromInstallDir destBase dropDrive f - logDebug $ "rm -f " <> T.pack f + logDebug2 $ "rm -f " <> T.pack f hideError NoSuchThing $ rmFile dest pure () - logDebug $ "rm -f " <> T.pack recFile + logDebug2 $ "rm -f " <> T.pack recFile hideError NoSuchThing $ rmFile recFile - logDebug $ "rm -f " <> T.pack (fromInstallDir destBase) + logDebug2 $ "rm -f " <> T.pack (fromInstallDir destBase) hideError UnsatisfiedConstraints $ hideError NoSuchThing $ removeEmptyDirsRecursive (fromInstallDir destBase) diff --git a/lib/GHCup/Prelude/Logger/Internal.hs b/lib/GHCup/Prelude/Logger/Internal.hs index 7b0518392..94c7f1943 100644 --- a/lib/GHCup/Prelude/Logger/Internal.hs +++ b/lib/GHCup/Prelude/Logger/Internal.hs @@ -50,7 +50,15 @@ logDebug :: ( MonadReader env m ) => Text -> m () -logDebug = logInternal Debug +logDebug = logInternal (Debug 1) + +logDebug2 :: ( MonadReader env m + , LabelOptic' "loggerConfig" A_Lens env LoggerConfig + , MonadIO m + ) + => Text + -> m () +logDebug2 = logInternal (Debug 2) logError :: ( MonadReader env m , LabelOptic' "loggerConfig" A_Lens env LoggerConfig @@ -71,12 +79,12 @@ logInternal logLevel msg = do LoggerConfig {..} <- gets @"loggerConfig" let color' c = if fancyColors then color c else id let style' = case logLevel of - Debug -> style Bold . color' Blue + Debug _ -> style Bold . color' Blue Info -> style Bold . color' Green Warn -> style Bold . color' Yellow Error -> style Bold . color' Red let l = case logLevel of - Debug -> style' "[ Debug ]" + Debug _ -> style' "[ Debug ]" Info -> style' "[ Info ]" Warn -> style' "[ Warn ]" Error -> style' "[ Error ]" @@ -89,12 +97,19 @@ logInternal logLevel msg = do . fmap (\line' -> style' "[ ... ] " <> line' ) $ xs - when (lcPrintDebug || (not lcPrintDebug && (logLevel /= Debug))) - $ liftIO $ consoleOutter out + case logLevel of + Debug lvl + | Just cfgLvl <- lcPrintDebugLvl + , lvl <= cfgLvl + -> liftIO $ consoleOutter out + Info -> liftIO $ consoleOutter out + Warn -> liftIO $ consoleOutter out + Error -> liftIO $ consoleOutter out + _ -> pure () -- raw output let lr = case logLevel of - Debug -> "Debug:" + Debug _ -> "Debug:" Info -> "Info:" Warn -> "Warn:" Error -> "Error:" diff --git a/lib/GHCup/Prelude/Process/Posix.hs b/lib/GHCup/Prelude/Process/Posix.hs index 06f64f679..edc6ec40d 100644 --- a/lib/GHCup/Prelude/Process/Posix.hs +++ b/lib/GHCup/Prelude/Process/Posix.hs @@ -117,7 +117,7 @@ execLogged exe args chdir lfile env = do $ forkIO $ EX.handle (\(_ :: IOException) -> pure ()) $ EX.finally - (if verbose + (if verbose > 0 then tee fd stdoutRead else printToRegion fd stdoutRead 6 pState no_color ) diff --git a/lib/GHCup/Types.hs b/lib/GHCup/Types.hs index 2b6877a03..c3eb466c3 100644 --- a/lib/GHCup/Types.hs +++ b/lib/GHCup/Types.hs @@ -407,7 +407,7 @@ data UserSettings = UserSettings , uMetaCache :: Maybe Integer , uMetaMode :: Maybe MetaMode , uNoVerify :: Maybe Bool - , uVerbose :: Maybe Bool + , uVerbose :: Maybe Int , uKeepDirs :: Maybe KeepDirs , uDownloader :: Maybe Downloader , uKeyBindings :: Maybe UserKeyBindings @@ -551,7 +551,7 @@ data Settings = Settings , noVerify :: Bool , keepDirs :: KeepDirs , downloader :: Downloader - , verbose :: Bool + , verbose :: Int , urlSource :: [NewURLSource] , noNetwork :: Bool , gpgSetting :: GPGSetting @@ -582,7 +582,7 @@ defaultMetaCache :: Integer defaultMetaCache = 300 -- 5 minutes defaultSettings :: Settings -defaultSettings = Settings False defaultMetaCache Lax False Never Curl False [NewGHCupURL] False GPGNone False Nothing (DM mempty) [] defaultPagerConfig True +defaultSettings = Settings False defaultMetaCache Lax False Never Curl 0 [NewGHCupURL] False GPGNone False Nothing (DM mempty) [] defaultPagerConfig True instance NFData Settings @@ -765,15 +765,15 @@ instance Show (IO ()) where data LogLevel = Warn | Info - | Debug + | Debug Int | Error deriving (Eq, Ord, Show) data LoggerConfig = LoggerConfig - { lcPrintDebug :: Bool -- ^ whether to print debug in colorOutter - , consoleOutter :: T.Text -> IO () -- ^ how to write the console output - , fileOutter :: T.Text -> IO () -- ^ how to write the file output - , fancyColors :: Bool + { lcPrintDebugLvl :: Maybe Int -- ^ whether to print debug in colorOutter + , consoleOutter :: T.Text -> IO () -- ^ how to write the console output + , fileOutter :: T.Text -> IO () -- ^ how to write the file output + , fancyColors :: Bool } deriving Show