From 15e5904bc7836c4d441b7c87053a51c9a89117aa Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Thu, 3 Sep 2026 22:22:41 +0000 Subject: [PATCH 1/2] feat(cloud): add ruby-cloud-renamed-from for renamed wrapper gems --- .../generators/cloud_generator_parameters.rb | 1 + .../gapic/presenters/wrapper_gem_presenter.rb | 33 +++++++++++-- .../cloud/wrapper_gem/entrypoint.text.erb | 2 +- .../cloud/wrapper_gem/readme.text.erb | 2 +- .../presenters/wrapper_gem_presenter_test.rb | 48 +++++++++++++++++++ .../test/gapic/schema/cloud_api_test.rb | 1 + .../default_generator_parameters.rb | 2 + gapic-generator/test/gapic/schema/api_test.rb | 2 + shared/test_resources/api_test_resources.rb | 2 + 9 files changed, 87 insertions(+), 6 deletions(-) diff --git a/gapic-generator-cloud/lib/gapic/generators/cloud_generator_parameters.rb b/gapic-generator-cloud/lib/gapic/generators/cloud_generator_parameters.rb index 5f6160bd9..dd5b4ed02 100644 --- a/gapic-generator-cloud/lib/gapic/generators/cloud_generator_parameters.rb +++ b/gapic-generator-cloud/lib/gapic/generators/cloud_generator_parameters.rb @@ -40,6 +40,7 @@ module CloudGeneratorParameters "ruby-cloud-homepage" => ":gem.:homepage", "ruby-cloud-env-prefix" => ":gem.:env_prefix", "ruby-cloud-wrapper-of" => ":gem.:version_dependencies", + "ruby-cloud-renamed-from" => ":gem.:renamed_from", "ruby-cloud-migration-version" => ":gem.:migration_version", "ruby-cloud-product-url" => ":gem.:product_documentation_url", "ruby-cloud-issues-url" => ":gem.:issue_tracker_url", diff --git a/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb b/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb index ce9015169..b75256a6d 100644 --- a/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb +++ b/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb @@ -105,12 +105,37 @@ def factory_method_suffix gem_config(:factory_method_suffix).to_s end + def renamed_from + gem_config(:renamed_from) || name + end + + def renamed_gem? + renamed_from != name + end + + def namespace + gem_config(:namespace) || + fix_namespace(@api, renamed_from.split("-").map(&:camelize).join("::")) + end + + def gem_namespace + fix_namespace(@api, name.split("-").map(&:camelize).join("::")) + end + + def version_name_full + if renamed_gem? + "#{gem_namespace}::VERSION" + else + "#{namespace}::VERSION" + end + end + def version_dependencies gem_config(:version_dependencies).to_s.split(";").map { |str| str.split ":" } end def versioned_gems - version_dependencies.map { |version, _requirement| "#{name}-#{version}" }.sort + version_dependencies.map { |version, _requirement| "#{renamed_from}-#{version}" }.sort end def default_version @@ -129,7 +154,7 @@ def dependencies # 0.x and 1.x versions to ease the transition to 1.0 (GA) releases # for those dependencies. (Note the 0.x->1.0 transition is # generally not breaking.) - deps["#{name}-#{version}"] = + deps["#{renamed_from}-#{version}"] = if requirement.start_with? "0." [">= #{requirement}", "< 2.a"] else @@ -143,13 +168,13 @@ def dependencies end def google_cloud_short_name - m = /^google-cloud-(.*)$/.match name + m = /^google-cloud-(.*)$/.match renamed_from return nil unless m m[1].tr "-", "_" end def docs_link version: nil, class_name: nil, text: nil, gem_name: nil - gem_name ||= version ? "#{name}-#{version}" : name + gem_name ||= version ? "#{renamed_from}-#{version}" : name base_url = if cloud_product? "https://cloud.google.com/ruby/docs/reference/#{gem_name}/latest" diff --git a/gapic-generator-cloud/templates/cloud/wrapper_gem/entrypoint.text.erb b/gapic-generator-cloud/templates/cloud/wrapper_gem/entrypoint.text.erb index fef101a95..8cfa45794 100644 --- a/gapic-generator-cloud/templates/cloud/wrapper_gem/entrypoint.text.erb +++ b/gapic-generator-cloud/templates/cloud/wrapper_gem/entrypoint.text.erb @@ -1,4 +1,4 @@ <%- assert_locals gem -%> <%= render partial: "shared/header" -%> -require "<%= gem.namespace_require %>" unless defined? <%= gem.namespace %>::VERSION +require "<%= gem.namespace_require %>" unless defined? <%= gem.version_name_full %> diff --git a/gapic-generator-cloud/templates/cloud/wrapper_gem/readme.text.erb b/gapic-generator-cloud/templates/cloud/wrapper_gem/readme.text.erb index b13272f76..707374b65 100644 --- a/gapic-generator-cloud/templates/cloud/wrapper_gem/readme.text.erb +++ b/gapic-generator-cloud/templates/cloud/wrapper_gem/readme.text.erb @@ -9,7 +9,7 @@ <%- end %> Actual client classes for the various versions of this API are defined in -_versioned_ client gems, with names of the form `<%= gem.name %>-v*`. +_versioned_ client gems, with names of the form `<%= gem.renamed_from %>-v*`. The gem `<%= gem.name %>` is the main client library that brings the versioned gems in as dependencies, and provides high-level methods for constructing clients. More information on versioned clients can be found below diff --git a/gapic-generator-cloud/test/gapic/presenters/wrapper_gem_presenter_test.rb b/gapic-generator-cloud/test/gapic/presenters/wrapper_gem_presenter_test.rb index 499d23eac..92b14b3a9 100644 --- a/gapic-generator-cloud/test/gapic/presenters/wrapper_gem_presenter_test.rb +++ b/gapic-generator-cloud/test/gapic/presenters/wrapper_gem_presenter_test.rb @@ -151,4 +151,52 @@ def test_gem_readme_disabled_xrefs presenter_param = Gapic::Presenters::WrapperGemPresenter.new api_param assert_equal ["Typical Garbage Service using MixIns"], presenter_param.readme_description end + + def test_renamed_gem_google_cloud_run_client + params = { + ":gem.:name" => "google-cloud-run-client", + ":gem.:renamed_from" => "google-cloud-run", + ":gem.:version_dependencies" => "v2:0.17" + } + api_param = api :testing, params_override: params + presenter = Gapic::Presenters::WrapperGemPresenter.new api_param + + assert_equal "google-cloud-run-client", presenter.name + assert_equal "google-cloud-run", presenter.renamed_from + assert presenter.renamed_gem? + assert_equal "Google::Cloud::Run", presenter.namespace + assert_equal "Google::Cloud::Run::Client", presenter.gem_namespace + assert_equal "Google::Cloud::Run::Client::VERSION", presenter.version_name_full + assert_equal "google/cloud/run/client/version", presenter.version_require + assert_equal "google/cloud/run/client/version.rb", presenter.version_file_path + assert_equal ["google-cloud-run-v2"], presenter.versioned_gems + assert_equal [">= 0.17", "< 2.a"], presenter.dependencies["google-cloud-run-v2"] + assert_equal "run", presenter.google_cloud_short_name + assert presenter.needs_entrypoint? + assert presenter.needs_default_config_block? + end + + def test_renamed_gem_google_iam_client + params = { + ":gem.:name" => "google-iam-client", + ":gem.:renamed_from" => "google-iam", + ":gem.:version_dependencies" => "v2:0.5" + } + api_param = api :testing, params_override: params + presenter = Gapic::Presenters::WrapperGemPresenter.new api_param + + assert_equal "google-iam-client", presenter.name + assert_equal "google-iam", presenter.renamed_from + assert presenter.renamed_gem? + assert_equal "Google::Iam", presenter.namespace + assert_equal "Google::Iam::Client", presenter.gem_namespace + assert_equal "Google::Iam::Client::VERSION", presenter.version_name_full + assert_equal "google/iam/client/version", presenter.version_require + assert_equal "google/iam/client/version.rb", presenter.version_file_path + assert_equal ["google-iam-v2"], presenter.versioned_gems + assert_equal [">= 0.5", "< 2.a"], presenter.dependencies["google-iam-v2"] + assert_nil presenter.google_cloud_short_name + assert presenter.needs_entrypoint? + refute presenter.needs_default_config_block? + end end diff --git a/gapic-generator-cloud/test/gapic/schema/cloud_api_test.rb b/gapic-generator-cloud/test/gapic/schema/cloud_api_test.rb index d11b24f74..b599d16d7 100644 --- a/gapic-generator-cloud/test/gapic/schema/cloud_api_test.rb +++ b/gapic-generator-cloud/test/gapic/schema/cloud_api_test.rb @@ -46,6 +46,7 @@ def test_parse_parameters_readable ["ruby-cloud-homepage", API_INFO[:homepage]], ["ruby-cloud-env-prefix", API_INFO[:env_prefix]], ["ruby-cloud-wrapper-of", API_INFO[:wrapper_of]], + ["ruby-cloud-renamed-from", API_INFO[:renamed_from]], ["ruby-cloud-migration-version", API_INFO[:migration_version]], ["ruby-cloud-product-url", API_INFO[:product_url]], ["ruby-cloud-issues-url", API_INFO[:issues_url]], diff --git a/gapic-generator/lib/gapic/generators/default_generator_parameters.rb b/gapic-generator/lib/gapic/generators/default_generator_parameters.rb index d82d19af5..3c3bbdaa5 100644 --- a/gapic-generator/lib/gapic/generators/default_generator_parameters.rb +++ b/gapic-generator/lib/gapic/generators/default_generator_parameters.rb @@ -40,6 +40,7 @@ module DefaultGeneratorParameters ":gem.:homepage", ":gem.:env_prefix", ":gem.:version_dependencies", + ":gem.:renamed_from", ":gem.:migration_version", ":gem.:product_documentation_url", ":gem.:issue_tracker_url", @@ -83,6 +84,7 @@ module DefaultGeneratorParameters "gem-homepage" => ":gem.:homepage", "gem-env-prefix" => ":gem.:env_prefix", "gem-wrapper-of" => ":gem.:version_dependencies", + "gem-renamed-from" => ":gem.:renamed_from", "gem-migration-version" => ":gem.:migration_version", "gem-product-url" => ":gem.:product_documentation_url", "gem-issues-url" => ":gem.:issue_tracker_url", diff --git a/gapic-generator/test/gapic/schema/api_test.rb b/gapic-generator/test/gapic/schema/api_test.rb index af0883412..1a156b8fb 100644 --- a/gapic-generator/test/gapic/schema/api_test.rb +++ b/gapic-generator/test/gapic/schema/api_test.rb @@ -50,6 +50,7 @@ def test_parse_parameters_literal [":gem.:homepage", API_INFO[:homepage]], [":gem.:env_prefix", API_INFO[:env_prefix]], [":gem.:version_dependencies", API_INFO[:wrapper_of]], + [":gem.:renamed_from", API_INFO[:renamed_from]], [":gem.:migration_version", API_INFO[:migration_version]], [":gem.:product_documentation_url", API_INFO[:product_url]], [":gem.:issue_tracker_url", API_INFO[:issues_url]], @@ -101,6 +102,7 @@ def test_parse_parameters_readable ["gem-homepage", API_INFO[:homepage]], ["gem-env-prefix", API_INFO[:env_prefix]], ["gem-wrapper-of", API_INFO[:wrapper_of]], + ["gem-renamed-from", API_INFO[:renamed_from]], ["gem-migration-version", API_INFO[:migration_version]], ["gem-product-url", API_INFO[:product_url]], ["gem-issues-url", API_INFO[:issues_url]], diff --git a/shared/test_resources/api_test_resources.rb b/shared/test_resources/api_test_resources.rb index 17770817e..d0b1f6439 100644 --- a/shared/test_resources/api_test_resources.rb +++ b/shared/test_resources/api_test_resources.rb @@ -40,6 +40,7 @@ module ApiTestResources homepage: 'https://github.com/googleapis/googleapis', env_prefix: 'CONTAINER_ANALYSIS', wrapper_of: 'v1:0.0;v1beta1:0.0', + renamed_from: 'container-analysis-renamed', migration_version: '0.20', product_url: 'https://cloud.google.com/container-registry/docs/container-analysis', issues_url: 'https://example.com/issues', @@ -87,6 +88,7 @@ module ApiTestResources homepage: API_INFO[:homepage], env_prefix: API_INFO[:env_prefix], version_dependencies: API_INFO[:wrapper_of], + renamed_from: API_INFO[:renamed_from], migration_version: API_INFO[:migration_version], product_documentation_url: API_INFO[:product_url], issue_tracker_url: API_INFO[:issues_url], From 492b12d659b0f7d85fbc73a89f62570bb6bb4635 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Thu, 3 Sep 2026 22:36:41 +0000 Subject: [PATCH 2/2] docs(cloud): document background and naming conflicts for renamed_from --- .../gapic/presenters/wrapper_gem_presenter.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb b/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb index b75256a6d..2c75e22aa 100644 --- a/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb +++ b/gapic-generator-cloud/lib/gapic/presenters/wrapper_gem_presenter.rb @@ -105,6 +105,22 @@ def factory_method_suffix gem_config(:factory_method_suffix).to_s end + ## + # The canonical gem name prior to renaming. + # + # In some cases, a wrapper gem cannot be published under its canonical + # name because a conflicting gem already exists on RubyGems.org. For example: + # - "google-cloud-run" was renamed to "google-cloud-run-client" because RubyGems + # already had an existing gem named "google_cloud_run". + # - "google-iam" was renamed to "google-iam-client" because RubyGems already had + # an unrelated gem named "google-iam". + # + # Even though the wrapper gem itself is renamed with a "-client" suffix, it + # still wraps versioned client gems named after the canonical name (e.g. + # "google-cloud-run-v2", "google-iam-v2") and defines classes in the canonical + # namespace (e.g. "Google::Cloud::Run", "Google::Iam"). + # + # @return [String] def renamed_from gem_config(:renamed_from) || name end