@@ -615,6 +615,187 @@ jobs:
615615 - name : Test uplc-ghc
616616 run : JOBS=1 GHC="$GITHUB_WORKSPACE/_build/install/bin/uplc-ghc" ./plinth-test.sh
617617
618+ # ghcup install tests: verify each platform's bindist installs cleanly as the
619+ # custom `plinth` ghcup tool -- the same path end users take -- on every push,
620+ # not just on tags. Each mirrors its plinth-test-* sibling but installs via
621+ # ghcup + generate-ghcup-metadata.py (file:// metadata) instead of a bare
622+ # configure+make, so a broken dlInstallSpec / generator / metadata schema is
623+ # caught in the PR that introduces it. plinth-ghcup-test.sh does the work; it
624+ # needs only the bindist tarball + python3 + a ghcup >= 0.2.1.0 (no GHC
625+ # rebuild, no submodules -- the sample it compiles is plain Haskell).
626+ plinth-ghcup-test-linux :
627+ name : plinth-ghcup-test / ${{ matrix.os }} / ghc ${{ matrix.ghc }}
628+ needs : plinth-build-linux
629+ runs-on : ${{ matrix.os }}
630+ strategy :
631+ fail-fast : false
632+ matrix :
633+ os : [ubuntu-latest, ubuntu-24.04-arm]
634+ ghc : ['9.6.7']
635+
636+ steps :
637+
638+ - uses : actions/checkout@v4
639+ with :
640+ submodules : false
641+
642+ - name : Download uplc-ghc bindist
643+ uses : actions/download-artifact@v4
644+ with :
645+ name : plinth-bindist-${{ matrix.os }}-${{ matrix.ghc }}
646+ path : _build/artifact
647+
648+ # A stock ghcup for this architecture; the installer DSL needs >= 0.2.1.0
649+ # (plinth-ghcup-test.sh capability-gates on it).
650+ - name : Install stock ghcup
651+ run : |
652+ set -eux
653+ mkdir -p "$HOME/.local/bin"
654+ curl -fL "https://downloads.haskell.org/~ghcup/$(uname -m)-linux-ghcup" \
655+ -o "$HOME/.local/bin/ghcup"
656+ chmod +x "$HOME/.local/bin/ghcup"
657+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
658+
659+ - name : Install and test uplc-ghc via ghcup
660+ run : BINDIST_DIR=_build/artifact ./plinth-ghcup-test.sh
661+
662+ plinth-ghcup-test-linux-musl :
663+ name : plinth-ghcup-test / ${{ matrix.os }} (musl) / ghc ${{ matrix.ghc }}
664+ needs : plinth-build-linux-musl
665+ runs-on : ${{ matrix.os }}
666+ strategy :
667+ fail-fast : false
668+ matrix :
669+ os : [ubuntu-latest, ubuntu-24.04-arm]
670+ ghc : ['9.6.7']
671+
672+ steps :
673+
674+ - uses : actions/checkout@v4
675+ with :
676+ submodules : false
677+
678+ - name : Download uplc-ghc bindist (musl)
679+ uses : actions/download-artifact@v4
680+ with :
681+ name : plinth-bindist-musl-${{ matrix.os }}-${{ matrix.ghc }}
682+ path : _build/artifact
683+
684+ # Run inside Alpine so the musl uplc-ghc can execute. Unlike the build/test
685+ # jobs we do NOT source alpine-setup.sh: that bootstraps a full boot GHC +
686+ # cabal we would never use here. Instead install just the deps needed to run
687+ # uplc-ghc and link the sample, and download the ghcup binary directly --
688+ # the same x86_64/aarch64-linux ghcup the official installer uses on Alpine.
689+ #
690+ # coreutils/findutils/grep are the GNU tools the bindist's `make install`
691+ # (which ghcup runs for us) is exercised with upstream; busybox's applets
692+ # differ in flag support, so don't rely on them for that path.
693+ #
694+ # EXPECT_MUSL=1 asserts the artifact really is the musl bindist: the ghcup
695+ # platform is derived from the bindist name, and a musl bindist mislabelled
696+ # as glibc installs fine here while being broken for users on Alpine.
697+ - name : Install and test uplc-ghc via ghcup (Alpine/musl)
698+ run : |
699+ docker run --rm \
700+ -v "$GITHUB_WORKSPACE:/workspace" -w /workspace \
701+ -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 \
702+ alpine:3.20 sh -c '
703+ set -eux
704+ apk add --no-cache bash build-base coreutils curl findutils grep \
705+ gmp-dev ncurses-dev python3 tar xz
706+ mkdir -p "$HOME/.local/bin"
707+ curl -fL "https://downloads.haskell.org/~ghcup/$(uname -m)-linux-ghcup" \
708+ -o "$HOME/.local/bin/ghcup"
709+ chmod +x "$HOME/.local/bin/ghcup"
710+ BINDIST_DIR=_build/artifact GHCUP_BIN="$HOME/.local/bin/ghcup" \
711+ EXPECT_MUSL=1 bash ./plinth-ghcup-test.sh
712+ '
713+
714+ plinth-ghcup-test-macos :
715+ name : plinth-ghcup-test / macos-15 / ghc ${{ matrix.ghc }}
716+ needs : plinth-build-macos
717+ runs-on : macos-15
718+ strategy :
719+ fail-fast : false
720+ matrix :
721+ ghc : ['9.6.7']
722+
723+ steps :
724+
725+ - uses : actions/checkout@v4
726+ with :
727+ submodules : false
728+
729+ - name : Download uplc-ghc bindist
730+ uses : actions/download-artifact@v4
731+ with :
732+ name : plinth-bindist-macos-${{ matrix.ghc }}
733+ path : _build/artifact
734+
735+ # macos-15 is Apple Silicon (aarch64-apple-darwin).
736+ - name : Install stock ghcup
737+ run : |
738+ set -eux
739+ mkdir -p "$HOME/.local/bin"
740+ curl -fL "https://downloads.haskell.org/~ghcup/aarch64-apple-darwin-ghcup" \
741+ -o "$HOME/.local/bin/ghcup"
742+ chmod +x "$HOME/.local/bin/ghcup"
743+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
744+
745+ - name : Install and test uplc-ghc via ghcup
746+ run : BINDIST_DIR=_build/artifact ./plinth-ghcup-test.sh
747+
748+ plinth-ghcup-test-windows :
749+ name : plinth-ghcup-test / windows-latest / ghc ${{ matrix.ghc }}
750+ needs : plinth-build-windows
751+ runs-on : windows-latest
752+ strategy :
753+ fail-fast : false
754+ matrix :
755+ ghc : ['9.6.7']
756+ defaults :
757+ run :
758+ shell : msys2 {0}
759+
760+ steps :
761+
762+ # The bindist / ghcup use symlinks; enable them before checkout.
763+ - name : Configure git for Windows
764+ shell : bash
765+ run : git config --global core.symlinks true
766+
767+ - uses : actions/checkout@v4
768+ with :
769+ submodules : false
770+
771+ # python3 (for generate-ghcup-metadata.py) + tar/xz/curl to fetch ghcup and
772+ # unpack. cygpath (used by plinth-ghcup-test.sh for native/MSYS path
773+ # translation) is part of the base MSYS2 install.
774+ - name : Setup MSYS2
775+ uses : msys2/setup-msys2@v2
776+ with :
777+ msystem : MINGW64
778+ path-type : inherit
779+ update : false
780+ install : >-
781+ tar xz curl mingw-w64-x86_64-python
782+
783+ - name : Download uplc-ghc bindist
784+ uses : actions/download-artifact@v4
785+ with :
786+ name : plinth-bindist-windows-${{ matrix.ghc }}
787+ path : _build/artifact
788+
789+ - name : Install stock ghcup
790+ run : |
791+ set -eux
792+ mkdir -p "$HOME/.local/bin"
793+ curl -fL "https://downloads.haskell.org/~ghcup/x86_64-mingw64-ghcup.exe" \
794+ -o "$HOME/.local/bin/ghcup.exe"
795+
796+ - name : Install and test uplc-ghc via ghcup
797+ run : BINDIST_DIR=_build/artifact GHCUP_BIN="$HOME/.local/bin/ghcup.exe" ./plinth-ghcup-test.sh
798+
618799 # Note [ghcup release channel]
619800 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
620801 # On a v* tag, publish the per-platform bindists as a GitHub Release and
@@ -634,11 +815,13 @@ jobs:
634815 release :
635816 name : release / ghcup channel
636817 if : startsWith(github.ref, 'refs/tags/')
818+ # Gate publishing on the per-platform ghcup install tests (which transitively
819+ # require the build jobs and their uploaded bindist artifacts).
637820 needs :
638- - plinth-build -linux
639- - plinth-build -linux-musl
640- - plinth-build -windows
641- - plinth-build -macos
821+ - plinth-ghcup-test -linux
822+ - plinth-ghcup-test -linux-musl
823+ - plinth-ghcup-test -windows
824+ - plinth-ghcup-test -macos
642825 runs-on : ubuntu-latest
643826 # Overrides the top-level `contents: read`: this job creates a Release and
644827 # pushes the regenerated channel to gh-pages.
@@ -669,50 +852,8 @@ jobs:
669852 # ghcup tool version: the tag without the leading 'v'.
670853 echo "VERSION=${TAG#v}" >> "$GITHUB_ENV"
671854
672- # A stock ghcup for the pre-publish validation gate. Download the latest
673- # released ghcup; the installer DSL for custom tools needs >= 0.2.1.0.
674- - name : Install stock ghcup
675- run : |
676- set -eux
677- mkdir -p "$HOME/.local/bin"
678- curl -fL https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup \
679- -o "$HOME/.local/bin/ghcup"
680- chmod +x "$HOME/.local/bin/ghcup"
681- echo "$HOME/.local/bin" >> "$GITHUB_PATH"
682- "$HOME/.local/bin/ghcup" --version
683-
684- # Validation gate: generate metadata with file:// URLs to the downloaded
685- # tarballs and actually install the linux bindist as the plinth tool. This
686- # exercises the installer DSL (configure + make install + symlinks) before
687- # anything is published.
688- - name : Validate ghcup install (linux bindist)
689- run : |
690- set -eux
691- python3 generate-ghcup-metadata.py \
692- --version "$VERSION" \
693- --base-url "file://$PWD/dist" \
694- --db "$RUNNER_TEMP/validate.versions.json" \
695- --output "$RUNNER_TEMP/ghcup-plinth-validate.yaml" \
696- --set-latest \
697- dist/*.tar.xz
698- # Capability gate: a ghcup that predates the installer DSL (< 0.2.1.0)
699- # won't recognize the custom `plinth` tool. Fail loudly with an upgrade
700- # hint rather than with a cryptic error deep in `install`.
701- if ! ghcup --url-source "file://$RUNNER_TEMP/ghcup-plinth-validate.yaml" \
702- list -t plinth 2>/dev/null | grep -q plinth; then
703- echo "error: this ghcup ($(ghcup --version)) does not recognize the custom"
704- echo " 'plinth' tool. The installer DSL needs ghcup >= 0.2.1.0."
705- exit 1
706- fi
707- export GHCUP_INSTALL_BASE_PREFIX="$RUNNER_TEMP/ghcup-validate"
708- export XDG_CONFIG_HOME="$RUNNER_TEMP/ghcup-validate/config"
709- export XDG_DATA_HOME="$RUNNER_TEMP/ghcup-validate/data"
710- mkdir -p "$XDG_CONFIG_HOME" "$XDG_DATA_HOME"
711- ghcup --url-source "file://$RUNNER_TEMP/ghcup-plinth-validate.yaml" \
712- install plinth "$VERSION"
713- ghcup --url-source "file://$RUNNER_TEMP/ghcup-plinth-validate.yaml" \
714- set plinth "$VERSION"
715- "$GHCUP_INSTALL_BASE_PREFIX/.ghcup/bin/uplc-ghc" --version
855+ # The install is already validated end-to-end on every platform by the
856+ # plinth-ghcup-test-* jobs this job `needs`, so no re-validation here.
716857
717858 # Publish the Release with all tarballs. Create it if missing, otherwise
718859 # (re-)upload the assets.
0 commit comments