1# frozen_string_literal: true
2
3module Atlassian
4  module JiraConnect
5    module Serializers
6      # A Jira 'build' represents what we call a 'pipeline'
7      class BuildEntity < Grape::Entity
8        include Gitlab::Routing
9
10        format_with(:iso8601, &:iso8601)
11
12        expose :schema_version, as: :schemaVersion
13        expose :pipeline_id, as: :pipelineId
14        expose :iid, as: :buildNumber
15        expose :update_sequence_id, as: :updateSequenceNumber
16        expose :source_ref, as: :displayName
17        expose :url
18        expose :state
19        expose :updated_at, as: :lastUpdated, format_with: :iso8601
20        expose :issue_keys, as: :issueKeys
21        expose :test_info, as: :testInfo
22        expose :references
23
24        def issue_keys
25          # extract Jira issue keys from either the source branch/ref or the
26          # merge request title.
27          @issue_keys ||= begin
28            pipeline.all_merge_requests.flat_map do |mr|
29              src = "#{mr.source_branch} #{mr.title}"
30              JiraIssueKeyExtractor.new(src).issue_keys
31            end.uniq
32          end
33        end
34
35        private
36
37        alias_method :pipeline, :object
38        delegate :project, to: :object
39
40        def url
41          project_pipeline_url(project, pipeline)
42        end
43
44        # translate to Jira status
45        def state
46          case pipeline.status
47          when 'scheduled', 'created', 'pending', 'preparing', 'waiting_for_resource' then 'pending'
48          when 'running' then 'in_progress'
49          when 'success' then 'successful'
50          when 'failed' then 'failed'
51          when 'canceled', 'skipped' then 'cancelled'
52          else
53            'unknown'
54          end
55        end
56
57        def pipeline_id
58          pipeline.ensure_ci_ref!
59
60          pipeline.ci_ref.id.to_s
61        end
62
63        def schema_version
64          '1.0'
65        end
66
67        def test_info
68          builds = pipeline.builds.pluck(:status) # rubocop: disable CodeReuse/ActiveRecord
69          n = builds.size
70          passed = builds.count { |s| s == 'success' }
71          failed = builds.count { |s| s == 'failed' }
72
73          {
74            totalNumber: n,
75            numberPassed: passed,
76            numberFailed: failed,
77            numberSkipped: n - (passed + failed)
78          }
79        end
80
81        def references
82          ref = pipeline.source_ref
83
84          [{
85            commit: { id: pipeline.sha, repositoryUri: project_url(project) },
86            ref: { name: ref, uri: project_commits_url(project, ref) }
87          }]
88        end
89
90        def update_sequence_id
91          options[:update_sequence_id] || Client.generate_update_sequence_id
92        end
93      end
94    end
95  end
96end
97