helm / helm

The Kubernetes Package Manager
https://helm.sh
Apache License 2.0
27.03k stars 7.11k forks source link

Support reproducible builds to an OCI registry #12973

Open stevehipwell opened 6 months ago

stevehipwell commented 6 months ago

I'd like to be able to support creating Helm charts targeting an OCI registry as a reproducible build, which means being able to pass in the value for the org.opencontainers.image.created OCI annotation to helm push. This would build on the changes made in #12903 but work for cases where the package was being recreated.

An example use case for this would be as follows.

chart="my-chart"
chart_path="./charts/${chart}"
version="0.1.0"

date_epoch="$(git log -1 --format='%ct' "${chart_path}")"
created_date="$(date -u --date="@${date_epoch}" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null)"

helm package "${chart_path}" --version "${version}"
helm push --created-date "${created_date}" "${chart}-${version}.tgz" "oci://my-registry.io/my-repo/${chart}"

CC @sabre1041

sabre1041 commented 6 months ago

@stevehipwell been thinking about the different options at hand and comparing existing container/artifact packaging tools.

Docker does not natively support adding creation timestamps via CLI options, but Podman does. For Docker, labels (associated with the org.opencontainers.image.created) can be add during build time. ORAS does provide the ability to specify annotations that are applied to the artifact either from inline parameters or from a file.

There are really two options that could be applied at artifact push time:

stevehipwell commented 6 months ago

@sabre1041 my preference for Helm v3 would be to support either the proposed --created-date or ORAS mirroring --annotation (I'm not sure why this is annotation and not --label?) flag. Logically this is aligned well with the current implementation which is either now or the created date of a file.

For Helm v4 I think there are some really good use cases for driving the annotations from another location to Chart.yaml; personally I'd like to see the chart source be (more) static with common changes such as image tag/digest, CHANGELOG, etc being merged to create the package. But I guess that's another discussion; I missed the Helm 4 highway KubeCon session and can't find the recording so I don't know if this was covered.

sabre1041 commented 6 months ago

@stevehipwell Labels (in the traditional container build sense) are stored within the OCI Image Configuration. Helm stores the contents of the Chart.yaml in the OCI Image Configuration, but what we would want to target here is the OCI annotations that are placed on the OCI Image Manifest. Helm populates a set of default annotations along with user defined annotations within the Chart.yaml file. The logic for populating annotations are found here.

stevehipwell commented 6 months ago

@sabre1041 in this case the only annotation changing is the created one, so what's required is to set that manually. I had the same issue with ORAS pushing the Artifact Hub config, but due to the --annotation flag it was easily solved.

sabre1041 commented 6 months ago

@sabre1041 in this case the only annotation changing is the created one, so what's required is to set that manually. I had the same issue with ORAS pushing the Artifact Hub config, but due to the --annotation flag it was easily solved.

I personally lean toward the annotation and/or annotation-file options as it provides flexibility to include other use cases in the future

stevehipwell commented 6 months ago

@sabre1041 wouldn't the annotation pattern require significantly more code to implement? I think it's the right way to go but I'm not sure if it's a reason not to also do the pragmatic option?

Adding a --created-date flag (I think this aligns with the annotation) to override the current logic would be pretty simple and consistent with the current behaviour. I assume that if/when the annotation functionality was added it'd take precedent over the existed created date logic anyway.

github-actions[bot] commented 3 months ago

This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.

stevehipwell commented 3 months ago

/not-stale

sabre1041 commented 1 month ago

related to #13272

gjenkins8 commented 1 month ago

The above PR would allow:

helm package "${chart_path}" --version "${version}"
touch -m -t 197001010000.00 "${chart}-${version}.tgz"
helm push "${chart}-${version}.tgz" "oci://my-registry.io/my-repo/${chart}"

Note sure if this is the final/desired solution. But perhaps a possible one?

stevehipwell commented 1 month ago

@gjenkins8 @sabre1041 fixing the broken implementation makes sense. However as it isn't portable or part of the Helm logic it doesn't solve the problem this issue is specifically for.

Although on a Linux system it should be possible to use the touch workaround, this seems like a significant complexity overhead for passing in a single value; supporting an input would actually reduce the complexity as the filesystem metadata wouldn't be required.