-
Notifications
You must be signed in to change notification settings - Fork 58
Add cache-dir input to allow specifying cache content location during auto-discovery
#52
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
Conversation
src/opts.ts
Outdated
| const target = "/var/cache-target"; | ||
|
|
||
| cacheMap[id] = { | ||
| cacheMap[`${bindRoot}/${id}`] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A breaking change because of this. I could update this to allow bindRoot to be null to restore the original behavior. However, the only scenario where the original behavior could work reliably is when the ids were all explicitly set which would make their source be the working directory. We could avoid breakage by making the default cache-dir be . if we want a mostly breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the approach of maintaining backward compatibility by defaulting cache-dir to ..
This way, we avoid having to release a major version with breaking changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update this to avoid having a breaking change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes are now fully backwards compatible. I didn't go with the cache-dir="." approach as that was still breaking for cache mount ids with absolute paths
|
@bennesp did you want to give this a review? |
bennesp
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the problem you’re addressing and I really appreciate the solution you’ve proposed.
At the same time, I would prefer if the change could be implemented in a way that avoids breaking compatibility, so it doesn’t break any existing workflows.
That said, since I’m not the repository owner, this is just my opinion, feel free to challenge it 😄
| with: | ||
| images: Build | ||
|
|
||
| - name: Cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switching this example from two caches to just one sounds a bit confusing.
In my use cases it’s important to use two different caches because they have different lifecycles: one gets reused more often, while the other is invalidated more frequently.
So it would be nice to keep an example showing how to handle both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate more on what you'd like to see? The updated example uses one GHA cache for all of the cache mounts just like the original example did. The only difference here is that the cache-map is generated from the Dockerfile and that the locations of the cache mounts on disk are ./cache-mount//var/cache/apt and ./cache-mount//var/lib/apt instead of ./var-cache-apt and ./var-lib-apt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I think I got confused by the two paths we had previously, but indeed the cache is just one.
To be sure I got it right, please follow this scenario:
- A
Dockerfilewith two caches:--mount=type=cache,id=var-cache-aptand--mount=type=cache,id=var-lib-apt - A workflow like the following:
- name: Cache
uses: actions/cache@v3
id: cache
with:
path: |
var-cache-apt
var-lib-apt
key: cache-${{ hashFiles('.github/workflows/test/Dockerfile') }}
- name: Restore Docker cache mounts
uses: reproducible-containers/[email protected]Given the two points above, I would expect the "Restore" step to work correctly, by populating the builder cache with the content of ./var-cache-apt and ./var-lib-apt.
Is it correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the Dockerfile you mentioned the example you provided is correct given that a cache-map is also provided. An example with that included would be:
- name: Cache
uses: actions/cache@v3
id: cache
with:
path: |
var-cache-apt
var-lib-apt
key: cache-${{ hashFiles('.github/workflows/test/Dockerfile') }}
- name: Restore Docker cache mounts
uses: reproducible-containers/[email protected]
with:
cache-map: |
{
"var-cache-apt": "/var/cache/apt",
"var-lib-apt": "/var/lib/apt"
}Alternatively these equivalent examples would also work with that same Dockerfile with variations to the cache-map:
Extracting the cache-map from the Dockerfile
- name: Cache
uses: actions/cache@v3
id: cache
with:
path: |
/var/cache/apt
/var/lib/apt
key: cache-${{ hashFiles('.github/workflows/test/Dockerfile') }}
- name: Restore Docker cache mounts
uses: reproducible-containers/[email protected]
with:
dockerfile: DockerfileNote: This example would only be possible if additional permissions are granted in GHA. I tried this and ran into this problem:
No cache map provided. Trying to parse the Dockerfile to find the cache mount instructions...
Cache map parsed from Dockerfile: {"/var/cache/apt":{"id":"/var/cache/apt","target":"/var/cache-target"},"/var/lib/apt":{"id":"/var/lib/apt","target":"/var/cache-target"}}
Error: EACCES: permission denied, open '/var/cache/apt/buildstamp'
at async open (node:internal/fs/promises:639:25)
at async Object.writeFile (node:internal/fs/promises:1216:14)
at async $bd1d73aff0732146$var$injectCache (file:///home/runner/work/_actions/reproducible-containers/buildkit-cache-dance/653a570f730e3b9460adc576db523788ba59a0d7/dist/index.js:7152:5)
at async $bd1d73aff0732146$export$38c65e9f06d3d433 (file:///home/runner/work/_actions/reproducible-containers/buildkit-cache-dance/653a570f730e3b9460adc576db523788ba59a0d7/dist/index.js:7199:72)
at async $bec5d2ddaaf4a876$var$main (file:///home/runner/work/_actions/reproducible-containers/buildkit-cache-dance/653a570f730e3b9460adc576db523788ba59a0d7/dist/index.js:7306:9)
at async file:///home/runner/work/_actions/reproducible-containers/buildkit-cache-dance/653a570f730e3b9460adc576db523788ba59a0d7/dist/index.js:7310:5 {
errno: -13,
code: 'EACCES',
syscall: 'open',
path: '/var/cache/apt/buildstamp'
}
Extracting the cache-map from the Dockerfile and use cache-dir
- name: Cache
uses: actions/cache@v3
id: cache
with:
path: |
cache-mount/var/cache/apt
cache-mount/var/lib/apt
key: cache-${{ hashFiles('.github/workflows/test/Dockerfile') }}
- name: Restore Docker cache mounts
uses: reproducible-containers/[email protected]
with:
dockerfile: Dockerfile
cache-dir: cache-mountThis would generate the following cache-map:
{
"cache-mount//var/cache/apt": {
"id":"/var/cache/apt",
"target":"/var/cache-target"
},
"cache-mount//var/lib/apt":{
"id":"/var/lib/apt",
"target":"/var/cache-target"
}
}This example is equivalent to what I currently am proposing just a little more verbose for the path in actions/cache.
src/opts.ts
Outdated
| const target = "/var/cache-target"; | ||
|
|
||
| cacheMap[id] = { | ||
| cacheMap[`${bindRoot}/${id}`] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the approach of maintaining backward compatibility by defaulting cache-dir to ..
This way, we avoid having to release a major version with breaking changes.
| "var-lib-apt": "/var/lib/apt" | ||
| } | ||
| skip-extraction: ${{ steps.cache.outputs.cache-hit }} | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this change relevant to cache-dir?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I updated the primary example of how to use this action above to demonstrate how to use dockerfile/cache-dir I moved the snippet from the original example here. Doing this was necessary as this sentence no longer made sense since there was no example using a "single string":
Optionally, instead of a single string for the
targetyou can provide an object with additional options that should be passed to--mount=type=cachein the valuescache-mapJSON. Thetargetpath must be present in the object as a property.
|
Please squash commits that are related to the |
Signed-off-by: Curtis Vogt <[email protected]>
Signed-off-by: Curtis Vogt <[email protected]>
Done. I've kept the README change as a separate commit as it appears you may want that removed from this PR entirely |
|
@AkihiroSuda can you give this another review? |
|
Will review this week, sorry for the delay |
AkihiroSuda
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, sorry for the delay
Follow up to #49. We need to be able to specify the location on the host system where the bind directory is located which will be used for injecting/extracting cache data. Without this change users can easily run into issues when using absolute paths for their
id: