Skip to content

Haskell CI (WASM) #1582

Haskell CI (WASM)

Haskell CI (WASM) #1582

Workflow file for this run

name: Haskell CI (WASM)
on:
merge_group:
pull_request:
push:
# we need this to populate cache for `master` branch to make it available to the child branches, see
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache
branches:
- master
# GH caches are removed when not accessed within 7 days - this schedule runs the job every 6 days making
# sure that we always have some caches on master
# schedule:
# - cron: '0 0 */6 * *'
jobs:
build:
runs-on: ${{ matrix.sys.os }}
strategy:
fail-fast: false
matrix:
sys:
- { os: ubuntu-latest, shell: bash }
# - { os: macos-latest, shell: bash }
defaults:
run:
shell: ${{ matrix.sys.shell }}
env:
# Modify this value to "invalidate" the cabal cache.
CABAL_CACHE_VERSION: "2025-05-29"
concurrency:
group: >
wasm
a+${{ github.event_name }}
b+${{ github.workflow_ref }}
c+${{ github.job }}
f+${{ matrix.sys.os }}
g+${{ (startsWith(github.ref, 'refs/heads/gh-readonly-queue/') && github.run_id) || github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Concurrency group
run: >
echo
wasm
a+${{ github.event_name }}
b+${{ github.workflow_ref }}
c+${{ github.job }}
f+${{ matrix.sys.os }}
g+${{ (startsWith(github.ref, 'refs/heads/gh-readonly-queue/') && github.run_id) || github.event.pull_request.number || github.ref }}
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=
substituters = https://cache.iog.io/ https://cache.nixos.org/
- uses: rrbutani/use-nix-shell-action@v1
with:
devShell: .#wasm
- name: Cabal update
run: |
wasm32-wasi-cabal update
# A dry run `build all` operation does *NOT* downlaod anything, it just looks at the package
# indices to generate an install plan.
- name: Build dry run
run: |
wasm32-wasi-cabal build cardano-wasm --dry-run
# From the install plan we generate a dependency list.
- name: Record dependencies
id: record-deps
run: |
cat dist-newstyle/cache/plan.json | jq -r '."install-plan"[] | select(.style != "local") | .id' | sort | uniq > dependencies.txt
- name: Store month number as environment variable used in cache version
run: |
cat <<EOF >> $GITHUB_ENV
MONTHNUM=$(date -u '+%m')
GHC=$(ghc --numeric-version)
STORE=$(wasm32-wasi-cabal path --store | tail -n 1)
EOF
# Cache is disabled because GHA default builders are not able to build all dependencies
# because they lack RAM, so having the cache expire would break the CI check.
# For this reason, we are providing a build of the dependencies instead in
# the "Restore cached deps" step, and we make the check not required.
# When we are able to make this CI check self-sufficient, we should reenable the
# caching and remove the manual restoring of cached deps.
# From the dependency list we restore the cached dependencies.
# We use the hash of `dependencies.txt` as part of the cache key because that will be stable
# until the `index-state` values in the `cabal.project` file changes.
# - name: Restore cached dependencies
# uses: actions/cache/restore@v4
# id: cache
# with:
# path: |
# ${{ env.STORE }}
# dist-newstyle
# key:
# wasm-cache-${{ env.CABAL_CACHE_VERSION }}-${{ runner.os }}-${{ env.GHC }}-${{ hashFiles('cardano-wasm/dependencies.txt') }}
# restore-keys: |
# wasm-cache-${{ env.CABAL_CACHE_VERSION }}-${{ runner.os }}-${{ env.GHC }}-
- name: Restore cached deps
run: |
wget "https://agrius.feralhosting.com/palas/wasm-cache/3cb3dd8c0e361bcde820ee8c1eb1270346b54c06024aaa7500c4da2a74e2be79.tar.xz"
tar -xf 3cb3dd8c0e361bcde820ee8c1eb1270346b54c06024aaa7500c4da2a74e2be79.tar.xz
rm 3cb3dd8c0e361bcde820ee8c1eb1270346b54c06024aaa7500c4da2a74e2be79.tar.xz
rm -fr ~/.ghc-wasm/.cabal/store/
mv store ~/.ghc-wasm/.cabal/
# Now we install the dependencies. If the cache was found and restored in the previous step,
# this should be a no-op, but if the cache key was not found we need to build stuff so we can
# cache it for the next step.
- name: Install dependencies
run: |
wasm32-wasi-cabal build cardano-wasm --only-dependencies --no-semaphore -j1 --ghc-options="-j1"
# Always store the cabal cache.
# - name: Cache Cabal store
# uses: actions/cache/save@v4
# if: always()
# with:
# path: |
# ${{ env.STORE }}
# dist-newstyle
# key:
# ${{ steps.cache.outputs.cache-primary-key }}
# Now we build.
- name: Build all
run: |
wasm32-wasi-cabal build cardano-wasm --no-semaphore -j1 --ghc-options="-j1"
wasm32-wasi-cabal build cardano-wasi --no-semaphore -j1 --ghc-options="-j1"
wasm-opt -O4 $(env -u CABAL_CONFIG wasm32-wasi-cabal list-bin exe:cardano-wasi | tail -n1) -o cardano-wasm/cardano-wasi.wasm
- name: Prepare example
run: |
wasm-opt -Oz $(env -u CABAL_CONFIG wasm32-wasi-cabal list-bin exe:cardano-wasm | tail -n1) -o cardano-wasm/lib-wrapper/cardano-wasm.wasm
$(wasm32-wasi-ghc --print-libdir)/post-link.mjs -i "$(env -u CABAL_CONFIG wasm32-wasi-cabal list-bin exe:cardano-wasm | tail -n1)" -o cardano-wasm/lib-wrapper/cardano-wasm.js
cp cardano-wasm/lib-wrapper/* cardano-wasm/examples/basic/
- name: Build grpc bridge
run: |
nix build .#proto-js-bundle
- name: Prepare NPM package
run: |
cp cardano-wasm/lib-wrapper/* cardano-wasm/npm-wrapper/src/
rm cardano-wasm/npm-wrapper/src/cardano-api.js
cp result/cardano_node_grpc_web_pb.js cardano-wasm/npm-wrapper/src/
cp -r result/node cardano-wasm/npm-wrapper/src/
cd cardano-wasm/npm-wrapper
npm install
npm run build
npm test
npm pack
- name: Prepare webpack test
run: |
cp cardano-wasm/npm-wrapper/*.tgz cardano-wasm/npm-test/webpack/
cd cardano-wasm/npm-test/webpack
npm install ./*.tgz
npx webpack serve --port 8081 &
cd ../../..
- uses: rrbutani/use-nix-shell-action@v1
with:
devShell: .#playwright
- name: Run playwright test in example and webpack test
run: |
httpserver -h localhost -a 127.0.0.1 -p 8080 cardano-wasm/examples/basic &
playwright test cardano-wasm/js-test/basic-test.spec.ts
playwright test cardano-wasm/npm-test/webpack-test.spec.ts
# - name: Run tests
# env:
# TMPDIR: ${{ runner.temp }}
# TMP: ${{ runner.temp }}
# KEEP_WORKSPACE: 1
# run: cabal test all --enable-tests --test-show-details=direct
# Uncomment the following back in for debugging. Remember to launch a `pwsh` from
# the tmux session to debug `pwsh` issues. And be reminded that the `/msys2` and
# `/msys2/mingw64` paths are not in PATH by default for the workflow, but tmate
# will put them in.
# You may also want to run
#
# $env:PATH=("C:\Program Files\PowerShell\7;{0}" -f $env:ORIGINAL_PATH)
#
# to restore the original path. Do note that some test might need msys2
# and will silently fail if msys2 is not in path. See the "Run tests" step.
#
# - name: Setup tmate session
# if: ${{ failure() }}
# uses: mxschmitt/action-tmate@v3
# with:
# limit-access-to-actor: true
- name: Prepare wasm library
run: |
cp result/cardano_node_grpc_web_pb.js cardano-wasm/lib-wrapper/
- name: Test NPM package with node.js
run: |
export TMPDIR=$(mktemp -d)
cp cardano-wasm/npm-test/node.test.js $TMPDIR/
cp cardano-wasm/npm-wrapper/*.tgz $TMPDIR/
cd $TMPDIR
npm install ./*.tgz
node node.test.js
cd -
- name: Upload built wasm library
uses: actions/upload-artifact@v4
with:
name: cardano-wasm
path: cardano-wasm/lib-wrapper/*
compression-level: 9
- name: Upload pure WASI wasm binary
uses: actions/upload-artifact@v4
with:
name: cardano-wasi
path: cardano-wasm/cardano-wasi.wasm
compression-level: 9
- name: Upload built NPM package
uses: actions/upload-artifact@v4
with:
name: npm-package
path: cardano-wasm/npm-wrapper/*.tgz
wasm-builds-complete:
needs: [build]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Check if any previous job failed
run: |
if [[ "${{ needs.build.result }}" == "failure" ]]; then
# this ignores skipped dependencies
echo 'Required jobs failed to build.'
exit 1
else
echo 'Build complete'
fi