diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index 0ad8a08960ae07d008c3369abb59947b27f503a3..a326fa308adc48d59bb0141ae3bc618e221b0ed5 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -12,6 +12,7 @@ module IssuableActions before_action :authorize_destroy_issuable!, only: :destroy before_action :check_destroy_confirmation!, only: :destroy before_action :authorize_admin_issuable!, only: :bulk_update + before_action :set_application_context!, only: :show end def show @@ -226,6 +227,10 @@ def authorize_update_issuable! render_404 unless can?(current_user, :"update_#{resource_name}", issuable) end + def set_application_context! + # no-op. The logic is defined in EE module. + end + def bulk_update_params clean_bulk_update_params( params.require(:update).permit(bulk_update_permitted_keys) diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb index 6fd9eae9edba706e82bfd2f4c9f89e92f02100c9..66a358963e2388dbc49bfe255fd9941759d47e3f 100644 --- a/app/controllers/projects/merge_requests/conflicts_controller.rb +++ b/app/controllers/projects/merge_requests/conflicts_controller.rb @@ -75,6 +75,8 @@ def resolve_conflicts private + alias_method :issuable, :merge_request + def authorize_can_resolve_conflicts! @conflicts_list = ::MergeRequests::Conflicts::ListService.new(@merge_request) diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 69f7d3f0ff59c4ec93987be239a6374d9f5a4741..c0dcdb01d48dd389a12391817da99ca4e0cbee46 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -1045,6 +1045,7 @@ Input type: `AdminSidekiqQueuesDeleteJobsInput` | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="mutationadminsidekiqqueuesdeletejobsairesource"></a>`aiResource` | [`String`](#string) | Delete jobs matching ai_resource in the context metadata. | | <a id="mutationadminsidekiqqueuesdeletejobsartifactsize"></a>`artifactSize` | [`String`](#string) | Delete jobs matching artifact_size in the context metadata. | | <a id="mutationadminsidekiqqueuesdeletejobsartifactusedcdn"></a>`artifactUsedCdn` | [`String`](#string) | Delete jobs matching artifact_used_cdn in the context metadata. | | <a id="mutationadminsidekiqqueuesdeletejobsartifactsdependenciescount"></a>`artifactsDependenciesCount` | [`String`](#string) | Delete jobs matching artifacts_dependencies_count in the context metadata. | diff --git a/ee/app/controllers/concerns/ee/issuable_actions.rb b/ee/app/controllers/concerns/ee/issuable_actions.rb index 83b899353c20858ec774f3b97979c129cd920d90..e307ceef64f526577330f5c0286d63b6069d3dc3 100644 --- a/ee/app/controllers/concerns/ee/issuable_actions.rb +++ b/ee/app/controllers/concerns/ee/issuable_actions.rb @@ -18,5 +18,10 @@ module IssuableActions def bulk_update_permitted_keys @permitted_keys ||= (super + EE_PERMITTED_KEYS).freeze end + + override :set_application_context! + def set_application_context! + ::Gitlab::ApplicationContext.push(ai_resource: issuable.try(:to_global_id)) + end end end diff --git a/ee/app/controllers/ee/projects/issues_controller.rb b/ee/app/controllers/ee/projects/issues_controller.rb index 38dc727837666985ec6ef3fecd7390667f6a484d..916369300ad4c51f9b228141f4fda14d4d7de9d6 100644 --- a/ee/app/controllers/ee/projects/issues_controller.rb +++ b/ee/app/controllers/ee/projects/issues_controller.rb @@ -21,9 +21,7 @@ module IssuesController before_action only: :show do push_licensed_feature(:escalation_policies, project) push_force_frontend_feature_flag(:summarize_comments, can?(current_user, :summarize_notes, issue)) - push_force_frontend_feature_flag(:generate_description_ai, - can?(current_user, :generate_description, issue)) - @ai_resource_id = issue.to_global_id + push_force_frontend_feature_flag(:generate_description_ai, can?(current_user, :generate_description, issue)) end before_action :redirect_if_test_case, only: [:show] diff --git a/ee/app/views/layouts/_tanuki_bot_chat.html.haml b/ee/app/views/layouts/_tanuki_bot_chat.html.haml index 26ec492b903121d718bd79508158329c22d9801b..fc55f95c1b4534ee6c465b4040fcc1b9e1e73d44 100644 --- a/ee/app/views/layouts/_tanuki_bot_chat.html.haml +++ b/ee/app/views/layouts/_tanuki_bot_chat.html.haml @@ -1,3 +1,4 @@ - return unless ::Gitlab::Llm::TanukiBot.enabled_for?(user: current_user) +- resource_id = Gitlab::ApplicationContext.current_context_attribute(:ai_resource).presence -#js-tanuki-bot-chat-app{ data: { user_id: current_user.to_global_id, resource_id: @ai_resource_id } } +#js-tanuki-bot-chat-app{ data: { user_id: current_user.to_global_id, resource_id: resource_id } } diff --git a/ee/lib/ee/gitlab/application_context.rb b/ee/lib/ee/gitlab/application_context.rb index 0f2027c64dd9f40da6271b23f23e74d3c6bfbba8..ec7c3ae9dbcca99f2c7f7145c2f2e4d915ebdc12 100644 --- a/ee/lib/ee/gitlab/application_context.rb +++ b/ee/lib/ee/gitlab/application_context.rb @@ -6,8 +6,15 @@ module ApplicationContext extend ::Gitlab::Utils::Override extend ActiveSupport::Concern + Attribute = Struct.new(:name, :type) + EE_KNOWN_KEYS = [ - :subscription_plan + :subscription_plan, + :ai_resource + ].freeze + + EE_APPLICATION_ATTRIBUTES = [ + Attribute.new(:ai_resource, ::GlobalID) ].freeze class_methods do @@ -17,11 +24,18 @@ module ApplicationContext def known_keys super + EE_KNOWN_KEYS end + + override :application_attributes + def application_attributes + super + EE_APPLICATION_ATTRIBUTES + end end override :to_lazy_hash def to_lazy_hash super.tap do |hash| + assign_hash_if_value(hash, :ai_resource) + hash[:subscription_plan] = -> { subcription_plan_name } if include_namespace? end end diff --git a/ee/spec/lib/ee/gitlab/application_context_spec.rb b/ee/spec/lib/ee/gitlab/application_context_spec.rb index dc7f27b1427d6ac105ca629b5eb4cb5d1e65569e..d3a783fba9891a45bc773a5afa2f13c697e4b624 100644 --- a/ee/spec/lib/ee/gitlab/application_context_spec.rb +++ b/ee/spec/lib/ee/gitlab/application_context_spec.rb @@ -50,6 +50,7 @@ def result(context) [:remote_ip] | [:remote_ip, :client_id] [:runner] | [:project, :root_namespace, :client_id, :subscription_plan] [:caller_id] | [:caller_id] + [:ai_resource] | [:ai_resource] [] | [] end diff --git a/ee/spec/requests/projects/issues_controller_spec.rb b/ee/spec/requests/projects/issues_controller_spec.rb index c941514b781d0294b3135b07e9b5d454e7ee9564..82919fa9b75483918e9f504db1f02cb915ebe07c 100644 --- a/ee/spec/requests/projects/issues_controller_spec.rb +++ b/ee/spec/requests/projects/issues_controller_spec.rb @@ -115,12 +115,6 @@ def get_show end end end - - it 'assigns ai_resource_id' do - get_show - - expect(assigns(:ai_resource_id)).to eq(issue.to_global_id) - end end describe 'GET #index' do diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb index 0ea52b7b7c8213dd519626f74fa0b50336d238ae..67fc2ae2fcc0d37e4c932299746afd4d61d0d540 100644 --- a/lib/gitlab/application_context.rb +++ b/lib/gitlab/application_context.rb @@ -47,11 +47,16 @@ class ApplicationContext Attribute.new(:root_caller_id, String), Attribute.new(:merge_action_status, String) ].freeze + private_constant :APPLICATION_ATTRIBUTES def self.known_keys KNOWN_KEYS end + def self.application_attributes + APPLICATION_ATTRIBUTES + end + def self.with_context(args, &block) application_context = new(**args) application_context.use(&block) @@ -79,12 +84,13 @@ def self.current_context_attribute(attribute_name) end def initialize(**args) - unknown_attributes = args.keys - APPLICATION_ATTRIBUTES.map(&:name) + unknown_attributes = args.keys - self.class.application_attributes.map(&:name) raise ArgumentError, "#{unknown_attributes} are not known keys" if unknown_attributes.any? @set_values = args.keys assign_attributes(args) + set_attr_readers end # rubocop: disable Metrics/CyclomaticComplexity @@ -122,12 +128,14 @@ def use attr_reader :set_values - APPLICATION_ATTRIBUTES.each do |attr| - lazy_attr_reader attr.name, type: attr.type + def set_attr_readers + self.class.application_attributes.each do |attr| + self.class.lazy_attr_reader attr.name, type: attr.type + end end def assign_hash_if_value(hash, attribute_name) - unless KNOWN_KEYS.include?(attribute_name) + unless self.class.known_keys.include?(attribute_name) raise ArgumentError, "unknown attribute `#{attribute_name}`" end @@ -137,7 +145,7 @@ def assign_hash_if_value(hash, attribute_name) end def assign_attributes(values) - values.slice(*APPLICATION_ATTRIBUTES.map(&:name)).each do |name, value| + values.slice(*self.class.application_attributes.map(&:name)).each do |name, value| instance_variable_set("@#{name}", value) end end