-
Notifications
You must be signed in to change notification settings - Fork 26
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
fix: filter out anonymous images #789
Conversation
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 would love feedback from users regarding whether this change would be beneficial to them. As a user, I would personally prefer that the action fail so that I realize I forgot to name and tag my Docker images. Clearly we could fail more gracefully than we currently do, but my initial concern is that this approach is too clever and will prevent downstream issues from being detected. I have reviewed the change in any case so that it's clear to everyone what would need to change if there is a clear user preference for silently ignoring anonymous Docker images. Any context anyone can offer around how and when such images most often arise would be greatly appreciated.
@@ -42,7 +42,8 @@ const saveDockerImages = async (): Promise<void> => { | |||
const images = await execBashCommand(LIST_COMMAND); | |||
const imagesList = images.split("\n"); | |||
const newImages = imagesList.filter( | |||
(image: string): boolean => !preexistingImages.includes(image), | |||
(image: string): boolean => | |||
!preexistingImages.includes(image) && image !== "<none>:<none>", |
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.
The failure also occurs when only the tag is <none>
(or presumably when only the image name is <none>
), so we should instead check !image.startsWith("<none>:") && !image.endsWith(":<none>") && !preexistingImages.includes(image)
. It may be wrong in this case, but my instinct is typically to do the constant-time checks first for best performance.
newImages.length === 0 || | ||
newImages.every((img) => img == "<none>:<none>") |
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.
This could be simplified/corrected to: newImages.some((image: string): boolean => !image.startsWith("<none>:") && !image.endsWith(":<none>"))
. I don't recommend using ==
in JavaScript.
@@ -268,6 +271,7 @@ describe("Docker images", (): void => { | |||
["my-key", false, false, [["preexisting-image"], []]], | |||
["my-key", false, true, [["preexisting-image"], ["new-image"]]], | |||
["my-key", true, false, [["preexisting-image"], ["new-image"]]], | |||
["my-key", false, false, [["preexisting-image"], ["<none>:<none>"]]], |
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.
Astutely observed that this change was needed! We should probably also bias the dockerImages
arbitrary to generate some unnamed and/or untagged Docker images, but I can certainly understand if you would prefer not to get into that in this PR.
`docker save {{ .ID }}` would allow us to cache/load such anonymous images. | ||
However, the docker client loses reference to the original | ||
`{{ .Repository }}:{{ .Tag }}` value upon `docker load` for previously | ||
named images, resulting in: | ||
|
||
```sh | ||
my-image:tag | ||
``` | ||
|
||
to become | ||
|
||
```sh | ||
<none>:<none> | ||
``` | ||
|
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.
This is great context for the commit message, but I doubt the typical developer cares to know our rationale, and I am sensitive to how quickly people stop reading once they feel the docs are no longer relevant.
@@ -94,6 +97,30 @@ True on cache hit (even if the subsequent | |||
failed) and false on cache miss. See also | |||
[skipping steps based on cache-hit](https://github.com/marketplace/actions/cache#Skipping-steps-based-on-cache-hit). | |||
|
|||
## Anonymous image names | |||
|
|||
Anonymous images (eg. `<none>:<none>`) will be skipped during caching |
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.
Nit: "eg." --> "e.g.,"
Be sure to name + tag those images you wish to be handled by the caching | ||
and loading operations in this action. |
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.
"handled by the caching and loading operations in this action" --> "cached" for brevity
Be sure to name + tag those images you wish to be handled by the caching | ||
and loading operations in this action. |
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.
This can be combined with the first paragraph.
@@ -94,6 +97,30 @@ True on cache hit (even if the subsequent | |||
failed) and false on cache miss. See also | |||
[skipping steps based on cache-hit](https://github.com/marketplace/actions/cache#Skipping-steps-based-on-cache-hit). | |||
|
|||
## Anonymous image names |
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.
This section is only relevant to a small minority of users, so let's move it below the Permissions section.
@@ -18,3 +18,5 @@ build | |||
!.yarn/releases | |||
!.yarn/sdks | |||
!.yarn/versions | |||
|
|||
node_modules/ |
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 on the rationale for this change?
- [`key`](#key) | ||
- [Optional](#optional) | ||
- [`read-only`](#read-only) |
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.
This doesn't seem related to this pull request. I'm guessing this change was made by our tooling?
Our contributing guide explains how to run our CI locally. That plus a rebase will likely get you through the remaining build errors. |
Actually, it occurs to me that we could probably save the anonymous images by ID and the named ones by name to avoid the need for filtering? I think we may even be able to pull this off by using conditional expressions in the format string that we pass on the command line. Concretely, I am imagining that the only production change needed may be to set: LIST_COMMAND = `docker image list --format '{{ if ne .Repository "<none>" }}{{ .Repository }}{{ if ne .Tag "<none>" }}:{{ .Tag }}{{ end }}{{ else }}{{ .ID }}{{ end }}'` This will cause us to use the image name and tag when available, but fall back on the ID otherwise. I am assuming that Docker disallows tagging of anonymous images, but if it's possible to have an image with a tag but no name, then the template would need to be modified to handle that case. Here are the pertinent Docker docs, which link to the Go template syntax. |
Superseded by #816, where I have implemented the strategy described in my previous comment. |
relates to #572
through local testing, i'm finding that using
docker save {{ .ID }}
actually anonymizes named images upondocker load
given this docker client behavior, i'm thinking we might just want to filter out the anonymous images (these aren't being cached currently anyway, due to the docker client not accepting
<none>:<none>
as a save-able image input)I dont see the tests running in CI/CD, so here's an output of
npm run test