Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use cabal-cache #4717

Merged
merged 1 commit into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 43 additions & 35 deletions .github/workflows/github-page.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,41 @@ jobs:
SECP256K1_REF: ac83be33d0956faf6b7f61a60ab524ef7d6a473a

steps:
- uses: actions/checkout@v1
# this seems to break something. It _must_ come after the pacman setup
# above. It appears as if PATHEXT is set _after_ ghcup install ghc/cabal, and
# as such we'd need pacman.exe instead.
- name: Setup Haskell
run: |
# Use GHCUP to manage ghc/cabal
ghcup install ghc --set ${{ matrix.ghc }}
ghcup install cabal --set 3.8.1.0

- name: Set cache version
run: echo "CACHE_VERSION=UN37rUo" >> $GITHUB_ENV
ghc --version
cabal --version

- name: Add build script path
run: echo "$(pwd)/.github/bin" >> $GITHUB_PATH
- name: "Setup cabal-store"
id: cabal-store
shell: bash
run: |
cabal help user-config
cabal_config_file="$(cabal help user-config | grep -A 1 'You can edit the cabal configuration file to set defaults' | tail -n 1 | xargs)"

- uses: haskell/actions/setup@v1
id: setup-haskell
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: 3.6.2.0
echo "cabal-store=$(dirname "$cabal_config_file")/store" | tee -a "$GITHUB_OUTPUT"

- name: Haskell versions
run: |
ghc --version
cabal --version
- uses: actions/checkout@v2

- name: Add build script path
run: echo "$(pwd)/.github/bin" >> $GITHUB_PATH

- name: Install build environment
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get -y install libsodium23 libsodium-dev
sudo apt-get -y install libsystemd0 libsystemd-dev
sudo apt-get -y remove --purge software-properties-common
sudo apt-get -y autoremove

- name: "LINUX: Install secp256k1"
if: runner.os != 'Windows'
- name: "Install secp256k1"
shell: bash
env:
CI_SECP_FLAGS: "--prefix=/usr"
Expand All @@ -60,13 +65,6 @@ jobs:
- name: Cabal update
run: cabal update

- name: Disable reorder goals on MacOS and Linux
# Avoid reorder goals for platforms that don't need it because re-order goals can take up to 10 minutes
if: matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest'
run: |
cat cabal.project | sed 's|reorder-goals: True|reorder-goals: False|g' > cabal.project.tmp
mv cabal.project.tmp cabal.project

- name: combine github-pages, and machine local project files.
run: |
cat .github/workflows/cabal.project.local.github-pages \
Expand All @@ -79,18 +77,28 @@ jobs:
mkdir ./haddocks
DRY_RUN=1 ./scripts/haddocs.sh ./haddocks true

- name: Record dependencies
run: |
cat ${{ env.PLAN_JSON }} | jq -r '."install-plan"[].id' | sort | uniq > dependencies.txt

- uses: actions/cache@v2
name: Cache cabal store
- name: Cabal cache over S3
uses: action-works/cabal-cache-s3@v1
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
with:
region: us-west-2
dist-dir: dist-newstyle
store-path: ${{ steps.cabal-store.outputs.cabal-store }}
threads: 16
archive-uri: ${{ secrets.BINARY_CACHE_URI }}
skip: "${{ secrets.BINARY_CACHE_URI == '' }}"

- name: Cabal cache over HTTPS
uses: action-works/cabal-cache-s3@v1
with:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: cache-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('dependencies.txt') }}
restore-keys: |
cache-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('dependencies.txt') }}
cache-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}-
dist-dir: dist-newstyle
store-path: ${{ steps.cabal-store.outputs.cabal-store }}
threads: 16
archive-uri: https://iohk.cache.haskellworks.io
skip: "${{ secrets.BINARY_CACHE_URI != '' }}"
enable-save: false

- name: Install dependencies
run: cabal build all
Expand Down
120 changes: 77 additions & 43 deletions .github/workflows/haskell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ jobs:
LD_LIBRARY_PATH: ${{ (matrix.os != 'windows-latest' && '/usr/local/lib') || '' }}

steps:
- name: Setup tmate session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true

- name: "WIN: Install System Dependencies via pacman (msys2)"
if: runner.os == 'Windows'
run: |
Expand All @@ -61,15 +55,15 @@ jobs:
automake `
libtool `
make

# this seems to break something. It _must_ come after the pacman setup
# above. It appears as if PATHEXT is set _after_ ghcup install ghc/cabal, and
# as such we'd need pacman.exe instead.
- name: Setup Haskell
run: |
run: |
# Use GHCUP to manage ghc/cabal
ghcup install ghc --set ${{ matrix.ghc }}
ghcup install cabal --set 3.6.2.0
ghcup install cabal --set 3.8.1.0

ghc --version
cabal --version
Expand All @@ -96,19 +90,28 @@ jobs:
-a ("extra-lib-dirs: {0}, C:/msys64/mingw64/lib" -f $ghcMingwDir) `
-f init

- name: "OUTPUT Record cabal-store (Linux)"
id: lin-setup-haskell
if: runner.os != 'Windows'
run: echo "cabal-store=/home/runner/.cabal/store" >> $GITHUB_OUTPUT

- name: "OUTPUT Record cabal-store (Windows)"
id: win-setup-haskell
if: runner.os == 'Windows'
# Unify the computation of the cabal store directory to a single step. This makes referencing the cabal
# store in later steps easier.
#
# We know on cabal store is located in the following locations by OS:
#
# Linux: /home/runner/.cabal/store
# MacOS: /Users/runner/.cabal/store
# Windows: C:\cabal\store
#
# However, we compute these as best be can from information cabal provides in case this changes in the future.
- name: "Setup cabal-store"
id: cabal-store
shell: bash
run: echo "cabal-store=C:\\cabal\\store" >> $GITHUB_OUTPUT
run: |
cabal help user-config
cabal_config_file="$(cabal help user-config | grep -A 1 'You can edit the cabal configuration file to set defaults' | tail -n 1 | xargs)"

- name: Set cache version
run: echo "CACHE_VERSION=grFfw7r" >> $GITHUB_ENV
if [[ '${{ runner.os }}' != 'Windows' ]]; then
echo "cabal-store=$(dirname "$cabal_config_file")/store" | tee -a "$GITHUB_OUTPUT"
else
echo "cabal-store=C:\\cabal\\store" | tee -a "$GITHUB_OUTPUT"
fi
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unify the computation of the cabal store directory to a single step. This makes referencing the cabal store in later steps easier.

This also fixes the problem where on MacOS, the cabal-store=/home/runner/.cabal/store is incorrect. This should be /Users/runner/.cabal/store.

To avoid this problem in future, on Linux and MacOS, the step queries cabal for the some information to compute the location of the cabal store.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put this as a comment in the file?


- uses: actions/checkout@v2

Expand Down Expand Up @@ -180,36 +183,65 @@ jobs:
echo "# cabal.project.local"
cat cabal.project.local

- name: Record dependencies
id: record-deps
- name: List all pkg-config packages
run: |
cabal build all --dry-run
cat dist-newstyle/cache/plan.json | jq -r '."install-plan"[].id' | sort | uniq > dependencies.txt
# The tests call out to msys2 commands. We generally do not want to mix toolchains, so
# we are very deliberate about only adding msys64 to the path where absolutely necessary.
${{ (runner.os == 'Windows' && '$env:PATH=("C:\msys64\mingw64\bin;{0}" -f $env:PATH)') || '' }}
pkg-config --list-all

- name: "OUTPUT Record weeknum"
shell: bash
run: echo "weeknum=$(/usr/bin/date -u "+%W")" >> $GITHUB_OUTPUT
- name: Build dry run
run: |
# The tests call out to msys2 commands. We generally do not want to mix toolchains, so
# we are very deliberate about only adding msys64 to the path where absolutely necessary.
${{ (runner.os == 'Windows' && '$env:PATH=("C:\msys64\mingw64\bin;{0}" -f $env:PATH)') || '' }}
cabal build all --dry-run

- name: Cache Cabal store
uses: actions/cache@v2
# For users who fork cardano-node and want to define a writable cache, then can set up their own
# S3 bucket then define in their forked repository settings the following secrets:
#
# AWS_ACCESS_KEY_ID
# AWS_SECRET_ACCESS_KEY
# BINARY_CACHE_URI
# BINARY_CACHE_REGION
- name: Cabal cache over S3
uses: action-works/cabal-cache-s3@v1
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
with:
path: ${{ runner.os == 'Windows' && steps.win-setup-haskell.outputs.cabal-store || steps.lin-setup-haskell.outputs.cabal-store }}
key: cache-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('dependencies.txt') }}-${{ hashFiles('date.txt') }}
restore-keys: |
cache-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('dependencies.txt') }}
cache-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}

- uses: actions/cache@v2
name: "Cache `dist-newstyle`"
region: ${{ secrets.BINARY_CACHE_REGION }}
dist-dir: dist-newstyle
store-path: ${{ steps.cabal-store.outputs.cabal-store }}
threads: 16
archive-uri: ${{ secrets.BINARY_CACHE_URI }}
skip: "${{ secrets.BINARY_CACHE_URI == '' }}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step syncs the cabal store with S3, an object store service (think a service for storing files).

The S3 bucket is set to s3://iohk.cache.haskellworks.io.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise


# It's important to ensure that people who fork this repository can not only successfully build in
# CI by default, but also have meaning cabal store caching.
#
# Because syncing with S3 requires credentials, we cannot rely on S3 for this. For this reason a
# https fallback is used. The https server mirrors the content of the S3 bucket. The https cabal
# store archive is read-only for security reasons.
#
# Users who fork this repository who want to have a writable cabal store archive are encouraged
# to set up their own S3 bucket.
- name: Cabal cache over HTTPS
uses: action-works/cabal-cache-s3@v1
with:
path: |
dist-newstyle
!dist-newstyle/**/.git
key: cache-dist-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}-${{ steps.record-deps.outputs.weeknum }}
restore-keys: cache-dist-${{ env.CACHE_VERSION }}-${{ runner.os }}-${{ matrix.ghc }}
dist-dir: dist-newstyle
store-path: ${{ steps.cabal-store.outputs.cabal-store }}
threads: 16
archive-uri: https://iohk.cache.haskellworks.io
skip: "${{ secrets.BINARY_CACHE_URI != '' }}"
enable-save: false
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's important to ensure that people who fork this repository can not only successfully build in CI by default, but also have meaning cabal store caching.

Because syncing with S3 requires credentials, we cannot rely on S3 for this. For this reason a https fallback is used. The https server mirrors the content of the S3 bucket. The https cabal store archive is read-only for security reasons.

Users who fork this repository who want to have a writable cabal store archive are encouraged to set up their own S3 bucket.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this


- name: Build
run: cabal build cardano-node cardano-cli cardano-node-chairman cardano-submit-api
run: |
# The tests call out to msys2 commands. We generally do not want to mix toolchains, so
# we are very deliberate about only adding msys64 to the path where absolutely necessary.
${{ (runner.os == 'Windows' && '$env:PATH=("C:\msys64\mingw64\bin;{0}" -f $env:PATH)') || '' }}
cabal build cardano-node cardano-cli cardano-node-chairman cardano-submit-api

- name: Run tests (all)
if: github.event.inputs.tests == 'all'
Expand Down Expand Up @@ -288,6 +320,8 @@ jobs:
# - name: Setup tmate session
# if: ${{ failure() }}
# uses: mxschmitt/action-tmate@v3
# with:
# limit-access-to-actor: true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this to the commented out tmate step for security reasons in case someone decides to use it.


release:
needs: [build]
Expand Down