setup-bun
setup-bun copied to clipboard
Seems quick! where's the cache?
Title is a bit tongue in cheek.
It doesn't look like there's a way to set a damage file or anything for purposes of a cache in the action. This is normally configured in the actions/setup-node action on GH actions.
It doesn't look like bun has that, which is a bit disappointing because it feels like there might be an even deeper win here if that was available.
What do you mean by damage file? Saving dependencies/whole bun into cache?
When a file is damaged (changed), the cache should be dropped and refreshed.
setup-node calls it cache-dependency-path
, which is a fine modern name I guess.
EDIT2: Yes please. If there was caching for the built dependencies subsequent runs would be even faster(?).
It might be possible to use github action's hashFiles
expression to hash bun.lockb
and package.json
and use that as the cache key?
Alternatively shouldn't we just always cache the ~/.bun/install/cache
folder?
It might be possible to use github action's
hashFiles
expression to hashbun.lockb
andpackage.json
and use that as the cache key?
Yeah, that seems reasonable (until there's a better option).
Alternatively shouldn't we just always cache the
~/.bun/install/cache
folder?
You could, but it doesn't align to the other node projects. If there's no problem with it in bun that's fine, but the other products expressly look at this.
Alternatively shouldn't we just always cache the
~/.bun/install/cache
folder?You could, but it doesn't align to the other node projects. If there's no problem with it in bun that's fine, but the other products expressly look at this.
I haven't had a chance to use bun much yet, but from what I can see from the docs, it supposedly always downloads packages to that folder, then uses hardlinks to add the packages to the node_modules
folder
If that's the case, then that's the only folder that needs to be cached. You could cache it with the same key every time, or use that same hashFiles
expression to create a key, to stop the cache growing in size over time
We haven't implemented dependency caching yet, because early testing showed bun install
was faster than using Github's caching mechanism.
can the hashFiles()
technique really work? since the hash changes every time you run bun install
:/
(i might completely be misunderstanding how caching in github actions is supposed to work)
I tested the solution mentioned above with:
- uses: actions/cache@v3
with:
key: key
path: ~/.bun/install/cache
It reduces the bun install
time from 10 seconds to 2 seconds, but the cache restore time is 8 seconds, so it's a bit of a wash.
For me, this cache config adds 2 seconds to restore the cache and then drops my bun install time from 6-10s to <2s. Of course sometimes the cache restore takes longer due to network variability, but that variability impacts install time too if fetching all deps every time. Seems worthwhile overall to put something like this in by default (exact ideal key config is up for debate).
- uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-${{ matrix.bun }}-bun-${{ hashFiles('**/bun.lockb') }}
restore-keys: |
${{ runner.os }}-${{ matrix.bun }}-bun-
@bgentry but what about the time to save the cache?
In my GitLab CI it took 2 min to save the cache:
(35s to restore cache, 2s to install).
On a run that the .lock file was changed (so, changed cache key and then no cache), it took 17s to install the packages and 1m20s to save the cache.
I use https://www.sonatype.com/products/sonatype-nexus-repository, so that might already remove the need to cache again the deps.
1m20s sounds like you either have an enormous set of deps to cache, or a very slow transfer speed. With GitHub Actions my cache save time was generally under 10 seconds.
I'm a bit confused, can someone help me out. This seems to be so suspiciously fast that it seems impossible.
I just refactored a workflow. The steps used to look like this (bunch of details omitted for brevity):
Single cached install step, then multiple parallel jobs after that
install-cache:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: yarn install
- run: npx playwright install
- uses: actions/cache/save@v4
test-types:
needs: install-cache
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
- run: yarn test:types
test-unit:
needs: install-cache
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
- run: yarn test:unit
test-e2e:
needs: install-cache
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
- run: yarn test:e2e
While experimenting with transitioning our stack from Node/Yarn to Bun, I updated this to just look like this:
All jobs start right away in parallel, install step just duplicated in every job
test-types:
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run test:types
test-unit:
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run test:unit
test-e2e:
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bunx playwright install
- run: bun run test:e2e
And... Bun installs the packages in less than a second? How is that possible when we have ~50 dependencies? Surely just the network download of the packages alone must take more than a second? Is there some kind of edge computing going on here where Actions can download the packages extra fast? Or is there a hidden cache somewhere that I'm unable to see? Our Actions cache page seems to be empty, and I believe even if some third-party action (e.g.
setup-node
) saves some cache for you (without using @actions/cache
directly), it would show up there? I'm used to yarn install
taking over a minute, and I figured a large % of that was the downloading, but maybe it really was the dependency resolution stuff that was taking the most time (which is what bun crushes yarn with)?
More details about how just ditching @actions/cache all-together saved me time
Regarding the fact that my change doesn't cache playwright anymore... simply saving (~10s) and restoring (~10s) our node_modules
and playwright with @actions/cache
takes longer than just installing playwright once (~12s).
Here are some comparison of run times between the different caching/installation approaches:
cache miss, need to do cache-save before cache-restores | cache hit, only need to do cache-restores | no cache step at all |
---|---|---|
run | run | run |
Does anyone have insight into why the results here seem to vary so much? Some reports of cache being much faster, some reports of cache being the same, and some reports (myself included) showing cache taking longer.
No cache: 21s to download and install Cache: 19s to restore ~600 mb cache, 8s to install
GitHub Action with no cache
name: Bun Install Benchmark
on:
push:
branches:
- main
workflow_dispatch:
jobs:
dependencies:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install Dependencies
run: bun i
GitHub Action with cache
name: Bun Install (With Cache) Benchmark
on:
push:
branches:
- main
workflow_dispatch:
jobs:
dependencies:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install Dependencies
run: bun i