Commit 502aabdc authored by Alejandro Rodríguez's avatar Alejandro Rodríguez

Merge branch 'master' into 8-14-stable

parents b83e8a5a f4710ee8
...@@ -61,9 +61,10 @@ update-knapsack: ...@@ -61,9 +61,10 @@ update-knapsack:
- scripts/merge-reports knapsack/spinach_report.json knapsack/spinach_node_*.json - scripts/merge-reports knapsack/spinach_report.json knapsack/spinach_node_*.json
- rm -f knapsack/*_node_*.json - rm -f knapsack/*_node_*.json
only: only:
- master - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
# Execute all testing suites - master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
.use-db: &use-db .use-db: &use-db
services: services:
...@@ -143,7 +144,10 @@ spinach 9 10: *spinach-knapsack ...@@ -143,7 +144,10 @@ spinach 9 10: *spinach-knapsack
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.1-git-2.7-phantomjs-2.1" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.1-git-2.7-phantomjs-2.1"
<<: *use-db <<: *use-db
only: only:
- master - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
cache: cache:
key: "ruby21" key: "ruby21"
paths: paths:
...@@ -286,7 +290,10 @@ bundler:audit: ...@@ -286,7 +290,10 @@ bundler:audit:
stage: test stage: test
<<: *ruby-static-analysis <<: *ruby-static-analysis
only: only:
- master - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
script: script:
- "bundle exec bundle-audit check --update --ignore OSVDB-115941" - "bundle exec bundle-audit check --update --ignore OSVDB-115941"
...@@ -297,6 +304,9 @@ migration paths: ...@@ -297,6 +304,9 @@ migration paths:
SETUP_DB: "false" SETUP_DB: "false"
only: only:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
script: script:
- git checkout HEAD . - git checkout HEAD .
- git fetch --tags - git fetch --tags
......
...@@ -63,6 +63,7 @@ header { ...@@ -63,6 +63,7 @@ header {
&:focus, &:focus,
&:active { &:active {
background-color: $background-color; background-color: $background-color;
color: darken($gl-icon-color, 50%);
} }
.fa-caret-down { .fa-caret-down {
...@@ -152,7 +153,7 @@ header { ...@@ -152,7 +153,7 @@ header {
padding-right: 20px; padding-right: 20px;
margin: 0; margin: 0;
font-size: 19px; font-size: 19px;
max-width: 400px; max-width: 385px;
display: inline-block; display: inline-block;
line-height: $header-height; line-height: $header-height;
font-weight: normal; font-weight: normal;
...@@ -191,6 +192,10 @@ header { ...@@ -191,6 +192,10 @@ header {
font-size: 10px; font-size: 10px;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
&:hover {
color: darken($color: $gl-text-color, $amount: 50%);
}
} }
.project-item-select { .project-item-select {
...@@ -218,6 +223,14 @@ header { ...@@ -218,6 +223,14 @@ header {
} }
} }
.page-sidebar-pinned.right-sidebar-expanded {
@media (max-width: $screen-lg-min) {
.header-content .title {
width: 300px;
}
}
}
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
header .container-fluid { header .container-fluid {
font-size: 18px; font-size: 18px;
......
...@@ -252,7 +252,7 @@ $award-emoji-new-btn-icon-color: #dcdcdc; ...@@ -252,7 +252,7 @@ $award-emoji-new-btn-icon-color: #dcdcdc;
*/ */
$search-input-border-color: rgba(#4688f1, .8); $search-input-border-color: rgba(#4688f1, .8);
$search-input-focus-shadow-color: $dropdown-input-focus-shadow; $search-input-focus-shadow-color: $dropdown-input-focus-shadow;
$search-input-width: 244px; $search-input-width: 220px;
$location-badge-color: #aaa; $location-badge-color: #aaa;
$location-badge-bg: $gray-normal; $location-badge-bg: $gray-normal;
$location-badge-active-bg: #4f91f8; $location-badge-active-bg: #4f91f8;
......
...@@ -84,7 +84,8 @@ ...@@ -84,7 +84,8 @@
font-weight: 600; font-weight: 600;
} }
.commit { .commit,
.generic_commit_status {
padding: 10px 0; padding: 10px 0;
position: relative; position: relative;
...@@ -102,7 +103,6 @@ ...@@ -102,7 +103,6 @@
vertical-align: baseline; vertical-align: baseline;
} }
.avatar { .avatar {
margin-left: -46px; margin-left: -46px;
} }
......
...@@ -141,6 +141,22 @@ ul.notes { ...@@ -141,6 +141,22 @@ ul.notes {
} }
} }
.page-sidebar-pinned.right-sidebar-expanded {
@media (max-width: $screen-lg-min) {
.note-header {
.note-headline-light {
display: block;
}
.note-actions {
position: absolute;
right: 0;
top: 0;
}
}
}
}
// Diff code in discussion view // Diff code in discussion view
.discussion-body .diff-file { .discussion-body .diff-file {
.file-title { .file-title {
......
...@@ -109,10 +109,6 @@ ...@@ -109,10 +109,6 @@
float: none; float: none;
} }
.api {
color: $code-color;
}
.branch-commit { .branch-commit {
.branch-name { .branch-name {
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
padding: 4px; padding: 4px;
width: $search-input-width; width: $search-input-width;
line-height: 24px; line-height: 24px;
&:hover {
border-color: lighten($dropdown-input-focus-border, 20%);
box-shadow: 0 0 4px lighten($search-input-focus-shadow-color, 20%);
}
} }
.location-text { .location-text {
...@@ -28,10 +33,9 @@ ...@@ -28,10 +33,9 @@
} }
.search-input { .search-input {
padding-right: 20px;
border: none; border: none;
font-size: 14px; font-size: 14px;
padding: 0; padding: 0 20px 0 0;
margin-left: 5px; margin-left: 5px;
line-height: 25px; line-height: 25px;
width: 98%; width: 98%;
...@@ -153,6 +157,7 @@ ...@@ -153,6 +157,7 @@
width: 68%; width: 68%;
} }
} }
} }
.search-holder { .search-holder {
...@@ -229,4 +234,5 @@ ...@@ -229,4 +234,5 @@
&:focus { &:focus {
color: $gl-link-color; color: $gl-link-color;
} }
} }
...@@ -7,8 +7,8 @@ class HelpController < ApplicationController ...@@ -7,8 +7,8 @@ class HelpController < ApplicationController
@help_index = File.read(Rails.root.join('doc', 'README.md')) @help_index = File.read(Rails.root.join('doc', 'README.md'))
# Prefix Markdown links with `help/` unless they already have been # Prefix Markdown links with `help/` unless they already have been
# See http://rubular.com/r/nwwhzH6Z8X # See http://rubular.com/r/ie2MlpdUMq
@help_index.gsub!(/(\]\()(?!help\/)([^\)\(]+)(\))/, '\1help/\2\3') @help_index.gsub!(/(\]\()(\/?help\/)?([^\)\(]+\))/, '\1/help/\3')
end end
def show def show
......
...@@ -3,7 +3,7 @@ module AuthHelper ...@@ -3,7 +3,7 @@ module AuthHelper
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
def ldap_enabled? def ldap_enabled?
Gitlab.config.ldap.enabled Gitlab::LDAP::Config.enabled?
end end
def omniauth_enabled? def omniauth_enabled?
......
...@@ -82,6 +82,10 @@ module GitlabRoutingHelper ...@@ -82,6 +82,10 @@ module GitlabRoutingHelper
namespace_project_merge_request_path(entity.project.namespace, entity.project, entity, *args) namespace_project_merge_request_path(entity.project.namespace, entity.project, entity, *args)
end end
def pipeline_path(pipeline, *args)
namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, *args)
end
def milestone_path(entity, *args) def milestone_path(entity, *args)
namespace_project_milestone_path(entity.project.namespace, entity.project, entity, *args) namespace_project_milestone_path(entity.project.namespace, entity.project, entity, *args)
end end
......
...@@ -203,6 +203,10 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -203,6 +203,10 @@ class ApplicationSetting < ActiveRecord::Base
ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url) ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url)
end end
def sidekiq_throttling_column_exists?
ActiveRecord::Base.connection.column_exists?(:application_settings, :sidekiq_throttling_enabled)
end
def domain_whitelist_raw def domain_whitelist_raw
self.domain_whitelist.join("\n") unless self.domain_whitelist.nil? self.domain_whitelist.join("\n") unless self.domain_whitelist.nil?
end end
...@@ -256,6 +260,12 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -256,6 +260,12 @@ class ApplicationSetting < ActiveRecord::Base
ensure_health_check_access_token! ensure_health_check_access_token!
end end
def sidekiq_throttling_enabled?
return false unless sidekiq_throttling_column_exists?
sidekiq_throttling_enabled
end
private private
def check_repository_storages def check_repository_storages
......
...@@ -266,7 +266,7 @@ class Issue < ActiveRecord::Base ...@@ -266,7 +266,7 @@ class Issue < ActiveRecord::Base
def as_json(options = {}) def as_json(options = {})
super(options).tap do |json| super(options).tap do |json|
json[:subscribed] = subscribed?(options[:user]) if options.has_key?(:user) json[:subscribed] = subscribed?(options[:user]) if options.has_key?(:user) && options[:user]
if options.has_key?(:labels) if options.has_key?(:labels)
json[:labels] = labels.as_json( json[:labels] = labels.as_json(
......
...@@ -7,6 +7,7 @@ class Note < ActiveRecord::Base ...@@ -7,6 +7,7 @@ class Note < ActiveRecord::Base
include Importable include Importable
include FasterCacheKeys include FasterCacheKeys
include CacheMarkdownField include CacheMarkdownField
include AfterCommitQueue
cache_markdown_field :note, pipeline: :note cache_markdown_field :note, pipeline: :note
......
...@@ -49,20 +49,14 @@ class ProjectFeature < ActiveRecord::Base ...@@ -49,20 +49,14 @@ class ProjectFeature < ActiveRecord::Base
end end
def builds_enabled? def builds_enabled?
return true unless builds_access_level
builds_access_level > DISABLED builds_access_level > DISABLED
end end
def wiki_enabled? def wiki_enabled?
return true unless wiki_access_level
wiki_access_level > DISABLED wiki_access_level > DISABLED
end end
def merge_requests_enabled? def merge_requests_enabled?
return true unless merge_requests_access_level
merge_requests_access_level > DISABLED merge_requests_access_level > DISABLED
end end
......
...@@ -26,9 +26,12 @@ module Notes ...@@ -26,9 +26,12 @@ module Notes
note.note = content note.note = content
end end
if !only_commands && note.save note.run_after_commit do
# Finish the harder work in the background # Finish the harder work in the background
NewNoteWorker.perform_in(2.seconds, note.id, params) NewNoteWorker.perform_async(note.id)
end
if !only_commands && note.save
todo_service.new_note(note, current_user) todo_service.new_note(note, current_user)
end end
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
= render "shared/empty_states/todos_all_done.svg" = render "shared/empty_states/todos_all_done.svg"
- if todos_filter_empty? - if todos_filter_empty?
%h4.text-center %h4.text-center
Good job! Looks like you don't have any todos left. = Gitlab.config.gitlab.no_todos_messages.sample
%p.text-center %p.text-center
Are you looking for things to do? Take a look at Are you looking for things to do? Take a look at
= succeed "," do = succeed "," do
......
%board-sidebar{ "inline-template" => true, %board-sidebar{ "inline-template" => true,
":current-user" => "#{current_user.to_json(only: [:username, :id, :name], methods: [:avatar_url]) if current_user}" } ":current-user" => "#{current_user ? current_user.to_json(only: [:username, :id, :name], methods: [:avatar_url]) : {}}" }
%aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" } %aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" }
.issuable-sidebar .issuable-sidebar
.block.issuable-sidebar-header .block.issuable-sidebar-header
......
.block.assignee .block.assignee
.title.hide-collapsed .title.hide-collapsed
Assignee Assignee
= icon("spinner spin", class: "block-loading")
- if can?(current_user, :admin_issue, @project) - if can?(current_user, :admin_issue, @project)
= icon("spinner spin", class: "block-loading")
= link_to "Edit", "#", class: "edit-link pull-right" = link_to "Edit", "#", class: "edit-link pull-right"
.value.hide-collapsed .value.hide-collapsed
%span.assign-yourself.no-value{ "v-if" => "!issue.assignee" } %span.assign-yourself.no-value{ "v-if" => "!issue.assignee" }
......
.block.due_date .block.due_date
.title .title
Due date Due date
= icon("spinner spin", class: "block-loading")
- if can?(current_user, :admin_issue, @project) - if can?(current_user, :admin_issue, @project)
= icon("spinner spin", class: "block-loading")
= link_to "Edit", "#", class: "edit-link pull-right" = link_to "Edit", "#", class: "edit-link pull-right"
.value .value
.value-content .value-content
......
.block.labels .block.labels
.title .title
Labels Labels
= icon("spinner spin", class: "block-loading")
- if can?(current_user, :admin_issue, @project) - if can?(current_user, :admin_issue, @project)
= icon("spinner spin", class: "block-loading")
= link_to "Edit", "#", class: "edit-link pull-right" = link_to "Edit", "#", class: "edit-link pull-right"
.value.issuable-show-labels .value.issuable-show-labels
%span.no-value{ "v-if" => "issue.labels && issue.labels.length === 0" } %span.no-value{ "v-if" => "issue.labels && issue.labels.length === 0" }
......
.block.milestone .block.milestone
.title .title
Milestone Milestone
= icon("spinner spin", class: "block-loading")
- if can?(current_user, :admin_issue, @project) - if can?(current_user, :admin_issue, @project)
= icon("spinner spin", class: "block-loading")
= link_to "Edit", "#", class: "edit-link pull-right" = link_to "Edit", "#", class: "edit-link pull-right"
.value .value
%span.no-value{ "v-if" => "!issue.milestone" } %span.no-value{ "v-if" => "!issue.milestone" }
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
= ci_status_with_icon(@build.status) = ci_status_with_icon(@build.status)
Build Build
%strong ##{@build.id} %strong ##{@build.id}
in pipeline
= link_to pipeline_path(@build.pipeline) do
%strong ##{@build.pipeline.id}
for commit for commit
= link_to ci_status_path(@build.pipeline) do = link_to ci_status_path(@build.pipeline) do
%strong= @build.pipeline.short_sha %strong= @build.pipeline.short_sha
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
%tr %tr
%th Status %th Status
%th Build %th Build
%th Pipeline
- if admin - if admin
%th Project %th Project
%th Runner %th Runner
...@@ -19,6 +20,6 @@ ...@@ -19,6 +20,6 @@
%th Coverage %th Coverage
%th %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 } = render partial: "projects/ci/builds/build", collection: builds, as: :build, locals: { commit_sha: true, ref: true, pipeline_link: true, stage: true, allow_retry: true, coverage: admin || project.build_coverage_enabled?, admin: admin }
= paginate builds, theme: 'gitlab' = paginate builds, theme: 'gitlab'
- if !project.empty_repo? && can?(current_user, :download_code, project) - if !project.empty_repo? && can?(current_user, :download_code, project)
%span{class: 'hidden-xs hidden-sm download-button'} %span{class: 'download-button'}
.dropdown.inline .dropdown.inline
%button.btn{ 'data-toggle' => 'dropdown' } %button.btn{ 'data-toggle' => 'dropdown' }
= icon('download') = icon('download')
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
- ref = local_assigns.fetch(:ref, nil) - ref = local_assigns.fetch(:ref, nil)
- commit_sha = local_assigns.fetch(:commit_sha, nil) - commit_sha = local_assigns.fetch(:commit_sha, nil)
- retried = local_assigns.fetch(:retried, false) - retried = local_assigns.fetch(:retried, false)
- pipeline_link = local_assigns.fetch(:pipeline_link, false)
- stage = local_assigns.fetch(:stage, false) - stage = local_assigns.fetch(:stage, false)
- coverage = local_assigns.fetch(:coverage, false) - coverage = local_assigns.fetch(:coverage, false)
- allow_retry = local_assigns.fetch(:allow_retry, false) - allow_retry = local_assigns.fetch(:allow_retry, false)
...@@ -51,6 +52,16 @@ ...@@ -51,6 +52,16 @@
- if build.manual? - if build.manual?
%span.label.label-info manual %span.label.label-info manual
- if pipeline_link
%td
= link_to pipeline_path(build.pipeline) do
%span.pipeline-id ##{build.pipeline.id}
%span by
- if build.pipeline.user
= user_avatar(user: build.pipeline.user, size: 20)
- else
%span.monospace API
- if admin - if admin
%td %td
- if build.project - if build.project
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
- if stage - if stage
&nbsp; &nbsp;
= stage.titleize = stage.titleize
= render statuses.latest_ci_stages, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true = render statuses.latest_ci_stages, coverage: @project.build_coverage_enabled?, stage: false, ref: false, pipeline_link: false, allow_retry: true
= render statuses.retried_ci_stages, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true = render statuses.retried_ci_stages, coverage: @project.build_coverage_enabled?, stage: false, ref: false, pipeline_link: false, retried: true
%tr %tr
%td{colspan: 10} %td{colspan: 10}
&nbsp; &nbsp;
...@@ -15,6 +15,16 @@ ...@@ -15,6 +15,16 @@
- if defined?(retried) && retried - if defined?(retried) && retried
= icon('warning', class: 'text-warning has-tooltip', title: 'Status was retried.') = icon('warning', class: 'text-warning has-tooltip', title: 'Status was retried.')
- if defined?(pipeline_link) && pipeline_link
%td
= link_to pipeline_path(generic_commit_status.pipeline) do
%span.pipeline-id ##{generic_commit_status.pipeline.id}
%span by
- if generic_commit_status.pipeline.user
= user_avatar(user: generic_commit_status.pipeline.user, size: 20)
- else
%span.monospace API
- if defined?(commit_sha) && commit_sha - if defined?(commit_sha) && commit_sha
%td %td
= link_to generic_commit_status.short_sha, namespace_project_commit_path(generic_commit_status.project.namespace, generic_commit_status.project, generic_commit_status.sha), class: "monospace" = link_to generic_commit_status.short_sha, namespace_project_commit_path(generic_commit_status.project.namespace, generic_commit_status.project, generic_commit_status.sha), class: "monospace"
......
...@@ -90,7 +90,8 @@ ...@@ -90,7 +90,8 @@
= f.label :visibility_level, class: 'label-light' do = f.label :visibility_level, class: 'label-light' do
Visibility Level Visibility Level
= link_to "(?)", help_page_path("public_access/public_access") = link_to "(?)", help_page_path("public_access/public_access")
= render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: @project.visibility_level, form_model: @project) = render 'shared/visibility_level', f: f, visibility_level: default_project_visibility, can_change_visibility_level: true, form_model: @project
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4 = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel' = link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel'
......
...@@ -2,10 +2,12 @@ class NewNoteWorker ...@@ -2,10 +2,12 @@ class NewNoteWorker
include Sidekiq::Worker include Sidekiq::Worker
include DedicatedSidekiqQueue include DedicatedSidekiqQueue
def perform(note_id, note_params) def perform(note_id)
note = Note.find(note_id) if note = Note.find_by(id: note_id)
NotificationService.new.new_note(note)
NotificationService.new.new_note(note) Notes::PostProcessService.new(note).execute
Notes::PostProcessService.new(note).execute else
Rails.logger.error("NewNoteWorker: couldn't find note with ID=#{note_id}, skipping job")
end
end end
end end
---
title: Add link to build pipeline within individual build pages
merge_request: 7082
author:
---
title: Project download buttons always show
merge_request: 7405
author: Philip Karpiak
---
title: Fix error links in help index page
merge_request: 7396
author: Fu Xu
---
title: Give search-input correct padding-right value
merge_request: 7407
author: Philip Karpiak
---
title: Show random messages when the To Do list is empty
merge_request: 6818
author: Josep Llaneras
---
title: Fix project Visibility Level selector not using default values
merge_request:
author:
---
title: Fix record not found error on NewNoteWorker processing
merge_request: 6863
author: Oswaldo Ferreira
---
title: Added ability to put emojis into repository name
merge_request: 7420
author: Vincent Composieux
---
title: Centralize LDAP config/filter logic
merge_request: 6606
author:
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
# #
production: production:
adapter: mysql2 adapter: mysql2
encoding: utf8 encoding: utf8mb4
collation: utf8_general_ci collation: utf8mb4_general_ci
reconnect: false reconnect: false
database: gitlabhq_production database: gitlabhq_production
pool: 10 pool: 10
...@@ -18,8 +18,8 @@ production: ...@@ -18,8 +18,8 @@ production:
# #
development: development:
adapter: mysql2 adapter: mysql2
encoding: utf8 encoding: utf8mb4
collation: utf8_general_ci collation: utf8mb4_general_ci
reconnect: false reconnect: false
database: gitlabhq_development database: gitlabhq_development
pool: 5 pool: 5
...@@ -32,8 +32,8 @@ development: ...@@ -32,8 +32,8 @@ development:
# Do not set this db to the same as development or production. # Do not set this db to the same as development or production.
test: &test test: &test
adapter: mysql2 adapter: mysql2
encoding: utf8 encoding: utf8mb4
collation: utf8_general_ci collation: utf8mb4_general_ci
reconnect: false reconnect: false
database: gitlabhq_test database: gitlabhq_test
pool: 5 pool: 5
......
...@@ -215,6 +215,7 @@ Settings.gitlab.default_projects_features['visibility_level'] = Settings.send( ...@@ -215,6 +215,7 @@ Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(
Settings.gitlab['domain_whitelist'] ||= [] Settings.gitlab['domain_whitelist'] ||= []
Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab google_code fogbugz git gitlab_project] Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab google_code fogbugz git gitlab_project]
Settings.gitlab['trusted_proxies'] ||= [] Settings.gitlab['trusted_proxies'] ||= []
Settings.gitlab['no_todos_messages'] ||= YAML.load_file(Rails.root.join('config', 'no_todos_messages.yml'))
# #
# CI # CI
......
...@@ -213,22 +213,9 @@ Devise.setup do |config| ...@@ -213,22 +213,9 @@ Devise.setup do |config|
end end
if Gitlab::LDAP::Config.enabled? if Gitlab::LDAP::Config.enabled?
Gitlab.config.ldap.servers.values.each do |server| Gitlab::LDAP::Config.providers.each do |provider|
if server['allow_username_or_email_login'] ldap_config = Gitlab::LDAP::Config.new(provider)
email_stripping_proc = ->(name) {name.gsub(/@.*\z/, '')} config.omniauth(provider, ldap_config.omniauth_options)
else
email_stripping_proc = ->(name) {name}
end
config.omniauth server['provider_name'],
host: server['host'],
base: server['base'],
uid: server['uid'],
port: server['port'],
method: server['method'],
bind_dn: server['bind_dn'],
password: server['password'],
name_proc: email_stripping_proc
end end
end end
......
# When the Todos list on the user's dashboard becomes empty, one of the messages below shows up randomly.
#
# If you come up with a fun one, please feel free to contribute it to GitLab!
# https://about.gitlab.com/contributing/
---
- Good job! Looks like you don't have any todos left.
- Coffee really tastes better without any todos left.
- Isn't an empty To Do list beautiful?
- Time for a rewarding coffee break
- Give yourself a pat on the back!
- High five!
- Hence forth you shall be known as 'Todo Destroyer'
\ No newline at end of file
...@@ -44,7 +44,7 @@ listen "127.0.0.1:8080", :tcp_nopush => true ...@@ -44,7 +44,7 @@ listen "127.0.0.1:8080", :tcp_nopush => true
# nuke workers after 30 seconds instead of 60 seconds (the default) # nuke workers after 30 seconds instead of 60 seconds (the default)
# #
# NOTICE: git push over http depends on this value. # NOTICE: git push over http depends on this value.
# If you want be able to push huge amount of data to git repository over http # If you want to be able to push huge amount of data to git repository over http
# you will have to increase this value too. # you will have to increase this value too.
# #
# Example of output if you try to push 1GB repo to GitLab over http. # Example of output if you try to push 1GB repo to GitLab over http.
...@@ -82,7 +82,7 @@ GC.respond_to?(:copy_on_write_friendly=) and ...@@ -82,7 +82,7 @@ GC.respond_to?(:copy_on_write_friendly=) and
check_client_connection false check_client_connection false
before_fork do |server, worker| before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true" # the following is highly recommended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection # as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect! ActiveRecord::Base.connection.disconnect!
......
...@@ -76,7 +76,7 @@ configuration to move each data location to a subdirectory: ...@@ -76,7 +76,7 @@ configuration to move each data location to a subdirectory:
user['home'] = '/gitlab-data/home' user['home'] = '/gitlab-data/home'
git_data_dir '/gitlab-data/git-data' git_data_dir '/gitlab-data/git-data'
gitlab_rails['shared_path'] = '/gitlab-data/shared' gitlab_rails['shared_path'] = '/gitlab-data/shared'
gitlab_rails['uploads_directory'] = "/gitlab-data/uploads" gitlab_rails['uploads_directory'] = '/gitlab-data/uploads'
gitlab_ci['builds_directory'] = '/gitlab-data/builds' gitlab_ci['builds_directory'] = '/gitlab-data/builds'
``` ```
......
...@@ -48,15 +48,15 @@ Redis. ...@@ -48,15 +48,15 @@ Redis.
redis['password'] = 'Redis Password' redis['password'] = 'Redis Password'
``` ```
1. Run `sudo gitlab-ctl reconfigure` to install and configure PostgreSQL. 1. Run `sudo touch /etc/gitlab/skip-auto-migrations` to prevent database migrations
from running on upgrade. Only the primary GitLab application server should
handle migrations.
1. Run `sudo gitlab-ctl reconfigure` to install and configure Redis.
> **Note**: This `reconfigure` step will result in some errors. > **Note**: This `reconfigure` step will result in some errors.
That's OK - don't be alarmed. That's OK - don't be alarmed.
1. Run `touch /etc/gitlab/skip-auto-migrations` to prevent database migrations
from running on upgrade. Only the primary GitLab application server should
handle migrations.
## Experimental Redis Sentinel support ## Experimental Redis Sentinel support
> [Introduced][ce-1877] in GitLab 8.11. > [Introduced][ce-1877] in GitLab 8.11.
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
contributing to documentation. contributing to documentation.
- [SQL Migration Style Guide](migration_style_guide.md) for creating safe SQL migrations - [SQL Migration Style Guide](migration_style_guide.md) for creating safe SQL migrations
- [Testing standards and style guidelines](testing.md) - [Testing standards and style guidelines](testing.md)
- [UX guide](ux_guide/README.md) for building GitLab with existing CSS styles and elements - [UX guide](ux_guide/index.md) for building GitLab with existing CSS styles and elements
- [Frontend guidelines](frontend.md) - [Frontend guidelines](frontend.md)
- [SQL guidelines](sql.md) for working with SQL queries - [SQL guidelines](sql.md) for working with SQL queries
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers - [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
......
...@@ -14,8 +14,8 @@ There are two ways to create a new project in GitLab. ...@@ -14,8 +14,8 @@ There are two ways to create a new project in GitLab.
1. Fill out the information: 1. Fill out the information:
1. "Project name" is the name of your project (you can't use spaces, but you 1. "Project name" is the name of your project (you can't use special characters,
can use hyphens or underscores). but you can use spaces, hyphens, underscores or even emojis).
1. The "Project description" is optional and will be shown in your project's 1. The "Project description" is optional and will be shown in your project's
dashboard so others can briefly understand what your project is about. dashboard so others can briefly understand what your project is about.
1. Select a [visibility level](../public_access/public_access.md). 1. Select a [visibility level](../public_access/public_access.md).
......
...@@ -44,7 +44,7 @@ This [resource](http://kb.kerio.com/product/kerio-connect/server-configuration/s ...@@ -44,7 +44,7 @@ This [resource](http://kb.kerio.com/product/kerio-connect/server-configuration/s
has all the information you need to add a certificate to the main trusted chain. has all the information you need to add a certificate to the main trusted chain.
This [answer](http://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu) This [answer](http://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)
at SuperUser also has relevant information. at Super User also has relevant information.
**Omnibus Trusted Chain** **Omnibus Trusted Chain**
......
...@@ -590,7 +590,7 @@ Quote break. ...@@ -590,7 +590,7 @@ Quote break.
You can also use raw HTML in your Markdown, and it'll mostly work pretty well. You can also use raw HTML in your Markdown, and it'll mostly work pretty well.
See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubydoc.info/gems/html-pipeline/HTML/Pipeline/SanitizationFilter#WHITELIST-constant) class for the list of allowed HTML tags and attributes. In addition to the default `SanitizationFilter` whitelist, GitLab allows `span` elements. See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubydoc.info/gems/html-pipeline/1.11.0/HTML/Pipeline/SanitizationFilter#WHITELIST-constant) class for the list of allowed HTML tags and attributes. In addition to the default `SanitizationFilter` whitelist, GitLab allows `span` elements.
```no-highlight ```no-highlight
<dl> <dl>
......
...@@ -48,7 +48,7 @@ module API ...@@ -48,7 +48,7 @@ module API
put ':id/access_requests/:user_id/approve' do put ':id/access_requests/:user_id/approve' do
source = find_source(source_type, params[:id]) source = find_source(source_type, params[:id])
member = ::Members::ApproveAccessRequestService.new(source, current_user, declared(params)).execute member = ::Members::ApproveAccessRequestService.new(source, current_user, declared_params).execute
status :created status :created
present member.user, with: Entities::Member, member: member present member.user, with: Entities::Member, member: member
......
...@@ -36,8 +36,7 @@ module API ...@@ -36,8 +36,7 @@ module API
optional :font, type: String, desc: 'Foreground color' optional :font, type: String, desc: 'Foreground color'
end end
post do post do
create_params = declared(params, include_missing: false).to_h message = BroadcastMessage.create(declared_params(include_missing: false))
message = BroadcastMessage.create(create_params)
if message.persisted? if message.persisted?
present message, with: Entities::BroadcastMessage present message, with: Entities::BroadcastMessage
...@@ -73,9 +72,8 @@ module API ...@@ -73,9 +72,8 @@ module API
end end
put ':id' do put ':id' do
message = find_message message = find_message
update_params = declared(params, include_missing: false).to_h
if message.update(update_params) if message.update(declared_params(include_missing: false))
present message, with: Entities::BroadcastMessage present message, with: Entities::BroadcastMessage
else else
render_validation_error!(message) render_validation_error!(message)
......
...@@ -53,7 +53,7 @@ module API ...@@ -53,7 +53,7 @@ module API
post ":id/repository/commits" do post ":id/repository/commits" do
authorize! :push_code, user_project authorize! :push_code, user_project
attrs = declared(params) attrs = declared_params
attrs[:source_branch] = attrs[:branch_name] attrs[:source_branch] = attrs[:branch_name]
attrs[:target_branch] = attrs[:branch_name] attrs[:target_branch] = attrs[:branch_name]
attrs[:actions].map! do |action| attrs[:actions].map! do |action|
......
...@@ -82,7 +82,7 @@ module API ...@@ -82,7 +82,7 @@ module API
end end
post ":id/#{path}/:key_id/enable" do post ":id/#{path}/:key_id/enable" do
key = ::Projects::EnableDeployKeyService.new(user_project, key = ::Projects::EnableDeployKeyService.new(user_project,
current_user, declared(params)).execute current_user, declared_params).execute
if key if key
present key, with: Entities::SSHKey present key, with: Entities::SSHKey
......
...@@ -32,8 +32,7 @@ module API ...@@ -32,8 +32,7 @@ module API
post ':id/environments' do post ':id/environments' do
authorize! :create_environment, user_project authorize! :create_environment, user_project
create_params = declared(params, include_parent_namespaces: false).to_h environment = user_project.environments.create(declared_params)
environment = user_project.environments.create(create_params)
if environment.persisted? if environment.persisted?
present environment, with: Entities::Environment present environment, with: Entities::Environment
...@@ -55,8 +54,8 @@ module API ...@@ -55,8 +54,8 @@ module API
authorize! :update_environment, user_project authorize! :update_environment, user_project
environment = user_project.environments.find(params[:environment_id]) environment = user_project.environments.find(params[:environment_id])
update_params = declared(params, include_missing: false).extract!(:name, :external_url).to_h update_params = declared_params(include_missing: false).extract!(:name, :external_url)
if environment.update(update_params) if environment.update(update_params)
present environment, with: Entities::Environment present environment, with: Entities::Environment
else else
......
...@@ -23,6 +23,11 @@ module API ...@@ -23,6 +23,11 @@ module API
warden.try(:authenticate) if %w[GET HEAD].include?(env['REQUEST_METHOD']) warden.try(:authenticate) if %w[GET HEAD].include?(env['REQUEST_METHOD'])
end end
def declared_params(options = {})
options = { include_parent_namespaces: false }.merge(options)
declared(params, options).to_h.symbolize_keys
end
def find_user_by_private_token def find_user_by_private_token
token = private_token token = private_token
return nil unless token.present? return nil unless token.present?
......
...@@ -30,10 +30,7 @@ module API ...@@ -30,10 +30,7 @@ module API
conflict!('Label already exists') if label conflict!('Label already exists') if label
priority = params.delete(:priority) priority = params.delete(:priority)
label_params = declared(params, label = user_project.labels.create(declared_params(include_missing: false))
include_parent_namespaces: false,
include_missing: false).to_h
label = user_project.labels.create(label_params)
if label.valid? if label.valid?
label.prioritize!(user_project, priority) if priority label.prioritize!(user_project, priority) if priority
...@@ -77,11 +74,9 @@ module API ...@@ -77,11 +74,9 @@ module API
update_priority = params.key?(:priority) update_priority = params.key?(:priority)
priority = params.delete(:priority) priority = params.delete(:priority)
label_params = declared(params, label_params = declared_params(include_missing: false)
include_parent_namespaces: false,
include_missing: false).to_h
# Rename new name to the actual label attribute name # Rename new name to the actual label attribute name
label_params[:name] = label_params.delete('new_name') if label_params.key?('new_name') label_params[:name] = label_params.delete(:new_name) if label_params.key?(:new_name)
render_validation_error!(label) unless label.update(label_params) render_validation_error!(label) unless label.update(label_params)
......
...@@ -120,7 +120,7 @@ module API ...@@ -120,7 +120,7 @@ module API
if member.nil? if member.nil?
{ message: "Access revoked", id: params[:user_id].to_i } { message: "Access revoked", id: params[:user_id].to_i }
else else
::Members::DestroyService.new(source, current_user, declared(params)).execute ::Members::DestroyService.new(source, current_user, declared_params).execute
present member.user, with: Entities::Member, member: member present member.user, with: Entities::Member, member: member
end end
......
...@@ -62,9 +62,8 @@ module API ...@@ -62,9 +62,8 @@ module API
end end
post ":id/milestones" do post ":id/milestones" do
authorize! :admin_milestone, user_project authorize! :admin_milestone, user_project
milestone_params = declared(params, include_parent_namespaces: false)
milestone = ::Milestones::CreateService.new(user_project, current_user, milestone_params).execute milestone = ::Milestones::CreateService.new(user_project, current_user, declared_params).execute
if milestone.valid? if milestone.valid?
present milestone, with: Entities::Milestone present milestone, with: Entities::Milestone
...@@ -86,9 +85,9 @@ module API ...@@ -86,9 +85,9 @@ module API
end end
put ":id/milestones/:milestone_id" do put ":id/milestones/:milestone_id" do
authorize! :admin_milestone, user_project authorize! :admin_milestone, user_project
milestone_params = declared(params, include_parent_namespaces: false, include_missing: false) milestone = user_project.milestones.find(params.delete(:milestone_id))
milestone = user_project.milestones.find(milestone_params.delete(:milestone_id)) milestone_params = declared_params(include_missing: false)
milestone = ::Milestones::UpdateService.new(user_project, current_user, milestone_params).execute(milestone) milestone = ::Milestones::UpdateService.new(user_project, current_user, milestone_params).execute(milestone)
if milestone.valid? if milestone.valid?
......
...@@ -33,10 +33,9 @@ module API ...@@ -33,10 +33,9 @@ module API
begin begin
notification_setting.transaction do notification_setting.transaction do
new_notification_email = params.delete(:notification_email) 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 current_user.update(notification_email: new_notification_email) if new_notification_email
notification_setting.update(declared_params) notification_setting.update(declared_params(include_missing: false))
end end
rescue ArgumentError => e # catch level enum error rescue ArgumentError => e # catch level enum error
render_api_error! e.to_s, 400 render_api_error! e.to_s, 400
...@@ -81,9 +80,7 @@ module API ...@@ -81,9 +80,7 @@ module API
notification_setting = current_user.notification_settings_for(source) notification_setting = current_user.notification_settings_for(source)
begin begin
declared_params = declared(params, include_missing: false).to_h notification_setting.update(declared_params(include_missing: false))
notification_setting.update(declared_params)
rescue ArgumentError => e # catch level enum error rescue ArgumentError => e # catch level enum error
render_api_error! e.to_s, 400 render_api_error! e.to_s, 400
end end
......
...@@ -51,8 +51,7 @@ module API ...@@ -51,8 +51,7 @@ module API
use :project_hook_properties use :project_hook_properties
end end
post ":id/hooks" do post ":id/hooks" do
new_hook_params = declared(params, include_missing: false, include_parent_namespaces: false).to_h hook = user_project.hooks.new(declared_params(include_missing: false))
hook = user_project.hooks.new(new_hook_params)
if hook.save if hook.save
present hook, with: Entities::ProjectHook present hook, with: Entities::ProjectHook
...@@ -71,12 +70,9 @@ module API ...@@ -71,12 +70,9 @@ module API
use :project_hook_properties use :project_hook_properties
end end
put ":id/hooks/:hook_id" do put ":id/hooks/:hook_id" do
hook = user_project.hooks.find(params[:hook_id]) hook = user_project.hooks.find(params.delete(:hook_id))
new_params = declared(params, include_missing: false, include_parent_namespaces: false).to_h
new_params.delete('hook_id')
if hook.update_attributes(new_params) if hook.update_attributes(declared_params(include_missing: false))
present hook, with: Entities::ProjectHook present hook, with: Entities::ProjectHook
else else
error!("Invalid url given", 422) if hook.errors[:url].present? error!("Invalid url given", 422) if hook.errors[:url].present?
......
...@@ -57,9 +57,7 @@ module API ...@@ -57,9 +57,7 @@ module API
runner = get_runner(params.delete(:id)) runner = get_runner(params.delete(:id))
authenticate_update_runner!(runner) authenticate_update_runner!(runner)
runner_params = declared(params, include_missing: false) if runner.update(declared_params(include_missing: false))
if runner.update(runner_params)
present runner, with: Entities::RunnerDetails, current_user: current_user present runner, with: Entities::RunnerDetails, current_user: current_user
else else
render_validation_error!(runner) render_validation_error!(runner)
......
...@@ -9,23 +9,20 @@ module API ...@@ -9,23 +9,20 @@ module API
'labels' => proc { |id| find_project_label(id) }, 'labels' => proc { |id| find_project_label(id) },
} }
params do
requires :id, type: String, desc: 'The ID of a project'
requires :subscribable_id, type: String, desc: 'The ID of a resource'
end
resource :projects do resource :projects do
subscribable_types.each do |type, finder| subscribable_types.each do |type, finder|
type_singularized = type.singularize type_singularized = type.singularize
type_id_str = :"#{type_singularized}_id"
entity_class = Entities.const_get(type_singularized.camelcase) entity_class = Entities.const_get(type_singularized.camelcase)
# Subscribe to a resource desc 'Subscribe to a resource' do
# success entity_class
# Parameters: end
# id (required) - The ID of a project post ":id/#{type}/:subscribable_id/subscription" do
# subscribable_id (required) - The ID of a resource resource = instance_exec(params[:subscribable_id], &finder)
# Example Request:
# POST /projects/:id/labels/:subscribable_id/subscription
# POST /projects/:id/issues/:subscribable_id/subscription
# POST /projects/:id/merge_requests/:subscribable_id/subscription
post ":id/#{type}/:#{type_id_str}/subscription" do
resource = instance_exec(params[type_id_str], &finder)
if resource.subscribed?(current_user) if resource.subscribed?(current_user)
not_modified! not_modified!
...@@ -35,17 +32,11 @@ module API ...@@ -35,17 +32,11 @@ module API
end end
end end
# Unsubscribe from a resource desc 'Unsubscribe from a resource' do
# success entity_class
# Parameters: end
# id (required) - The ID of a project delete ":id/#{type}/:subscribable_id/subscription" do
# subscribable_id (required) - The ID of a resource resource = instance_exec(params[:subscribable_id], &finder)
# Example Request:
# DELETE /projects/:id/labels/:subscribable_id/subscription
# DELETE /projects/:id/issues/:subscribable_id/subscription
# DELETE /projects/:id/merge_requests/:subscribable_id/subscription
delete ":id/#{type}/:#{type_id_str}/subscription" do
resource = instance_exec(params[type_id_str], &finder)
if !resource.subscribed?(current_user) if !resource.subscribed?(current_user)
not_modified! not_modified!
......
...@@ -27,7 +27,7 @@ module API ...@@ -27,7 +27,7 @@ module API
optional :enable_ssl_verification, type: Boolean, desc: "Do SSL verification when triggering the hook" optional :enable_ssl_verification, type: Boolean, desc: "Do SSL verification when triggering the hook"
end end
post do post do
hook = SystemHook.new declared(params, include_missing: false).to_h hook = SystemHook.new(declared_params(include_missing: false))
if hook.save if hook.save
present hook, with: Entities::Hook present hook, with: Entities::Hook
......
...@@ -40,10 +40,9 @@ module API ...@@ -40,10 +40,9 @@ module API
end end
post ':id/repository/tags' do post ':id/repository/tags' do
authorize_push_project authorize_push_project
create_params = declared(params)
result = CreateTagService.new(user_project, current_user). result = CreateTagService.new(user_project, current_user).
execute(create_params[:tag_name], create_params[:ref], create_params[:message], create_params[:release_description]) execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
if result[:status] == :success if result[:status] == :success
present result[:tag], present result[:tag],
......
...@@ -335,7 +335,7 @@ module API ...@@ -335,7 +335,7 @@ module API
requires :id, type: String, desc: 'The user ID' requires :id, type: String, desc: 'The user ID'
end end
get ':id/events' do get ':id/events' do
user = User.find_by(id: declared(params).id) user = User.find_by(id: params[:id])
not_found!('User') unless user not_found!('User') unless user
events = user.events. events = user.events.
......
...@@ -2,7 +2,7 @@ module Ci ...@@ -2,7 +2,7 @@ module Ci
class GitlabCiYamlProcessor class GitlabCiYamlProcessor
class ValidationError < StandardError; end class ValidationError < StandardError; end
include Gitlab::Ci::Config::Node::LegacyValidationHelpers include Gitlab::Ci::Config::Entry::LegacyValidationHelpers
attr_reader :path, :cache, :stages, :jobs attr_reader :path, :cache, :stages, :jobs
......
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
def initialize(config) def initialize(config)
@config = Loader.new(config).load! @config = Loader.new(config).load!
@global = Node::Global.new(@config) @global = Entry::Global.new(@config)
@global.compose! @global.compose!
end end
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a configuration of job artifacts. # Entry that represents a configuration of job artifacts.
# #
class Artifacts < Entry class Artifacts < Node
include Validatable include Validatable
include Attributable include Attributable
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
module Attributable module Attributable
extend ActiveSupport::Concern extend ActiveSupport::Concern
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a boolean value. # Entry that represents a boolean value.
# #
class Boolean < Entry class Boolean < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a cache configuration # Entry that represents a cache configuration
# #
class Cache < Entry class Cache < Node
include Configurable include Configurable
ALLOWED_KEYS = %i[key untracked paths] ALLOWED_KEYS = %i[key untracked paths]
...@@ -14,13 +14,13 @@ module Gitlab ...@@ -14,13 +14,13 @@ module Gitlab
validates :config, allowed_keys: ALLOWED_KEYS validates :config, allowed_keys: ALLOWED_KEYS
end end
node :key, Node::Key, entry :key, Entry::Key,
description: 'Cache key used to define a cache affinity.' description: 'Cache key used to define a cache affinity.'
node :untracked, Node::Boolean, entry :untracked, Entry::Boolean,
description: 'Cache all untracked files.' description: 'Cache all untracked files.'
node :paths, Node::Paths, entry :paths, Entry::Paths,
description: 'Specify which paths should be cached across builds.' description: 'Specify which paths should be cached across builds.'
end end
end end
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a job script. # Entry that represents a job script.
# #
class Commands < Entry class Commands < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# This mixin is responsible for adding DSL, which purpose is to # This mixin is responsible for adding DSL, which purpose is to
# simplifly process of adding child nodes. # simplifly process of adding child nodes.
...@@ -48,8 +48,8 @@ module Gitlab ...@@ -48,8 +48,8 @@ module Gitlab
private # rubocop:disable Lint/UselessAccessModifier private # rubocop:disable Lint/UselessAccessModifier
def node(key, node, metadata) def entry(key, entry, metadata)
factory = Node::Factory.new(node) factory = Entry::Factory.new(entry)
.with(description: metadata[:description]) .with(description: metadata[:description])
(@nodes ||= {}).merge!(key.to_sym => factory) (@nodes ||= {}).merge!(key.to_sym => factory)
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents an environment. # Entry that represents an environment.
# #
class Environment < Entry class Environment < Node
include Validatable include Validatable
ALLOWED_KEYS = %i[name url action on_stop] ALLOWED_KEYS = %i[name url action on_stop]
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Factory class responsible for fabricating node entry objects. # Factory class responsible for fabricating entry objects.
# #
class Factory class Factory
class InvalidFactory < StandardError; end class InvalidFactory < StandardError; end
def initialize(node) def initialize(entry)
@node = node @entry = entry
@metadata = {} @metadata = {}
@attributes = {} @attributes = {}
end end
...@@ -37,11 +37,11 @@ module Gitlab ...@@ -37,11 +37,11 @@ module Gitlab
# See issue #18775. # See issue #18775.
# #
if @value.nil? if @value.nil?
Node::Unspecified.new( Entry::Unspecified.new(
fabricate_unspecified fabricate_unspecified
) )
else else
fabricate(@node, @value) fabricate(@entry, @value)
end end
end end
...@@ -49,21 +49,21 @@ module Gitlab ...@@ -49,21 +49,21 @@ module Gitlab
def fabricate_unspecified def fabricate_unspecified
## ##
# If node has a default value we fabricate concrete node # If entry has a default value we fabricate concrete node
# with default value. # with default value.
# #
if @node.default.nil? if @entry.default.nil?
fabricate(Node::Undefined) fabricate(Entry::Undefined)
else else
fabricate(@node, @node.default) fabricate(@entry, @entry.default)
end end
end end
def fabricate(node, value = nil) def fabricate(entry, value = nil)
node.new(value, @metadata).tap do |entry| entry.new(value, @metadata).tap do |node|
entry.key = @attributes[:key] node.key = @attributes[:key]
entry.parent = @attributes[:parent] node.parent = @attributes[:parent]
entry.description = @attributes[:description] node.description = @attributes[:description]
end end
end end
end end
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# This class represents a global entry - root node for entire # This class represents a global entry - root Entry for entire
# GitLab CI Configuration file. # GitLab CI Configuration file.
# #
class Global < Entry class Global < Node
include Configurable include Configurable
node :before_script, Node::Script, entry :before_script, Entry::Script,
description: 'Script that will be executed before each job.' description: 'Script that will be executed before each job.'
node :image, Node::Image, entry :image, Entry::Image,
description: 'Docker image that will be used to execute jobs.' description: 'Docker image that will be used to execute jobs.'
node :services, Node::Services, entry :services, Entry::Services,
description: 'Docker images that will be linked to the container.' description: 'Docker images that will be linked to the container.'
node :after_script, Node::Script, entry :after_script, Entry::Script,
description: 'Script that will be executed after each job.' description: 'Script that will be executed after each job.'
node :variables, Node::Variables, entry :variables, Entry::Variables,
description: 'Environment variables that will be used.' description: 'Environment variables that will be used.'
node :stages, Node::Stages, entry :stages, Entry::Stages,
description: 'Configuration of stages for this pipeline.' description: 'Configuration of stages for this pipeline.'
node :types, Node::Stages, entry :types, Entry::Stages,
description: 'Deprecated: stages for this pipeline.' description: 'Deprecated: stages for this pipeline.'
node :cache, Node::Cache, entry :cache, Entry::Cache,
description: 'Configure caching between build jobs.' description: 'Configure caching between build jobs.'
helpers :before_script, :image, :services, :after_script, helpers :before_script, :image, :services, :after_script,
...@@ -46,7 +46,7 @@ module Gitlab ...@@ -46,7 +46,7 @@ module Gitlab
private private
def compose_jobs! def compose_jobs!
factory = Node::Factory.new(Node::Jobs) factory = Entry::Factory.new(Entry::Jobs)
.value(@config.except(*self.class.nodes.keys)) .value(@config.except(*self.class.nodes.keys))
.with(key: :jobs, parent: self, .with(key: :jobs, parent: self,
description: 'Jobs definition for this pipeline') description: 'Jobs definition for this pipeline')
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a hidden CI/CD job. # Entry that represents a hidden CI/CD key.
# #
class Hidden < Entry class Hidden < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a Docker image. # Entry that represents a Docker image.
# #
class Image < Entry class Image < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a concrete CI/CD job. # Entry that represents a concrete CI/CD job.
# #
class Job < Entry class Job < Node
include Configurable include Configurable
include Attributable include Attributable
...@@ -34,43 +34,43 @@ module Gitlab ...@@ -34,43 +34,43 @@ module Gitlab
end end
end end
node :before_script, Node::Script, entry :before_script, Entry::Script,
description: 'Global before script overridden in this job.' description: 'Global before script overridden in this job.'
node :script, Node::Commands, entry :script, Entry::Commands,
description: 'Commands that will be executed in this job.' description: 'Commands that will be executed in this job.'
node :stage, Node::Stage, entry :stage, Entry::Stage,
description: 'Pipeline stage this job will be executed into.' description: 'Pipeline stage this job will be executed into.'
node :type, Node::Stage, entry :type, Entry::Stage,
description: 'Deprecated: stage this job will be executed into.' description: 'Deprecated: stage this job will be executed into.'
node :after_script, Node::Script, entry :after_script, Entry::Script,
description: 'Commands that will be executed when finishing job.' description: 'Commands that will be executed when finishing job.'
node :cache, Node::Cache, entry :cache, Entry::Cache,
description: 'Cache definition for this job.' description: 'Cache definition for this job.'
node :image, Node::Image, entry :image, Entry::Image,
description: 'Image that will be used to execute this job.' description: 'Image that will be used to execute this job.'
node :services, Node::Services, entry :services, Entry::Services,
description: 'Services that will be used to execute this job.' description: 'Services that will be used to execute this job.'
node :only, Node::Trigger, entry :only, Entry::Trigger,
description: 'Refs policy this job will be executed for.' description: 'Refs policy this job will be executed for.'
node :except, Node::Trigger, entry :except, Entry::Trigger,
description: 'Refs policy this job will be executed for.' description: 'Refs policy this job will be executed for.'
node :variables, Node::Variables, entry :variables, Entry::Variables,
description: 'Environment variables available for this job.' description: 'Environment variables available for this job.'
node :artifacts, Node::Artifacts, entry :artifacts, Entry::Artifacts,
description: 'Artifacts configuration for this job.' description: 'Artifacts configuration for this job.'
node :environment, Node::Environment, entry :environment, Entry::Environment,
description: 'Environment configuration for this job.' description: 'Environment configuration for this job.'
helpers :before_script, :script, :stage, :type, :after_script, helpers :before_script, :script, :stage, :type, :after_script,
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a set of jobs. # Entry that represents a set of jobs.
# #
class Jobs < Entry class Jobs < Node
include Validatable include Validatable
validations do validations do
...@@ -29,9 +29,9 @@ module Gitlab ...@@ -29,9 +29,9 @@ module Gitlab
def compose!(deps = nil) def compose!(deps = nil)
super do super do
@config.each do |name, config| @config.each do |name, config|
node = hidden?(name) ? Node::Hidden : Node::Job node = hidden?(name) ? Entry::Hidden : Entry::Job
factory = Node::Factory.new(node) factory = Entry::Factory.new(node)
.value(config || {}) .value(config || {})
.metadata(name: name) .metadata(name: name)
.with(key: name, parent: self, .with(key: name, parent: self,
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a key. # Entry that represents a key.
# #
class Key < Entry class Key < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
module LegacyValidationHelpers module LegacyValidationHelpers
private private
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Base abstract class for each configuration entry node. # Base abstract class for each configuration entry node.
# #
class Entry class Node
class InvalidError < StandardError; end class InvalidError < StandardError; end
attr_reader :config, :metadata attr_reader :config, :metadata
...@@ -21,7 +21,7 @@ module Gitlab ...@@ -21,7 +21,7 @@ module Gitlab
end end
def [](key) def [](key)
@entries[key] || Node::Undefined.new @entries[key] || Entry::Undefined.new
end end
def compose!(deps = nil) def compose!(deps = nil)
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents an array of paths. # Entry that represents an array of paths.
# #
class Paths < Entry class Paths < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a script. # Entry that represents a script.
# #
class Script < Entry class Script < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a configuration of Docker services. # Entry that represents a configuration of Docker services.
# #
class Services < Entry class Services < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a stage for a job. # Entry that represents a stage for a job.
# #
class Stage < Entry class Stage < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a configuration for pipeline stages. # Entry that represents a configuration for pipeline stages.
# #
class Stages < Entry class Stages < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents a trigger policy for the job. # Entry that represents a trigger policy for the job.
# #
class Trigger < Entry class Trigger < Node
include Validatable include Validatable
validations do validations do
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# This class represents an undefined node. # This class represents an undefined entry.
# #
# Implements the Null Object pattern. class Undefined < Node
#
class Undefined < Entry
def initialize(*) def initialize(*)
super(nil) super(nil)
end end
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# This class represents an unspecified entry node. # This class represents an unspecified entry.
# #
# It decorates original entry adding method that indicates it is # It decorates original entry adding method that indicates it is
# unspecified. # unspecified.
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
module Validatable module Validatable
extend ActiveSupport::Concern extend ActiveSupport::Concern
class_methods do class_methods do
def validator def validator
@validator ||= Class.new(Node::Validator).tap do |validator| @validator ||= Class.new(Entry::Validator).tap do |validator|
if defined?(@validations) if defined?(@validations)
@validations.each { |rules| validator.class_eval(&rules) } @validations.each { |rules| validator.class_eval(&rules) }
end end
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
class Validator < SimpleDelegator class Validator < SimpleDelegator
include ActiveModel::Validations include ActiveModel::Validations
include Node::Validators include Entry::Validators
def initialize(node) def initialize(entry)
super(node) super(entry)
@node = node @entry = entry
end end
def messages def messages
...@@ -30,7 +30,7 @@ module Gitlab ...@@ -30,7 +30,7 @@ module Gitlab
def key_name def key_name
if key.blank? if key.blank?
@node.class.name.demodulize.underscore.humanize @entry.class.name.demodulize.underscore.humanize
else else
key key
end end
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
module Validators module Validators
class AllowedKeysValidator < ActiveModel::EachValidator class AllowedKeysValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
......
module Gitlab module Gitlab
module Ci module Ci
class Config class Config
module Node module Entry
## ##
# Entry that represents environment variables. # Entry that represents environment variables.
# #
class Variables < Entry class Variables < Node
include Validatable include Validatable
validations do validations do
......
...@@ -24,7 +24,7 @@ module Gitlab ...@@ -24,7 +24,7 @@ module Gitlab
end end
def sidekiq_throttling_enabled? def sidekiq_throttling_enabled?
current_application_settings.sidekiq_throttling_enabled current_application_settings.sidekiq_throttling_enabled?
end end
def fake_application_settings def fake_application_settings
......
...@@ -89,9 +89,7 @@ module Gitlab ...@@ -89,9 +89,7 @@ module Gitlab
end end
def user_filter(filter = nil) def user_filter(filter = nil)
if config.user_filter.present? user_filter = config.constructed_user_filter if config.user_filter.present?
user_filter = Net::LDAP::Filter.construct(config.user_filter)
end
if user_filter && filter if user_filter && filter
Net::LDAP::Filter.join(filter, user_filter) Net::LDAP::Filter.join(filter, user_filter)
......
...@@ -54,11 +54,9 @@ module Gitlab ...@@ -54,11 +54,9 @@ module Gitlab
# Apply LDAP user filter if present # Apply LDAP user filter if present
if config.user_filter.present? if config.user_filter.present?
filter = Net::LDAP::Filter.join( filter = Net::LDAP::Filter.join(filter, config.constructed_user_filter)
filter,
Net::LDAP::Filter.construct(config.user_filter)
)
end end
filter filter
end end
......
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
end end
def self.providers def self.providers
servers.map {|server| server['provider_name'] } servers.map { |server| server['provider_name'] }
end end
def self.valid_provider?(provider) def self.valid_provider?(provider)
...@@ -38,13 +38,31 @@ module Gitlab ...@@ -38,13 +38,31 @@ module Gitlab
end end
def adapter_options def adapter_options
{ opts = base_options.merge(
host: options['host'], encryption: encryption,
port: options['port'], )
encryption: encryption
}.tap do |options| opts.merge!(auth_options) if has_auth?
options.merge!(auth_options) if has_auth?
opts
end
def omniauth_options
opts = base_options.merge(
base: base,
method: options['method'],
filter: omniauth_user_filter,
name_proc: name_proc
)
if has_auth?
opts.merge!(
bind_dn: options['bind_dn'],
password: options['password']
)
end end
opts
end end
def base def base
...@@ -68,6 +86,10 @@ module Gitlab ...@@ -68,6 +86,10 @@ module Gitlab
options['user_filter'] options['user_filter']
end end
def constructed_user_filter
@constructed_user_filter ||= Net::LDAP::Filter.construct(user_filter)
end
def group_base def group_base
options['group_base'] options['group_base']
end end
...@@ -96,8 +118,27 @@ module Gitlab ...@@ -96,8 +118,27 @@ module Gitlab
options['password'] || options['bind_dn'] options['password'] || options['bind_dn']
end end
def allow_username_or_email_login
options['allow_username_or_email_login']
end
def name_proc
if allow_username_or_email_login
Proc.new { |name| name.gsub(/@.*\z/, '') }
else
Proc.new { |name| name }
end
end
protected protected
def base_options
{
host: options['host'],
port: options['port']
}
end
def base_config def base_config
Gitlab.config.ldap Gitlab.config.ldap
end end
...@@ -126,6 +167,16 @@ module Gitlab ...@@ -126,6 +167,16 @@ module Gitlab
} }
} }
end end
def omniauth_user_filter
uid_filter = Net::LDAP::Filter.eq(uid, '%{username}')
if user_filter.present?
Net::LDAP::Filter.join(uid_filter, constructed_user_filter).to_s
else
uid_filter.to_s
end
end
end end
end end
end end
...@@ -26,12 +26,12 @@ module Gitlab ...@@ -26,12 +26,12 @@ module Gitlab
end end
def project_name_regex def project_name_regex
@project_name_regex ||= /\A[\p{Alnum}_][\p{Alnum}\p{Pd}_\. ]*\z/.freeze @project_name_regex ||= /\A[\p{Alnum}\u{00A9}-\u{1f9c0}_][\p{Alnum}\p{Pd}\u{00A9}-\u{1f9c0}_\. ]*\z/.freeze
end end
def project_name_regex_message def project_name_regex_message
"can contain only letters, digits, '_', '.', dash and space. " \ "can contain only letters, digits, emojis, '_', '.', dash, space. " \
"It must start with letter, digit or '_'." "It must start with letter, digit, emoji or '_'."
end end
def project_path_regex def project_path_regex
......
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