# Github cache action

**URL:** <https://discourse.haskell.org/t/github-cache-action/9926>\
**Category:** Learn\
**Created:** [July 10, 2024, 5:32pm UTC](https://discourse.haskell.org/t/github-cache-action/9926 "2024-07-10T17:32:24Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [July 10, 2024, 5:32pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/1 "2024-07-10T17:32:24Z")

</div>

I am currently trying to speed up ci on github with caching however my stack caches are too big is there a way to be more specific with the cached paths to reduce the cache size but still get good build times?

```haskell
      - name: Use Cache
        uses: actions/cache@v4
        with:
          key: ${{ matrix.os }}_${{ matrix.resolver }}
          path: |
            ~/.stack
            ./.stack-work
            ./*/.stack-work

```

Perhaps splitting up the `~/.stack` path, but I am unsure what that should actually look like.

---

<div class="post-metadata">

**Author:** ![tcard](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tcard/32/4823_2.png) [@tcard](https://discourse.haskell.org/u/tcard)\
**Post date:** [July 10, 2024, 9:38pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/2 "2024-07-10T21:38:19Z")

</div>

Is your project publicly available? If you link to it, I can better understand your configuration.

Your code includes `matrix.resolver`, which I assume is a Stackage `lts-*` / `nightly-*` / `ghc-*` string. This makes me wonder how you are installing GHC and Stack. Perhaps you are not using [haskell-actions/setup](https://github.com/haskell-actions/setup) and are instead installing Stack and then letting Stack install GHC? Stack installs GHC into `~/.stack`, so this may be a significant factor of the cache size. If you are testing `nightly` (which points to the latest nightly snapshot), then you may be accumulating every version of GHC that you have ever tested in the corresponding cache.

I use `stack-${{ matrix.ghc }}.yaml` files instead. The matrix specifies the GHC versions to test. Each `stack-${{ matrix.ghc }}.yaml` file has the Stack configuration, specifying the resolver.

Example `stack-9.6.6.yaml` file:

```haskell
resolver: lts-22.28

packages:
  ...

```

Example `stack-9.8.2.yaml` file:

```haskell
resolver: nightly-2024-07-09

packages:
  ...

```

Example `stack-9.10.1.yaml` file:

```haskell
resolver: ghc-9.10.1

packages:
  ...

extra-deps:
  ...

```

In the workflow, you can then use [haskell-actions/setup](https://github.com/haskell-actions/setup) to install both GHC and Stack. Every `stack` command used must include the `--system-ghc` option to prevent Stack from installing GHC into `~/.stack`.

I am not sure what you mean by “splitting up the `~/.stack` path.” Perhaps you want to cache `~/.stack` separately from the `.stack-work` directories? You can do this using multiple cache steps. Separate caches must of course have different keys.

---

<div class="post-metadata">

**Author:** ![simonmic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/simonmic/32/1796_2.png) [@simonmic](https://discourse.haskell.org/u/simonmic)\
**Post date:** [July 10, 2024, 9:40pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/3 "2024-07-10T21:40:43Z")

</div>

[Here](https://github.com/simonmichael/hledger/blob/dcf0249c8ccd0aed8d0fde4466504b81669e7eb7/.github/workflows/ci.yml#L146-L214) are the things I cache. There may be simpler/better ways…

---

<div class="post-metadata">

**Author:** ![tcard](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tcard/32/4823_2.png) [@tcard](https://discourse.haskell.org/u/tcard)\
**Post date:** [July 10, 2024, 11:47pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/4 "2024-07-10T23:47:54Z")

</div>

If you want to (temporarily) insert a debug step that shows the size of your `~/.stack`, here is a script that attempts to provide a useful summary:

```bash
#!/usr/bin/env bash
# shellcheck disable=SC2088

if [! -d "${HOME}/.stack"] ; then
  echo '~/.stack not found'
  exit 0
fi

echo '## programs'
if [-d "${HOME}/.stack/programs"] ; then
  find ~/.stack/programs -mindepth 2 -maxdepth 2 -type d -print0 \
    | xargs --null du --human-readable --summarize
else
  echo '(not found)'
fi

echo
echo '## snapshots'
if [-d "${HOME}/.stack/snapshots"] ; then
  du --human-readable --summarize ~/.stack/snapshots
else
  echo '(not found)'
fi

echo
echo '## setup-exe-cache'
if [-d "${HOME}/.stack/setup-exe-cache"] ; then
  du --human-readable --summarize ~/.stack/setup-exe-cache
else
  echo '(not found)'
fi

echo
echo '## ~/.stack total'
du --human-readable --summarize ~/.stack

```

Note that the “programs” section shows the size of each program directory. It does not include archives. When using `--system-ghc`, none should be installed here.

---

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [July 11, 2024, 1:10pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/5 "2024-07-11T13:10:46Z")

</div>

> <https://github.com/snoyberg/mono-traversable/pull/226>

---

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [July 11, 2024, 6:03pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/6 "2024-07-11T18:03:21Z")

</div>

Thank you for pointing out to use haskell-actions to install ghc instead of stack! That will solve my size problem and make the cache include patterns very simple.

---

<div class="post-metadata">

**Author:** ![tcard](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tcard/32/4823_2.png) [@tcard](https://discourse.haskell.org/u/tcard)\
**Post date:** [July 12, 2024, 12:49am UTC](https://discourse.haskell.org/t/github-cache-action/9926/7 "2024-07-12T00:49:08Z")

</div>

Thanks!

I checked out your CI configuration and learned something new. You are using the Stack `--snapshot` option to _override_ the resolver configured in the `stack.yaml` file. This allows you to test many snapshots without having to clutter your project with many `stack-*.yaml` files. Nice!

I may be able to do this to clean up some of my projects, but many of my projects require different configuration for different snapshots. For example, some configuration requires `extra-deps` that pin specific versions of packages that are not in the snapshot. Also, `optparse-applicative` has different dependencies depending on the version, and Cabal can handle this automatically while Stack requires manual configuration.

Thanks for sharing!

---

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [July 12, 2024, 9:30pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/8 "2024-07-12T21:30:35Z")

</div>

Glad we both learned something useful!

---

<div class="post-metadata">

**Author:** ![janus](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/janus/32/1060_2.png) [@janus](https://discourse.haskell.org/u/janus)\
**Post date:** [July 12, 2024, 9:34pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/9 "2024-07-12T21:34:08Z")

</div>

Another option is to use [haskell-ci](https://hackage.haskell.org/package/haskell-ci). But use it from Github, because the released version isn’t generating compatible CI configs now that Github bumped their glibc requirement.

---

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [July 12, 2024, 9:45pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/10 "2024-07-12T21:45:22Z")

</div>

I am unsure if your second sentence means that it works or that it does not work on github.

---

<div class="post-metadata">

**Author:** ![janus](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/janus/32/1060_2.png) [@janus](https://discourse.haskell.org/u/janus)\
**Post date:** [July 12, 2024, 10:16pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/11 "2024-07-12T22:16:36Z")

</div>

What I mean is that the version of Haskell-CI on Hackage isn’t new enough. The versions are all intended to generate working CI configurations, I am just telling you not to use v0.18.1 (the latest on hackage). Because it won’t actually generate something that works. Instead you should pull haskell-ci from Github and use it to generate a Github CI configuration (which will work, since the `master` version of Haskell-CI was updated to handle the glibc bump). And your CI configuration would work for a couple of years. At that point, when it stops working, you could regenerate with an even newer version of Haskell-CI.

---

<div class="post-metadata">

**Author:** ![ulidtko](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ulidtko/32/4063_2.png) [@ulidtko](https://discourse.haskell.org/u/ulidtko)\
**Post date:** [August 19, 2024, 7:45am UTC](https://discourse.haskell.org/t/github-cache-action/9926/12 "2024-08-19T07:45:03Z")

</div>

Please see my comment here: [Blessed recipe how to use stack on github actions, in particular caching? · Issue #5754 · commercialhaskell/stack · GitHub](https://github.com/commercialhaskell/stack/issues/5754#issuecomment-1696156869)

> Perhaps splitting up the `~/.stack` path, but I am unsure what that should actually look like.

Yes, exactly 👍 The linked post shows how.

---

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [August 19, 2024, 1:21pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/13 "2024-08-19T13:21:06Z")

</div>

Wish I had this when I was figuring it out.

So, currently I am caching

```haskell
          path: |
            ${{ steps.setup-haskell-stack.outputs.stack-root }}
            .stack-work
            */.stack-work

```

but according to issue 5754 I should change the stack root line to be

```haskell
 ${{ steps.setup-haskell-stack.outputs.stack-root }}/pantry
 ${{ steps.setup-haskell-stack.outputs.stack-root }}/snapshots

```

Reference to [steps.setup-haskell-stack.outputs.stack-root](https://github.com/marketplace/actions/setup-haskell#outputs)

[Workflow file](https://github.com/snoyberg/mono-traversable/blob/c7a27c3579b3247015ad2ca983861be3d1603159/.github/workflows/tests.yml#L51)

---

<div class="post-metadata">

**Author:** ![ulidtko](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ulidtko/32/4063_2.png) [@ulidtko](https://discourse.haskell.org/u/ulidtko)\
**Post date:** [August 19, 2024, 1:35pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/14 "2024-08-19T13:35:29Z")

</div>

> but according to issue 5754 I should change

No.

You should have 4 separate caches.

Please read the post. There’re snippets after `TL;DR`

---

<div class="post-metadata">

**Author:** ![BebeSparkelSparkel](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@BebeSparkelSparkel](https://discourse.haskell.org/u/BebeSparkelSparkel)\
**Post date:** [August 19, 2024, 4:54pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/15 "2024-08-19T16:54:24Z")

</div>

The complexity of this warrants its own action or a change to stack support easy caching of workflows.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [August 19, 2024, 9:25pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/16 "2024-08-19T21:25:19Z")

</div>

> […] a change to stack to support easy caching of workflows.

But is it just `stack`, or `cabal` (the library) which `stack` uses? Moreover, is this a problem for the 'Hub, or is the 'Lab also affected?

---

<div class="post-metadata">

**Author:** ![ulidtko](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ulidtko/32/4063_2.png) [@ulidtko](https://discourse.haskell.org/u/ulidtko)\
**Post date:** [August 19, 2024, 9:35pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/17 "2024-08-19T21:35:02Z")

</div>

It’s not a problem… it’s a tradeoff. Want quick-n-dirty simple cache? Plop in entire `~/.stack` plus `.stack-work` to one pot; brace for issues some ~years later (depending on project velocity).

Want fast rebuilds in a mostly correct, long-term reliable setup? Alas, brace complexity.

… Remember, cache invalidation is one of the hardest problems of computer science 😂

---

<div class="post-metadata">

**Author:** ![ulidtko](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ulidtko/32/4063_2.png) [@ulidtko](https://discourse.haskell.org/u/ulidtko)\
**Post date:** [August 19, 2024, 9:39pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/18 "2024-08-19T21:39:23Z")

</div>

[My post](https://github.com/commercialhaskell/stack/issues/5754#issuecomment-1696156869) is explicitly `stack` centric. CI caching with `cabal v1-build` & `cabal v2-build` each will be mostly different; [haskell-ci](https://github.com/haskell-CI/haskell-ci) may be of help there.

Re: GitLab — please read.

> I’ve done quite a few CI/CD pipelines for haskell, on CircleCI, BitBucket Pipelines, GitHub Actions… even Jenkins.

In all cases, the syntax (yaml, groovy, whatnot) is ofcourse different; but underlying issues, ideas, and principles, are the same. So yes, on GitLab too.

---

<div class="post-metadata">

**Author:** ![ulidtko](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ulidtko/32/4063_2.png) [@ulidtko](https://discourse.haskell.org/u/ulidtko)\
**Post date:** [August 19, 2024, 10:08pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/19 "2024-08-19T22:08:03Z")

</div>

I thought a lot about this…

> The complexity of this warrants its own action or a change to stack support easy caching of workflows.

Still undecided though.

See, the problem space is riddled with nuance & vast enough that trying to invent a universal “higher-order YAML” to solve it all — seems utterly futile. The universality aspect is bound to _multiply_ complexity, too. I just don’t see how to make it happen.

Set up CI in a given repo? Sure, easy, hold my beer. Concoct a universal CI for _any_ Haskell repo? Hell no.

Perhaps having it explicitly in the workflow yaml, tailored for each specific case, is better in terms of complexity. Much less abstractions to decode, than a universal action must have (“build targets? cabal flags? monorepos? native dependencies?? backpack mixins?? vendored private source repos?! custom ghc builds?!?” etc etc) — with the steps “inlined”, the reader is seeing direct `stack build` calls, instead of yet another layer of bespoke YAML-embedded DSL.

* * *

In terms of stack support: yes, a “build plan” feature would help resolve one minor correctness issue in that setup. Yet, complexity would remain; it won’t solve the need for 3–4 separate caches.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [August 19, 2024, 11:42pm UTC](https://discourse.haskell.org/t/github-cache-action/9926/20 "2024-08-19T23:42:57Z")

</div>

> [@ulidtko](#):
>
> Want quick-n-dirty simple cache? Plop in entire `~/.stack` plus `.stack-work` to one pot; brace for issues some ~years later […]

…much like what seems to happen with people’s `.cabal` directories:

> [@](#):
>
> [ChShersh](http://discourse.haskell.org/t/request-for-testing-of-the-xdg-enabled-cabal-install/5200/8):
> 
> My typical workflow involves nuking `~/.cabal` periodically.

Hence my post.

[Next page](https://discourse.haskell.org/t/github-cache-action/9926.md?page=2)
