From 957a73ff8ad674cb2dcbfb634a04236f88c1bc35 Mon Sep 17 00:00:00 2001 From: Carlos O'Ryan Date: Tue, 30 Jun 2026 16:25:41 -0400 Subject: [PATCH 1/2] feat(librarian/swift): use discovery config Use the discovery configuration to generate `getOperation()` mixins in discovery-based APIs. --- internal/librarian/swift/generate.go | 25 ++++++++++--- internal/librarian/swift/generate_test.go | 44 +++++++++++++++++++++++ internal/sidekick/api/xref.go | 12 +++---- 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/internal/librarian/swift/generate.go b/internal/librarian/swift/generate.go index a5ca234e2b1..9d82ec2fe85 100644 --- a/internal/librarian/swift/generate.go +++ b/internal/librarian/swift/generate.go @@ -23,6 +23,7 @@ import ( "github.com/googleapis/librarian/internal/command" "github.com/googleapis/librarian/internal/config" "github.com/googleapis/librarian/internal/serviceconfig" + "github.com/googleapis/librarian/internal/sidekick/api" "github.com/googleapis/librarian/internal/sidekick/parser" sidekickswift "github.com/googleapis/librarian/internal/sidekick/swift" "github.com/googleapis/librarian/internal/sources" @@ -74,8 +75,8 @@ func camelLibraryName(api string) string { return name.String() } -func libraryToModelConfig(library *config.Library, api *config.API, src *sources.Sources) (*parser.ModelConfig, error) { - svcConfig, err := serviceconfig.Find(src.Googleapis, api.Path, config.LanguageSwift) +func libraryToModelConfig(library *config.Library, apiCfg *config.API, src *sources.Sources) (*parser.ModelConfig, error) { + svcConfig, err := serviceconfig.Find(src.Googleapis, apiCfg.Path, config.LanguageSwift) if err != nil { return nil, err } @@ -89,15 +90,29 @@ func libraryToModelConfig(library *config.Library, api *config.API, src *sources specFormat = library.SpecificationFormat } - return &parser.ModelConfig{ + modelCfg := &parser.ModelConfig{ Language: config.LanguageSwift, SpecificationFormat: specFormat, ServiceConfig: svcConfig.ServiceConfig, - SpecificationSource: api.Path, + SpecificationSource: apiCfg.Path, Source: sourceConfig, Codec: map[string]string{ "copyright-year": library.CopyrightYear, "version": library.Version, }, - }, nil + } + if library.Swift != nil && library.Swift.Discovery != nil { + pollers := make([]*api.Poller, len(library.Swift.Discovery.Pollers)) + for i, poller := range library.Swift.Discovery.Pollers { + pollers[i] = &api.Poller{ + Prefix: poller.Prefix, + MethodID: poller.MethodID, + } + } + modelCfg.Discovery = &api.Discovery{ + OperationID: library.Swift.Discovery.OperationID, + Pollers: pollers, + } + } + return modelCfg, nil } diff --git a/internal/librarian/swift/generate_test.go b/internal/librarian/swift/generate_test.go index 3fb948d47b5..e4abae4766b 100644 --- a/internal/librarian/swift/generate_test.go +++ b/internal/librarian/swift/generate_test.go @@ -21,6 +21,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/googleapis/librarian/internal/config" + "github.com/googleapis/librarian/internal/sidekick/api" "github.com/googleapis/librarian/internal/sidekick/parser" "github.com/googleapis/librarian/internal/sources" "github.com/googleapis/librarian/internal/testhelper" @@ -207,6 +208,49 @@ func TestLibraryToModelConfig(t *testing.T) { }, }, }, + { + name: "discovery config with LRO", + library: &config.Library{ + Name: "google-cloud-compute-v1", + CopyrightYear: "2038", + Version: "1.2.3", + Roots: []string{"discovery", "googleapis"}, + SpecificationFormat: config.SpecDiscovery, + Swift: &config.SwiftPackage{ + Discovery: &config.SwiftDiscovery{ + OperationID: ".google.cloud.compute.v1.", + Pollers: []config.SwiftPoller{ + { + Prefix: "compute/v1/projects/{project}/zones/{zone}", + MethodID: ".google.cloud.compute.v1.zoneOperations.get", + }, + }, + }, + }, + }, + api: &config.API{ + Path: "discoveries/compute.v1.json", + }, + want: &parser.ModelConfig{ + Language: config.LanguageSwift, + SpecificationFormat: config.SpecDiscovery, + SpecificationSource: "discoveries/compute.v1.json", + ServiceConfig: "google/cloud/compute/v1/compute_v1.yaml", + Codec: map[string]string{"copyright-year": "2038", "version": "1.2.3"}, + Source: &sources.SourceConfig{ + ActiveRoots: []string{"discovery", "googleapis"}, + }, + Discovery: &api.Discovery{ + OperationID: ".google.cloud.compute.v1.", + Pollers: []*api.Poller{ + { + Prefix: "compute/v1/projects/{project}/zones/{zone}", + MethodID: ".google.cloud.compute.v1.zoneOperations.get", + }, + }, + }, + }, + }, } { t.Run(test.name, func(t *testing.T) { srcs := &sources.Sources{ diff --git a/internal/sidekick/api/xref.go b/internal/sidekick/api/xref.go index 958a73624d7..44180fe9f31 100644 --- a/internal/sidekick/api/xref.go +++ b/internal/sidekick/api/xref.go @@ -361,11 +361,11 @@ func sortOneOfFieldForExamples(f1, f2 *Field) int { } func enrichMethodSamples(m *Method) { - m.IsSimple = m.Pagination == nil && - !m.ClientSideStreaming && !m.ServerSideStreaming && - m.OperationInfo == nil && m.DiscoveryLro == nil - - m.IsLRO = m.OperationInfo != nil + // Methods with AIP-151 LRO annotations *OR* discovery LRO annotations are LROs. + m.IsLRO = m.OperationInfo != nil || m.DiscoveryLro != nil + m.IsStreaming = m.ClientSideStreaming || m.ServerSideStreaming + // A simple method is not paginated, not streaming and not an LRO. + m.IsSimple = m.Pagination == nil && !m.IsStreaming && !m.IsLRO if m.SourceServiceID == ".google.longrunning.Operations" && m.Name == "GetOperation" && @@ -381,8 +381,6 @@ func enrichMethodSamples(m *Method) { m.IsList = m.OutputType != nil && m.OutputType.Pagination != nil - m.IsStreaming = m.ClientSideStreaming || m.ServerSideStreaming - if m.SampleInfo = aipStandardGetInfo(m); m.SampleInfo != nil { m.IsAIPStandardGet = true } else if m.SampleInfo = aipStandardDeleteInfo(m); m.SampleInfo != nil { From d998b1439cc78e56685f691cc9b7d17695066607 Mon Sep 17 00:00:00 2001 From: Carlos O'Ryan Date: Wed, 1 Jul 2026 10:38:32 -0400 Subject: [PATCH 2/2] Address review comments --- internal/sidekick/api/xref_test.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/internal/sidekick/api/xref_test.go b/internal/sidekick/api/xref_test.go index 14880aa7693..5e388a9572d 100644 --- a/internal/sidekick/api/xref_test.go +++ b/internal/sidekick/api/xref_test.go @@ -672,7 +672,7 @@ func TestIsSimpleMethod(t *testing.T) { } func TestIsLRO(t *testing.T) { - testCases := []struct { + for _, test := range []struct { name string method *Method want bool @@ -687,12 +687,16 @@ func TestIsLRO(t *testing.T) { method: &Method{OperationInfo: &OperationInfo{}}, want: true, }, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - enrichMethodSamples(tc.method) - if got := tc.method.IsLRO; got != tc.want { - t.Errorf("IsLRO() = %v, want %v", got, tc.want) + { + name: "LRO method is discovery LRO", + method: &Method{DiscoveryLro: &DiscoveryLro{}}, + want: true, + }, + } { + t.Run(test.name, func(t *testing.T) { + enrichMethodSamples(test.method) + if got := test.method.IsLRO; got != test.want { + t.Errorf("IsLRO() = %v, want %v", got, test.want) } }) }