Class: Gitlab::Triage::CommandBuilders::TextContentBuilder

Inherits:
BaseCommandBuilder show all
Defined in:
lib/gitlab/triage/command_builders/text_content_builder.rb

Constant Summary collapse

SUPPORTED_PLACEHOLDERS =
{
  created_at: "{{created_at}}",
  updated_at: "{{updated_at}}",
  closed_at: "{{closed_at}}",
  merged_at: "{{merged_at}}",
  state: "{{state}}",
  author: "@{{author.username}}",
  assignee: "@{{assignee.username}}",
  assignees: "@{{assignees.username}}",
  source_branch: "{{source_branch}}",
  target_branch: "{{target_branch}}",
  closed_by: "@{{closed_by.username}}",
  merged_by: "@{{merged_by.username}}",
  milestone: %(%"{{milestone.title}}"),
  labels: %(~"{{labels}}"),
  upvotes: "{{upvotes}}",
  downvotes: "{{downvotes}}",
  title: "{{title}}",
  web_url: "{{web_url}}",
  full_reference: "{{references.full}}",
  type: "{{type}}",
  items: "{{items}}",
  name: "{{name}}"
}.freeze
PLACEHOLDER_REGEX =
/{{([\w\.]+)}}/.freeze

Instance Attribute Summary

Attributes inherited from BaseCommandBuilder

#items, #network, #resource

Instance Method Summary collapse

Methods inherited from BaseCommandBuilder

#build_command, #content_string, #slash_command_string

Constructor Details

#initialize(items, resource: nil, network: nil, redact_confidentials: true) ⇒ TextContentBuilder

Returns a new instance of TextContentBuilder.



39
40
41
42
43
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 39

def initialize(
  items, resource: nil, network: nil, redact_confidentials: true)
  super(items, resource: resource, network: network)
  @redact_confidentials = redact_confidentials
end

Instance Method Details

#eval_interpolation(item) ⇒ Object (private)



57
58
59
60
61
62
63
64
65
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 57

def eval_interpolation(item)
  quoted_comment = "%Q{#{item}}"

  Resource::Context.build(
    resource,
    network: network,
    redact_confidentials: @redact_confidentials
  ).eval(quoted_comment)
end

#extract_attributes(path) ⇒ Object (private)



97
98
99
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 97

def extract_attributes(path)
  redact_attributes(path, resource_dig_and_map(path.split('.')))
end

#format_item(item) ⇒ Object (private)



51
52
53
54
55
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 51

def format_item(item)
  return item unless resource

  replace_placeholders(eval_interpolation(item))
end

#redact_attributes(path, attributes) ⇒ Object (private)



121
122
123
124
125
126
127
128
129
130
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 121

def redact_attributes(path, attributes)
  return attributes unless redact_confidential_attributes?

  case path
  when 'web_url', 'items', 'type', 'references.full'
    attributes # No need to redact them
  else
    [Resource::Base::CONFIDENTIAL_TEXT]
  end
end

#redact_confidential_attributes?Boolean (private)

Returns:

  • (Boolean)


132
133
134
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 132

def redact_confidential_attributes?
  @redact_confidentials && resource[:confidential]
end

#replace_placeholders(item) ⇒ Object (private)



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 67

def replace_placeholders(item)
  SUPPORTED_PLACEHOLDERS.inject(item) do |comment, (placeholder, template)|
    next comment unless comment.include?("{{#{placeholder}}}")

    path = template[/.*#{PLACEHOLDER_REGEX}.*/, 1]
    attributes = extract_attributes(path)

    formatted_text = attributes.map do |attribute|
      template.sub(PLACEHOLDER_REGEX, attribute.to_s)
    end.join(', ')

    escaped_text =
      case placeholder
      when :items
        # We don't need to escape it because it's recursive,
        # which the contents should all be escaped already.
        # Or put it another way, items isn't an attribute
        # retrieved externally. It's a generated value which
        # should be safe to begin with. At some point we
        # may want to make this more distinguishable,
        # separating values from API and values generated.
        formatted_text
      else
        CGI.escape_html(formatted_text)
      end

    comment.gsub("{{#{placeholder}}}", escaped_text)
  end
end

#resource_dig_and_map(indices) ⇒ Object (private)

If we don’t have to map arrays, we can simply do:

resource.dig(*indices)

Thus this method name. The only array here is ‘assignees`



106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 106

def resource_dig_and_map(indices)
  attributes = indices.inject(resource) do |result, index|
    break unless result

    case result
    when Array
      result.flat_map { |sub_resource| sub_resource[index] }
    else
      result[index]
    end
  end

  Array.wrap(attributes)
end

#separatorObject (private)



47
48
49
# File 'lib/gitlab/triage/command_builders/text_content_builder.rb', line 47

def separator
  "\n\n"
end