diff --git a/.toys/ci.rb b/.toys/ci.rb index cb5650a2fc2a..a1cd344821c7 100644 --- a/.toys/ci.rb +++ b/.toys/ci.rb @@ -237,8 +237,8 @@ def interpret_github_event logger.info "Using local commits" [base_commit, head_commit] end - base_ref = nil if base_ref&.empty? - head_ref = nil if head_ref&.empty? + base_ref = nil if base_ref && base_ref.empty? + head_ref = nil if head_ref && head_ref.empty? [base_ref, head_ref] end diff --git a/google-cloud-error_reporting/AUTHENTICATION.md b/google-cloud-error_reporting/AUTHENTICATION.md index d3e9a71b86c5..6adea5259616 100644 --- a/google-cloud-error_reporting/AUTHENTICATION.md +++ b/google-cloud-error_reporting/AUTHENTICATION.md @@ -96,20 +96,24 @@ client = Google::Cloud::ErrorReporting.new ### Configuration -The **Project ID** and the path to the **Credentials JSON** file can be configured +The **Project ID**, **Quota Project**, and the path to the **Credentials JSON** file can be configured instead of placing them in environment variables or providing them as arguments. ```ruby require "google/cloud/error_reporting" Google::Cloud::ErrorReporting.configure do |config| - config.project_id = "my-project-id" - config.credentials = "path/to/keyfile.json" + config.project_id = "my-project-id" # The project where errors are reported + config.quota_project = "my-billing-project" # The project billed for quota/billing (optional) + config.credentials = "path/to/keyfile.json" end client = Google::Cloud::ErrorReporting.new ``` +> [!NOTE] +> **Project ID** (where errors are sent) and **Quota Project** (which project is billed for the API call) are distinct. By default, the library bills the project associated with the credentials. Use `config.quota_project` if you need to bill a different project. + ### Cloud SDK This option allows for an easy way to authenticate during development. If diff --git a/google-cloud-error_reporting/README.md b/google-cloud-error_reporting/README.md index efaa355a5451..2ebf27bad7d5 100644 --- a/google-cloud-error_reporting/README.md +++ b/google-cloud-error_reporting/README.md @@ -168,9 +168,12 @@ Google::Cloud.configure do |config| # Shared parameters config.project_id = "your-project-id" config.keyfile = "/path/to/key.json" + config.quota_project = "your-billing-project" + # Or Error Reporting specific parameters config.error_reporting.project_id = "your-project-id" config.error_reporting.keyfile = "/path/to/key.json" + config.error_reporting.quota_project = "your-billing-project" end ``` diff --git a/google-cloud-error_reporting/lib/google/cloud/error_reporting.rb b/google-cloud-error_reporting/lib/google/cloud/error_reporting.rb index 28aa231c4ef4..51844b2b9cff 100644 --- a/google-cloud-error_reporting/lib/google/cloud/error_reporting.rb +++ b/google-cloud-error_reporting/lib/google/cloud/error_reporting.rb @@ -93,7 +93,10 @@ def self.new project_id: nil, credentials = resolve_credentials credentials, scope project_id = resolve_project_id project_id, credentials - service = ErrorReporting::Service.new project_id, credentials, host: endpoint, timeout: timeout + quota_project = configure.quota_project + service = ErrorReporting::Service.new project_id, credentials, + host: endpoint, timeout: timeout, + quota_project: quota_project ErrorReporting::Project.new service end diff --git a/google-cloud-error_reporting/lib/google/cloud/error_reporting/project.rb b/google-cloud-error_reporting/lib/google/cloud/error_reporting/project.rb index cf65e373c50d..551328404eb8 100644 --- a/google-cloud-error_reporting/lib/google/cloud/error_reporting/project.rb +++ b/google-cloud-error_reporting/lib/google/cloud/error_reporting/project.rb @@ -122,8 +122,8 @@ def project_id # error_event = error_reporting.error_event "Error with Backtrace" # error_reporting.report error_event # - def report *args, &block - service.report(*args, &block) + def report(*args, &) + service.report(*args, &) end ## diff --git a/google-cloud-error_reporting/lib/google/cloud/error_reporting/service.rb b/google-cloud-error_reporting/lib/google/cloud/error_reporting/service.rb index ef43277e5aa8..467cb654a8ff 100644 --- a/google-cloud-error_reporting/lib/google/cloud/error_reporting/service.rb +++ b/google-cloud-error_reporting/lib/google/cloud/error_reporting/service.rb @@ -29,14 +29,17 @@ class Service attr_accessor :credentials attr_accessor :timeout attr_accessor :host + attr_accessor :quota_project ## # Creates a new Service instance. - def initialize project, credentials, timeout: nil, host: nil + def initialize project, credentials, timeout: nil, host: nil, quota_project: nil @project = project @credentials = credentials @timeout = timeout @host = host + @quota_project = quota_project + @quota_project ||= credentials.quota_project_id if credentials.respond_to? :quota_project_id end def error_reporting @@ -46,6 +49,7 @@ def error_reporting config.credentials = credentials if credentials config.timeout = timeout if timeout config.endpoint = host if host + config.quota_project = quota_project if quota_project config.lib_name = "gccl" config.lib_version = Google::Cloud::ErrorReporting::VERSION end diff --git a/google-cloud-error_reporting/support/doctest_helper.rb b/google-cloud-error_reporting/support/doctest_helper.rb index b179fbd0de4b..38392f631381 100644 --- a/google-cloud-error_reporting/support/doctest_helper.rb +++ b/google-cloud-error_reporting/support/doctest_helper.rb @@ -13,6 +13,7 @@ # limitations under the License. require "minitest/focus" +require "ostruct" require "google/cloud/error_reporting" @@ -73,13 +74,13 @@ def mock_error_reporting doctest.before "Google::Cloud#error_reporting" do mock_error_reporting do |mock| - mock.expect :report_error_event, nil, [Hash] + mock.expect :report_error_event, nil, [], project_name: String, event: Google::Cloud::ErrorReporting::V1beta1::ReportedErrorEvent end end doctest.before "Google::Cloud.error_reporting" do mock_error_reporting do |mock| - mock.expect :report_error_event, nil, [Hash] + mock.expect :report_error_event, nil, [], project_name: String, event: Google::Cloud::ErrorReporting::V1beta1::ReportedErrorEvent end end @@ -89,13 +90,13 @@ def mock_error_reporting doctest.before "Google::Cloud::ErrorReporting::ErrorEvent" do mock_error_reporting do |mock| - mock.expect :report_error_event, nil, [Hash] + mock.expect :report_error_event, nil, [], project_name: String, event: Google::Cloud::ErrorReporting::V1beta1::ReportedErrorEvent end end doctest.before "Google::Cloud::ErrorReporting::Project" do mock_error_reporting do |mock| - mock.expect :report_error_event, nil, [Hash] + mock.expect :report_error_event, nil, [], project_name: String, event: Google::Cloud::ErrorReporting::V1beta1::ReportedErrorEvent end end @@ -103,7 +104,7 @@ def mock_error_reporting doctest.before "Google::Cloud::ErrorReporting::Service" do mock_error_reporting do |mock| - mock.expect :report_error_event, nil, [Hash] + mock.expect :report_error_event, nil, [], project_name: String, event: Google::Cloud::ErrorReporting::V1beta1::ReportedErrorEvent end end end diff --git a/google-cloud-error_reporting/test/google/cloud/error_reporting/service_test.rb b/google-cloud-error_reporting/test/google/cloud/error_reporting/service_test.rb new file mode 100644 index 000000000000..29176cb63a02 --- /dev/null +++ b/google-cloud-error_reporting/test/google/cloud/error_reporting/service_test.rb @@ -0,0 +1,67 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" +require "signet/oauth_2/client" + +describe Google::Cloud::ErrorReporting::Service do # rubocop:disable Metrics/BlockLength + let(:project) { "test-project" } + let :credentials do + creds = Signet::OAuth2::Client.new + def creds.quota_project_id + "credentials-quota-project" + end + + def creds.disable_universe_domain_check + true + end + creds + end + + describe ".new" do + it "sets project and credentials" do + service = Google::Cloud::ErrorReporting::Service.new project, credentials + _(service.project).must_equal project + _(service.credentials).must_equal credentials + end + + it "accepts quota_project" do + quota_project = "test-quota-project" + service = Google::Cloud::ErrorReporting::Service.new project, credentials, quota_project: quota_project + _(service.quota_project).must_equal quota_project + end + + it "falls back to credentials quota_project_id if not explicitly passed" do + service = Google::Cloud::ErrorReporting::Service.new project, credentials + _(service.quota_project).must_equal "credentials-quota-project" + end + end + + describe "#error_reporting" do + it "configures the gRPC client with quota_project" do + quota_project = "test-quota-project" + service = Google::Cloud::ErrorReporting::Service.new project, credentials, quota_project: quota_project + + client = service.error_reporting + _(client.configure.quota_project).must_equal quota_project + end + + it "configures the gRPC client with credentials quota_project" do + service = Google::Cloud::ErrorReporting::Service.new project, credentials + + client = service.error_reporting + _(client.configure.quota_project).must_equal "credentials-quota-project" + end + end +end diff --git a/google-cloud-error_reporting/test/google/cloud/error_reporting_test.rb b/google-cloud-error_reporting/test/google/cloud/error_reporting_test.rb index f01c3c01eb56..7d5c96a28e18 100644 --- a/google-cloud-error_reporting/test/google/cloud/error_reporting_test.rb +++ b/google-cloud-error_reporting/test/google/cloud/error_reporting_test.rb @@ -66,11 +66,12 @@ def creds.is_a? target it "uses provided endpoint" do endpoint = "errorreporting-endpoint2.example.com" - stubbed_service = ->(project, credentials, timeout: nil, host: nil) { + stubbed_service = ->(project, credentials, timeout: nil, host: nil, quota_project: nil) { _(project).must_equal "project-id" _(credentials).must_equal default_credentials _(timeout).must_be :nil? _(host).must_equal endpoint + _(quota_project).must_be :nil? OpenStruct.new project: project } ENV.stub :[], nil do @@ -85,6 +86,7 @@ def creds.is_a? target end end + it "uses provided project (alias), keyfile (alias), service, and version" do stubbed_credentials = ->(keyfile, scope: nil) { _(keyfile).must_equal "/path/to/a/keyfile" @@ -315,11 +317,12 @@ def creds.is_a? target _(scope).must_equal default_scopes "error_reporting-credentials" } - stubbed_service = ->(project, credentials, timeout: nil, host: nil) { + stubbed_service = ->(project, credentials, timeout: nil, host: nil, quota_project: nil) { _(project).must_equal "project-id" _(credentials).must_equal "error_reporting-credentials" _(timeout).must_be :nil? _(host).must_equal default_endpoint + _(quota_project).must_be :nil? OpenStruct.new project: project } @@ -352,11 +355,12 @@ def creds.is_a? target _(scope).must_equal default_scopes "error_reporting-credentials" } - stubbed_service = ->(project, credentials, timeout: nil, host: nil) { + stubbed_service = ->(project, credentials, timeout: nil, host: nil, quota_project: nil) { _(project).must_equal "project-id" _(credentials).must_equal "error_reporting-credentials" _(timeout).must_be :nil? _(host).must_equal default_endpoint + _(quota_project).must_be :nil? OpenStruct.new project: project } @@ -389,11 +393,12 @@ def creds.is_a? target _(scope).must_equal default_scopes "error_reporting-credentials" } - stubbed_service = ->(project, credentials, timeout: nil, host: nil) { + stubbed_service = ->(project, credentials, timeout: nil, host: nil, quota_project: nil) { _(project).must_equal "project-id" _(credentials).must_equal "error_reporting-credentials" _(timeout).must_equal 42 _(host).must_equal default_endpoint + _(quota_project).must_be :nil? OpenStruct.new project: project } @@ -423,11 +428,12 @@ def creds.is_a? target it "uses error_reporting config for endpoint" do endpoint = "errorreporting-endpoint2.example.com" - stubbed_service = ->(project, credentials, timeout: nil, host: nil) { + stubbed_service = ->(project, credentials, timeout: nil, host: nil, quota_project: nil) { _(project).must_equal "project-id" _(credentials).must_equal default_credentials _(timeout).must_be :nil? _(host).must_equal endpoint + _(quota_project).must_be :nil? OpenStruct.new project: project } @@ -454,11 +460,12 @@ def creds.is_a? target _(scope).must_equal default_scopes "error_reporting-credentials" } - stubbed_service = ->(project, credentials, timeout: nil, host: nil) { + stubbed_service = ->(project, credentials, timeout: nil, host: nil, quota_project: nil) { _(project).must_equal "project-id" _(credentials).must_equal "error_reporting-credentials" _(timeout).must_equal 42 _(host).must_equal default_endpoint + _(quota_project).must_be :nil? OpenStruct.new project: project } @@ -485,5 +492,29 @@ def creds.is_a? target end end end + + it "uses error_reporting config for quota_project" do + stubbed_service = lambda do |project, credentials, timeout: nil, host: nil, quota_project: nil| + _(project).must_equal "project-id" + _(credentials).must_equal default_credentials + _(timeout).must_be :nil? + _(host).must_equal default_endpoint + _(quota_project).must_equal "configure-quota-project" + OpenStruct.new project: project + end + + ENV.stub :[], nil do + Google::Cloud::ErrorReporting.configure do |config| + config.project_id = "project-id" + config.quota_project = "configure-quota-project" + end + + Google::Cloud::ErrorReporting::Service.stub :new, stubbed_service do + error_reporting = Google::Cloud::ErrorReporting.new credentials: default_credentials + _(error_reporting).must_be_kind_of Google::Cloud::ErrorReporting::Project + _(error_reporting.project).must_equal "project-id" + end + end + end end end