Commit 8e84acbf authored by Kamil Trzcinski's avatar Kamil Trzcinski

Optimise CI status accessor

parent 89f0dc71
......@@ -44,8 +44,12 @@ module Ci
sha[0...8]
end
def self.stages
CommitStatus.where(commit: all).stages
end
def stages
statuses.group(:stage).order(:stage_idx).pluck(:stage)
statuses.stages
end
def project_id
......
......@@ -49,6 +49,7 @@ class CommitStatus < ActiveRecord::Base
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :commit_id)) }
scope :ordered, -> { order(:ref, :stage_idx, :name) }
scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) }
AVAILABLE_STATUSES = ['pending', 'running', 'success', 'failed', 'canceled']
......@@ -84,6 +85,40 @@ class CommitStatus < ActiveRecord::Base
delegate :before_sha, :sha, :short_sha, to: :commit, prefix: false
def self.stages
order_by = 'max(stage_idx)'
group('stage').order(order_by).pluck(:stage, order_by).map(&:first).compact
end
def self.status_sql
builds = all.select('count(id)').to_sql
success = all.success.select('count(id)').to_sql
ignored = all.failed.where(allow_failure: true).select('count(id)').to_sql if all.try(:ignored)
ignored ||= '0'
pending = all.pending.select('count(id)').to_sql
running = all.running.select('count(id)').to_sql
canceled = all.canceled.select('count(id)').to_sql
deduce_status = "(CASE
WHEN (#{builds})=0 THEN 'skipped'
WHEN (#{builds})=(#{success})+(#{ignored}) THEN 'success'
WHEN (#{builds})=(#{pending}) THEN 'pending'
WHEN (#{builds})=(#{canceled}) THEN 'canceled'
WHEN (#{running})+(#{pending})>0 THEN 'running'
ELSE 'failed'
END)"
deduce_status
end
def self.status
pluck(self.status_sql).first
end
def self.stages_status
Hash[group(:stage).pluck(:stage, self.status_sql)]
end
def ignored?
allow_failure? && (failed? || canceled?)
end
......
......@@ -43,6 +43,7 @@ module CiStatus
scope :pending, -> { where(status: 'pending') }
scope :success, -> { where(status: 'success') }
scope :failed, -> { where(status: 'failed') }
scope :canceled, -> { where(status: 'canceled') }
scope :running_or_pending, -> { where(status: [:running, :pending]) }
scope :finished, -> { where(status: [:success, :failed, :canceled]) }
end
......
class AddCiCommitIndexes < ActiveRecord::Migration
def change
add_index :ci_commits, [:gl_project_id, :sha]
add_index :ci_commits, [:gl_project_id, :status]
add_index :ci_commits, [:status]
end
end
class UpdateCiCommit < ActiveRecord::Migration
def change
execute("UPDATE ci_commits SET status=#{status}, ref=#{ref}, tag=#{tag} WHERE status IS NULL")
end
def status
builds = '(SELECT COUNT(*) FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id)'
success = "(SELECT COUNT(*) FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id AND status='success')"
ignored = "(SELECT COUNT(*) FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id AND (status='failed' OR status='canceled') AND allow_failure)"
pending = "(SELECT COUNT(*) FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id AND status='pending')"
running = "(SELECT COUNT(*) FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id AND status='running')"
canceled = "(SELECT COUNT(*) FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id AND status='canceled')"
"(CASE
WHEN #{builds}=0 THEN 'skipped'
WHEN #{builds}=#{success}+#{ignored} THEN 'success'
WHEN #{builds}=#{pending} THEN 'pending'
WHEN #{builds}=#{canceled} THEN 'canceled'
WHEN #{running}+#{pending}>0 THEN 'running'
ELSE 'failed'
END)"
end
def ref
'(SELECT ref FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id ORDER BY id DESC LIMIT 1)'
end
def tag
'(SELECT tag FROM ci_builds WHERE ci_builds.commit_id=ci_commits.id ORDER BY id DESC LIMIT 1)'
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment