1# frozen_string_literal: true
2
3module Atlassian
4  module JiraConnect
5    module Serializers
6      class FeatureFlagEntity < Grape::Entity
7        include Gitlab::Routing
8
9        alias_method :flag, :object
10
11        format_with(:string, &:to_s)
12
13        expose :schema_version, as: :schemaVersion
14        expose :id, format_with: :string
15        expose :name, as: :key
16        expose :update_sequence_id, as: :updateSequenceId
17        expose :name, as: :displayName
18        expose :summary
19        expose :details
20        expose :issue_keys, as: :issueKeys
21
22        def issue_keys
23          @issue_keys ||= JiraIssueKeyExtractor.new(flag.description).issue_keys
24        end
25
26        def schema_version
27          '1.0'
28        end
29
30        def update_sequence_id
31          options[:update_sequence_id] || Client.generate_update_sequence_id
32        end
33
34        STRATEGY_NAMES = {
35          ::Operations::FeatureFlags::Strategy::STRATEGY_DEFAULT => 'All users',
36          ::Operations::FeatureFlags::Strategy::STRATEGY_GITLABUSERLIST => 'User List',
37          ::Operations::FeatureFlags::Strategy::STRATEGY_GRADUALROLLOUTUSERID => 'Percent of users',
38          ::Operations::FeatureFlags::Strategy::STRATEGY_FLEXIBLEROLLOUT => 'Percent rollout',
39          ::Operations::FeatureFlags::Strategy::STRATEGY_USERWITHID => 'User IDs'
40        }.freeze
41
42        private
43
44        # The summary does not map very well to our FeatureFlag model.
45        #
46        # We allow feature flags to have multiple strategies, depending
47        # on the environment. Jira expects a single rollout strategy.
48        #
49        # Also, we don't actually support showing a single flag, so we use the
50        # edit path as an interim solution.
51        def summary(strategies = flag.strategies)
52          {
53            url: edit_project_feature_flag_url(flag.project, flag),
54            lastUpdated: flag.updated_at.iso8601,
55            status: {
56              enabled: flag.active,
57              defaultValue: '',
58              rollout: {
59                percentage: strategies.map do |s|
60                  s.parameters['rollout'] || s.parameters['percentage']
61                end.compact.first&.to_f,
62                text: strategies.map { |s| STRATEGY_NAMES[s.name] }.compact.join(', ')
63              }.compact
64            }
65          }
66        end
67
68        def details
69          envs = flag.strategies.flat_map do |s|
70            s.scopes.map do |es|
71              env_type = es.environment_scope.scan(/development|testing|staging|production/).first
72              [es.environment_scope, env_type, s]
73            end
74          end
75
76          envs.map do |env_name, env_type, strat|
77            summary([strat]).merge(environment: { name: env_name, type: env_type }.compact)
78          end
79        end
80      end
81    end
82  end
83end
84