From b8d25d00cee7ca2564965cb5c07b481e3788d5fb Mon Sep 17 00:00:00 2001
From: Dipti Pai <diptipai89@outlook.com>
Date: Tue, 27 Aug 2024 00:07:07 -0700
Subject: [PATCH] Add new integration tests for Azure OIDC for git repositories

Signed-off-by: Dipti Pai <diptipai89@outlook.com>
---
 oci/tests/integration/.env.sample             |   8 +-
 oci/tests/integration/Makefile                |   9 +-
 oci/tests/integration/README.md               |  34 ++-
 oci/tests/integration/aws_test.go             |  10 +
 oci/tests/integration/azure_test.go           | 163 ++++++++++++-
 oci/tests/integration/gcp_test.go             |  10 +
 oci/tests/integration/git_test.go             |  46 ++++
 oci/tests/integration/go.mod                  | 103 +++++---
 oci/tests/integration/go.sum                  | 228 +++++++++++-------
 .../{repo_list_test.go => job_test.go}        |  50 +---
 oci/tests/integration/oci_test.go             |  88 +++++++
 oci/tests/integration/suite_test.go           | 189 +++++++++++----
 oci/tests/integration/terraform/azure/main.tf |  21 +-
 .../integration/terraform/azure/outputs.tf    |  22 ++
 .../integration/terraform/azure/variables.tf  |  18 ++
 .../integration/terraform/azure/version.tf    |   7 +
 oci/tests/integration/testapp/main.go         |  97 +++++++-
 oci/tests/integration/util_test.go            | 123 ++++++++++
 18 files changed, 983 insertions(+), 243 deletions(-)
 create mode 100644 oci/tests/integration/git_test.go
 rename oci/tests/integration/{repo_list_test.go => job_test.go} (64%)
 create mode 100644 oci/tests/integration/oci_test.go
 create mode 100644 oci/tests/integration/terraform/azure/version.tf
 create mode 100644 oci/tests/integration/util_test.go

diff --git a/oci/tests/integration/.env.sample b/oci/tests/integration/.env.sample
index e50eb0c1..12357f86 100644
--- a/oci/tests/integration/.env.sample
+++ b/oci/tests/integration/.env.sample
@@ -11,12 +11,14 @@
 # export TF_VAR_rand=${RANDOM}
 
 ## Azure
+# export ARM_SUBSCRIPTION_ID=
+# export TF_VAR_azuredevops_org=
+# export TF_VAR_azuredevops_pat=
 # export TF_VAR_azure_location=eastus
 ## Set the following only when authenticating using Service Principal (suited
 ## for CI environment).
 # export ARM_CLIENT_ID=
 # export ARM_CLIENT_SECRET=
-# export ARM_SUBSCRIPTION_ID=
 # export ARM_TENANT_ID=
 
 ## GCP
@@ -48,3 +50,7 @@
 # export TF_VAR_wi_k8s_sa_name=test-workload-id
 # export TF_VAR_wi_k8s_sa_ns=default
 # export TF_VAR_enable_wi=true
+
+## Test Configuration variables
+# export TF_VAR_enable_git=true
+# export TF_VAR_enable_oci=true
diff --git a/oci/tests/integration/Makefile b/oci/tests/integration/Makefile
index 2183bfd6..dfe5954f 100644
--- a/oci/tests/integration/Makefile
+++ b/oci/tests/integration/Makefile
@@ -1,4 +1,5 @@
 GO_TEST_ARGS ?=
+GO_TEST_PREFIX ?=
 PROVIDER_ARG ?=
 TEST_TIMEOUT ?= 30m
 GOARCH ?= amd64
@@ -15,7 +16,7 @@ docker-build: app
 
 test:
 	docker image inspect $(TEST_IMG) >/dev/null
-	TEST_IMG=$(TEST_IMG) go test -timeout $(TEST_TIMEOUT) -v ./ $(GO_TEST_ARGS) $(PROVIDER_ARG) --tags=integration
+	TEST_IMG=$(TEST_IMG) go test -timeout $(TEST_TIMEOUT) -v ./ -run "^$(GO_TEST_PREFIX).*" $(GO_TEST_ARGS) $(PROVIDER_ARG) --tags=integration
 
 test-aws:
 	$(MAKE) test PROVIDER_ARG="-provider aws"
@@ -23,6 +24,12 @@ test-aws:
 test-azure:
 	$(MAKE) test PROVIDER_ARG="-provider azure"
 
+test-azure-git:
+	$(MAKE) test PROVIDER_ARG="-provider azure" GO_TEST_PREFIX="TestGit"
+
+test-azure-oci:
+	$(MAKE) test PROVIDER_ARG="-provider azure" GO_TEST_PREFIX="TestOci"
+
 test-gcp:
 	$(MAKE) test PROVIDER_ARG="-provider gcp"
 
diff --git a/oci/tests/integration/README.md b/oci/tests/integration/README.md
index 3fc14ce3..b9347d3f 100644
--- a/oci/tests/integration/README.md
+++ b/oci/tests/integration/README.md
@@ -1,7 +1,7 @@
-# OCI integration test
+# Integration tests
 
-OCI integration test uses a test application(`testapp/`) to test the
-oci package against each of the supported cloud providers.
+Integration tests uses a test application(`testapp/`) to test the
+oci and git package against each of the supported cloud providers.
 
 **NOTE:** Tests in this package aren't run automatically by the `test-*` make
 target at the root of `fluxcd/pkg` repo. These tests are more complicated than
@@ -16,7 +16,7 @@ runs the test app as a batch job which tries to log in and list tags from the
 test registry repository. A successful job indicates successful test. If the job
 fails, the test fails.
 
-Logs of a successful job run:
+Logs of a successful job run for oci:
 ```console
 $ kubectl logs test-job-93tbl-4jp2r
 2022/07/28 21:59:06 repo: xxx.dkr.ecr.us-east-2.amazonaws.com/test-repo-flux-test-heroic-ram
@@ -25,6 +25,17 @@ $ kubectl logs test-job-93tbl-4jp2r
 2022/07/28 21:59:06 tags: [v0.1.4 v0.1.3 v0.1.0 v0.1.2]
 ```
 
+Logs of a successful job run for git:
+```console
+$ kubectl logs test-job-dzful-jrcqw
+2024/07/19 19:04:06 Validating git oidc by cloning repo  https://dev.azure.com/xxx/fluxProjtoughowerewolf/_git/fluxRepotoughowerewolf
+2024/07/19 19:04:07 Successfully cloned repository
+2024/07/19 19:04:07 apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: foobar
+```
+
 ## Requirements
 
 ### Amazon Web Services
@@ -42,6 +53,12 @@ $ kubectl logs test-job-93tbl-4jp2r
     workloads to access ACR.
 - Azure CLI, need to be logged in using `az login` as a User (not a Service
   Principal).
+- An Azure DevOps organization, personal access token for accessing repositories within the organization. The scope required for the personal access token is:
+  - Project and Team - read, write and manage access
+  - Member Entitlement Management (Read & Write)
+  - Code - Full
+  - Please take a look at the [terraform provider](https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/guides/authenticating_using_the_personal_access_token#create-a-personal-access-token) for more explanation.
+  - A valid Azure devops configuration is needed even if git is not being tested. 
 
   **NOTE:** To use Service Principal (for example in CI environment), set the
   `ARM-*` variables in `.env`, source it and authenticate Azure CLI with:
@@ -246,9 +263,10 @@ Run the test with `make test-*`, setting the test app image with variable
 $ make test-azure
 make test PROVIDER_ARG="-provider azure"
 docker image inspect fluxcd/testapp:test >/dev/null
-TEST_IMG=fluxcd/testapp:test go test -timeout 30m -v ./ -verbose -retain -provider azure --tags=integration
-2022/07/29 02:06:51 Terraform binary:  /usr/bin/terraform
-2022/07/29 02:06:51 Init Terraform
+TEST_IMG=fluxcd/testapp:test go test -timeout 30m -v ./ -run "^.*" -provider azure --tags=integration
+2024/08/26 23:39:13 Terraform binary:  /snap/bin/terraform
+2024/08/26 23:39:13 Init Terraform
+2024/08/26 23:39:15 Applying Terraform
 ...
 ```
 
@@ -273,6 +291,8 @@ export TF_VAR_enable_wi=
 
 They have been included in the `.env.sample` and you can simply uncomment it.
 
+The git integration tests require workload identity to be enabled.
+
 ## Debugging the tests
 
 For debugging environment provisioning, enable verbose output with `-verbose`
diff --git a/oci/tests/integration/aws_test.go b/oci/tests/integration/aws_test.go
index 640a514b..5c57ca19 100644
--- a/oci/tests/integration/aws_test.go
+++ b/oci/tests/integration/aws_test.go
@@ -98,3 +98,13 @@ func getWISAAnnotationsAWS(output map[string]*tfjson.StateOutput) (map[string]st
 		eksRoleArnAnnotation: iamARN,
 	}, nil
 }
+
+// When implemented, getGitTestConfigAws would return the git-specific test config for AWS
+func getGitTestConfigAWS(outputs map[string]*tfjson.StateOutput) (*gitTestConfig, error) {
+	return nil, fmt.Errorf("NotImplemented for AWS")
+}
+
+// When implemented, givePermissionsToRepositoryAWS would grant the required permissions to AWS CodeCommit repository
+func givePermissionsToRepositoryAWS(output map[string]*tfjson.StateOutput) error {
+	return fmt.Errorf("NotImplemented for AWS")
+}
diff --git a/oci/tests/integration/azure_test.go b/oci/tests/integration/azure_test.go
index 104ca721..b680135b 100644
--- a/oci/tests/integration/azure_test.go
+++ b/oci/tests/integration/azure_test.go
@@ -20,12 +20,20 @@ limitations under the License.
 package integration
 
 import (
+	"bytes"
 	"context"
+	"encoding/base64"
+	"encoding/json"
 	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"strings"
+	"time"
 
-	tfjson "github.com/hashicorp/terraform-json"
-
+	"github.com/fluxcd/pkg/git"
 	"github.com/fluxcd/test-infra/tftestenv"
+	tfjson "github.com/hashicorp/terraform-json"
 )
 
 const (
@@ -81,3 +89,154 @@ func getWISAAnnotationsAzure(output map[string]*tfjson.StateOutput) (map[string]
 		azureWIClientIdAnnotation: clientID,
 	}, nil
 }
+
+// Give managed identity permissions on the azure devops project using
+// ServicePrincipalEntitlement REST API
+// https://learn.microsoft.com/en-us/rest/api/azure/devops/memberentitlementmanagement/service-principal-entitlements/add?view=azure-devops-rest-7.1&tabs=HTTP
+// This can be moved to terraform if/when this PR completes -
+// https://github.com/microsoft/terraform-provider-azuredevops/pull/1028
+type ServicePrincipalEntitlement struct {
+	AccessLevel struct {
+		AccountLicenseType string `json:"accountLicenseType"`
+	} `json:"accessLevel"`
+	ProjectEntitlements []struct {
+		Group struct {
+			GroupType string `json:"groupType"`
+		} `json:"group"`
+		ProjectRef struct {
+			ID string `json:"id"`
+		} `json:"projectRef"`
+	} `json:"projectEntitlements"`
+	ServicePrincipal struct {
+		Origin      string `json:"origin"`
+		OriginID    string `json:"originId"`
+		SubjectKind string `json:"subjectKind"`
+	} `json:"servicePrincipal"`
+}
+
+func givePermissionsToRepositoryAzure(outputs map[string]*tfjson.StateOutput) error {
+	// Organization, PAT, Project ID and WI ID are availble as terraform output
+	organization := outputs["azure_devops_organization"].Value.(string)
+	project_id := outputs["azure_devops_project_id"].Value.(string)
+	pat := outputs["azure_devops_access_token"].Value.(string)
+	wi_object_id := outputs["workload_identity_object_id"].Value.(string)
+
+	encodedPat := base64.StdEncoding.EncodeToString([]byte(":" + pat))
+	apiURL := fmt.Sprintf("https://vsaex.dev.azure.com/%s/_apis/serviceprincipalentitlements?api-version=7.1-preview.1", organization)
+
+	// Set up the request payload
+	payload := ServicePrincipalEntitlement{
+		AccessLevel: struct {
+			AccountLicenseType string `json:"accountLicenseType"`
+		}{
+			AccountLicenseType: "express",
+		},
+		ProjectEntitlements: []struct {
+			Group struct {
+				GroupType string `json:"groupType"`
+			} `json:"group"`
+			ProjectRef struct {
+				ID string `json:"id"`
+			} `json:"projectRef"`
+		}{
+			{
+				Group: struct {
+					GroupType string `json:"groupType"`
+				}{
+					GroupType: "projectContributor",
+				},
+				ProjectRef: struct {
+					ID string `json:"id"`
+				}{
+					ID: project_id,
+				},
+			},
+		},
+		ServicePrincipal: struct {
+			Origin      string `json:"origin"`
+			OriginID    string `json:"originId"`
+			SubjectKind string `json:"subjectKind"`
+		}{
+			Origin:      "aad",
+			OriginID:    wi_object_id,
+			SubjectKind: "servicePrincipal",
+		},
+	}
+
+	// Marshal the payload into JSON
+	jsonPayload, err := json.Marshal(payload)
+	if err != nil {
+		log.Printf("Error marshalling the payload:%v", err)
+		return err
+	}
+
+	// First request to add user always fails, second request succeeds, add a
+	// retry
+	retryAttempts := 3
+	retryDelay := 5 * time.Second // 5 seconds delay
+	attempts := 0
+
+	for attempts < retryAttempts {
+		attempts++
+		// Create a new request
+		req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonPayload))
+		if err != nil {
+			log.Printf("Error creating the request: %v", err)
+			return err
+		}
+
+		// Set the authorization header to use the PAT
+		req.Header.Set("Authorization", "Basic "+strings.TrimSpace(encodedPat))
+		req.Header.Set("Content-Type", "application/json")
+
+		// Send the request
+		client := &http.Client{}
+		resp, err := client.Do(req)
+		if err != nil {
+			log.Printf("Error sending the request: %v", err)
+			return err
+		}
+		defer resp.Body.Close()
+
+		// Read the response body
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil || strings.Contains(string(body), "VS403283: Could not add user") {
+			log.Printf("Encountered error : %v, retrying..", err)
+			time.Sleep(retryDelay)
+			continue
+		}
+
+		log.Printf("Added managed identity to organization:")
+		break
+	}
+	return nil
+}
+
+// getGitTestConfigAzure returns the test config used to setup the git repository
+func getGitTestConfigAzure(outputs map[string]*tfjson.StateOutput) (*gitTestConfig, error) {
+	config := &gitTestConfig{
+		defaultGitTransport:   git.HTTP,
+		gitUsername:           git.DefaultPublicKeyAuthUser,
+		gitPat:                outputs["azure_devops_access_token"].Value.(string),
+		applicationRepository: outputs["git_repo_url"].Value.(string),
+	}
+
+	opts, err := getAuthOpts(config.applicationRepository, map[string][]byte{
+		"password": []byte(config.gitPat),
+		"username": []byte(git.DefaultPublicKeyAuthUser),
+	})
+	if err != nil {
+		return nil, err
+	}
+	config.defaultAuthOpts = opts
+
+	parts := strings.Split(config.applicationRepository, "@")
+	// Check if the URL contains the "@" symbol
+	if len(parts) > 1 {
+		// Reconstruct the URL without the username
+		config.applicationRepositoryWithoutUser = "https://" + parts[1]
+	}
+
+	fmt.Println("URL without username:", config.applicationRepositoryWithoutUser)
+	return config, nil
+}
diff --git a/oci/tests/integration/gcp_test.go b/oci/tests/integration/gcp_test.go
index a92b5791..98e74f73 100644
--- a/oci/tests/integration/gcp_test.go
+++ b/oci/tests/integration/gcp_test.go
@@ -90,3 +90,13 @@ func getWISAAnnotationsGCP(output map[string]*tfjson.StateOutput) (map[string]st
 		gcpIAMAnnotation: saEmail,
 	}, nil
 }
+
+// When implemented, getGitTestConfigGCP would return the git-specific test config for GCP
+func getGitTestConfigGCP(outputs map[string]*tfjson.StateOutput) (*gitTestConfig, error) {
+	return nil, fmt.Errorf("NotImplemented for GCP")
+}
+
+// When implemented, givePermissionsToRepositoryGCP would grant the required permissions to Google cloud source repositories
+func givePermissionsToRepositoryGCP(output map[string]*tfjson.StateOutput) error {
+	return fmt.Errorf("NotImplemented for GCP")
+}
diff --git a/oci/tests/integration/git_test.go b/oci/tests/integration/git_test.go
new file mode 100644
index 00000000..d2605ec6
--- /dev/null
+++ b/oci/tests/integration/git_test.go
@@ -0,0 +1,46 @@
+//go:build integration
+// +build integration
+
+/*
+Copyright 2022 The Flux authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package integration
+
+import (
+	"context"
+	"fmt"
+	"testing"
+)
+
+func TestGitCloneUsingProvider(t *testing.T) {
+	if !enableGit {
+		t.Skip("Skipping test, enable git in env, supported providers ", supportedGitProviders)
+	}
+
+	ctx := context.TODO()
+	tmpDir := t.TempDir()
+
+	setupGitRepository(ctx, tmpDir)
+	t.Run("Git oidc credential test", func(t *testing.T) {
+		args := []string{
+			"-category=git",
+			"-oidc-login=true",
+			fmt.Sprintf("-provider=%s", *targetProvider),
+			fmt.Sprintf("-repo=%s", testGitCfg.applicationRepositoryWithoutUser),
+		}
+		testjobExecutionWithArgs(t, args)
+	})
+}
diff --git a/oci/tests/integration/go.mod b/oci/tests/integration/go.mod
index 3ec4ef63..672d297a 100644
--- a/oci/tests/integration/go.mod
+++ b/oci/tests/integration/go.mod
@@ -1,6 +1,8 @@
 module github.com/fluxcd/pkg/oci/tests/integration
 
-go 1.22.0
+go 1.22.4
+
+toolchain go1.22.5
 
 replace (
 	github.com/fluxcd/pkg/cache => ../../../cache
@@ -8,24 +10,31 @@ replace (
 )
 
 require (
-	github.com/fluxcd/pkg/cache v0.0.1
+	github.com/fluxcd/pkg/auth v0.0.0-00010101000000-000000000000
+	github.com/fluxcd/pkg/cache v0.0.3
+	github.com/fluxcd/pkg/git v0.19.0
+	github.com/fluxcd/pkg/git/gogit v0.19.0
 	github.com/fluxcd/pkg/oci v0.34.0
 	github.com/fluxcd/test-infra/tftestenv v0.0.0-20240110132047-17651823b08c
+	github.com/go-git/go-git/v5 v5.12.0
 	github.com/google/go-containerregistry v0.19.1
 	github.com/hashicorp/terraform-exec v0.20.0
 	github.com/hashicorp/terraform-json v0.19.0
-	github.com/onsi/gomega v1.33.1
-	k8s.io/api v0.30.0
-	k8s.io/apimachinery v0.30.0
-	sigs.k8s.io/controller-runtime v0.18.1
+	github.com/onsi/gomega v1.34.1
+	k8s.io/api v0.31.0
+	k8s.io/apimachinery v0.31.0
+	sigs.k8s.io/controller-runtime v0.19.0
 )
 
 require (
-	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
-	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 // indirect
-	github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
+	dario.cat/mergo v1.0.0 // indirect
+	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 // indirect
+	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
+	github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect
 	github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
-	github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
+	github.com/Masterminds/semver/v3 v3.2.1 // indirect
+	github.com/Microsoft/go-winio v0.6.1 // indirect
+	github.com/ProtonMail/go-crypto v1.0.0 // indirect
 	github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
 	github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
 	github.com/aws/aws-sdk-go-v2/config v1.27.11 // indirect
@@ -43,20 +52,27 @@ require (
 	github.com/aws/smithy-go v1.20.2 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/blang/semver/v4 v4.0.0 // indirect
-	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 	github.com/cloudflare/circl v1.3.7 // indirect
 	github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
+	github.com/cyphar/filepath-securejoin v0.2.4 // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/docker/cli v24.0.9+incompatible // indirect
 	github.com/docker/distribution v2.8.2+incompatible // indirect
 	github.com/docker/docker v24.0.9+incompatible // indirect
 	github.com/docker/docker-credential-helpers v0.7.0 // indirect
 	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+	github.com/emirpasic/gods v1.18.1 // indirect
 	github.com/evanphx/json-patch/v5 v5.9.0 // indirect
-	github.com/fluxcd/cli-utils v0.36.0-flux.7 // indirect
+	github.com/fluxcd/cli-utils v0.36.0-flux.9 // indirect
+	github.com/fluxcd/pkg/ssh v0.13.0 // indirect
+	github.com/fluxcd/pkg/version v0.4.0 // indirect
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
 	github.com/go-errors/errors v1.5.1 // indirect
-	github.com/go-logr/logr v1.4.1 // indirect
+	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
+	github.com/go-git/go-billy/v5 v5.5.0 // indirect
+	github.com/go-logr/logr v1.4.2 // indirect
 	github.com/go-logr/zapr v1.3.0 // indirect
 	github.com/go-openapi/jsonpointer v0.19.6 // indirect
 	github.com/go-openapi/jsonreference v0.20.2 // indirect
@@ -76,10 +92,12 @@ require (
 	github.com/hashicorp/go-version v1.6.0 // indirect
 	github.com/hashicorp/hc-install v0.6.2 // indirect
 	github.com/imdario/mergo v0.3.15 // indirect
+	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/compress v1.17.4 // indirect
+	github.com/kevinburke/ssh_config v1.2.0 // indirect
+	github.com/klauspost/compress v1.17.9 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
@@ -89,45 +107,58 @@ require (
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/opencontainers/go-digest v1.0.0 // indirect
 	github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
+	github.com/pjbgf/sha1cd v0.3.0 // indirect
 	github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
 	github.com/pkg/errors v0.9.1 // indirect
-	github.com/prometheus/client_golang v1.19.0 // indirect
-	github.com/prometheus/client_model v0.5.0 // indirect
-	github.com/prometheus/common v0.48.0 // indirect
-	github.com/prometheus/procfs v0.12.0 // indirect
+	github.com/prometheus/client_golang v1.20.0 // indirect
+	github.com/prometheus/client_model v0.6.1 // indirect
+	github.com/prometheus/common v0.55.0 // indirect
+	github.com/prometheus/procfs v0.15.1 // indirect
+	github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
+	github.com/skeema/knownhosts v1.2.2 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/vbatts/tar-split v0.11.3 // indirect
+	github.com/x448/float16 v0.8.4 // indirect
+	github.com/xanzy/ssh-agent v0.3.3 // indirect
 	github.com/xlab/treeprint v1.2.0 // indirect
 	github.com/zclconf/go-cty v1.14.1 // indirect
 	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/crypto v0.22.0 // indirect
-	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
-	golang.org/x/mod v0.15.0 // indirect
-	golang.org/x/net v0.24.0 // indirect
-	golang.org/x/oauth2 v0.19.0 // indirect
-	golang.org/x/sync v0.7.0 // indirect
-	golang.org/x/sys v0.19.0 // indirect
-	golang.org/x/term v0.19.0 // indirect
-	golang.org/x/text v0.14.0 // indirect
-	golang.org/x/time v0.5.0 // indirect
+	golang.org/x/crypto v0.26.0 // indirect
+	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
+	golang.org/x/mod v0.20.0 // indirect
+	golang.org/x/net v0.28.0 // indirect
+	golang.org/x/oauth2 v0.22.0 // indirect
+	golang.org/x/sync v0.8.0 // indirect
+	golang.org/x/sys v0.24.0 // indirect
+	golang.org/x/term v0.23.0 // indirect
+	golang.org/x/text v0.17.0 // indirect
+	golang.org/x/time v0.6.0 // indirect
+	golang.org/x/tools v0.24.0 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
-	google.golang.org/protobuf v1.33.0 // indirect
+	google.golang.org/protobuf v1.34.2 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
+	gopkg.in/warnings.v0 v0.1.2 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/apiextensions-apiserver v0.30.0 // indirect
-	k8s.io/cli-runtime v0.30.0 // indirect
-	k8s.io/client-go v0.30.0 // indirect
-	k8s.io/klog/v2 v2.120.1 // indirect
+	k8s.io/apiextensions-apiserver v0.31.0 // indirect
+	k8s.io/cli-runtime v0.31.0 // indirect
+	k8s.io/client-go v0.31.0 // indirect
+	k8s.io/klog/v2 v2.130.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
-	k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
+	k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
-	sigs.k8s.io/kustomize/api v0.17.1 // indirect
-	sigs.k8s.io/kustomize/kyaml v0.17.0 // indirect
+	sigs.k8s.io/kustomize/api v0.17.3 // indirect
+	sigs.k8s.io/kustomize/kyaml v0.17.2 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
 	sigs.k8s.io/yaml v1.4.0 // indirect
 )
+
+replace github.com/fluxcd/pkg/auth => github.com/dipti-pai/pkg/auth v0.0.0-20240822170700-a2f84e127913
+
+replace github.com/fluxcd/pkg/git/gogit => github.com/dipti-pai/pkg/git/gogit v0.0.0-20240822170700-a2f84e127913
+
+replace github.com/fluxcd/pkg/git => github.com/dipti-pai/pkg/git v0.0.0-20240822170700-a2f84e127913
diff --git a/oci/tests/integration/go.sum b/oci/tests/integration/go.sum
index 8fc2c40d..52b9fdf7 100644
--- a/oci/tests/integration/go.sum
+++ b/oci/tests/integration/go.sum
@@ -1,12 +1,12 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
 dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc=
 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
@@ -15,12 +15,19 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
 github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
+github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
+github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
+github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
 github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
 github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
-github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
-github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
+github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
+github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
 github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
 github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
 github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
 github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA=
@@ -55,8 +62,8 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM
 github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
 github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
-github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
 github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -76,8 +83,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
-github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
+github.com/dipti-pai/pkg/auth v0.0.0-20240822170700-a2f84e127913 h1:uUaYV/QbxgLW1kYYKhSrrJFYp/D94ogYoRtBRM/Trfk=
+github.com/dipti-pai/pkg/auth v0.0.0-20240822170700-a2f84e127913/go.mod h1:GyfTIyzUHtsVQG0OsetFI4rA9Vinbt0AdFKKYewWm5E=
+github.com/dipti-pai/pkg/git v0.0.0-20240822170700-a2f84e127913 h1:JE4MuxE3P7ctLy9tCies8rsvPcJcAVyhmWTaeb6D4aI=
+github.com/dipti-pai/pkg/git v0.0.0-20240822170700-a2f84e127913/go.mod h1:7+ND7LWwCVRuO0ZAb+TPWQF6M3SObY10VIodFToGW+A=
+github.com/dipti-pai/pkg/git/gogit v0.0.0-20240822170700-a2f84e127913 h1:quDlLeIOI59IeI0WXFJlSJD8QEiNuYgk2OtHhNxquK0=
+github.com/dipti-pai/pkg/git/gogit v0.0.0-20240822170700-a2f84e127913/go.mod h1:enJclTZCS1HLaXeC3zTu16axNLamghes0p48Km/owvY=
 github.com/docker/cli v24.0.9+incompatible h1:OxbimnP/z+qVjDLpq9wbeFU3Nc30XhSe+LkwYQisD50=
 github.com/docker/cli v24.0.9+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
@@ -86,6 +97,8 @@ github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKs
 github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
 github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
+github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M=
+github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5/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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
@@ -98,22 +111,36 @@ github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0
 github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
 github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
 github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
-github.com/fluxcd/cli-utils v0.36.0-flux.7 h1:81zEo/LNmIRWMgtsZy/8L13TMUZHmmJib4gHRvKwVE8=
-github.com/fluxcd/cli-utils v0.36.0-flux.7/go.mod h1:TcfLhvBjtQnqxYMsHQUAEB2c5WJRVuibtas2Izz5ZTs=
+github.com/fluxcd/cli-utils v0.36.0-flux.9 h1:RITKdwIAqT3EFKXl7B91mj6usVjxcy7W8PJZlxqUa84=
+github.com/fluxcd/cli-utils v0.36.0-flux.9/go.mod h1:q6lXQpbAlrZmTB4Qe5oAENkv0y2kwMWcqTMDHrRo2Is=
+github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
+github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo=
+github.com/fluxcd/pkg/gittestserver v0.12.0 h1:QGbIVyje9U6urSAeDw3diKb/5wdA+Cnw1YJN+3Zflaw=
+github.com/fluxcd/pkg/gittestserver v0.12.0/go.mod h1:Eh82e+kzKdhpafnUwR5oCBmxqAqhF5QuCn290AFntPM=
+github.com/fluxcd/pkg/ssh v0.13.0 h1:lPU1Gst8XIz7AU2dhdqVFaaOWd54/O1LZu62vH4JB/s=
+github.com/fluxcd/pkg/ssh v0.13.0/go.mod h1:J9eyirMd4s++tWG4euRRhmcthKX203GPHpzFpH++TP8=
+github.com/fluxcd/pkg/version v0.4.0 h1:3F6oeIZ+ug/f7pALIBhcUhfURel37EPPOn7nsGfsnOg=
+github.com/fluxcd/pkg/version v0.4.0/go.mod h1:izVsSDxac81qWRmpOL9qcxZYx+zAN1ajoP5SidGP6PA=
 github.com/fluxcd/test-infra/tftestenv v0.0.0-20240110132047-17651823b08c h1:Cz+NgW2Y0rNODbwanioXO79dUgm9mzGBfQyp5COvNz4=
 github.com/fluxcd/test-infra/tftestenv v0.0.0-20240110132047-17651823b08c/go.mod h1:liFlLEXgambGVdWSJ4JzbIHf1Vjpp1HwUyPazPIVZug=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
+github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
+github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
 github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
 github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
 github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
 github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
-github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
-github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
-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-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
+github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
+github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
+github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 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-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -123,9 +150,10 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
 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-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
 github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
+github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
@@ -162,8 +190,8 @@ github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDIt
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
-github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
+github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
+github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -204,8 +232,9 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4
 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
-github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
+github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 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=
@@ -223,8 +252,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
 github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
-github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
+github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
+github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
 github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
 github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -238,10 +267,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
-github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g=
-github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
-github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
-github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
+github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
+github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
+github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
+github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
@@ -257,29 +286,30 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-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_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
+github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
 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/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.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
+github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
+github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
+github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
+github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
+github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
 github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
-github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
-github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
-github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
-github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
+github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
+github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
+github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
+github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -287,7 +317,9 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
 github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -297,6 +329,8 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
 github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
 github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=
 github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
+github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
+github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
 github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
 github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
@@ -318,13 +352,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
-golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
+golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
+golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
-golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -332,8 +367,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/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.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
-golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
+golang.org/x/mod v0.20.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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -343,15 +378,16 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
-golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
+golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
+golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
-golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
+golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
+golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -359,13 +395,16 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -376,26 +415,27 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
-golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
+golang.org/x/sys v0.24.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=
 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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
-golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
+golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-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/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
+golang.org/x/time v0.6.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=
@@ -406,8 +446,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 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.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
-golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
+golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
+golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
 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=
@@ -430,9 +470,10 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
 google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
@@ -441,6 +482,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/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=
@@ -451,34 +493,34 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
 gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
-k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
-k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
-k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
-k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
-k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
-k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48=
-k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg=
-k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
-k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
-k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
-k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
-k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
-k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
+k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE=
+k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
+k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
+k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc=
+k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
+k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA=
+k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw=
+k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8=
+k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU=
+k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs=
+k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo=
+k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
+k8s.io/klog/v2 v2.130.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.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk=
-k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI=
-k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
-k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/controller-runtime v0.18.1 h1:RpWbigmuiylbxOCLy0tGnq1cU1qWPwNIQzoJk+QeJx4=
-sigs.k8s.io/controller-runtime v0.18.1/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw=
+k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg=
+k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4=
+k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
+k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
+sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
-sigs.k8s.io/kustomize/api v0.17.1 h1:MYJBOP/yQ3/5tp4/sf6HiiMfNNyO97LmtnirH9SLNr4=
-sigs.k8s.io/kustomize/api v0.17.1/go.mod h1:ffn5491s2EiNrJSmgqcWGzQUVhc/pB0OKNI0HsT/0tA=
-sigs.k8s.io/kustomize/kyaml v0.17.0 h1:G2bWs03V9Ur2PinHLzTUJ8Ded+30SzXZKiO92SRDs3c=
-sigs.k8s.io/kustomize/kyaml v0.17.0/go.mod h1:6lxkYF1Cv9Ic8g/N7I86cvxNc5iinUo/P2vKsHNmpyE=
+sigs.k8s.io/kustomize/api v0.17.3 h1:6GCuHSsxq7fN5yhF2XrC+AAr8gxQwhexgHflOAD/JJU=
+sigs.k8s.io/kustomize/api v0.17.3/go.mod h1:TuDH4mdx7jTfK61SQ/j1QZM/QWR+5rmEiNjvYlhzFhc=
+sigs.k8s.io/kustomize/kyaml v0.17.2 h1:+AzvoJUY0kq4QAhH/ydPHHMRLijtUKiyVyh7fOSshr0=
+sigs.k8s.io/kustomize/kyaml v0.17.2/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
 sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
 sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
diff --git a/oci/tests/integration/repo_list_test.go b/oci/tests/integration/job_test.go
similarity index 64%
rename from oci/tests/integration/repo_list_test.go
rename to oci/tests/integration/job_test.go
index 459cf566..5820340b 100644
--- a/oci/tests/integration/repo_list_test.go
+++ b/oci/tests/integration/job_test.go
@@ -21,8 +21,6 @@ package integration
 
 import (
 	"context"
-	"fmt"
-	"strings"
 	"testing"
 
 	. "github.com/onsi/gomega"
@@ -32,51 +30,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-func TestImageRepositoryListTags(t *testing.T) {
-	for name, repo := range testRepos {
-		t.Run(name, func(t *testing.T) {
-			args := []string{fmt.Sprintf("-repo=%s", repo)}
-			testImageRepositoryListTags(t, args)
-		})
-	}
-}
-
-func TestRepositoryRootLoginListTags(t *testing.T) {
-	for name, repo := range testRepos {
-		t.Run(name, func(t *testing.T) {
-			parts := strings.SplitN(repo, "/", 2)
-			args := []string{
-				fmt.Sprintf("-registry=%s", parts[0]),
-				fmt.Sprintf("-repo=%s", parts[1]),
-			}
-			testImageRepositoryListTags(t, args)
-		})
-	}
-}
-
-func TestOIDCLoginListTags(t *testing.T) {
-	for name, repo := range testRepos {
-		t.Run(name, func(t *testing.T) {
-			// Registry only.
-			parts := strings.SplitN(repo, "/", 2)
-			args := []string{
-				"-oidc-login=true",
-				fmt.Sprintf("-registry=%s", parts[0]),
-				fmt.Sprintf("-repo=%s", parts[1]),
-			}
-			testImageRepositoryListTags(t, args)
-
-			// Registry + repo.
-			args = []string{
-				"-oidc-login=true",
-				fmt.Sprintf("-repo=%s", repo),
-			}
-			testImageRepositoryListTags(t, args)
-		})
-	}
-}
-
-func testImageRepositoryListTags(t *testing.T, args []string) {
+func testjobExecutionWithArgs(t *testing.T, args []string) {
 	g := NewWithT(t)
 	ctx := context.TODO()
 
@@ -107,10 +61,12 @@ func testImageRepositoryListTags(t *testing.T, args []string) {
 	key := client.ObjectKeyFromObject(job)
 
 	g.Expect(testEnv.Client.Create(ctx, job)).To(Succeed())
+
 	defer func() {
 		background := metav1.DeletePropagationBackground
 		g.Expect(testEnv.Client.Delete(ctx, job, &client.DeleteOptions{PropagationPolicy: &background})).To(Succeed())
 	}()
+
 	g.Eventually(func() bool {
 		if err := testEnv.Client.Get(ctx, key, job); err != nil {
 			return false
diff --git a/oci/tests/integration/oci_test.go b/oci/tests/integration/oci_test.go
new file mode 100644
index 00000000..9f4ff7aa
--- /dev/null
+++ b/oci/tests/integration/oci_test.go
@@ -0,0 +1,88 @@
+//go:build integration
+// +build integration
+
+/*
+Copyright 2022 The Flux authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package integration
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func TestOciImageRepositoryListTags(t *testing.T) {
+	if !enableOci {
+		t.Skip("Skipping test as oci is not enabled in env")
+	}
+
+	for name, repo := range testRepos {
+		t.Run(name, func(t *testing.T) {
+			args := []string{
+				"-category=oci",
+				fmt.Sprintf("-repo=%s", repo),
+			}
+			testjobExecutionWithArgs(t, args)
+		})
+	}
+}
+
+func TestOciRepositoryRootLoginListTags(t *testing.T) {
+	if !enableOci {
+		t.Skip("Skipping test as oci is not enabled in env")
+	}
+
+	for name, repo := range testRepos {
+		t.Run(name, func(t *testing.T) {
+			parts := strings.SplitN(repo, "/", 2)
+			args := []string{
+				"-category=oci",
+				fmt.Sprintf("-registry=%s", parts[0]),
+				fmt.Sprintf("-repo=%s", parts[1]),
+			}
+			testjobExecutionWithArgs(t, args)
+		})
+	}
+}
+
+func TestOciOIDCLoginListTags(t *testing.T) {
+	if !enableOci {
+		t.Skip("Skipping test as oci is not enabled in env")
+	}
+
+	for name, repo := range testRepos {
+		t.Run(name, func(t *testing.T) {
+			// Registry only.
+			parts := strings.SplitN(repo, "/", 2)
+			args := []string{
+				"-category=oci",
+				"-oidc-login=true",
+				fmt.Sprintf("-registry=%s", parts[0]),
+				fmt.Sprintf("-repo=%s", parts[1]),
+			}
+			testjobExecutionWithArgs(t, args)
+
+			// Registry + repo.
+			args = []string{
+				"-category=oci",
+				"-oidc-login=true",
+				fmt.Sprintf("-repo=%s", repo),
+			}
+			testjobExecutionWithArgs(t, args)
+		})
+	}
+}
diff --git a/oci/tests/integration/suite_test.go b/oci/tests/integration/suite_test.go
index 2ddc566e..accd691c 100644
--- a/oci/tests/integration/suite_test.go
+++ b/oci/tests/integration/suite_test.go
@@ -37,6 +37,7 @@ import (
 	"k8s.io/apimachinery/pkg/runtime"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 
+	"github.com/fluxcd/pkg/git"
 	"github.com/fluxcd/test-infra/tftestenv"
 )
 
@@ -66,11 +67,20 @@ const (
 )
 
 var (
+	// supportedOciProviders are the providers supported by the test.
+	supportedOciProviders = []string{"aws", "azure", "gcp"}
+
 	// supportedProviders are the providers supported by the test.
-	supportedProviders = []string{"aws", "azure", "gcp"}
+	supportedGitProviders = []string{"azure"}
 
 	// targetProvider is the name of the kubernetes provider to test against.
-	targetProvider = flag.String("provider", "", fmt.Sprintf("name of the provider %v", supportedProviders))
+	targetProvider = flag.String("provider", "", fmt.Sprintf("name of the provider %v for oci, %v for git", supportedOciProviders, supportedGitProviders))
+
+	// enableOci is set to true when oci is enabled in env and a supported provider is specified.
+	enableOci bool
+
+	// enableGit is set to true when oci is enabled in env and a supported provider is specified.
+	enableGit bool
 
 	// retain flag to prevent destroy and retaining the created infrastructure.
 	retain = flag.Bool("retain", false, "retain the infrastructure for debugging purposes")
@@ -106,8 +116,11 @@ var (
 	// identity. It is set from the terraform variable (`TF_VAR_k8s_serviceaccount_name`)
 	wiServiceAccount string
 
-	// enableWI is set to true when the TF_vAR_enable_wi is set to "true", so the tests run for Workload Identtty
+	// enableWI is set to true when the TF_VAR_enable_wi is set to "true", so the tests run for Workload Identtty
 	enableWI bool
+
+	// testGitCfg is a struct containing different variables needed for running git tests.
+	testGitCfg *gitTestConfig
 )
 
 // registryLoginFunc is used to perform registry login against a provider based
@@ -126,6 +139,23 @@ type pushTestImages func(ctx context.Context, localImgs map[string]string, outpu
 // service account when workload identity is used on the cluster.
 type getWISAAnnotations func(output map[string]*tfjson.StateOutput) (map[string]string, error)
 
+// givePermissionsToRepository calls provider specific API to add additional permissions to the git repository/project
+type givePermissionsToRepository func(output map[string]*tfjson.StateOutput) error
+
+// getGitTestConfig gets the configuration for the tests
+type getGitTestConfig func(output map[string]*tfjson.StateOutput) (*gitTestConfig, error)
+
+// gitTestConfig hold different variable that will be needed by the different test functions.
+type gitTestConfig struct {
+	// authentication info for git repositories
+	gitPat                           string
+	gitUsername                      string
+	defaultGitTransport              git.TransportType
+	defaultAuthOpts                  *git.AuthOptions
+	applicationRepository            string
+	applicationRepositoryWithoutUser string
+}
+
 // ProviderConfig is the test configuration of a supported cloud provider to run
 // the tests against.
 type ProviderConfig struct {
@@ -141,6 +171,10 @@ type ProviderConfig struct {
 	// getWISAAnnotations is used to return the provider specific annotations
 	// for the service account when using workload identity.
 	getWISAAnnotations getWISAAnnotations
+	// givePermissionsToRepository is used to give the identity access to the Git repository
+	givePermissionsToRepository givePermissionsToRepository
+	// getGitTestConfig is used to return provider specific test configuration
+	getGitTestConfig getGitTestConfig
 }
 
 var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890")
@@ -159,16 +193,20 @@ func TestMain(m *testing.M) {
 
 	// Validate the provider.
 	if *targetProvider == "" {
-		log.Fatalf("-provider flag must be set to one of %v", supportedProviders)
+		log.Fatalf("-provider flag must be set to one of %v for git or %v for oci", supportedGitProviders, supportedOciProviders)
 	}
-	var supported bool
-	for _, p := range supportedProviders {
-		if p == *targetProvider {
-			supported = true
-		}
+
+	if os.Getenv("TF_VAR_enable_git") == "true" && supportedProvider(*targetProvider, supportedGitProviders) {
+		enableGit = true
 	}
-	if !supported {
-		log.Fatalf("Unsupported provider %q, must be one of %v", *targetProvider, supportedProviders)
+
+	if os.Getenv("TF_VAR_enable_oci") == "true" && supportedProvider(*targetProvider, supportedOciProviders) {
+		enableOci = true
+	}
+
+	enableWI = os.Getenv("TF_VAR_enable_wi") == "true"
+	if enableGit && !enableWI {
+		log.Fatalf("Workload identity must be enabled to run git tests")
 	}
 
 	providerCfg := getProviderConfig(*targetProvider)
@@ -249,12 +287,65 @@ func TestMain(m *testing.M) {
 		panic(fmt.Sprintf("Failed to get the terraform state output: %v", err))
 	}
 
-	testRepos, err = providerCfg.registryLogin(ctx, output)
+	pushAppImage(ctx, providerCfg, output, localImgs)
+	configureAdditionalInfra(ctx, providerCfg, output)
+
+	exitCode = m.Run()
+}
+
+func supportedProvider(targetProvider string, supportedProviders []string) bool {
+	for _, p := range supportedProviders {
+		if p == targetProvider {
+			return true
+		}
+	}
+	return false
+}
+
+// getProviderConfig returns the test configuration of supported providers.
+func getProviderConfig(provider string) *ProviderConfig {
+	switch provider {
+	case "aws":
+		return &ProviderConfig{
+			terraformPath:               terraformPathAWS,
+			registryLogin:               registryLoginECR,
+			pushAppTestImages:           pushAppTestImagesECR,
+			createKubeconfig:            createKubeconfigEKS,
+			getWISAAnnotations:          getWISAAnnotationsAWS,
+			givePermissionsToRepository: givePermissionsToRepositoryAWS,
+			getGitTestConfig:            getGitTestConfigAWS,
+		}
+	case "azure":
+		providerCfg := &ProviderConfig{
+			terraformPath:               terraformPathAzure,
+			registryLogin:               registryLoginACR,
+			pushAppTestImages:           pushAppTestImagesACR,
+			createKubeconfig:            createKubeConfigAKS,
+			getWISAAnnotations:          getWISAAnnotationsAzure,
+			givePermissionsToRepository: givePermissionsToRepositoryAzure,
+			getGitTestConfig:            getGitTestConfigAzure,
+		}
+		return providerCfg
+	case "gcp":
+		return &ProviderConfig{
+			terraformPath:               terraformPathGCP,
+			registryLogin:               registryLoginGCR,
+			pushAppTestImages:           pushAppTestImagesGCR,
+			createKubeconfig:            createKubeconfigGKE,
+			getWISAAnnotations:          getWISAAnnotationsGCP,
+			givePermissionsToRepository: givePermissionsToRepositoryGCP,
+			getGitTestConfig:            getGitTestConfigGCP,
+		}
+	}
+	return nil
+}
+
+func pushAppImage(ctx context.Context, providerCfg *ProviderConfig, tfOutput map[string]*tfjson.StateOutput, localImgs map[string]string) {
+	_, err := providerCfg.registryLogin(ctx, tfOutput)
 	if err != nil {
 		panic(fmt.Sprintf("Failed to log into registry: %v", err))
 	}
-
-	pushedImages, err := providerCfg.pushAppTestImages(ctx, localImgs, output)
+	pushedImages, err := providerCfg.pushAppTestImages(ctx, localImgs, tfOutput)
 	if err != nil {
 		panic(fmt.Sprintf("Failed to push test images: %v", err))
 	}
@@ -268,64 +359,58 @@ func TestMain(m *testing.M) {
 	} else {
 		testAppImage = appImg
 	}
+}
 
-	// Create and push test images.
-	if err := tftestenv.CreateAndPushImages(testRepos, testImageTags); err != nil {
-		panic(fmt.Sprintf("Failed to create and push images: %v", err))
+func configureAdditionalInfra(ctx context.Context, providerCfg *ProviderConfig, tfOutput map[string]*tfjson.StateOutput) {
+	if enableOci {
+		log.Println("OCI is enabled, push oci test images")
+		pushOciTestImages(ctx, providerCfg, tfOutput)
+	}
+
+	if enableGit {
+		var err error
+		log.Println("Git is enabled, get test config")
+		testGitCfg, err = providerCfg.getGitTestConfig(tfOutput)
+
+		if err != nil {
+			panic(fmt.Sprintf("Failed to get Git test config : %v", err))
+		}
+
+		// Call provider specific API to configure permisions for the git repository
+		log.Println("Giving permissions to workload identity to access repository")
+		providerCfg.givePermissionsToRepository(tfOutput)
 	}
 
-	enableWI = os.Getenv("TF_VAR_enable_wi") == "true"
 	if enableWI {
-		log.Println("Running tests with workload identity enabled")
-		annotations, err := providerCfg.getWISAAnnotations(output)
+		log.Println("Workload identity is enabled, initializing service account with annotations")
+		annotations, err := providerCfg.getWISAAnnotations(tfOutput)
 		if err != nil {
 			panic(fmt.Sprintf("Failed to get service account func for workload identity: %v", err))
 		}
 
-		if err := creatWorkloadIDServiceAccount(ctx, annotations); err != nil {
+		if err := createWorkloadIDServiceAccount(ctx, annotations); err != nil {
 			panic(err)
 		}
 	}
-
-	exitCode = m.Run()
 }
 
-// getProviderConfig returns the test configuration of supported providers.
-func getProviderConfig(provider string) *ProviderConfig {
-	switch provider {
-	case "aws":
-		return &ProviderConfig{
-			terraformPath:      terraformPathAWS,
-			registryLogin:      registryLoginECR,
-			pushAppTestImages:  pushAppTestImagesECR,
-			createKubeconfig:   createKubeconfigEKS,
-			getWISAAnnotations: getWISAAnnotationsAWS,
-		}
-	case "azure":
-		return &ProviderConfig{
-			terraformPath:      terraformPathAzure,
-			registryLogin:      registryLoginACR,
-			pushAppTestImages:  pushAppTestImagesACR,
-			createKubeconfig:   createKubeConfigAKS,
-			getWISAAnnotations: getWISAAnnotationsAzure,
-		}
-	case "gcp":
-		return &ProviderConfig{
-			terraformPath:      terraformPathGCP,
-			registryLogin:      registryLoginGCR,
-			pushAppTestImages:  pushAppTestImagesGCR,
-			createKubeconfig:   createKubeconfigGKE,
-			getWISAAnnotations: getWISAAnnotationsGCP,
-		}
+func pushOciTestImages(ctx context.Context, providerCfg *ProviderConfig, tfOutput map[string]*tfjson.StateOutput) {
+	testRepos, err := providerCfg.registryLogin(ctx, tfOutput)
+	if err != nil {
+		panic(fmt.Sprintf("Failed to log into registry: %v", err))
+	}
+
+	// Create and push test images.
+	if err := tftestenv.CreateAndPushImages(testRepos, testImageTags); err != nil {
+		panic(fmt.Sprintf("Failed to create and push images: %v", err))
 	}
-	return nil
 }
 
 // creatWorkloadIDServiceAccount creates the service account (name and namespace specified in the terraform
 // variables) with the annotations passed into the function.
 //
 // TODO: move creation of serviceaccount to terraform
-func creatWorkloadIDServiceAccount(ctx context.Context, annotations map[string]string) error {
+func createWorkloadIDServiceAccount(ctx context.Context, annotations map[string]string) error {
 	wiServiceAccount = os.Getenv(envVarWISAName)
 	wiSANamespace := os.Getenv(envVarWISANamespace)
 	if wiServiceAccount == "" || wiSANamespace == "" {
diff --git a/oci/tests/integration/terraform/azure/main.tf b/oci/tests/integration/terraform/azure/main.tf
index fba04c6d..68b2deb6 100644
--- a/oci/tests/integration/terraform/azure/main.tf
+++ b/oci/tests/integration/terraform/azure/main.tf
@@ -9,7 +9,9 @@ resource "random_pet" "suffix" {
 }
 
 locals {
-  name = "fluxTest${random_pet.suffix.id}"
+  name         = "fluxTest${random_pet.suffix.id}"
+  project_name = "fluxProj${random_pet.suffix.id}"
+  repo_name    = "fluxRepo${random_pet.suffix.id}"
 }
 
 module "aks" {
@@ -55,3 +57,20 @@ resource "azurerm_federated_identity_credential" "federated-identity2" {
 
   depends_on = [module.aks]
 }
+
+provider "azuredevops" {
+  org_service_url       = "https://dev.azure.com/${var.azuredevops_org}"
+  personal_access_token = var.azuredevops_pat
+}
+
+module "devops" {
+  count = var.enable_git ? 1 : 0
+  // TODO: replace source with fluxcd path once PR https://github.com/fluxcd/test-infra/pull/44 is merged
+  source = "git::https://github.com/dipti-pai/test-infra.git//tf-modules/azure/devops"
+  providers = {
+    azuredevops = azuredevops
+  }
+
+  project_name    = local.project_name
+  repository_name = local.repo_name
+}
diff --git a/oci/tests/integration/terraform/azure/outputs.tf b/oci/tests/integration/terraform/azure/outputs.tf
index 02822208..80241036 100644
--- a/oci/tests/integration/terraform/azure/outputs.tf
+++ b/oci/tests/integration/terraform/azure/outputs.tf
@@ -14,3 +14,25 @@ output "acr_registry_id" {
 output "workload_identity_client_id" {
   value = var.enable_wi ? azurerm_user_assigned_identity.wi-id[0].client_id : ""
 }
+
+output "workload_identity_object_id" {
+  value = var.enable_wi ? azurerm_user_assigned_identity.wi-id[0].principal_id : ""
+}
+
+output "azure_devops_organization" {
+  value = var.azuredevops_org
+}
+
+output "azure_devops_access_token" {
+  sensitive = true
+  value     = var.azuredevops_pat
+}
+
+output "git_repo_url" {
+  value = var.enable_git ? module.devops[0].repo_url : ""
+}
+
+output "azure_devops_project_id" {
+  value = var.enable_git ? module.devops[0].project_id : ""
+}
+
diff --git a/oci/tests/integration/terraform/azure/variables.tf b/oci/tests/integration/terraform/azure/variables.tf
index e2a1f205..369be926 100644
--- a/oci/tests/integration/terraform/azure/variables.tf
+++ b/oci/tests/integration/terraform/azure/variables.tf
@@ -25,3 +25,21 @@ variable "enable_wi" {
   default     = false
   description = "Enable workload identity on cluster and create federated identity"
 }
+
+variable "enable_git" {
+  type        = bool
+  default     = false
+  description = "Enable git repository creation"
+}
+
+variable "azuredevops_org" {
+  type        = string
+  description = "Azure Devops organization to create project and git repository"
+  default     = ""
+}
+
+variable "azuredevops_pat" {
+  type        = string
+  description = "Personal access token to create project and repository in azure devops"
+  default     = ""
+}
diff --git a/oci/tests/integration/terraform/azure/version.tf b/oci/tests/integration/terraform/azure/version.tf
new file mode 100644
index 00000000..c0d18ac7
--- /dev/null
+++ b/oci/tests/integration/terraform/azure/version.tf
@@ -0,0 +1,7 @@
+terraform {
+  required_providers {
+    azuredevops = {
+      source  = "microsoft/azuredevops"
+    }
+  }
+}
\ No newline at end of file
diff --git a/oci/tests/integration/testapp/main.go b/oci/tests/integration/testapp/main.go
index 4ca6eb9e..90b3aba2 100644
--- a/oci/tests/integration/testapp/main.go
+++ b/oci/tests/integration/testapp/main.go
@@ -21,6 +21,10 @@ import (
 	"flag"
 	"fmt"
 	"log"
+	"net/url"
+	"os"
+	"path/filepath"
+	"slices"
 	"strings"
 	"time"
 
@@ -31,6 +35,9 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 
 	"github.com/fluxcd/pkg/cache"
+	"github.com/fluxcd/pkg/git"
+	"github.com/fluxcd/pkg/git/gogit"
+	"github.com/fluxcd/pkg/git/repository"
 	"github.com/fluxcd/pkg/oci/auth/login"
 )
 
@@ -41,13 +48,27 @@ import (
 //     is provided separately, e.g. registry: foo.azurecr.io, repo: bar.
 var (
 	registry  = flag.String("registry", "", "registry of the repository")
-	repo      = flag.String("repo", "", "repository to list")
+	repo      = flag.String("repo", "", "git/oci repository to list")
 	oidcLogin = flag.Bool("oidc-login", false, "login with OIDCLogin function")
+	category  = flag.String("category", "", "Test category to run - oci/git")
+	provider  = flag.String("provider", "", "Supported oidc provider - azure")
 )
 
 func main() {
 	flag.Parse()
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	defer cancel()
 	ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
+	if *category == "oci" {
+		checkOci(ctx)
+	} else if *category == "git" {
+		checkGit(ctx)
+	} else {
+		panic("unsupported category")
+	}
+}
+
+func checkOci(ctx context.Context) {
 	cache, err := cache.New(5, cache.StoreObjectKeyFunc,
 		cache.WithCleanupInterval[cache.StoreObject[authn.Authenticator]](1*time.Second))
 	if err != nil {
@@ -59,8 +80,6 @@ func main() {
 		AzureAutoLogin: true,
 		Cache:          cache,
 	}
-	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-	defer cancel()
 
 	if *repo == "" {
 		panic("must provide -repo value")
@@ -106,3 +125,75 @@ func main() {
 	}
 	log.Println("tags:", tags)
 }
+
+func checkGit(ctx context.Context) {
+	u, err := url.Parse(*repo)
+	if err != nil {
+		panic(err)
+	}
+
+	cache, err := cache.New(5, cache.StoreObjectKeyFunc,
+		cache.WithCleanupInterval[cache.StoreObject[git.Credentials]](10*time.Second))
+	if err != nil {
+		panic(err)
+	}
+
+	// Clone twice, first time a new token is fetched, subsequently the cached token is used
+	for i := 0; i < 2; i++ {
+		var authData map[string][]byte
+		authOpts, err := git.NewAuthOptions(*u, authData)
+		if err != nil {
+			panic(err)
+		}
+		authOpts.Cache = cache
+		authOpts.ProviderOpts = &git.ProviderOptions{
+			Name: git.ProviderAzure,
+		}
+		cloneDir, err := os.MkdirTemp("", fmt.Sprint("test-clone-", i))
+		if err != nil {
+			panic(err)
+		}
+		defer os.RemoveAll(cloneDir)
+		c, err := gogit.NewClient(cloneDir, authOpts, gogit.WithSingleBranch(false), gogit.WithDiskStorage())
+		if err != nil {
+			panic(err)
+		}
+
+		_, err = c.Clone(ctx, *repo, repository.CloneConfig{
+			CheckoutStrategy: repository.CheckoutStrategy{
+				Branch: "main",
+			},
+		})
+		if err != nil {
+			panic(err)
+		}
+
+		log.Println("Successfully cloned repository ")
+		// Check file from clone.
+		fPath := filepath.Join(cloneDir, "configmap.yaml")
+		if _, err := os.Stat(fPath); os.IsNotExist(err) {
+			panic("expected artifact configmap.yaml to exist in clone dir")
+		}
+
+		// read the whole file at once
+		contents, err := os.ReadFile(fPath)
+		if err != nil {
+			panic(err)
+		}
+		log.Println(string(contents))
+		keys, err := cache.ListKeys()
+		if err != nil {
+			panic(err)
+		}
+		log.Println("Keys in cache ", i, keys)
+		if !slices.Contains(keys, *repo) {
+			panic("expected cloned repo url to be present in cache")
+		}
+		val, exists, err := cache.GetByKey(*repo)
+		if err != nil || !exists {
+			panic("expected cloned repo url key to be present in cache")
+		}
+		time, err := cache.GetExpiration(val)
+		log.Println("Cache entry expiration ", time, err)
+	}
+}
diff --git a/oci/tests/integration/util_test.go b/oci/tests/integration/util_test.go
new file mode 100644
index 00000000..317767f3
--- /dev/null
+++ b/oci/tests/integration/util_test.go
@@ -0,0 +1,123 @@
+//go:build integration
+// +build integration
+
+/*
+Copyright 2024 The Flux authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package integration
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"io"
+	"net/url"
+	"strings"
+	"time"
+
+	"github.com/fluxcd/pkg/git"
+	"github.com/fluxcd/pkg/git/gogit"
+	"github.com/fluxcd/pkg/git/repository"
+	"github.com/go-git/go-git/v5/plumbing"
+)
+
+const (
+	// default branch to be used when cloning git repositories
+	defaultBranch = "main"
+)
+
+// Clones the git repository specified in the test config and commits a config
+// map yaml into the repository
+func setupGitRepository(ctx context.Context, tmpDir string) {
+	c, err := getRepository(ctx, tmpDir, testGitCfg.applicationRepository, defaultBranch, testGitCfg.defaultAuthOpts)
+
+	if err != nil {
+		panic(err)
+	}
+
+	manifest := `apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: foobar`
+	branchName := defaultBranch
+
+	files := make(map[string]io.Reader)
+	files["configmap.yaml"] = strings.NewReader(manifest)
+	err = commitAndPushAll(ctx, c, files, branchName)
+
+	if err != nil {
+		panic(err)
+	}
+}
+
+// Uses git package to get auth options
+func getAuthOpts(repoURL string, authData map[string][]byte) (*git.AuthOptions, error) {
+	u, err := url.Parse(repoURL)
+	if err != nil {
+		return nil, err
+	}
+
+	return git.NewAuthOptions(*u, authData)
+}
+
+// getRepository clones the specified branch of the git repository
+func getRepository(ctx context.Context, dir, repoURL, branchName string, authOpts *git.AuthOptions) (*gogit.Client, error) {
+	c, err := gogit.NewClient(dir, authOpts, gogit.WithSingleBranch(false), gogit.WithDiskStorage())
+	if err != nil {
+		return nil, err
+	}
+
+	_, err = c.Clone(ctx, repoURL, repository.CloneConfig{
+		CheckoutStrategy: repository.CheckoutStrategy{
+			Branch: branchName,
+		},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return c, nil
+}
+
+// commitAndPushAll creates a commit and pushes the changes using gogit client
+func commitAndPushAll(ctx context.Context, client *gogit.Client, files map[string]io.Reader, branchName string) error {
+	err := client.SwitchBranch(ctx, branchName)
+	if err != nil && !errors.Is(err, plumbing.ErrReferenceNotFound) {
+		return err
+	}
+
+	_, err = client.Commit(git.Commit{
+		Author: git.Signature{
+			Name:  git.DefaultPublicKeyAuthUser,
+			Email: "test@example.com",
+			When:  time.Now(),
+		},
+	}, repository.WithFiles(files))
+	if err != nil {
+		if errors.Is(err, git.ErrNoStagedFiles) {
+			return nil
+		}
+
+		return err
+	}
+
+	err = client.Push(ctx, repository.PushConfig{})
+	if err != nil {
+		return fmt.Errorf("unable to push: %s", err)
+	}
+
+	return nil
+}