diff options
Diffstat (limited to 'app/models/integrations/buildkite.rb')
-rw-r--r-- | app/models/integrations/buildkite.rb | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb new file mode 100644 index 00000000000..906a5d02f9c --- /dev/null +++ b/app/models/integrations/buildkite.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true + +require "addressable/uri" + +module Integrations + class Buildkite < BaseCi + include ReactiveService + + 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? + + after_save :compose_service_hook, 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 + + def webhook_url + "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}" + end + + def compose_service_hook + hook = service_hook || build_service_hook + hook.url = webhook_url + hook.enable_ssl_verification = true + hook.save + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + + service_hook.execute(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 fields + [ + { type: 'text', + name: 'token', + title: 'Integration Token', + help: 'This token will be provided when you create a Buildkite pipeline with a GitLab repository', + required: true }, + + { type: 'text', + name: 'project_url', + title: 'Pipeline URL', + placeholder: "#{ENDPOINT}/acme-inc/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 + { verify: false, extra_log_info: { project_id: project_id } } + end + end +end |