Commit 51769eb2 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'ce-981829f3-to-master' into 'master'

Merge CE 981829f3 into EE master

This merges everything up to (and including) CE commit 981829f3 into EE. This was done mainly to have the update guides for CE also in EE along with any other changes since the last merge.

See merge request !442
parents ff0bfe78 e774b022
......@@ -96,6 +96,11 @@ scss-lint:
script:
- bundle exec rake scss_lint
license-finder:
stage: test
script:
- bundle exec license_finder
brakeman:
stage: test
script:
......
......@@ -6,6 +6,7 @@ v 8.8.1
v 8.9.0 (unreleased)
- Bulk assign/unassign labels to issues.
- Allow enabling wiki page events from Webhook management UI
- Bump rouge to 1.11.0
- Make EmailsOnPushWorker use Sidekiq mailers queue
- Fix wiki page events' webhook to point to the wiki repository
- Fix issue todo not remove when leave project !4150 (Long Nguyen)
......@@ -39,8 +40,10 @@ v 8.9.0 (unreleased)
- Cache project build count in sidebar nav
- Reduce number of queries needed to render issue labels in the sidebar
- Improve error handling importing projects
- Remove duplicated notification settings
- Put project Files and Commits tabs under Code tab
- Replace Colorize with Rainbow for coloring console output in Rake tasks.
- An indicator is now displayed at the top of the comment field for confidential issues.
v 8.8.4 (unreleased)
- Ensure branch cleanup regardless of whether the GitHub import process succeeds
......@@ -48,6 +51,10 @@ v 8.8.4 (unreleased)
- Fix todos page throwing errors when you have a project pending deletion
- Reduce number of SQL queries when rendering user references
- Upgrade to jQuery 2
- Remove prev/next buttons on issues and merge requests
- Import GitHub repositories respecting the API rate limit
- Fix importer for GitHub comments on diff
- Disable Webhooks before proceeding with the GitHub import
v 8.8.3
- Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312
......@@ -168,6 +175,7 @@ v 8.7.6
- Fix import from GitLab.com to a private instance failure. !4181
- Fix external imports not finding the import data. !4106
- Fix notification delay when changing status of an issue
- Bump Workhorse to 0.7.5 so it can serve raw diffs
v 8.7.5
- Fix relative links in wiki pages. !4050
......
......@@ -121,7 +121,7 @@ gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2'
gem 'rouge', '~> 1.10.1'
gem 'rouge', '~> 1.11'
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
......@@ -317,6 +317,8 @@ group :development, :test do
gem 'bundler-audit', require: false
gem 'benchmark-ips', require: false
gem "license_finder", require: false
end
group :test do
......
......@@ -390,6 +390,12 @@ GEM
actionmailer (>= 3.2)
letter_opener (~> 1.0)
railties (>= 3.2)
license_finder (2.1.0)
bundler
httparty
rubyzip
thor
xml-simple
licensee (8.0.0)
rugged (>= 0.24b)
listen (3.0.5)
......@@ -593,7 +599,7 @@ GEM
railties (>= 4.2.0, < 5.1)
rinku (1.7.3)
rotp (2.1.2)
rouge (1.10.1)
rouge (1.11.0)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
......@@ -642,6 +648,7 @@ GEM
sexp_processor (~> 4.1)
rubyntlm (0.5.2)
rubypants (0.2.0)
rubyzip (1.2.0)
rufus-scheduler (3.1.10)
rugged (0.24.0)
safe_yaml (1.0.4)
......@@ -816,6 +823,7 @@ GEM
builder
expression_parser
rinku
xml-simple (1.1.5)
xpath (2.0.0)
nokogiri (~> 1.3)
......@@ -907,6 +915,7 @@ DEPENDENCIES
jwt
kaminari (~> 0.17.0)
letter_opener_web (~> 1.3.0)
license_finder
licensee (~> 8.0.0)
loofah (~> 2.0.3)
mail_room (~> 0.7)
......@@ -959,7 +968,7 @@ DEPENDENCIES
request_store (~> 1.3.0)
rerun (~> 0.11.0)
responders (~> 2.0)
rouge (~> 1.10.1)
rouge (~> 1.11)
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.4.0)
rspec-retry
......
......@@ -10,14 +10,6 @@ class @ShortcutsIssuable extends ShortcutsNavigation
@replyWithSelectedText()
return false
)
Mousetrap.bind('j', =>
@prevIssue()
return false
)
Mousetrap.bind('k', =>
@nextIssue()
return false
)
Mousetrap.bind('e', =>
@editIssue()
return false
......@@ -29,16 +21,6 @@ class @ShortcutsIssuable extends ShortcutsNavigation
else
@enabledHelp.push('.hidden-shortcut.issues')
prevIssue: ->
$prevBtn = $('.prev-btn')
if not $prevBtn.hasClass('disabled')
Turbolinks.visit($prevBtn.attr('href'))
nextIssue: ->
$nextBtn = $('.next-btn')
if not $nextBtn.hasClass('disabled')
Turbolinks.visit($nextBtn.attr('href'))
replyWithSelectedText: ->
if window.getSelection
selected = window.getSelection().toString()
......
......@@ -66,10 +66,6 @@
display: none;
}
%ul.notes .note-role, .note-actions {
display: none;
}
.nav-links, .nav-links {
li a {
font-size: 14px;
......
......@@ -87,6 +87,39 @@
}
}
.md-header .nav-links {
display: flex;
display: -webkit-flex;
flex-flow: row wrap;
-webkit-flex-flow: row wrap;
width: 100%;
.pull-right {
// Flexbox quirk to make sure right-aligned items stay right-aligned.
margin-left: auto;
}
}
.confidential-issue-warning {
background-color: $gray-normal;
border-radius: 3px;
padding: 3px 12px;
margin: auto;
margin-top: 0;
text-align: center;
font-size: 13px;
@media (max-width: $screen-md-min) {
// On smaller devices the warning becomes the fourth item in the list,
// rather than centering, and grows to span the full width of the
// comment area.
order: 4;
-webkit-order: 4;
margin: 6px auto;
width: 100%;
}
}
.discussion-form {
padding: $gl-padding-top $gl-padding;
background-color: $white-light;
......
......@@ -134,6 +134,11 @@ ul.notes {
.note-header {
padding-bottom: 3px;
padding-right: 20px;
@media (min-width: $screen-sm-min) {
padding-right: 0;
}
}
.note-emoji-button {
......@@ -211,6 +216,8 @@ ul.notes {
.discussion-header,
.note-header {
position: relative;
a {
color: inherit;
......@@ -247,6 +254,16 @@ ul.notes {
color: $notes-action-color;
}
.note-actions {
position: absolute;
right: 0;
top: 0;
@media (min-width: $screen-sm-min) {
position: relative;
}
}
.discussion-actions {
@media (max-width: $screen-md-max) {
float: none;
......@@ -260,8 +277,13 @@ ul.notes {
.note-action-button {
display: inline-block;
margin-left: 0;
line-height: 20px;
@media (min-width: $screen-sm-min) {
margin-left: 10px;
line-height: 24px;
}
.fa {
color: $notes-action-color;
......
......@@ -26,9 +26,9 @@ class Projects::BuildsController < Projects::ApplicationController
end
def show
@builds = @project.ci_commits.find_by_sha(@build.sha).builds.order('id DESC')
@builds = @project.pipelines.find_by_sha(@build.sha).builds.order('id DESC')
@builds = @builds.where("id not in (?)", @build.id)
@commit = @build.commit
@pipeline = @build.pipeline
respond_to do |format|
format.html
......
......@@ -99,12 +99,12 @@ class Projects::CommitController < Projects::ApplicationController
@commit ||= @project.commit(params[:id])
end
def ci_commits
@ci_commits ||= project.ci_commits.where(sha: commit.sha)
def pipelines
@pipelines ||= project.pipelines.where(sha: commit.sha)
end
def ci_builds
@ci_builds ||= Ci::Build.where(commit: ci_commits)
@ci_builds ||= Ci::Build.where(pipeline: pipelines)
end
def define_show_vars
......@@ -117,8 +117,8 @@ class Projects::CommitController < Projects::ApplicationController
@diff_refs = [commit.parent || commit, commit]
@notes_count = commit.notes.count
@statuses = CommitStatus.where(commit: ci_commits)
@builds = Ci::Build.where(commit: ci_commits)
@statuses = CommitStatus.where(pipeline: pipelines)
@builds = Ci::Build.where(pipeline: pipelines)
end
def assign_change_commit_vars(mr_source_branch)
......
......@@ -60,8 +60,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
respond_to do |format|
format.html
format.json { render json: @merge_request, methods: :rebase_in_progress? }
format.diff { render text: @merge_request.to_diff }
format.patch { render text: @merge_request.to_patch }
format.diff do
headers.store(*Gitlab::Workhorse.send_git_diff(@project.repository,
@merge_request.diff_base_commit.id,
@merge_request.last_commit.id))
headers['Content-Disposition'] = 'inline'
head :ok
end
end
end
......@@ -121,8 +128,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
@diff_notes_disabled = true
@ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit
@pipeline = @merge_request.pipeline
@statuses = @pipeline.statuses if @pipeline
@note_counts = Note.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
......@@ -130,8 +137,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
set_suggested_approvers
end
def create
@target_branches ||= []
@merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute
......@@ -215,7 +220,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.update(merge_error: nil)
if params[:merge_when_build_succeeds].present? && @merge_request.ci_commit && @merge_request.ci_commit.active?
if params[:merge_when_build_succeeds].present? && @merge_request.pipeline && @merge_request.pipeline.active?
MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user, merge_params)
.execute(@merge_request)
@status = :merge_when_build_succeeds
......@@ -253,10 +258,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def ci_status
ci_commit = @merge_request.ci_commit
if ci_commit
status = ci_commit.status
coverage = ci_commit.try(:coverage)
pipeline = @merge_request.pipeline
if pipeline
status = pipeline.status
coverage = pipeline.try(:coverage)
status ||= "preparing"
else
......@@ -351,8 +356,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request_diff = @merge_request.merge_request_diff
@ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit
@pipeline = @merge_request.pipeline
@statuses = @pipeline.statuses if @pipeline
if @merge_request.locked_long_ago?
@merge_request.unlock_mr
......@@ -361,8 +366,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def define_widget_vars
@ci_commit = @merge_request.ci_commit
@ci_commits = [@ci_commit].compact
@pipeline = @merge_request.pipeline
@pipelines = [@pipeline].compact
closes_issues
end
......@@ -384,7 +389,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :approver_ids,
:target_project_id, :target_branch, :milestone_id,
:state_event, :description, :task_num, :force_remove_source_branch,
label_ids: []
)
......
......@@ -7,7 +7,7 @@ class Projects::PipelinesController < Projects::ApplicationController
def index
@scope = params[:scope]
all_pipelines = project.ci_commits
all_pipelines = project.pipelines
@pipelines_count = all_pipelines.count
@running_or_pending_count = all_pipelines.running_or_pending.count
@pipelines = PipelinesFinder.new(project).execute(all_pipelines, @scope)
......@@ -15,7 +15,7 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def new
@pipeline = project.ci_commits.new(ref: @project.default_branch)
@pipeline = project.pipelines.new(ref: @project.default_branch)
end
def create
......@@ -50,7 +50,7 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def pipeline
@pipeline ||= project.ci_commits.find_by!(id: params[:id])
@pipeline ||= project.pipelines.find_by!(id: params[:id])
end
def commit
......
module CiStatusHelper
def ci_status_path(ci_commit)
project = ci_commit.project
builds_namespace_project_commit_path(project.namespace, project, ci_commit.sha)
def ci_status_path(pipeline)
project = pipeline.project
builds_namespace_project_commit_path(project.namespace, project, pipeline.sha)
end
def ci_status_with_icon(status, target = nil)
......
......@@ -8,14 +8,6 @@ module IssuablesHelper
"right-sidebar-#{sidebar_gutter_collapsed? ? 'collapsed' : 'expanded'}"
end
def issuables_count(issuable)
base_issuable_scope(issuable).maximum(:iid)
end
def next_issuable_for(issuable)
base_issuable_scope(issuable).where('iid > ?', issuable.iid).last
end
def multi_label_name(current_labels, default_label)
# current_labels may be a string from before
if current_labels.is_a?(Array)
......@@ -45,10 +37,6 @@ module IssuablesHelper
end
end
def prev_issuable_for(issuable)
base_issuable_scope(issuable).where('iid < ?', issuable.iid).first
end
def user_dropdown_label(user_id, default_label)
return default_label if user_id.nil?
return "Unassigned" if user_id == "0"
......
......@@ -45,8 +45,8 @@ module Ci
new_build.options = build.options
new_build.commands = build.commands
new_build.tag_list = build.tag_list
new_build.gl_project_id = build.gl_project_id
new_build.commit_id = build.commit_id
new_build.project = build.project
new_build.pipeline = build.pipeline
new_build.name = build.name
new_build.allow_failure = build.allow_failure
new_build.stage = build.stage
......@@ -66,7 +66,7 @@ module Ci
# We use around_transition to create builds for next stage as soon as possible, before the `after_*` is executed
around_transition any => [:success, :failed, :canceled] do |build, block|
block.call
build.commit.create_next_builds(build) if build.commit
build.pipeline.create_next_builds(build) if build.pipeline
end
after_transition any => [:success, :failed, :canceled] do |build|
......@@ -80,7 +80,7 @@ module Ci
end
def retried?
!self.commit.statuses.latest.include?(self)
!self.pipeline.statuses.latest.include?(self)
end
def retry
......@@ -89,7 +89,7 @@ module Ci
def depends_on_builds
# Get builds of the same type
latest_builds = self.commit.builds.latest
latest_builds = self.pipeline.builds.latest
# Return builds from previous stages
latest_builds.where('stage_idx < ?', stage_idx)
......@@ -114,11 +114,11 @@ module Ci
def merge_request
merge_requests = MergeRequest.includes(:merge_request_diff)
.where(source_branch: ref, source_project_id: commit.gl_project_id)
.where(source_branch: ref, source_project_id: pipeline.gl_project_id)
.reorder(iid: :asc)
merge_requests.find do |merge_request|
merge_request.commits.any? { |ci| ci.id == commit.sha }
merge_request.commits.any? { |ci| ci.id == pipeline.sha }
end
end
......@@ -361,8 +361,8 @@ module Ci
end
def global_yaml_variables
if commit.config_processor
commit.config_processor.global_variables.map do |key, value|
if pipeline.config_processor
pipeline.config_processor.global_variables.map do |key, value|
{ key: key, value: value, public: true }
end
else
......@@ -371,8 +371,8 @@ module Ci
end
def job_yaml_variables
if commit.config_processor
commit.config_processor.job_variables(name).map do |key, value|
if pipeline.config_processor
pipeline.config_processor.job_variables(name).map do |key, value|
{ key: key, value: value, public: true }
end
else
......
module Ci
class Commit < ActiveRecord::Base
class Pipeline < ActiveRecord::Base
extend Ci::Model
include Statuseable
self.table_name = 'ci_commits'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
has_many :statuses, class_name: 'CommitStatus'
has_many :builds, class_name: 'Ci::Build'
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id
validates_presence_of :sha
validates_presence_of :status
......@@ -21,7 +23,7 @@ module Ci
def self.stages
# We use pluck here due to problems with MySQL which doesn't allow LIMIT/OFFSET in queries
CommitStatus.where(commit: pluck(:id)).stages
CommitStatus.where(pipeline: pluck(:id)).stages
end
def project_id
......@@ -47,7 +49,7 @@ module Ci
end
def short_sha
Ci::Commit.truncate_sha(sha)
Ci::Pipeline.truncate_sha(sha)
end
def commit_data
......
......@@ -3,7 +3,7 @@ module Ci
extend Ci::Model
belongs_to :trigger, class_name: 'Ci::Trigger'
belongs_to :commit, class_name: 'Ci::Commit'
belongs_to :commit, class_name: 'Ci::Pipeline', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build'
serialize :variables
......
......@@ -214,13 +214,13 @@ class Commit
@raw.short_id(7)
end
def ci_commits
@ci_commits ||= project.ci_commits.where(sha: sha)
def pipelines
@pipeline ||= project.pipelines.where(sha: sha)
end
def status
return @status if defined?(@status)
@status ||= ci_commits.status
@status ||= pipelines.status
end
def revert_branch_name
......
......@@ -4,10 +4,10 @@ class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
belongs_to :commit, class_name: 'Ci::Commit', touch: true
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id, touch: true
belongs_to :user
validates :commit, presence: true
validates :pipeline, presence: true
validates_presence_of :name
......@@ -44,18 +44,18 @@ class CommitStatus < ActiveRecord::Base
end
after_transition [:pending, :running] => :success do |commit_status|
MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.commit.project, nil).trigger(commit_status)
MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.pipeline.project, nil).trigger(commit_status)
end
after_transition any => :failed do |commit_status|
MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.commit.project, nil).execute(commit_status)
MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.pipeline.project, nil).execute(commit_status)
end
end
delegate :sha, :short_sha, to: :commit
delegate :sha, :short_sha, to: :pipeline
def before_sha
commit.before_sha || Gitlab::Git::BLANK_SHA
pipeline.before_sha || Gitlab::Git::BLANK_SHA
end
def self.stages
......
......@@ -317,13 +317,6 @@ class MergeRequest < ActiveRecord::Base
)
end
# Returns the raw diff for this merge request
#
# see "git diff"
def to_diff
target_project.repository.diff_text(diff_base_commit.sha, source_sha)
end
# Returns the commit as a series of email patches.
#
# see "git format-patch"
......@@ -655,8 +648,8 @@ class MergeRequest < ActiveRecord::Base
diverged_commits_count > 0
end
def ci_commit
@ci_commit ||= source_project.ci_commit(last_commit.id, source_branch) if last_commit && source_project
def pipeline
@pipeline ||= source_project.pipeline(last_commit.id, source_branch) if last_commit && source_project
end
def diff_refs
......
......@@ -121,7 +121,7 @@ class Project < ActiveRecord::Base
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
has_many :commit_statuses, dependent: :destroy, class_name: 'CommitStatus', foreign_key: :gl_project_id
has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id
has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :gl_project_id # the builds are created from the commit_statuses
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject', foreign_key: :gl_project_id
has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner'
......@@ -1066,12 +1066,12 @@ class Project < ActiveRecord::Base
!namespace.share_with_group_lock
end
def ci_commit(sha, ref)
ci_commits.order(id: :desc).find_by(sha: sha, ref: ref)
def pipeline(sha, ref)
pipelines.order(id: :desc).find_by(sha: sha, ref: ref)
end
def ensure_ci_commit(sha, ref)
ci_commit(sha, ref) || ci_commits.create(sha: sha, ref: ref)
def ensure_pipeline(sha, ref)
pipeline(sha, ref) || pipelines.create(sha: sha, ref: ref)
end
def enable_ci
......
module Ci
class CreateBuildsService
def initialize(commit)
@commit = commit
def initialize(pipeline)
@pipeline = pipeline
end
def execute(stage, user, status, trigger_request = nil)
builds_attrs = config_processor.builds_for_stage_and_ref(stage, @commit.ref, @commit.tag, trigger_request)
builds_attrs = config_processor.builds_for_stage_and_ref(stage, @pipeline.ref, @pipeline.tag, trigger_request)
# check when to create next build
builds_attrs = builds_attrs.select do |build_attrs|
......@@ -21,7 +21,7 @@ module Ci
builds_attrs.map do |build_attrs|
# don't create the same build twice
unless @commit.builds.find_by(ref: @commit.ref, tag: @commit.tag,
unless @pipeline.builds.find_by(ref: @pipeline.ref, tag: @pipeline.tag,
trigger_request: trigger_request, name: build_attrs[:name])
build_attrs.slice!(:name,
:commands,
......@@ -31,13 +31,13 @@ module Ci
:stage,
:stage_idx)
build_attrs.merge!(ref: @commit.ref,
tag: @commit.tag,
build_attrs.merge!(ref: @pipeline.ref,
tag: @pipeline.tag,
trigger_request: trigger_request,
user: user,
project: @commit.project)
project: @pipeline.project)
@commit.builds.create!(build_attrs)
@pipeline.builds.create!(build_attrs)
end
end
end
......@@ -45,7 +45,7 @@ module Ci
private
def config_processor
@config_processor ||= @commit.config_processor
@config_processor ||= @pipeline.config_processor
end
end
end
module Ci
class CreatePipelineService < BaseService
def execute
pipeline = project.ci_commits.new(params)
pipeline = project.pipelines.new(params)
unless ref_names.include?(params[:ref])
pipeline.errors.add(:base, 'Reference not found')
......@@ -19,7 +19,7 @@ module Ci
end
begin
Ci::Commit.transaction do
Ci::Pipeline.transaction do
pipeline.sha = commit.id
unless pipeline.config_processor
......
......@@ -7,14 +7,14 @@ module Ci
# check if ref is tag
tag = project.repository.find_tag(ref).present?
ci_commit = project.ci_commits.create(sha: commit.sha, ref: ref, tag: tag)
pipeline = project.pipelines.create(sha: commit.sha, ref: ref, tag: tag)
trigger_request = trigger.trigger_requests.create!(
variables: variables,
commit: ci_commit,
commit: pipeline,
)
if ci_commit.create_builds(nil, trigger_request)
if pipeline.create_builds(nil, trigger_request)
trigger_request
end
end
......
......@@ -3,9 +3,9 @@ module Ci
def execute(project, opts)
sha = opts[:sha] || ref_sha(project, opts[:ref])
ci_commits = project.ci_commits.where(sha: sha)
ci_commits = ci_commits.where(ref: opts[:ref]) if opts[:ref]
image_name = image_for_status(ci_commits.status)
pipelines = project.pipelines.where(sha: sha)
pipelines = pipelines.where(ref: opts[:ref]) if opts[:ref]
image_name = image_for_status(pipelines.status)
image_path = Rails.root.join('public/ci', image_name)
OpenStruct.new(path: image_path, name: image_name)
......
......@@ -21,23 +21,23 @@ class CreateCommitBuildsService
return false
end
commit = Ci::Commit.new(project: project, sha: sha, ref: ref, before_sha: before_sha, tag: tag)
pipeline = Ci::Pipeline.new(project: project, sha: sha, ref: ref, before_sha: before_sha, tag: tag)
# Skip creating ci_commit when no gitlab-ci.yml is found
unless commit.ci_yaml_file
# Skip creating pipeline when no gitlab-ci.yml is found
unless pipeline.ci_yaml_file
return false
end
# Create a new ci_commit
commit.save!
# Create a new pipeline
pipeline.save!
# Skip creating builds for commits that have [ci skip]
unless commit.skip_ci?
unless pipeline.skip_ci?
# Create builds for commit
commit.create_builds(user)
pipeline.create_builds(user)
end
commit.touch
commit
pipeline.touch
pipeline
end
end
......@@ -55,12 +55,12 @@ module MergeRequests
def each_merge_request(commit_status)
merge_request_from(commit_status).each do |merge_request|
ci_commit = merge_request.ci_commit
pipeline = merge_request.pipeline
next unless ci_commit
next unless ci_commit.sha == commit_status.sha
next unless pipeline
next unless pipeline.sha == commit_status.sha
yield merge_request, ci_commit
yield merge_request, pipeline
end
end
end
......
......@@ -20,10 +20,10 @@ module MergeRequests
# Triggers the automatic merge of merge_request once the build succeeds
def trigger(commit_status)
each_merge_request(commit_status) do |merge_request, ci_commit|
each_merge_request(commit_status) do |merge_request, pipeline|
next unless merge_request.merge_when_build_succeeds?
next unless merge_request.mergeable?
next unless ci_commit.success?
next unless pipeline.success?
MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params)
end
......
......@@ -52,7 +52,7 @@ module Projects
def create_status
GenericCommitStatus.new(
project: project,
commit: build.commit,
pipeline: build.pipeline,
user: build.user,
ref: build.ref,
stage: 'deploy',
......
......@@ -99,8 +99,8 @@
%td.build-link
- if project
= link_to ci_status_path(build.commit) do
%strong #{build.commit.short_sha}
= link_to ci_status_path(build.pipeline) do
%strong #{build.pipeline.short_sha}
%td.timestamp
- if build.finished_at
......
.event-title
%span.author_name= link_to_author event
%span.event_label{class: event.action_name}
= event_action_name(event)
- if event.target
%strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title
= event.action_name
%strong
= link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title do
= event.target_type.titleize.downcase
= event.target.reference_link_text
- else
= event_action_name(event)
= event_preposition(event)
......
......@@ -4,6 +4,10 @@
%i.fa.fa-github
Import projects from GitHub
%p
%i.fa.fa-warning
To import GitHub pull requests, any pull request source branches that had been deleted are temporarily restored on GitHub. To prevent any connected CI services from being overloaded with dozens of irrelevant branches being created and deleted again, GitHub webhooks are temporarily disabled during the import process.
%p.light
Select projects you want to import.
%hr
......
......@@ -10,7 +10,7 @@
%p
Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.project.namespace, @build.project, @build.sha)}
%p
Author: #{@build.commit.git_author_name}
Author: #{@build.pipeline.git_author_name}
%p
Branch: #{@build.ref}
%p
......@@ -18,7 +18,7 @@
%p
Job: #{@build.name}
%p
Message: #{@build.commit.git_commit_message}
Message: #{@build.pipeline.git_commit_message}
%p
Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.project.namespace, @build.project, @build)}
Build failed for <%= @project.name %>
Status: <%= @build.status %>
Commit: <%= @build.commit.short_sha %>
Author: <%= @build.commit.git_author_name %>
Commit: <%= @build.pipeline.short_sha %>
Author: <%= @build.pipeline.git_author_name %>
Branch: <%= @build.ref %>
Stage: <%= @build.stage %>
Job: <%= @build.name %>
Message: <%= @build.commit.git_commit_message %>
Message: <%= @build.pipeline.git_commit_message %>
Url: <%= namespace_project_build_url(@build.project.namespace, @build.project, @build) %>
......@@ -10,7 +10,7 @@
%p
Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.project.namespace, @build.project, @build.sha)}
%p
Author: #{@build.commit.git_author_name}
Author: #{@build.pipeline.git_author_name}
%p
Branch: #{@build.ref}
%p
......@@ -18,7 +18,7 @@
%p
Job: #{@build.name}
%p
Message: #{@build.commit.git_commit_message}
Message: #{@build.pipeline.git_commit_message}
%p
Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.project.namespace, @build.project, @build)}
Build successful for <%= @project.name %>
Status: <%= @build.status %>
Commit: <%= @build.commit.short_sha %>
Author: <%= @build.commit.git_author_name %>
Commit: <%= @build.pipeline.short_sha %>
Author: <%= @build.pipeline.git_author_name %>
Branch: <%= @build.ref %>
Stage: <%= @build.stage %>
Job: <%= @build.name %>
Message: <%= @build.commit.git_commit_message %>
Message: <%= @build.pipeline.git_commit_message %>
Url: <%= namespace_project_build_url(@build.project.namespace, @build.project, @build) %>
......@@ -7,6 +7,12 @@
%li
%a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 }
Preview
- if defined?(@issue) && @issue.confidential?
%li.confidential-issue-warning
= icon('warning')
%span This is a confidential issue. Your comment will not be visible to the public.
%li.pull-right
%button.zen-control.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 }
Go full screen
......
......@@ -4,7 +4,7 @@
.build-page
.row-content-block.top-block
Build ##{@build.id} for commit
%strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit)
%strong.monospace= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline)
from
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
- merge_request = @build.merge_request
......@@ -13,7 +13,7 @@
= link_to "merge request #{merge_request.to_reference}", merge_request_path(merge_request)
#up-build-trace
- builds = @build.commit.builds.latest.to_a
- builds = @build.pipeline.builds.latest.to_a
- if builds.size > 1
%ul.nav-links.no-top.no-bottom
- builds.each do |build|
......@@ -178,16 +178,16 @@
Commit
.pull-right
%small
= link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline), class: "monospace"
%p
%span.attr-name Branch:
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
%p
%span.attr-name Author:
#{@build.commit.git_author_name}
#{@build.pipeline.git_author_name}
%p
%span.attr-name Message:
#{@build.commit.git_commit_message}
#{@build.pipeline.git_commit_message}
- if @build.tags.any?
.build-widget
......@@ -201,7 +201,7 @@
.build-widget
%h4.title #{pluralize(@builds.count(:id), "other build")} for
= succeed ":" do
= link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline), class: "monospace"
%table.table.builds
- @builds.each_with_index do |build, i|
%tr.build
......
- status = commit.status
- status = pipeline.status
%tr.commit
%td.commit-link
= link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: "ci-status ci-#{status}" do
= link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: "ci-status ci-#{status}" do
= ci_icon_for_status(status)
%strong ##{commit.id}
%strong ##{pipeline.id}
%td
%div.branch-commit
- if commit.ref
= link_to commit.ref, namespace_project_commits_path(@project.namespace, @project, commit.ref), class: "monospace"
- if pipeline.ref
= link_to pipeline.ref, namespace_project_commits_path(@project.namespace, @project, pipeline.ref), class: "monospace"
&middot;
= link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace"
= link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: "commit-id monospace"
&nbsp;
- if commit.tag?
- if pipeline.tag?
%span.label.label-primary tag
- elsif commit.latest?
- elsif pipeline.latest?
%span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest
- if commit.triggered?
- if pipeline.triggered?
%span.label.label-primary triggered
- if commit.yaml_errors.present?
%span.label.label-danger.has-tooltip{ title: "#{commit.yaml_errors}" } yaml invalid
- if commit.builds.any?(&:stuck?)
- if pipeline.yaml_errors.present?
%span.label.label-danger.has-tooltip{ title: "#{pipeline.yaml_errors}" } yaml invalid
- if pipeline.builds.any?(&:stuck?)
%span.label.label-warning stuck
%p.commit-title
- if commit_data = commit.commit_data
- if commit_data = pipeline.commit_data
= link_to_gfm truncate(commit_data.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message"
- else
Cant find HEAD commit for this branch
- stages_status = commit.statuses.stages_status
- stages_status = pipeline.statuses.stages_status
- stages.each do |stage|
%td
- status = stages_status[stage]
- tooltip = "#{stage.titleize}: #{status || 'not found'}"
- if status
= link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do
= link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do
= ci_icon_for_status(status)
- else
.light.has-tooltip{ title: tooltip }
\-
%td
- if commit.started_at && commit.finished_at
- if pipeline.started_at && pipeline.finished_at
%p.duration
#{duration_in_words(commit.finished_at, commit.started_at)}
#{duration_in_words(pipeline.finished_at, pipeline.started_at)}
%td
.controls.hidden-xs.pull-right
- artifacts = commit.builds.latest.select { |b| b.artifacts? }
- artifacts = pipeline.builds.latest.select { |b| b.artifacts? }
- if artifacts.present?
.dropdown.inline.build-artifacts
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
......@@ -63,9 +63,9 @@
%span #{build.name}
- if can?(current_user, :update_pipeline, @project)
- if commit.retryable?
= link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do
- if pipeline.retryable?
= link_to retry_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn has-tooltip', title: "Retry", method: :post do
= icon("repeat")
- if commit.cancelable?
= link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
- if pipeline.cancelable?
= link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
= icon("remove")
- @ci_commits.each do |ci_commit|
= render "ci_commit", ci_commit: ci_commit, pipeline_details: true
- @pipelines.each do |pipeline|
= render "pipeline", pipeline: pipeline, pipeline_details: true
......@@ -53,13 +53,13 @@
- if @commit.status
.commit-info-row
Builds for
= pluralize(@commit.ci_commits.count, 'pipeline')
= pluralize(@commit.pipelines.count, 'pipeline')
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "ci-status-link ci-status-icon-#{@commit.status}" do
= ci_icon_for_status(@commit.status)
= ci_label_for_status(@commit.status)
- if @commit.ci_commits.duration
- if @commit.pipelines.duration
in
= time_interval_in_words @commit.ci_commits.duration
= time_interval_in_words @commit.pipelines.duration
.commit-box.content-block
%h3.commit-title
......
.row-content-block.build-content.middle-block
.pull-right
- if can?(current_user, :update_pipeline, ci_commit.project)
- if ci_commit.builds.latest.failed.any?(&:retryable?)
= link_to "Retry failed", retry_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: 'btn btn-grouped btn-primary', method: :post
- if can?(current_user, :update_pipeline, pipeline.project)
- if pipeline.builds.latest.failed.any?(&:retryable?)
= link_to "Retry failed", retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn btn-grouped btn-primary', method: :post
- if ci_commit.builds.running_or_pending.any?
= link_to "Cancel running", cancel_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
- if pipeline.builds.running_or_pending.any?
= link_to "Cancel running", cancel_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
.oneline.clearfix
- if defined?(pipeline_details) && pipeline_details
Pipeline
= link_to "##{ci_commit.id}", namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: "monospace"
= link_to "##{pipeline.id}", namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "monospace"
with
= pluralize ci_commit.statuses.count(:id), "build"
- if ci_commit.ref
= pluralize pipeline.statuses.count(:id), "build"
- if pipeline.ref
for
= link_to ci_commit.ref, namespace_project_commits_path(ci_commit.project.namespace, ci_commit.project, ci_commit.ref), class: "monospace"
= link_to pipeline.ref, namespace_project_commits_path(pipeline.project.namespace, pipeline.project, pipeline.ref), class: "monospace"
- if defined?(link_to_commit) && link_to_commit
for commit
= link_to ci_commit.short_sha, namespace_project_commit_path(ci_commit.project.namespace, ci_commit.project, ci_commit.sha), class: "monospace"
- if ci_commit.duration
= link_to pipeline.short_sha, namespace_project_commit_path(pipeline.project.namespace, pipeline.project, pipeline.sha), class: "monospace"
- if pipeline.duration
in
= time_interval_in_words ci_commit.duration
= time_interval_in_words pipeline.duration
- if ci_commit.yaml_errors.present?
- if pipeline.yaml_errors.present?
.bs-callout.bs-callout-danger
%h4 Found errors in your .gitlab-ci.yml:
%ul
- ci_commit.yaml_errors.split(",").each do |error|
- pipeline.yaml_errors.split(",").each do |error|
%li= error
You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
- if ci_commit.project.builds_enabled? && !ci_commit.ci_yaml_file
- if pipeline.project.builds_enabled? && !pipeline.ci_yaml_file
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
......@@ -45,8 +45,8 @@
%th Tags
%th Duration
%th Finished at
- if ci_commit.project.build_coverage_enabled?
- if pipeline.project.build_coverage_enabled?
%th Coverage
%th
- ci_commit.statuses.stages.each do |stage|
= render 'projects/commit/ci_stage', stage: stage, statuses: ci_commit.statuses.where(stage: stage)
- pipeline.statuses.stages.each do |stage|
= render 'projects/commit/ci_stage', stage: stage, statuses: pipeline.statuses.where(stage: stage)
......@@ -16,4 +16,4 @@
%li
Commits covered:
%strong
= @project.ci_commits.count(:all)
= @project.pipelines.count(:all)
......@@ -2,12 +2,12 @@
%h2.merge-requests-title
= pluralize(@merge_requests.count, 'Related Merge Request')
%ul.unstyled-list
- has_any_ci = @merge_requests.any?(&:ci_commit)
- has_any_ci = @merge_requests.any?(&:pipeline)
- @merge_requests.each do |merge_request|
%li
%span.merge-request-ci-status
- if merge_request.ci_commit
= render_pipeline_status(merge_request.ci_commit)
- if merge_request.pipeline
= render_pipeline_status(merge_request.pipeline)
- elsif has_any_ci
= icon('blank fw')
%span.merge-request-id
......
......@@ -5,10 +5,10 @@
- @related_branches.each do |branch|
%li
- sha = @project.repository.find_branch(branch).target
- ci_commit = @project.ci_commit(sha, branch) if sha
- if ci_commit
- pipeline = @project.pipeline(sha, branch) if sha
- if ci_copipelinemmit
%span.related-branch-ci-status
= render_pipeline_status(ci_commit)
= render_pipeline_status(pipeline)
%span.related-branch-info
%strong
= link_to namespace_project_compare_path(@project.namespace, @project, from: @project.default_branch, to: branch), class: "label-branch" do
......
......@@ -11,9 +11,9 @@
= icon('ban')
CLOSED
- if merge_request.ci_commit
- if merge_request.pipeline
%li
= render_pipeline_status(merge_request.ci_commit)
= render_pipeline_status(merge_request.pipeline)
- if merge_request.open? && merge_request.broken?
%li
......
......@@ -23,7 +23,7 @@
= link_to url_for(params), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
Commits
%span.badge= @commits.size
- if @ci_commit
- if @pipeline
%li.builds-tab.active
= link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do
Builds
......@@ -43,7 +43,7 @@
%p To preserve performance the line changes are not shown.
- else
= render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @merge_request.diff_refs, show_whitespace_toggle: false
- if @ci_commit
- if @pipeline
#builds.builds.tab-pane
= render "projects/merge_requests/show/builds"
......
......@@ -54,7 +54,7 @@
= link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
Commits
%span.badge= @commits.size
- if @ci_commit
- if @pipeline
%li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
Builds
......
= render "projects/commit/ci_commit", ci_commit: @ci_commit, link_to_commit: true
= render "projects/commit/pipeline", pipeline: @pipeline, link_to_commit: true
- if @ci_commit
- if @pipeline
.mr-widget-heading
- %w[success skipped canceled failed running pending].each do |status|
.ci_widget{ class: "ci-#{status}", style: ("display:none" unless @ci_commit.status == status) }
.ci_widget{ class: "ci-#{status}", style: ("display:none" unless @pipeline.status == status) }
= ci_icon_for_status(status)
%span
CI build
......@@ -9,7 +9,7 @@
for
- commit = @merge_request.last_commit
= succeed "." do
= link_to @ci_commit.short_sha, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, @ci_commit.sha), class: "monospace"
= link_to @pipeline.short_sha, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, @pipeline.sha), class: "monospace"
%span.ci-coverage
= link_to "View details", builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "js-show-tab", data: {action: 'builds'}
......
......@@ -13,7 +13,7 @@
check_enable: #{@merge_request.unchecked? ? "true" : "false"},
ci_status_url: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
gitlab_icon: "#{asset_path 'gitlab_logo.png'}",
ci_status: "#{@merge_request.ci_commit ? @merge_request.ci_commit.status : ''}",
ci_status: "#{@merge_request.pipeline ? @merge_request.pipeline.status : ''}",
ci_message: {
normal: "Build {{status}} for \"{{title}}\"",
preparing: "{{status}} build for \"{{title}}\""
......
- status_class = @ci_commit ? " ci-#{@ci_commit.status}" : nil
- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token
......@@ -6,7 +6,7 @@
.accept-merge-holder.clearfix.js-toggle-container
.clearfix
.accept-action
- if @ci_commit && @ci_commit.active?
- if @pipeline && @pipeline.active?
%span.btn-group
= button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do
Merge When Build Succeeds
......
......@@ -19,15 +19,14 @@
.note-actions
- access = note.project.team.human_max_access(note.author.id)
- if access
%span.note-role
= access
%span.note-role.hidden-xs= access
- if note_editable
= link_to '#', title: 'Award Emoji', class: 'note-action-button note-emoji-button js-add-award js-note-emoji', data: { position: 'right' } do
= icon('spinner spin')
= icon('smile-o')
= link_to '#', title: 'Edit comment', class: 'note-action-button js-note-edit' do
= icon('pencil')
= link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'note-action-button js-note-delete danger' do
= link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'note-action-button hidden-xs js-note-delete danger' do
= icon('trash-o')
.note-body{class: note_editable ? 'js-task-list-container' : ''}
.note-text
......
......@@ -4,7 +4,7 @@
= link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
%span
Pipelines
%span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
%span.badge.count.ci_counter= number_with_delimiter(@project.pipelines.running_or_pending.count)
- if project_nav_tab? :builds
= nav_link(controller: %w(builds)) do
......
......@@ -5,4 +5,4 @@
= render "projects/pipelines/info"
%div.block-connector
= render "projects/commit/ci_commit", ci_commit: @pipeline
= render "projects/commit/pipeline", pipeline: @pipeline
......@@ -18,7 +18,7 @@
You can view the #{link_to "most recent version", namespace_project_wiki_path(@project.namespace, @project, @page)} or browse the #{link_to "history", namespace_project_wiki_history_path(@project.namespace, @project, @page)}.
.wiki-holder.prepend-top-default
.wiki-holder.prepend-top-default.append-bottom-default
.wiki
= preserve do
= render_wiki_content(@page)
......@@ -2,23 +2,8 @@
.issuable-sidebar
- can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
.block.issuable-sidebar-header
%span.issuable-count.hide-collapsed.pull-left
= issuable.iid
of
= issuables_count(issuable)
%a.gutter-toggle.pull-right.js-sidebar-toggle{href: '#'}
= sidebar_gutter_toggle_icon
.issuable-nav.hide-collapsed.pull-right.btn-group{role: 'group', "aria-label" => '...'}
- if prev_issuable = prev_issuable_for(issuable)
= link_to 'Prev', [@project.namespace.becomes(Namespace), @project, prev_issuable], class: 'btn btn-default prev-btn issuable-pager'
- else
%a.btn.btn-default.issuable-pager.disabled{href: '#'}
Prev
- if next_issuable = next_issuable_for(issuable)
= link_to 'Next', [@project.namespace.becomes(Namespace), @project, next_issuable], class: 'btn btn-default next-btn issuable-pager'
- else
%a.btn.btn-default.issuable-pager.disabled{href: '#'}
Next
= form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, format: :json, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f|
.block.assignee
......
......@@ -6,6 +6,10 @@
%ul.well-list
- @query.application_backtrace.each do |location|
%li
%strong
- if defined?(BetterErrors)
= link_to(location.path, BetterErrors.editor[location.path, location.line])
- else
= location.path
%small.light
= t('sherlock.line')
......
......@@ -11,13 +11,17 @@
= @query.duration.round(4)
= t('sherlock.milliseconds')
%li
- frame = @query.last_application_frame
%span.light
#{t('sherlock.origin')}:
%strong
= @query.last_application_frame.path
- if defined?(BetterErrors)
= link_to(frame.path, BetterErrors.editor[frame.path, frame.line])
- else
= frame.path
%small.light
= t('sherlock.line')
= @query.last_application_frame.line
= frame.line
.panel.panel-default
.panel-heading
......
---
# IGNORED GROUPS AND GEMS
- - :ignore_group
- development
- :who: Connor Shea
:why: Development gems are not distributed with the final product and are therefore exempt.
:versions: []
:when: 2016-04-17 21:27:01.054140000 Z
- - :ignore_group
- test
- :who: Connor Shea
:why: Test gems are not distributed with the final product and are therefore exempt.
:versions: []
:when: 2016-04-17 21:27:06.250326000 Z
- - :ignore
- bundler
- :who: Connor Shea
:why: Bundler is MIT licensed but will sometimes fail in CI.
:versions: []
:when: 2016-05-02 06:42:08.045090000 Z
# LICENSE WHITELIST
- - :whitelist
- MIT
- :who: Connor Shea
:why: http://choosealicense.com/licenses/mit/
:versions: []
:when: 2016-04-17 21:12:24.558441000 Z
- - :whitelist
- Apache 2.0
- :who: Connor Shea
:why: http://choosealicense.com/licenses/apache-2.0/
:versions: []
:when: 2016-05-02 05:27:43.762702000 Z
- - :whitelist
- ruby
- :who: Connor Shea
:why: https://github.com/ruby/ruby/blob/ruby_2_1/COPYING
:versions: []
:when: 2016-05-02 05:31:54.498490000 Z
- - :whitelist
- LGPL
- :who: Connor Shea
:why: http://www.gnu.org/licenses/license-list.html#LGPLv2.1
:versions: []
:when: 2016-05-02 05:32:48.645841000 Z
- - :whitelist
- ISC
- :who: Connor Shea
:why: http://www.gnu.org/licenses/license-list.html#ISC
:versions: []
:when: 2016-05-02 05:42:01.894452000 Z
- - :whitelist
- New BSD
- :who: Connor Shea
:why: https://opensource.org/licenses/BSD-3-Clause
:versions: []
:when: 2016-05-02 05:44:38.246021000 Z
- - :whitelist
- LGPL-2.1+
- :who: Connor Shea
:why: Equivalent to LGPL.
:versions: []
:when: 2016-05-02 05:52:56.303239000 Z
- - :whitelist
- BSD
- :who: Connor Shea
:why: https://opensource.org/licenses/BSD-2-Clause
:versions: []
:when: 2016-05-02 05:55:09.796363000 Z
# LICENSE BLACKLIST
- - :blacklist
- GPLv2
- :who: Connor Shea
:why: GPL-licensed libraries cannot be linked to from non-GPL projects.
:versions: []
:when: 2016-05-02 05:29:27.637336000 Z
- - :blacklist
- GPLv3
- :who: Connor Shea
:why: GPL-licensed libraries cannot be linked to from non-GPL projects.
:versions: []
:when: 2016-05-02 05:29:43.904715000 Z
# GEM LICENSES
- - :license
- raphael-rails
- MIT
- :who: Connor Shea
:why: https://github.com/mockdeep/raphael-rails/blob/master/license.txt
:versions: []
:when: 2016-04-17 21:30:07.575392000 Z
- - :license
- rouge
- MIT
- :who: Connor Shea
:why: https://github.com/jneen/rouge/blob/master/LICENSE
:versions: []
:when: 2016-04-17 21:31:29.490394000 Z
- - :license
- pyu-ruby-sasl
- MIT
- :who: Connor Shea
:why: https://github.com/pyu10055/ruby-sasl/blob/master/MIT-LICENSE
:versions: []
:when: 2016-04-17 21:41:55.266420000 Z
- - :license
- six
- MIT
- :who: Connor Shea
:why: https://github.com/randx/six/blob/master/LICENSE
:versions: []
:when: 2016-04-17 21:42:31.420186000 Z
- - :license
- rdoc
- ruby
- :who: Connor Shea
:why: https://github.com/rdoc/rdoc/blob/master/LICENSE.rdoc
:versions: []
:when: 2016-04-17 21:43:30.480413000 Z
- - :license
- expression_parser
- MIT
- :who: Connor Shea
:why: https://github.com/nricciar/expression_parser/blob/master/MIT-LICENSE
:versions: []
:when: 2016-04-17 21:45:41.829912000 Z
- - :license
- creole
- ruby
- :who: Connor Shea
:why: https://github.com/minad/creole#license
:versions: []
:when: 2016-04-17 21:49:10.329759000 Z
- - :license
- eventmachine
- ruby
- :who: Connor Shea
:why: https://github.com/eventmachine/eventmachine/blob/master/LICENSE
:versions: []
:when: 2016-04-17 21:49:10.329759001 Z
- - :license
- unicorn
- ruby
- :who: Connor Shea
:why: http://unicorn.bogomips.org/LICENSE.html
:versions: []
:when: 2016-05-02 05:45:28.817510000 Z
- - :license
- unicorn-worker-killer
- ruby
- :who: Connor Shea
:why: https://github.com/kzk/unicorn-worker-killer/blob/master/LICENSE
:versions: []
:when: 2016-05-02 05:45:38.323867000 Z
- - :license
- json
- ruby
- :who: Connor Shea
:why: https://github.com/flori/json/tree/master#license
:versions: []
:when: 2016-05-02 05:50:07.826564000 Z
- - :license
- unf
- BSD
- :who: Connor Shea
:why: https://github.com/knu/ruby-unf/blob/master/LICENSE
:versions: []
:when: 2016-05-02 05:51:46.886872000 Z
- - :license
- rubypants
- BSD
- :who: Connor Shea
:why: https://github.com/jmcnevin/rubypants/blob/master/LICENSE.rdoc
:versions: []
:when: 2016-05-02 05:56:50.696858000 Z
---
decisions_file: './config/dependency_decisions.yml'
......@@ -19,7 +19,7 @@ class Gitlab::Seeder::Builds
commits = @project.repository.commits('master', path: nil, limit: 5)
commits_sha = commits.map { |commit| commit.raw.id }
commits_sha.map do |sha|
@project.ensure_ci_commit(sha, 'master')
@project.ensure_pipeline(sha, 'master')
end
rescue
[]
......
......@@ -16,21 +16,21 @@ user = User.new(user_args)
user.skip_confirmation!
if user.save
puts "Administrator account created:".green
puts "Administrator account created:".color(:green)
puts
puts "login: root".green
puts "login: root".color(:green)
if user_args.key?(:password)
puts "password: #{user_args[:password]}".green
puts "password: #{user_args[:password]}".color(:green)
else
puts "password: You'll be prompted to create one on your first visit.".green
puts "password: You'll be prompted to create one on your first visit.".color(:green)
end
puts
else
puts "Could not create the default administrator account:".red
puts "Could not create the default administrator account:".color(:red)
puts
user.errors.full_messages.map do |message|
puts "--> #{message}".red
puts "--> #{message}".color(:red)
end
puts
......
class RemoveDuplicatedNotificationSettings < ActiveRecord::Migration
def up
execute <<-SQL
DELETE FROM notification_settings WHERE id NOT IN ( SELECT min_id from (SELECT MIN(id) as min_id FROM notification_settings GROUP BY user_id, source_type, source_id) as dups )
SQL
end
end
class AddIndexToNotificationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def change
add_concurrent_index :notification_settings, [:user_id, :source_id, :source_type], { unique: true, name: "index_notifications_on_user_id_and_source_id_and_source_type" }
end
end
......@@ -7,6 +7,7 @@
- [Gotchas](gotchas.md) to avoid
- [How to dump production data to staging](db_dump.md)
- [Instrumentation](instrumentation.md)
- [Licensing](licensing.md) for ensuring license compliance
- [Migration Style Guide](migration_style_guide.md) for creating safe migrations
- [Performance guidelines](performance.md)
- [Rake tasks](rake_tasks.md) for development
......
# GitLab Licensing and Compatibility
GitLab CE is licensed under the terms of the MIT License. GitLab EE is licensed under "The GitLab Enterprise Edition (EE) license" wherein there are more restrictions. See their respective LICENSE files ([CE][CE], [EE][EE]) for more information.
## Automated Testing
In order to comply with the terms the libraries we use are licensed under, we have to make sure to check new gems for compatible licenses whenever they're added. To automate this process, we use the [license_finder][license_finder] gem by Pivotal. It runs every time a new commit is pushed and verifies that all gems in the bundle use a license that doesn't conflict with the licensing of either GitLab Community Edition or GitLab Enterprise Edition.
There are some limitations with the automated testing, however. CSS and JavaScript libraries, as well as any Ruby libraries not included by way of Bundler, must be verified manually and independently. Take care whenever one such library is used, as automated tests won't catch problematic licenses from them.
Some gems may not include their license information in their `gemspec` file. These won't be detected by License Finder, and will have to be verified manually.
### License Finder commands
There are a few basic commands License Finder provides that you'll need in order to manage license detection.
To verify that the checks are passing, and/or to see what dependencies are causing the checks to fail:
```
bundle exec license_finder
```
To whitelist a new license:
```
license_finder whitelist add MIT
```
To blacklist a new license:
```
license_finder blacklist add GPLv2
```
To tell License Finder about a dependency's license if it isn't auto-detected:
```
license_finder licenses add my_unknown_dependency MIT
```
For all of the above, please include `--why "Reason"` and `--who "My Name"` so the `decisions.yml` file can keep track of when, why, and who approved of a dependency.
More detailed information on how the gem and its commands work is available in the [License Finder README][license_finder].
## Acceptable Licenses
Libraries with the following licenses are acceptable for use:
- [The MIT License][MIT] (the MIT Expat License specifically): The MIT License requires that the license itself is included with all copies of the source. It is a permissive (non-copyleft) license as defined by the Open Source Initiative.
- [LGPL][LGPL] (version 2, version 3): GPL constraints regarding modification and redistribution under the same license are not required of projects using an LGPL library, only upon modification of the LGPL-licensed library itself.
- [Apache 2.0 License][apache-2]: A permissive license that also provides an express grant of patent rights from contributors to users.
- [Ruby 1.8 License][ruby-1.8]: Dual-licensed under either itself or the GPLv2, defer to the Ruby License itself. Acceptable because of point 3b: "You may distribute the software in object code or binary form, provided that you do at least ONE of the following: b) accompany the distribution with the machine-readable source of the software."
- [Ruby 1.9 License][ruby-1.9]: Dual-licensed under either itself or the BSD 2-Clause License, defer to BSD 2-Clause.
- [BSD 2-Clause License][BSD-2-Clause]: A permissive (non-copyleft) license as defined by the Open Source Initiative.
- [BSD 3-Clause License][BSD-3-Clause] (also known as New BSD or Modified BSD): A permissive (non-copyleft) license as defined by the Open Source Initiative
- [ISC License][ISC] (also known as the OpenBSD License): A permissive (non-copyleft) license as defined by the Open Source Initiative.
## Unacceptable Licenses
Libraries with the following licenses are unacceptable for use:
- [GNU GPL][GPL] (version 1, [version 2][GPLv2], [version 3][GPLv3], or any future versions): GPL-licensed libraries cannot be linked to from non-GPL projects.
- [GNU AGPLv3][AGPLv3]: AGPL-licensed libraries cannot be linked to from non-GPL projects.
## Notes
Decisions regarding the GNU GPL licenses are based on information provided by [The GNU Project][GNU-GPL-FAQ], as well as [the Open Source Initiative][OSI-GPL], which both state that linking GPL libraries makes the program itself GPL.
If a gem uses a license which is not listed above, open an issue and ask. If a license is not included in the "acceptable" list, operate under the assumption that it is not acceptable.
Keep in mind that each license has its own restrictions (typically defined in their body text). Please make sure to comply with those restrictions at all times whenever an external library is used.
Gems which are included only in the "development" or "test" groups by Bundler are exempt from license requirements, as they're not distributed for use in production.
**NOTE:** This document is **not** legal advice, nor is it comprehensive. It should not be taken as such.
[CE]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/LICENSE
[EE]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/LICENSE
[license_finder]: https://github.com/pivotal/LicenseFinder
[MIT]: http://choosealicense.com/licenses/mit/
[LGPL]: http://choosealicense.com/licenses/lgpl-3.0/
[apache-2]: http://choosealicense.com/licenses/apache-2.0/
[ruby-1.8]: https://github.com/ruby/ruby/blob/ruby_1_8_6/COPYING
[ruby-1.9]: https://www.ruby-lang.org/en/about/license.txt
[BSD-2-Clause]: https://opensource.org/licenses/BSD-2-Clause
[BSD-3-Clause]: https://opensource.org/licenses/BSD-3-Clause
[ISC]: https://opensource.org/licenses/ISC
[GPL]: http://choosealicense.com/licenses/gpl-3.0/
[GPLv2]: http://www.gnu.org/licenses/gpl-2.0.txt
[GPLv3]: http://www.gnu.org/licenses/gpl-3.0.txt
[AGPLv3]: http://choosealicense.com/licenses/agpl-3.0/
[GNU-GPL-FAQ]: http://www.gnu.org/licenses/gpl-faq.html#IfLibraryIsGPL
[OSI-GPL]: https://opensource.org/faq#linking-proprietary-code
......@@ -269,9 +269,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ee.git -b 8-8-stable-ee gitlab
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ee.git -b 8-9-stable-ee gitlab
**Note:** You can change `8-8-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `8-9-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
......@@ -397,7 +397,7 @@ GitLab Shell is an SSH access and repository management software developed speci
cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse
sudo -u git -H git checkout v0.7.4
sudo -u git -H git checkout v0.7.5
sudo -u git -H make
### Initialize Database and Activate Advanced Features
......
# From 8.8 to 8.9
Make sure you view this update guide from the tag (version) of GitLab you would
like to install. In most cases this should be the highest numbered production
tag (without rc in it). You can select the tag in the version dropdown at the
top left corner of GitLab (below the menu bar).
If the highest number stable branch is unclear please check the
[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
guide links by version.
### 1. Stop server
sudo service gitlab stop
### 2. Backup
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 3. Get latest code
```bash
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
```
For GitLab Community Edition:
```bash
sudo -u git -H git checkout 8-9-stable
```
OR
For GitLab Enterprise Edition:
```bash
sudo -u git -H git checkout 8-9-stable-ee
```
### 4. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch --all --tags
sudo -u git -H git checkout v3.0.0
```
### 5. Update gitlab-workhorse
Install and compile gitlab-workhorse. This requires
[Go 1.5](https://golang.org/dl) which should already be on your system from
GitLab 8.1.
```bash
cd /home/git/gitlab-workhorse
sudo -u git -H git fetch --all
sudo -u git -H git checkout v0.7.5
sudo -u git -H make
```
### 6. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL installations (note: the line below states '--without postgres')
sudo -u git -H bundle install --without postgres development test --deployment
# PostgreSQL installations (note: the line below states '--without mysql')
sudo -u git -H bundle install --without mysql development test --deployment
# Optional: clean up old gems
sudo -u git -H bundle clean
# Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Clean up assets and cache
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 7. Update configuration files
#### New configuration options for `gitlab.yml`
There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-8-stable:config/gitlab.yml.example origin/8-9-stable:config/gitlab.yml.example
```
#### Git configuration
Disable `git gc --auto` because GitLab runs `git gc` for us already.
```sh
sudo -u git -H git config --global gc.auto 0
```
#### Nginx configuration
Ensure you're still up-to-date with the latest NGINX configuration changes:
```sh
# For HTTPS configurations
git diff origin/8-8-stable:lib/support/nginx/gitlab-ssl origin/8-9-stable:lib/support/nginx/gitlab-ssl
# For HTTP configurations
git diff origin/8-8-stable:lib/support/nginx/gitlab origin/8-9-stable:lib/support/nginx/gitlab
```
If you are using Apache instead of NGINX please see the updated [Apache templates].
Also note that because Apache does not support upstreams behind Unix sockets you
will need to let gitlab-workhorse listen on a TCP port. You can do this
via [/etc/default/gitlab].
[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/lib/support/init.d/gitlab.default.example#L37
#### Init script
Ensure you're still up-to-date with the latest init script changes:
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
### 8. Start application
sudo service gitlab start
sudo service nginx restart
### 9. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations, the upgrade is complete!
## Things went south? Revert to previous version (8.7)
### 1. Revert the code to the previous version
Follow the [upgrade guide from 8.7 to 8.8](8.7-to-8.8.md), except for the
database migration (the backup is already migrated to the previous version).
### 2. Restore from the backup
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
......@@ -25,13 +25,6 @@ Feature: Project Issues
Scenario: I visit issue page
Given I click link "Release 0.4"
Then I should see issue "Release 0.4"
And I should see "1 of 2" in the sidebar
Scenario: I navigate between issues
Given I click link "Release 0.4"
Then I click link "Next" in the sidebar
Then I should see issue "Tweet control"
And I should see "2 of 2" in the sidebar
@javascript
Scenario: I filter by author
......
......@@ -49,14 +49,12 @@ Feature: Project Merge Requests
Scenario: I visit an open merge request page
Given I click link "Bug NS-04"
Then I should see merge request "Bug NS-04"
And I should see "1 of 1" in the sidebar
Scenario: I visit a merged merge request page
Given project "Shop" have "Feature NS-05" merged merge request
And I click link "Merged"
And I click link "Feature NS-05"
Then I should see merge request "Feature NS-05"
And I should see "3 of 3" in the sidebar
Scenario: I close merge request page
Given I click link "Bug NS-04"
......@@ -76,18 +74,6 @@ Feature: Project Merge Requests
And I submit new merge request "Wiki Feature"
Then I should see merge request "Wiki Feature"
Scenario: I download a diff on a public merge request
Given public project "Community"
And "John Doe" owns public project "Community"
And project "Community" has "Bug CO-01" open merge request with diffs inside
Given I logout directly
And I visit merge request page "Bug CO-01"
And I click on "Email Patches"
Then I should see a patch diff
And I visit merge request page "Bug CO-01"
And I click on "Plain Diff"
Then I should see a patch diff
@javascript
Scenario: I comment on a merge request
Given I visit merge request page "Bug NS-04"
......
......@@ -164,12 +164,12 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
step 'commit has ci status' do
@project.enable_ci
ci_commit = create :ci_commit, project: @project, sha: sample_commit.id
create :ci_build, commit: ci_commit
pipeline = create :ci_pipeline, project: @project, sha: sample_commit.id
create :ci_build, pipeline: pipeline
end
step 'repository contains ".gitlab-ci.yml" file' do
allow_any_instance_of(Ci::Commit).to receive(:ci_yaml_file).and_return(String.new)
allow_any_instance_of(Ci::Pipeline).to receive(:ci_yaml_file).and_return(String.new)
end
step 'I see commit ci info' do
......
......@@ -654,8 +654,8 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step '"Bug NS-05" has CI status' do
project = merge_request.source_project
project.enable_ci
ci_commit = create :ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch
create :ci_build, commit: ci_commit
pipeline = create :ci_pipeline, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch
create :ci_build, pipeline: pipeline
end
step 'I should see merge request "Bug NS-05" with CI status' do
......
......@@ -27,10 +27,10 @@ class Spinach::Features::ProjectPages < Spinach::FeatureSteps
end
step 'pages are deployed' do
commit = @project.ensure_ci_commit(@project.commit('HEAD').sha, 'HEAD')
pipeline = @project.ensure_pipeline(@project.commit('HEAD').sha, 'HEAD')
build = build(:ci_build,
project: @project,
commit: commit,
pipeline: pipeline,
ref: 'HEAD',
artifacts_file: fixture_file_upload(Rails.root + 'spec/fixtures/pages.zip'),
artifacts_metadata: fixture_file_upload(Rails.root + 'spec/fixtures/pages.zip.meta')
......
......@@ -10,8 +10,8 @@ module SharedBuilds
end
step 'project has a recent build' do
@ci_commit = create(:ci_commit, project: @project, sha: @project.commit.sha, ref: 'master')
@build = create(:ci_build_with_coverage, commit: @ci_commit)
@pipeline = create(:ci_pipeline, project: @project, sha: @project.commit.sha, ref: 'master')
@build = create(:ci_build_with_coverage, pipeline: @pipeline)
end
step 'recent build is successful' do
......@@ -23,7 +23,7 @@ module SharedBuilds
end
step 'project has another build that is running' do
create(:ci_build, commit: @ci_commit, name: 'second build', status: 'running')
create(:ci_build, pipeline: @pipeline, name: 'second build', status: 'running')
end
step 'I visit recent build details page' do
......
......@@ -138,22 +138,6 @@ module SharedIssuable
end
end
step 'I should see "1 of 1" in the sidebar' do
expect_sidebar_content('1 of 1')
end
step 'I should see "1 of 2" in the sidebar' do
expect_sidebar_content('1 of 2')
end
step 'I should see "2 of 2" in the sidebar' do
expect_sidebar_content('2 of 2')
end
step 'I should see "3 of 3" in the sidebar' do
expect_sidebar_content('3 of 3')
end
step 'I click link "Next" in the sidebar' do
page.within '.issuable-sidebar' do
click_link 'Next'
......
......@@ -236,7 +236,7 @@ module SharedProject
step 'project "Shop" has CI build' do
project = Project.find_by(name: "Shop")
create :ci_commit, project: project, sha: project.commit.sha, ref: 'master', status: 'skipped'
create :ci_pipeline, project: project, sha: project.commit.sha, ref: 'master', status: 'skipped'
end
step 'I should see last commit with CI status' do
......
......@@ -33,7 +33,7 @@ module API
get ':id/repository/commits/:sha/builds' do
authorize_read_builds!
commit = user_project.ci_commits.find_by_sha(params[:sha])
commit = user_project.pipelines.find_by_sha(params[:sha])
return not_found! unless commit
builds = commit.builds.order('id DESC')
......
......@@ -22,8 +22,8 @@ module API
not_found!('Commit') unless user_project.commit(params[:sha])
ci_commits = user_project.ci_commits.where(sha: params[:sha])
statuses = ::CommitStatus.where(commit: ci_commits)
pipelines = user_project.pipelines.where(sha: params[:sha])
statuses = ::CommitStatus.where(pipeline: pipelines)
statuses = statuses.latest unless parse_boolean(params[:all])
statuses = statuses.where(ref: params[:ref]) if params[:ref].present?
statuses = statuses.where(stage: params[:stage]) if params[:stage].present?
......@@ -50,7 +50,7 @@ module API
commit = @project.commit(params[:sha])
not_found! 'Commit' unless commit
# Since the CommitStatus is attached to Ci::Commit (in the future Pipeline)
# Since the CommitStatus is attached to Ci::Pipeline (in the future Pipeline)
# We need to always have the pipeline object
# To have a valid pipeline object that can be attached to specific MR
# Other CI service needs to send `ref`
......@@ -64,11 +64,11 @@ module API
ref = branches.first
end
ci_commit = @project.ensure_ci_commit(commit.sha, ref)
pipeline = @project.ensure_pipeline(commit.sha, ref)
name = params[:name] || params[:context]
status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref])
status ||= GenericCommitStatus.new(project: @project, commit: ci_commit, user: current_user)
status = GenericCommitStatus.running_or_pending.find_by(pipeline: pipeline, name: name, ref: params[:ref])
status ||= GenericCommitStatus.new(project: @project, pipeline: pipeline, user: current_user)
status.update(attrs)
case params[:state].to_s
......
......@@ -243,7 +243,7 @@ module API
should_remove_source_branch: params[:should_remove_source_branch]
}
if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.ci_commit && merge_request.ci_commit.active?
if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.pipeline && merge_request.pipeline.active?
::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params).
execute(merge_request)
else
......
......@@ -60,7 +60,7 @@ module Ci
class BuildTime < Chart
def collect
commits = project.ci_commits.last(30)
commits = project.pipelines.last(30)
commits.each do |commit|
@labels << commit.short_sha
......
......@@ -3,7 +3,7 @@ module Gitlab
class << self
def build(build)
project = build.project
commit = build.commit
commit = build.pipeline
user = build.user
data = {
......
......@@ -11,7 +11,7 @@ module Gitlab
# add_concurrent_index :users, :some_column
#
# See Rails' `add_index` for more info on the available arguments.
def add_concurrent_index(*args)
def add_concurrent_index(table_name, column_name, options = {})
if transaction_open?
raise 'add_concurrent_index can not be run inside a transaction, ' \
'you can disable transactions by calling disable_ddl_transaction! ' \
......@@ -19,10 +19,10 @@ module Gitlab
end
if Database.postgresql?
args << { algorithm: :concurrently }
options = options.merge({ algorithm: :concurrently })
end
add_index(*args)
add_index(table_name, column_name, options)
end
# Updates the value of a column in batches.
......
......@@ -9,6 +9,10 @@ module Gitlab
@formatter = Gitlab::ImportFormatter.new
end
def create!
self.klass.create!(self.attributes)
end
private
def gl_user_id(github_id)
......
......@@ -8,6 +8,7 @@ module Gitlab
commit_id: raw_data.commit_id,
line_code: line_code,
author_id: author_id,
type: type,
created_at: raw_data.created_at,
updated_at: raw_data.updated_at
}
......@@ -53,6 +54,10 @@ module Gitlab
def note
formatter.author_line(author) + body
end
def type
'LegacyDiffNote' if on_diff?
end
end
end
end
module Gitlab
module GithubImport
class HookFormatter
EVENTS = %w[* create delete pull_request push].freeze
attr_reader :raw
delegate :id, :name, :active, to: :raw
def initialize(raw)
@raw = raw
end
def config
raw.config.attrs
end
def valid?
(EVENTS & raw.events).any? && active
end
end
end
end
......@@ -3,6 +3,9 @@ module Gitlab
class Importer
include Gitlab::ShellAdapter
GITHUB_SAFE_REMAINING_REQUESTS = 100
GITHUB_SAFE_SLEEP_TIME = 500
attr_reader :client, :project, :repo, :repo_url
def initialize(project)
......@@ -25,14 +28,53 @@ module Gitlab
private
def turn_auto_pagination_off!
client.auto_paginate = false
end
def turn_auto_pagination_on!
client.auto_paginate = true
end
def rate_limit
client.rate_limit!
end
def rate_limit_exceed?
rate_limit.remaining <= GITHUB_SAFE_REMAINING_REQUESTS
end
def rate_limit_sleep_time
rate_limit.resets_in + GITHUB_SAFE_SLEEP_TIME
end
def paginate
turn_auto_pagination_off!
sleep rate_limit_sleep_time if rate_limit_exceed?
data = yield
last_response = client.last_response
while last_response.rels[:next]
sleep rate_limit_sleep_time if rate_limit_exceed?
last_response = last_response.rels[:next].get
data.concat(last_response.data) if last_response.data.is_a?(Array)
end
turn_auto_pagination_on!
data
end
def credentials
@credentials ||= project.import_data.credentials if project.import_data
end
def import_labels
client.labels(repo).each do |raw_data|
Label.create!(LabelFormatter.new(project, raw_data).attributes)
end
labels = paginate { client.labels(repo, per_page: 100) }
labels.each { |raw| LabelFormatter.new(project, raw).create! }
true
rescue ActiveRecord::RecordInvalid => e
......@@ -40,9 +82,8 @@ module Gitlab
end
def import_milestones
client.list_milestones(repo, state: :all).each do |raw_data|
Milestone.create!(MilestoneFormatter.new(project, raw_data).attributes)
end
milestones = paginate { client.milestones(repo, state: :all, per_page: 100) }
milestones.each { |raw| MilestoneFormatter.new(project, raw).create! }
true
rescue ActiveRecord::RecordInvalid => e
......@@ -50,16 +91,15 @@ module Gitlab
end
def import_issues
client.list_issues(repo, state: :all, sort: :created, direction: :asc).each do |raw_data|
gh_issue = IssueFormatter.new(project, raw_data)
data = paginate { client.issues(repo, state: :all, sort: :created, direction: :asc, per_page: 100) }
if gh_issue.valid?
issue = Issue.create!(gh_issue.attributes)
apply_labels(gh_issue.number, issue)
data.each do |raw|
gh_issue = IssueFormatter.new(project, raw)
if gh_issue.has_comments?
import_comments(gh_issue.number, issue)
end
if gh_issue.valid?
issue = gh_issue.create!
apply_labels(issue)
import_comments(issue) if gh_issue.has_comments?
end
end
......@@ -69,50 +109,68 @@ module Gitlab
end
def import_pull_requests
pull_requests = client.pull_requests(repo, state: :all, sort: :created, direction: :asc)
.map { |raw| PullRequestFormatter.new(project, raw) }
.select(&:valid?)
hooks = client.hooks(repo).map { |raw| HookFormatter.new(raw) }.select(&:valid?)
disable_webhooks(hooks)
pull_requests = paginate { client.pull_requests(repo, state: :all, sort: :created, direction: :asc, per_page: 100) }
pull_requests = pull_requests.map { |raw| PullRequestFormatter.new(project, raw) }.select(&:valid?)
source_branches_removed = pull_requests.reject(&:source_branch_exists?).map { |pr| [pr.source_branch_name, pr.source_branch_sha] }
target_branches_removed = pull_requests.reject(&:target_branch_exists?).map { |pr| [pr.target_branch_name, pr.target_branch_sha] }
branches_removed = source_branches_removed | target_branches_removed
create_refs(branches_removed)
restore_branches(branches_removed)
pull_requests.each do |pull_request|
merge_request = MergeRequest.new(pull_request.attributes)
if merge_request.save
apply_labels(pull_request.number, merge_request)
import_comments(pull_request.number, merge_request)
import_comments_on_diff(pull_request.number, merge_request)
end
merge_request = pull_request.create!
apply_labels(merge_request)
import_comments(merge_request)
import_comments_on_diff(merge_request)
end
true
rescue ActiveRecord::RecordInvalid => e
raise Projects::ImportService::Error, e.message
ensure
delete_refs(branches_removed)
clean_up_restored_branches(branches_removed)
clean_up_disabled_webhooks(hooks)
end
def disable_webhooks(hooks)
update_webhooks(hooks, active: false)
end
def clean_up_disabled_webhooks(hooks)
update_webhooks(hooks, active: true)
end
def create_refs(branches)
def update_webhooks(hooks, options)
hooks.each do |hook|
client.edit_hook(repo, hook.id, hook.name, hook.config, options)
end
end
def restore_branches(branches)
branches.each do |name, sha|
sleep rate_limit_sleep_time if rate_limit_exceed?
client.create_ref(repo, "refs/heads/#{name}", sha)
end
project.repository.fetch_ref(repo_url, '+refs/heads/*', 'refs/heads/*')
end
def delete_refs(branches)
def clean_up_restored_branches(branches)
branches.each do |name, _|
sleep rate_limit_sleep_time if rate_limit_exceed?
client.delete_ref(repo, "heads/#{name}")
project.repository.rm_branch(project.creator, name)
end
end
def apply_labels(number, issuable)
issue = client.issue(repo, number)
def apply_labels(issuable)
sleep rate_limit_sleep_time if rate_limit_exceed?
issue = client.issue(repo, issuable.iid)
if issue.labels.count > 0
label_ids = issue.labels.map do |raw|
......@@ -123,20 +181,20 @@ module Gitlab
end
end
def import_comments(issue_number, noteable)
comments = client.issue_comments(repo, issue_number)
create_comments(comments, noteable)
def import_comments(issuable)
comments = paginate { client.issue_comments(repo, issuable.iid, per_page: 100) }
create_comments(issuable, comments)
end
def import_comments_on_diff(pull_request_number, merge_request)
comments = client.pull_request_comments(repo, pull_request_number)
create_comments(comments, merge_request)
def import_comments_on_diff(merge_request)
comments = paginate { client.pull_request_comments(repo, merge_request.iid, per_page: 100) }
create_comments(merge_request, comments)
end
def create_comments(comments, noteable)
comments.each do |raw_data|
comment = CommentFormatter.new(project, raw_data)
noteable.notes.create!(comment.attributes)
def create_comments(issuable, comments)
comments.each do |raw|
comment = CommentFormatter.new(project, raw)
issuable.notes.create!(comment.attributes)
end
end
......
......@@ -20,6 +20,10 @@ module Gitlab
raw_data.comments > 0
end
def klass
Issue
end
def number
raw_data.number
end
......
......@@ -9,6 +9,10 @@ module Gitlab
}
end
def klass
Label
end
private
def color
......
......@@ -14,6 +14,10 @@ module Gitlab
}
end
def klass
Milestone
end
private
def number
......
......@@ -24,6 +24,10 @@ module Gitlab
}
end
def klass
MergeRequest
end
def number
raw_data.number
end
......
......@@ -30,6 +30,19 @@ module Gitlab
]
end
def send_git_diff(repository, from, to)
params = {
'RepoPath' => repository.path_to_repo,
'ShaFrom' => from,
'ShaTo' => to
}
[
SEND_DATA_HEADER,
"git-diff:#{encode(params)}"
]
end
protected
def encode(hash)
......
......@@ -19,7 +19,7 @@ namespace :gitlab do
Rake::Task["setup_postgresql"].invoke
Rake::Task["db:seed_fu"].invoke
rescue Gitlab::TaskAbortedByUserError
puts "Quitting...".red
puts "Quitting...".color(:red)
exit 1
end
end
......@@ -84,17 +84,14 @@ describe Projects::MergeRequestsController do
end
describe "as diff" do
include_examples "export merge as", :diff
let(:format) { :diff }
it "should really only be a git diff" do
it "triggers workhorse to serve the request" do
get(:show,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: merge_request.iid,
format: format)
format: :diff)
expect(response.body).to start_with("diff --git")
expect(response.headers['Gitlab-Workhorse-Send-Data']).to start_with("git-diff:")
end
end
......@@ -250,7 +247,7 @@ describe Projects::MergeRequestsController do
end
before do
create(:ci_empty_commit, project: project, sha: merge_request.source_sha, ref: merge_request.source_branch)
create(:ci_empty_pipeline, project: project, sha: merge_request.source_sha, ref: merge_request.source_branch)
end
it 'returns :merge_when_build_succeeds' do
......
......@@ -16,7 +16,7 @@ FactoryGirl.define do
}
end
commit factory: :ci_commit
pipeline factory: :ci_pipeline
trait :success do
status 'success'
......@@ -43,7 +43,7 @@ FactoryGirl.define do
end
after(:build) do |build, evaluator|
build.project = build.commit.project
build.project = build.pipeline.project
end
factory :ci_not_started_build do
......
......@@ -17,30 +17,30 @@
#
FactoryGirl.define do
factory :ci_empty_commit, class: Ci::Commit do
factory :ci_empty_pipeline, class: Ci::Pipeline do
sha '97de212e80737a608d939f648d959671fb0a0142'
project factory: :empty_project
factory :ci_commit_without_jobs do
factory :ci_pipeline_without_jobs do
after(:build) do |commit|
allow(commit).to receive(:ci_yaml_file) { YAML.dump({}) }
end
end
factory :ci_commit_with_one_job do
factory :ci_pipeline_with_one_job do
after(:build) do |commit|
allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" } }) }
end
end
factory :ci_commit_with_two_jobs do
factory :ci_pipeline_with_two_job do
after(:build) do |commit|
allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" }, spinach: { script: "ls" } }) }
end
end
factory :ci_commit do
factory :ci_pipeline do
after(:build) do |commit|
allow(commit).to receive(:ci_yaml_file) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
end
......
......@@ -3,12 +3,12 @@ FactoryGirl.define do
name 'default'
status 'success'
description 'commit status'
commit factory: :ci_commit_with_one_job
pipeline factory: :ci_pipeline_with_one_job
started_at 'Tue, 26 Jan 2016 08:21:42 +0100'
finished_at 'Tue, 26 Jan 2016 08:23:42 +0100'
after(:build) do |build, evaluator|
build.project = build.commit.project
build.project = build.pipeline.project
end
factory :generic_commit_status, class: GenericCommitStatus do
......
......@@ -6,15 +6,15 @@ describe 'Admin Builds' do
end
describe 'GET /admin/builds' do
let(:commit) { create(:ci_commit) }
let(:pipeline) { create(:ci_pipeline) }
context 'All tab' do
context 'when have builds' do
it 'shows all builds' do
create(:ci_build, commit: commit, status: :pending)
create(:ci_build, commit: commit, status: :running)
create(:ci_build, commit: commit, status: :success)
create(:ci_build, commit: commit, status: :failed)
create(:ci_build, pipeline: pipeline, status: :pending)
create(:ci_build, pipeline: pipeline, status: :running)
create(:ci_build, pipeline: pipeline, status: :success)
create(:ci_build, pipeline: pipeline, status: :failed)
visit admin_builds_path
......@@ -39,9 +39,9 @@ describe 'Admin Builds' do
context 'Running tab' do
context 'when have running builds' do
it 'shows running builds' do
build1 = create(:ci_build, commit: commit, status: :pending)
build2 = create(:ci_build, commit: commit, status: :success)
build3 = create(:ci_build, commit: commit, status: :failed)
build1 = create(:ci_build, pipeline: pipeline, status: :pending)
build2 = create(:ci_build, pipeline: pipeline, status: :success)
build3 = create(:ci_build, pipeline: pipeline, status: :failed)
visit admin_builds_path(scope: :running)
......@@ -55,7 +55,7 @@ describe 'Admin Builds' do
context 'when have no builds running' do
it 'shows a message' do
create(:ci_build, commit: commit, status: :success)
create(:ci_build, pipeline: pipeline, status: :success)
visit admin_builds_path(scope: :running)
......@@ -69,9 +69,9 @@ describe 'Admin Builds' do
context 'Finished tab' do
context 'when have finished builds' do
it 'shows finished builds' do
build1 = create(:ci_build, commit: commit, status: :pending)
build2 = create(:ci_build, commit: commit, status: :running)
build3 = create(:ci_build, commit: commit, status: :success)
build1 = create(:ci_build, pipeline: pipeline, status: :pending)
build2 = create(:ci_build, pipeline: pipeline, status: :running)
build3 = create(:ci_build, pipeline: pipeline, status: :success)
visit admin_builds_path(scope: :finished)
......@@ -85,7 +85,7 @@ describe 'Admin Builds' do
context 'when have no builds finished' do
it 'shows a message' do
create(:ci_build, commit: commit, status: :running)
create(:ci_build, pipeline: pipeline, status: :running)
visit admin_builds_path(scope: :finished)
......
......@@ -8,8 +8,8 @@ describe "Admin Runners" do
describe "Runners page" do
before do
runner = FactoryGirl.create(:ci_runner)
commit = FactoryGirl.create(:ci_commit)
FactoryGirl.create(:ci_build, commit: commit, runner_id: runner.id)
pipeline = FactoryGirl.create(:ci_pipeline)
FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id)
visit admin_runners_path
end
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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