name: ci-single.yml
on:
workflow_dispatch:
jobs:
build:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Cache the PNPM store
uses: actions/cache@v3
with:
path: ~/.rush-pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('common/config/rush/pnpm-lock.yaml') }}-v1001
# If we can't find a match, restore the latest cache entry
restore-keys: |
${{ runner.os }}-pnpm-
- name: Set RUSH_PNPM_STORE_PATH
run: echo "RUSH_PNPM_STORE_PATH=~/.rush-pnpm-store" >> $GITHUB_ENV
- name: Rush Install
run: node common/scripts/install-run-rush.js install
Good situation
There is a cache miss
We run rush install
The "Post" action writes ~/.rush-pnpm-store to the cache
And on the next run:
There is a cache hit
We run rush install and it goes much faster
The "Post" action does nothing
Bad situation with apparently no solution
There is a cache miss
We run rush install and it fails right away (for example, a config file has a syntax error)
The "Post" action writes a completely empty ~/.rush-pnpm-store to the cache
And now for the next 7 days, every run goes like this:
There is a cache hit, which restores an empty folder
We run rush install and it is extremely slow
The "Post" action does nothing
Is the magical "Post" action even a good design?
This would be easy to solve if the cache read/write were separate steps.
Hypothetical Example
name: ci-single.yml
on:
workflow_dispatch:
jobs:
build:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- uses: actions/setup-node@v3
with:
node-version: 16
- name: READ the PNPM store
uses: actions/cache@v3
with:
mode: read-only # πππ
path: ~/.rush-pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('common/config/rush/pnpm-lock.yaml') }}-v1001
# If we can't find a match, restore the latest cache entry
restore-keys: |
${{ runner.os }}-pnpm-
- name: Set RUSH_PNPM_STORE_PATH
run: echo "RUSH_PNPM_STORE_PATH=~/.rush-pnpm-store" >> $GITHUB_ENV
- name: Rush Install
run: node common/scripts/install-run-rush.js install
- name: WRITE the PNPM store
uses: actions/cache@v3
with:
mode: write-only # πππ
path: ~/.rush-pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('common/config/rush/pnpm-lock.yaml') }}-v1001
# If we can't find a match, restore the latest cache entry
restore-keys: |
${{ runner.os }}-pnpm-
Benefits:
The cache won't get written unless "rush install" succeeds
In fact, I can control exactly when the cache write happens. For example, maybe it is more efficient to write before attempting "rush build" (not shown in this excerpt).
Are there workaround?
actions/cache@v3 introduced a confusingly named setting lookup-only that sounds like it disables the post write:
lookup-only - If true, only checks if cache entry exists and skips download. Does not change save cache behavior. Default: false
But actually disables the read, not the write.
As far as I can tell, there is absolutely no way to use actions/cache to read from the cache without saving something.
Why is it designed like that? Should we improve it?
A simple example:
Good situation
rush install
~/.rush-pnpm-store
to the cacheAnd on the next run:
rush install
and it goes much fasterBad situation with apparently no solution
rush install
and it fails right away (for example, a config file has a syntax error)~/.rush-pnpm-store
to the cacheAnd now for the next 7 days, every run goes like this:
rush install
and it is extremely slowIs the magical "Post" action even a good design?
This would be easy to solve if the cache read/write were separate steps.
Hypothetical Example
Benefits:
Are there workaround?
actions/cache@v3
introduced a confusingly named settinglookup-only
that sounds like it disables the post write:But actually disables the read, not the write.
As far as I can tell, there is absolutely no way to use
actions/cache
to read from the cache without saving something.Why is it designed like that? Should we improve it?