ko-build / ko

Build and deploy Go applications
https://ko.build
Apache License 2.0
7.64k stars 401 forks source link

Idea: ko rebase #358

Open imjasonh opened 3 years ago

imjasonh commented 3 years ago

When a newer version of a base image is available, in some cases you can pick up those updates without having to completely rebuild your image from scratch on top of the new base image. Instead, you can rebase. It just so happens ko builds images that are amenable to rebasing. 👍

With future improvements to the OCI spec to declare standard annotations to signal base image information, crane will be able to take advantage of these annotations to detect and rebase images without any external information required.

ko resolve builds a bunch of images, by default based on gcr.io/distroless/static:nonroot. If ko produced images that wrote base image annotations, it could also have a CLI surface to ingest YAML generated by a previous ko resolve to detect image references, determine base image information for those images, identify new available base image versions, perform a rebase, and replace image references in the output YAML.

The result would be a workflow like: ko resolve > release.yaml, wait for a distroless release, ko rebase release.yaml > release.yaml, and release.yaml would now include images based on the new distroless release, without having to rebuild anything at all, or even have access to the original source.

jonjohnsonjr commented 3 years ago

it could also have a CLI surface to ingest YAML generated by a previous ko resolve to detect image references

Detecting which strings are actually images is a bit tricky. With the original ko yaml, we have ko:// prefixes, which makes this easy, but we will have to hit the internet to detect which strings are definitely images and we'll need some way to distinguish ko-built images that we want to rebase.

I think it would be fine to have ko rebase as a command, but this makes me think about how we might decouple the operation from the source and sink.

Imagine:

# Extract images from release.yaml
ko extract -f release.yaml
example.com/foo:bar
example.com/baz@sha256:abc
# Drop into a streaming mode that reads from stdin and writes to stdout
ko extract -f release.yaml | crane rebase -
example.com/foo:bar@sha256:aaa
example.com/baz@sha256:def
# Equivalent to `ko rebase -f release.yaml`
ko extract -f release.yaml | crane rebase - | ko rewrite -f release.yaml --images - > rebased.yaml

Assuming that ko extract and ko rewrite use the same logic for finding images within release.yaml in the exact same order, ko rewrite can know which image references to replace. A little bit of care around deduplication, and we've got a lovely little tool :P

imjasonh commented 3 years ago

If we expect KO_DOCKER_REPO to be set, can we search the YAML for string values with the KO_DOCKER_REPO prefix?

That is, if KO_DOCKER_REPO=gcr.io/hello,

images:
- some/other:image
- gcr.io/hello/ko-built-me

would only return gcr.io/hello/ko-built-me, and not the other image ref.

mattmoor commented 3 years ago

With the original ko yaml, we have ko:// prefixes

What if it only applied to strings with the $KO_DOCKER_REPO prefix 😉

EDIT: keeps reading and sees @imjasonh suggesting exactly this 🤦