Skip to content

Commit 202e0a0

Browse files
authored
release: add verify-image-digests.sh and release-image-digests.sh scripts (#2933)
1 parent b0be52e commit 202e0a0

File tree

5 files changed

+154
-5
lines changed

5 files changed

+154
-5
lines changed

docs/release-procedure.md

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ critical bug fixes.
1616
2. Update the minor version with the expected version.
1717

1818
Make changes in the `docs/manifests/tests/examples` directories using the
19-
`hack/bump_release.sh` script by running the following command:
19+
`hack/bump-release.sh` script by running the following command:
2020

2121
```bash
2222
$ hack/bump-release.sh 28 29 0
2323
```
2424

25-
This will replace `1.28.x`/`2.28.x` with `1.29.0`/`2.29.0` strings in the
25+
This will replace `1.28.x` with `1.29.0` strings in the
2626
`docs/manifests/tests/examples` directories. Ensure that you double-check the
2727
diff before committing the changes. Non-related changes must not be shipped.
2828

@@ -43,8 +43,32 @@ critical bug fixes.
4343

4444
6. Make PR modifying [images.yaml](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-provider-os/images.yaml) to promote gcr.io images to registry.k8s.io. The point is to copy the proper image sha256 hashes from the staging repository to the images.yaml.
4545

46-
7. Once images are promoted create release notes using the "Generate release notes" button in the GitHub "New release" UI and publish the release.
46+
Use `hack/release-image-digests.sh` script and `hack/verify-image-digests.sh` to verify the digests before submitting the PR.
47+
48+
```bash
49+
$ ./hack/release-image-digests.sh ../k8s.io/registry.k8s.io/images/k8s-staging-provider-os/images.yaml vX.Y.Z
50+
```
51+
52+
Generate a PR with the updated `images.yaml` file. Make sure to review the changes and ensure that the correct images are being promoted.
53+
54+
7. Once images are promoted (takes about 30 minutes) create release notes using the "Generate release notes" button in the GitHub "New release" UI and publish the release.
55+
56+
8. Update the helm chart version with the expected version.
57+
58+
Make changes in the `charts` directory using the
59+
`hack/bump-release.sh` script by running the following command:
60+
61+
```bash
62+
$ hack/bump-charts.sh 28 29 0
63+
```
64+
65+
This will replace `1.28.x`/`2.28.x` with `1.29.0`/`2.29.0` strings in the
66+
`docs/manifests/tests/examples` directories. Ensure that you double-check the
67+
diff before committing the changes. Non-related changes must not be shipped.
68+
69+
Make a PR to bump the chart version in the `charts` directory. Once the PR is
70+
merged, the chart will be automatically published to the repository registry.
4771

48-
8. Update `kubernetes/test-infra` to add jobs for the new release branch in the [`config/jobs/kubernetes/cloud-provider-openstack`](https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes/cloud-provider-openstack) directory.
72+
9. Update `kubernetes/test-infra` to add jobs for the new release branch in the [`config/jobs/kubernetes/cloud-provider-openstack`](https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes/cloud-provider-openstack) directory.
4973

5074
This is generally as simple as copying the `release-master` file to `release-X.Y`, adding `--release-XY` suffixes to the job names and `testgrid-tab-name` annotations, and updating the branch specifiers.

hack/bump-charts.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/sh
2+
3+
# Copyright 2025 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
FROM_MAJOR="${1:?FROM_MAJOR (1st arg) not set or empty}"
18+
TO_MAJOR="${2:?TO_MAJOR (2nd arg) not set or empty}"
19+
TO_MINOR="${3:?TO_MINOR (3rd arg) not set or empty}"
20+
21+
# example usage: hack/bump-release.sh 28 28 1
22+
# should replace 1.28.x with 1.28.1 / 2.28.x with 2.28.1
23+
24+
find charts -type f -exec sed -i -re 's/((ersion)?: ?v?)?([1-2]\.)'${FROM_MAJOR}'\.([0-9][0-9a-zA-Z.-]*)/\1\3'${TO_MAJOR}'.'${TO_MINOR}'/g' "{}" \;

hack/bump-release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ TO_MINOR="${3:?TO_MINOR (3rd arg) not set or empty}"
2121
# example usage: hack/bump-release.sh 28 28 1
2222
# should replace 1.28.x with 1.28.1 / 2.28.x with 2.28.1
2323

24-
find charts docs manifests tests examples -type f -exec sed -i -re 's/((ersion)?: ?v?)?([1-2]\.)'${FROM_MAJOR}'\.([0-9][0-9a-zA-Z.-]*)/\1\3'${TO_MAJOR}'.'${TO_MINOR}'/g' "{}" \;
24+
find docs manifests tests examples -type f -exec sed -i -re 's/((ersion)?: ?v?)?([1-2]\.)'${FROM_MAJOR}'\.([0-9][0-9a-zA-Z.-]*)/\1\3'${TO_MAJOR}'.'${TO_MINOR}'/g' "{}" \;

hack/release-image-digests.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
3+
# Copyright 2025 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# example:
18+
# ./release-image-digests.sh registry.k8s.io/images/k8s-staging-provider-os/images.yaml [v1.33.0] [v1.33.1]
19+
20+
YAML_FILE=${1:?Usage: $0 <yaml_file> [<tag>...]}
21+
TAGS="${@:2}"
22+
23+
# fail if file does not exist
24+
if [ ! -f "${YAML_FILE}" ]; then
25+
echo "ERROR: File ${YAML_FILE} does not exist" >&2
26+
exit 1
27+
fi
28+
29+
if [ -z "$TAGS" ]; then
30+
echo "Processing existing tags in ${YAML_FILE}..."
31+
TAGS=$(yq '[.[] | .dmap | to_entries[] | .value[]] | unique | sort | .[]' "${YAML_FILE}")
32+
fi
33+
34+
IMAGES=$(yq '.[] | .name' "${YAML_FILE}")
35+
for TAG in $TAGS; do
36+
for IMAGE in $IMAGES; do
37+
#echo "Processing image: $IMAGE:$TAG)"
38+
digest="$(curl -sI "https://gcr.io/v2/k8s-staging-provider-os/${IMAGE}/manifests/${TAG}" | awk '/(i?)docker-content-digest/{ gsub(/\r/, ""); print tolower($NF)}')"
39+
if [ -z "$digest" ]; then
40+
echo "ERROR: gcr.io/k8s-staging-provider-os/$IMAGE:$TAG digest is empty" >&2
41+
continue
42+
fi
43+
44+
# add new digest -> tag mapping
45+
yq -i '(.[] | select(.name == "'"${IMAGE}"'") | .dmap["'"${digest}"'" | . style="double"]) = (["'"${TAG}"'" | . style="double"] | . style="flow")' "${YAML_FILE}"
46+
# add/replace existing digest -> tag mapping
47+
# yq -i '(.[] | select(.name == "'"${IMAGE}"'") | .dmap) |= with_entries(select(.value[] | contains("'"${TAG}"'") | not)) | (.[] | select(.name == "'"${IMAGE}"'") | .dmap["'"${digest}"'" | . style="double"]) = (["'"${TAG}"'" | . style="double"] | . style="flow") ' "${YAML_FILE}"
48+
done
49+
done
50+
51+
echo "YAML file updated: $YAML_FILE"

hack/verify-image-digests.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/bash
2+
3+
# Copyright 2025 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# example:
18+
# ./verify-image-digests.sh 'v1.33.*' registry.k8s.io/images/k8s-staging-provider-os/images.yaml
19+
20+
# default to match all images
21+
MATCH=${1:-'.*'}
22+
23+
# fail if $2 is not set
24+
YAML_FILE=${2:?Usage: $0 '<match>' <yaml_file>}
25+
26+
# fail if file does not exist
27+
if [ ! -f "${YAML_FILE}" ]; then
28+
echo "ERROR: File ${YAML_FILE} does not exist" >&2
29+
exit 1
30+
fi
31+
32+
while read -r IMAGE DIGEST TAG; do
33+
#echo "image=$IMAGE, digest='$DIGEST', tag=$TAG"
34+
digest="$(curl -sI "https://gcr.io/v2/k8s-staging-provider-os/${IMAGE}/manifests/${TAG}" | awk '/(i?)docker-content-digest/{ gsub(/\r/, ""); print tolower($NF)}')"
35+
if [ -z "$digest" ]; then
36+
echo "ERROR: gcr.io/k8s-staging-provider-os/$IMAGE:$TAG digest is empty" >&2
37+
continue
38+
fi
39+
if [ "$digest" != "$DIGEST" ]; then
40+
echo "ERROR: gcr.io/k8s-staging-provider-os/$IMAGE:$TAG digest mismatch: expected $DIGEST, got $digest" >&2
41+
fi
42+
digest1="$(curl -sIL "https://registry.k8s.io/v2/provider-os/${IMAGE}/manifests/${TAG}" | awk '/(i?)docker-content-digest/{ gsub(/\r/, ""); print tolower($NF)}')"
43+
if [ -z "$digest1" ]; then
44+
echo "ERROR: registry.k8s.io/provider-os/$IMAGE:$TAG digest is empty" >&2
45+
continue
46+
fi
47+
if [ "$digest1" != "$DIGEST" ]; then
48+
echo "ERROR: registry.k8s.io/provider-os/$IMAGE:$TAG digest mismatch: expected $DIGEST, got $digest1" >&2
49+
fi
50+
done <<< `yq '.[] | .name as $name | .dmap | to_entries | sort_by(.value[0]) | reverse | .[] | select(.value[0] | test("'"${MATCH}"'")) | "\($name) \(.key) \(.value[0])"' "${YAML_FILE}"`

0 commit comments

Comments
 (0)