summaryrefslogtreecommitdiff
path: root/app/models/project.rb
blob: ed5bc2e9951368b6791ba298ad19a018b7692cf6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
class Project < ActiveRecord::Base
  attr_accessible :name, :path, :scripts, :timeout, :token,
    :default_ref, :gitlab_url, :always_build, :polling_interval

  has_many :builds, dependent: :destroy


  #
  # Validations
  #
  validates_presence_of :name, :path, :scripts, :timeout, :token, :default_ref
  validate :repo_present?
  validates_uniqueness_of :name

  validates :polling_interval,
    presence: true,
    if: ->(project) { project.always_build.present? }

  before_validation :set_default_values
  after_save :set_scheduler

  def set_default_values
    self.token = SecureRandom.hex(15) if self.token.blank?
  end

  def repo_present?
    repo
  rescue Grit::NoSuchPathError, Grit::InvalidGitRepositoryError
    errors.add(:path, 'Project path is not a git repository')
    false
  end

  def register_build opts={}
    ref = opts[:ref]

    raise 'ref is not defined' unless ref

    if ref.include? 'heads'
      ref = ref.scan(/heads\/(.*)$/).flatten[0]
    end

    before_sha = opts[:before]
    sha = opts[:after] || last_ref_sha(ref)

    data = {
      project_id: self.id,
      ref: ref,
      sha: sha,
      before_sha: before_sha
    }

    @build = Build.create(data)
  end

  def gitlab?
    gitlab_url.present?
  end

  def last_ref_sha ref
    `cd #{self.path} && git fetch && git log remotes/origin/#{ref} -1 --format=oneline | grep -e '^[a-z0-9]*' -o`.strip
  end

  def status
    if last_build
      last_build.status
    end
  end

  def last_build
    builds.last
  end

  def last_build_date
    last_build.try(:updated_at)
  end

  def human_status
    status
  end

  def status_image ref = 'master'
    build = self.builds.where(ref: ref).latest_sha.last
    image_for_build build
  end

  def last_build_for_sha sha
    builds.where(sha: sha).order('id DESC').limit(1).first
  end

  def sha_status_image sha
    build = last_build_for_sha(sha)
    image_for_build build
  end

  def image_for_build build
    return 'unknown.png' unless build

    if build.success?
      'success.png'
    elsif build.failed?
      'failed.png'
    elsif build.active?
      'running.png'
    else
      'unknown.png'
    end
  end

  def repo
    @repo ||= Grit::Repo.new(path)
  end

  def last_commit(ref = 'master')
    repo.commits(ref, 1).first
  end

  def tracked_refs
    @tracked_refs ||= default_ref.split(",").map{|ref| ref.strip}
  end

  def valid_token? token
    self.token && self.token == token
  end

  def set_scheduler
    true
  end

  def schedule_id
    "project-#{id}"
  end
end


# == Schema Information
#
# Table name: projects
#
#  id          :integer(4)      not null, primary key
#  name        :string(255)     not null
#  path        :string(255)     not null
#  timeout     :integer(4)      default(1800), not null
#  scripts     :text            default(""), not null
#  created_at  :datetime        not null
#  updated_at  :datetime        not null
#  token       :string(255)
#  default_ref :string(255)
#