Skip to content

Bump version to 9.6.166 for Plinth 1.66 #142

Bump version to 9.6.166 for Plinth 1.66

Bump version to 9.6.166 for Plinth 1.66 #142

Workflow file for this run

name: CI
on:
pull_request:
types: [opened, synchronize]
push:
branches: [master, ghc-9.6-plinth]
# Pushing a v* tag builds every platform (as on a branch push) and then the
# `release` job publishes a GitHub Release + updates the ghcup channel. See
# Note [ghcup release channel] on the release job below.
tags: ['v*']
workflow_dispatch:
# Least-privilege GITHUB_TOKEN: jobs only check out code (contents: read).
# Submodules use a dedicated SSH key and artifacts use the Actions runtime
# token, so no write scopes are needed.
permissions:
contents: read
jobs:
plinth-build-linux:
name: plinth-build / ${{ matrix.os }} / ghc ${{ matrix.ghc }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
ghc: ['9.6.7']
steps:
# checkout first: the local composite action (.github/actions/prepare) must
# be on disk before the runner can resolve it.
- uses: actions/checkout@v4
with:
submodules: false
- uses: ./.github/actions/prepare
with:
ghc-version: ${{ matrix.ghc }}
# BINDIST=1 produces the fixed-up uplc-ghc bindist (+ .tar.xz archive) while
# keeping the lean dev flavour. The plinth-test job consumes that archive.
- name: Build uplc-ghc bindist
run: BINDIST=1 ./plinth-build.sh
- name: Upload uplc-ghc bindist
uses: actions/upload-artifact@v4
with:
# key by platform + GHC so multiple build matrix legs (or another job)
# never collide on the artifact name within a single run. See the
# matching download in the plinth-test job, which shares this matrix.
name: plinth-bindist-${{ matrix.os }}-${{ matrix.ghc }}
path: _build/bindist/*.tar.xz
retention-days: 1
# the archive is already xz-compressed; don't re-zip it
compression-level: 0
# plinth-test runs in its own job for a separate status check and timeout
# budget. It depends on `plinth-build-linux` (it can't run in parallel: it
# needs the built compiler), downloading the bindist archive instead of
# rebuilding GHC. Its matrix mirrors the build so the artifact-name key
# matches per leg.
plinth-test-linux:
name: plinth-test / ${{ matrix.os }} / ghc ${{ matrix.ghc }}
needs: plinth-build-linux
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
ghc: ['9.6.7']
steps:
# checkout first: the local composite action (.github/actions/prepare) must
# be on disk before the runner can resolve it. The prepare action also
# fetches submodules, which the test needs: plinth/test/cabal.project pulls
# plutus-tx/plutus-core/plutus-ledger-api from the plutus submodule.
- uses: actions/checkout@v4
with:
submodules: false
- uses: ./.github/actions/prepare
with:
ghc-version: ${{ matrix.ghc }}
# A single Plinth plugin (Core -> PLC) compile of a makeLift-heavy module
# (PlutusLedgerApi.V3.Contexts) spikes past the ~16 GB runner RAM and gets
# OOM-killed even with JOBS=1. Add a 16 GB swapfile on the large /mnt disk
# so the spike spills to swap and the compile completes.
- name: Add 16 GB swap
run: |
sudo fallocate -l 16G /mnt/swapfile
sudo chmod 600 /mnt/swapfile
sudo mkswap /mnt/swapfile
sudo swapon /mnt/swapfile
swapon --show
free -h
- name: Download uplc-ghc bindist
uses: actions/download-artifact@v4
with:
# matches the plinth-build upload name; both jobs share the same matrix.
name: plinth-bindist-${{ matrix.os }}-${{ matrix.ghc }}
path: _build/artifact
# Install the bindist with the usual configure + make install; the bindist's
# wrappers/ dir (added by the BINDIST fixup) makes this produce bin/uplc-ghc.
# Each step is guarded so a missing artifact or failed install fails loudly
# here, not with a confusing error deep in the test.
- name: Install uplc-ghc bindist
run: |
shopt -s nullglob
archives=(_build/artifact/*.tar.xz)
if [ ${#archives[@]} -ne 1 ]; then
echo "error: expected exactly one bindist archive, found: ${archives[*]:-none}"
exit 1
fi
mkdir -p _build/bindist
echo "extracting ${archives[0]}"
tar --xz -xf "${archives[0]}" -C _build/bindist
bindirs=(_build/bindist/ghc-*)
if [ ${#bindirs[@]} -ne 1 ]; then
echo "error: expected one extracted bindist dir, found: ${bindirs[*]:-none}"
exit 1
fi
( cd "${bindirs[0]}" && ./configure --prefix="$GITHUB_WORKSPACE/_build/install" && make install )
uplc="$GITHUB_WORKSPACE/_build/install/bin/uplc-ghc"
if [ ! -x "$uplc" ]; then
echo "error: $uplc missing or not executable after make install"
ls -l "$GITHUB_WORKSPACE/_build/install/bin" || true
exit 1
fi
rm -rf _build/artifact
# Build packages serially (JOBS=1): compiling with the Plinth plugin
# (Core -> PLC) is memory-heavy, and concurrent GHC processes OOM-kill the
# runner (seen mid-compile on PlutusLedgerApi.V3).
- name: Test uplc-ghc
run: JOBS=1 GHC="$GITHUB_WORKSPACE/_build/install/bin/uplc-ghc" ./plinth-test.sh
# musl (Alpine) build, mirroring plinth-build-linux. GitHub runners are glibc
# and haskell-actions/setup only ships glibc GHC, so the toolchain + build run
# inside an alpine:3.20 container via `docker run` (with a musl boot-GHC from
# ghcup). The workspace is mounted in; host-level free-disk / submodule steps
# still run on the runner first. `docker run` (not a job-level `container:`)
# keeps those host steps working.
plinth-build-linux-musl:
name: plinth-build / ${{ matrix.os }} (musl) / ghc ${{ matrix.ghc }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
ghc: ['9.6.7']
steps:
- name: Free disk space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: true
dotnet: true
haskell: false
large-packages: false
docker-images: true
swap-storage: true
- uses: actions/checkout@v4
with:
submodules: false
# The runner's workspace disk (/) is small; /mnt has ~70 GB. Bind-mount it as
# _build so the GHC build has room. docker -v is recursive, so this nested
# mount is visible inside the container at /workspace/_build.
- name: Build on the large /mnt disk
run: |
sudo mkdir -p /mnt/_build
mkdir -p "$GITHUB_WORKSPACE/_build"
sudo mount --bind /mnt/_build "$GITHUB_WORKSPACE/_build"
sudo chown "$USER" "$GITHUB_WORKSPACE/_build"
# The static plugin baked into uplc-ghc is built from the plutus submodule.
- name: Init and update submodules
run: |
git submodule sync
git submodule update --init --recursive --depth 1 --jobs 4
# BINDIST=1 produces the fixed-up uplc-ghc bindist (+ .tar.xz). plinth-build.sh
# appends a -musl suffix to the archive name when run on musl libc.
- name: Build uplc-ghc bindist (Alpine/musl)
run: |
docker run --rm \
-v "$GITHUB_WORKSPACE:/workspace" -w /workspace \
-e BINDIST=1 -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 \
alpine:3.20 sh -c '
set -eux
. ./.github/alpine-setup.sh
./plinth-build.sh
'
- name: Upload uplc-ghc bindist (musl)
uses: actions/upload-artifact@v4
with:
name: plinth-bindist-musl-${{ matrix.os }}-${{ matrix.ghc }}
path: _build/bindist/*.tar.xz
retention-days: 1
# the archive is already xz-compressed; don't re-zip it
compression-level: 0
# musl test, mirroring plinth-test-linux: consume the musl bindist, install it
# and run the test suite inside alpine:3.20. Depends on plinth-build-linux-musl.
plinth-test-linux-musl:
name: plinth-test / ${{ matrix.os }} (musl) / ghc ${{ matrix.ghc }}
needs: plinth-build-linux-musl
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
ghc: ['9.6.7']
steps:
- name: Free disk space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: true
dotnet: true
haskell: false
large-packages: false
docker-images: true
swap-storage: true
- uses: actions/checkout@v4
with:
submodules: false
# plinth/test/cabal.project pulls plutus-tx/plutus-core/plutus-ledger-api
# from the plutus submodule.
- name: Init and update submodules
run: |
git submodule sync
git submodule update --init --recursive --depth 1 --jobs 4
# A single Plinth plugin compile of a makeLift-heavy module
# (PlutusLedgerApi.V3.Contexts) spikes past the ~16 GB runner RAM and gets
# OOM-killed even with JOBS=1. Add a 16 GB swapfile on the large /mnt disk
# so the spike spills to swap; the container shares the host's memory+swap.
- name: Add 16 GB swap
run: |
sudo fallocate -l 16G /mnt/swapfile
sudo chmod 600 /mnt/swapfile
sudo mkswap /mnt/swapfile
sudo swapon /mnt/swapfile
swapon --show
free -h
- name: Download uplc-ghc bindist (musl)
uses: actions/download-artifact@v4
with:
name: plinth-bindist-musl-${{ matrix.os }}-${{ matrix.ghc }}
path: _build/artifact
# Install the musl bindist (configure + make install) and run the test suite
# inside Alpine. Mirrors the glibc test job's install guards (exactly one
# archive, exactly one extracted dir, executable check) and JOBS=1.
- name: Install and test uplc-ghc (Alpine/musl)
run: |
docker run --rm \
-v "$GITHUB_WORKSPACE:/workspace" -w /workspace \
-e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 \
alpine:3.20 sh -c '
set -eux
. ./.github/alpine-setup.sh
archives=$(ls _build/artifact/*.tar.xz)
n=$(echo "$archives" | wc -l)
if [ "$n" -ne 1 ]; then
echo "error: expected exactly one bindist archive, found: ${archives:-none}"
exit 1
fi
mkdir -p _build/bindist
echo "extracting $archives"
tar --xz -xf "$archives" -C _build/bindist
bindirs=$(ls -d _build/bindist/ghc-*)
if [ "$(echo "$bindirs" | wc -l)" -ne 1 ]; then
echo "error: expected one extracted bindist dir, found: ${bindirs:-none}"
exit 1
fi
( cd "$bindirs" && ./configure --prefix=/workspace/_build/install && make install )
uplc=/workspace/_build/install/bin/uplc-ghc
if [ ! -x "$uplc" ]; then
echo "error: $uplc missing or not executable after make install"
ls -l /workspace/_build/install/bin || true
exit 1
fi
rm -rf _build/artifact
JOBS=1 GHC="$uplc" ./plinth-test.sh
'
plinth-build-windows:
name: plinth-build / windows-latest / ghc ${{ matrix.ghc }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
ghc: ['9.6.7']
defaults:
run:
shell: msys2 {0}
steps:
# Git on Windows defaults to not creating symlinks; the submodules and
# bindist rely on them, so enable symlink support before checkout.
- name: Configure git for Windows
shell: bash
run: git config --global core.symlinks true
- uses: actions/checkout@v4
with:
submodules: false
# The pre-MSYS2 step runs in the default Git-for-Windows bash because the
# MSYS2 environment is not set up yet. All submodules are public HTTPS, so
# no credentials are needed.
- name: Init and update submodules
shell: bash
run: |
git submodule sync
# Shallow (single-commit) submodule clones: the build never needs
# submodule history, and these 29 submodules (notably plutus) carry a
# lot of it. --jobs fetches them in parallel. GitHub allows fetching
# the pinned SHA directly, so depth 1 works even when it isn't a
# branch tip.
git submodule update --init --recursive --depth 1 --jobs 4
# MINGW64 toolchain + the autotools/python/sphinx needed by the build.
# path-type: inherit keeps the Windows PATH (incl. the GHC/cabal installed
# below) visible inside the MSYS2 shell.
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
path-type: inherit
update: false
install: >-
autoconf automake make tar xz patch curl
mingw-w64-x86_64-python mingw-w64-x86_64-python-sphinx
- uses: haskell-actions/setup@v2
id: setup
name: Setup Haskell tools
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: "latest"
cabal-update: true
# BINDIST=1 produces the fixed-up uplc-ghc bindist (+ .tar.xz archive); the
# plinth-test-windows job consumes that archive instead of rebuilding.
- name: Build uplc-ghc bindist
run: BINDIST=1 ./plinth-build.sh
- name: Upload uplc-ghc bindist
uses: actions/upload-artifact@v4
with:
# key by GHC so this never collides with another job's artifact within a
# run. See the matching download in the plinth-test-windows job.
name: plinth-bindist-windows-${{ matrix.ghc }}
path: _build/bindist/*.tar.xz
retention-days: 1
# the archive is already xz-compressed; don't re-zip it
compression-level: 0
# plinth-test on Windows, mirroring plinth-test-linux: consume the bindist
# produced by plinth-build-windows, install it (configure + make install under
# MSYS2) and run the test suite. Depends on plinth-build-windows.
plinth-test-windows:
name: plinth-test / windows-latest / ghc ${{ matrix.ghc }}
needs: plinth-build-windows
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
ghc: ['9.6.7']
defaults:
run:
shell: msys2 {0}
steps:
# Git on Windows defaults to not creating symlinks; the submodules and the
# bindist's wrappers/ dir rely on them, so enable symlink support first.
- name: Configure git for Windows
shell: bash
run: git config --global core.symlinks true
- uses: actions/checkout@v4
with:
submodules: false
# The pre-MSYS2 step runs in the default Git-for-Windows bash because the
# MSYS2 environment is not set up yet. plinth/test/cabal.project pulls
# plutus-tx/plutus-core/plutus-ledger-api from the plutus submodule.
- name: Init and update submodules
shell: bash
run: |
git submodule sync
# Shallow (single-commit) submodule clones: the build never needs
# submodule history. --jobs fetches them in parallel.
git submodule update --init --recursive --depth 1 --jobs 4
# MINGW64 toolchain incl. tar/xz to extract the bindist. path-type: inherit
# keeps the Windows PATH (incl. the cabal installed below) visible.
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
path-type: inherit
update: false
install: >-
autoconf automake make tar xz patch curl
mingw-w64-x86_64-python mingw-w64-x86_64-python-sphinx
# plinth-test.sh invokes cabal, so cabal must be on PATH. (The boot GHC this
# also installs is unused by the test.)
- uses: haskell-actions/setup@v2
id: setup
name: Setup Haskell tools
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: "latest"
cabal-update: true
- name: Download uplc-ghc bindist
uses: actions/download-artifact@v4
with:
# matches the plinth-build-windows upload name.
name: plinth-bindist-windows-${{ matrix.ghc }}
path: _build/artifact
# Unlike Unix, the Windows GHC bindist has no configure/make install: it is
# relocatable, so we just extract it and run bin/uplc-ghc.exe in place.
- name: Extract uplc-ghc bindist
run: |
shopt -s nullglob
archives=(_build/artifact/*.tar.xz)
if [ ${#archives[@]} -ne 1 ]; then
echo "error: expected exactly one bindist archive, found: ${archives[*]:-none}"
exit 1
fi
mkdir -p _build/install
echo "extracting ${archives[0]}"
tar --xz -xf "${archives[0]}" -C _build/install
bindirs=(_build/install/ghc-*)
if [ ${#bindirs[@]} -ne 1 ]; then
echo "error: expected one extracted bindist dir, found: ${bindirs[*]:-none}"
exit 1
fi
uplc="${bindirs[0]}/bin/uplc-ghc.exe"
if [ ! -x "$uplc" ]; then
echo "error: $uplc missing or not executable in extracted bindist"
ls -l "${bindirs[0]}/bin" || true
exit 1
fi
rm -rf _build/artifact
# Build packages serially (JOBS=1): compiling with the Plinth plugin
# (Core -> PLC) is memory-heavy. Pass GHC as an absolute path: plinth-test.sh
# cd's into plinth/test before invoking cabal, so a repo-root-relative path
# would be resolved against the wrong directory.
- name: Test uplc-ghc
run: |
bindirs=(_build/install/ghc-*)
JOBS=1 GHC="$(pwd)/${bindirs[0]}/bin/uplc-ghc.exe" ./plinth-test.sh
# macOS build, mirroring plinth-build-linux. macOS uses the Unix bindist
# (configure + make install), so the build is much like Linux; the
# differences are: no /mnt large-disk mount (the runner's disk is large
# enough for the lean flavour) and autoconf/automake come from Homebrew
# rather than the base image. Runs on Apple Silicon (aarch64-darwin).
plinth-build-macos:
name: plinth-build / macos-15 / ghc ${{ matrix.ghc }}
runs-on: macos-15
strategy:
fail-fast: false
matrix:
ghc: ['9.6.7']
steps:
- uses: actions/checkout@v4
with:
submodules: false
# The static plugin baked into uplc-ghc is built from the plutus submodule.
- name: Init and update submodules
run: |
git submodule sync
# Shallow (single-commit) submodule clones: the build never needs
# submodule history. --jobs fetches them in parallel.
git submodule update --init --recursive --depth 1 --jobs 4
# The GHC source build's boot step runs autoreconf, which needs
# autoconf/automake; they are not in the macOS runner image. The lean
# BINDIST flavour builds with --docs=none, so no sphinx is needed.
- name: Install autotools (macOS)
run: brew install autoconf automake
- uses: haskell-actions/setup@v2
id: setup
name: Setup Haskell tools
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: "latest"
cabal-update: true
# BINDIST=1 produces the fixed-up uplc-ghc bindist (+ .tar.xz archive); the
# plinth-test-macos job consumes that archive instead of rebuilding.
- name: Build uplc-ghc bindist
run: BINDIST=1 ./plinth-build.sh
- name: Upload uplc-ghc bindist
uses: actions/upload-artifact@v4
with:
# key by GHC so this never collides with another job's artifact within a
# run. See the matching download in the plinth-test-macos job.
name: plinth-bindist-macos-${{ matrix.ghc }}
path: _build/bindist/*.tar.xz
retention-days: 1
# the archive is already xz-compressed; don't re-zip it
compression-level: 0
# plinth-test on macOS, mirroring plinth-test-linux: consume the bindist
# produced by plinth-build-macos, install it (configure + make install) and
# run the test suite. Depends on plinth-build-macos.
plinth-test-macos:
name: plinth-test / macos-15 / ghc ${{ matrix.ghc }}
needs: plinth-build-macos
runs-on: macos-15
strategy:
fail-fast: false
matrix:
ghc: ['9.6.7']
steps:
- uses: actions/checkout@v4
with:
submodules: false
# plinth/test/cabal.project pulls plutus-tx/plutus-core/plutus-ledger-api
# from the plutus submodule.
- name: Init and update submodules
run: |
git submodule sync
git submodule update --init --recursive --depth 1 --jobs 4
# plinth-test.sh invokes cabal, so cabal must be on PATH. (The boot GHC this
# also installs is unused by the test.)
- uses: haskell-actions/setup@v2
id: setup
name: Setup Haskell tools
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: "latest"
cabal-update: true
- name: Download uplc-ghc bindist
uses: actions/download-artifact@v4
with:
# matches the plinth-build-macos upload name.
name: plinth-bindist-macos-${{ matrix.ghc }}
path: _build/artifact
# Install the bindist with the usual configure + make install; the bindist's
# wrappers/ dir (added by the BINDIST fixup) makes this produce bin/uplc-ghc.
# Each step is guarded so a missing artifact or failed install fails loudly
# here, not with a confusing error deep in the test.
- name: Install uplc-ghc bindist
run: |
shopt -s nullglob
archives=(_build/artifact/*.tar.xz)
if [ ${#archives[@]} -ne 1 ]; then
echo "error: expected exactly one bindist archive, found: ${archives[*]:-none}"
exit 1
fi
mkdir -p _build/bindist
echo "extracting ${archives[0]}"
tar --xz -xf "${archives[0]}" -C _build/bindist
bindirs=(_build/bindist/ghc-*)
if [ ${#bindirs[@]} -ne 1 ]; then
echo "error: expected one extracted bindist dir, found: ${bindirs[*]:-none}"
exit 1
fi
( cd "${bindirs[0]}" && ./configure --prefix="$GITHUB_WORKSPACE/_build/install" && make install )
uplc="$GITHUB_WORKSPACE/_build/install/bin/uplc-ghc"
if [ ! -x "$uplc" ]; then
echo "error: $uplc missing or not executable after make install"
ls -l "$GITHUB_WORKSPACE/_build/install/bin" || true
exit 1
fi
rm -rf _build/artifact
# Build packages serially (JOBS=1): compiling with the Plinth plugin
# (Core -> PLC) is memory-heavy. A single makeLift-heavy compile
# (PlutusLedgerApi.V3.Contexts) spikes well past the runner's RAM; unlike
# the Linux job (explicit swapfile) macOS grows its swap dynamically, so the
# spike spills to swap on its own and no swap-setup step is needed here.
- name: Test uplc-ghc
run: JOBS=1 GHC="$GITHUB_WORKSPACE/_build/install/bin/uplc-ghc" ./plinth-test.sh
# ghcup install tests: verify each platform's bindist installs cleanly as the
# custom `plinth` ghcup tool -- the same path end users take -- on every push,
# not just on tags. Each mirrors its plinth-test-* sibling but installs via
# ghcup + generate-ghcup-metadata.py (file:// metadata) instead of a bare
# configure+make, so a broken dlInstallSpec / generator / metadata schema is
# caught in the PR that introduces it. plinth-ghcup-test.sh does the work; it
# needs only the bindist tarball + python3 + a ghcup >= 0.2.1.0 (no GHC
# rebuild, no submodules -- the sample it compiles is plain Haskell).
plinth-ghcup-test-linux:
name: plinth-ghcup-test / ${{ matrix.os }} / ghc ${{ matrix.ghc }}
needs: plinth-build-linux
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
ghc: ['9.6.7']
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Download uplc-ghc bindist
uses: actions/download-artifact@v4
with:
name: plinth-bindist-${{ matrix.os }}-${{ matrix.ghc }}
path: _build/artifact
# A stock ghcup for this architecture; the installer DSL needs >= 0.2.1.0
# (plinth-ghcup-test.sh capability-gates on it).
- name: Install stock ghcup
run: |
set -eux
mkdir -p "$HOME/.local/bin"
curl -fL "https://downloads.haskell.org/~ghcup/$(uname -m)-linux-ghcup" \
-o "$HOME/.local/bin/ghcup"
chmod +x "$HOME/.local/bin/ghcup"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Install and test uplc-ghc via ghcup
run: BINDIST_DIR=_build/artifact ./plinth-ghcup-test.sh
plinth-ghcup-test-linux-musl:
name: plinth-ghcup-test / ${{ matrix.os }} (musl) / ghc ${{ matrix.ghc }}
needs: plinth-build-linux-musl
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
ghc: ['9.6.7']
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Download uplc-ghc bindist (musl)
uses: actions/download-artifact@v4
with:
name: plinth-bindist-musl-${{ matrix.os }}-${{ matrix.ghc }}
path: _build/artifact
# Run inside Alpine so the musl uplc-ghc can execute. Unlike the build/test
# jobs we do NOT source alpine-setup.sh: that bootstraps a full boot GHC +
# cabal we would never use here. Instead install just the deps needed to run
# uplc-ghc and link the sample, and download the ghcup binary directly --
# the same x86_64/aarch64-linux ghcup the official installer uses on Alpine.
#
# coreutils/findutils/grep are the GNU tools the bindist's `make install`
# (which ghcup runs for us) is exercised with upstream; busybox's applets
# differ in flag support, so don't rely on them for that path.
#
# EXPECT_MUSL=1 asserts the artifact really is the musl bindist: the ghcup
# platform is derived from the bindist name, and a musl bindist mislabelled
# as glibc installs fine here while being broken for users on Alpine.
- name: Install and test uplc-ghc via ghcup (Alpine/musl)
run: |
docker run --rm \
-v "$GITHUB_WORKSPACE:/workspace" -w /workspace \
-e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 \
alpine:3.20 sh -c '
set -eux
apk add --no-cache bash build-base coreutils curl findutils grep \
gmp-dev ncurses-dev python3 tar xz
mkdir -p "$HOME/.local/bin"
curl -fL "https://downloads.haskell.org/~ghcup/$(uname -m)-linux-ghcup" \
-o "$HOME/.local/bin/ghcup"
chmod +x "$HOME/.local/bin/ghcup"
BINDIST_DIR=_build/artifact GHCUP_BIN="$HOME/.local/bin/ghcup" \
EXPECT_MUSL=1 bash ./plinth-ghcup-test.sh
'
plinth-ghcup-test-macos:
name: plinth-ghcup-test / macos-15 / ghc ${{ matrix.ghc }}
needs: plinth-build-macos
runs-on: macos-15
strategy:
fail-fast: false
matrix:
ghc: ['9.6.7']
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Download uplc-ghc bindist
uses: actions/download-artifact@v4
with:
name: plinth-bindist-macos-${{ matrix.ghc }}
path: _build/artifact
# macos-15 is Apple Silicon (aarch64-apple-darwin).
- name: Install stock ghcup
run: |
set -eux
mkdir -p "$HOME/.local/bin"
curl -fL "https://downloads.haskell.org/~ghcup/aarch64-apple-darwin-ghcup" \
-o "$HOME/.local/bin/ghcup"
chmod +x "$HOME/.local/bin/ghcup"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Install and test uplc-ghc via ghcup
run: BINDIST_DIR=_build/artifact ./plinth-ghcup-test.sh
plinth-ghcup-test-windows:
name: plinth-ghcup-test / windows-latest / ghc ${{ matrix.ghc }}
needs: plinth-build-windows
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
ghc: ['9.6.7']
defaults:
run:
shell: msys2 {0}
steps:
# The bindist / ghcup use symlinks; enable them before checkout.
- name: Configure git for Windows
shell: bash
run: git config --global core.symlinks true
- uses: actions/checkout@v4
with:
submodules: false
# python3 (for generate-ghcup-metadata.py) + tar/xz/curl to fetch ghcup and
# unpack. cygpath (used by plinth-ghcup-test.sh for native/MSYS path
# translation) is part of the base MSYS2 install.
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
path-type: inherit
update: false
install: >-
tar xz curl mingw-w64-x86_64-python
- name: Download uplc-ghc bindist
uses: actions/download-artifact@v4
with:
name: plinth-bindist-windows-${{ matrix.ghc }}
path: _build/artifact
- name: Install stock ghcup
run: |
set -eux
mkdir -p "$HOME/.local/bin"
curl -fL "https://downloads.haskell.org/~ghcup/x86_64-mingw64-ghcup.exe" \
-o "$HOME/.local/bin/ghcup.exe"
- name: Install and test uplc-ghc via ghcup
run: BINDIST_DIR=_build/artifact GHCUP_BIN="$HOME/.local/bin/ghcup.exe" ./plinth-ghcup-test.sh
# Note [ghcup release channel]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# On a v* tag, publish the per-platform bindists as a GitHub Release and
# (re)generate the ghcup channel metadata on the gh-pages branch. uplc-ghc is
# distributed as a custom third-party ghcup tool named `plinth`, installable
# with a stock ghcup >= 0.2.1.0 (installer DSL). Users then run:
# ghcup config add-release-channel \
# https://input-output-hk.github.io/ghc-plinth/ghcup-plinth.yaml
# ghcup install plinth <version>
#
# The generator (generate-ghcup-metadata.py) accumulates every released
# version into gh-pages/ghcup-plinth.versions.json and re-emits the channel
# YAML, so old versions stay installable. Before publishing, we validate the
# metadata end-to-end by installing plinth from a file:// copy of it (real
# download + configure + make + symlink), decoupled from the not-yet-public
# release URLs.
release:
name: release / ghcup channel
if: startsWith(github.ref, 'refs/tags/')
# Gate publishing on the per-platform ghcup install tests (which transitively
# require the build jobs and their uploaded bindist artifacts).
needs:
- plinth-ghcup-test-linux
- plinth-ghcup-test-linux-musl
- plinth-ghcup-test-windows
- plinth-ghcup-test-macos
runs-on: ubuntu-latest
# Overrides the top-level `contents: read`: this job creates a Release and
# pushes the regenerated channel to gh-pages.
permissions:
contents: write
env:
TAG: ${{ github.ref_name }}
steps:
- uses: actions/checkout@v4
with:
submodules: false
# Collect every platform's bindist tarball into dist/. Each artifact holds a
# single ghc-<ver>-<platform>[-musl].tar.xz with a distinct name, so
# merge-multiple flattens them without collisions.
- name: Download all bindists
uses: actions/download-artifact@v4
with:
pattern: plinth-bindist-*
path: dist
merge-multiple: true
- name: List bindists and set version
run: |
set -eux
ls -l dist/*.tar.xz
# ghcup tool version: the tag without the leading 'v'.
echo "VERSION=${TAG#v}" >> "$GITHUB_ENV"
# The install is already validated end-to-end on every platform by the
# plinth-ghcup-test-* jobs this job `needs`, so no re-validation here.
# Publish the Release with all tarballs. Create it if missing, otherwise
# (re-)upload the assets.
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -eux
if ! gh release view "$TAG" >/dev/null 2>&1; then
gh release create "$TAG" \
--title "uplc-ghc $VERSION" \
--notes "Plinth standalone compiler (uplc-ghc) bindists for $VERSION. Install via ghcup: see README." \
dist/*.tar.xz
else
gh release upload "$TAG" dist/*.tar.xz --clobber
fi
# Regenerate the channel on gh-pages with the real Release download URLs and
# push it. The generator merges into the existing versions DB so previously
# released versions remain in the channel.
- name: Check out gh-pages
uses: actions/checkout@v4
with:
ref: gh-pages
path: gh-pages-out
- name: Regenerate and publish ghcup channel
run: |
set -eux
python3 generate-ghcup-metadata.py \
--version "$VERSION" \
--base-url "https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}" \
--db gh-pages-out/ghcup-plinth.versions.json \
--output gh-pages-out/ghcup-plinth.yaml \
--release-day "$(date -u +%Y-%m-%d)" \
--set-latest \
dist/*.tar.xz
cd gh-pages-out
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add ghcup-plinth.yaml ghcup-plinth.versions.json
git commit -m "ghcup channel: publish plinth ${VERSION} (${TAG})" || echo "no changes to commit"
git push