From bc0e68c1c3f70017b74c72239ef4b4a7b462615e Mon Sep 17 00:00:00 2001 From: maru Date: Mon, 10 Nov 2025 20:44:40 +0000 Subject: [PATCH] [bootstrapmonitor] Switch from `latest` to `master` tag A recent PR (#4469) proposes to change the `latest` tag to refer to the image of the most recent release intead of the latest merge to master. This change requires updating the bootstrap monitor to use the `master` tag (already updated on every merge to master) to ensure bootstrap testing continues to target the most recently published image. --- scripts/build_image.sh | 14 ++++++++++---- scripts/tests.load.kube.kind.sh | 4 ++-- tests/fixture/bootstrapmonitor/README.md | 10 +++++----- .../bootstrapmonitor/bootstrap_test_config.go | 2 +- tests/fixture/bootstrapmonitor/common.go | 8 ++++---- tests/fixture/bootstrapmonitor/e2e/e2e_test.go | 6 +++--- tests/fixture/bootstrapmonitor/init.go | 14 +++++++------- tests/fixture/bootstrapmonitor/wait.go | 14 +++++++------- 8 files changed, 39 insertions(+), 33 deletions(-) diff --git a/scripts/build_image.sh b/scripts/build_image.sh index d96547abc58d..7806a499847a 100755 --- a/scripts/build_image.sh +++ b/scripts/build_image.sh @@ -9,7 +9,7 @@ set -euo pipefail # DOCKER_IMAGE=myavalanchego ./scripts/build_image.sh # Build local single arch image with a custom image name # DOCKER_IMAGE=avaplatform/avalanchego ./scripts/build_image.sh # Build and push multi-arch image to docker hub # DOCKER_IMAGE=localhost:5001/avalanchego ./scripts/build_image.sh # Build and push multi-arch image to private registry -# DOCKER_IMAGE=localhost:5001/avalanchego FORCE_TAG_LATEST=1 ./scripts/build_image.sh # Build and push image to private registry with tag `latest` +# DOCKER_IMAGE=localhost:5001/avalanchego FORCE_TAG_MASTER=1 ./scripts/build_image.sh # Build and push image to private registry with tag `master` # Multi-arch builds require Docker Buildx and QEMU. buildx should be enabled by # default in the version of docker included with Ubuntu 22.04, and qemu can be @@ -32,8 +32,8 @@ AVALANCHE_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) # Skip building the race image SKIP_BUILD_RACE="${SKIP_BUILD_RACE:-}" -# Force tagging as latest even if not the master branch -FORCE_TAG_LATEST="${FORCE_TAG_LATEST:-}" +# Force tagging as master for testing purposes +FORCE_TAG_MASTER="${FORCE_TAG_MASTER:-}" # Load the constants source "$AVALANCHE_PATH"/scripts/constants.sh @@ -117,7 +117,13 @@ if [[ -z "${SKIP_BUILD_RACE}" ]]; then fi # Only tag the latest image for the master branch when images are pushed to a registry -if [[ "${DOCKER_IMAGE}" == *"/"* && ($image_tag == "master" || -n "${FORCE_TAG_LATEST}") ]]; then +if [[ "${DOCKER_IMAGE}" == *"/"* && $image_tag == "master" ]]; then echo "Tagging current avalanchego images as $DOCKER_IMAGE:latest" docker buildx imagetools create -t "$DOCKER_IMAGE:latest" "$DOCKER_IMAGE:$commit_hash" fi + +# Forcibly tag the image as `master` if requested. This is only intended to be used for testing. +if [[ "${DOCKER_IMAGE}" == *"/"* && -n "${FORCE_TAG_MASTER}" ]]; then + echo "Tagging current avalanchego images as $DOCKER_IMAGE:master" + docker buildx imagetools create -t "$DOCKER_IMAGE:master" "$DOCKER_IMAGE:$commit_hash" +fi diff --git a/scripts/tests.load.kube.kind.sh b/scripts/tests.load.kube.kind.sh index e8069abdf9e3..e0df21de2b4a 100755 --- a/scripts/tests.load.kube.kind.sh +++ b/scripts/tests.load.kube.kind.sh @@ -17,7 +17,7 @@ AVALANCHEGO_IMAGE="localhost:5001/avalanchego" if [[ -n "${SKIP_BUILD_IMAGE:-}" ]]; then echo "Skipping build of avalanchego image due to SKIP_BUILD_IMAGE=${SKIP_BUILD_IMAGE}" else - DOCKER_IMAGE="$AVALANCHEGO_IMAGE" FORCE_TAG_LATEST=1 ./scripts/build_image.sh + DOCKER_IMAGE="$AVALANCHEGO_IMAGE" FORCE_TAG_MASTER=1 ./scripts/build_image.sh fi # Determine kubeconfig context to use @@ -33,4 +33,4 @@ else echo "Defaulting to limited-permission context 'kind-kind-tmpnet' to test RBAC Role permissions" fi -go run ./tests/load/main --runtime=kube --kube-image="$AVALANCHEGO_IMAGE" "$KUBECONFIG_CONTEXT" "$@" +go run ./tests/load/main --runtime=kube --kube-image="$AVALANCHEGO_IMAGE:master" "$KUBECONFIG_CONTEXT" "$@" diff --git a/tests/fixture/bootstrapmonitor/README.md b/tests/fixture/bootstrapmonitor/README.md index 0e190315ab56..ed096d52cfd5 100644 --- a/tests/fixture/bootstrapmonitor/README.md +++ b/tests/fixture/bootstrapmonitor/README.md @@ -94,12 +94,12 @@ and initiates a new test when one is found. - Mounting the same data volume as the avalanchego node - Reading bootstrap test configuration as described previously - Determining the image ID and versions for an image if the - avalanchego image for the pod uses the `latest` tag. This will + avalanchego image for the pod uses the `master` tag. This will only need to be performed the first pod that a bootstrap testing `StatefulSet` runs. Subsequent pods from the same `StatefulSet` should have an image qualified with its SHA and version details set by the previous test run's `wait-for-completion` pod. - - A new pod will be started with the `latest` image to execute + - A new pod will be started with the `master` image to execute `avalanchego --versions-json` to determine the image ID (which includes a sha256 hash) of the image and its avalanchego versions. Those values will then be applied to the `StatefulSet` @@ -109,7 +109,7 @@ and initiates a new test when one is found. versions (including commit hash) of the binary that the image provides. - A separate pod is used because the image ID of a non-init - avalanchego container using a `latest`-tagged image is only + avalanchego container using a `master`-tagged image is only available when that container runs rather than when an init container runs. - While it would be possible to add an init container running the same avalanchego image as the primary avalanchego container, @@ -178,8 +178,8 @@ sync bootstrap usually takes much longer. If avalanchego supported a `--bootstrap-mode` flag that exited on successful bootstrap, and a pod configured with this flag used an -image with a `latest` tag, the pod would continuously bootstrap, exit, -and restart with the current latest image. While appealingly simple, +image with a `master` tag, the pod would continuously bootstrap, exit, +and restart with the current `master` image. While appealingly simple, this approach doesn't directly support: - A mechanism for resuming a long-running bootstrap. Given the diff --git a/tests/fixture/bootstrapmonitor/bootstrap_test_config.go b/tests/fixture/bootstrapmonitor/bootstrap_test_config.go index c14a8d9fa6d1..85fd41581351 100644 --- a/tests/fixture/bootstrapmonitor/bootstrap_test_config.go +++ b/tests/fixture/bootstrapmonitor/bootstrap_test_config.go @@ -111,7 +111,7 @@ func bootstrapTestConfigForPod(pod *corev1.Pod, nodeContainerName string) (*Boot } // Attempt to retrieve the image versions from a pod annotation. The annotation may not be populated in - // the case of a newly-created bootstrap test using an image tagged `latest` that hasn't yet had a + // the case of a newly-created bootstrap test using an image tagged `master` that hasn't yet had a // chance to discover the versions. if versionsAnnotation := pod.Annotations[VersionsAnnotationKey]; len(versionsAnnotation) > 0 { if err := json.Unmarshal([]byte(versionsAnnotation), &testConfig.Versions); err != nil { diff --git a/tests/fixture/bootstrapmonitor/common.go b/tests/fixture/bootstrapmonitor/common.go index 999eb997bb57..5953bcd0b47a 100644 --- a/tests/fixture/bootstrapmonitor/common.go +++ b/tests/fixture/bootstrapmonitor/common.go @@ -127,8 +127,8 @@ type ImageDetails struct { Versions *version.Versions } -// GetLatestImageDetails retrieves the image details for the avalanchego image with tag `latest`. -func getLatestImageDetails( +// GetMasterImageDetails retrieves the image details for the avalanchego image with tag `master`. +func getMasterImageDetails( ctx context.Context, log logging.Logger, clientset *kubernetes.Clientset, @@ -141,7 +141,7 @@ func getLatestImageDetails( return nil, err } - // Start a new pod with the `latest`-tagged avalanchego image to discover its image ID + // Start a new pod with the `master`-tagged avalanchego image to discover its image ID pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "avalanchego-version-check-", @@ -152,7 +152,7 @@ func getLatestImageDetails( Name: containerName, Command: []string{"./avalanchego"}, Args: []string{"--version-json"}, - Image: baseImageName + ":latest", + Image: baseImageName + ":master", }, }, RestartPolicy: corev1.RestartPolicyNever, diff --git a/tests/fixture/bootstrapmonitor/e2e/e2e_test.go b/tests/fixture/bootstrapmonitor/e2e/e2e_test.go index 0317d3e00031..d70f99e165d5 100644 --- a/tests/fixture/bootstrapmonitor/e2e/e2e_test.go +++ b/tests/fixture/bootstrapmonitor/e2e/e2e_test.go @@ -46,7 +46,7 @@ const ( repoRelativePath = "tests/fixture/bootstrapmonitor/e2e" avalanchegoImage = "localhost:5001/avalanchego" - latestAvalanchegoImage = avalanchegoImage + ":latest" + masterAvalanchegoImage = avalanchegoImage + ":master" monitorImage = "localhost:5001/bootstrap-monitor" latestMonitorImage = monitorImage + ":latest" @@ -256,7 +256,7 @@ func buildImage(tc tests.TestContext, imageName string, forceNewHash bool, scrip ) // #nosec G204 cmd.Env = append(os.Environ(), "DOCKER_IMAGE="+imageName, - "FORCE_TAG_LATEST=1", + "FORCE_TAG_MASTER=1", "SKIP_BUILD_RACE=1", ) output, err := cmd.CombinedOutput() @@ -267,7 +267,7 @@ func newNodeStatefulSet(name string, flags tmpnet.FlagsMap) *appsv1.StatefulSet statefulSet := tmpnet.NewNodeStatefulSet( name, true, // generateName - latestAvalanchegoImage, + masterAvalanchegoImage, nodeContainerName, volumeName, volumeSize, diff --git a/tests/fixture/bootstrapmonitor/init.go b/tests/fixture/bootstrapmonitor/init.go index bdc88dc04753..d8e6e5b81ea7 100644 --- a/tests/fixture/bootstrapmonitor/init.go +++ b/tests/fixture/bootstrapmonitor/init.go @@ -49,18 +49,18 @@ func InitBootstrapTest(log logging.Logger, namespace string, podName string, nod } log.Info("Retrieved bootstrap test config", zap.Reflect("testConfig", testConfig)) - // If the image uses the latest tag, determine the latest image id and set the container image to that - if strings.HasSuffix(testConfig.Image, ":latest") { + // If the image uses the master tag, determine the master image id and set the container image to that + if strings.HasSuffix(testConfig.Image, ":master") { log.Info("Determining image id for image", zap.String("image", testConfig.Image)) - latestImageDetails, err := getLatestImageDetails(ctx, log, clientset, namespace, testConfig.Image, nodeContainerName) + masterImageDetails, err := getMasterImageDetails(ctx, log, clientset, namespace, testConfig.Image, nodeContainerName) if err != nil { - return fmt.Errorf("failed to get latest image details: %w", err) + return fmt.Errorf("failed to get master image details: %w", err) } log.Info("Updating owning statefulset with image details", - zap.String("image", latestImageDetails.Image), - zap.Reflect("versions", latestImageDetails.Versions), + zap.String("image", masterImageDetails.Image), + zap.Reflect("versions", masterImageDetails.Versions), ) - if err := setImageDetails(ctx, log, clientset, namespace, podName, latestImageDetails); err != nil { + if err := setImageDetails(ctx, log, clientset, namespace, podName, masterImageDetails); err != nil { return fmt.Errorf("failed to set container image: %w", err) } } diff --git a/tests/fixture/bootstrapmonitor/wait.go b/tests/fixture/bootstrapmonitor/wait.go index d813835be2fe..41cfef0f63b1 100644 --- a/tests/fixture/bootstrapmonitor/wait.go +++ b/tests/fixture/bootstrapmonitor/wait.go @@ -114,25 +114,25 @@ func WaitForCompletion( ctx, cancel := context.WithTimeout(context.Background(), contextDuration) defer cancel() - log.Info("Starting pod to get the image id for the `latest` tag") - latestImageDetails, err := getLatestImageDetails(ctx, log, clientset, namespace, testConfig.Image, nodeContainerName) + log.Info("Starting pod to get the image id for the `master` tag") + masterImageDetails, err := getMasterImageDetails(ctx, log, clientset, namespace, testConfig.Image, nodeContainerName) if err != nil { - log.Error("failed to get latest image id", zap.Error(err)) + log.Error("failed to get master image id", zap.Error(err)) return false, nil } - if latestImageDetails.Image == testConfig.Image { + if masterImageDetails.Image == testConfig.Image { log.Info(ImageUnchanged) return false, nil } log.Info("Found updated image", - zap.String("image", latestImageDetails.Image), - zap.Reflect("versions", latestImageDetails.Versions), + zap.String("image", masterImageDetails.Image), + zap.Reflect("versions", masterImageDetails.Versions), ) log.Info("Updating StatefulSet to trigger a new test") - if err := setImageDetails(ctx, log, clientset, namespace, podName, latestImageDetails); err != nil { + if err := setImageDetails(ctx, log, clientset, namespace, podName, masterImageDetails); err != nil { log.Error("failed to set container image", zap.Error(err)) return false, nil }