From 914cfbd2f154ed3154a7dc3cee3309713eea786f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 6 Oct 2015 12:01:16 +0200 Subject: Implement Commit Status API --- app/models/ci/commit.rb | 88 +++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 47 deletions(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index fde754a92a1..042a68681bb 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -20,7 +20,8 @@ module Ci extend Ci::Model belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id - has_many :builds, dependent: :destroy, class_name: 'Ci::Build' + has_many :statuses, dependent: :destroy, class_name: 'CommitStatus' + has_many :builds, class_name: 'Ci::Build' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' validates_presence_of :sha @@ -81,12 +82,11 @@ module Ci end def stage - running_or_pending = builds_without_retry.running_or_pending - running_or_pending.limit(1).pluck(:stage).first + running_or_pending = statuses.latest.running_or_pending + running_or_pending.first.try(:stage) end def create_builds(ref, tag, user, trigger_request = nil) - return if skip_ci? && trigger_request.blank? return unless config_processor config_processor.stages.any? do |stage| CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present? @@ -94,7 +94,6 @@ module Ci end def create_next_builds(ref, tag, user, trigger_request) - return if skip_ci? && trigger_request.blank? return unless config_processor stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage) @@ -107,39 +106,47 @@ module Ci end def refs - builds.group(:ref).pluck(:ref) + statuses.pluck(:ref).compact.uniq end - def last_ref - builds.latest.first.try(:ref) - end - - def builds_without_retry - builds.latest + def statuses_for_ref(ref = nil) + if ref + statuses.for_ref(ref) + else + statuses + end end - def builds_without_retry_for_ref(ref) - builds.for_ref(ref).latest + def builds_without_retry(ref = nil) + if ref + builds.for_ref(ref).latest + else + builds.latest + end end - def retried_builds - @retried_builds ||= (builds.order(id: :desc) - builds_without_retry) + def retried + @retried ||= (statuses.order(id: :desc) - statuses.latest) end - def status - if skip_ci? - return 'skipped' - elsif yaml_errors.present? + def status(ref = nil) + if yaml_errors.present? return 'failed' - elsif builds.none? + end + + latest_statuses = statuses.latest.to_a + latest_statuses.reject! { |status| status.try(&:allow_failure?) } + latest_statuses.select! { |status| status.ref == nil || status.ref == ref } if ref + + if latest_statuses.none? return 'skipped' - elsif success? + elsif latest_statuses.all?(&:success?) 'success' - elsif pending? + elsif latest_statuses.all?(&:pending?) 'pending' - elsif running? + elsif latest_statuses.any?(&:running?) || latest_statuses.any?(&:pending?) 'running' - elsif canceled? + elsif latest_statuses.all?(&:canceled?) 'canceled' else 'failed' @@ -147,21 +154,15 @@ module Ci end def pending? - builds_without_retry.all? do |build| - build.pending? - end + status == 'pending' end def running? - builds_without_retry.any? do |build| - build.running? || build.pending? - end + status == 'running' end def success? - builds_without_retry.all? do |build| - build.success? || build.ignored? - end + status == 'success' end def failed? @@ -169,21 +170,15 @@ module Ci end def canceled? - builds_without_retry.all? do |build| - build.canceled? - end - end - - def duration - @duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i + status == 'canceled' end - def duration_for_ref(ref) - builds_without_retry_for_ref(ref).select(&:duration).sum(&:duration).to_i + def duration(ref = nil) + statuses_for_ref(ref).latest.select(&:duration).sum(&:duration).to_i end def finished_at - @finished_at ||= builds.order('finished_at DESC').first.try(:finished_at) + @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at) end def coverage @@ -195,8 +190,8 @@ module Ci end end - def matrix_for_ref?(ref) - builds_without_retry_for_ref(ref).pluck(:id).size > 1 + def matrix?(ref) + builds_without_retry(ref).pluck(:id).size > 1 end def config_processor @@ -217,7 +212,6 @@ module Ci end def skip_ci? - return false if builds.any? git_commit_message =~ /(\[ci skip\])/ if git_commit_message end -- cgit v1.2.1 From 0aefeeb882b40d740b80f15ac6610a88a340d30b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 12:16:00 +0200 Subject: Add Commit Status documentation --- app/models/ci/commit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 042a68681bb..623ff619c49 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -136,7 +136,7 @@ module Ci latest_statuses = statuses.latest.to_a latest_statuses.reject! { |status| status.try(&:allow_failure?) } - latest_statuses.select! { |status| status.ref == nil || status.ref == ref } if ref + latest_statuses.select! { |status| status.ref.nil? || status.ref == ref } if ref if latest_statuses.none? return 'skipped' -- cgit v1.2.1 From 789fe7b4899fb97c48ad363c5ecb1969d78d1536 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 16:32:58 +0200 Subject: Update rendering --- app/models/ci/commit.rb | 66 ++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 623ff619c49..201b6f62b86 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -106,50 +106,47 @@ module Ci end def refs - statuses.pluck(:ref).compact.uniq + statuses.order(:ref).pluck(:ref).uniq end - def statuses_for_ref(ref = nil) - if ref - statuses.for_ref(ref) - else - statuses - end + def latest_statuses + @latest_statuses ||= statuses.latest.to_a end - def builds_without_retry(ref = nil) - if ref - builds.for_ref(ref).latest - else - builds.latest - end + def builds_without_retry + @builds_without_retry ||= builds.latest.to_a + end + + def builds_without_retry_for_ref(ref) + builds_without_retry.select { |build| build.ref == ref } end def retried @retried ||= (statuses.order(id: :desc) - statuses.latest) end - def status(ref = nil) + def status if yaml_errors.present? return 'failed' end - latest_statuses = statuses.latest.to_a - latest_statuses.reject! { |status| status.try(&:allow_failure?) } - latest_statuses.select! { |status| status.ref.nil? || status.ref == ref } if ref - - if latest_statuses.none? - return 'skipped' - elsif latest_statuses.all?(&:success?) - 'success' - elsif latest_statuses.all?(&:pending?) - 'pending' - elsif latest_statuses.any?(&:running?) || latest_statuses.any?(&:pending?) - 'running' - elsif latest_statuses.all?(&:canceled?) - 'canceled' - else - 'failed' + @status ||= begin + latest = latest_statuses + latest.reject! { |status| status.try(&:allow_failure?) } + + if latest.none? + 'skipped' + elsif latest.all?(&:success?) + 'success' + elsif latest.all?(&:pending?) + 'pending' + elsif latest.any?(&:running?) || latest.any?(&:pending?) + 'running' + elsif latest.all?(&:canceled?) + 'canceled' + else + 'failed' + end end end @@ -173,8 +170,9 @@ module Ci status == 'canceled' end - def duration(ref = nil) - statuses_for_ref(ref).latest.select(&:duration).sum(&:duration).to_i + def duration + duration_array = latest_statuses.map(&:duration).compact + duration_array.reduce(:+).to_i end def finished_at @@ -190,8 +188,8 @@ module Ci end end - def matrix?(ref) - builds_without_retry(ref).pluck(:id).size > 1 + def matrix_for_ref?(ref) + builds_without_retry_for_ref(ref).size > 1 end def config_processor -- cgit v1.2.1 From 5cd504ed331dd23d17709285237945fb867978a8 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 16:39:08 +0200 Subject: Rename builds_without_retry to latest_builds --- app/models/ci/commit.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 201b6f62b86..296890c5e7c 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -48,7 +48,7 @@ module Ci end def retry - builds_without_retry.each do |build| + latest_builds.each do |build| Ci::Build.retry(build) end end @@ -113,12 +113,12 @@ module Ci @latest_statuses ||= statuses.latest.to_a end - def builds_without_retry - @builds_without_retry ||= builds.latest.to_a + def latest_builds + @latest_builds ||= builds.latest.to_a end - def builds_without_retry_for_ref(ref) - builds_without_retry.select { |build| build.ref == ref } + def latest_builds_for_ref(ref) + latest_builds.select { |build| build.ref == ref } end def retried @@ -181,7 +181,7 @@ module Ci def coverage if project.coverage_enabled? - coverage_array = builds_without_retry.map(&:coverage).compact + coverage_array = latest_builds.map(&:coverage).compact if coverage_array.size >= 1 '%.2f' % (coverage_array.reduce(:+) / coverage_array.size) end @@ -189,7 +189,7 @@ module Ci end def matrix_for_ref?(ref) - builds_without_retry_for_ref(ref).size > 1 + latest_builds_for_ref(ref).size > 1 end def config_processor -- cgit v1.2.1 From daca1c6511c3a09d5f0c33a8c4d29487e668afc2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 21:35:52 +0200 Subject: Fix broken tests --- app/models/ci/commit.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 296890c5e7c..f6fc4645947 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -82,7 +82,7 @@ module Ci end def stage - running_or_pending = statuses.latest.running_or_pending + running_or_pending = statuses.latest.running_or_pending.ordered running_or_pending.first.try(:stage) end @@ -189,7 +189,7 @@ module Ci end def matrix_for_ref?(ref) - latest_builds_for_ref(ref).size > 1 + builds_without_retry_for_ref(ref).size > 1 end def config_processor -- cgit v1.2.1 From 766da5fa7bdded8a333a758d7b172533ade5a934 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 22:34:59 +0200 Subject: Fix broken matrix_for_ref? Signed-off-by: Kamil Trzcinski --- app/models/ci/commit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index f6fc4645947..68864edfbbf 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -189,7 +189,7 @@ module Ci end def matrix_for_ref?(ref) - builds_without_retry_for_ref(ref).size > 1 + latest_builds_for_ref(ref).size > 1 end def config_processor -- cgit v1.2.1 From 09255eecd0812d35b09613a1cf2402d3108fcc49 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 14 Oct 2015 14:07:41 +0200 Subject: Remove ordering from :ci_commits relation --- app/models/ci/commit.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 68864edfbbf..cd45366b34e 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -24,6 +24,8 @@ module Ci has_many :builds, class_name: 'Ci::Build' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' + scope :ordered, -> { order('CASE WHEN ci_commits.committed_at IS NULL THEN 0 ELSE 1 END', :committed_at, :id) } + validates_presence_of :sha validate :valid_commit_sha -- cgit v1.2.1 From 0aa6061d6ab0ab921ad585329b43b84d20da873e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Oct 2015 15:08:31 +0200 Subject: Implement when syntax in .gitlab-ci.yml --- app/models/ci/commit.rb | 52 ++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) (limited to 'app/models/ci/commit.rb') diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index cd45366b34e..13437b2483f 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -91,19 +91,28 @@ module Ci def create_builds(ref, tag, user, trigger_request = nil) return unless config_processor config_processor.stages.any? do |stage| - CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present? + CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request, 'success').present? end end - def create_next_builds(ref, tag, user, trigger_request) + def create_next_builds(build) return unless config_processor - stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage) + # don't create other builds if this one is retried + latest_builds = builds.similar(build).latest + return unless latest_builds.exists?(build.id) - config_processor.stages.any? do |stage| - unless stages.include?(stage) - CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present? - end + # get list of stages after this build + next_stages = config_processor.stages.drop_while { |stage| stage != build.stage } + next_stages.delete(build.stage) + + # get status for all prior builds + prior_builds = latest_builds.reject { |other_build| next_stages.include?(other_build.stage) } + status = Ci::Status.get_status(prior_builds) + + # create builds for next stages based + next_stages.any? do |stage| + CreateBuildsService.new.execute(self, stage, build.ref, build.tag, build.user, build.trigger_request, status).present? end end @@ -132,24 +141,7 @@ module Ci return 'failed' end - @status ||= begin - latest = latest_statuses - latest.reject! { |status| status.try(&:allow_failure?) } - - if latest.none? - 'skipped' - elsif latest.all?(&:success?) - 'success' - elsif latest.all?(&:pending?) - 'pending' - elsif latest.any?(&:running?) || latest.any?(&:pending?) - 'running' - elsif latest.all?(&:canceled?) - 'canceled' - else - 'failed' - end - end + @status ||= Ci::Status.get_status(latest_statuses) end def pending? @@ -219,16 +211,6 @@ module Ci update!(committed_at: DateTime.now) end - def should_create_next_builds?(build) - # don't create other builds if this one is retried - other_builds = builds.similar(build).latest - return false unless other_builds.include?(build) - - other_builds.all? do |build| - build.success? || build.ignored? - end - end - private def save_yaml_error(error) -- cgit v1.2.1