Skip to content

Commit

Permalink
ci: wip cabal flow
Browse files Browse the repository at this point in the history
  • Loading branch information
Connor Baker committed Feb 6, 2024
1 parent 9b2d847 commit fbe0759
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 157 deletions.
220 changes: 148 additions & 72 deletions .github/workflows/workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,80 +6,156 @@ on:
pull_request:

jobs:
build:
name: Build - Windows
runs-on: windows-latest
steps:
- name: Install dependencies
run: |
choco install -y haskell-stack
choco install -y r --version 4.0.0
- uses: actions/checkout@v4
- name: Get Stack snapshot install directory
id: stack-snapshot
# NOTE: `stack path` must run at least once prior to caching to ensure the directory
# exists and is populated.
run: |
stack path --snapshot-install-root
"dir=$(stack path --snapshot-install-root)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
- uses: actions/cache@v4
with:
path: ${{ steps.stack-snapshot.outputs.dir }}
key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }}
restore-keys: ${{ runner.os }}-stack-
- name: Build
run: |
stack build inline-r H `
--extra-lib-dirs="C:/Program files/R/R-4.0.0/bin/x64" `
--extra-include-dirs="C:/Program files/R/R-4.0.0/include"
test:
name: Build & Test - ${{ matrix.os }} - ${{ matrix.stack_yaml }}
strategy:
fail-fast: false
matrix:
os:
- macos-latest
- ubuntu-latest
stack_yaml:
- stack.yaml
- stack-lts-19.yaml
- stack-lts-20.yaml
- stack-lts-21.yaml
- stack-nightly.yaml
runs-on: ${{ matrix.os }}
# stack-windows:
# name: Stack - Windows - stack.yaml
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v4
# - name: Install Stack
# run: choco install -y haskell-stack
# - name: Install R
# run: choco install -y r --version 4.0.0
# # NOTE: `stack path` must run at least once prior to caching to ensure the directory
# # exists and is populated.
# - name: Prime Stack snapshot cache
# run: stack path --snapshot-install-root
# - name: Get Stack snapshot install directory
# id: stack-snapshot
# run: Add-Content -Path $env:GITHUB_OUTPUT -Value ("dir=$(stack path --snapshot-install-root)")
# - uses: actions/cache@v4
# with:
# path: ${{ steps.stack-snapshot.outputs.dir }}
# key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }}
# restore-keys: ${{ runner.os }}-stack-
# - name: Build
# run: |
# stack build inline-r H `
# --extra-lib-dirs="C:/Program files/R/R-4.0.0/bin/x64" `
# --extra-include-dirs="C:/Program files/R/R-4.0.0/include"

# stack-macOS:
# name: Stack - macOS - ${{ matrix.stack_yaml }}
# strategy:
# fail-fast: false
# matrix:
# stack_yaml:
# - stack.yaml
# - stack-lts-19.yaml
# - stack-lts-20.yaml
# - stack-lts-21.yaml
# - stack-nightly.yaml
# runs-on: macos-latest
# steps:
# - uses: actions/checkout@v4
# - uses: DeterminateSystems/nix-installer-action@main
# - uses: DeterminateSystems/magic-nix-cache-action@main
# - name: Install Stack
# run: nix-env --file ./nixpkgs.nix --install --attr stack
# # NOTE: The renaming of the stack.yaml file is a workaround for
# # https://github.com/commercialhaskell/stack/issues/5028.
# - name: Make desired stack.yaml available
# if: ${{ matrix.stack_yaml != 'stack.yaml' }}
# run: mv ${{ matrix.stack_yaml }} stack.yaml
# # NOTE: `stack path` must run at least once prior to caching to ensure the directory
# # exists and is populated.
# - name: Prime Stack snapshot cache
# run: stack --nix path --snapshot-install-root
# - name: Get Stack snapshot install directory
# id: stack-snapshot
# run: echo "dir=$(stack --nix path --snapshot-install-root)" > "${GITHUB_OUTPUT}"
# - uses: actions/cache@v4
# with:
# path: ${{ steps.stack-snapshot.outputs.dir }}
# key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }}
# restore-keys: ${{ runner.os }}-stack-
# - name: Stack build
# run: stack --nix build

# stack-linux:
# name: Stack - Linux - ${{ matrix.stack_yaml }}
# strategy:
# fail-fast: false
# matrix:
# stack_yaml:
# - stack.yaml
# - stack-lts-19.yaml
# - stack-lts-20.yaml
# - stack-lts-21.yaml
# - stack-nightly.yaml
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: DeterminateSystems/nix-installer-action@main
# - uses: DeterminateSystems/magic-nix-cache-action@main
# - name: Install Stack
# run: nix-env --file ./nixpkgs.nix --install --attr stack
# # NOTE: The renaming of the stack.yaml file is a workaround for
# # https://github.com/commercialhaskell/stack/issues/5028.
# - name: Make desired stack.yaml available
# if: ${{ matrix.stack_yaml != 'stack.yaml' }}
# run: mv ${{ matrix.stack_yaml }} stack.yaml
# # NOTE: `stack path` must run at least once prior to caching to ensure the directory
# # exists and is populated.
# - name: Prime Stack snapshot cache
# run: stack --nix path --snapshot-install-root
# - name: Get Stack snapshot install directory
# id: stack-snapshot
# run: echo "dir=$(stack --nix path --snapshot-install-root)" > "${GITHUB_OUTPUT}"
# - uses: actions/cache@v4
# with:
# path: ${{ steps.stack-snapshot.outputs.dir }}
# key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }}
# restore-keys: ${{ runner.os }}-stack-
# - name: Stack build
# run: stack --nix build
# - name: Stack test
# run: stack --nix test
# - name: Add ~/.local/bin to PATH
# run: echo "$HOME/.local/bin" >> "${GITHUB_PATH}"
# - name: Stack install
# run: stack --nix install
# - name: IHaskell install
# run: stack --nix exec -- ihaskell install
# - name: Test IHaskell jupyter notebook example
# run: stack --nix exec -- jupyter nbconvert --to notebook --execute --inplace ./ihaskell-inline-r/examples/tutorial-ihaskell-inline-r.ipynb

cabal-linux:
name: Cabal - Linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- name: Install Stack
run: |
nix-env --file ./nixpkgs.nix --install --attr stack
- name: Get Stack snapshot install directory
id: stack-snapshot
# NOTE: `stack path` must run at least once prior to caching to ensure the directory
# exists and is populated.
# NOTE: The renaming of the stack.yaml file is a workaround for
# https://github.com/commercialhaskell/stack/issues/5028.
run: |
[ ${{ matrix.stack_yaml }} = stack.yaml ] || mv ${{ matrix.stack_yaml }} stack.yaml
stack --nix path --snapshot-install-root
echo "dir=$(stack --nix path --snapshot-install-root)" > "${GITHUB_OUTPUT}"
- uses: actions/cache@v4
- name: Configure the build
run: cabal configure --enable-tests --disable-documentation
shell: nix-shell ./shell-cabal.nix -I nixpkgs=./nixpkgs.nix --run "{0}"
- name: Generate dist-newstyle/cache/plan.json
run: cabal build all --dry-run
shell: nix-shell ./shell-cabal.nix -I nixpkgs=./nixpkgs.nix --run "{0}"
- name: Restore cached dependencies
uses: actions/cache/restore@v4
id: cache
env:
key: ${{ runner.os }}-cabal-${{ hashFiles('**/*.cabal') }}
with:
path: ${{ env.HOME }}/.cabal/store
key: ${{ env.key }}-plan-${{ hashFiles('**/plan.json') }}
restore-keys: ${{ env.key }}-
- name: Install Haskell dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: cabal build all --only-dependencies
shell: nix-shell ./shell-cabal.nix -I nixpkgs=./nixpkgs.nix --run "{0}"
# Cache dependencies already here, so that we do not have to rebuild them should the subsequent steps fail.
- name: Cache Haskell dependencies
uses: actions/cache/save@v4
# If we had an exact cache hit, trying to save the cache would error because of key clash.
if: steps.cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.stack-snapshot.outputs.dir }}
key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }}
restore-keys: ${{ runner.os }}-stack-
- name: Build
run: |
stack --nix build
- name: Test
if: ${{ runner.os == 'Linux' }}
run: |
stack --nix test
- name: Test IHaskell jupyter notebook example
if: ${{ runner.os == 'Linux' }}
run: |
stack --nix install
export PATH="$HOME/.local/bin:$PATH"
stack --nix exec -- ihaskell install
stack --nix exec -- jupyter nbconvert --to notebook --execute --inplace ./ihaskell-inline-r/examples/tutorial-ihaskell-inline-r.ipynb
path: ${{ env.HOME }}/.cabal/store
key: ${{ steps.cache.outputs.cache-primary-key }}
- name: Cabal build
run: cabal build all
shell: nix-shell ./shell-cabal.nix -I nixpkgs=./nixpkgs.nix --run "{0}"
- name: Cabal test
run: cabal test all
shell: nix-shell ./shell-cabal.nix -I nixpkgs=./nixpkgs.nix --run "{0}"
93 changes: 93 additions & 0 deletions nix/R.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
pkgs ? import ./nixpkgs.nix { },
RVersion ? "4.2.3",
}:
let
inherit (pkgs) fetchpatch fetchurl;
inherit (pkgs.lib) lists strings versions;
in
# Set enableStrictBarrier to true to build HaskellR against a version of R with
# the --enable-strict-barrier configure flag enabled for better memory
# diagnostics.
(pkgs.R.override { enableStrictBarrier = false; }).overrideAttrs (
# Pin R to a specific version to avoid breaking changes in the R API.
finalAttrs: prevAttrs: {
version = RVersion;
src = fetchurl {
url = "https://cran.r-project.org/src/base/R-${versions.major finalAttrs.version}/R-${finalAttrs.version}.tar.gz";
hash = builtins.getAttr RVersion {
"4.0.0" = "sha256-Br6wKRtWmXhITrDctdIzlmXsdFc3vftOhz56WnVJKUA=";
"4.0.1" = "sha256-lf4kpNjY+PiIRgyPX+QxHOxlbnoXItIzIYvAOGG8bzI=";
"4.0.2" = "sha256-07zqs2TaCHZiXkCXgItCUSOV/fQSkvSRWrH9JXwbvnU=";
"4.0.3" = "sha256-CZg6injV+2vEXSexxV+bpSZfePpUpVwTrmkfh8W7ng0=";
"4.0.4" = "sha256-Uj8n1pdEoIyPC9Xh5sPYmk2yntmDOIunCWOjzTpKgC4=";
"4.0.5" = "sha256-Cj7geap3LhMf5UNTEatif8vMtaUMq8VCkub2IEbx/+8=";
"4.1.0" = "sha256-6OaJWdcoLKFHNg/JZEram9FhureBurFNM7iZmpUYJ4E=";
"4.1.1" = "sha256-UV4DJldSJX0LcDbzgPguQrRu2Ec/VPJce2ftJbu902Q=";
"4.1.2" = "sha256-IDYiXp9yB9TOCX5Ulyrs2qi0DX2ZEc0mSR+sWg+rOK8=";
"4.1.3" = "sha256-Ff9bMzxhCUBgsqUunB2OxVzELdAp45yiKr2qkJUm/tY=";
"4.2.0" = "sha256-OOq3cZt60JU4jwaqCQxaKyAnkZRd5g0+K7DqsfUJdIg=";
"4.2.1" = "sha256-TVLbSG0nhI5UYT1O6XetlS7AjOF4B+G1JbEM1ENsZD8=";
"4.2.2" = "sha256-D/YrQuxRr6VxPK7nxP3noMRZQLo5vvjFyUh/7wyVPfU=";
"4.2.3" = "sha256-VeSpptQ74xTiwD0CZqb6VESv3OULMDv8O4Kzl5UW4HQ=";
"4.3.0" = "sha256-RdzEi2zyfTYQIPd/3ho5IJ6Ze4FAKzZjyhwBAFampgk=";
"4.3.1" = "sha256-jdC/JPECPG9hjDsxc4PSkbSklPQNc7mDrCL/6pnkupk=";
"4.3.2" = "sha256-s/V2CsLu6AJqPw7vyyW0dyPZeAOO7o6ER2IJTIYMRSo=";
};
};

patches =
prevAttrs.patches or [ ]
# R: 4.0.4 -> 4.1.0
# See https://github.com/NixOS/nixpkgs/commit/9a88197fe7825f486052e3a9eca4a68192335978
++
lists.optionals
(
RVersion == "4.1.0"
&& strings.hasInfix "--without-recommended-packages" (prevAttrs.preConfigure or "")
)
[
(fetchpatch {
name = "fix-tests-without-recommended-packages.patch";
url = "https://github.com/wch/r-source/commit/7715c67cabe13bb15350cba1a78591bbb76c7bac.patch";
# this part of the patch reverts something that was committed after R 4.1.0, so ignore it.
excludes = [ "tests/Pkgs/xDir/pkg/DESCRIPTION" ];
hash = "sha256-iguLndCIuKuCxVCi/4NSu+9RzBx5JyeHx3K6IhpYshQ=";
})
(fetchpatch {
name = "use-codetools-conditionally.patch";
url = "https://github.com/wch/r-source/commit/7543c28b931db386bb254e58995973493f88e30d.patch";
hash = "sha256-+yHXB5AItFyQjSxfogxk72DrSDGiBh7OiLYFxou6Xlk=";
})
]
# R: 4.1.3 -> 4.2.0
# See: https://github.com/NixOS/nixpkgs/commit/5eb9f35c44d30153ff1df2105ed73e148a79a3ee
++ lists.optionals (RVersion == "4.2.0" || RVersion == "4.2.1") [
(fetchpatch {
name = "test-reg-packages.patch";
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/5eb9f35c44d30153ff1df2105ed73e148a79a3ee/pkgs/applications/science/math/R/test-reg-packages.patch";
hash = "sha256-FUzrenAFvD8GL1/RMG8DRRx+ITcEkDkRGKTVyAhyKqA=";
})
];

postPatch =
prevAttrs.postPatch or ""
# Nixpkgs ships with curl >= 8.x, which is not compatible with R pre-4.3. However, in the release notes for R
# 4.3 (https://stat.ethz.ch/pipermail/r-announce/2023/000691.html), it is mentioned that despite the major
# version change for curl, the API is still compatible with the previous version. Therefore, we can patch the
# check for curl 7.x. This fixes the following error:
# error: libcurl >= 7.28.0 library and headers are required with support for https
# We must patch the ./configure script and the ./m4/R.m4 file to make this work.
+ strings.optionalString (strings.versionOlder RVersion "4.3.0") ''
substituteInPlace \
./configure \
./m4/R.m4 \
--replace-fail \
"#if LIBCURL_VERSION_MAJOR > 7" \
"#if LIBCURL_VERSION_MAJOR < 7" \
--replace-fail \
"#elif LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 28" \
"#elif LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 28 || LIBCURL_VERSION_MAJOR == 8"
'';
}
)
65 changes: 65 additions & 0 deletions shell-cabal.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
pkgs ? import ./nixpkgs.nix { },
ghcAttr ? "ghc98",
RVersion ? "4.2.3",
}:
let
inherit (pkgs)
cabal-install
cacert
haskell
pkg-config
python3
rPackages
rWrapper
stdenv
zeromq
zlib
;

inherit (pkgs.lib) strings;

# Set enableStrictBarrier to true to build HaskellR against a version of R with
# the --enable-strict-barrier configure flag enabled for better memory
# diagnostics.
R = builtins.import ./nix/R.nix { inherit pkgs RVersion; };

rEnv = rWrapper.override {
inherit R;
# ggplot2 is required for ./ihaskell-inline-r/examples/tutorial-ihaskell-inline-r.ipynb
packages = with rPackages; [ ggplot2 ];
};

python3Env = python3.withPackages (
ps: with ps; [
ipython
jupyter_client
notebook
]
);
in
haskell.packages.${ghcAttr}.shellFor rec {
packages = haskellPackages: [ ];

nativeBuildInputs = [ pkg-config ];

buildInputs = [
cabal-install
cacert
python3Env
rEnv
zeromq
zlib
];

# Fixes https://github.com/commercialhaskell/stack/issues/2358
LANG = "en_US.UTF-8";

# XXX: workaround for https://ghc.haskell.org/trac/ghc/ticket/11042.
${(strings.optionalString stdenv.isDarwin "DY") + "LD_LIBRARY_PATH"} = strings.makeLibraryPath (
[ ("${R}/lib/R" + (strings.optionalString stdenv.isDarwin "/lib")) ] ++ nativeBuildInputs
);

# Non-NixOS git needs cert
GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
}
Loading

0 comments on commit fbe0759

Please sign in to comment.