Skip to content

Allow groups to require licensed seats for Duo Chat

Jessie Young requested to merge jy-groups-opt-out-chat-ga into master

This MR is urgent and high priority. See this thread for more information.

What does this MR do and why?

  • The current default behavior, as of GA of Duo Chat, is that any GitLab user who belongs to a Premium or Ultimate group can use Duo Chat.
  • With this MR: If the feature flag 'duo_chat_requires_licensed_seat' is enabled for a root group, members of that root group will only be given Chat access if they also have a Duo Pro seat.
  • This allows customers to opt into seat-based licensing for Chat before the "free access cut-off" date, which will be in the future.
  • #457090 (closed)

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Screenshots are required for UI changes, and strongly recommended for all other merge requests.

Before After

How to set up and validate locally

################
# Condition:
# - Make sure that the user is a member of the group.
# - The user does not have duo pro seat.
User.first.member_namespaces.by_root_id(Group.first).any? # => true
User.first.any_group_with_ai_chat_available? # => true
User.first.duo_pro_add_on_available? # => false

# Test Case: When flag is disabled, user can access chat.
Feature.disable(:duo_chat_requires_licensed_seat)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => true

# Test Case: When flag is enabled on the specific group, user can't access chat.
Feature.enable(:duo_chat_requires_licensed_seat, Group.first)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => false

# Test Case: When flag is disabled on the specific group, user can access chat.
Feature.disable(:duo_chat_requires_licensed_seat, Group.first)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => true

# Test Case: When flag is enabled globally, user can't access chat.
Feature.disable(:duo_chat_requires_licensed_seat) # Cleanup all gates and enable globally
Feature.enable(:duo_chat_requires_licensed_seat)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => false

################
# Update condition:
# - The user has duo pro seat.
User.first.duo_pro_add_on_available? # => true

# Test Case: When flag is disabled, user can access chat.
Feature.disable(:duo_chat_requires_licensed_seat)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => true

# Test Case: When flag is enabled on the specific group, user can access chat.
Feature.enable(:duo_chat_requires_licensed_seat, Group.first)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => true

# Test Case: When flag is disabled on the specific group, user can access chat.
Feature.disable(:duo_chat_requires_licensed_seat, Group.first)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => true

# Test Case: When flag is enabled globally, user can access chat.
Feature.disable(:duo_chat_requires_licensed_seat) # Cleanup all gates and enable globally
Feature.enable(:duo_chat_requires_licensed_seat)
User.clear_group_with_ai_available_cache([User.first.id]) # Clear cache
User.first.can?(:access_duo_chat) # => true
Edited by Shinya Maeda

Merge request reports