Commit 58a343ab authored by Ruben Davila's avatar Ruben Davila

Merge branch 'master' into 8-12-stable

parents a6b8c456 acc7f7c6
...@@ -206,6 +206,7 @@ spinach 9 10 ruby21: *spinach-knapsack-ruby21 ...@@ -206,6 +206,7 @@ spinach 9 10 ruby21: *spinach-knapsack-ruby21
- bundle exec $CI_BUILD_NAME - bundle exec $CI_BUILD_NAME
rubocop: *exec rubocop: *exec
rake haml_lint: *exec
rake scss_lint: *exec rake scss_lint: *exec
rake brakeman: *exec rake brakeman: *exec
rake flog: *exec rake flog: *exec
......
# Whether to ignore frontmatter at the beginning of HAML documents for
# frameworks such as Jekyll/Middleman
skip_frontmatter: false
exclude:
- 'vendor/**/*'
- 'spec/**/*'
linters:
AltText:
enabled: false
ClassAttributeWithStaticValue:
enabled: false
ClassesBeforeIds:
enabled: false
ConsecutiveComments:
enabled: false
ConsecutiveSilentScripts:
enabled: false
max_consecutive: 2
EmptyObjectReference:
enabled: true
EmptyScript:
enabled: true
FinalNewline:
enabled: false
present: true
HtmlAttributes:
enabled: false
ImplicitDiv:
enabled: false
LeadingCommentSpace:
enabled: false
LineLength:
enabled: false
max: 80
MultilinePipe:
enabled: false
MultilineScript:
enabled: true
ObjectReferenceAttributes:
enabled: true
RuboCop:
enabled: false
# These cops are incredibly noisy when it comes to HAML templates, so we
# ignore them.
ignored_cops:
- Lint/BlockAlignment
- Lint/EndAlignment
- Lint/Void
- Metrics/LineLength
- Style/AlignParameters
- Style/BlockNesting
- Style/ElseAlignment
- Style/FileName
- Style/FinalNewline
- Style/FrozenStringLiteralComment
- Style/IfUnlessModifier
- Style/IndentationWidth
- Style/Next
- Style/TrailingBlankLines
- Style/TrailingWhitespace
- Style/WhileUntilModifier
RubyComments:
enabled: false
SpaceBeforeScript:
enabled: false
SpaceInsideHashAttributes:
enabled: false
style: space
Indentation:
enabled: true
character: space # or tab
TagName:
enabled: true
TrailingWhitespace:
enabled: false
UnnecessaryInterpolation:
enabled: false
UnnecessaryStringOutput:
enabled: false
This diff is collapsed.
...@@ -298,6 +298,7 @@ group :development, :test do ...@@ -298,6 +298,7 @@ group :development, :test do
gem 'rubocop', '~> 0.41.2', require: false gem 'rubocop', '~> 0.41.2', require: false
gem 'rubocop-rspec', '~> 1.5.0', require: false gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false gem 'scss_lint', '~> 0.47.0', require: false
gem 'haml_lint', '~> 0.18.2', require: false
gem 'simplecov', '0.12.0', require: false gem 'simplecov', '0.12.0', require: false
gem 'flog', '~> 4.3.2', require: false gem 'flog', '~> 4.3.2', require: false
gem 'flay', '~> 2.6.1', require: false gem 'flay', '~> 2.6.1', require: false
......
...@@ -322,6 +322,13 @@ GEM ...@@ -322,6 +322,13 @@ GEM
grape-entity (0.4.8) grape-entity (0.4.8)
activesupport activesupport
multi_json (>= 1.3.2) multi_json (>= 1.3.2)
haml (4.0.7)
tilt
haml_lint (0.18.2)
haml (~> 4.0)
rake (>= 10, < 12)
rubocop (>= 0.36.0)
sysexits (~> 1.1)
hamlit (2.6.1) hamlit (2.6.1)
temple (~> 0.7.6) temple (~> 0.7.6)
thor thor
...@@ -723,6 +730,7 @@ GEM ...@@ -723,6 +730,7 @@ GEM
stringex (2.5.2) stringex (2.5.2)
sys-filesystem (1.1.6) sys-filesystem (1.1.6)
ffi ffi
sysexits (1.2.0)
systemu (2.6.5) systemu (2.6.5)
task_list (1.0.2) task_list (1.0.2)
html-pipeline html-pipeline
...@@ -866,6 +874,7 @@ DEPENDENCIES ...@@ -866,6 +874,7 @@ DEPENDENCIES
gon (~> 6.1.0) gon (~> 6.1.0)
grape (~> 0.15.0) grape (~> 0.15.0)
grape-entity (~> 0.4.2) grape-entity (~> 0.4.2)
haml_lint (~> 0.18.2)
hamlit (~> 2.6.1) hamlit (~> 2.6.1)
health_check (~> 2.1.0) health_check (~> 2.1.0)
hipchat (~> 1.5.0) hipchat (~> 1.5.0)
......
...@@ -79,10 +79,6 @@ ...@@ -79,10 +79,6 @@
padding-left: 15px !important; padding-left: 15px !important;
} }
.issue-info, .merge-request-info {
display: none;
}
.nav-links, .nav-links { .nav-links, .nav-links {
li a { li a {
font-size: 14px; font-size: 14px;
......
...@@ -206,7 +206,7 @@ ...@@ -206,7 +206,7 @@
padding-top: 0; padding-top: 0;
.block { .block {
width: $sidebar_collapsed_width - 1px; width: $sidebar_collapsed_width - 2px;
margin-left: -19px; margin-left: -19px;
padding: 15px 0 0; padding: 15px 0 0;
border-bottom: none; border-bottom: none;
......
...@@ -37,6 +37,15 @@ form.edit-issue { ...@@ -37,6 +37,15 @@ form.edit-issue {
margin: 0; margin: 0;
} }
ul.related-merge-requests > li {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
.merge-request-id {
flex-shrink: 0;
}
}
.merge-requests-title, .related-branches-title { .merge-requests-title, .related-branches-title {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
......
...@@ -62,6 +62,7 @@ module AuthenticatesWithTwoFactor ...@@ -62,6 +62,7 @@ module AuthenticatesWithTwoFactor
session.delete(:otp_user_id) session.delete(:otp_user_id)
session.delete(:challenges) session.delete(:challenges)
remember_me(user) if user_params[:remember_me] == '1'
sign_in(user) sign_in(user)
else else
flash.now[:alert] = 'Authentication via U2F device failed.' flash.now[:alert] = 'Authentication via U2F device failed.'
......
...@@ -7,8 +7,7 @@ module CreatesCommit ...@@ -7,8 +7,7 @@ module CreatesCommit
commit_params = @commit_params.merge( commit_params = @commit_params.merge(
source_project: @project, source_project: @project,
source_branch: @ref, source_branch: @ref,
target_branch: @target_branch, target_branch: @target_branch
previous_path: @previous_path
) )
result = service.new(@tree_edit_project, current_user, commit_params).execute result = service.new(@tree_edit_project, current_user, commit_params).execute
......
...@@ -38,12 +38,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -38,12 +38,7 @@ class Projects::BlobController < Projects::ApplicationController
end end
def update def update
if params[:file_path].present? @path = params[:file_path] if params[:file_path].present?
@previous_path = @path
@path = params[:file_path]
@commit_params[:file_path] = @path
end
after_edit_path = after_edit_path =
if from_merge_request && @target_branch == @ref if from_merge_request && @target_branch == @ref
diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) + diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) +
...@@ -143,6 +138,8 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -143,6 +138,8 @@ class Projects::BlobController < Projects::ApplicationController
params[:file_name] = params[:file].original_filename params[:file_name] = params[:file].original_filename
end end
File.join(@path, params[:file_name]) File.join(@path, params[:file_name])
elsif params[:file_path].present?
params[:file_path]
else else
@path @path
end end
...@@ -155,6 +152,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -155,6 +152,7 @@ class Projects::BlobController < Projects::ApplicationController
@commit_params = { @commit_params = {
file_path: @file_path, file_path: @file_path,
commit_message: params[:commit_message], commit_message: params[:commit_message],
previous_path: @path,
file_content: params[:content], file_content: params[:content],
file_content_encoding: params[:encoding], file_content_encoding: params[:encoding],
last_commit_sha: params[:last_commit_sha] last_commit_sha: params[:last_commit_sha]
......
...@@ -428,17 +428,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -428,17 +428,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def validates_merge_request def validates_merge_request
# If source project was removed (Ex. mr from fork to origin)
return invalid_mr unless @merge_request.source_project
# Show git not found page # Show git not found page
# if there is no saved commits between source & target branch # if there is no saved commits between source & target branch
if @merge_request.commits.blank? if @merge_request.commits.blank?
# and if target branch doesn't exist # and if target branch doesn't exist
return invalid_mr unless @merge_request.target_branch_exists? return invalid_mr unless @merge_request.target_branch_exists?
# or if source branch doesn't exist
return invalid_mr unless @merge_request.source_branch_exists?
end end
end end
......
...@@ -146,7 +146,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -146,7 +146,7 @@ class ApplicationSetting < ActiveRecord::Base
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
domain_whitelist: Settings.gitlab['domain_whitelist'], domain_whitelist: Settings.gitlab['domain_whitelist'],
import_sources: %w[github bitbucket gitlab google_code fogbugz git gitlab_project], import_sources: Gitlab::ImportSources.values,
shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
max_artifacts_size: Settings.artifacts['max_size'], max_artifacts_size: Settings.artifacts['max_size'],
require_two_factor_authentication: false, require_two_factor_authentication: false,
......
...@@ -148,6 +148,7 @@ module Ci ...@@ -148,6 +148,7 @@ module Ci
variables += runner.predefined_variables if runner variables += runner.predefined_variables if runner
variables += project.container_registry_variables variables += project.container_registry_variables
variables += yaml_variables variables += yaml_variables
variables += user_variables
variables += project.secret_variables variables += project.secret_variables
variables += trigger_request.user_variables if trigger_request variables += trigger_request.user_variables if trigger_request
variables variables
...@@ -434,6 +435,15 @@ module Ci ...@@ -434,6 +435,15 @@ module Ci
read_attribute(:yaml_variables) || build_attributes_from_config[:yaml_variables] || [] read_attribute(:yaml_variables) || build_attributes_from_config[:yaml_variables] || []
end end
def user_variables
return [] if user.blank?
[
{ key: 'GITLAB_USER_ID', value: user.id.to_s, public: true },
{ key: 'GITLAB_USER_EMAIL', value: user.email, public: true }
]
end
private private
def update_artifacts_size def update_artifacts_size
...@@ -469,6 +479,7 @@ module Ci ...@@ -469,6 +479,7 @@ module Ci
] ]
variables << { key: 'CI_BUILD_TAG', value: ref, public: true } if tag? variables << { key: 'CI_BUILD_TAG', value: ref, public: true } if tag?
variables << { key: 'CI_BUILD_TRIGGERED', value: 'true', public: true } if trigger_request variables << { key: 'CI_BUILD_TRIGGERED', value: 'true', public: true } if trigger_request
variables << { key: 'CI_BUILD_MANUAL', value: 'true', public: true } if manual?
variables variables
end end
......
...@@ -316,6 +316,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -316,6 +316,10 @@ class MergeRequest < ActiveRecord::Base
closed? && forked_source_project_missing? closed? && forked_source_project_missing?
end end
def closed_without_source_project?
closed? && !source_project
end
def forked_source_project_missing? def forked_source_project_missing?
return false unless for_fork? return false unless for_fork?
return true unless source_project return true unless source_project
...@@ -323,6 +327,12 @@ class MergeRequest < ActiveRecord::Base ...@@ -323,6 +327,12 @@ class MergeRequest < ActiveRecord::Base
!source_project.forked_from?(target_project) !source_project.forked_from?(target_project)
end end
def reopenable?
return false if closed_without_fork? || closed_without_source_project? || merged?
closed?
end
def ensure_merge_request_diff def ensure_merge_request_diff
merge_request_diff || create_merge_request_diff merge_request_diff || create_merge_request_diff
end end
......
...@@ -58,7 +58,7 @@ class Project < ActiveRecord::Base ...@@ -58,7 +58,7 @@ class Project < ActiveRecord::Base
# Relations # Relations
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User' belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id' belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
belongs_to :namespace belongs_to :namespace
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
......
...@@ -813,7 +813,7 @@ class Repository ...@@ -813,7 +813,7 @@ class Repository
update: true update: true
} }
if previous_path if previous_path && previous_path != path
options[:file][:previous_path] = previous_path options[:file][:previous_path] = previous_path
Gitlab::Git::Blob.rename(raw_repository, options) Gitlab::Git::Blob.rename(raw_repository, options)
else else
......
...@@ -12,6 +12,7 @@ class Service < ActiveRecord::Base ...@@ -12,6 +12,7 @@ class Service < ActiveRecord::Base
default_value_for :tag_push_events, true default_value_for :tag_push_events, true
default_value_for :note_events, true default_value_for :note_events, true
default_value_for :build_events, true default_value_for :build_events, true
default_value_for :pipeline_events, true
default_value_for :wiki_page_events, true default_value_for :wiki_page_events, true
after_initialize :initialize_properties after_initialize :initialize_properties
......
...@@ -31,13 +31,13 @@ module Ci ...@@ -31,13 +31,13 @@ module Ci
current_status = status_for_prior_stages(index) current_status = status_for_prior_stages(index)
created_builds_in_stage(index).select do |build| created_builds_in_stage(index).select do |build|
process_build(build, current_status) if HasStatus::COMPLETED_STATUSES.include?(current_status)
process_build(build, current_status)
end
end end
end end
def process_build(build, current_status) def process_build(build, current_status)
return false unless HasStatus::COMPLETED_STATUSES.include?(current_status)
if valid_statuses_for_when(build.when).include?(current_status) if valid_statuses_for_when(build.when).include?(current_status)
build.enqueue build.enqueue
true true
......
...@@ -27,6 +27,8 @@ module Projects ...@@ -27,6 +27,8 @@ module Projects
# Git data (e.g. a list of branch names). # Git data (e.g. a list of branch names).
flush_caches(project, wiki_path) flush_caches(project, wiki_path)
Projects::UnlinkForkService.new(project, current_user).execute
Project.transaction do Project.transaction do
project.destroy! project.destroy!
......
- project = build.project
%tr.build.commit
%td.status
= ci_status_with_icon(build.status)
%td
.branch-commit
- if can?(current_user, :read_build, build.project)
= link_to namespace_project_build_url(build.project.namespace, build.project, build) do
%span.build-link ##{build.id}
- else
%span.build-link ##{build.id}
- if build.ref
.icon-container
= build.tag? ? icon('tag') : icon('code-fork')
= link_to build.ref, namespace_project_commits_path(build.project.namespace, build.project, build.ref), class: "monospace branch-name"
- else
.light none
.icon-container
= custom_icon("icon_commit")
= link_to build.short_sha, namespace_project_commit_path(build.project.namespace, build.project, build.sha), class: "monospace commit-id"
- if build.stuck?
%i.fa.fa-warning.text-warning
.label-container
- if build.tags.any?
- build.tags.each do |tag|
%span.label.label-primary
= tag
- if build.try(:trigger_request)
%span.label.label-info triggered
- if build.try(:allow_failure)
%span.label.label-danger allowed to fail
%td
- if project
= link_to project.name_with_namespace, admin_namespace_project_path(project.namespace, project)
%td
- if build.try(:runner)
= runner_link(build.runner)
- else
.light none
%td
#{build.stage} / #{build.name}
%td
- if build.duration
%p.duration
= custom_icon("icon_timer")
= duration_in_numbers(build.duration)
- if build.finished_at
%p.finished-at
= icon("calendar")
%span #{time_ago_with_tooltip(build.finished_at)}
- if defined?(coverage) && coverage
%td.coverage
- if build.try(:coverage)
#{build.coverage}%
%td
.pull-right
- if can?(current_user, :read_build, project) && build.artifacts?
= link_to download_namespace_project_build_artifacts_path(build.project.namespace, build.project, build), title: 'Download artifacts', class: 'btn btn-build' do
%i.fa.fa-download
- if can?(current_user, :update_build, build.project)
- if build.active?
= link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
%i.fa.fa-remove.cred
- elsif defined?(allow_retry) && allow_retry && build.retryable?
= link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
%i.fa.fa-refresh
...@@ -4,26 +4,8 @@ ...@@ -4,26 +4,8 @@
%div{ class: container_class } %div{ class: container_class }
.top-area .top-area
%ul.nav-links - build_path_proc = ->(scope) { admin_builds_path(scope: scope) }
%li{class: ('active' if @scope.nil?)} = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
= link_to admin_builds_path do
All
%span.badge.js-totalbuilds-count= @all_builds.count(:id)
%li{class: ('active' if @scope == 'pending')}
= link_to admin_builds_path(scope: :pending) do
Pending
%span.badge= number_with_delimiter(@all_builds.pending.count(:id))
%li{class: ('active' if @scope == 'running')}
= link_to admin_builds_path(scope: :running) do
Running
%span.badge= number_with_delimiter(@all_builds.running.count(:id))
%li{class: ('active' if @scope == 'finished')}
= link_to admin_builds_path(scope: :finished) do
Finished
%span.badge= number_with_delimiter(@all_builds.finished.count(:id))
.nav-controls .nav-controls
- if @all_builds.running_or_pending.any? - if @all_builds.running_or_pending.any?
...@@ -33,23 +15,4 @@ ...@@ -33,23 +15,4 @@
#{(@scope || 'all').capitalize} builds #{(@scope || 'all').capitalize} builds
%ul.content-list.builds-content-list %ul.content-list.builds-content-list
- if @builds.blank? = render "projects/builds/table", builds: @builds, admin: true
%li
.nothing-here-block No builds to show
- else
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Commit
%th Project
%th Runner
%th Name
%th
%th
- @builds.each do |build|
= render "admin/builds/build", build: build
= paginate @builds, theme: 'gitlab'
...@@ -18,6 +18,5 @@ ...@@ -18,6 +18,5 @@
= f.submit "Verify code", class: "btn btn-save" = f.submit "Verify code", class: "btn btn-save"
- if @user.two_factor_u2f_enabled? - if @user.two_factor_u2f_enabled?
%hr %hr
= render "u2f/authenticate" = render "u2f/authenticate", locals: { params: params, resource: resource, resource_name: resource_name }
- page_title "SSH Keys" - page_title "SSH Keys"
= render 'profiles/head'
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
- diverging_commit_counts = @repository.diverging_commit_counts(branch) - diverging_commit_counts = @repository.diverging_commit_counts(branch)
- number_commits_behind = diverging_commit_counts[:behind] - number_commits_behind = diverging_commit_counts[:behind]
- number_commits_ahead = diverging_commit_counts[:ahead] - number_commits_ahead = diverging_commit_counts[:ahead]
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
%li(class="js-branch-#{branch.name}") %li(class="js-branch-#{branch.name}")
%div %div
= link_to namespace_project_tree_path(@project.namespace, @project, branch.name), class: 'item-title str-truncated' do = link_to namespace_project_tree_path(@project.namespace, @project, branch.name), class: 'item-title str-truncated' do
...@@ -19,12 +20,12 @@ ...@@ -19,12 +20,12 @@
%i.fa.fa-lock %i.fa.fa-lock
protected protected
.controls.hidden-xs .controls.hidden-xs
- if create_mr_button?(@repository.root_ref, branch.name) - if merge_project && create_mr_button?(@repository.root_ref, branch.name)
= link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
Merge Request Merge Request
- if branch.name != @repository.root_ref - if branch.name != @repository.root_ref
= link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: "btn btn-default #{'prepend-left-10' unless merge_project}", method: :post, title: "Compare" do
Compare Compare
= render 'projects/buttons/download', project: @project, ref: branch.name = render 'projects/buttons/download', project: @project, ref: branch.name
......
- admin = local_assigns.fetch(:admin, false)
- if builds.blank?
%li
.nothing-here-block No builds to show
- else
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Commit
- if admin
%th Project
%th Runner
%th Stage
%th Name
%th
%th Coverage
%th
= render partial: "projects/ci/builds/build", collection: builds, as: :build, locals: { commit_sha: true, ref: true, stage: true, allow_retry: true, coverage: admin || project.build_coverage_enabled?, admin: admin }
= paginate builds, theme: 'gitlab'
...@@ -4,30 +4,8 @@ ...@@ -4,30 +4,8 @@
%div{ class: container_class } %div{ class: container_class }
.top-area .top-area
%ul.nav-links - build_path_proc = ->(scope) { project_builds_path(@project, scope: scope) }
%li{class: ('active' if @scope.nil?)} = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
= link_to project_builds_path(@project) do
All
%span.badge.js-totalbuilds-count
= number_with_delimiter(@all_builds.count(:id))
%li{class: ('active' if @scope == 'pending')}
= link_to project_builds_path(@project, scope: :pending) do
Pending
%span.badge
= number_with_delimiter(@all_builds.pending.count(:id))
%li{class: ('active' if @scope == 'running')}
= link_to project_builds_path(@project, scope: :running) do
Running
%span.badge
= number_with_delimiter(@all_builds.running.count(:id))
%li{class: ('active' if @scope == 'finished')}
= link_to project_builds_path(@project, scope: :finished) do
Finished
%span.badge
= number_with_delimiter(@all_builds.finished.count(:id))
.nav-controls .nav-controls
- if can?(current_user, :update_build, @project) - if can?(current_user, :update_build, @project)
...@@ -42,23 +20,4 @@ ...@@ -42,23 +20,4 @@
%span CI Lint %span CI Lint
%ul.content-list.builds-content-list %ul.content-list.builds-content-list
- if @builds.blank? = render "table", builds: @builds, project: @project
%li
.nothing-here-block No builds to show
- else
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Commit
%th Stage
%th Name
%th
- if @project.build_coverage_enabled?
%th Coverage
%th
= render @builds, commit_sha: true, ref: true, stage: true, allow_retry: true, coverage: @project.build_coverage_enabled?
= paginate @builds, theme: 'gitlab'
- admin = local_assigns.fetch(:admin, false)
- ref = local_assigns.fetch(:ref, nil)
- commit_sha = local_assigns.fetch(:commit_sha, nil)
- retried = local_assigns.fetch(:retried, false)
- stage = local_assigns.fetch(:stage, false)
- coverage = local_assigns.fetch(:coverage, false)
- allow_retry = local_assigns.fetch(:allow_retry, false)
%tr.build.commit %tr.build.commit
%td.status %td.status
- if can?(current_user, :read_build, build) - if can?(current_user, :read_build, build)
...@@ -9,11 +17,11 @@ ...@@ -9,11 +17,11 @@
.branch-commit .branch-commit
- if can?(current_user, :read_build, build) - if can?(current_user, :read_build, build)
= link_to namespace_project_build_url(build.project.namespace, build.project, build) do = link_to namespace_project_build_url(build.project.namespace, build.project, build) do
%span ##{build.id} %span.build-link ##{build.id}
- else - else
%span ##{build.id} %span.build-link ##{build.id}
- if defined?(ref) && ref - if ref
- if build.ref - if build.ref
.icon-container .icon-container
= build.tag? ? icon('tag') : icon('code-fork') = build.tag? ? icon('tag') : icon('code-fork')
...@@ -23,12 +31,12 @@ ...@@ -23,12 +31,12 @@
.icon-container .icon-container
= custom_icon("icon_commit") = custom_icon("icon_commit")
- if defined?(commit_sha) && commit_sha - if commit_sha
= link_to build.short_sha, namespace_project_commit_path(build.project.namespace, build.project, build.sha), class: "commit-id monospace" = link_to build.short_sha, namespace_project_commit_path(build.project.namespace, build.project, build.sha), class: "commit-id monospace"
- if build.stuck? - if build.stuck?
= icon('warning', class: 'text-warning has-tooltip', title: 'Build is stuck. Check runners.') = icon('warning', class: 'text-warning has-tooltip', title: 'Build is stuck. Check runners.')
- if defined?(retried) && retried - if retried
= icon('warning', class: 'text-warning has-tooltip', title: 'Build was retried.') = icon('warning', class: 'text-warning has-tooltip', title: 'Build was retried.')
.label-container .label-container
...@@ -40,19 +48,24 @@ ...@@ -40,19 +48,24 @@
%span.label.label-info triggered %span.label.label-info triggered
- if build.try(:allow_failure) - if build.try(:allow_failure)
%span.label.label-danger allowed to fail %span.label.label-danger allowed to fail
- if defined?(retried) && retried - if retried
%span.label.label-warning retried %span.label.label-warning retried
- if build.manual? - if build.manual?
%span.label.label-info manual %span.label.label-info manual
- if defined?(runner) && runner - if admin
%td
- if build.project
= link_to build.project.name_with_namespace, admin_namespace_project_path(build.project.namespace, build.project)
- if admin
%td %td
- if build.try(:runner) - if build.try(:runner)
= runner_link(build.runner) = runner_link(build.runner)
- else - else
.light none .light none
- if defined?(stage) && stage - if stage
%td %td
= build.stage = build.stage
...@@ -64,13 +77,14 @@ ...@@ -64,13 +77,14 @@
%p.duration %p.duration
= custom_icon("icon_timer") = custom_icon("icon_timer")
= duration_in_numbers(build.duration) = duration_in_numbers(build.duration)
- if build.finished_at - if build.finished_at
%p.finished-at %p.finished-at
= icon("calendar") = icon("calendar")
%span #{time_ago_with_tooltip(build.finished_at)} %span #{time_ago_with_tooltip(build.finished_at)}
- if defined?(coverage) && coverage %td.coverage
%td.coverage - if coverage
- if build.try(:coverage) - if build.try(:coverage)
#{build.coverage}% #{build.coverage}%
...@@ -83,10 +97,10 @@ ...@@ -83,10 +97,10 @@
- if build.active? - if build.active?
= link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do = link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
= icon('remove', class: 'cred') = icon('remove', class: 'cred')
- elsif defined?(allow_retry) && allow_retry - elsif allow_retry
- if build.retryable? - if build.retryable?
= link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do = link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
= icon('repeat') = icon('repeat')
- elsif build.playable? - elsif build.playable? && !admin
= link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do = link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do
= custom_icon('icon_play') = custom_icon('icon_play')
- if @merge_requests.any? - if @merge_requests.any?
%h2.merge-requests-title %h2.merge-requests-title
= pluralize(@merge_requests.count, 'Related Merge Request') = pluralize(@merge_requests.count, 'Related Merge Request')
%ul.unstyled-list %ul.unstyled-list.related-merge-requests
- has_any_ci = @merge_requests.any?(&:pipeline) - has_any_ci = @merge_requests.any?(&:pipeline)
- @merge_requests.each do |merge_request| - @merge_requests.each do |merge_request|
%li %li
......
- if @related_branches.any? - if @related_branches.any?
%h2.related-branches-title %h2.related-branches-title
= pluralize(@related_branches.count, 'Related Branch') = pluralize(@related_branches.count, 'Related Branch')
%ul.unstyled-list %ul.unstyled-list.related-merge-requests
- @related_branches.each do |branch| - @related_branches.each do |branch|
%li %li
- target = @project.repository.find_branch(branch).target - target = @project.repository.find_branch(branch).target
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- if can?(current_user, :update_merge_request, @merge_request) - if can?(current_user, :update_merge_request, @merge_request)
- if @merge_request.open? - if @merge_request.open?
= link_to 'Close merge request', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-nr btn-comment btn-close close-mr-link js-note-target-close", title: "Close merge request", data: {original_text: "Close merge request", alternative_text: "Comment & close merge request"} = link_to 'Close merge request', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-nr btn-comment btn-close close-mr-link js-note-target-close", title: "Close merge request", data: {original_text: "Close merge request", alternative_text: "Comment & close merge request"}
- if @merge_request.closed? - if @merge_request.reopenable?
= link_to 'Reopen merge request', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-nr btn-comment btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request", data: {original_text: "Reopen merge request", alternative_text: "Comment & reopen merge request"} = link_to 'Reopen merge request', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-nr btn-comment btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request", data: {original_text: "Reopen merge request", alternative_text: "Comment & reopen merge request"}
%comment-and-resolve-btn{ "inline-template" => true, ":discussion-id" => "" } %comment-and-resolve-btn{ "inline-template" => true, ":discussion-id" => "" }
%button.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { namespace_path: "#{@merge_request.project.namespace.path}", project_path: "#{@merge_request.project.path}" } } %button.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { namespace_path: "#{@merge_request.project.namespace.path}", project_path: "#{@merge_request.project.path}" } }
......
...@@ -29,17 +29,19 @@ ...@@ -29,17 +29,19 @@
%ul.dropdown-menu.dropdown-menu-align-right %ul.dropdown-menu.dropdown-menu-align-right
%li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch) %li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
%li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff) %li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff)
.normal - unless @merge_request.closed_without_fork?
%span Request to merge .normal
%span.label-branch= source_branch_with_namespace(@merge_request) %span Request to merge
%span into %span.label-branch= source_branch_with_namespace(@merge_request)
%span.label-branch %span into
= link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch) %span.label-branch
- if @merge_request.open? && @merge_request.diverged_from_target_branch? = link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch)
%span (#{pluralize(@merge_request.diverged_commits_count, 'commit')} behind) - if @merge_request.open? && @merge_request.diverged_from_target_branch?
%span (#{pluralize(@merge_request.diverged_commits_count, 'commit')} behind)
= render "projects/merge_requests/show/how_to_merge" - unless @merge_request.closed_without_source_project?
= render "projects/merge_requests/widget/show.html.haml" = render "projects/merge_requests/show/how_to_merge"
= render "projects/merge_requests/widget/show.html.haml"
- if @merge_request.source_branch_exists? && @merge_request.mergeable? && @merge_request.can_be_merged_by?(current_user) - if @merge_request.source_branch_exists? && @merge_request.mergeable? && @merge_request.can_be_merged_by?(current_user)
.light.prepend-top-default.append-bottom-default .light.prepend-top-default.append-bottom-default
...@@ -53,10 +55,11 @@ ...@@ -53,10 +55,11 @@
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do
Discussion Discussion
%span.badge= @merge_request.mr_and_commit_notes.user.count %span.badge= @merge_request.mr_and_commit_notes.user.count
%li.commits-tab - unless @merge_request.closed_without_source_project?
= link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#commits', action: 'commits', toggle: 'tab' } do %li.commits-tab
Commits = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#commits', action: 'commits', toggle: 'tab' } do
%span.badge= @commits_count Commits
%span.badge= @commits_count
- if @pipeline - if @pipeline
%li.pipelines-tab %li.pipelines-tab
= link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do = link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
......
- return unless note.author - return unless note.author
- return if note.cross_reference_not_visible_for?(current_user) - return if note.cross_reference_not_visible_for?(current_user)
- can_resolve = can?(current_user, :resolve_note, note)
- note_editable = note_editable?(note) - note_editable = note_editable?(note)
%li.timeline-entry{ id: dom_id(note), class: ["note", "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} } %li.timeline-entry{ id: dom_id(note), class: ["note", "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} }
...@@ -24,6 +23,8 @@ ...@@ -24,6 +23,8 @@
%span.note-role.hidden-xs= access %span.note-role.hidden-xs= access
- if note.resolvable? - if note.resolvable?
- can_resolve = can?(current_user, :resolve_note, note)
%resolve-btn{ ":namespace-path" => "'#{note.project.namespace.path}'", %resolve-btn{ ":namespace-path" => "'#{note.project.namespace.path}'",
":project-path" => "'#{note.project.path}'", ":project-path" => "'#{note.project.path}'",
":discussion-id" => "'#{note.discussion_id}'", ":discussion-id" => "'#{note.discussion_id}'",
......
%ul.nav-links
%li{ class: ('active' if scope.nil?) }
= link_to build_path_proc.call(nil) do
All
%span.badge.js-totalbuilds-count
= number_with_delimiter(all_builds.count(:id))
%li{ class: ('active' if scope == 'pending') }
= link_to build_path_proc.call('pending') do
Pending
%span.badge
= number_with_delimiter(all_builds.pending.count(:id))
%li{ class: ('active' if scope == 'running') }
= link_to build_path_proc.call('running') do
Running
%span.badge
= number_with_delimiter(all_builds.running.count(:id))
%li{ class: ('active' if scope == 'finished') }
= link_to build_path_proc.call('finished') do
Finished
%span.badge
= number_with_delimiter(all_builds.finished.count(:id))
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
%div %div
%p We heard back from your U2F device. Click this button to authenticate with the GitLab server. %p We heard back from your U2F device. Click this button to authenticate with the GitLab server.
= form_tag(new_user_session_path, method: :post) do |f| = form_tag(new_user_session_path, method: :post) do |f|
- resource_params = params[resource_name].presence || params
= hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
= hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response" = hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
= submit_tag "Authenticate via U2F Device", class: "btn btn-success" = submit_tag "Authenticate via U2F Device", class: "btn btn-success"
......
This diff is collapsed.
...@@ -68,7 +68,8 @@ if Gitlab::Metrics.enabled? ...@@ -68,7 +68,8 @@ if Gitlab::Metrics.enabled?
['app', 'mailers', 'emails'] => ['app', 'mailers'], ['app', 'mailers', 'emails'] => ['app', 'mailers'],
['app', 'services', '**'] => ['app', 'services'], ['app', 'services', '**'] => ['app', 'services'],
['lib', 'gitlab', 'diff'] => ['lib'], ['lib', 'gitlab', 'diff'] => ['lib'],
['lib', 'gitlab', 'email', 'message'] => ['lib'] ['lib', 'gitlab', 'email', 'message'] => ['lib'],
['lib', 'gitlab', 'checks'] => ['lib']
} }
paths_to_instrument.each do |(path, prefix)| paths_to_instrument.each do |(path, prefix)|
......
...@@ -13,9 +13,5 @@ Mime::Type.register "video/mp4", :mp4, [], [:m4v, :mov] ...@@ -13,9 +13,5 @@ Mime::Type.register "video/mp4", :mp4, [], [:m4v, :mov]
Mime::Type.register "video/webm", :webm Mime::Type.register "video/webm", :webm
Mime::Type.register "video/ogg", :ogv Mime::Type.register "video/ogg", :ogv
middlewares = Gitlab::Application.config.middleware Mime::Type.unregister :json
middlewares.swap(ActionDispatch::ParamsParser, ActionDispatch::ParamsParser, { Mime::Type.register 'application/json', :json, %w(application/vnd.git-lfs+json application/json)
Mime::Type.lookup('application/vnd.git-lfs+json') => lambda do |body|
ActiveSupport::JSON.decode(body)
end
})
...@@ -406,7 +406,8 @@ To configure the storage driver in Omnibus: ...@@ -406,7 +406,8 @@ To configure the storage driver in Omnibus:
's3' => { 's3' => {
'accesskey' => 's3-access-key', 'accesskey' => 's3-access-key',
'secretkey' => 's3-secret-key-for-access-key', 'secretkey' => 's3-secret-key-for-access-key',
'bucket' => 'your-s3-bucket' 'bucket' => 'your-s3-bucket',
'region' => 'your-s3-region'
} }
} }
``` ```
...@@ -428,6 +429,7 @@ storage: ...@@ -428,6 +429,7 @@ storage:
accesskey: 'AKIAKIAKI' accesskey: 'AKIAKIAKI'
secretkey: 'secret123' secretkey: 'secret123'
bucket: 'gitlab-registry-bucket-AKIAKIAKI' bucket: 'gitlab-registry-bucket-AKIAKIAKI'
region: 'your-s3-region'
cache: cache:
blobdescriptor: inmemory blobdescriptor: inmemory
delete: delete:
......
...@@ -27,6 +27,7 @@ following locations: ...@@ -27,6 +27,7 @@ following locations:
- [Open source license templates](licenses.md) - [Open source license templates](licenses.md)
- [Namespaces](namespaces.md) - [Namespaces](namespaces.md)
- [Notes](notes.md) (comments) - [Notes](notes.md) (comments)
- [Notification settings](notification_settings.md)
- [Pipelines](pipelines.md) - [Pipelines](pipelines.md)
- [Projects](projects.md) including setting Webhooks - [Projects](projects.md) including setting Webhooks
- [Project Access Requests](access_requests.md) - [Project Access Requests](access_requests.md)
......
...@@ -38,6 +38,15 @@ POST /ci/api/v1/builds/register ...@@ -38,6 +38,15 @@ POST /ci/api/v1/builds/register
curl --request POST "https://gitlab.example.com/ci/api/v1/builds/register" --form "token=t0k3n" curl --request POST "https://gitlab.example.com/ci/api/v1/builds/register" --form "token=t0k3n"
``` ```
**Responses:**
| Status | Data |Description |
|--------|------|---------------------------------------------------------------------------|
| `201` | yes | When a build is scheduled for a runner |
| `204` | no | When no builds are scheduled for a runner (for GitLab Runner >= `v1.3.0`) |
| `403` | no | When invalid token is used or no token is sent |
| `404` | no | When no builds are scheduled for a runner (for GitLab Runner < `v1.3.0`) **or** when the runner is set to `paused` in GitLab runner's configuration page |
### Update details of an existing build ### Update details of an existing build
``` ```
......
# Notification settings
>**Note:** This feature was [introduced][ce-5632] in GitLab 8.12.
**Valid notification levels**
The notification levels are defined in the `NotificationSetting::level` model enumeration. Currently, these levels are recognized:
```
disabled
participating
watch
global
mention
custom
```
If the `custom` level is used, specific email events can be controlled. Notification email events are defined in the `NotificationSetting::EMAIL_EVENTS` model variable. Currently, these events are recognized:
```
new_note
new_issue
reopen_issue
close_issue
reassign_issue
new_merge_request
reopen_merge_request
close_merge_request
reassign_merge_request
merge_merge_request
```
## Global notification settings
Get current notification settings and email address.
```
GET /notification_settings
```
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/notification_settings
```
Example response:
```json
{
"level": "participating",
"notification_email": "admin@example.com"
}
```
## Update global notification settings
Update current notification settings and email address.
```
PUT /notification_settings
```
```bash
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/notification_settings?level=watch
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `level` | string | no | The global notification level |
| `notification_email` | string | no | The email address to send notifications |
| `new_note` | boolean | no | Enable/disable this notification |
| `new_issue` | boolean | no | Enable/disable this notification |
| `reopen_issue` | boolean | no | Enable/disable this notification |
| `close_issue` | boolean | no | Enable/disable this notification |
| `reassign_issue` | boolean | no | Enable/disable this notification |
| `new_merge_request` | boolean | no | Enable/disable this notification |
| `reopen_merge_request` | boolean | no | Enable/disable this notification |
| `close_merge_request` | boolean | no | Enable/disable this notification |
| `reassign_merge_request` | boolean | no | Enable/disable this notification |
| `merge_merge_request` | boolean | no | Enable/disable this notification |
Example response:
```json
{
"level": "watch",
"notification_email": "admin@example.com"
}
```
## Group / project level notification settings
Get current group or project notification settings.
```
GET /groups/:id/notification_settings
GET /projects/:id/notification_settings
```
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/5/notification_settings
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/notification_settings
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The group/project ID or path |
Example response:
```json
{
"level": "global"
}
```
## Update group/project level notification settings
Update current group/project notification settings.
```
PUT /groups/:id/notification_settings
PUT /projects/:id/notification_settings
```
```bash
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/5/notification_settings?level=watch
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/notification_settings?level=custom&new_note=true
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The group/project ID or path |
| `level` | string | no | The global notification level |
| `new_note` | boolean | no | Enable/disable this notification |
| `new_issue` | boolean | no | Enable/disable this notification |
| `reopen_issue` | boolean | no | Enable/disable this notification |
| `close_issue` | boolean | no | Enable/disable this notification |
| `reassign_issue` | boolean | no | Enable/disable this notification |
| `new_merge_request` | boolean | no | Enable/disable this notification |
| `reopen_merge_request` | boolean | no | Enable/disable this notification |
| `close_merge_request` | boolean | no | Enable/disable this notification |
| `reassign_merge_request` | boolean | no | Enable/disable this notification |
| `merge_merge_request` | boolean | no | Enable/disable this notification |
Example responses:
```json
{
"level": "watch"
}
{
"level": "custom",
"events": {
"new_note": true,
"new_issue": false,
"reopen_issue": false,
"close_issue": false,
"reassign_issue": false,
"new_merge_request": false,
"reopen_merge_request": false,
"close_merge_request": false,
"reassign_merge_request": false,
"merge_merge_request": false
}
}
```
[ce-5632]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5632
...@@ -34,6 +34,7 @@ The `API_TOKEN` will take the Secure Variable value: `SECURE`. ...@@ -34,6 +34,7 @@ The `API_TOKEN` will take the Secure Variable value: `SECURE`.
| **CI_BUILD_REF_NAME** | all | all | The branch or tag name for which project is built | | **CI_BUILD_REF_NAME** | all | all | The branch or tag name for which project is built |
| **CI_BUILD_REPO** | all | all | The URL to clone the Git repository | | **CI_BUILD_REPO** | all | all | The URL to clone the Git repository |
| **CI_BUILD_TRIGGERED** | all | 0.5 | The flag to indicate that build was [triggered] | | **CI_BUILD_TRIGGERED** | all | 0.5 | The flag to indicate that build was [triggered] |
| **CI_BUILD_MANUAL** | 8.12 | all | The flag to indicate that build was manually started |
| **CI_BUILD_TOKEN** | all | 1.2 | Token used for authenticating with the GitLab Container Registry | | **CI_BUILD_TOKEN** | all | 1.2 | Token used for authenticating with the GitLab Container Registry |
| **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally | | **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally |
| **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally | | **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally |
...@@ -47,6 +48,8 @@ The `API_TOKEN` will take the Secure Variable value: `SECURE`. ...@@ -47,6 +48,8 @@ The `API_TOKEN` will take the Secure Variable value: `SECURE`.
| **CI_RUNNER_ID** | 8.10 | 0.5 | The unique id of runner being used | | **CI_RUNNER_ID** | 8.10 | 0.5 | The unique id of runner being used |
| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab | | **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
| **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags | | **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags |
| **GITLAB_USER_ID** | 8.12 | all | The id of the user who started the build |
| **GITLAB_USER_EMAIL** | 8.12 | all | The email of the user who started the build |
**Some of the variables are only available when using runner with at least defined version.** **Some of the variables are only available when using runner with at least defined version.**
...@@ -60,6 +63,7 @@ export CI_BUILD_REPO="https://gitab-ci-token:abcde-1234ABCD5678ef@gitlab.com/git ...@@ -60,6 +63,7 @@ export CI_BUILD_REPO="https://gitab-ci-token:abcde-1234ABCD5678ef@gitlab.com/git
export CI_BUILD_TAG="1.0.0" export CI_BUILD_TAG="1.0.0"
export CI_BUILD_NAME="spec:other" export CI_BUILD_NAME="spec:other"
export CI_BUILD_STAGE="test" export CI_BUILD_STAGE="test"
export CI_BUILD_MANUAL="true"
export CI_BUILD_TRIGGERED="true" export CI_BUILD_TRIGGERED="true"
export CI_BUILD_TOKEN="abcde-1234ABCD5678ef" export CI_BUILD_TOKEN="abcde-1234ABCD5678ef"
export CI_PIPELINE_ID="1000" export CI_PIPELINE_ID="1000"
...@@ -78,6 +82,8 @@ export CI_SERVER="yes" ...@@ -78,6 +82,8 @@ export CI_SERVER="yes"
export CI_SERVER_NAME="GitLab" export CI_SERVER_NAME="GitLab"
export CI_SERVER_REVISION="70606bf" export CI_SERVER_REVISION="70606bf"
export CI_SERVER_VERSION="8.9.0" export CI_SERVER_VERSION="8.9.0"
export GITLAB_USER_ID="42"
export GITLAB_USER_EMAIL="alexzander@sporer.com"
``` ```
### YAML-defined variables ### YAML-defined variables
......
...@@ -137,3 +137,18 @@ end ...@@ -137,3 +137,18 @@ end
``` ```
Here the final value of `sleep_real_time` will be `3`, _not_ `1`. Here the final value of `sleep_real_time` will be `3`, _not_ `1`.
## Tracking Custom Events
Besides instrumenting code GitLab Performance Monitoring also supports tracking
of custom events. This is primarily intended to be used for tracking business
metrics such as the number of Git pushes, repository imports, and so on.
To track a custom event simply call `Gitlab::Metrics.add_event` passing it an
event name and a custom set of (optional) tags. For example:
```ruby
Gitlab::Metrics.add_event(:user_login, email: current_user.email)
```
Event names should be verbs such as `push_repository` and `remove_branch`.
...@@ -400,7 +400,7 @@ If you are not using Linux you may have to run `gmake` instead of ...@@ -400,7 +400,7 @@ If you are not using Linux you may have to run `gmake` instead of
cd /home/git cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse cd gitlab-workhorse
sudo -u git -H git checkout v0.8.0 sudo -u git -H git checkout v0.8.1
sudo -u git -H make sudo -u git -H make
### Initialize Database and Activate Advanced Features ### Initialize Database and Activate Advanced Features
......
...@@ -82,7 +82,7 @@ GitLab 8.1. ...@@ -82,7 +82,7 @@ GitLab 8.1.
```bash ```bash
cd /home/git/gitlab-workhorse cd /home/git/gitlab-workhorse
sudo -u git -H git fetch --all sudo -u git -H git fetch --all
sudo -u git -H git checkout v0.8.0 sudo -u git -H git checkout v0.8.1
sudo -u git -H make sudo -u git -H make
``` ```
......
...@@ -15,6 +15,7 @@ At its current state, GitHub importer can import: ...@@ -15,6 +15,7 @@ At its current state, GitHub importer can import:
- the wiki pages (introduced in GitLab 8.4) - the wiki pages (introduced in GitLab 8.4)
- the milestones (introduced in GitLab 8.7) - the milestones (introduced in GitLab 8.7)
- the labels (introduced in GitLab 8.7) - the labels (introduced in GitLab 8.7)
- the release note descriptions (introduced in GitLab 8.12)
With GitLab 8.7+, references to pull requests and issues are preserved. With GitLab 8.7+, references to pull requests and issues are preserved.
......
...@@ -51,6 +51,7 @@ module API ...@@ -51,6 +51,7 @@ module API
mount ::API::Milestones mount ::API::Milestones
mount ::API::Namespaces mount ::API::Namespaces
mount ::API::Notes mount ::API::Notes
mount ::API::NotificationSettings
mount ::API::Pipelines mount ::API::Pipelines
mount ::API::ProjectHooks mount ::API::ProjectHooks
mount ::API::ProjectSnippets mount ::API::ProjectSnippets
......
...@@ -37,7 +37,7 @@ module API ...@@ -37,7 +37,7 @@ module API
# id (required) - The ID of a project # id (required) - The ID of a project
# sha (required) - The commit hash # sha (required) - The commit hash
# ref (optional) - The ref # ref (optional) - The ref
# state (required) - The state of the status. Can be: pending, running, success, error or failure # state (required) - The state of the status. Can be: pending, running, success, failed or canceled
# target_url (optional) - The target URL to associate with this status # target_url (optional) - The target URL to associate with this status
# description (optional) - A short description of the status # description (optional) - A short description of the status
# name or context (optional) - A string label to differentiate this status from the status of other systems. Default: "default" # name or context (optional) - A string label to differentiate this status from the status of other systems. Default: "default"
...@@ -46,7 +46,7 @@ module API ...@@ -46,7 +46,7 @@ module API
post ':id/statuses/:sha' do post ':id/statuses/:sha' do
authorize! :create_commit_status, user_project authorize! :create_commit_status, user_project
required_attributes! [:state] required_attributes! [:state]
attrs = attributes_for_keys [:ref, :target_url, :description, :context, :name] attrs = attributes_for_keys [:target_url, :description]
commit = @project.commit(params[:sha]) commit = @project.commit(params[:sha])
not_found! 'Commit' unless commit not_found! 'Commit' unless commit
...@@ -58,36 +58,38 @@ module API ...@@ -58,36 +58,38 @@ module API
# the first found branch on that commit # the first found branch on that commit
ref = params[:ref] ref = params[:ref]
unless ref ref ||= @project.repository.branch_names_contains(commit.sha).first
branches = @project.repository.branch_names_contains(commit.sha) not_found! 'References for commit' unless ref
not_found! 'References for commit' if branches.none?
ref = branches.first name = params[:name] || params[:context] || 'default'
end
pipeline = @project.ensure_pipeline(ref, commit.sha, current_user) pipeline = @project.ensure_pipeline(ref, commit.sha, current_user)
name = params[:name] || params[:context] status = GenericCommitStatus.running_or_pending.find_or_initialize_by(
status = GenericCommitStatus.running_or_pending.find_by(pipeline: pipeline, name: name, ref: params[:ref]) project: @project, pipeline: pipeline,
status ||= GenericCommitStatus.new(project: @project, pipeline: pipeline, user: current_user) user: current_user, name: name, ref: ref)
status.update(attrs) status.attributes = attrs
case params[:state].to_s begin
when 'running' case params[:state].to_s
status.run when 'pending'
when 'success' status.enqueue!
status.success when 'running'
when 'failed' status.enqueue
status.drop status.run!
when 'canceled' when 'success'
status.cancel status.success!
else when 'failed'
status.status = params[:state].to_s status.drop!
end when 'canceled'
status.cancel!
else
render_api_error!('invalid state', 400)
end
if status.save
present status, with: Entities::CommitStatus present status, with: Entities::CommitStatus
else rescue StateMachines::InvalidTransition => e
render_validation_error!(status) render_api_error!(e.message, 400)
end end
end end
end end
......
...@@ -375,7 +375,7 @@ module API ...@@ -375,7 +375,7 @@ module API
expose :access_level expose :access_level
expose :notification_level do |member, options| expose :notification_level do |member, options|
if member.notification_setting if member.notification_setting
NotificationSetting.levels[member.notification_setting.level] ::NotificationSetting.levels[member.notification_setting.level]
end end
end end
end end
...@@ -386,6 +386,21 @@ module API ...@@ -386,6 +386,21 @@ module API
class GroupAccess < MemberAccess class GroupAccess < MemberAccess
end end
class NotificationSetting < Grape::Entity
expose :level
expose :events, if: ->(notification_setting, _) { notification_setting.custom? } do
::NotificationSetting::EMAIL_EVENTS.each do |event|
expose event
end
end
end
class GlobalNotificationSetting < NotificationSetting
expose :notification_email do |notification_setting, options|
notification_setting.user.notification_email
end
end
class ProjectService < Grape::Entity class ProjectService < Grape::Entity
expose :id, :title, :created_at, :updated_at, :active expose :id, :title, :created_at, :updated_at, :active
expose :push_events, :issues_events, :merge_requests_events expose :push_events, :issues_events, :merge_requests_events
......
...@@ -269,6 +269,10 @@ module API ...@@ -269,6 +269,10 @@ module API
render_api_error!('304 Not Modified', 304) render_api_error!('304 Not Modified', 304)
end end
def no_content!
render_api_error!('204 No Content', 204)
end
def render_validation_error!(model) def render_validation_error!(model)
if model.errors.any? if model.errors.any?
render_api_error!(model.errors.messages || '400 Bad Request', 400) render_api_error!(model.errors.messages || '400 Bad Request', 400)
......
...@@ -41,7 +41,8 @@ module API ...@@ -41,7 +41,8 @@ module API
issues = current_user.issues.inc_notes_with_associations issues = current_user.issues.inc_notes_with_associations
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil? issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil? issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
issues.reorder(issuable_order_by => issuable_sort) issues = issues.reorder(issuable_order_by => issuable_sort)
present paginate(issues), with: Entities::Issue, current_user: current_user present paginate(issues), with: Entities::Issue, current_user: current_user
end end
end end
...@@ -73,7 +74,11 @@ module API ...@@ -73,7 +74,11 @@ module API
params[:group_id] = group.id params[:group_id] = group.id
params[:milestone_title] = params.delete(:milestone) params[:milestone_title] = params.delete(:milestone)
params[:label_name] = params.delete(:labels) params[:label_name] = params.delete(:labels)
params[:sort] = "#{params.delete(:order_by)}_#{params.delete(:sort)}" if params[:order_by] && params[:sort]
if params[:order_by] || params[:sort]
# The Sortable concern takes 'created_desc', not 'created_at_desc' (for example)
params[:sort] = "#{issuable_order_by.sub('_at', '')}_#{issuable_sort}"
end
issues = IssuesFinder.new(current_user, params).execute issues = IssuesFinder.new(current_user, params).execute
...@@ -113,7 +118,8 @@ module API ...@@ -113,7 +118,8 @@ module API
issues = filter_issues_milestone(issues, params[:milestone]) issues = filter_issues_milestone(issues, params[:milestone])
end end
issues.reorder(issuable_order_by => issuable_sort) issues = issues.reorder(issuable_order_by => issuable_sort)
present paginate(issues), with: Entities::Issue, current_user: current_user present paginate(issues), with: Entities::Issue, current_user: current_user
end end
......
module API
# notification_settings API
class NotificationSettings < Grape::API
before { authenticate! }
helpers ::API::Helpers::MembersHelpers
resource :notification_settings do
desc 'Get global notification level settings and email, defaults to Participate' do
detail 'This feature was introduced in GitLab 8.12'
success Entities::GlobalNotificationSetting
end
get do
notification_setting = current_user.global_notification_setting
present notification_setting, with: Entities::GlobalNotificationSetting
end
desc 'Update global notification level settings and email, defaults to Participate' do
detail 'This feature was introduced in GitLab 8.12'
success Entities::GlobalNotificationSetting
end
params do
optional :level, type: String, desc: 'The global notification level'
optional :notification_email, type: String, desc: 'The email address to send notifications'
NotificationSetting::EMAIL_EVENTS.each do |event|
optional event, type: Boolean, desc: 'Enable/disable this notification'
end
end
put do
notification_setting = current_user.global_notification_setting
begin
notification_setting.transaction do
new_notification_email = params.delete(:notification_email)
declared_params = declared(params, include_missing: false).to_h
current_user.update(notification_email: new_notification_email) if new_notification_email
notification_setting.update(declared_params)
end
rescue ArgumentError => e # catch level enum error
render_api_error! e.to_s, 400
end
render_validation_error! current_user
render_validation_error! notification_setting
present notification_setting, with: Entities::GlobalNotificationSetting
end
end
%w[group project].each do |source_type|
resource source_type.pluralize do
desc "Get #{source_type} level notification level settings, defaults to Global" do
detail 'This feature was introduced in GitLab 8.12'
success Entities::NotificationSetting
end
params do
requires :id, type: String, desc: 'The group ID or project ID or project NAMESPACE/PROJECT_NAME'
end
get ":id/notification_settings" do
source = find_source(source_type, params[:id])
notification_setting = current_user.notification_settings_for(source)
present notification_setting, with: Entities::NotificationSetting
end
desc "Update #{source_type} level notification level settings, defaults to Global" do
detail 'This feature was introduced in GitLab 8.12'
success Entities::NotificationSetting
end
params do
requires :id, type: String, desc: 'The group ID or project ID or project NAMESPACE/PROJECT_NAME'
optional :level, type: String, desc: "The #{source_type} notification level"
NotificationSetting::EMAIL_EVENTS.each do |event|
optional event, type: Boolean, desc: 'Enable/disable this notification'
end
end
put ":id/notification_settings" do
source = find_source(source_type, params.delete(:id))
notification_setting = current_user.notification_settings_for(source)
begin
declared_params = declared(params, include_missing: false).to_h
notification_setting.update(declared_params)
rescue ArgumentError => e # catch level enum error
render_api_error! e.to_s, 400
end
render_validation_error! notification_setting
present notification_setting, with: Entities::NotificationSetting
end
end
end
end
end
...@@ -428,18 +428,9 @@ module API ...@@ -428,18 +428,9 @@ module API
# Example Request: # Example Request:
# GET /projects/search/:query # GET /projects/search/:query
get "/search/:query" do get "/search/:query" do
ids = current_user.authorized_projects.map(&:id) search_service = Search::GlobalService.new(current_user, search: params[:query]).execute
visibility_levels = [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ] projects = search_service.objects('projects', params[:page])
projects = Project.where("(id in (?) OR visibility_level in (?)) AND (name LIKE (?))", ids, visibility_levels, "%#{params[:query]}%") projects = projects.reorder(project_order_by => project_sort)
sort = params[:sort] == 'desc' ? 'desc' : 'asc'
projects = case params["order_by"]
when 'id' then projects.order("id #{sort}")
when 'name' then projects.order("name #{sort}")
when 'created_at' then projects.order("created_at #{sort}")
when 'last_activity_at' then projects.order("last_activity_at #{sort}")
else projects
end
present paginate(projects), with: Entities::Project present paginate(projects), with: Entities::Project
end end
......
...@@ -27,7 +27,7 @@ module Ci ...@@ -27,7 +27,7 @@ module Ci
else else
Gitlab::Metrics.add_event(:build_not_found) Gitlab::Metrics.add_event(:build_not_found)
not_found! build_not_found!
end end
end end
......
...@@ -32,6 +32,14 @@ module Ci ...@@ -32,6 +32,14 @@ module Ci
end end
end end
def build_not_found!
if headers['User-Agent'].match(/gitlab-ci-multi-runner \d+\.\d+\.\d+(~beta\.\d+\.g[0-9a-f]+)? /)
no_content!
else
not_found!
end
end
def current_runner def current_runner
@runner ||= Runner.find_by_token(params[:token].to_s) @runner ||= Runner.find_by_token(params[:token].to_s)
end end
......
...@@ -195,7 +195,7 @@ module Gitlab ...@@ -195,7 +195,7 @@ module Gitlab
# Create (if necessary) and link the secret token file # Create (if necessary) and link the secret token file
def generate_and_link_secret_token def generate_and_link_secret_token
secret_file = Gitlab.config.gitlab_shell.secret_file secret_file = Gitlab.config.gitlab_shell.secret_file
unless File.exist? secret_file unless File.size?(secret_file)
# Generate a new token of 16 random hexadecimal characters and store it in secret_file. # Generate a new token of 16 random hexadecimal characters and store it in secret_file.
token = SecureRandom.hex(16) token = SecureRandom.hex(16)
File.write(secret_file, token) File.write(secret_file, token)
......
...@@ -23,6 +23,7 @@ module Gitlab ...@@ -23,6 +23,7 @@ module Gitlab
protected protected
def protected_branch_checks def protected_branch_checks
return unless @branch_name
return unless project.protected_branch?(@branch_name) return unless project.protected_branch?(@branch_name)
if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches) if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches)
......
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.
= render partial: "u2f/authenticate", locals: { new_user_session_path: "/users/sign_in" } = render partial: "u2f/authenticate", locals: { new_user_session_path: "/users/sign_in", params: {}, resource_name: "user" }
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