summaryrefslogtreecommitdiff
path: root/app/models/project.rb
blob: 3db8ef5def9ad6684fd553499e7d2fe0cf20e2d3 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# == Schema Information
#
# Table name: projects
#
#  id                        :integer          not null, primary key
#  name                      :string(255)      not null
#  timeout                   :integer          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)
#  gitlab_url                :string(255)
#  always_build              :boolean          default(FALSE), not null
#  polling_interval          :integer
#  public                    :boolean          default(FALSE), not null
#  ssh_url_to_repo           :string(255)
#  gitlab_id                 :integer
#  allow_git_fetch           :boolean          default(TRUE), not null
#  email_recipients          :string(255)
#  email_add_committer       :boolean          default(TRUE), not null 
#  email_only_breaking_build :boolean          default(TRUE), not null 
#

class Project < ActiveRecord::Base
  attr_accessible :name, :path, :scripts, :timeout, :token,
    :default_ref, :gitlab_url, :always_build, :polling_interval,
    :public, :ssh_url_to_repo, :gitlab_id, :allow_git_fetch, 
    :email_recipients, :email_add_committer, :email_only_breaking_build

  has_many :builds, dependent: :destroy
  has_many :runner_projects, dependent: :destroy
  has_many :runners, through: :runner_projects

  #
  # Validations
  #
  validates_presence_of :name, :scripts, :timeout, :token, :default_ref, :gitlab_url, :ssh_url_to_repo, :gitlab_id

  validates_uniqueness_of :name

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


  scope :public, where(public: true)

  before_validation :set_default_values

  class << self
    def parse(project_yaml)
      project = YAML.load(project_yaml)

      params = {
        name: project.name_with_namespace,
        gitlab_id: project.id,
        gitlab_url: project.web_url,
        scripts: 'ls -la',
        default_ref: project.default_branch || 'master',
        ssh_url_to_repo: project.ssh_url_to_repo,
        email_add_committer:       GitlabCi.config.gitlab_ci.add_committer,
        email_only_breaking_build: GitlabCi.config.gitlab_ci.only_breaking_build,
      }

      Project.new(params)
    end

    def from_gitlab(user, page, per_page, scope = :owned)
      opts = { private_token: user.private_token }
      opts[:per_page] = per_page if per_page.present?
      opts[:page]     = page     if page.present?

      projects = Network.new.projects(user.url, opts, scope)

      if projects
        projects.map { |pr| OpenStruct.new(pr) }
      else
        []
      end
    end

    def already_added?(project)
      where(gitlab_url: project.web_url).any?
    end
  end

  def set_default_values
    self.token = SecureRandom.hex(15) if self.token.blank?
  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]

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

    @build = Build.create(data)
  end

  def gitlab?
    gitlab_url.present?
  end

  def status
    last_build.status if last_build
  end

  def last_build
    builds.last
  end

  def last_build_date
    last_build.try(:created_at)
  end

  def human_status
    status
  end

  def status_image ref = 'master'
    build = self.builds.where(ref: ref).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 tracked_refs
    @tracked_refs ||= default_ref.split(",").map{|ref| ref.strip}
  end

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

  def no_running_builds?
    # Get running builds not later than 3 days ago to ignore hangs
    builds.running.where("updated_at > ?", 3.days.ago).empty?
  end
  
  def email_notification?
    email_add_committer || !email_recipients.blank?
  end
  
end