summaryrefslogtreecommitdiff
path: root/app/models/integrations/buildkite.rb
blob: 90593d78a5d2529c3f6e7d4c9fd60255e20b005d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# frozen_string_literal: true

require "addressable/uri"

module Integrations
  class Buildkite < BaseCi
    include HasWebHook
    include ReactivelyCached
    extend Gitlab::Utils::Override

    ENDPOINT = "https://buildkite.com"

    prop_accessor :project_url, :token

    validates :project_url, presence: true, public_url: true, if: :activated?
    validates :token, presence: true, if: :activated?

    def self.supported_events
      %w(push merge_request tag_push)
    end

    # This is a stub method to work with deprecated API response
    # TODO: remove enable_ssl_verification after 14.0
    # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
    def enable_ssl_verification
      true
    end

    # Since SSL verification will always be enabled for Buildkite,
    # we no longer needs to store the boolean.
    # This is a stub method to work with deprecated API param.
    # TODO: remove enable_ssl_verification after 14.0
    # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
    def enable_ssl_verification=(_value)
      self.properties.delete('enable_ssl_verification') # Remove unused key
    end

    override :hook_url
    def hook_url
      "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}"
    end

    def execute(data)
      return unless supported_events.include?(data[:object_kind])

      execute_web_hook!(data)
    end

    def commit_status(sha, ref)
      with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
    end

    def commit_status_path(sha)
      "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
    end

    def build_page(sha, ref)
      "#{project_url}/builds?commit=#{sha}"
    end

    def title
      'Buildkite'
    end

    def description
      'Run CI/CD pipelines with Buildkite.'
    end

    def self.to_param
      'buildkite'
    end

    def help
      s_('ProjectService|Run CI/CD pipelines with Buildkite.')
    end

    def fields
      [
        { type: 'text',
          name: 'token',
          title: _('Token'),
          help: s_('ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository.'),
          required: true },

        { type: 'text',
          name: 'project_url',
          title: _('Pipeline URL'),
          placeholder: "#{ENDPOINT}/example-org/test-pipeline",
          required: true }
      ]
    end

    def calculate_reactive_cache(sha, ref)
      response = Gitlab::HTTP.try_get(commit_status_path(sha), request_options)

      status =
        if response&.code == 200 && response['status']
          response['status']
        else
          :error
        end

      { commit_status: status }
    end

    private

    def webhook_token
      token_parts.first
    end

    def status_token
      token_parts.second
    end

    def token_parts
      if token.present?
        token.split(':')
      else
        []
      end
    end

    def buildkite_endpoint(subdomain = nil)
      if subdomain.present?
        uri = Addressable::URI.parse(ENDPOINT)
        new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}"

        if uri.port.present?
          "#{new_endpoint}:#{uri.port}"
        else
          new_endpoint
        end
      else
        ENDPOINT
      end
    end

    def request_options
      { extra_log_info: { project_id: project_id } }
    end
  end
end