Skip to content

WIP

WIP #16237

Workflow file for this run

name: Haskell CI
# If it's a scheduled (for us: nightly) build, set the name of this run to a static value, so we can identify it easier.
# Otherwise, replicate the default run name: either the PR title if it exists, or the commit message otherwise.
run-name: |
${{github.event_name == 'schedule' && 'Haskell CI - NIGHTLY'
|| github.event.pull_request.title == '' && github.event.head_commit.message
|| github.event.pull_request.title}}
on:
push:
branches: [ "master", "release/**" ]
pull_request:
branches: [ "**" ]
schedule:
# "Nightly" builds: Every day at 06:00 UTC
- cron: '0 6 * * *'
# for running the workflow manually - useful for branches without PRs, for which jobs don't get ran automatically
workflow_dispatch:
inputs:
nightly:
description: Run with the same settings as a nightly build
type: boolean
default: false
# Cancel running workflows when a new workflow on the same PR or branch is started,
# but put scheduled workflows into their own group
concurrency:
group: ${{
format('{0}-{1}{2}',
github.workflow,
github.event.pull_request.number || github.ref,
github.event_name == 'schedule' && '-scheduled' || '')}}
cancel-in-progress: true
jobs:
build:
strategy:
matrix:
ghc: ["8.10.7", "9.2.8", "9.6.6", "9.8.2", "9.10.1"]
os: [ubuntu-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
env:
# Modify this value to "invalidate" the cabal cache.
CABAL_CACHE_VERSION: "2024-09-23"
# current ref from: 27.02.2022
SECP256K1_REF: ac83be33d0956faf6b7f61a60ab524ef7d6a473a
SECP_CACHE_VERSION: "2022-12-30"
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Free up disk space
run: |
# Remove software and language runtimes we're not using
sudo rm -rf \
"$AGENT_TOOLSDIRECTORY" \
/opt/google/chrome \
/opt/microsoft/msedge \
/opt/microsoft/powershell \
/opt/pipx \
/usr/lib/mono \
/usr/local/julia* \
/usr/local/lib/android \
/usr/local/lib/node_modules \
/usr/local/share/chromium \
/usr/local/share/powershell \
/usr/share/dotnet \
/usr/share/swift
df -h /
- name: Install system dependencies
uses: input-output-hk/actions/base@latest
with:
use-sodium-vrf: false # default is true
- name: Install Haskell
id: install-haskell
uses: input-output-hk/actions/haskell@latest
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: 3.12.1.0
- name: Configure to use libsodium
run: |
cat >> cabal.project <<EOF
package cardano-crypto-praos
flags: -external-libsodium-vrf
EOF
- name: Configure to limit the heap size for ghc 8
if: startsWith(${{ matrix.ghc }}, 8)
run: |
cat >> cabal.project <<EOF
with-compiler: $PWD/scripts/ghc-limited
with-hc-pkg: ghc-pkg
EOF
echo "GHC_HEAP_LIMIT=12" >> $GITHUB_ENV
- name: Cabal update
run: cabal update
# We create a dependencies.txt file that can be used to index the cabal
# store cache.
#
# We do not use plan.json directly because adding a dependency to our
# Cabal files which was already present somewhere else would result in a
# diferent plan, even though the set of dependencies is the same.
- name: Record dependencies to be used as cache keys
id: record-deps
run: |
cabal build all --enable-tests --dry-run --minimize-conflict-set
cat dist-newstyle/cache/plan.json \
| jq '.["install-plan"][].id' \
| sort \
| uniq \
| tee dependencies.txt
- name: Restore cache
uses: actions/cache/restore@v4
id: restore-cabal-cache
env:
cache-name: cache-cabal-build
with:
path: |
${{ steps.install-haskell.outputs.cabal-store }}
# A new cache is created upon a change to the cabal build plan,
# cabal.project (and/or cabal.project.local), or a bump to
# CABAL_CACHE_VERSION.
key: ${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('dependencies.txt') }}-${{ hashFiles('cabal.project*') }}
# Restoring attempts are from current branch then master. The key above
# is by default already a restore-key.
restore-keys: |
${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('dependencies.txt') }}
${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-
- name: Check workflow test matrix
run: cabal build all --dry-run && scripts/check-workflow-test-matrix.hs
- name: Build dependencies
id: build-dependencies
run: cabal build all --only-dependencies
# Save the cache of built dependencies early, so that it is available for
# the next GHA run if the Build step fails.
- name: Save cache
uses: actions/cache/save@v4
id: save-cabal-cache
# Note: cache-hit will be set to true only when cache hit occurs for the
# exact key match. For a partial key match via restore-keys or a cache
# miss, it will be set to false.
if: steps.build-dependencies.outcome == 'success' && steps.restore-cabal-cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.install-haskell.outputs.cabal-store }}
key: ${{ steps.restore-cabal-cache.outputs.cache-primary-key }}
- name: Build
run: cabal build all
# Pass working directory to test jobs
- name: Archive working directory
# pax format is needed to avoid unnecessary rebuilding, because the
# default format uses a one-second resolution for timestamps
run: tar --use-compress-program zstdmt --format posix --exclude-vcs -cf /var/tmp/state.tzst . && mv /var/tmp/state.tzst .
- name: Upload working directory archive
# upload-artifact is pinned to avoid a bug in download-artifact
# See https://github.com/actions/download-artifact/issues/328
uses: actions/upload-artifact@v4.2.0
with:
name: state-${{ matrix.ghc }}-${{ matrix.os }}
path: state.tzst
overwrite: true
retention-days: 1
test:
needs: build
strategy:
matrix:
package:
- byron-spec-chain
- byron-spec-ledger
- cardano-crypto-wrapper
- cardano-data
- cardano-ledger-allegra
- cardano-ledger-alonzo
- cardano-ledger-alonzo-test
- cardano-ledger-api
- cardano-ledger-babbage
- cardano-ledger-babbage-test
- cardano-ledger-binary
- cardano-ledger-byron
- cardano-ledger-conformance
- cardano-ledger-conway
- cardano-ledger-conway-test
- cardano-ledger-core
- cardano-ledger-mary
- cardano-ledger-shelley
- cardano-ledger-shelley-ma-test
- cardano-ledger-shelley-test
- cardano-ledger-test
- cardano-protocol-tpraos
- constrained-generators
- non-integral
- set-algebra
- small-steps
- vector-map
ghc: ["8.10.7", "9.2.8", "9.6.6", "9.8.2", "9.10.1"]
os: [ubuntu-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
name: ${{ matrix.package }}-${{ matrix.ghc }}-${{ matrix.os }}
env:
# Modify this value to "invalidate" the cabal cache.
CABAL_CACHE_VERSION: "2024-09-23"
# current ref from: 27.02.2022
SECP256K1_REF: ac83be33d0956faf6b7f61a60ab524ef7d6a473a
SECP_CACHE_VERSION: "2022-12-30"
packages-with-ruby-cddl-tests: '["cardano-protocol-tpraos", "cardano-ledger-shelley", "cardano-ledger-allegra", "cardano-ledger-mary", "cardano-ledger-alonzo", "cardano-ledger-babbage", "cardano-ledger-conway"]'
defaults:
run:
shell: bash
steps:
- name: Free up disk space
run: |
# Remove software and language runtimes we're not using
sudo rm -rf \
"$AGENT_TOOLSDIRECTORY" \
/opt/google/chrome \
/opt/microsoft/msedge \
/opt/microsoft/powershell \
/opt/pipx \
/usr/lib/mono \
/usr/local/julia* \
/usr/local/lib/android \
/usr/local/lib/node_modules \
/usr/local/share/chromium \
/usr/local/share/powershell \
/usr/share/dotnet \
/usr/share/swift
df -h /
- name: Install system dependencies
uses: input-output-hk/actions/base@latest
with:
use-sodium-vrf: false # default is true
- name: Install Haskell
id: install-haskell
uses: input-output-hk/actions/haskell@latest
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: 3.12.1.0
- name: Set up Ruby 2.7
if: contains(fromJson(env.packages-with-ruby-cddl-tests), matrix.package)
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- name: Install cbor-diag and cddl
if: contains(fromJson(env.packages-with-ruby-cddl-tests), matrix.package)
run: |
gem install cddl -v 0.10.3
gem install cbor-diag
- name: Download Mainnet Mirror
if: matrix.package == 'cardano-ledger-byron'
run: |
REF=a31ac75
{
curl -L https://github.com/input-output-hk/cardano-mainnet-mirror/tarball/$REF -o mainnet-mirror.tgz
tar -xzf mainnet-mirror.tgz
mv input-output-hk-cardano-mainnet-mirror-$REF/epochs .
} ||
{
git clone https://github.com/input-output-hk/cardano-mainnet-mirror
cd cardano-mainnet-mirror
git checkout $REF
mv epochs ..
cd ..
}
- name: Set NIGHTLY environment variable if the job was triggered by the scheduler
if: "${{ github.event_name == 'schedule'
|| contains(github.event.pull_request.title, 'nightly')
|| github.event_name == 'workflow_dispatch' && github.event.inputs.nightly }}"
run: |
echo "NIGHTLY=true" >> $GITHUB_ENV
# Retrieve working directory from build jobs
- name: Download working directory archive
uses: actions/download-artifact@v4
with:
name: state-${{ matrix.ghc }}-${{ matrix.os }}
- name: Unarchive working directory
run: tar -xf state.tzst --use-compress-program unzstd && rm state.tzst
- name: Cabal update
run: cabal update
# A dependencies.txt file should have been created by the build job, so we
# check if it exists and is not empty.
- name: Check dependencies to be used as cache keys
id: check-deps
run: |
./scripts/file-not-null.sh dependencies.txt
- name: Restore cache
uses: actions/cache/restore@v4
id: restore-cabal-cache
env:
cache-name: cache-cabal-build
with:
path: |
${{ steps.install-haskell.outputs.cabal-store }}
key: ${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('dependencies.txt') }}-${{ hashFiles('cabal.project*') }}
# The cache with this specific key should have been created by the build
# job. If the cache is missing, something is terribly wrong! We fail the
# test job, or otherwise we would start rebuilding all the dependencies.
fail-on-cache-miss: true
- name: Run tests
run: |
export CARDANO_MAINNET_MIRROR="$(pwd)/epochs"
if [ -z "$NIGHTLY" ]; then
cabal test "${{ matrix.package }}"
else
TRIES=3
scripts/cabal-test-with-retries.sh "${{ matrix.package }}" "$TRIES"
fi
complete:
name: Tests completed
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- run: |
case ${{ needs.test.result }} in
success)
echo 'All tests completed successfully'
true;;
failure)
echo 'Some tests failed'
false;;
*)
echo 'Tests were ${{ needs.test.result }}'
false;;
esac
fourmolu:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Install fourmolu
run: |
FOURMOLU_VERSION="0.16.2.0"
mkdir -p "$HOME/.local/bin"
curl -sL "https://github.com/fourmolu/fourmolu/releases/download/v${FOURMOLU_VERSION}/fourmolu-${FOURMOLU_VERSION}-linux-x86_64" -o "$HOME/.local/bin/fourmolu"
chmod a+x "$HOME/.local/bin/fourmolu"
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Run fourmolu
run: ./scripts/fourmolize.sh
cabal-format:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Format all cabal files
run: ./scripts/cabal-format.sh
gen-hie:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
fail-fast: false
steps:
- name: Cache implicit-hie executable (gen-hie)
id: cache-gen-hie
uses: actions/cache@v4
with:
path: |
~/.cabal/bin/gen-hie
key: ${{ runner.os }}-cache-gen-hie
- name: Install gen-hie if not cached
if: steps.cache-gen-hie.outputs.cache-hit != 'true'
run: cabal update && cabal install implicit-hie --install-method=copy --overwrite-policy=always
- name: Add cabal-bin to PATH
run: echo "$HOME/.cabal/bin" >> $GITHUB_PATH
- uses: actions/checkout@v4
- name: Regenerate hie.yaml and confirm that it is in sync
run: ./scripts/gen-hie.sh
branch-history:
name: Check branch history
runs-on: ubuntu-latest
if: ${{ github.base_ref != '' && github.ref != '' }} # Only true for PRs
steps:
- uses: actions/checkout@v4
- name: Ensure the branch doesn't contain any merges
run: |
PR_TARGET=${{ github.base_ref }}
PR_MERGE=${{ github.ref }}
PR_HEAD=${PR_MERGE%/merge}/head
git fetch origin -n --refmap= +$PR_TARGET:pr-target +$PR_HEAD:pr-head
if git log --merges --oneline --decorate pr-target..pr-head | grep .; then
echo 'Branch must not contain merges'
false
fi
notify-nightly-failure:
name: Send a slack notification on \#ledger-internal if the nightly build failed
runs-on: ubuntu-latest
needs:
- test
if: always() && github.event_name == 'schedule' && needs.test.result == 'failure'
steps:
- name: Send slack notification
id: slack
uses: slackapi/slack-github-action@v1.24.0
with:
payload: |
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Nightly Github Actions build failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
SRP-validity:
name: Check if formal-ledger-specifications SRP is valid
runs-on: ubuntu-latest
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Check if provided formal-ledger-specifications SRP commit hash exists
run: |
TAG=$(sed -ne \
'/ *location: *https:\/\/github.com\/IntersectMBO\/formal-ledger-specifications.git/,/--sha256/ p' \
cabal.project \
| sed -ne 's/^ *tag: *//p')
git fetch https://github.com/intersectmbo/formal-ledger-specifications.git MAlonzo-code
git show -s $TAG || { \
echo "Commit $TAG was not found on the MAlonzo-code branch of formal-ledger-specifications."
exit 1
}