diff --git a/doc/config-schema.md b/doc/config-schema.md index 5d2976baf..79c8cf0cf 100644 --- a/doc/config-schema.md +++ b/doc/config-schema.md @@ -201,6 +201,7 @@ This document describes the schema for the librarian.yaml. | `import_path` | string | Is the Go import path for the API. | | `nested_protos` | list of string | Is a list of nested proto files. | | `no_metadata` | bool | Indicates whether to skip generating gapic_metadata.json. This is typically false. | +| `no_snippets` | bool | Indicates whether to skip generating snippets. This is typically false. | | `path` | string | Is the source path. | | `proto_only` | bool | Determines whether to generate a Proto-only client. A proto-only client does not define a service in the proto files. | | `proto_package` | string | Is the proto package name. | diff --git a/internal/config/language.go b/internal/config/language.go index 583fe11e4..512b3519f 100644 --- a/internal/config/language.go +++ b/internal/config/language.go @@ -80,6 +80,9 @@ type GoAPI struct { // NoMetadata indicates whether to skip generating gapic_metadata.json. // This is typically false. NoMetadata bool `yaml:"no_metadata,omitempty"` + // NoSnippets indicates whether to skip generating snippets. + // This is typically false. + NoSnippets bool `yaml:"no_snippets,omitempty"` // Path is the source path. Path string `yaml:"path,omitempty"` // ProtoOnly determines whether to generate a Proto-only client. diff --git a/internal/librarian/golang/generate.go b/internal/librarian/golang/generate.go index c5a64a9c2..53b6755a3 100644 --- a/internal/librarian/golang/generate.go +++ b/internal/librarian/golang/generate.go @@ -145,6 +145,9 @@ func buildGAPICOpts(apiPath string, goAPI *config.GoAPI, googleapisDir string) ( if !goAPI.NoMetadata { opts = append(opts, "metadata") } + if goAPI.NoSnippets { + opts = append(opts, "omit-snippets") + } if sc != nil && sc.HasRESTNumericEnums(config.LanguageGo) { opts = append(opts, "rest-numeric-enums") } @@ -199,7 +202,6 @@ func moveAPIDirectory(library *config.Library, goAPI *config.GoAPI, outDir strin // moveAndUpdateSnippets moves the generated snippets from the temporary location to their final // destination and updates their library versions. func moveAndUpdateSnippets(library *config.Library, goAPI *config.GoAPI, outDir string) error { - snippetDirPrefix := filepath.Join(outDir, "cloud.google.com", "go", "internal", "generated", "snippets") snippetDest := findSnippetDirectory(library, goAPI, outDir) if snippetDest == "" { return nil @@ -207,6 +209,7 @@ func moveAndUpdateSnippets(library *config.Library, goAPI *config.GoAPI, outDir if err := os.MkdirAll(snippetDest, 0755); err != nil { return err } + snippetDirPrefix := filepath.Join(outDir, "cloud.google.com", "go", "internal", "generated", "snippets") snippetSrc := filepath.Join(snippetDirPrefix, goAPI.ImportPath) if err := filesystem.MoveAndMerge(snippetSrc, snippetDest); err != nil { return err diff --git a/internal/librarian/golang/generate_test.go b/internal/librarian/golang/generate_test.go index 5d1fa5e40..5e22d0606 100644 --- a/internal/librarian/golang/generate_test.go +++ b/internal/librarian/golang/generate_test.go @@ -594,6 +594,26 @@ func TestBuildGAPICOpts(t *testing.T) { "release-level=ga", }, }, + { + name: "no snippets", + apiPath: "google/cloud/gkehub/v1", + goAPI: &config.GoAPI{ + ClientPackage: "gkehub", + ImportPath: "gkehub/apiv1", + NoSnippets: true, + Path: "google/cloud/gkehub/v1", + }, + googleapisDir: googleapisDir, + want: []string{ + "go-gapic-package=cloud.google.com/go/gkehub/apiv1;gkehub", + "metadata", + "omit-snippets", + "rest-numeric-enums", + "api-service-config=" + filepath.Join(googleapisDir, "google/cloud/gkehub/v1/gkehub_v1.yaml"), + "transport=grpc+rest", + "release-level=ga", + }, + }, { name: "generator features", apiPath: "google/cloud/bigquery/v2", @@ -802,6 +822,37 @@ func TestMoveGeneratedFiles(t *testing.T) { return outDir, filepath.Join(outDir, "apiv1"), filepath.Join(repoRoot, "internal", "generated", "snippets", "lib", "apiv1"), lib }, }, + { + name: "no snippets", + setup: func(t *testing.T, tmpDir string) (string, string, string, *config.Library) { + repoRoot := filepath.Join(tmpDir, "repo") + outDir := filepath.Join(repoRoot, "lib") + srcDir := filepath.Join(outDir, "cloud.google.com", "go", "lib", "apiv1") + if err := os.MkdirAll(srcDir, 0755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(srcDir, "main.go"), []byte("package foo"), 0644); err != nil { + t.Fatal(err) + } + // Even if snippet source exists in cloud.google.com/go, it should not be moved. + snippetDirSuffix := filepath.Join("internal", "generated", "snippets", "lib", "apiv1") + snippetSrcDir := filepath.Join(outDir, "cloud.google.com", "go", snippetDirSuffix) + if err := os.MkdirAll(snippetSrcDir, 0755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(snippetSrcDir, "snippet.go"), []byte("package internal"), 0644); err != nil { + t.Fatal(err) + } + lib := &config.Library{ + Name: "lib", + APIs: []*config.API{{Path: "lib/v1"}}, + Go: &config.GoModule{ + GoAPIs: []*config.GoAPI{{Path: "lib/v1", ImportPath: "lib/apiv1", NoSnippets: true}}, + }, + } + return outDir, filepath.Join(outDir, "apiv1"), filepath.Join(repoRoot, snippetDirSuffix), lib + }, + }, } { t.Run(test.name, func(t *testing.T) { tmpDir := t.TempDir() @@ -813,8 +864,14 @@ func TestMoveGeneratedFiles(t *testing.T) { if _, err := os.Stat(filepath.Join(apiDir, "main.go")); err != nil { t.Errorf("expected main.go to exist, got err: %v", err) } - if _, err := os.Stat(filepath.Join(snippetDir, "snippet.go")); err != nil { - t.Errorf("expected snippet.go to exist, got err: %v", err) + if lib.Go.GoAPIs[0].NoSnippets { + if _, err := os.Stat(filepath.Join(snippetDir, "snippet.go")); !errors.Is(err, os.ErrNotExist) { + t.Errorf("expected snippet.go to not exist, got err: %v", err) + } + } else { + if _, err := os.Stat(filepath.Join(snippetDir, "snippet.go")); err != nil { + t.Errorf("expected snippet.go to exist, got err: %v", err) + } } }) } diff --git a/internal/librarian/golang/module.go b/internal/librarian/golang/module.go index 0151b7bb3..64cab6564 100644 --- a/internal/librarian/golang/module.go +++ b/internal/librarian/golang/module.go @@ -174,10 +174,10 @@ func snippetDirectory(output, importPath string) string { } // findSnippetDirectory returns the path to the snippet directory for the given API path and library output directory. -// It returns an empty string if the API is proto-only or if the snippet directory is in a path marked for deletion -// after generation. +// It returns an empty string if the API is proto-only, if snippet generation is disabled, +// or if the snippet directory is in a path marked for deletion after generation. func findSnippetDirectory(library *config.Library, goAPI *config.GoAPI, output string) string { - if goAPI.ProtoOnly { + if goAPI.ProtoOnly || goAPI.NoSnippets { return "" } snippetDir := snippetDirectory(repoRootPath(output, library.Name), clientPathFromRepoRoot(library, goAPI)) diff --git a/internal/librarian/golang/tidy.go b/internal/librarian/golang/tidy.go index 2d42e04b7..b1f745a2e 100644 --- a/internal/librarian/golang/tidy.go +++ b/internal/librarian/golang/tidy.go @@ -59,6 +59,7 @@ func isEmptyAPI(goAPI *config.GoAPI) bool { goAPI.ImportPath == "" && len(goAPI.NestedProtos) == 0 && !goAPI.NoMetadata && + !goAPI.NoSnippets && !goAPI.ProtoOnly && goAPI.ProtoPackage == "" } diff --git a/internal/librarian/golang/tidy_test.go b/internal/librarian/golang/tidy_test.go index dad33515d..e4583da3d 100644 --- a/internal/librarian/golang/tidy_test.go +++ b/internal/librarian/golang/tidy_test.go @@ -249,6 +249,12 @@ func TestIsEmptyAPI(t *testing.T) { NoMetadata: true, }, }, + { + name: "not empty with NoSnippets", + goAPI: &config.GoAPI{ + NoSnippets: true, + }, + }, { name: "not empty with ProtoOnly", goAPI: &config.GoAPI{