diff --git a/.changelog/12747.txt b/.changelog/12747.txt
new file mode 100644
index 00000000000..154eae5af32
--- /dev/null
+++ b/.changelog/12747.txt
@@ -0,0 +1,3 @@
+```release-note: enhancement
+gemini: promoted resources `gemini_code_repository_index`, `gemini_repository_group` to GA.
+```
\ No newline at end of file
diff --git a/google/acctest/bootstrap_test_utils.go b/google/acctest/bootstrap_test_utils.go
index 015b2acacf9..4afd61d715d 100644
--- a/google/acctest/bootstrap_test_utils.go
+++ b/google/acctest/bootstrap_test_utils.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"log"
 	"maps"
+	"net/http"
 	"os"
 	"strings"
 	"testing"
@@ -1426,6 +1427,316 @@ func SetupProjectsAndGetAccessToken(org, billing, pid, service string, config *t
 	return accessToken, nil
 }
 
+// For bootstrapping Developer Connect git repository link
+const SharedGitRepositoryLinkIdPrefix = "tf-bootstrap-git-repository-"
+
+func BootstrapGitRepository(t *testing.T, gitRepositoryLinkId, location, cloneUri, parentConnectionId string) string {
+	gitRepositoryLinkId = SharedGitRepositoryLinkIdPrefix + gitRepositoryLinkId
+
+	config := BootstrapConfig(t)
+	if config == nil {
+		t.Fatal("Could not bootstrap config.")
+	}
+
+	log.Printf("[DEBUG] Getting shared git repository link %q", gitRepositoryLinkId)
+
+	getURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections/%s/gitRepositoryLinks/%s",
+		config.DeveloperConnectBasePath, config.Project, location, parentConnectionId, gitRepositoryLinkId)
+
+	headers := make(http.Header)
+	_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:    config,
+		Method:    "GET",
+		Project:   config.Project,
+		RawURL:    getURL,
+		UserAgent: config.UserAgent,
+		Headers:   headers,
+	})
+
+	if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) {
+		log.Printf("[DEBUG] Git repository link %q not found, bootstrapping", gitRepositoryLinkId)
+		obj := map[string]interface{}{
+			"clone_uri":   cloneUri,
+			"annotations": map[string]string{},
+		}
+
+		postURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections/%s/gitRepositoryLinks?gitRepositoryLinkId=%s",
+			config.DeveloperConnectBasePath, config.Project, location, parentConnectionId, gitRepositoryLinkId)
+		headers := make(http.Header)
+		_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "POST",
+			Project:   config.Project,
+			RawURL:    postURL,
+			UserAgent: config.UserAgent,
+			Body:      obj,
+			Timeout:   20 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Fatalf("Error bootstrapping git repository link %q: %s", gitRepositoryLinkId, err)
+		}
+
+		_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "GET",
+			Project:   config.Project,
+			RawURL:    getURL,
+			UserAgent: config.UserAgent,
+			Timeout:   20 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Fatalf("Error getting git repository link %q: %s", gitRepositoryLinkId, err)
+		}
+	}
+
+	return gitRepositoryLinkId
+}
+
+const SharedConnectionIdPrefix = "tf-bootstrap-developer-connect-connection-"
+
+// For bootstrapping Developer Connect connection resources
+func BootstrapDeveloperConnection(t *testing.T, connectionId, location, tokenResource string, appInstallationId int) string {
+	connectionId = SharedConnectionIdPrefix + connectionId
+
+	config := BootstrapConfig(t)
+	if config == nil {
+		t.Fatal("Could not bootstrap config.")
+	}
+
+	log.Printf("[DEBUG] Getting shared developer connection %q", connectionId)
+
+	getURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections/%s",
+		config.DeveloperConnectBasePath, config.Project, location, connectionId)
+
+	headers := make(http.Header)
+	_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:    config,
+		Method:    "GET",
+		Project:   config.Project,
+		RawURL:    getURL,
+		UserAgent: config.UserAgent,
+		Headers:   headers,
+	})
+
+	if err != nil {
+		log.Printf("[DEBUG] Developer connection %q not found, bootstrapping", connectionId)
+		authorizerCredential := map[string]string{
+			"oauth_token_secret_version": tokenResource,
+		}
+		githubConfig := map[string]interface{}{
+			"github_app":            "DEVELOPER_CONNECT",
+			"app_installation_id":   appInstallationId,
+			"authorizer_credential": authorizerCredential,
+		}
+		obj := map[string]interface{}{
+			"disabled":      false,
+			"github_config": githubConfig,
+		}
+
+		postURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections?connectionId=%s",
+			config.DeveloperConnectBasePath, config.Project, location, connectionId)
+		headers := make(http.Header)
+		_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "POST",
+			Project:   config.Project,
+			RawURL:    postURL,
+			UserAgent: config.UserAgent,
+			Body:      obj,
+			Timeout:   20 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Fatalf("Error bootstrapping developer connection %q: %s", connectionId, err)
+		}
+
+		_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "GET",
+			Project:   config.Project,
+			RawURL:    getURL,
+			UserAgent: config.UserAgent,
+			Timeout:   20 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Fatalf("Error getting developer connection %q: %s", connectionId, err)
+		}
+	}
+
+	return connectionId
+}
+
+const SharedRepositoryGroupPrefix = "tf-bootstrap-repo-group-"
+
+func BoostrapSharedRepositoryGroup(t *testing.T, repositoryGroupId, location, labels, codeRepositoryIndexId, resource string) string {
+	repositoryGroupId = SharedRepositoryGroupPrefix + repositoryGroupId
+
+	config := BootstrapConfig(t)
+	if config == nil {
+		t.Fatal("Could not bootstrap config.")
+	}
+
+	log.Printf("[DEBUG] Getting shared repository group %q", repositoryGroupId)
+
+	getURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s",
+		config.GeminiBasePath, config.Project, location, codeRepositoryIndexId, repositoryGroupId)
+
+	headers := make(http.Header)
+	_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:    config,
+		Method:    "GET",
+		Project:   config.Project,
+		RawURL:    getURL,
+		UserAgent: config.UserAgent,
+		Headers:   headers,
+	})
+	if err != nil {
+		log.Printf("[DEBUG] Repository group %q not found, bootstrapping", codeRepositoryIndexId)
+		repositories := [1]interface{}{map[string]string{
+			"resource":       resource,
+			"branch_pattern": "main",
+		}}
+		postURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups?repositoryGroupId=%s",
+			config.GeminiBasePath, config.Project, location, codeRepositoryIndexId, repositoryGroupId)
+		obj := map[string]interface{}{
+			"repositories": repositories,
+		}
+		if labels != "" {
+			obj["labels"] = labels
+		}
+
+		headers := make(http.Header)
+		for {
+			_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+				Config:    config,
+				Method:    "POST",
+				Project:   config.Project,
+				RawURL:    postURL,
+				UserAgent: config.UserAgent,
+				Body:      obj,
+				Timeout:   20 * time.Minute,
+				Headers:   headers,
+			})
+			if err != nil {
+				if transport_tpg.IsGoogleApiErrorWithCode(err, 409) {
+					errMsg := fmt.Sprintf("%s", err)
+					if strings.Contains(errMsg, "unable to queue the operation") {
+						log.Printf("[DEBUG] Waiting for enqueued operation to finish before creating RepositoryGroup: %#v", obj)
+						time.Sleep(10 * time.Second)
+					} else if strings.Contains(errMsg, "parent resource not in ready state") {
+						log.Printf("[DEBUG] Waiting for parent resource to become active before creating RepositoryGroup: %#v", obj)
+						time.Sleep(1 * time.Minute)
+					} else {
+						t.Fatalf("Error creating RepositoryGroup: %s", err)
+					}
+				} else {
+					t.Fatalf("Error creating repository group %q: %s", repositoryGroupId, err)
+				}
+			} else {
+				break
+			}
+		}
+
+		_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "GET",
+			Project:   config.Project,
+			RawURL:    getURL,
+			UserAgent: config.UserAgent,
+			Timeout:   20 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Errorf("Error getting repository group %q: %s", repositoryGroupId, err)
+		}
+	}
+
+	return repositoryGroupId
+}
+
+// BootstrapSharedCodeRepositoryIndex will create a code repository index
+// if it hasn't been created in the test project.
+//
+// BootstrapSharedCodeRepositoryIndex returns a persistent code repository index
+// for a test or set of tests.
+//
+// Deletion of code repository index takes a few minutes, and creation of it
+// currently takes about half an hour.
+// That is the reason to use the shared code repository indexes for test resources.
+const SharedCodeRepositoryIndexPrefix = "tf-bootstrap-cri-"
+
+func BootstrapSharedCodeRepositoryIndex(t *testing.T, codeRepositoryIndexId, location, kmsKey string, labels map[string]string) string {
+	codeRepositoryIndexId = SharedCodeRepositoryIndexPrefix + codeRepositoryIndexId
+
+	config := BootstrapConfig(t)
+	if config == nil {
+		t.Fatal("Could not bootstrap config.")
+	}
+
+	log.Printf("[DEBUG] Getting shared code repository index %q", codeRepositoryIndexId)
+
+	getURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes/%s", config.GeminiBasePath, config.Project, location, codeRepositoryIndexId)
+
+	headers := make(http.Header)
+	_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:    config,
+		Method:    "GET",
+		Project:   config.Project,
+		RawURL:    getURL,
+		UserAgent: config.UserAgent,
+		Timeout:   90 * time.Minute,
+		Headers:   headers,
+	})
+
+	// CRI not found responds with 404 not found
+	if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) {
+		log.Printf("[DEBUG] Code repository index %q not found, bootstrapping", codeRepositoryIndexId)
+		postURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes?codeRepositoryIndexId=%s", config.GeminiBasePath, config.Project, location, codeRepositoryIndexId)
+		obj := make(map[string]interface{})
+		if labels != nil {
+			obj["labels"] = labels
+		}
+		if kmsKey != "" {
+			obj["kmsKey"] = kmsKey
+		}
+
+		headers := make(http.Header)
+		_, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "POST",
+			Project:   config.Project,
+			RawURL:    postURL,
+			UserAgent: config.UserAgent,
+			Body:      obj,
+			Timeout:   90 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Fatalf("Error creating code repository index %q: %s", codeRepositoryIndexId, err)
+		}
+
+		_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "GET",
+			Project:   config.Project,
+			RawURL:    getURL,
+			UserAgent: config.UserAgent,
+			Timeout:   90 * time.Minute,
+			Headers:   headers,
+		})
+		if err != nil {
+			t.Fatalf("Error getting code repository index %q: %s", codeRepositoryIndexId, err)
+		}
+	} else if err != nil {
+		t.Fatalf("Error getting code repository index %q: %s", codeRepositoryIndexId, err)
+	}
+
+	return codeRepositoryIndexId
+}
+
 const sharedTagKeyPrefix = "tf-bootstrap-tagkey"
 
 func BootstrapSharedTestTagKey(t *testing.T, testId string) string {
diff --git a/google/fwmodels/provider_model.go b/google/fwmodels/provider_model.go
index 3db059300e6..3abd43d0531 100644
--- a/google/fwmodels/provider_model.go
+++ b/google/fwmodels/provider_model.go
@@ -96,6 +96,7 @@ type ProviderModel struct {
 	FilestoreCustomEndpoint                types.String `tfsdk:"filestore_custom_endpoint"`
 	FirebaseAppCheckCustomEndpoint         types.String `tfsdk:"firebase_app_check_custom_endpoint"`
 	FirestoreCustomEndpoint                types.String `tfsdk:"firestore_custom_endpoint"`
+	GeminiCustomEndpoint                   types.String `tfsdk:"gemini_custom_endpoint"`
 	GKEBackupCustomEndpoint                types.String `tfsdk:"gke_backup_custom_endpoint"`
 	GKEHubCustomEndpoint                   types.String `tfsdk:"gke_hub_custom_endpoint"`
 	GKEHub2CustomEndpoint                  types.String `tfsdk:"gke_hub2_custom_endpoint"`
diff --git a/google/fwprovider/framework_provider.go b/google/fwprovider/framework_provider.go
index 66cceae8b4c..4a75771bfe1 100644
--- a/google/fwprovider/framework_provider.go
+++ b/google/fwprovider/framework_provider.go
@@ -556,6 +556,12 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest,
 					transport_tpg.CustomEndpointValidator(),
 				},
 			},
+			"gemini_custom_endpoint": &schema.StringAttribute{
+				Optional: true,
+				Validators: []validator.String{
+					transport_tpg.CustomEndpointValidator(),
+				},
+			},
 			"gke_backup_custom_endpoint": &schema.StringAttribute{
 				Optional: true,
 				Validators: []validator.String{
diff --git a/google/provider/provider.go b/google/provider/provider.go
index 38435922add..ca1595cada1 100644
--- a/google/provider/provider.go
+++ b/google/provider/provider.go
@@ -478,6 +478,11 @@ func Provider() *schema.Provider {
 				Optional:     true,
 				ValidateFunc: transport_tpg.ValidateCustomEndpoint,
 			},
+			"gemini_custom_endpoint": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: transport_tpg.ValidateCustomEndpoint,
+			},
 			"gke_backup_custom_endpoint": {
 				Type:         schema.TypeString,
 				Optional:     true,
@@ -1060,6 +1065,7 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr
 	config.FilestoreBasePath = d.Get("filestore_custom_endpoint").(string)
 	config.FirebaseAppCheckBasePath = d.Get("firebase_app_check_custom_endpoint").(string)
 	config.FirestoreBasePath = d.Get("firestore_custom_endpoint").(string)
+	config.GeminiBasePath = d.Get("gemini_custom_endpoint").(string)
 	config.GKEBackupBasePath = d.Get("gke_backup_custom_endpoint").(string)
 	config.GKEHubBasePath = d.Get("gke_hub_custom_endpoint").(string)
 	config.GKEHub2BasePath = d.Get("gke_hub2_custom_endpoint").(string)
diff --git a/google/provider/provider_mmv1_resources.go b/google/provider/provider_mmv1_resources.go
index aefc5730d00..4aa7e9f5bf9 100644
--- a/google/provider/provider_mmv1_resources.go
+++ b/google/provider/provider_mmv1_resources.go
@@ -70,6 +70,7 @@ import (
 	"github.com/hashicorp/terraform-provider-google/google/services/filestore"
 	"github.com/hashicorp/terraform-provider-google/google/services/firebaseappcheck"
 	"github.com/hashicorp/terraform-provider-google/google/services/firestore"
+	"github.com/hashicorp/terraform-provider-google/google/services/gemini"
 	"github.com/hashicorp/terraform-provider-google/google/services/gkebackup"
 	"github.com/hashicorp/terraform-provider-google/google/services/gkehub"
 	"github.com/hashicorp/terraform-provider-google/google/services/gkehub2"
@@ -398,6 +399,7 @@ var generatedIAMDatasources = map[string]*schema.Resource{
 	"google_dataproc_metastore_federation_iam_policy":        tpgiamresource.DataSourceIamPolicy(dataprocmetastore.DataprocMetastoreFederationIamSchema, dataprocmetastore.DataprocMetastoreFederationIamUpdaterProducer),
 	"google_dataproc_metastore_service_iam_policy":           tpgiamresource.DataSourceIamPolicy(dataprocmetastore.DataprocMetastoreServiceIamSchema, dataprocmetastore.DataprocMetastoreServiceIamUpdaterProducer),
 	"google_dns_managed_zone_iam_policy":                     tpgiamresource.DataSourceIamPolicy(dns.DNSManagedZoneIamSchema, dns.DNSManagedZoneIamUpdaterProducer),
+	"google_gemini_repository_group_iam_policy":              tpgiamresource.DataSourceIamPolicy(gemini.GeminiRepositoryGroupIamSchema, gemini.GeminiRepositoryGroupIamUpdaterProducer),
 	"google_gke_backup_backup_plan_iam_policy":               tpgiamresource.DataSourceIamPolicy(gkebackup.GKEBackupBackupPlanIamSchema, gkebackup.GKEBackupBackupPlanIamUpdaterProducer),
 	"google_gke_backup_restore_plan_iam_policy":              tpgiamresource.DataSourceIamPolicy(gkebackup.GKEBackupRestorePlanIamSchema, gkebackup.GKEBackupRestorePlanIamUpdaterProducer),
 	"google_gke_hub_membership_iam_policy":                   tpgiamresource.DataSourceIamPolicy(gkehub.GKEHubMembershipIamSchema, gkehub.GKEHubMembershipIamUpdaterProducer),
@@ -465,9 +467,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{
 }
 
 // Resources
-// Generated resources: 508
-// Generated IAM resources: 261
-// Total generated resources: 769
+// Generated resources: 510
+// Generated IAM resources: 264
+// Total generated resources: 774
 var generatedResources = map[string]*schema.Resource{
 	"google_folder_access_approval_settings":                                     accessapproval.ResourceAccessApprovalFolderSettings(),
 	"google_organization_access_approval_settings":                               accessapproval.ResourceAccessApprovalOrganizationSettings(),
@@ -881,6 +883,11 @@ var generatedResources = map[string]*schema.Resource{
 	"google_firestore_document":                                                  firestore.ResourceFirestoreDocument(),
 	"google_firestore_field":                                                     firestore.ResourceFirestoreField(),
 	"google_firestore_index":                                                     firestore.ResourceFirestoreIndex(),
+	"google_gemini_code_repository_index":                                        gemini.ResourceGeminiCodeRepositoryIndex(),
+	"google_gemini_repository_group":                                             gemini.ResourceGeminiRepositoryGroup(),
+	"google_gemini_repository_group_iam_binding":                                 tpgiamresource.ResourceIamBinding(gemini.GeminiRepositoryGroupIamSchema, gemini.GeminiRepositoryGroupIamUpdaterProducer, gemini.GeminiRepositoryGroupIdParseFunc),
+	"google_gemini_repository_group_iam_member":                                  tpgiamresource.ResourceIamMember(gemini.GeminiRepositoryGroupIamSchema, gemini.GeminiRepositoryGroupIamUpdaterProducer, gemini.GeminiRepositoryGroupIdParseFunc),
+	"google_gemini_repository_group_iam_policy":                                  tpgiamresource.ResourceIamPolicy(gemini.GeminiRepositoryGroupIamSchema, gemini.GeminiRepositoryGroupIamUpdaterProducer, gemini.GeminiRepositoryGroupIdParseFunc),
 	"google_gke_backup_backup_plan":                                              gkebackup.ResourceGKEBackupBackupPlan(),
 	"google_gke_backup_backup_plan_iam_binding":                                  tpgiamresource.ResourceIamBinding(gkebackup.GKEBackupBackupPlanIamSchema, gkebackup.GKEBackupBackupPlanIamUpdaterProducer, gkebackup.GKEBackupBackupPlanIdParseFunc),
 	"google_gke_backup_backup_plan_iam_member":                                   tpgiamresource.ResourceIamMember(gkebackup.GKEBackupBackupPlanIamSchema, gkebackup.GKEBackupBackupPlanIamUpdaterProducer, gkebackup.GKEBackupBackupPlanIdParseFunc),
diff --git a/google/services/gemini/gemini_operation.go b/google/services/gemini/gemini_operation.go
new file mode 100644
index 00000000000..9a0aa18c727
--- /dev/null
+++ b/google/services/gemini/gemini_operation.go
@@ -0,0 +1,93 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package gemini
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"time"
+
+	"github.com/hashicorp/terraform-provider-google/google/tpgresource"
+	transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
+)
+
+type GeminiOperationWaiter struct {
+	Config    *transport_tpg.Config
+	UserAgent string
+	Project   string
+	tpgresource.CommonOperationWaiter
+}
+
+func (w *GeminiOperationWaiter) QueryOp() (interface{}, error) {
+	if w == nil {
+		return nil, fmt.Errorf("Cannot query operation, it's unset or nil.")
+	}
+	// Returns the proper get.
+	url := fmt.Sprintf("%s%s", w.Config.GeminiBasePath, w.CommonOperationWaiter.Op.Name)
+
+	return transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               w.Config,
+		Method:               "GET",
+		Project:              w.Project,
+		RawURL:               url,
+		UserAgent:            w.UserAgent,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+}
+
+func createGeminiWaiter(config *transport_tpg.Config, op map[string]interface{}, project, activity, userAgent string) (*GeminiOperationWaiter, error) {
+	w := &GeminiOperationWaiter{
+		Config:    config,
+		UserAgent: userAgent,
+		Project:   project,
+	}
+	if err := w.CommonOperationWaiter.SetOp(op); err != nil {
+		return nil, err
+	}
+	return w, nil
+}
+
+// nolint: deadcode,unused
+func GeminiOperationWaitTimeWithResponse(config *transport_tpg.Config, op map[string]interface{}, response *map[string]interface{}, project, activity, userAgent string, timeout time.Duration) error {
+	w, err := createGeminiWaiter(config, op, project, activity, userAgent)
+	if err != nil {
+		return err
+	}
+	if err := tpgresource.OperationWait(w, activity, timeout, config.PollInterval); err != nil {
+		return err
+	}
+	rawResponse := []byte(w.CommonOperationWaiter.Op.Response)
+	if len(rawResponse) == 0 {
+		return errors.New("`resource` not set in operation response")
+	}
+	return json.Unmarshal(rawResponse, response)
+}
+
+func GeminiOperationWaitTime(config *transport_tpg.Config, op map[string]interface{}, project, activity, userAgent string, timeout time.Duration) error {
+	if val, ok := op["name"]; !ok || val == "" {
+		// This was a synchronous call - there is no operation to wait for.
+		return nil
+	}
+	w, err := createGeminiWaiter(config, op, project, activity, userAgent)
+	if err != nil {
+		// If w is nil, the op was synchronous.
+		return err
+	}
+	return tpgresource.OperationWait(w, activity, timeout, config.PollInterval)
+}
diff --git a/google/services/gemini/iam_gemini_repository_group.go b/google/services/gemini/iam_gemini_repository_group.go
new file mode 100644
index 00000000000..6690843a072
--- /dev/null
+++ b/google/services/gemini/iam_gemini_repository_group.go
@@ -0,0 +1,262 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package gemini
+
+import (
+	"fmt"
+
+	"github.com/hashicorp/errwrap"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+	"google.golang.org/api/cloudresourcemanager/v1"
+
+	"github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
+	"github.com/hashicorp/terraform-provider-google/google/tpgresource"
+	transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
+)
+
+var GeminiRepositoryGroupIamSchema = map[string]*schema.Schema{
+	"project": {
+		Type:     schema.TypeString,
+		Computed: true,
+		Optional: true,
+		ForceNew: true,
+	},
+	"location": {
+		Type:     schema.TypeString,
+		Computed: true,
+		Optional: true,
+		ForceNew: true,
+	},
+	"code_repository_index": {
+		Type:     schema.TypeString,
+		Required: true,
+		ForceNew: true,
+	},
+	"repository_group_id": {
+		Type:             schema.TypeString,
+		Required:         true,
+		ForceNew:         true,
+		DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
+	},
+}
+
+type GeminiRepositoryGroupIamUpdater struct {
+	project             string
+	location            string
+	codeRepositoryIndex string
+	repositoryGroupId   string
+	d                   tpgresource.TerraformResourceData
+	Config              *transport_tpg.Config
+}
+
+func GeminiRepositoryGroupIamUpdaterProducer(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (tpgiamresource.ResourceIamUpdater, error) {
+	values := make(map[string]string)
+
+	project, _ := tpgresource.GetProject(d, config)
+	if project != "" {
+		if err := d.Set("project", project); err != nil {
+			return nil, fmt.Errorf("Error setting project: %s", err)
+		}
+	}
+	values["project"] = project
+	location, _ := tpgresource.GetLocation(d, config)
+	if location != "" {
+		if err := d.Set("location", location); err != nil {
+			return nil, fmt.Errorf("Error setting location: %s", err)
+		}
+	}
+	values["location"] = location
+	if v, ok := d.GetOk("code_repository_index"); ok {
+		values["code_repository_index"] = v.(string)
+	}
+
+	if v, ok := d.GetOk("repository_group_id"); ok {
+		values["repository_group_id"] = v.(string)
+	}
+
+	// We may have gotten either a long or short name, so attempt to parse long name if possible
+	m, err := tpgresource.GetImportIdQualifiers([]string{"projects/(?P<project>[^/]+)/locations/(?P<location>[^/]+)/codeRepositoryIndexes/(?P<code_repository_index>[^/]+)/repositoryGroups/(?P<repository_group_id>[^/]+)", "(?P<project>[^/]+)/(?P<location>[^/]+)/(?P<code_repository_index>[^/]+)/(?P<repository_group_id>[^/]+)", "(?P<location>[^/]+)/(?P<code_repository_index>[^/]+)/(?P<repository_group_id>[^/]+)", "(?P<repository_group_id>[^/]+)"}, d, config, d.Get("repository_group_id").(string))
+	if err != nil {
+		return nil, err
+	}
+
+	for k, v := range m {
+		values[k] = v
+	}
+
+	u := &GeminiRepositoryGroupIamUpdater{
+		project:             values["project"],
+		location:            values["location"],
+		codeRepositoryIndex: values["code_repository_index"],
+		repositoryGroupId:   values["repository_group_id"],
+		d:                   d,
+		Config:              config,
+	}
+
+	if err := d.Set("project", u.project); err != nil {
+		return nil, fmt.Errorf("Error setting project: %s", err)
+	}
+	if err := d.Set("location", u.location); err != nil {
+		return nil, fmt.Errorf("Error setting location: %s", err)
+	}
+	if err := d.Set("code_repository_index", u.codeRepositoryIndex); err != nil {
+		return nil, fmt.Errorf("Error setting code_repository_index: %s", err)
+	}
+	if err := d.Set("repository_group_id", u.GetResourceId()); err != nil {
+		return nil, fmt.Errorf("Error setting repository_group_id: %s", err)
+	}
+
+	return u, nil
+}
+
+func GeminiRepositoryGroupIdParseFunc(d *schema.ResourceData, config *transport_tpg.Config) error {
+	values := make(map[string]string)
+
+	project, _ := tpgresource.GetProject(d, config)
+	if project != "" {
+		values["project"] = project
+	}
+
+	location, _ := tpgresource.GetLocation(d, config)
+	if location != "" {
+		values["location"] = location
+	}
+
+	m, err := tpgresource.GetImportIdQualifiers([]string{"projects/(?P<project>[^/]+)/locations/(?P<location>[^/]+)/codeRepositoryIndexes/(?P<code_repository_index>[^/]+)/repositoryGroups/(?P<repository_group_id>[^/]+)", "(?P<project>[^/]+)/(?P<location>[^/]+)/(?P<code_repository_index>[^/]+)/(?P<repository_group_id>[^/]+)", "(?P<location>[^/]+)/(?P<code_repository_index>[^/]+)/(?P<repository_group_id>[^/]+)", "(?P<repository_group_id>[^/]+)"}, d, config, d.Id())
+	if err != nil {
+		return err
+	}
+
+	for k, v := range m {
+		values[k] = v
+	}
+
+	u := &GeminiRepositoryGroupIamUpdater{
+		project:             values["project"],
+		location:            values["location"],
+		codeRepositoryIndex: values["code_repository_index"],
+		repositoryGroupId:   values["repository_group_id"],
+		d:                   d,
+		Config:              config,
+	}
+	if err := d.Set("repository_group_id", u.GetResourceId()); err != nil {
+		return fmt.Errorf("Error setting repository_group_id: %s", err)
+	}
+	d.SetId(u.GetResourceId())
+	return nil
+}
+
+func (u *GeminiRepositoryGroupIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
+	url, err := u.qualifyRepositoryGroupUrl("getIamPolicy")
+	if err != nil {
+		return nil, err
+	}
+
+	project, err := tpgresource.GetProject(u.d, u.Config)
+	if err != nil {
+		return nil, err
+	}
+	var obj map[string]interface{}
+
+	userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent)
+	if err != nil {
+		return nil, err
+	}
+
+	policy, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               u.Config,
+		Method:               "GET",
+		Project:              project,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Body:                 obj,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err)
+	}
+
+	out := &cloudresourcemanager.Policy{}
+	err = tpgresource.Convert(policy, out)
+	if err != nil {
+		return nil, errwrap.Wrapf("Cannot convert a policy to a resource manager policy: {{err}}", err)
+	}
+
+	return out, nil
+}
+
+func (u *GeminiRepositoryGroupIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
+	json, err := tpgresource.ConvertToMap(policy)
+	if err != nil {
+		return err
+	}
+
+	obj := make(map[string]interface{})
+	obj["policy"] = json
+
+	url, err := u.qualifyRepositoryGroupUrl("setIamPolicy")
+	if err != nil {
+		return err
+	}
+	project, err := tpgresource.GetProject(u.d, u.Config)
+	if err != nil {
+		return err
+	}
+
+	userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               u.Config,
+		Method:               "POST",
+		Project:              project,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Body:                 obj,
+		Timeout:              u.d.Timeout(schema.TimeoutCreate),
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err)
+	}
+
+	return nil
+}
+
+func (u *GeminiRepositoryGroupIamUpdater) qualifyRepositoryGroupUrl(methodIdentifier string) (string, error) {
+	urlTemplate := fmt.Sprintf("{{GeminiBasePath}}%s:%s", fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s", u.project, u.location, u.codeRepositoryIndex, u.repositoryGroupId), methodIdentifier)
+	url, err := tpgresource.ReplaceVars(u.d, u.Config, urlTemplate)
+	if err != nil {
+		return "", err
+	}
+	return url, nil
+}
+
+func (u *GeminiRepositoryGroupIamUpdater) GetResourceId() string {
+	return fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s", u.project, u.location, u.codeRepositoryIndex, u.repositoryGroupId)
+}
+
+func (u *GeminiRepositoryGroupIamUpdater) GetMutexKey() string {
+	return fmt.Sprintf("iam-gemini-repositorygroup-%s", u.GetResourceId())
+}
+
+func (u *GeminiRepositoryGroupIamUpdater) DescribeResource() string {
+	return fmt.Sprintf("gemini repositorygroup %q", u.GetResourceId())
+}
diff --git a/google/services/gemini/iam_gemini_repository_group_test.go b/google/services/gemini/iam_gemini_repository_group_test.go
index 40f66691570..6be9446972a 100644
--- a/google/services/gemini/iam_gemini_repository_group_test.go
+++ b/google/services/gemini/iam_gemini_repository_group_test.go
@@ -1,3 +1,277 @@
 // Copyright (c) HashiCorp, Inc.
 // SPDX-License-Identifier: MPL-2.0
 package gemini_test
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
+
+	"github.com/hashicorp/terraform-provider-google/google/acctest"
+	"github.com/hashicorp/terraform-provider-google/google/envvar"
+)
+
+// To run tests locally please replace the `oauth_token_secret_version` with your secret manager version.
+// More details: https://cloud.google.com/developer-connect/docs/connect-github-repo#before_you_begin
+
+func TestAccGeminiRepositoryGroupIamBinding(t *testing.T) {
+	location := "us-central1"
+	codeRepositoryIndexId := acctest.BootstrapSharedCodeRepositoryIndex(t, "basic", location, "", map[string]string{"ccfe_debug_note": "terraform_e2e_should_be_deleted"})
+	developerConnectionId := acctest.BootstrapDeveloperConnection(t, "basic", location, "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1", 54180648)
+	gitRepositoryLinkId := acctest.BootstrapGitRepository(t, "basic", location, "https://github.com/CC-R-github-robot/tf-test.git", developerConnectionId)
+	repositoryGroupId := "tf-test-iam-repository-group-id-" + acctest.RandString(t, 10)
+
+	context := map[string]interface{}{
+		"role":                  "roles/cloudaicompanion.repositoryGroupsUser",
+		"code_repository_index": codeRepositoryIndexId,
+		"location":              location,
+		"project":               envvar.GetTestProjectFromEnv(),
+		"connection_id":         developerConnectionId,
+		"git_link_id":           gitRepositoryLinkId,
+		"repository_group_id":   repositoryGroupId,
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				Config: testAccGeminiRepositoryGroupIamBinding_basic(context),
+			},
+			{
+				ResourceName:      "google_gemini_repository_group_iam_binding.foo",
+				ImportStateId:     fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s roles/cloudaicompanion.repositoryGroupsUser", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), codeRepositoryIndexId, repositoryGroupId),
+				ImportState:       true,
+				ImportStateVerify: true,
+			},
+			{
+				// Test Iam Binding update
+				Config: testAccGeminiRepositoryGroupIamBinding_update(context),
+			},
+			{
+				ResourceName:      "google_gemini_repository_group_iam_binding.foo",
+				ImportStateId:     fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s roles/cloudaicompanion.repositoryGroupsUser", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), codeRepositoryIndexId, repositoryGroupId),
+				ImportState:       true,
+				ImportStateVerify: true,
+			},
+		},
+	})
+}
+
+func TestAccGeminiRepositoryGroupIamMember(t *testing.T) {
+	location := "us-central1"
+	codeRepositoryIndexId := acctest.BootstrapSharedCodeRepositoryIndex(t, "basic", location, "", map[string]string{"ccfe_debug_note": "terraform_e2e_should_be_deleted"})
+	developerConnectionId := acctest.BootstrapDeveloperConnection(t, "basic", location, "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1", 54180648)
+	gitRepositoryLinkId := acctest.BootstrapGitRepository(t, "basic", location, "https://github.com/CC-R-github-robot/tf-test.git", developerConnectionId)
+	repositoryGroupId := "tf-test-iam-repository-group-id-" + acctest.RandString(t, 10)
+
+	context := map[string]interface{}{
+		"role":                  "roles/cloudaicompanion.repositoryGroupsUser",
+		"code_repository_index": codeRepositoryIndexId,
+		"location":              location,
+		"project":               envvar.GetTestProjectFromEnv(),
+		"connection_id":         developerConnectionId,
+		"git_link_id":           gitRepositoryLinkId,
+		"repository_group_id":   repositoryGroupId,
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				// Test Iam Member creation (no update for member, no need to test)
+				Config: testAccGeminiRepositoryGroupIamMember_basic(context),
+			},
+			{
+				ResourceName:      "google_gemini_repository_group_iam_member.foo",
+				ImportStateId:     fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s roles/cloudaicompanion.repositoryGroupsUser user:admin@hashicorptest.com", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), codeRepositoryIndexId, repositoryGroupId),
+				ImportState:       true,
+				ImportStateVerify: true,
+			},
+		},
+	})
+}
+
+func TestAccGeminiRepositoryGroupIamPolicy(t *testing.T) {
+	location := "us-central1"
+	codeRepositoryIndexId := acctest.BootstrapSharedCodeRepositoryIndex(t, "basic", location, "", map[string]string{"ccfe_debug_note": "terraform_e2e_should_be_deleted"})
+	developerConnectionId := acctest.BootstrapDeveloperConnection(t, "basic", location, "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1", 54180648)
+	gitRepositoryLinkId := acctest.BootstrapGitRepository(t, "basic", location, "https://github.com/CC-R-github-robot/tf-test.git", developerConnectionId)
+	repositoryGroupId := "tf-test-iam-repository-group-id-" + acctest.RandString(t, 10)
+
+	context := map[string]interface{}{
+		"role":                  "roles/cloudaicompanion.repositoryGroupsUser",
+		"code_repository_index": codeRepositoryIndexId,
+		"location":              location,
+		"project":               envvar.GetTestProjectFromEnv(),
+		"connection_id":         developerConnectionId,
+		"git_link_id":           gitRepositoryLinkId,
+		"repository_group_id":   repositoryGroupId,
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				Config: testAccGeminiRepositoryGroupIamPolicy_basic(context),
+				Check:  resource.TestCheckResourceAttrSet("data.google_gemini_repository_group_iam_policy.foo", "policy_data"),
+			},
+			{
+				ResourceName:      "google_gemini_repository_group_iam_policy.foo",
+				ImportStateId:     fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), codeRepositoryIndexId, repositoryGroupId),
+				ImportState:       true,
+				ImportStateVerify: true,
+			},
+			{
+				Config: testAccGeminiRepositoryGroupIamPolicy_emptyBinding(context),
+			},
+			{
+				ResourceName:      "google_gemini_repository_group_iam_policy.foo",
+				ImportStateId:     fmt.Sprintf("projects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), codeRepositoryIndexId, repositoryGroupId),
+				ImportState:       true,
+				ImportStateVerify: true,
+			},
+		},
+	})
+}
+
+func testAccGeminiRepositoryGroupIamMember_basic(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_repository_group_iam_member" "foo" {
+  project = "%{project}"
+  location = "%{location}"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = google_gemini_repository_group.example.repository_group_id
+  role = "%{role}"
+  member = "user:admin@hashicorptest.com"
+}
+
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "%{repository_group_id}"
+  repositories {
+    resource = "projects/%{project}/locations/us-central1/connections/%{connection_id}/gitRepositoryLinks/%{git_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+`, context)
+}
+
+func testAccGeminiRepositoryGroupIamPolicy_basic(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+data "google_iam_policy" "foo" {
+  binding {
+    role = "%{role}"
+    members = ["user:admin@hashicorptest.com"]
+  }
+}
+
+resource "google_gemini_repository_group_iam_policy" "foo" {
+  project = "%{project}"
+  location = "%{location}"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = google_gemini_repository_group.example.repository_group_id
+  policy_data = data.google_iam_policy.foo.policy_data
+}
+
+data "google_gemini_repository_group_iam_policy" "foo" {
+  project = "%{project}"
+  location = "%{location}"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = google_gemini_repository_group.example.repository_group_id
+  depends_on = [
+    google_gemini_repository_group_iam_policy.foo
+  ]
+}
+
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "%{repository_group_id}"
+  repositories {
+    resource = "projects/%{project}/locations/us-central1/connections/%{connection_id}/gitRepositoryLinks/%{git_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+`, context)
+}
+
+func testAccGeminiRepositoryGroupIamPolicy_emptyBinding(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+data "google_iam_policy" "foo" {
+}
+
+resource "google_gemini_repository_group_iam_policy" "foo" {
+  project = "%{project}"
+  location = "%{location}"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = google_gemini_repository_group.example.repository_group_id
+  policy_data = data.google_iam_policy.foo.policy_data
+}
+
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "%{repository_group_id}"
+  repositories {
+    resource = "projects/%{project}/locations/us-central1/connections/%{connection_id}/gitRepositoryLinks/%{git_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+`, context)
+}
+
+func testAccGeminiRepositoryGroupIamBinding_basic(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_repository_group_iam_binding" "foo" {
+  project = "%{project}"
+  location = "%{location}"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = google_gemini_repository_group.example.repository_group_id
+  role = "%{role}"
+  members = ["user:admin@hashicorptest.com"]
+}
+
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "%{repository_group_id}"
+  repositories {
+    resource = "projects/%{project}/locations/us-central1/connections/%{connection_id}/gitRepositoryLinks/%{git_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+`, context)
+}
+
+func testAccGeminiRepositoryGroupIamBinding_update(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_repository_group_iam_binding" "foo" {
+  project = "%{project}"
+  location = "%{location}"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = google_gemini_repository_group.example.repository_group_id
+  role = "%{role}"
+  members = ["user:admin@hashicorptest.com", "user:gterraformtest1@gmail.com"]
+}
+
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "%{repository_group_id}"
+  repositories {
+    resource = "projects/%{project}/locations/us-central1/connections/%{connection_id}/gitRepositoryLinks/%{git_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+`, context)
+}
diff --git a/google/services/gemini/resource_gemini_code_repository_index.go b/google/services/gemini/resource_gemini_code_repository_index.go
new file mode 100644
index 00000000000..36df0ee07c0
--- /dev/null
+++ b/google/services/gemini/resource_gemini_code_repository_index.go
@@ -0,0 +1,555 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package gemini
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"reflect"
+	"strings"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+
+	"github.com/hashicorp/terraform-provider-google/google/tpgresource"
+	transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
+)
+
+func ResourceGeminiCodeRepositoryIndex() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceGeminiCodeRepositoryIndexCreate,
+		Read:   resourceGeminiCodeRepositoryIndexRead,
+		Update: resourceGeminiCodeRepositoryIndexUpdate,
+		Delete: resourceGeminiCodeRepositoryIndexDelete,
+
+		Importer: &schema.ResourceImporter{
+			State: resourceGeminiCodeRepositoryIndexImport,
+		},
+
+		Timeouts: &schema.ResourceTimeout{
+			Create: schema.DefaultTimeout(90 * time.Minute),
+			Update: schema.DefaultTimeout(90 * time.Minute),
+			Delete: schema.DefaultTimeout(90 * time.Minute),
+		},
+
+		CustomizeDiff: customdiff.All(
+			tpgresource.SetLabelsDiff,
+			tpgresource.DefaultProviderProject,
+		),
+
+		Schema: map[string]*schema.Schema{
+			"code_repository_index_id": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: `Required. Id of the Code Repository Index.`,
+			},
+			"location": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: `The location of the Code Repository Index, for example 'us-central1'.`,
+			},
+			"kms_key": {
+				Type:     schema.TypeString,
+				Optional: true,
+				ForceNew: true,
+				Description: `Optional. Immutable. Customer-managed encryption key name, in the format
+'projects/*/locations/*/keyRings/*/cryptoKeys/*'.`,
+			},
+			"labels": {
+				Type:     schema.TypeMap,
+				Optional: true,
+				Description: `Optional. Labels as key value pairs.
+
+**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
+Please refer to the field 'effective_labels' for all of the labels present on the resource.`,
+				Elem: &schema.Schema{Type: schema.TypeString},
+			},
+			"create_time": {
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: `Output only. Create time stamp.`,
+			},
+			"effective_labels": {
+				Type:        schema.TypeMap,
+				Computed:    true,
+				Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
+				Elem:        &schema.Schema{Type: schema.TypeString},
+			},
+			"name": {
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: `Immutable. Identifier. Name of Code Repository Index.`,
+			},
+			"state": {
+				Type:     schema.TypeString,
+				Computed: true,
+				Description: `Output only. Code Repository Index instance State.
+Possible values are: 'STATE_UNSPECIFIED', 'CREATING', 'ACTIVE', 'DELETING', 'SUSPENDED'.`,
+			},
+			"terraform_labels": {
+				Type:     schema.TypeMap,
+				Computed: true,
+				Description: `The combination of labels configured directly on the resource
+ and default labels configured on the provider.`,
+				Elem: &schema.Schema{Type: schema.TypeString},
+			},
+			"update_time": {
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: `Output only. Update time stamp.`,
+			},
+			"force_destroy": {
+				Type:        schema.TypeBool,
+				Optional:    true,
+				Description: `If set to true, will allow deletion of the CodeRepositoryIndex even if there are existing RepositoryGroups for the resource. These RepositoryGroups will also be deleted.`,
+				Default:     false,
+			},
+			"project": {
+				Type:     schema.TypeString,
+				Optional: true,
+				Computed: true,
+				ForceNew: true,
+			},
+		},
+		UseJSONNumber: true,
+	}
+}
+
+func resourceGeminiCodeRepositoryIndexCreate(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	obj := make(map[string]interface{})
+	kmsKeyProp, err := expandGeminiCodeRepositoryIndexKmsKey(d.Get("kms_key"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("kms_key"); !tpgresource.IsEmptyValue(reflect.ValueOf(kmsKeyProp)) && (ok || !reflect.DeepEqual(v, kmsKeyProp)) {
+		obj["kmsKey"] = kmsKeyProp
+	}
+	labelsProp, err := expandGeminiCodeRepositoryIndexEffectiveLabels(d.Get("effective_labels"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
+		obj["labels"] = labelsProp
+	}
+
+	lockName, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+	transport_tpg.MutexStore.Lock(lockName)
+	defer transport_tpg.MutexStore.Unlock(lockName)
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes?codeRepositoryIndexId={{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Creating new CodeRepositoryIndex: %#v", obj)
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for CodeRepositoryIndex: %s", err)
+	}
+	billingProject = project
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	headers := make(http.Header)
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               config,
+		Method:               "POST",
+		Project:              billingProject,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Body:                 obj,
+		Timeout:              d.Timeout(schema.TimeoutCreate),
+		Headers:              headers,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return fmt.Errorf("Error creating CodeRepositoryIndex: %s", err)
+	}
+
+	// Store the ID now
+	id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return fmt.Errorf("Error constructing id: %s", err)
+	}
+	d.SetId(id)
+
+	// Use the resource in the operation response to populate
+	// identity fields and d.Id() before read
+	var opRes map[string]interface{}
+	err = GeminiOperationWaitTimeWithResponse(
+		config, res, &opRes, project, "Creating CodeRepositoryIndex", userAgent,
+		d.Timeout(schema.TimeoutCreate))
+	if err != nil {
+		// The resource didn't actually create
+		d.SetId("")
+
+		return fmt.Errorf("Error waiting to create CodeRepositoryIndex: %s", err)
+	}
+
+	if err := d.Set("name", flattenGeminiCodeRepositoryIndexName(opRes["name"], d, config)); err != nil {
+		return err
+	}
+
+	// This may have caused the ID to update - update it if so.
+	id, err = tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return fmt.Errorf("Error constructing id: %s", err)
+	}
+	d.SetId(id)
+
+	log.Printf("[DEBUG] Finished creating CodeRepositoryIndex %q: %#v", d.Id(), res)
+
+	return resourceGeminiCodeRepositoryIndexRead(d, meta)
+}
+
+func resourceGeminiCodeRepositoryIndexRead(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for CodeRepositoryIndex: %s", err)
+	}
+	billingProject = project
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	headers := make(http.Header)
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               config,
+		Method:               "GET",
+		Project:              billingProject,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Headers:              headers,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("GeminiCodeRepositoryIndex %q", d.Id()))
+	}
+
+	// Explicitly set virtual fields to default values if unset
+	if _, ok := d.GetOkExists("force_destroy"); !ok {
+		if err := d.Set("force_destroy", false); err != nil {
+			return fmt.Errorf("Error setting force_destroy: %s", err)
+		}
+	}
+	if err := d.Set("project", project); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+
+	if err := d.Set("update_time", flattenGeminiCodeRepositoryIndexUpdateTime(res["updateTime"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("state", flattenGeminiCodeRepositoryIndexState(res["state"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("labels", flattenGeminiCodeRepositoryIndexLabels(res["labels"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("kms_key", flattenGeminiCodeRepositoryIndexKmsKey(res["kmsKey"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("name", flattenGeminiCodeRepositoryIndexName(res["name"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("create_time", flattenGeminiCodeRepositoryIndexCreateTime(res["createTime"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("terraform_labels", flattenGeminiCodeRepositoryIndexTerraformLabels(res["labels"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+	if err := d.Set("effective_labels", flattenGeminiCodeRepositoryIndexEffectiveLabels(res["labels"], d, config)); err != nil {
+		return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
+	}
+
+	return nil
+}
+
+func resourceGeminiCodeRepositoryIndexUpdate(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for CodeRepositoryIndex: %s", err)
+	}
+	billingProject = project
+
+	obj := make(map[string]interface{})
+	labelsProp, err := expandGeminiCodeRepositoryIndexEffectiveLabels(d.Get("effective_labels"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
+		obj["labels"] = labelsProp
+	}
+
+	lockName, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+	transport_tpg.MutexStore.Lock(lockName)
+	defer transport_tpg.MutexStore.Unlock(lockName)
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Updating CodeRepositoryIndex %q: %#v", d.Id(), obj)
+	headers := make(http.Header)
+	updateMask := []string{}
+
+	if d.HasChange("effective_labels") {
+		updateMask = append(updateMask, "labels")
+	}
+	// updateMask is a URL parameter but not present in the schema, so ReplaceVars
+	// won't set it
+	url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
+	if err != nil {
+		return err
+	}
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	// if updateMask is empty we are not updating anything so skip the post
+	if len(updateMask) > 0 {
+		res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:               config,
+			Method:               "PATCH",
+			Project:              billingProject,
+			RawURL:               url,
+			UserAgent:            userAgent,
+			Body:                 obj,
+			Timeout:              d.Timeout(schema.TimeoutUpdate),
+			Headers:              headers,
+			ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+		})
+
+		if err != nil {
+			return fmt.Errorf("Error updating CodeRepositoryIndex %q: %s", d.Id(), err)
+		} else {
+			log.Printf("[DEBUG] Finished updating CodeRepositoryIndex %q: %#v", d.Id(), res)
+		}
+
+		err = GeminiOperationWaitTime(
+			config, res, project, "Updating CodeRepositoryIndex", userAgent,
+			d.Timeout(schema.TimeoutUpdate))
+
+		if err != nil {
+			return err
+		}
+	}
+
+	return resourceGeminiCodeRepositoryIndexRead(d, meta)
+}
+
+func resourceGeminiCodeRepositoryIndexDelete(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for CodeRepositoryIndex: %s", err)
+	}
+	billingProject = project
+
+	lockName, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+	transport_tpg.MutexStore.Lock(lockName)
+	defer transport_tpg.MutexStore.Unlock(lockName)
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return err
+	}
+
+	var obj map[string]interface{}
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	headers := make(http.Header)
+
+	log.Printf("[DEBUG] Deleting CodeRepositoryIndex %q", d.Id())
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               config,
+		Method:               "DELETE",
+		Project:              billingProject,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Body:                 obj,
+		Timeout:              d.Timeout(schema.TimeoutDelete),
+		Headers:              headers,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return transport_tpg.HandleNotFoundError(err, d, "CodeRepositoryIndex")
+	}
+
+	err = GeminiOperationWaitTime(
+		config, res, project, "Deleting CodeRepositoryIndex", userAgent,
+		d.Timeout(schema.TimeoutDelete))
+
+	if err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Finished deleting CodeRepositoryIndex %q: %#v", d.Id(), res)
+	return nil
+}
+
+func resourceGeminiCodeRepositoryIndexImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
+	config := meta.(*transport_tpg.Config)
+	if err := tpgresource.ParseImportId([]string{
+		"^projects/(?P<project>[^/]+)/locations/(?P<location>[^/]+)/codeRepositoryIndexes/(?P<code_repository_index_id>[^/]+)$",
+		"^(?P<project>[^/]+)/(?P<location>[^/]+)/(?P<code_repository_index_id>[^/]+)$",
+		"^(?P<location>[^/]+)/(?P<code_repository_index_id>[^/]+)$",
+	}, d, config); err != nil {
+		return nil, err
+	}
+
+	// Replace import id for the resource id
+	id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index_id}}")
+	if err != nil {
+		return nil, fmt.Errorf("Error constructing id: %s", err)
+	}
+	d.SetId(id)
+
+	// Explicitly set virtual fields to default values on import
+	if err := d.Set("force_destroy", false); err != nil {
+		return nil, fmt.Errorf("Error setting force_destroy: %s", err)
+	}
+
+	return []*schema.ResourceData{d}, nil
+}
+
+func flattenGeminiCodeRepositoryIndexUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiCodeRepositoryIndexState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiCodeRepositoryIndexLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	if v == nil {
+		return v
+	}
+
+	transformed := make(map[string]interface{})
+	if l, ok := d.GetOkExists("labels"); ok {
+		for k := range l.(map[string]interface{}) {
+			transformed[k] = v.(map[string]interface{})[k]
+		}
+	}
+
+	return transformed
+}
+
+func flattenGeminiCodeRepositoryIndexKmsKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiCodeRepositoryIndexName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiCodeRepositoryIndexCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiCodeRepositoryIndexTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	if v == nil {
+		return v
+	}
+
+	transformed := make(map[string]interface{})
+	if l, ok := d.GetOkExists("terraform_labels"); ok {
+		for k := range l.(map[string]interface{}) {
+			transformed[k] = v.(map[string]interface{})[k]
+		}
+	}
+
+	return transformed
+}
+
+func flattenGeminiCodeRepositoryIndexEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func expandGeminiCodeRepositoryIndexKmsKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandGeminiCodeRepositoryIndexEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
diff --git a/google/services/gemini/resource_gemini_code_repository_index_generated_meta.yaml b/google/services/gemini/resource_gemini_code_repository_index_generated_meta.yaml
new file mode 100644
index 00000000000..e457d0b20fd
--- /dev/null
+++ b/google/services/gemini/resource_gemini_code_repository_index_generated_meta.yaml
@@ -0,0 +1,5 @@
+resource: 'google_gemini_code_repository_index'
+generation_type: 'mmv1'
+api_service_name: 'cloudaicompanion.googleapis.com'
+api_version: 'v1'
+api_resource_type_kind: 'CodeRepositoryIndex'
diff --git a/google/services/gemini/resource_gemini_code_repository_index_test.go b/google/services/gemini/resource_gemini_code_repository_index_test.go
index 40f66691570..633aab169a1 100644
--- a/google/services/gemini/resource_gemini_code_repository_index_test.go
+++ b/google/services/gemini/resource_gemini_code_repository_index_test.go
@@ -1,3 +1,204 @@
 // Copyright (c) HashiCorp, Inc.
 // SPDX-License-Identifier: MPL-2.0
 package gemini_test
+
+import (
+	"fmt"
+	"os"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
+
+	"github.com/hashicorp/terraform-provider-google/google/acctest"
+)
+
+func TestAccGeminiCodeRepositoryIndex_update(t *testing.T) {
+	bootstrappedKMS := acctest.BootstrapKMSKeyInLocation(t, "us-central1")
+	context := map[string]interface{}{
+		"random_suffix": acctest.RandString(t, 10),
+		"project_id":    os.Getenv("GOOGLE_PROJECT"),
+		"kms_key":       bootstrappedKMS.CryptoKey.Name,
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				Config: testAccGeminiCodeRepositoryIndex_basic(context),
+			},
+			{
+				ResourceName:            "google_gemini_code_repository_index.example",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateVerifyIgnore: []string{"code_repository_index_id", "labels", "location", "terraform_labels"},
+			},
+			{
+				Config: testAccGeminiCodeRepositoryIndex_update(context),
+			},
+			{
+				ResourceName:            "google_gemini_code_repository_index.example",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateVerifyIgnore: []string{"code_repository_index_id", "labels", "location", "terraform_labels"},
+			},
+		},
+	})
+}
+
+// TestAccGeminiCodeRepositoryIndex_delete checks if there is no error in deleting CRI along with children resource
+// note: this is an example of a bad usage, where RGs refer to the CRI using a string id, not a reference, as they
+// will be force-removed upon CRI deletion, because the CRI provider uses --force option by default
+// The plan after the _delete function should not be empty due to the child resource in plan
+func TestAccGeminiCodeRepositoryIndex_delete(t *testing.T) {
+	bootstrappedKMS := acctest.BootstrapKMSKeyInLocation(t, "us-central1")
+	randomSuffix := acctest.RandString(t, 10)
+	context := map[string]interface{}{
+		"random_suffix": randomSuffix,
+		"project_id":    os.Getenv("GOOGLE_PROJECT"),
+		"kms_key":       bootstrappedKMS.CryptoKey.Name,
+		"cri_id":        fmt.Sprintf("tf-test-cri-index-delete-example-%s", randomSuffix),
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				Config: testAccGeminiCodeRepositoryIndex_withChildren_basic(context),
+			},
+			{
+				ResourceName:            "google_gemini_code_repository_index.example",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateVerifyIgnore: []string{"code_repository_index_id", "labels", "location", "terraform_labels", "force_destroy"},
+			},
+			{
+				Config:             testAccGeminiCodeRepositoryIndex_withChildren_delete(context),
+				ExpectNonEmptyPlan: true,
+				PlanOnly:           true,
+			},
+		},
+	})
+}
+
+func testAccGeminiCodeRepositoryIndex_withChildren_basic(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_code_repository_index" "example" {
+  labels = {"ccfe_debug_note": "terraform_e2e_should_be_deleted"}
+  location = "us-central1"
+  code_repository_index_id = "%{cri_id}"
+  force_destroy = true
+}
+
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{cri_id}"
+  repository_group_id = "tf-test-rg-repository-group-id-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+  depends_on = [
+    google_gemini_code_repository_index.example
+  ]
+}
+
+resource "google_developer_connect_git_repository_link" "conn" {
+  git_repository_link_id = "tf-test-repository-conn-delete"
+  parent_connection = google_developer_connect_connection.github_conn.connection_id
+  clone_uri = "https://github.com/CC-R-github-robot/tf-test.git"
+  location = "us-central1"
+  annotations = {}
+}
+
+resource "google_developer_connect_connection" "github_conn" {
+  location = "us-central1"
+  connection_id = "tf-test-cloudaicompanion-delete-%{random_suffix}"
+  disabled = false
+
+  github_config {
+    github_app = "DEVELOPER_CONNECT"
+    app_installation_id = 54180648
+
+    authorizer_credential {
+      oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1"
+    }
+  }
+}
+`, context)
+}
+
+// Removed depends_on to not break plan test
+func testAccGeminiCodeRepositoryIndex_withChildren_delete(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{cri_id}"
+  repository_group_id = "tf-test-rg-repository-group-id-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_developer_connect_git_repository_link" "conn" {
+  git_repository_link_id = "tf-test-repository-conn-delete"
+  parent_connection = google_developer_connect_connection.github_conn.connection_id
+  clone_uri = "https://github.com/CC-R-github-robot/tf-test.git"
+  location = "us-central1"
+  annotations = {}
+}
+
+resource "google_developer_connect_connection" "github_conn" {
+  location = "us-central1"
+  connection_id = "tf-test-cloudaicompanion-delete-%{random_suffix}"
+  disabled = false
+
+  github_config {
+    github_app = "DEVELOPER_CONNECT"
+    app_installation_id = 54180648
+
+    authorizer_credential {
+      oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1"
+    }
+  }
+}
+`, context)
+}
+
+func testAccGeminiCodeRepositoryIndex_basic(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_code_repository_index" "example" {
+  labels = {"ccfe_debug_note": "terraform_e2e_should_be_deleted"}
+  location = "us-central1"
+  code_repository_index_id = "tf-test-cri-index-example-%{random_suffix}"
+  kms_key = "%{kms_key}"
+  depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding]
+}
+
+data "google_project" "project" {
+}
+
+resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" {
+  crypto_key_id = "%{kms_key}"
+  role          = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
+  members = [
+    "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloudaicompanion.iam.gserviceaccount.com",
+  ]
+}
+`, context)
+}
+
+func testAccGeminiCodeRepositoryIndex_update(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_code_repository_index" "example" {
+  labels = {"ccfe_debug_note": "terraform_e2e_should_be_deleted", "new_label": "new_val"}
+  location = "us-central1"
+  code_repository_index_id = "tf-test-cri-index-example-%{random_suffix}"
+  kms_key = "%{kms_key}"
+}
+`, context)
+}
diff --git a/google/services/gemini/resource_gemini_repository_group.go b/google/services/gemini/resource_gemini_repository_group.go
new file mode 100644
index 00000000000..c669968409f
--- /dev/null
+++ b/google/services/gemini/resource_gemini_repository_group.go
@@ -0,0 +1,611 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package gemini
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"reflect"
+	"strings"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+
+	"github.com/hashicorp/terraform-provider-google/google/tpgresource"
+	transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
+)
+
+func ResourceGeminiRepositoryGroup() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceGeminiRepositoryGroupCreate,
+		Read:   resourceGeminiRepositoryGroupRead,
+		Update: resourceGeminiRepositoryGroupUpdate,
+		Delete: resourceGeminiRepositoryGroupDelete,
+
+		Importer: &schema.ResourceImporter{
+			State: resourceGeminiRepositoryGroupImport,
+		},
+
+		Timeouts: &schema.ResourceTimeout{
+			Create: schema.DefaultTimeout(30 * time.Minute),
+			Update: schema.DefaultTimeout(30 * time.Minute),
+			Delete: schema.DefaultTimeout(30 * time.Minute),
+		},
+
+		CustomizeDiff: customdiff.All(
+			tpgresource.SetLabelsDiff,
+			tpgresource.DefaultProviderProject,
+		),
+
+		Schema: map[string]*schema.Schema{
+			"code_repository_index": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: `Required. Id of the Code Repository Index.`,
+			},
+			"location": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: `The location of the Code Repository Index, for example 'us-central1'.`,
+			},
+			"repositories": {
+				Type:        schema.TypeList,
+				Required:    true,
+				Description: `Required. List of repositories to group.`,
+				Elem: &schema.Resource{
+					Schema: map[string]*schema.Schema{
+						"branch_pattern": {
+							Type:     schema.TypeString,
+							Required: true,
+							Description: `Required. The Git branch pattern used for indexing in RE2 syntax.
+See https://github.com/google/re2/wiki/syntax for syntax.`,
+						},
+						"resource": {
+							Type:     schema.TypeString,
+							Required: true,
+							Description: `Required. The DeveloperConnect repository full resource name, relative resource name
+or resource URL to be indexed.`,
+						},
+					},
+				},
+			},
+			"repository_group_id": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: `Required. Id of the Repository Group.`,
+			},
+			"labels": {
+				Type:     schema.TypeMap,
+				Optional: true,
+				Description: `Optional. Labels as key value pairs.
+
+**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
+Please refer to the field 'effective_labels' for all of the labels present on the resource.`,
+				Elem: &schema.Schema{Type: schema.TypeString},
+			},
+			"create_time": {
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: `Output only. Create time stamp.`,
+			},
+			"effective_labels": {
+				Type:        schema.TypeMap,
+				Computed:    true,
+				Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
+				Elem:        &schema.Schema{Type: schema.TypeString},
+			},
+			"name": {
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: `Immutable. Identifier. Name of Repository Group.`,
+			},
+			"terraform_labels": {
+				Type:     schema.TypeMap,
+				Computed: true,
+				Description: `The combination of labels configured directly on the resource
+ and default labels configured on the provider.`,
+				Elem: &schema.Schema{Type: schema.TypeString},
+			},
+			"update_time": {
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: `Output only. Update time stamp.`,
+			},
+			"project": {
+				Type:     schema.TypeString,
+				Optional: true,
+				Computed: true,
+				ForceNew: true,
+			},
+		},
+		UseJSONNumber: true,
+	}
+}
+
+func resourceGeminiRepositoryGroupCreate(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	obj := make(map[string]interface{})
+	repositoriesProp, err := expandGeminiRepositoryGroupRepositories(d.Get("repositories"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("repositories"); !tpgresource.IsEmptyValue(reflect.ValueOf(repositoriesProp)) && (ok || !reflect.DeepEqual(v, repositoriesProp)) {
+		obj["repositories"] = repositoriesProp
+	}
+	labelsProp, err := expandGeminiRepositoryGroupEffectiveLabels(d.Get("effective_labels"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
+		obj["labels"] = labelsProp
+	}
+
+	lockName, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}")
+	if err != nil {
+		return err
+	}
+	transport_tpg.MutexStore.Lock(lockName)
+	defer transport_tpg.MutexStore.Unlock(lockName)
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups?repositoryGroupId={{repository_group_id}}")
+	if err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Creating new RepositoryGroup: %#v", obj)
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for RepositoryGroup: %s", err)
+	}
+	billingProject = project
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	headers := make(http.Header)
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               config,
+		Method:               "POST",
+		Project:              billingProject,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Body:                 obj,
+		Timeout:              d.Timeout(schema.TimeoutCreate),
+		Headers:              headers,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return fmt.Errorf("Error creating RepositoryGroup: %s", err)
+	}
+
+	// Store the ID now
+	id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}")
+	if err != nil {
+		return fmt.Errorf("Error constructing id: %s", err)
+	}
+	d.SetId(id)
+
+	// Use the resource in the operation response to populate
+	// identity fields and d.Id() before read
+	var opRes map[string]interface{}
+	err = GeminiOperationWaitTimeWithResponse(
+		config, res, &opRes, project, "Creating RepositoryGroup", userAgent,
+		d.Timeout(schema.TimeoutCreate))
+	if err != nil {
+		// The resource didn't actually create
+		d.SetId("")
+
+		return fmt.Errorf("Error waiting to create RepositoryGroup: %s", err)
+	}
+
+	if err := d.Set("name", flattenGeminiRepositoryGroupName(opRes["name"], d, config)); err != nil {
+		return err
+	}
+
+	// This may have caused the ID to update - update it if so.
+	id, err = tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}")
+	if err != nil {
+		return fmt.Errorf("Error constructing id: %s", err)
+	}
+	d.SetId(id)
+
+	log.Printf("[DEBUG] Finished creating RepositoryGroup %q: %#v", d.Id(), res)
+
+	return resourceGeminiRepositoryGroupRead(d, meta)
+}
+
+func resourceGeminiRepositoryGroupRead(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}")
+	if err != nil {
+		return err
+	}
+
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for RepositoryGroup: %s", err)
+	}
+	billingProject = project
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	headers := make(http.Header)
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               config,
+		Method:               "GET",
+		Project:              billingProject,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Headers:              headers,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("GeminiRepositoryGroup %q", d.Id()))
+	}
+
+	if err := d.Set("project", project); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+
+	if err := d.Set("repositories", flattenGeminiRepositoryGroupRepositories(res["repositories"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+	if err := d.Set("name", flattenGeminiRepositoryGroupName(res["name"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+	if err := d.Set("create_time", flattenGeminiRepositoryGroupCreateTime(res["createTime"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+	if err := d.Set("update_time", flattenGeminiRepositoryGroupUpdateTime(res["updateTime"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+	if err := d.Set("labels", flattenGeminiRepositoryGroupLabels(res["labels"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+	if err := d.Set("terraform_labels", flattenGeminiRepositoryGroupTerraformLabels(res["labels"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+	if err := d.Set("effective_labels", flattenGeminiRepositoryGroupEffectiveLabels(res["labels"], d, config)); err != nil {
+		return fmt.Errorf("Error reading RepositoryGroup: %s", err)
+	}
+
+	return nil
+}
+
+func resourceGeminiRepositoryGroupUpdate(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for RepositoryGroup: %s", err)
+	}
+	billingProject = project
+
+	obj := make(map[string]interface{})
+	repositoriesProp, err := expandGeminiRepositoryGroupRepositories(d.Get("repositories"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("repositories"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, repositoriesProp)) {
+		obj["repositories"] = repositoriesProp
+	}
+	labelsProp, err := expandGeminiRepositoryGroupEffectiveLabels(d.Get("effective_labels"), d, config)
+	if err != nil {
+		return err
+	} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
+		obj["labels"] = labelsProp
+	}
+
+	lockName, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}")
+	if err != nil {
+		return err
+	}
+	transport_tpg.MutexStore.Lock(lockName)
+	defer transport_tpg.MutexStore.Unlock(lockName)
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}")
+	if err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Updating RepositoryGroup %q: %#v", d.Id(), obj)
+	headers := make(http.Header)
+	updateMask := []string{}
+
+	if d.HasChange("repositories") {
+		updateMask = append(updateMask, "repositories")
+	}
+
+	if d.HasChange("effective_labels") {
+		updateMask = append(updateMask, "labels")
+	}
+	// updateMask is a URL parameter but not present in the schema, so ReplaceVars
+	// won't set it
+	url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
+	if err != nil {
+		return err
+	}
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	// if updateMask is empty we are not updating anything so skip the post
+	if len(updateMask) > 0 {
+		res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:               config,
+			Method:               "PATCH",
+			Project:              billingProject,
+			RawURL:               url,
+			UserAgent:            userAgent,
+			Body:                 obj,
+			Timeout:              d.Timeout(schema.TimeoutUpdate),
+			Headers:              headers,
+			ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+		})
+
+		if err != nil {
+			return fmt.Errorf("Error updating RepositoryGroup %q: %s", d.Id(), err)
+		} else {
+			log.Printf("[DEBUG] Finished updating RepositoryGroup %q: %#v", d.Id(), res)
+		}
+
+		err = GeminiOperationWaitTime(
+			config, res, project, "Updating RepositoryGroup", userAgent,
+			d.Timeout(schema.TimeoutUpdate))
+
+		if err != nil {
+			return err
+		}
+	}
+
+	return resourceGeminiRepositoryGroupRead(d, meta)
+}
+
+func resourceGeminiRepositoryGroupDelete(d *schema.ResourceData, meta interface{}) error {
+	config := meta.(*transport_tpg.Config)
+	userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
+	if err != nil {
+		return err
+	}
+
+	billingProject := ""
+
+	project, err := tpgresource.GetProject(d, config)
+	if err != nil {
+		return fmt.Errorf("Error fetching project for RepositoryGroup: %s", err)
+	}
+	billingProject = project
+
+	lockName, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}")
+	if err != nil {
+		return err
+	}
+	transport_tpg.MutexStore.Lock(lockName)
+	defer transport_tpg.MutexStore.Unlock(lockName)
+
+	url, err := tpgresource.ReplaceVars(d, config, "{{GeminiBasePath}}projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}")
+	if err != nil {
+		return err
+	}
+
+	var obj map[string]interface{}
+
+	// err == nil indicates that the billing_project value was found
+	if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
+		billingProject = bp
+	}
+
+	headers := make(http.Header)
+
+	log.Printf("[DEBUG] Deleting RepositoryGroup %q", d.Id())
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:               config,
+		Method:               "DELETE",
+		Project:              billingProject,
+		RawURL:               url,
+		UserAgent:            userAgent,
+		Body:                 obj,
+		Timeout:              d.Timeout(schema.TimeoutDelete),
+		Headers:              headers,
+		ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCodeRepositoryIndexUnreadyError, transport_tpg.IsRepositoryGroupQueueError},
+	})
+	if err != nil {
+		return transport_tpg.HandleNotFoundError(err, d, "RepositoryGroup")
+	}
+
+	err = GeminiOperationWaitTime(
+		config, res, project, "Deleting RepositoryGroup", userAgent,
+		d.Timeout(schema.TimeoutDelete))
+
+	if err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Finished deleting RepositoryGroup %q: %#v", d.Id(), res)
+	return nil
+}
+
+func resourceGeminiRepositoryGroupImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
+	config := meta.(*transport_tpg.Config)
+	if err := tpgresource.ParseImportId([]string{
+		"^projects/(?P<project>[^/]+)/locations/(?P<location>[^/]+)/codeRepositoryIndexes/(?P<code_repository_index>[^/]+)/repositoryGroups/(?P<repository_group_id>[^/]+)$",
+		"^(?P<project>[^/]+)/(?P<location>[^/]+)/(?P<code_repository_index>[^/]+)/(?P<repository_group_id>[^/]+)$",
+		"^(?P<location>[^/]+)/(?P<code_repository_index>[^/]+)/(?P<repository_group_id>[^/]+)$",
+	}, d, config); err != nil {
+		return nil, err
+	}
+
+	// Replace import id for the resource id
+	id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}")
+	if err != nil {
+		return nil, fmt.Errorf("Error constructing id: %s", err)
+	}
+	d.SetId(id)
+
+	return []*schema.ResourceData{d}, nil
+}
+
+func flattenGeminiRepositoryGroupRepositories(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	if v == nil {
+		return v
+	}
+	l := v.([]interface{})
+	transformed := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		original := raw.(map[string]interface{})
+		if len(original) < 1 {
+			// Do not include empty json objects coming back from the api
+			continue
+		}
+		transformed = append(transformed, map[string]interface{}{
+			"resource":       flattenGeminiRepositoryGroupRepositoriesResource(original["resource"], d, config),
+			"branch_pattern": flattenGeminiRepositoryGroupRepositoriesBranchPattern(original["branchPattern"], d, config),
+		})
+	}
+	return transformed
+}
+func flattenGeminiRepositoryGroupRepositoriesResource(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiRepositoryGroupRepositoriesBranchPattern(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiRepositoryGroupName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiRepositoryGroupCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiRepositoryGroupUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func flattenGeminiRepositoryGroupLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	if v == nil {
+		return v
+	}
+
+	transformed := make(map[string]interface{})
+	if l, ok := d.GetOkExists("labels"); ok {
+		for k := range l.(map[string]interface{}) {
+			transformed[k] = v.(map[string]interface{})[k]
+		}
+	}
+
+	return transformed
+}
+
+func flattenGeminiRepositoryGroupTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	if v == nil {
+		return v
+	}
+
+	transformed := make(map[string]interface{})
+	if l, ok := d.GetOkExists("terraform_labels"); ok {
+		for k := range l.(map[string]interface{}) {
+			transformed[k] = v.(map[string]interface{})[k]
+		}
+	}
+
+	return transformed
+}
+
+func flattenGeminiRepositoryGroupEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+	return v
+}
+
+func expandGeminiRepositoryGroupRepositories(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
+	l := v.([]interface{})
+	req := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		if raw == nil {
+			continue
+		}
+		original := raw.(map[string]interface{})
+		transformed := make(map[string]interface{})
+
+		transformedResource, err := expandGeminiRepositoryGroupRepositoriesResource(original["resource"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedResource); val.IsValid() && !tpgresource.IsEmptyValue(val) {
+			transformed["resource"] = transformedResource
+		}
+
+		transformedBranchPattern, err := expandGeminiRepositoryGroupRepositoriesBranchPattern(original["branch_pattern"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedBranchPattern); val.IsValid() && !tpgresource.IsEmptyValue(val) {
+			transformed["branchPattern"] = transformedBranchPattern
+		}
+
+		req = append(req, transformed)
+	}
+	return req, nil
+}
+
+func expandGeminiRepositoryGroupRepositoriesResource(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandGeminiRepositoryGroupRepositoriesBranchPattern(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandGeminiRepositoryGroupEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
diff --git a/google/services/gemini/resource_gemini_repository_group_generated_meta.yaml b/google/services/gemini/resource_gemini_repository_group_generated_meta.yaml
new file mode 100644
index 00000000000..e4d2d6a2326
--- /dev/null
+++ b/google/services/gemini/resource_gemini_repository_group_generated_meta.yaml
@@ -0,0 +1,5 @@
+resource: 'google_gemini_repository_group'
+generation_type: 'mmv1'
+api_service_name: 'cloudaicompanion.googleapis.com'
+api_version: 'v1'
+api_resource_type_kind: 'RepositoryGroup'
diff --git a/google/services/gemini/resource_gemini_repository_group_sweeper.go b/google/services/gemini/resource_gemini_repository_group_sweeper.go
new file mode 100644
index 00000000000..d18ad4440ca
--- /dev/null
+++ b/google/services/gemini/resource_gemini_repository_group_sweeper.go
@@ -0,0 +1,143 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package gemini
+
+import (
+	"context"
+	"log"
+	"strings"
+	"testing"
+
+	"github.com/hashicorp/terraform-provider-google/google/envvar"
+	"github.com/hashicorp/terraform-provider-google/google/sweeper"
+	"github.com/hashicorp/terraform-provider-google/google/tpgresource"
+	transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
+)
+
+func init() {
+	sweeper.AddTestSweepers("GeminiRepositoryGroup", testSweepGeminiRepositoryGroup)
+}
+
+// At the time of writing, the CI only passes us-central1 as the region
+func testSweepGeminiRepositoryGroup(region string) error {
+	resourceName := "GeminiRepositoryGroup"
+	log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName)
+
+	config, err := sweeper.SharedConfigForRegion(region)
+	if err != nil {
+		log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err)
+		return err
+	}
+
+	err = config.LoadAndValidate(context.Background())
+	if err != nil {
+		log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err)
+		return err
+	}
+
+	t := &testing.T{}
+	billingId := envvar.GetTestBillingAccountFromEnv(t)
+
+	// Setup variables to replace in list template
+	d := &tpgresource.ResourceDataMock{
+		FieldsInSchema: map[string]interface{}{
+			"project":         config.Project,
+			"region":          region,
+			"location":        region,
+			"zone":            "-",
+			"billing_account": billingId,
+		},
+	}
+
+	listTemplate := strings.Split("https://cloudaicompanion.googleapis.com/v1/projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups", "?")[0]
+	listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate)
+	if err != nil {
+		log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err)
+		return nil
+	}
+
+	res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+		Config:    config,
+		Method:    "GET",
+		Project:   config.Project,
+		RawURL:    listUrl,
+		UserAgent: config.UserAgent,
+	})
+	if err != nil {
+		log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err)
+		return nil
+	}
+
+	resourceList, ok := res["repositoryGroups"]
+	if !ok {
+		log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.")
+		return nil
+	}
+
+	rl := resourceList.([]interface{})
+
+	log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName)
+	// Keep count of items that aren't sweepable for logging.
+	nonPrefixCount := 0
+	for _, ri := range rl {
+		obj := ri.(map[string]interface{})
+		var name string
+		// Id detected in the delete URL, attempt to use id.
+		if obj["id"] != nil {
+			name = tpgresource.GetResourceNameFromSelfLink(obj["id"].(string))
+		} else if obj["name"] != nil {
+			name = tpgresource.GetResourceNameFromSelfLink(obj["name"].(string))
+		} else {
+			log.Printf("[INFO][SWEEPER_LOG] %s resource name and id were nil", resourceName)
+			return nil
+		}
+		// Skip resources that shouldn't be sweeped
+		if !sweeper.IsSweepableTestResource(name) {
+			nonPrefixCount++
+			continue
+		}
+
+		deleteTemplate := "https://cloudaicompanion.googleapis.com/v1/projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}"
+		deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate)
+		if err != nil {
+			log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err)
+			return nil
+		}
+		deleteUrl = deleteUrl + name
+
+		// Don't wait on operations as we may have a lot to delete
+		_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
+			Config:    config,
+			Method:    "DELETE",
+			Project:   config.Project,
+			RawURL:    deleteUrl,
+			UserAgent: config.UserAgent,
+		})
+		if err != nil {
+			log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err)
+		} else {
+			log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name)
+		}
+	}
+
+	if nonPrefixCount > 0 {
+		log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount)
+	}
+
+	return nil
+}
diff --git a/google/services/gemini/resource_gemini_repository_group_test.go b/google/services/gemini/resource_gemini_repository_group_test.go
index 40f66691570..7e6ed392f52 100644
--- a/google/services/gemini/resource_gemini_repository_group_test.go
+++ b/google/services/gemini/resource_gemini_repository_group_test.go
@@ -1,3 +1,235 @@
 // Copyright (c) HashiCorp, Inc.
 // SPDX-License-Identifier: MPL-2.0
 package gemini_test
+
+import (
+	"os"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
+
+	"github.com/hashicorp/terraform-provider-google/google/acctest"
+)
+
+// To run tests locally please replace the `oauth_token_secret_version` with your secret manager version.
+// More details: https://cloud.google.com/developer-connect/docs/connect-github-repo#before_you_begin
+
+func TestAccGeminiRepositoryGroup_update(t *testing.T) {
+	codeRepositoryIndexId := acctest.BootstrapSharedCodeRepositoryIndex(t, "basic-rg-test", "us-central1", "", map[string]string{"ccfe_debug_note": "terraform_e2e_should_be_deleted"})
+	context := map[string]interface{}{
+		"random_suffix":         acctest.RandString(t, 10),
+		"project_id":            os.Getenv("GOOGLE_PROJECT"),
+		"code_repository_index": codeRepositoryIndexId,
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				Config: testAccGeminiRepositoryGroup_basic(context),
+			},
+			{
+				ResourceName:            "google_gemini_repository_group.example",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateVerifyIgnore: []string{"code_repository_index", "labels", "location", "repository_group_id", "terraform_labels"},
+			},
+			{
+				Config: testAccGeminiRepositoryGroup_update(context),
+			},
+			{
+				ResourceName:            "google_gemini_repository_group.example",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateVerifyIgnore: []string{"code_repository_index", "labels", "location", "repository_group_id", "terraform_labels"},
+			},
+		},
+	})
+}
+
+func TestAccGeminiRepositoryGroup_noBootstrap(t *testing.T) {
+	context := map[string]interface{}{
+		"random_suffix": acctest.RandString(t, 10),
+		"project_id":    os.Getenv("GOOGLE_PROJECT"),
+	}
+
+	acctest.VcrTest(t, resource.TestCase{
+		PreCheck:                 func() { acctest.AccTestPreCheck(t) },
+		ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
+		Steps: []resource.TestStep{
+			{
+				Config: testAccGeminiRepositoryGroup_noBootstrap(context),
+			},
+			{
+				ResourceName:            "google_gemini_repository_group.example_e",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateVerifyIgnore: []string{"code_repository_index", "labels", "location", "repository_group_id", "terraform_labels"},
+			},
+		},
+	})
+}
+
+func testAccGeminiRepositoryGroup_basic(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "tf-test-rg-repository-group-id-%{random_suffix}" 
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_developer_connect_git_repository_link" "conn" {
+  git_repository_link_id = "tf-test-repository-conn"
+  parent_connection = google_developer_connect_connection.github_conn.connection_id
+  clone_uri = "https://github.com/CC-R-github-robot/tf-test.git"
+  location = "us-central1"
+  annotations = {}
+}
+
+resource "google_developer_connect_connection" "github_conn" {
+  location = "us-central1"
+  connection_id = "tf-test-cloudaicompanion2-%{random_suffix}"
+  disabled = false
+
+  github_config {
+    github_app = "DEVELOPER_CONNECT"
+    app_installation_id = 54180648
+
+    authorizer_credential {
+      oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1"
+    }
+  }
+}
+`, context)
+}
+func testAccGeminiRepositoryGroup_update(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_repository_group" "example" {
+  location = "us-central1"
+  code_repository_index = "%{code_repository_index}"
+  repository_group_id = "tf-test-rg-repository-group-id-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1", "label2": "value2"}
+}
+
+resource "google_developer_connect_git_repository_link" "conn" {
+  git_repository_link_id = "tf-test-repository-conn"
+  parent_connection = google_developer_connect_connection.github_conn.connection_id
+  clone_uri = "https://github.com/CC-R-github-robot/tf-test.git"
+  location = "us-central1"
+  annotations = {}
+}
+
+resource "google_developer_connect_connection" "github_conn" {
+  location = "us-central1"
+  connection_id = "tf-test-cloudaicompanion3-%{random_suffix}"
+  disabled = false
+
+  github_config {
+    github_app = "DEVELOPER_CONNECT"
+    app_installation_id = 54180648
+
+    authorizer_credential {
+      oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1"
+    }
+  }
+}
+`, context)
+}
+
+func testAccGeminiRepositoryGroup_noBootstrap(context map[string]interface{}) string {
+	return acctest.Nprintf(`
+resource "google_gemini_code_repository_index" "cri" {
+  labels = {"ccfe_debug_note": "terraform_e2e_should_be_deleted"}
+  location = "us-central1"
+  code_repository_index_id = "tf-test-rg-index-example-%{random_suffix}"
+}
+
+resource "google_gemini_repository_group" "example_a" {
+  location = "us-central1"
+  code_repository_index = google_gemini_code_repository_index.cri.code_repository_index_id
+  repository_group_id = "tf-test-rg-nb-repository-group-id1-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_gemini_repository_group" "example_b" {
+  location = "us-central1"
+  code_repository_index = google_gemini_code_repository_index.cri.code_repository_index_id
+  repository_group_id = "tf-test-rg-nb-repository-group-id2-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_gemini_repository_group" "example_c" {
+  location = "us-central1"
+  code_repository_index = google_gemini_code_repository_index.cri.code_repository_index_id
+  repository_group_id = "tf-test-rg-nb-repository-group-id3-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_gemini_repository_group" "example_d" {
+  location = "us-central1"
+  code_repository_index = google_gemini_code_repository_index.cri.code_repository_index_id
+  repository_group_id = "tf-test-rg-nb-repository-group-id4-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_gemini_repository_group" "example_e" {
+  location = "us-central1"
+  code_repository_index = google_gemini_code_repository_index.cri.code_repository_index_id
+  repository_group_id = "tf-test-rg-nb-repository-group-id5-%{random_suffix}"
+  repositories {
+    resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}"
+    branch_pattern = "main"
+  }
+  labels = {"label1": "value1"}
+}
+
+resource "google_developer_connect_git_repository_link" "conn" {
+  git_repository_link_id = "tf-test-repository-conn"
+  parent_connection = google_developer_connect_connection.github_conn.connection_id
+  clone_uri = "https://github.com/CC-R-github-robot/tf-test.git"
+  location = "us-central1"
+  annotations = {}
+}
+
+resource "google_developer_connect_connection" "github_conn" {
+  location = "us-central1"
+  connection_id = "tf-test-cloudaicompanion1-%{random_suffix}"
+  disabled = false
+
+  github_config {
+    github_app = "DEVELOPER_CONNECT"
+    app_installation_id = 54180648
+
+    authorizer_credential {
+      oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1"
+    }
+  }
+}
+`, context)
+}
diff --git a/google/sweeper/gcp_sweeper_test.go b/google/sweeper/gcp_sweeper_test.go
index 752ac723ff8..942b7a71fab 100644
--- a/google/sweeper/gcp_sweeper_test.go
+++ b/google/sweeper/gcp_sweeper_test.go
@@ -72,6 +72,7 @@ import (
 	_ "github.com/hashicorp/terraform-provider-google/google/services/filestore"
 	_ "github.com/hashicorp/terraform-provider-google/google/services/firebaseappcheck"
 	_ "github.com/hashicorp/terraform-provider-google/google/services/firestore"
+	_ "github.com/hashicorp/terraform-provider-google/google/services/gemini"
 	_ "github.com/hashicorp/terraform-provider-google/google/services/gkebackup"
 	_ "github.com/hashicorp/terraform-provider-google/google/services/gkehub"
 	_ "github.com/hashicorp/terraform-provider-google/google/services/gkehub2"
diff --git a/google/transport/config.go b/google/transport/config.go
index 8cd361d9f30..71c5a886814 100644
--- a/google/transport/config.go
+++ b/google/transport/config.go
@@ -254,6 +254,7 @@ type Config struct {
 	FilestoreBasePath                string
 	FirebaseAppCheckBasePath         string
 	FirestoreBasePath                string
+	GeminiBasePath                   string
 	GKEBackupBasePath                string
 	GKEHubBasePath                   string
 	GKEHub2BasePath                  string
@@ -404,6 +405,7 @@ const EssentialContactsBasePathKey = "EssentialContacts"
 const FilestoreBasePathKey = "Filestore"
 const FirebaseAppCheckBasePathKey = "FirebaseAppCheck"
 const FirestoreBasePathKey = "Firestore"
+const GeminiBasePathKey = "Gemini"
 const GKEBackupBasePathKey = "GKEBackup"
 const GKEHubBasePathKey = "GKEHub"
 const GKEHub2BasePathKey = "GKEHub2"
@@ -548,6 +550,7 @@ var DefaultBasePaths = map[string]string{
 	FilestoreBasePathKey:                "https://file.googleapis.com/v1/",
 	FirebaseAppCheckBasePathKey:         "https://firebaseappcheck.googleapis.com/v1/",
 	FirestoreBasePathKey:                "https://firestore.googleapis.com/v1/",
+	GeminiBasePathKey:                   "https://cloudaicompanion.googleapis.com/v1/",
 	GKEBackupBasePathKey:                "https://gkebackup.googleapis.com/v1/",
 	GKEHubBasePathKey:                   "https://gkehub.googleapis.com/v1/",
 	GKEHub2BasePathKey:                  "https://gkehub.googleapis.com/v1/",
@@ -1027,6 +1030,11 @@ func SetEndpointDefaults(d *schema.ResourceData) error {
 			"GOOGLE_FIRESTORE_CUSTOM_ENDPOINT",
 		}, DefaultBasePaths[FirestoreBasePathKey]))
 	}
+	if d.Get("gemini_custom_endpoint") == "" {
+		d.Set("gemini_custom_endpoint", MultiEnvDefault([]string{
+			"GOOGLE_GEMINI_CUSTOM_ENDPOINT",
+		}, DefaultBasePaths[GeminiBasePathKey]))
+	}
 	if d.Get("gke_backup_custom_endpoint") == "" {
 		d.Set("gke_backup_custom_endpoint", MultiEnvDefault([]string{
 			"GOOGLE_GKE_BACKUP_CUSTOM_ENDPOINT",
@@ -2338,6 +2346,7 @@ func ConfigureBasePaths(c *Config) {
 	c.FilestoreBasePath = DefaultBasePaths[FilestoreBasePathKey]
 	c.FirebaseAppCheckBasePath = DefaultBasePaths[FirebaseAppCheckBasePathKey]
 	c.FirestoreBasePath = DefaultBasePaths[FirestoreBasePathKey]
+	c.GeminiBasePath = DefaultBasePaths[GeminiBasePathKey]
 	c.GKEBackupBasePath = DefaultBasePaths[GKEBackupBasePathKey]
 	c.GKEHubBasePath = DefaultBasePaths[GKEHubBasePathKey]
 	c.GKEHub2BasePath = DefaultBasePaths[GKEHub2BasePathKey]
diff --git a/website/docs/d/gemini_repository_group_iam_policy.html.markdown b/website/docs/d/gemini_repository_group_iam_policy.html.markdown
index 291c1d66362..aa031163e13 100644
--- a/website/docs/d/gemini_repository_group_iam_policy.html.markdown
+++ b/website/docs/d/gemini_repository_group_iam_policy.html.markdown
@@ -20,15 +20,12 @@ description: |-
 
 # `google_gemini_repository_group_iam_policy`
 Retrieves the current IAM policy data for repositorygroup
-~> **Warning:** This datasource is in beta, and should be used with the terraform-provider-google-beta provider.
-See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources.
 
 
 ## example
 
 ```hcl
 data "google_gemini_repository_group_iam_policy" "policy" {
-  provider = google-beta
   project = google_gemini_repository_group.example.project
   location = google_gemini_repository_group.example.location
   code_repository_index = google_gemini_repository_group.example.code_repository_index
diff --git a/website/docs/r/gemini_code_repository_index.html.markdown b/website/docs/r/gemini_code_repository_index.html.markdown
index 309c9cd722e..b245517202e 100644
--- a/website/docs/r/gemini_code_repository_index.html.markdown
+++ b/website/docs/r/gemini_code_repository_index.html.markdown
@@ -21,18 +21,20 @@ description: |-
 
 The resource for managing Code Repository Index for Gemini Code Assist.
 
-~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider.
-See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources.
 
+To get more information about CodeRepositoryIndex, see:
+
+* [API documentation](https://cloud.google.com/gemini/docs/api/reference/rest/v1/projects.locations.codeRepositoryIndexes)
+* How-to Guides
+    * [Gemini Code Assist overview](https://cloud.google.com/gemini/docs/codeassist/overview)
 
 ## Example Usage - Gemini Code Repository Index Basic
 
 
 ```hcl
 resource "google_gemini_code_repository_index" "example" {
-  provider = google-beta
   location = "us-central1"
-  code_repository_index_id = ""
+  code_repository_index_id = "code-repository-index-example"
   kms_key = "projects/projectExample/locations/locationExample/keyRings/keyRingExample/cryptoKeys/cryptoKeyExample"
 }
 ```
@@ -63,7 +65,7 @@ The following arguments are supported:
 * `kms_key` -
   (Optional)
   Optional. Immutable. Customer-managed encryption key name, in the format
-  projects/*/locations/*/keyRings/*/cryptoKeys/*.
+  `projects/*/locations/*/keyRings/*/cryptoKeys/*`.
 
 * `project` - (Optional) The ID of the project in which the resource belongs.
     If it is not provided, the provider project is used.
@@ -81,12 +83,7 @@ In addition to the arguments listed above, the following computed attributes are
 
 * `state` -
   Output only. Code Repository Index instance State.
-  Possible values:
-  STATE_UNSPECIFIED
-  CREATING
-  ACTIVE
-  DELETING
-  SUSPENDED
+  Possible values are: `STATE_UNSPECIFIED`, `CREATING`, `ACTIVE`, `DELETING`, `SUSPENDED`.
 
 * `name` -
   Immutable. Identifier. Name of Code Repository Index.
diff --git a/website/docs/r/gemini_repository_group.html.markdown b/website/docs/r/gemini_repository_group.html.markdown
index b25dfbb06c2..00083aa50d2 100644
--- a/website/docs/r/gemini_repository_group.html.markdown
+++ b/website/docs/r/gemini_repository_group.html.markdown
@@ -21,19 +21,19 @@ description: |-
 
 The resource for managing Repository Group for Gemini Code Assist.
 
-~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider.
-See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources.
 
+To get more information about RepositoryGroup, see:
+
+* [API documentation](https://cloud.google.com/gemini/docs/api/reference/rest/v1/projects.locations.codeRepositoryIndexes.repositoryGroups)
 
 ## Example Usage - Gemini Repository Group Basic
 
 
 ```hcl
 resource "google_gemini_repository_group" "example" {
-  provider = google-beta
   location = "us-central1"
-  code_repository_index = "%{cri_id}"
-  repository_group_id = "gen-repository-group-"
+  code_repository_index = "example-cri"
+  repository_group_id = "example-repository-group"
   repositories {
     resource = "projects/example-project/locations/us-central1/connections/example-connection/gitRepositoryLinks/example-repo"
     branch_pattern = "main"
@@ -49,7 +49,7 @@ The following arguments are supported:
 
 * `repositories` -
   (Required)
-  Required. List of repositories to group
+  Required. List of repositories to group.
   Structure is [documented below](#nested_repositories).
 
 * `location` -
@@ -82,7 +82,7 @@ The following arguments are supported:
 
 * `labels` -
   (Optional)
-  Optional. Labels as key value pairs
+  Optional. Labels as key value pairs.
   **Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
   Please refer to the field `effective_labels` for all of the labels present on the resource.
 
@@ -97,13 +97,13 @@ In addition to the arguments listed above, the following computed attributes are
 * `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}`
 
 * `name` -
-  Immutable. Identifier. name of resource
+  Immutable. Identifier. Name of Repository Group.
 
 * `create_time` -
-  Output only. Create time stamp
+  Output only. Create time stamp.
 
 * `update_time` -
-  Output only. Update time stamp
+  Output only. Update time stamp.
 
 * `terraform_labels` -
   The combination of labels configured directly on the resource
diff --git a/website/docs/r/gemini_repository_group_iam.html.markdown b/website/docs/r/gemini_repository_group_iam.html.markdown
index 93eb25467b2..2ae4c1f5db0 100644
--- a/website/docs/r/gemini_repository_group_iam.html.markdown
+++ b/website/docs/r/gemini_repository_group_iam.html.markdown
@@ -33,14 +33,11 @@ A data source can be used to retrieve policy data in advent you do not need crea
 ~> **Note:** `google_gemini_repository_group_iam_binding` resources **can be** used in conjunction with `google_gemini_repository_group_iam_member` resources **only if** they do not grant privilege to the same role.
 
 
-~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider.
-See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources.
 
 ## google_gemini_repository_group_iam_policy
 
 ```hcl
 data "google_iam_policy" "admin" {
-  provider = google-beta
   binding {
     role = "roles/cloudaicompanion.repositoryGroupsUser"
     members = [
@@ -50,7 +47,6 @@ data "google_iam_policy" "admin" {
 }
 
 resource "google_gemini_repository_group_iam_policy" "policy" {
-  provider = google-beta
   project = google_gemini_repository_group.example.project
   location = google_gemini_repository_group.example.location
   code_repository_index = google_gemini_repository_group.example.code_repository_index
@@ -63,7 +59,6 @@ resource "google_gemini_repository_group_iam_policy" "policy" {
 
 ```hcl
 resource "google_gemini_repository_group_iam_binding" "binding" {
-  provider = google-beta
   project = google_gemini_repository_group.example.project
   location = google_gemini_repository_group.example.location
   code_repository_index = google_gemini_repository_group.example.code_repository_index
@@ -79,7 +74,6 @@ resource "google_gemini_repository_group_iam_binding" "binding" {
 
 ```hcl
 resource "google_gemini_repository_group_iam_member" "member" {
-  provider = google-beta
   project = google_gemini_repository_group.example.project
   location = google_gemini_repository_group.example.location
   code_repository_index = google_gemini_repository_group.example.code_repository_index