Repository: rancher/fleet
Pull request #2207 (2024-03-04 15:15:42)

Remove drone and dapper scripts
Refers to https://github.com/rancher/fleet/issues/2121


Patch:
diff --git a/.drone.yml b/.drone.yml
deleted file mode 100644
index e53cce39..00000000
--- a/.drone.yml
+++ /dev/null
@@ -1,418 +0,0 @@
----
-
-kind: pipeline
-type: docker
-name: linux-amd64
-platform:
-  os: linux
-  arch: amd64
-steps:
-- name: build
-  image: rancher/dapper:v0.5.8
-  environment:
-    CROSS: "windows"
-  commands:
-  - dapper ci
-  volumes:
-  - name: docker
-    path: /var/run/docker.sock
-- name: fossa
-  image: registry.suse.com/suse/sle15:15.3
-  failure: ignore
-  environment:
-    FOSSA_API_KEY:
-      from_secret: FOSSA_API_KEY
-  commands:
-    - zypper -n install curl unzip tar
-    - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash"
-    - fossa analyze
-    - fossa test
-  when:
-    instance:
-      - drone-publish.rancher.io
-    ref:
-      include:
-        - "refs/heads/master"
-    event:
-      - push
-      - tag
-- name: github_binary_release
-  image: plugins/github-release
-  settings:
-    api_key:
-      from_secret: github_token
-    prerelease: true
-    checksum:
-    - sha256
-    checksum_file: CHECKSUMsum-amd64.txt
-    checksum_flatten: true
-    files:
-    - "dist/artifacts/*"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-      include:
-      - refs/head/master
-      - refs/tags/*
-      exclude:
-      - refs/tags/*-debug-*
-    event:
-    - tag
-- name: upload-tag
-  pull: default
-  image: plugins/gcs
-  settings:
-    acl:
-      - allUsers:READER
-    cache_control: "no-cache,must-revalidate"
-    source: ./dist/artifacts
-    target: releases.rancher.com/fleet/${DRONE_TAG}
-    token:
-      from_secret: google_auth_key
-  when:
-    event:
-      - tag
-- name: upload-latest
-  pull: default
-  image: plugins/gcs
-  settings:
-    acl:
-      - allUsers:READER
-    cache_control: "no-cache,must-revalidate"
-    source: ./dist/artifacts
-    target: releases.rancher.com/fleet/latest
-    token:
-      from_secret: google_auth_key
-  when:
-    event:
-      - tag
-- name: docker-publish-agent
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile.agent
-    password:
-      from_secret: docker_password
-    repo: "rancher/fleet-agent"
-    tag: "${DRONE_TAG}-linux-amd64"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "ARCH=amd64"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-- name: docker-publish-gitjob
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile.gitjob
-    password:
-      from_secret: docker_password
-    repo: "rancher/gitjob"
-    tag: "${DRONE_TAG}-linux-amd64"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "ARCH=amd64"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-- name: docker-publish
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/fleet"
-    tag: "${DRONE_TAG}-linux-amd64"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "ARCH=amd64"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-volumes:
-- name: docker
-  host:
-    path: /var/run/docker.sock
-
----
-
-kind: pipeline
-type: docker
-name: linux-arm64
-platform:
-  os: linux
-  arch: arm64
-steps:
-- name: build
-  image: rancher/dapper:v0.5.8
-  commands:
-  - dapper build
-  volumes:
-  - name: docker
-    path: /var/run/docker.sock
-- name: github_binary_release
-  image: plugins/github-release
-  settings:
-    api_key:
-      from_secret: github_token
-    prerelease: true
-    checksum:
-    - sha256
-    checksum_file: CHECKSUMsum-arm64.txt
-    checksum_flatten: true
-    files:
-    - "dist/artifacts/*"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-      include:
-      - refs/head/master
-      - refs/tags/*
-      exclude:
-      - refs/tags/*-debug-*
-    event:
-    - tag
-- name: docker-publish-agent
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile.agent
-    password:
-      from_secret: docker_password
-    repo: "rancher/fleet-agent"
-    tag: "${DRONE_TAG}-linux-arm64"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "ARCH=arm64"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-- name: docker-publish-gitjob
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile.gitjob
-    password:
-      from_secret: docker_password
-    repo: "rancher/gitjob"
-    tag: "${DRONE_TAG}-linux-arm64"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "ARCH=arm64"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-- name: docker-publish
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/fleet"
-    tag: "${DRONE_TAG}-linux-arm64"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "ARCH=arm64"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-volumes:
-- name: docker
-  host:
-    path: /var/run/docker.sock
-
----
-
-kind: pipeline
-type: docker
-name: windows-1809
-platform:
-  os: windows
-  arch: amd64
-  version: 1809
-# Currently have to define "depth" as otherwise clone fails at
-# https://github.com/drone/drone-git/blob/39d233b3d9eccc68e66508a06a725a2567f33143/windows/clone-tag.ps1#L12
-clone:
-  depth: 20
-steps:
-- name: docker-publish-agent
-  image: plugins/docker:windows-1809-amd64
-  settings:
-    purge: false
-    dockerfile: package/Dockerfile-windows.agent
-    password:
-      from_secret: docker_password
-    repo: "rancher/fleet-agent"
-    tag: "${DRONE_TAG}-windows-1809"
-    username:
-      from_secret: docker_username
-    build_args:
-      - "SERVERCORE_VERSION=1809"
-      - "RELEASES=releases.rancher.com"
-      - "VERSION=${DRONE_TAG}"
-    context: package/
-    custom_dns: 1.1.1.1
-  volumes:
-    - name: docker
-      path: \\\\.\\pipe\\docker_engine
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-volumes:
-  - name: docker
-    host:
-      path: \\\\.\\pipe\\docker_engine
-depends_on:
-- linux-amd64
-
----
-
-kind: pipeline
-type: docker
-name: windows-2022
-platform:
-  os: windows
-  arch: amd64
-  version: 2022
-# Currently have to define "depth" as otherwise clone fails at
-# https://github.com/drone/drone-git/blob/39d233b3d9eccc68e66508a06a725a2567f33143/windows/clone-tag.ps1#L12
-clone:
-  depth: 20
-steps:
-  - name: docker-publish-agent
-    image: rancher/drone-images:docker-amd64-ltsc2022
-    settings:
-      dockerfile: package/Dockerfile-windows.agent
-      password:
-        from_secret: docker_password
-      repo: "rancher/fleet-agent"
-      tag: "${DRONE_TAG}-windows-ltsc2022"
-      username:
-        from_secret: docker_username
-      build_args:
-        - "SERVERCORE_VERSION=ltsc2022"
-        - "RELEASES=releases.rancher.com"
-        - "VERSION=${DRONE_TAG}"
-        - ARCH=amd64
-      context: package/
-      custom_dns: 1.1.1.1
-    volumes:
-      - name: docker
-        path: \\\\.\\pipe\\docker_engine
-    when:
-      instance:
-        - drone-publish.rancher.io
-      ref:
-        - refs/head/master
-        - refs/tags/*
-      event:
-        - tag
-volumes:
-  - name: docker
-    host:
-      path: \\\\.\\pipe\\docker_engine
-depends_on:
-  - linux-amd64
-
----
-
-kind: pipeline
-type: docker
-name: manifest
-platform:
-  os: linux
-  arch: amd64
-steps:
-- name: manifest
-  image: plugins/manifest:1.0.2
-  settings:
-    username:
-      from_secret: docker_username
-    password:
-      from_secret: docker_password
-    spec: manifest.tmpl
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-- name: manifest-gitjob
-  image: plugins/manifest:1.0.2
-  settings:
-    username:
-      from_secret: docker_username
-    password:
-      from_secret: docker_password
-    spec: manifest-gitjob.tmpl
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-- name: manifest-agent
-  image: plugins/manifest:1.0.2
-  settings:
-    username:
-      from_secret: docker_username
-    password:
-      from_secret: docker_password
-    spec: manifest-agent.tmpl
-  when:
-    instance:
-    - drone-publish.rancher.io
-    ref:
-    - refs/head/master
-    - refs/tags/*
-    event:
-    - tag
-depends_on:
-- linux-amd64
-- linux-arm64
-- windows-1809
-- windows-2022
diff --git a/.github/scripts/label-downstream-cluster.sh b/.github/scripts/label-downstream-cluster.sh
index e233ebb2..20549a78 100755
--- a/.github/scripts/label-downstream-cluster.sh
+++ b/.github/scripts/label-downstream-cluster.sh
@@ -4,6 +4,6 @@ set -euxo pipefail
 
 ns=${FLEET_E2E_NS_DOWNSTREAM-fleet-default}
 
-{ grep -q -m 1 -e "k3d-downstream"; kill $!; } < <(kubectl get clusters.fleet.cattle.io -n "$ns" -w)
+{ grep -q -m 1 -e "1/1"; kill $!; } < <(kubectl get clusters.fleet.cattle.io -n "$ns" -w)
 name=$(kubectl get clusters.fleet.cattle.io -o=jsonpath='{.items[0].metadata.name}' -n "$ns")
 kubectl patch clusters.fleet.cattle.io -n "$ns" "$name" --type=json -p '[{"op": "add", "path": "/metadata/labels/env", "value": "test" }]'
diff --git a/.github/workflows/rancher-integration.yml b/.github/workflows/rancher-integration.yml
index e28973ac..7f7dea94 100644
--- a/.github/workflows/rancher-integration.yml
+++ b/.github/workflows/rancher-integration.yml
@@ -18,7 +18,6 @@ on:
   push:
     tags: [ 'v*' ]
     paths-ignore:
-      - 'scripts/**'
       - '*.md'
 
 env:
diff --git a/.github/workflows/release-against-rancher.yml b/.github/workflows/release-against-rancher.yml
index 4ad0e61c..22c9a908 100644
--- a/.github/workflows/release-against-rancher.yml
+++ b/.github/workflows/release-against-rancher.yml
@@ -9,7 +9,7 @@ on:
       rancher_ref:
         description: "Submit PR against the following rancher/rancher branch (e.g. release/v2.7)"
         required: true
-        default: "release/v2.8"
+        default: "release/v2.9"
       new_fleet:
         description: "New Fleet version (e.g. 0.8.0-rc.3)"
         required: true
@@ -22,11 +22,15 @@ on:
         description: "Should the Fleet api be bumped in the Rancher repo? (In most cases true unless there are incompatibilities.)"
         required: true
         default: "true"
+      go_version:
+        description: "Go version used for bumping the api. This should be the same version as in the go.mod file of the project."
+        required: true
+        default: '1.21.*'
 
 env:
   GOARCH: amd64
   CGO_ENABLED: 0
-  SETUP_GO_VERSION: '1.22.*'
+  SETUP_GO_VERSION: ${{github.event.inputs.go_version}}
 
 jobs:
   create-rancher-pr:
diff --git a/.github/workflows/release-fleet.yml b/.github/workflows/release-fleet.yml
new file mode 100644
index 00000000..77dde145
--- /dev/null
+++ b/.github/workflows/release-fleet.yml
@@ -0,0 +1,110 @@
+# Fleet release workflow
+name: Fleet release
+
+on:
+  push:
+    tags:
+      - v**
+
+permissions:
+  contents: write
+  packages: write
+
+env:
+  GOARCH: amd64
+  CGO_ENABLED: 0
+  SETUP_K3D_VERSION: 'v5.5.1'
+
+jobs:
+  build-fleet:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out Fleet
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Go
+        uses: actions/setup-go@v5
+        with:
+          go-version-file: 'go.mod'
+          check-latest: true
+
+      - name: Run golangci-lint
+        uses: golangci/golangci-lint-action@v4.0.0
+        with:
+          # Required: the version of golangci-lint is required and must be specified without patch version: we always
+          # use the latest patch version.
+          version: v1.55
+          args: --timeout=10m --config=.golangci.json
+
+      - name: Run FOSSA scan
+        uses: fossas/fossa-action@v1.3.1
+        with:
+          api-key: ${{ secrets.FOSSA_API_KEY }}
+
+      - name: Run FOSSA tests
+        uses: fossas/fossa-action@v1.3.1
+        with:
+          api-key: ${{ secrets.FOSSA_API_KEY }}
+          run-tests: true
+
+      - name: Check for code changes
+        run: |
+          ./.github/scripts/check-for-auto-generated-changes.sh
+          go mod verify
+
+      - name: Run unit tests
+        run: go test -cover -tags=test $(go list ./... | grep -v -e /e2e -e /integrationtests)
+
+      - name: Run integration tests
+        env:
+          SETUP_ENVTEST_VER: v0.0.0-20240115093953-9e6e3b144a69
+          ENVTEST_K8S_VERSION: 1.28
+        run: ./.github/scripts/run-integration-tests.sh
+
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+
+      - name: Log into Container registry
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Run GoReleaser
+        uses: goreleaser/goreleaser-action@v5
+        with:
+          distribution: goreleaser
+          version: v1.24.0
+          args: release --clean --verbose
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Upload charts to release
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          repo: "ghcr.io/rancher/fleet"
+          tag: "${GITHUB_REF_NAME}"
+        run: |
+          sed -i \
+              -e "s@repository:.*@repository: $repo@" \
+              -e "s/tag:.*/tag: ${VERSION}/" \
+              charts/fleet/values.yaml
+
+          sed -i \
+              -e "s@repository:.*@repository: $repo@" \
+              -e "s/tag: dev/tag: ${VERSION}/" \
+              charts/fleet-agent/values.yaml
+
+          helm package --version="$VERSION" --app-version="$VERSION" -d ./dist ./charts/fleet
+          helm package --version="$VERSION" --app-version="$VERSION" -d ./dist ./charts/fleet-crd
+          helm package --version="$VERSION" --app-version="$VERSION" -d ./dist ./charts/fleet-agent
+
+          for f in $(find dist/artifacts/ -name '*.tgz'); do
+            gh release upload $tag $f
+          done
diff --git a/.gitignore b/.gitignore
index 39a25da6..33d19e41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
 /build
-/.dapper
 /.cache
 /bin
 /dist
diff --git a/.goreleaser.yml b/.goreleaser.yml
new file mode 100644
index 00000000..a3e1e388
--- /dev/null
+++ b/.goreleaser.yml
@@ -0,0 +1,268 @@
+---
+project_name: fleet
+
+before:
+  hooks:
+    - go mod download
+
+archives:
+  - id: fleet-controller
+    format: binary
+    name_template: "{{ .Binary }}"
+    builds:
+      - fleet-controller
+
+  - id: fleet-agent
+    format: binary
+    name_template: "{{ .Binary }}"
+    builds:
+      - fleet-agent
+
+  - id: fleet-gitcloner
+    format: binary
+    name_template: "{{ .Binary }}"
+    builds:
+      - fleet-gitcloner
+
+  - id: fleet-gitjob
+    format: binary
+    name_template: "{{ .Binary }}"
+    builds:
+      - fleet-gitjob
+
+  - id: fleet-cli
+    format: binary
+    name_template: "{{ .Binary }}"
+    builds:
+      - fleet-cli
+
+builds:
+  -
+    id: fleet-controller
+    main: ./cmd/fleetcontroller
+    binary: fleetcontroller-{{ .Os }}-{{ .Arch }}{{ if .Arm }}64{{ end }}
+    no_unique_dist_dir: true
+    # gcflags:
+    #   - all="-N -l"
+    ldflags:
+      - -w -s
+      - -X github.com/rancher/fleet/pkg/version.GitCommit={{ .Commit }}
+      - -X github.com/rancher/fleet/pkg/version.Version={{ .Tag }}
+    targets:
+    - linux_amd64_v1
+    - linux_arm64
+  -
+    id: fleet-agent
+    main: ./cmd/fleetagent
+    binary: fleetagent-{{ .Os }}-{{ .Arch }}{{ if .Arm }}64{{ end }}
+    no_unique_dist_dir: true
+    ldflags:
+      - -w -s
+      - -X github.com/rancher/fleet/pkg/version.GitCommit={{ .Commit }}
+      - -X github.com/rancher/fleet/pkg/version.Version={{ .Tag }}
+    targets:
+    - linux_amd64_v1
+    - linux_arm64
+    - windows_amd64
+  -
+    id: fleet-gitcloner
+    main: ./cmd/gitcloner
+    binary: gitcloner-{{ .Os }}-{{ .Arch }}{{ if .Arm }}64{{ end }}
+    no_unique_dist_dir: true
+    ldflags:
+      - -w -s
+      - -X github.com/rancher/fleet/pkg/version.GitCommit={{ .Commit }}
+      - -X github.com/rancher/fleet/pkg/version.Version={{ .Tag }}
+    targets:
+    - linux_amd64_v1
+    - linux_arm64
+  -
+    id: fleet-gitjob
+    main: ./cmd/gitjob
+    binary: gitjob-{{ .Os }}-{{ .Arch }}{{ if .Arm }}64{{ end }}
+    no_unique_dist_dir: true
+    ldflags:
+      - -w -s
+      - -X github.com/rancher/fleet/pkg/version.GitCommit={{ .Commit }}
+      - -X github.com/rancher/fleet/pkg/version.Version={{ .Tag }}
+    targets:
+    - linux_amd64_v1
+    - linux_arm64
+  -
+    id: fleet-cli
+    main: ./cmd/fleetcli
+    binary: fleet-{{ .Os }}-{{ .Arch }}{{ if .Arm }}64{{ end }}
+    no_unique_dist_dir: true
+    ldflags:
+      - -w -s
+      - -X github.com/rancher/fleet/pkg/version.GitCommit={{ .Commit }}
+      - -X github.com/rancher/fleet/pkg/version.Version={{ .Tag }}
+    targets:
+    - linux_amd64_v1
+    - linux_arm64
+    - windows_amd64
+
+changelog:
+  ## Delegate Changelog to release-drafter
+  disable: false
+  use: github
+
+env:
+  - CGO_ENABLED=0
+
+snapshot:
+  name_template: "{{ .Tag }}-next"
+
+dockers:
+  # fleet-controller images
+  -
+    use: buildx
+
+    # GOOS of the built binaries/packages that should be used.
+    goos: linux
+
+    # GOARCH of the built binaries/packages that should be used.
+    goarch: amd64
+
+    # IDs to filter the binaries/packages.
+    ids:
+    - fleet-controller
+
+    # Templates of the Docker image names.
+    image_templates:
+    - "ghcr.io/rancher/fleet:{{ .Tag }}-linux-amd64"
+
+    # Path to the Dockerfile (from the project root).
+    dockerfile: package/Dockerfile
+
+    # Template of the docker build flags.
+    build_flag_templates:
+    - "--pull"
+    - "--label=org.opencontainers.image.created={{.Date}}"
+    - "--label=org.opencontainers.image.title={{.ProjectName}}"
+    - "--label=org.opencontainers.image.revision={{.FullCommit}}"
+    - "--label=org.opencontainers.image.version={{.Version}}"
+    - "--label=org.opencontainers.image.source=https://github.com/rancher/fleet"
+    - "--build-arg=ARCH=amd64"
+    - "--build-arg=BUILD_ENV=goreleaser"
+    - "--platform=linux/amd64"
+  -
+    use: buildx
+    goos: linux
+    goarch: arm64
+    ids:
+    - fleet-controller
+    image_templates:
+    - "ghcr.io/rancher/fleet:{{ .Tag }}-linux-arm64"
+    dockerfile: package/Dockerfile
+    build_flag_templates:
+    - "--pull"
+    - "--label=org.opencontainers.image.created={{.Date}}"
+    - "--label=org.opencontainers.image.title={{.ProjectName}}"
+    - "--label=org.opencontainers.image.revision={{.FullCommit}}"
+    - "--label=org.opencontainers.image.version={{.Version}}"
+    - "--label=org.opencontainers.image.source=https://github.com/rancher/fleet"
+    - "--build-arg=ARCH=arm64"
+    - "--build-arg=BUILD_ENV=goreleaser"
+    - "--platform=linux/arm64/v8"
+  # fleet-agent images
+  -
+    use: buildx
+    goos: linux
+    goarch: amd64
+    ids:
+    - fleet-agent
+    - fleet-cli
+    image_templates:
+    - "ghcr.io/rancher/fleet-agent:{{ .Tag }}-linux-amd64"
+    dockerfile: package/Dockerfile.agent
+    build_flag_templates:
+    - "--pull"
+    - "--label=org.opencontainers.image.created={{.Date}}"
+    - "--label=org.opencontainers.image.title={{.ProjectName}}"
+    - "--label=org.opencontainers.image.revision={{.FullCommit}}"
+    - "--label=org.opencontainers.image.version={{.Version}}"
+    - "--label=org.opencontainers.image.source=https://github.com/rancher/fleet"
+    - "--build-arg=ARCH=amd64"
+    - "--build-arg=BUILD_ENV=goreleaser"
+    - "--platform=linux/amd64"
+    extra_files: [ "package/log.sh" ]
+  -
+    use: buildx
+    goos: linux
+    goarch: arm64
+    ids:
+    - fleet-agent
+    - fleet-cli
+    image_templates:
+    - "ghcr.io/rancher/fleet-agent:{{ .Tag }}-linux-arm64"
+    dockerfile: package/Dockerfile.agent
+    build_flag_templates:
+    - "--pull"
+    - "--label=org.opencontainers.image.created={{.Date}}"
+    - "--label=org.opencontainers.image.title={{.ProjectName}}"
+    - "--label=org.opencontainers.image.revision={{.FullCommit}}"
+    - "--label=org.opencontainers.image.version={{.Version}}"
+    - "--label=org.opencontainers.image.source=https://github.com/rancher/fleet"
+    - "--build-arg=ARCH=arm64"
+    - "--build-arg=BUILD_ENV=goreleaser"
+    - "--platform=linux/arm64/v8"
+    extra_files: [ "package/log.sh" ]
+  # fleet-gitjob images
+  -
+    use: buildx
+    goos: linux
+    goarch: amd64
+    ids:
+    - fleet-gitcloner
+    - fleet-gitjob
+    image_templates:
+    - "ghcr.io/rancher/fleet-gitjob:{{ .Tag }}-linux-amd64"
+    dockerfile: package/Dockerfile.gitjob
+    build_flag_templates:
+    - "--pull"
+    - "--label=org.opencontainers.image.created={{.Date}}"
+    - "--label=org.opencontainers.image.title={{.ProjectName}}"
+    - "--label=org.opencontainers.image.revision={{.FullCommit}}"
+    - "--label=org.opencontainers.image.version={{.Version}}"
+    - "--label=org.opencontainers.image.source=https://github.com/rancher/fleet"
+    - "--build-arg=ARCH=amd64"
+    - "--build-arg=BUILD_ENV=goreleaser"
+    - "--platform=linux/amd64"
+  -
+    use: buildx
+    goos: linux
+    goarch: arm64
+    ids:
+    - fleet-gitcloner
+    - fleet-gitjob
+    image_templates:
+    - "ghcr.io/rancher/fleet-gitjob:{{ .Tag }}-linux-arm64"
+    dockerfile: package/Dockerfile.gitjob
+    build_flag_templates:
+    - "--pull"
+    - "--label=org.opencontainers.image.created={{.Date}}"
+    - "--label=org.opencontainers.image.title={{.ProjectName}}"
+    - "--label=org.opencontainers.image.revision={{.FullCommit}}"
+    - "--label=org.opencontainers.image.version={{.Version}}"
+    - "--label=org.opencontainers.image.source=https://github.com/rancher/fleet"
+    - "--build-arg=ARCH=arm64"
+    - "--build-arg=BUILD_ENV=goreleaser"
+    - "--platform=linux/arm64/v8"
+
+docker_manifests:
+  # https://goreleaser.com/customization/docker_manifest/
+  - name_template: "ghcr.io/rancher/fleet:{{ .Tag }}"
+    image_templates:
+    - "ghcr.io/rancher/fleet:{{ .Tag }}-linux-amd64"
+    - "ghcr.io/rancher/fleet:{{ .Tag }}-linux-arm64"
+
+  - name_template: "ghcr.io/rancher/fleet-agent:{{ .Tag }}"
+    image_templates:
+    - "ghcr.io/rancher/fleet-agent:{{ .Tag }}-linux-amd64"
+    - "ghcr.io/rancher/fleet-agent:{{ .Tag }}-linux-arm64"
+
+  - name_template: "ghcr.io/rancher/fleet-gitjob:{{ .Tag }}"
+    image_templates:
+    - "ghcr.io/rancher/fleet-gitjob:{{ .Tag }}-linux-amd64"
+    - "ghcr.io/rancher/fleet-gitjob:{{ .Tag }}-linux-arm64"
diff --git a/DEVELOPING.md b/DEVELOPING.md
index d1cffc6d..f4a152fb 100644
--- a/DEVELOPING.md
+++ b/DEVELOPING.md
@@ -63,8 +63,8 @@ Now, let's build and push your `fleet-agent` (`linux-amd64` image by default), i
 
 ```sh
 (
-    go fmt ./...
-    REPO=$AGENT_REPO make agent-dev
+    dev/build-fleet
+    docker tag rancher/fleet-agent:dev $AGENT_REPO/fleet-agent:dev
     docker push $AGENT_REPO/fleet-agent:dev
 )
 ```
diff --git a/Dockerfile.dapper b/Dockerfile.dapper
deleted file mode 100644
index 96e9f912..00000000
--- a/Dockerfile.dapper
+++ /dev/null
@@ -1,20 +0,0 @@
-FROM registry.suse.com/bci/golang:1.22
-
-ARG DAPPER_HOST_ARCH
-ENV ARCH $DAPPER_HOST_ARCH
-
-RUN zypper -n install git docker vim wget
-RUN curl -sL https://get.helm.sh/helm-v3.9.3-linux-${ARCH}.tar.gz | tar xvzf - -C /usr/local/bin --strip-components=1
-
-# Temporarily needed for running cmd/codegen/hack/patch_crd_descriptions.sh
-RUN zypper -n install jq python3-pip && python3 -m pip install yq
-
-ENV DAPPER_ENV REPO TAG DRONE_TAG CROSS DEBUG
-ENV DAPPER_SOURCE /go/src/github.com/rancher/fleet/
-ENV DAPPER_OUTPUT ./bin ./dist
-ENV DAPPER_DOCKER_SOCKET true
-ENV DAPPER_RUN_ARGS "-v fleet-pkg:/go/pkg -v fleet-cache:/root/.cache"
-WORKDIR ${DAPPER_SOURCE}
-
-ENTRYPOINT ["./scripts/entry"]
-CMD ["ci"]
diff --git a/Makefile b/Makefile
deleted file mode 100644
index a0649db7..00000000
--- a/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-TARGETS := $(shell ls scripts)
-
-.dapper:
-	@echo Downloading dapper
-	@curl -sL https://releases.rancher.com/dapper/latest/dapper-`uname -s`-`uname -m` > .dapper.tmp
-	@@chmod +x .dapper.tmp
-	@./.dapper.tmp -v
-	@mv .dapper.tmp .dapper
-
-$(TARGETS): .dapper
-	./.dapper $@
-
-.DEFAULT_GOAL := default
-
-.PHONY: $(TARGETS)
diff --git a/charts/fleet-crd/templates/crds.yaml b/charts/fleet-crd/templates/crds.yaml
index 6cff07c3..11448dba 100644
--- a/charts/fleet-crd/templates/crds.yaml
+++ b/charts/fleet-crd/templates/crds.yaml
@@ -3626,12 +3626,6 @@ spec:
         - jsonPath: .status.display.readyBundles
           name: Bundles-Ready
           type: string
-        - jsonPath: .status.display.readyNodes
-          name: Nodes-Ready
-          type: string
-        - jsonPath: .status.display.sampleNode
-          name: Sample-Node
-          type: string
         - jsonPath: .status.agent.lastSeen
           name: Last-Seen
           type: string
@@ -5109,29 +5103,6 @@ spec:
                         e.g. "cattle-fleet-system".
                       nullable: true
                       type: string
-                    nonReadyNodeNames:
-                      description: 'NonReadyNode contains the names of non-ready nodes.
-                        The list is
-
-                        limited to at most 3 names.'
-                      items:
-                        type: string
-                      type: array
-                    nonReadyNodes:
-                      description: NonReadyNodes is the number of nodes that are not
-                        ready.
-                      type: integer
-                    readyNodeNames:
-                      description: 'ReadyNodes contains the names of ready nodes.
-                        The list is limited to
-
-                        at most 3 names.'
-                      items:
-                        type: string
-                      type: array
-                    readyNodes:
-                      description: ReadyNodes is the number of nodes that are ready.
-                      type: integer
                   type: object
                 agentAffinityHash:
                   description: 'AgentAffinityHash is a hash of the agent''s affinity
@@ -5260,19 +5231,6 @@ spec:
 
                         to be ready.'
                       type: string
-                    readyNodes:
-                      description: 'ReadyNodes is a string in the form "%d/%d", that
-                        describes the
-
-                        number of nodes that are ready vs. the number of expected
-                        nodes.'
-                      type: string
-                    sampleNode:
-                      description: 'SampleNode is the name of one of the nodes that
-                        are ready. If no
-
-                        node is ready, it''s the name of a node that is not ready.'
-                      type: string
                     state:
                       description: State of the cluster, either one of the bundle
                         states, or "WaitCheckIn".
diff --git a/scripts/boilerplate.go.txt b/cmd/codegen/boilerplate.go.txt
similarity index 100%
rename from scripts/boilerplate.go.txt
rename to cmd/codegen/boilerplate.go.txt
diff --git a/cmd/codegen/hack/generate_and_sort_crds.sh b/cmd/codegen/hack/generate_and_sort_crds.sh
index 48778d24..0847041e 100644
--- a/cmd/codegen/hack/generate_and_sort_crds.sh
+++ b/cmd/codegen/hack/generate_and_sort_crds.sh
@@ -40,7 +40,7 @@ if ! $CONTROLLERGEN --version | grep -q "${CONTROLLERGEN_VERSION}" ; then
 fi
 
 # Run controller-gen
-${CONTROLLERGEN} object:headerFile=scripts/boilerplate.go.txt,year="$(date +%Y)" paths="./pkg/apis/..."
+${CONTROLLERGEN} object:headerFile=cmd/codegen/boilerplate.go.txt,year="$(date +%Y)" paths="./pkg/apis/..."
 ${CONTROLLERGEN} crd webhook paths="./pkg/apis/..." output:stdout > $CRDS_YAML
 # Sort
-run_yq --slurp --sort-keys --explicit-start --yaml-output -i 'sort_by(.metadata.name)[]' $CRDS_YAML
\ No newline at end of file
+run_yq --slurp --sort-keys --explicit-start --yaml-output -i 'sort_by(.metadata.name)[]' $CRDS_YAML
diff --git a/cmd/codegen/main.go b/cmd/codegen/main.go
index 04a85cbc..c3def293 100644
--- a/cmd/codegen/main.go
+++ b/cmd/codegen/main.go
@@ -17,7 +17,7 @@ func main() {
 	os.Unsetenv("GOPATH")
 	controllergen.Run(args.Options{
 		OutputPackage: "github.com/rancher/fleet/pkg/generated",
-		Boilerplate:   "scripts/boilerplate.go.txt",
+		Boilerplate:   "cmd/codegen/boilerplate.go.txt",
 		Groups: map[string]args.Group{
 			"fleet.cattle.io": {
 				Types: []interface{}{
diff --git a/dev/README.md b/dev/README.md
index 2a67c6ec..c9979034 100644
--- a/dev/README.md
+++ b/dev/README.md
@@ -147,7 +147,7 @@ remedy this. By default, the setup script will use `/usr/bin/helm`.
 
 ## Different Script Folders
 
-Our CIs, dapper/drone and github actions, use a different set of scripts. CI
+Our CIs and github actions use a different set of scripts. CI
 does not reuse dev scripts, however dev scripts may use CI scripts. We want to
 keep CI scripts short, targeted and readable. Dev scripts may change in an
 incompatible way at any day.
diff --git a/go.mod b/go.mod
index db4e3a5c..1a32d16f 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/rancher/fleet
 go 1.22
 
 replace (
+	github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
 	github.com/rancher/fleet/pkg/apis => ./pkg/apis
 	helm.sh/helm/v3 => github.com/rancher/helm/v3 v3.14.0-fleet2
 )
@@ -38,24 +39,24 @@ require (
 	github.com/stretchr/testify v1.8.4
 	github.com/testcontainers/testcontainers-go v0.26.0
 	go.uber.org/mock v0.4.0
-	golang.org/x/crypto v0.18.0
-	golang.org/x/exp v0.0.0-20231006140011-7918f672742d
+	golang.org/x/crypto v0.19.0
+	golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
 	golang.org/x/sync v0.6.0
 	gopkg.in/go-playground/webhooks.v5 v5.17.0
 	gopkg.in/yaml.v2 v2.4.0
 	gotest.tools v2.2.0+incompatible
 	helm.sh/helm/v3 v3.14.0
 	k8s.io/api v0.29.2
-	k8s.io/apiextensions-apiserver v0.29.0
+	k8s.io/apiextensions-apiserver v0.29.2
 	k8s.io/apimachinery v0.29.2
 	k8s.io/cli-runtime v0.29.2
 	k8s.io/client-go v0.29.2
-	k8s.io/klog/v2 v2.110.1
-	k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
+	k8s.io/klog/v2 v2.120.1
+	k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
 	k8s.io/kubectl v0.29.2
 	k8s.io/kubernetes v1.29.2
 	sigs.k8s.io/cli-utils v0.34.0
-	sigs.k8s.io/controller-runtime v0.17.0
+	sigs.k8s.io/controller-runtime v0.17.2
 	sigs.k8s.io/controller-tools v0.14.0
 	sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3
 	sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3
@@ -101,9 +102,9 @@ require (
 	github.com/docker/go-connections v0.4.0 // indirect
 	github.com/docker/go-metrics v0.0.1 // indirect
 	github.com/docker/go-units v0.5.0 // indirect
-	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+	github.com/emicklei/go-restful/v3 v3.11.3 // indirect
 	github.com/emirpasic/gods v1.18.1 // indirect
-	github.com/evanphx/json-patch/v5 v5.8.0 // indirect
+	github.com/evanphx/json-patch/v5 v5.9.0 // indirect
 	github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
 	github.com/fatih/color v1.16.0 // indirect
 	github.com/felixge/httpsnoop v1.0.3 // indirect
@@ -115,9 +116,9 @@ require (
 	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/go-logr/zapr v1.3.0 // indirect
 	github.com/go-ole/go-ole v1.2.6 // indirect
-	github.com/go-openapi/jsonpointer v0.20.0 // indirect
-	github.com/go-openapi/jsonreference v0.20.2 // indirect
-	github.com/go-openapi/swag v0.22.4 // indirect
+	github.com/go-openapi/jsonpointer v0.20.2 // indirect
+	github.com/go-openapi/jsonreference v0.20.4 // indirect
+	github.com/go-openapi/swag v0.22.9 // indirect
 	github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
 	github.com/gobuffalo/flect v1.0.2 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
@@ -127,10 +128,10 @@ require (
 	github.com/google/btree v1.1.2 // indirect
 	github.com/google/gnostic-models v0.6.8 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
-	github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
+	github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
 	github.com/google/s2a-go v0.1.7 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
-	github.com/google/uuid v1.4.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
 	github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
 	github.com/googleapis/gax-go/v2 v2.11.0 // indirect
 	github.com/gorilla/websocket v1.5.0 // indirect
@@ -142,7 +143,7 @@ require (
 	github.com/hashicorp/go-safetemp v1.0.0 // indirect
 	github.com/hashicorp/go-version v1.6.0 // indirect
 	github.com/huandu/xstrings v1.4.0 // indirect
-	github.com/imdario/mergo v0.3.16 // indirect
+	github.com/imdario/mergo v1.0.0 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
@@ -161,7 +162,6 @@ require (
 	github.com/mattn/go-colorable v0.1.13 // indirect
 	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/mattn/go-runewidth v0.0.13 // indirect
-	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
 	github.com/mitchellh/copystructure v1.2.0 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/go-testing-interface v1.14.1 // indirect
@@ -185,9 +185,9 @@ require (
 	github.com/pjbgf/sha1cd v0.3.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
-	github.com/prometheus/client_golang v1.18.0 // indirect
-	github.com/prometheus/client_model v0.5.0 // indirect
-	github.com/prometheus/common v0.45.0 // indirect
+	github.com/prometheus/client_golang v1.19.0 // indirect
+	github.com/prometheus/client_model v0.6.0 // indirect
+	github.com/prometheus/common v0.48.0 // indirect
 	github.com/prometheus/procfs v0.12.0 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
 	github.com/rogpeppe/go-internal v1.12.0 // indirect
@@ -218,14 +218,14 @@ require (
 	go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.26.0 // indirect
-	golang.org/x/mod v0.14.0 // indirect
-	golang.org/x/net v0.20.0 // indirect
-	golang.org/x/oauth2 v0.13.0 // indirect
-	golang.org/x/sys v0.16.0 // indirect
-	golang.org/x/term v0.16.0 // indirect
+	golang.org/x/mod v0.15.0 // indirect
+	golang.org/x/net v0.21.0 // indirect
+	golang.org/x/oauth2 v0.17.0 // indirect
+	golang.org/x/sys v0.17.0 // indirect
+	golang.org/x/term v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
-	golang.org/x/time v0.3.0 // indirect
-	golang.org/x/tools v0.16.1 // indirect
+	golang.org/x/time v0.5.0 // indirect
+	golang.org/x/tools v0.18.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
 	google.golang.org/api v0.126.0 // indirect
@@ -234,15 +234,15 @@ require (
 	google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
 	google.golang.org/grpc v1.58.3 // indirect
-	google.golang.org/protobuf v1.31.0 // indirect
+	google.golang.org/protobuf v1.32.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/apiserver v0.29.0 // indirect
-	k8s.io/code-generator v0.29.0 // indirect
+	k8s.io/apiserver v0.29.2 // indirect
+	k8s.io/code-generator v0.29.2 // indirect
 	k8s.io/component-base v0.29.2 // indirect
 	k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
-	k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
+	k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect
 	oras.land/oras-go v1.2.4 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
diff --git a/go.sum b/go.sum
index 894e73d4..4f896b97 100644
--- a/go.sum
+++ b/go.sum
@@ -290,7 +290,6 @@ github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHf
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
 github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
 github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
@@ -322,8 +321,8 @@ github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arX
 github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
 github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
 github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
-github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
-github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emicklei/go-restful/v3 v3.11.3 h1:yagOQz/38xJmcNeZJtrUcKjkHRltIaIFXKWeG1SkWGE=
+github.com/emicklei/go-restful/v3 v3.11.3/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -338,8 +337,8 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
 github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro=
-github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
+github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
+github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
 github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
 github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -378,7 +377,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
 github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -387,14 +385,12 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
 github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
 github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
 github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
-github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
-github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
-github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
-github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
-github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
-github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
+github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
+github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
+github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
 github.com/go-playground/webhooks/v6 v6.3.0 h1:zBLUxK1Scxwi97TmZt5j/B/rLlard2zY7P77FHg58FE=
 github.com/go-playground/webhooks/v6 v6.3.0/go.mod h1:GCocmfMtpJdkEOM1uG9p2nXzg1kY5X/LtvQgtPHUaaA=
 github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
@@ -506,8 +502,8 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
 github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
-github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
+github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
 github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
@@ -516,8 +512,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
-github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
 github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
 github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
@@ -569,7 +565,6 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU
 github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
 github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -606,7 +601,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -651,8 +645,6 @@ github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A
 github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
 github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
 github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg=
 github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
 github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
@@ -731,17 +723,17 @@ github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjz
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
+github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
+github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
-github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
-github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
+github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
+github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
@@ -882,8 +874,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
-golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
-golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -894,8 +886,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
-golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
+golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
+golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -923,8 +915,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -978,8 +970,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
-golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
-golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1005,8 +997,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri
 golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
 golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
 golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
-golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
-golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
+golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
+golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1105,8 +1097,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
-golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1114,8 +1106,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
-golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
-golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1134,8 +1126,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -1192,8 +1184,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
-golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
+golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
+golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1424,8 +1416,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1446,7 +1438,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -1465,33 +1456,33 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
 k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
-k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
-k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
+k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg=
+k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8=
 k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8=
 k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
-k8s.io/apiserver v0.29.0 h1:Y1xEMjJkP+BIi0GSEv1BBrf1jLU9UPfAnnGGbbDdp7o=
-k8s.io/apiserver v0.29.0/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM=
+k8s.io/apiserver v0.29.2 h1:+Z9S0dSNr+CjnVXQePG8TcBWHr3Q7BmAr7NraHvsMiQ=
+k8s.io/apiserver v0.29.2/go.mod h1:B0LieKVoyU7ykQvPFm7XSdIHaCHSzCzQWPFa5bqbeMQ=
 k8s.io/cli-runtime v0.29.2 h1:smfsOcT4QujeghsNjECKN3lwyX9AwcFU0nvJ7sFN3ro=
 k8s.io/cli-runtime v0.29.2/go.mod h1:KLisYYfoqeNfO+MkTWvpqIyb1wpJmmFJhioA0xd4MW8=
 k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
 k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
-k8s.io/code-generator v0.29.0 h1:2LQfayGDhaIlaamXjIjEQlCMy4JNCH9lrzas4DNW1GQ=
-k8s.io/code-generator v0.29.0/go.mod h1:5bqIZoCxs2zTRKMWNYqyQWW/bajc+ah4rh0tMY8zdGA=
+k8s.io/code-generator v0.29.2 h1:c9/iw2KnNpw2IRV+wwuG/Wns2TjPSgjWzbbjTevyiHI=
+k8s.io/code-generator v0.29.2/go.mod h1:FwFi3C9jCrmbPjekhaCYcYG1n07CYiW1+PAPCockaos=
 k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8=
 k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM=
 k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
 k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
-k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
-k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
-k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
+k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
+k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
 k8s.io/kubectl v0.29.2 h1:uaDYaBhumvkwz0S2XHt36fK0v5IdNgL7HyUniwb2IUo=
 k8s.io/kubectl v0.29.2/go.mod h1:BhizuYBGcKaHWyq+G7txGw2fXg576QbPrrnQdQDZgqI=
 k8s.io/kubernetes v1.29.2 h1:8hh1cntqdulanjQt7wSSSsJfBgOyx6fUdFWslvGL5m0=
 k8s.io/kubernetes v1.29.2/go.mod h1:xZPKU0yO0CBbLTnbd+XGyRmmtmaVuJykDb8gNCkeeUE=
-k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
-k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
+k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY=
 oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
@@ -1499,8 +1490,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 sigs.k8s.io/cli-utils v0.34.0 h1:zCUitt54f0/MYj/ajVFnG6XSXMhpZ72O/3RewIchW8w=
 sigs.k8s.io/cli-utils v0.34.0/go.mod h1:EXyMwPMu9OL+LRnj0JEMsGG/fRvbgFadcVlSnE8RhFs=
-sigs.k8s.io/controller-runtime v0.17.0 h1:fjJQf8Ukya+VjogLO6/bNX9HE6Y2xpsO5+fyS26ur/s=
-sigs.k8s.io/controller-runtime v0.17.0/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s=
+sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0=
+sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s=
 sigs.k8s.io/controller-tools v0.14.0 h1:rnNoCC5wSXlrNoBKKzL70LNJKIQKEzT6lloG6/LF73A=
 sigs.k8s.io/controller-tools v0.14.0/go.mod h1:TV7uOtNNnnR72SpzhStvPkoS/U5ir0nMudrkrC4M9Sc=
 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
diff --git a/internal/cmd/agent/clusterstatus/ticker.go b/internal/cmd/agent/clusterstatus/ticker.go
index d93e6dc6..13744ea3 100644
--- a/internal/cmd/agent/clusterstatus/ticker.go
+++ b/internal/cmd/agent/clusterstatus/ticker.go
@@ -1,10 +1,9 @@
-// Package clusterstatus updates the cluster.fleet.cattle.io status in the upstream cluster with the current node status.
+// Package clusterstatus updates the cluster.fleet.cattle.io status in the upstream cluster with the current cluster status.
 package clusterstatus
 
 import (
 	"context"
 	"encoding/json"
-	"sort"
 	"time"
 
 	"github.com/sirupsen/logrus"
@@ -16,7 +15,6 @@ import (
 	corecontrollers "github.com/rancher/wrangler/v2/pkg/generated/controllers/core/v1"
 	"github.com/rancher/wrangler/v2/pkg/ticker"
 
-	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
@@ -52,9 +50,9 @@ func Ticker(ctx context.Context,
 
 	go func() {
 		time.Sleep(durations.ClusterRegisterDelay)
-		logger.V(1).Info("Reporting cluster node status once")
+		logger.V(1).Info("Reporting cluster status once")
 		if err := h.Update(); err != nil {
-			logrus.Errorf("failed to report cluster node status: %v", err)
+			logrus.Errorf("failed to report cluster status: %v", err)
 		}
 	}()
 	go func() {
@@ -62,40 +60,21 @@ func Ticker(ctx context.Context,
 			checkinInterval = durations.DefaultClusterCheckInterval
 		}
 		for range ticker.Context(ctx, checkinInterval) {
-			logger.V(1).Info("Reporting cluster node status")
+			logger.V(1).Info("Reporting cluster status")
 			if err := h.Update(); err != nil {
-				logrus.Errorf("failed to report cluster node status: %v", err)
+				logrus.Errorf("failed to report cluster status: %v", err)
 			}
 		}
 	}()
 }
 
-// Update the cluster.fleet.cattle.io status in the upstream cluster with the current node status
+// Update the cluster.fleet.cattle.io status in the upstream cluster with the current cluster status
 func (h *handler) Update() error {
-	nodes, err := h.nodes.List(metav1.ListOptions{})
-	if err != nil {
-		return err
-	}
-
-	ready, nonReady := sortReadyUnready(nodes.Items)
-
 	agentStatus := fleet.AgentStatus{
-		LastSeen:      metav1.Now(),
-		Namespace:     h.agentNamespace,
-		NonReadyNodes: len(nonReady),
-		ReadyNodes:    len(ready),
+		LastSeen:  metav1.Now(),
+		Namespace: h.agentNamespace,
 	}
 
-	if len(ready) > 3 {
-		ready = ready[:3]
-	}
-	if len(nonReady) > 3 {
-		nonReady = nonReady[:3]
-	}
-
-	agentStatus.ReadyNodeNames = ready
-	agentStatus.NonReadyNodeNames = nonReady
-
 	if equality.Semantic.DeepEqual(h.reported, agentStatus) {
 		return nil
 	}
@@ -117,43 +96,3 @@ func (h *handler) Update() error {
 	h.reported = agentStatus
 	return nil
 }
-
-func sortReadyUnready(nodes []corev1.Node) (ready []string, nonReady []string) {
-	var (
-		masterNodeNames         []string
-		nonReadyMasterNodeNames []string
-		readyNodes              []string
-		nonReadyNodes           []string
-	)
-
-	for _, node := range nodes {
-		ready := false
-		for _, cond := range node.Status.Conditions {
-			if cond.Type == corev1.NodeReady && cond.Status == corev1.ConditionTrue {
-				ready = true
-				break
-			}
-		}
-
-		if node.Annotations["node-role.kubernetes.io/master"] == "true" {
-			if ready {
-				masterNodeNames = append(masterNodeNames, node.Name)
-			} else {
-				nonReadyMasterNodeNames = append(nonReadyMasterNodeNames, node.Name)
-			}
-		} else {
-			if ready {
-				readyNodes = append(readyNodes, node.Name)
-			} else {
-				nonReadyNodes = append(nonReadyNodes, node.Name)
-			}
-		}
-	}
-
-	sort.Strings(masterNodeNames)
-	sort.Strings(nonReadyMasterNodeNames)
-	sort.Strings(readyNodes)
-	sort.Strings(nonReadyNodes)
-
-	return append(masterNodeNames, readyNodes...), append(nonReadyMasterNodeNames, nonReadyNodes...)
-}
diff --git a/internal/cmd/agent/deployer/deployer.go b/internal/cmd/agent/deployer/deployer.go
index 4cf181f6..d77919eb 100644
--- a/internal/cmd/agent/deployer/deployer.go
+++ b/internal/cmd/agent/deployer/deployer.go
@@ -16,6 +16,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/log"
 )
@@ -161,20 +162,15 @@ func (d *Deployer) updateNamespace(ctx context.Context, ns *corev1.Namespace) er
 }
 
 // fetchNamespace gets the namespace matching the release ID. Returns an error if none is found.
+// releaseID is composed of release.Namespace/release.Name/release.Version
 func (d *Deployer) fetchNamespace(ctx context.Context, releaseID string) (*corev1.Namespace, error) {
-	// releaseID is composed of release.Namespace/release.Name/release.Version
 	namespace := strings.Split(releaseID, "/")[0]
-	list := &corev1.NamespaceList{}
-	err := d.client.List(ctx, list, client.MatchingLabels{
-		corev1.LabelMetadataName: namespace,
-	})
+	ns := &corev1.Namespace{}
+	err := d.client.Get(ctx, types.NamespacedName{Name: namespace}, ns)
 	if err != nil {
 		return nil, err
 	}
-	if len(list.Items) == 0 {
-		return nil, fmt.Errorf("namespace %s not found", namespace)
-	}
-	return &list.Items[0], nil
+	return ns, nil
 }
 
 // addLabelsFromOptions updates nsLabels so that it only contains all labels specified in optLabels, plus the `kubernetes.io/metadata.name` labels added by kubernetes when creating the namespace.
diff --git a/internal/cmd/controller/reconciler/cluster_controller.go b/internal/cmd/controller/reconciler/cluster_controller.go
index fc1f9b9e..febdc444 100644
--- a/internal/cmd/controller/reconciler/cluster_controller.go
+++ b/internal/cmd/controller/reconciler/cluster_controller.go
@@ -137,10 +137,6 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
 	cluster.Status.Display.ReadyBundles = fmt.Sprintf("%d/%d",
 		cluster.Status.Summary.Ready,
 		cluster.Status.Summary.DesiredReady)
-	cluster.Status.Display.ReadyNodes = fmt.Sprintf("%d/%d",
-		cluster.Status.Agent.ReadyNodes,
-		cluster.Status.Agent.NonReadyNodes+cluster.Status.Agent.ReadyNodes)
-	cluster.Status.Display.SampleNode = sampleNode(cluster.Status)
 
 	var state fleet.BundleState
 	for _, nonReady := range cluster.Status.Summary.NonReadyResources {
@@ -190,13 +186,3 @@ func (r *ClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
 		// cluster.Status.Namespace to create the namespace.
 		Complete(r)
 }
-
-func sampleNode(status fleet.ClusterStatus) string {
-	if len(status.Agent.ReadyNodeNames) > 0 {
-		return status.Agent.ReadyNodeNames[0]
-	}
-	if len(status.Agent.NonReadyNodeNames) > 0 {
-		return status.Agent.NonReadyNodeNames[0]
-	}
-	return ""
-}
diff --git a/package/Dockerfile b/package/Dockerfile
index ae854134..d40ac464 100644
--- a/package/Dockerfile
+++ b/package/Dockerfile
@@ -1,6 +1,7 @@
 ARG BUILD_ENV=dapper
+ARG ARCH
 
-FROM registry.suse.com/bci/bci-busybox:15.5 AS base
+FROM --platform=linux/$ARCH registry.suse.com/bci/bci-busybox:15.5 AS base
 
 FROM base AS copy_dapper
 ONBUILD ARG ARCH
@@ -10,6 +11,10 @@ FROM base AS copy_buildx
 ONBUILD ARG TARGETARCH
 ONBUILD COPY bin/fleetcontroller-linux-${TARGETARCH} /usr/bin/fleetcontroller
 
+FROM base AS copy_goreleaser
+ONBUILD ARG ARCH
+ONBUILD COPY fleetcontroller-linux-${ARCH} /usr/bin/fleetcontroller
+
 FROM copy_${BUILD_ENV}
 RUN addgroup -g 1000 fleet-apply && adduser -u 1000 -G fleet-apply -D fleet-apply
 USER 1000
diff --git a/package/Dockerfile.agent b/package/Dockerfile.agent
index 32a19353..98f89229 100644
--- a/package/Dockerfile.agent
+++ b/package/Dockerfile.agent
@@ -1,6 +1,7 @@
 ARG BUILD_ENV=dapper
+ARG ARCH
 
-FROM registry.suse.com/suse/git:2.35 AS base
+FROM --platform=linux/$ARCH registry.suse.com/suse/git:2.35 AS base
 COPY package/log.sh /usr/bin/
 # Create non-root user and group
 RUN echo "fleet-apply:x:1000:1000::/home/fleet-apply:/bin/bash" >> /etc/passwd && \
@@ -18,6 +19,11 @@ ONBUILD ARG TARGETARCH
 ONBUILD COPY bin/fleetagent-linux-$TARGETARCH /usr/bin/fleetagent
 ONBUILD COPY bin/fleet-linux-$TARGETARCH /usr/bin/fleet
 
+FROM base AS copy_goreleaser
+ONBUILD ARG ARCH
+ONBUILD COPY fleetagent-linux-$ARCH /usr/bin/fleetagent
+ONBUILD COPY fleet-linux-$ARCH /usr/bin/fleet
+
 FROM copy_${BUILD_ENV}
 USER 1000
 CMD ["fleetagent"]
diff --git a/package/Dockerfile.gitjob b/package/Dockerfile.gitjob
index 83b32dcc..2829cc61 100644
--- a/package/Dockerfile.gitjob
+++ b/package/Dockerfile.gitjob
@@ -1,6 +1,7 @@
 ARG BUILD_ENV=dapper
+ARG ARCH
 
-FROM registry.suse.com/bci/bci-base:15.5 AS base
+FROM --platform=linux/$ARCH registry.suse.com/bci/bci-base:15.5 AS base
 RUN zypper -n update && \
     zypper -n install openssh catatonit git-core && \
     zypper -n clean -a
@@ -16,6 +17,11 @@ ONBUILD ARG TARGETARCH
 ONBUILD COPY bin/gitjob-linux-$TARGETARCH /usr/bin/gitjob
 ONBUILD COPY bin/gitcloner-linux-$TARGETARCH /usr/bin/gitcloner
 
+FROM base AS copy_goreleaser
+ONBUILD ARG ARCH
+ONBUILD COPY gitjob-linux-$ARCH /usr/bin/gitjob
+ONBUILD COPY gitcloner-linux-$ARCH /usr/bin/gitcloner
+
 FROM copy_${BUILD_ENV}
 USER 1000
 ENTRYPOINT ["catatonit", "--"]
diff --git a/pkg/apis/fleet.cattle.io/v1alpha1/cluster_types.go b/pkg/apis/fleet.cattle.io/v1alpha1/cluster_types.go
index 14e2fe50..d3f753bb 100644
--- a/pkg/apis/fleet.cattle.io/v1alpha1/cluster_types.go
+++ b/pkg/apis/fleet.cattle.io/v1alpha1/cluster_types.go
@@ -46,8 +46,6 @@ var (
 // +kubebuilder:object:root=true
 // +kubebuilder:subresource:status
 // +kubebuilder:printcolumn:name="Bundles-Ready",type=string,JSONPath=`.status.display.readyBundles`
-// +kubebuilder:printcolumn:name="Nodes-Ready",type=string,JSONPath=`.status.display.readyNodes`
-// +kubebuilder:printcolumn:name="Sample-Node",type=string,JSONPath=`.status.display.sampleNode`
 // +kubebuilder:printcolumn:name="Last-Seen",type=string,JSONPath=`.status.agent.lastSeen`
 // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].message`
 
@@ -200,12 +198,6 @@ type ClusterDisplay struct {
 	// number of bundles that are ready vs. the number of bundles desired
 	// to be ready.
 	ReadyBundles string `json:"readyBundles,omitempty"`
-	// ReadyNodes is a string in the form "%d/%d", that describes the
-	// number of nodes that are ready vs. the number of expected nodes.
-	ReadyNodes string `json:"readyNodes,omitempty"`
-	// SampleNode is the name of one of the nodes that are ready. If no
-	// node is ready, it's the name of a node that is not ready.
-	SampleNode string `json:"sampleNode,omitempty"`
 	// State of the cluster, either one of the bundle states, or "WaitCheckIn".
 	State string `json:"state,omitempty"`
 }
@@ -220,18 +212,4 @@ type AgentStatus struct {
 	// +nullable
 	// +optional
 	Namespace string `json:"namespace"`
-	// NonReadyNodes is the number of nodes that are not ready.
-	// +optional
-	NonReadyNodes int `json:"nonReadyNodes"`
-	// ReadyNodes is the number of nodes that are ready.
-	// +optional
-	ReadyNodes int `json:"readyNodes"`
-	// NonReadyNode contains the names of non-ready nodes. The list is
-	// limited to at most 3 names.
-	// +optional
-	NonReadyNodeNames []string `json:"nonReadyNodeNames"`
-	// ReadyNodes contains the names of ready nodes. The list is limited to
-	// at most 3 names.
-	// +optional
-	ReadyNodeNames []string `json:"readyNodeNames"`
 }
diff --git a/pkg/apis/fleet.cattle.io/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/fleet.cattle.io/v1alpha1/zz_generated.deepcopy.go
index ca4129d3..d8be5ab8 100644
--- a/pkg/apis/fleet.cattle.io/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/fleet.cattle.io/v1alpha1/zz_generated.deepcopy.go
@@ -32,16 +32,6 @@ import (
 func (in *AgentStatus) DeepCopyInto(out *AgentStatus) {
 	*out = *in
 	in.LastSeen.DeepCopyInto(&out.LastSeen)
-	if in.NonReadyNodeNames != nil {
-		in, out := &in.NonReadyNodeNames, &out.NonReadyNodeNames
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-	if in.ReadyNodeNames != nil {
-		in, out := &in.ReadyNodeNames, &out.ReadyNodeNames
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentStatus.
diff --git a/scripts/agent-dev b/scripts/agent-dev
deleted file mode 100755
index 28a8d701..00000000
--- a/scripts/agent-dev
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/version
-
-cd $(dirname $0)/..
-
-mkdir -p bin
-mkdir -p dist/artifacts
-
-LINKFLAGS="-X github.com/rancher/fleet/pkg/version.Version=$VERSION"
-LINKFLAGS="-X github.com/rancher/fleet/pkg/version.GitCommit=$COMMIT $LINKFLAGS"
-LINKFLAGS="-s -w $LINKFLAGS"
-LINKFLAGS="$LINKFLAGS -extldflags -static"
-
-AGENT_ARCH=amd64
-
-echo "Building binary: fleet"
-GOOS=linux GOARCH=$AGENT_ARCH CGO_ENABLED=0 go build -ldflags "$LINKFLAGS" -o bin/fleet-linux-$AGENT_ARCH ./cmd/fleetcli
-cp bin/fleet-linux-$AGENT_ARCH dist/artifacts/
-
-echo "Building binary: fleetagent"
-GOOS=linux GOARCH=$AGENT_ARCH CGO_ENABLED=0 go build -ldflags "$LINKFLAGS" -o bin/fleetagent-linux-$AGENT_ARCH ./cmd/fleetagent
-cp bin/fleetagent-linux-$AGENT_ARCH dist/artifacts/
-
-IMAGE=$REPO/fleet-agent:$TAG
-echo "Building fleet-agent image for linux-$AGENT_ARCH: $IMAGE"
-docker build -f package/Dockerfile.agent -t $IMAGE --build-arg ARCH=$AGENT_ARCH .
diff --git a/scripts/build b/scripts/build
deleted file mode 100755
index d0a25ce0..00000000
--- a/scripts/build
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/version
-
-cd $(dirname $0)/..
-
-mkdir -p bin
-
-if [ -n "${DEBUG}" ]; then
-  GCFLAGS="-N -l"
-fi
-
-LINKFLAGS="-X github.com/rancher/fleet/pkg/version.Version=$VERSION"
-LINKFLAGS="-X github.com/rancher/fleet/pkg/version.GitCommit=$COMMIT $LINKFLAGS"
-if [ -z "${DEBUG}" ]; then
-  LINKFLAGS="-s -w $LINKFLAGS"
-fi
-OTHER_LINKFLAGS="-extldflags -static"
-
-function build-binaries() {
-    printf "Building for ${1}-${2} ...\n"
-    TEMP_LINKFLAGS=$LINKFLAGS
-    if [ $1 = "linux" ]; then
-        TEMP_LINKFLAGS="$LINKFLAGS $OTHER_LINKFLAGS"
-    fi
-    TEMP_SUFFIX=""
-    if [ $1 = "windows" ]; then
-        TEMP_SUFFIX=".exe"
-    fi
-    GOOS=${1} GOARCH=${2} CGO_ENABLED=0 go build -gcflags="all=${GCFLAGS}" -ldflags "$TEMP_LINKFLAGS" -o bin/fleet-${1}-${2}${TEMP_SUFFIX} ./cmd/fleetcli
-    if ! [ $1 = "darwin" ]; then
-        GOOS=${1} GOARCH=${2} CGO_ENABLED=0 go build -gcflags="all=${GCFLAGS}" -ldflags "$TEMP_LINKFLAGS" -o bin/fleetcontroller-${1}-${2}${TEMP_SUFFIX} ./cmd/fleetcontroller
-        GOOS=${1} GOARCH=${2} CGO_ENABLED=0 go build -gcflags="all=${GCFLAGS}" -ldflags "$TEMP_LINKFLAGS" -o bin/fleetagent-${1}-${2}${TEMP_SUFFIX} ./cmd/fleetagent
-        GOOS=${1} GOARCH=${2} CGO_ENABLED=0 go build -gcflags="all=${GCFLAGS}" -ldflags "$TEMP_LINKFLAGS" -o bin/gitjob-${1}-${2}${TEMP_SUFFIX} ./cmd/gitjob
-        GOOS=${1} GOARCH=${2} CGO_ENABLED=0 go build -gcflags="all=${GCFLAGS}" -ldflags "$TEMP_LINKFLAGS" -o bin/gitcloner-${1}-${2}${TEMP_SUFFIX} ./cmd/gitcloner
-    fi
-}
-
-if [ "$CROSS" = "true" ]; then
-    # If local (host) is unset, we default to false since we are already cross-compiling for all platforms.
-    if [ -z "$LOCAL" ]; then
-        LOCAL="false"
-    fi
-    OS_ARCH=( "linux amd64" "linux arm64" "darwin amd64" "windows amd64" )
-    for i in "${OS_ARCH[@]}"; do
-        set -- $i
-        build-binaries ${1} ${2}
-    done
-elif [ "$CROSS" = "windows" ]; then
-   build-binaries "windows" "amd64"
-fi
-
-# Always build for the host (local) OS and ARCH unless otherwise specified (setting LOCAL to "false").
-# LOCAL will be set to "false" if CROSS is "true" (avoids compiling the host OS and ARCH twice).
-if ! [ "$LOCAL" = "false" ]; then
-    build-binaries ${OS} ${ARCH}
-fi
-
-mkdir -p dist/artifacts
-cp -r bin/fleet* dist/artifacts/
diff --git a/scripts/ci b/scripts/ci
deleted file mode 100755
index 52334105..00000000
--- a/scripts/ci
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-set -e
-
-cd $(dirname $0)
-
-./build
-./test
-./validate
-./validate-ci
-./package
diff --git a/scripts/default b/scripts/default
deleted file mode 100755
index af2ad2db..00000000
--- a/scripts/default
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-set -e
-
-cd $(dirname $0)
-
-./build
-./test
-./package
diff --git a/scripts/entry b/scripts/entry
deleted file mode 100755
index 78fb5679..00000000
--- a/scripts/entry
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-set -e
-
-mkdir -p bin dist
-if [ -e ./scripts/$1 ]; then
-    ./scripts/"$@"
-else
-    exec "$@"
-fi
-
-chown -R $DAPPER_UID:$DAPPER_GID .
diff --git a/scripts/package b/scripts/package
deleted file mode 100755
index 2cc1bf9b..00000000
--- a/scripts/package
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/version
-
-cd $(dirname $0)/..
-
-function build-image() {
-  IMAGE=${REPO}/${1}:${TAG}
-  DOCKERFILE=package/Dockerfile${2}
-  if [ -e ${DOCKERFILE}.${ARCH} ]; then
-      DOCKERFILE=${DOCKERFILE}.${ARCH}
-  fi
-
-  docker build -f ${DOCKERFILE} -t ${IMAGE} --build-arg ARCH=${ARCH} .
-  echo Built ${IMAGE}
-
-  if [ "$PUSH" = "true" ]; then
-      docker push ${IMAGE}
-  fi
-}
-
-build-image fleet
-build-image fleet-agent .agent
-build-image gitjob .gitjob
-
-./scripts/package-helm
diff --git a/scripts/package-helm b/scripts/package-helm
deleted file mode 100755
index 4ea6d9dc..00000000
--- a/scripts/package-helm
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-set -e
-
-if ! hash helm 2>/dev/null; then
-    exit 0
-fi
-
-cd $(dirname $0)/..
-. ./scripts/version
-
-rm -rf build/charts
-mkdir -p build dist/artifacts
-cp -rf charts build/
-rm -rf build/charts/fleet-crd/templates/crds.yaml
-
-sed -i \
-    -e 's/^version:.*/version: '${HELM_VERSION}'/' \
-    -e 's/appVersion:.*/appVersion: '${HELM_VERSION}'/' \
-    build/charts/fleet/Chart.yaml
-
-sed -i \
-    -e 's/tag:.*/tag: '${HELM_TAG}'/' \
-    build/charts/fleet/values.yaml
-
-sed -i \
-    -e 's/version:.*/version: '${HELM_VERSION}'/' \
-    -e 's/appVersion:.*/appVersion: '${HELM_VERSION}'/' \
-    build/charts/fleet-crd/Chart.yaml
-
-sed -i \
-    -e 's/version:.*/version: '${HELM_VERSION}'/' \
-    -e 's/appVersion:.*/appVersion: '${HELM_VERSION}'/' \
-    build/charts/fleet-agent/Chart.yaml
-
-sed -i \
-    -e 's/tag: dev/tag: '${HELM_TAG}'/' \
-    build/charts/fleet-agent/values.yaml
-
-bash ./cmd/codegen/hack/generate_and_sort_crds.sh ./build/charts/fleet-crd/templates/crds.yaml
-
-helm package -d ./dist/artifacts ./build/charts/fleet
-helm package -d ./dist/artifacts ./build/charts/fleet-crd
-helm package -d ./dist/artifacts ./build/charts/fleet-agent
diff --git a/scripts/release b/scripts/release
deleted file mode 100755
index 7af0df35..00000000
--- a/scripts/release
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-exec $(dirname $0)/ci
diff --git a/scripts/validate b/scripts/validate
deleted file mode 100755
index 555703b2..00000000
--- a/scripts/validate
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-set -e
-
-cd "$(dirname "$0")"/..
-
-echo Running validation
-
-go mod verify
diff --git a/scripts/validate-ci b/scripts/validate-ci
deleted file mode 100755
index e7981cf8..00000000
--- a/scripts/validate-ci
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-set -e
-
-cd $(dirname $0)/..
-
-go generate
-
-source ./scripts/version
-
-if [ -n "$DIRTY" ]; then
-    echo Git is dirty
-    git status
-    git diff
-    exit 1
-fi
diff --git a/scripts/version b/scripts/version
deleted file mode 100755
index 5fefcd2a..00000000
--- a/scripts/version
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-
-if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
-    DIRTY="+dirty"
-fi
-
-GIT_TAG=${DRONE_TAG:-$(git tag -l --contains HEAD | head -n 1)}
-
-if [[ -z "$DIRTY" && -n "$GIT_TAG" ]]; then
-    VERSION=$GIT_TAG
-else
-    # Make sure tags are available in the CI environment
-    readarray -t TAGS < <(git tag -l)
-    if [[ ${#TAGS[@]} == 0 ]]; then
-        git fetch -t
-    fi
-    VERSION="$(git describe --tags)${DIRTY}"
-fi
-
-if [ -z "$ARCH" ]; then
-    ARCH=$(go env GOHOSTARCH)
-fi
-
-if [ -z "$OS" ]; then
-    OS=$(go env GOHOSTOS)
-fi
-
-SUFFIX="-${ARCH}"
-
-HELM_TAG=${TAG:-${VERSION}}
-HELM_VERSION=${HELM_TAG/v/}
-TAG=${TAG:-${VERSION}${SUFFIX}}
-REPO=${REPO:-rancher}
-
-if echo $TAG | grep -q dirty; then
-    TAG=dev
-    HELM_TAG=dev
-    HELM_VERSION=0.0.0-dev
-fi


Test patch:
diff --git a/.github/workflows/e2e-multicluster-ci.yml b/.github/workflows/e2e-multicluster-ci.yml
index 16677ddf..a3bb8908 100644
--- a/.github/workflows/e2e-multicluster-ci.yml
+++ b/.github/workflows/e2e-multicluster-ci.yml
@@ -121,7 +121,7 @@ jobs:
                 --set token="$token"
 
           echo "waiting for downstream cluster to be registered..."
-          { grep -q -m 1 "k3d-downstream"; kill $!; } < <(kubectl get cluster -n fleet-default -w)
+          { grep -q -m 1 "1/1"; kill $!; } < <(kubectl get cluster -n fleet-default -w)
 
           echo "waiting for cluster to report being ready..."
           while [ $(kubectl -n fleet-default get cluster -o jsonpath='{.items[0].status.summary.ready}') -ne 1 ]; do
diff --git a/internal/cmd/agent/clusterstatus/suite_test.go b/internal/cmd/agent/clusterstatus/suite_test.go
new file mode 100644
index 00000000..10a9beb6
--- /dev/null
+++ b/internal/cmd/agent/clusterstatus/suite_test.go
@@ -0,0 +1,22 @@
+package clusterstatus_test
+
+import (
+	"testing"
+	"time"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+const (
+	timeout = 30 * time.Second
+)
+
+func TestFleet(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "ClusterStatus Suite")
+}
+
+var _ = BeforeSuite(func() {
+	SetDefaultEventuallyTimeout(timeout)
+})
diff --git a/internal/cmd/agent/clusterstatus/ticker_test.go b/internal/cmd/agent/clusterstatus/ticker_test.go
new file mode 100644
index 00000000..adfb4feb
--- /dev/null
+++ b/internal/cmd/agent/clusterstatus/ticker_test.go
@@ -0,0 +1,77 @@
+package clusterstatus
+
+import (
+	"context"
+	"encoding/json"
+	"time"
+
+	"github.com/golang/mock/gomock"
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	fleet "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
+	"github.com/rancher/wrangler/v2/pkg/generic/fake"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
+)
+
+var _ = Describe("ClusterStatus Ticker", func() {
+	var (
+		clusterClient        *fake.MockClientInterface[*fleet.Cluster, *fleet.ClusterList]
+		nodeClient           *fake.MockNonNamespacedClientInterface[*v1.Node, *v1.NodeList]
+		ctx                  context.Context
+		cancel               context.CancelFunc
+		agentNamespace       string
+		clusterName          string
+		clusterNamespace     string
+		baseTime             metav1.Time
+		lastTime             metav1.Time
+		agentStatusNamespace string
+	)
+
+	BeforeEach(func() {
+		ctrl := gomock.NewController(GinkgoT())
+		clusterClient = fake.NewMockClientInterface[*fleet.Cluster, *fleet.ClusterList](ctrl)
+		nodeClient = fake.NewMockNonNamespacedClientInterface[*v1.Node, *v1.NodeList](ctrl)
+		agentNamespace = "cattle-fleet-system"
+		clusterName = "cluster-name"
+		clusterNamespace = "cluster-namespace"
+		baseTime = metav1.Now()
+		ctx, cancel = context.WithCancel(context.TODO())
+		clusterClient.EXPECT().Patch(clusterNamespace, clusterName, types.MergePatchType, gomock.Any(), "status").
+			DoAndReturn(func(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (fleet.Cluster, error) {
+				cluster := &fleet.Cluster{}
+				err := json.Unmarshal(data, cluster)
+				if err != nil {
+					return fleet.Cluster{}, err
+				}
+				// only storing the lastseen time value here.
+				// We're not checking for values here because calling Expect,
+				// for example, makes the mock call panic when it doesn't succeed
+				lastTime = cluster.Status.Agent.LastSeen
+				agentStatusNamespace = cluster.Status.Agent.Namespace
+				return *cluster, nil
+			}).AnyTimes()
+		Ticker(ctx, agentNamespace, clusterNamespace, clusterName, time.Second*1, nodeClient, clusterClient)
+	})
+
+	It("Increases the timestamp used to call Patch", func() {
+		By("Comparing every 2 seconds for a 6 seconds period")
+		Consistently(func() bool {
+			// return true when we're calling before Patch was even called
+			if lastTime.IsZero() {
+				return true
+			}
+			// check that the timestamp increases and the namespace is the expected one
+			result := baseTime.Before(&lastTime) && agentStatusNamespace == agentNamespace
+			baseTime = lastTime
+			return result
+		}, 6*time.Second, 2*time.Second).Should(BeTrue())
+		// ensure that lastTime was set (which means Patch was successfully called)
+		Expect(lastTime).ShouldNot(BeZero())
+	})
+
+	AfterEach(func() {
+		cancel()
+	})
+})
diff --git a/internal/cmd/agent/deployer/deployer_test.go b/internal/cmd/agent/deployer/deployer_test.go
index 4e82b9d2..c12c8fc7 100644
--- a/internal/cmd/agent/deployer/deployer_test.go
+++ b/internal/cmd/agent/deployer/deployer_test.go
@@ -2,12 +2,12 @@ package deployer
 
 import (
 	"context"
-	"errors"
 	"testing"
 
 	fleet "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
 
 	corev1 "k8s.io/api/core/v1"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
@@ -32,13 +32,14 @@ func TestSetNamespaceLabelsAndAnnotations(t *testing.T) {
 			}},
 			ns: corev1.Namespace{
 				ObjectMeta: metav1.ObjectMeta{
-					Name:   "namespace1234",
+					Name:   "namespace",
 					Labels: map[string]string{"kubernetes.io/metadata.name": "namespace"},
 				},
 			},
 			release: "namespace/foo/bar",
 			expectedNs: corev1.Namespace{
 				ObjectMeta: metav1.ObjectMeta{
+					Name:        "namespace",
 					Labels:      map[string]string{"kubernetes.io/metadata.name": "namespace", "optLabel1": "optValue1", "optLabel2": "optValue2"},
 					Annotations: map[string]string{"optAnn1": "optValue1"},
 				},
@@ -54,7 +55,7 @@ func TestSetNamespaceLabelsAndAnnotations(t *testing.T) {
 			}},
 			ns: corev1.Namespace{
 				ObjectMeta: metav1.ObjectMeta{
-					Name:        "namespace1234",
+					Name:        "namespace",
 					Labels:      map[string]string{"nsLabel": "nsValue", "kubernetes.io/metadata.name": "namespace"},
 					Annotations: map[string]string{"nsAnn": "nsValue"},
 				},
@@ -62,6 +63,7 @@ func TestSetNamespaceLabelsAndAnnotations(t *testing.T) {
 			release: "namespace/foo/bar",
 			expectedNs: corev1.Namespace{
 				ObjectMeta: metav1.ObjectMeta{
+					Name:        "namespace",
 					Labels:      map[string]string{"optLabel": "optValue", "kubernetes.io/metadata.name": "namespace"},
 					Annotations: map[string]string{},
 				},
@@ -77,7 +79,7 @@ func TestSetNamespaceLabelsAndAnnotations(t *testing.T) {
 			}},
 			ns: corev1.Namespace{
 				ObjectMeta: metav1.ObjectMeta{
-					Name:        "namespace1234",
+					Name:        "namespace",
 					Labels:      map[string]string{"bdLabel": "nsValue", "kubernetes.io/metadata.name": "namespace"},
 					Annotations: map[string]string{"bdAnn": "nsValue"},
 				},
@@ -85,6 +87,7 @@ func TestSetNamespaceLabelsAndAnnotations(t *testing.T) {
 			release: "namespace/foo/bar",
 			expectedNs: corev1.Namespace{
 				ObjectMeta: metav1.ObjectMeta{
+					Name:        "namespace",
 					Labels:      map[string]string{"bdLabel": "labelUpdated", "kubernetes.io/metadata.name": "namespace"},
 					Annotations: map[string]string{"bdAnn": "annUpdated"},
 				},
@@ -132,7 +135,6 @@ func TestSetNamespaceLabelsAndAnnotationsError(t *testing.T) {
 		},
 	}}
 	release := "test/foo/bar"
-	expectedErr := errors.New("namespace test not found")
 
 	scheme := runtime.NewScheme()
 	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
@@ -143,7 +145,7 @@ func TestSetNamespaceLabelsAndAnnotationsError(t *testing.T) {
 
 	err := h.setNamespaceLabelsAndAnnotations(context.Background(), bd, release)
 
-	if err.Error() != expectedErr.Error() {
-		t.Errorf("expected error %v: got %v", expectedErr, err)
+	if !apierrors.IsNotFound(err) {
+		t.Errorf("expected not found error: got %v", err)
 	}
 }
diff --git a/scripts/test b/scripts/test
deleted file mode 100755
index c9f3a702..00000000
--- a/scripts/test
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-set -eo pipefail
-
-cd "$(dirname "$0")/.."
-
-echo Running tests
-go test -cover -tags=test $(go list ./... | grep -v -e /e2e -e /integrationtests)