1# frozen_string_literal: true 2 3module Ci 4 ## 5 # This domain model is a representation of a group of jobs that are related 6 # to each other, like `rspec 0 1`, `rspec 0 2`. 7 # 8 # It is not persisted in the database. 9 # 10 class Group 11 include StaticModel 12 include Gitlab::Utils::StrongMemoize 13 include GlobalID::Identification 14 15 attr_reader :project, :stage, :name, :jobs 16 17 delegate :size, to: :jobs 18 19 def initialize(project, stage, name:, jobs:) 20 @project = project 21 @stage = stage 22 @name = name 23 @jobs = jobs 24 end 25 26 def id 27 "#{stage.id}-#{name}" 28 end 29 30 def ==(other) 31 other.present? && other.is_a?(self.class) && 32 project == other.project && 33 stage == other.stage && 34 name == other.name 35 end 36 37 def status 38 strong_memoize(:status) do 39 status_struct.status 40 end 41 end 42 43 def success? 44 status.to_s == 'success' 45 end 46 47 def has_warnings? 48 status_struct.warnings? 49 end 50 51 def status_struct 52 strong_memoize(:status_struct) do 53 Gitlab::Ci::Status::Composite 54 .new(@jobs, project: project) 55 end 56 end 57 58 def detailed_status(current_user) 59 if jobs.one? 60 jobs.first.detailed_status(current_user) 61 else 62 Gitlab::Ci::Status::Group::Factory 63 .new(self, current_user).fabricate! 64 end 65 end 66 67 # Construct a grouping of statuses for this stage. 68 # We allow the caller to pass in statuses for efficiency (avoiding N+1 69 # queries). 70 def self.fabricate(project, stage, statuses = nil) 71 statuses ||= stage.latest_statuses 72 73 statuses 74 .sort_by(&:sortable_name).group_by(&:group_name) 75 .map do |group_name, grouped_statuses| 76 self.new(project, stage, name: group_name, jobs: grouped_statuses) 77 end 78 end 79 end 80end 81