summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2016-08-16 17:49:53 -0500
committerDouwe Maan <douwe@selenight.nl>2016-08-16 17:49:53 -0500
commite07c27fee427195d8d89f6278d0fc12dfeec3588 (patch)
treec4676e5e953aecef8bf2bb715619027cd556c9cc /lib
parent029b7d2e9266246feff2f165a10b16be1d7fe88e (diff)
parent415159c28da1aec00bb383d46aad67a9de75faae (diff)
downloadgitlab-ce-e07c27fee427195d8d89f6278d0fc12dfeec3588.tar.gz
Merge branch 'master' into 4273-slash-commands
# Conflicts: # app/services/issues/create_service.rb
Diffstat (limited to 'lib')
-rw-r--r--lib/api/branches.rb29
-rw-r--r--lib/api/entities.rb12
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/api/project_hooks.rb2
-rw-r--r--lib/api/templates.rb26
-rw-r--r--lib/api/todos.rb8
-rw-r--r--lib/banzai/filter/sanitization_filter.rb4
-rw-r--r--lib/gitlab/akismet_helper.rb47
-rw-r--r--lib/gitlab/badge/base.rb21
-rw-r--r--lib/gitlab/badge/build.rb30
-rw-r--r--lib/gitlab/badge/build/metadata.rb22
-rw-r--r--lib/gitlab/badge/build/status.rb37
-rw-r--r--lib/gitlab/badge/build/template.rb32
-rw-r--r--lib/gitlab/badge/coverage/metadata.rb30
-rw-r--r--lib/gitlab/badge/coverage/report.rb56
-rw-r--r--lib/gitlab/badge/coverage/template.rb52
-rw-r--r--lib/gitlab/badge/metadata.rb36
-rw-r--r--lib/gitlab/badge/template.rb49
-rw-r--r--lib/gitlab/checks/change_access.rb2
-rw-r--r--lib/gitlab/data_builder/build.rb (renamed from lib/gitlab/build_data_builder.rb)6
-rw-r--r--lib/gitlab/data_builder/note.rb (renamed from lib/gitlab/note_data_builder.rb)6
-rw-r--r--lib/gitlab/data_builder/pipeline.rb62
-rw-r--r--lib/gitlab/data_builder/push.rb (renamed from lib/gitlab/push_data_builder.rb)6
-rw-r--r--lib/gitlab/import_export/json_hash_builder.rb9
-rw-r--r--lib/gitlab/template/base_template.rb71
-rw-r--r--lib/gitlab/template/finders/base_template_finder.rb35
-rw-r--r--lib/gitlab/template/finders/global_template_finder.rb38
-rw-r--r--lib/gitlab/template/finders/repo_template_finder.rb59
-rw-r--r--lib/gitlab/template/gitignore_template.rb (renamed from lib/gitlab/template/gitignore.rb)6
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb (renamed from lib/gitlab/template/gitlab_ci_yml.rb)6
-rw-r--r--lib/gitlab/template/issue_template.rb19
-rw-r--r--lib/gitlab/template/merge_request_template.rb19
-rw-r--r--lib/gitlab/user_access.rb4
33 files changed, 650 insertions, 193 deletions
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index a77afe634f6..b615703df93 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -61,22 +61,27 @@ module API
name: @branch.name
}
- unless developers_can_merge.nil?
- protected_branch_params.merge!({
- merge_access_level_attributes: {
- access_level: developers_can_merge ? Gitlab::Access::DEVELOPER : Gitlab::Access::MASTER
- }
- })
+ # If `developers_can_merge` is switched off, _all_ `DEVELOPER`
+ # merge_access_levels need to be deleted.
+ if developers_can_merge == false
+ protected_branch.merge_access_levels.where(access_level: Gitlab::Access::DEVELOPER).destroy_all
end
- unless developers_can_push.nil?
- protected_branch_params.merge!({
- push_access_level_attributes: {
- access_level: developers_can_push ? Gitlab::Access::DEVELOPER : Gitlab::Access::MASTER
- }
- })
+ # If `developers_can_push` is switched off, _all_ `DEVELOPER`
+ # push_access_levels need to be deleted.
+ if developers_can_push == false
+ protected_branch.push_access_levels.where(access_level: Gitlab::Access::DEVELOPER).destroy_all
end
+ protected_branch_params.merge!(
+ merge_access_levels_attributes: [{
+ access_level: developers_can_merge ? Gitlab::Access::DEVELOPER : Gitlab::Access::MASTER
+ }],
+ push_access_levels_attributes: [{
+ access_level: developers_can_push ? Gitlab::Access::DEVELOPER : Gitlab::Access::MASTER
+ }]
+ )
+
if protected_branch
service = ProtectedBranches::UpdateService.new(user_project, current_user, protected_branch_params)
service.execute(protected_branch)
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index ae74d14a4bb..055716ab1e3 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -48,7 +48,8 @@ module API
class ProjectHook < Hook
expose :project_id, :push_events
- expose :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events
+ expose :issues_events, :merge_requests_events, :tag_push_events
+ expose :note_events, :build_events, :pipeline_events
expose :enable_ssl_verification
end
@@ -129,12 +130,14 @@ module API
expose :developers_can_push do |repo_branch, options|
project = options[:project]
- project.protected_branches.matching(repo_branch.name).any? { |protected_branch| protected_branch.push_access_level.access_level == Gitlab::Access::DEVELOPER }
+ access_levels = project.protected_branches.matching(repo_branch.name).map(&:push_access_levels).flatten
+ access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER }
end
expose :developers_can_merge do |repo_branch, options|
project = options[:project]
- project.protected_branches.matching(repo_branch.name).any? { |protected_branch| protected_branch.merge_access_level.access_level == Gitlab::Access::DEVELOPER }
+ access_levels = project.protected_branches.matching(repo_branch.name).map(&:merge_access_levels).flatten
+ access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER }
end
end
@@ -344,7 +347,8 @@ module API
class ProjectService < Grape::Entity
expose :id, :title, :created_at, :updated_at, :active
- expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events
+ expose :push_events, :issues_events, :merge_requests_events
+ expose :tag_push_events, :note_events, :build_events, :pipeline_events
# Expose serialized properties
expose :properties do |service, options|
field_names = service.fields.
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index c4d3134da6c..077258faee1 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -3,8 +3,6 @@ module API
class Issues < Grape::API
before { authenticate! }
- helpers ::Gitlab::AkismetHelper
-
helpers do
def filter_issues_state(issues, state)
case state
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 6bb70bc8bc3..3f63cd678e8 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -45,6 +45,7 @@ module API
:tag_push_events,
:note_events,
:build_events,
+ :pipeline_events,
:enable_ssl_verification
]
@hook = user_project.hooks.new(attrs)
@@ -78,6 +79,7 @@ module API
:tag_push_events,
:note_events,
:build_events,
+ :pipeline_events,
:enable_ssl_verification
]
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index 18408797756..b9e718147e1 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -1,21 +1,28 @@
module API
class Templates < Grape::API
- TEMPLATE_TYPES = {
- gitignores: Gitlab::Template::Gitignore,
- gitlab_ci_ymls: Gitlab::Template::GitlabCiYml
+ GLOBAL_TEMPLATE_TYPES = {
+ gitignores: Gitlab::Template::GitignoreTemplate,
+ gitlab_ci_ymls: Gitlab::Template::GitlabCiYmlTemplate
}.freeze
- TEMPLATE_TYPES.each do |template, klass|
+ helpers do
+ def render_response(template_type, template)
+ not_found!(template_type.to_s.singularize) unless template
+ present template, with: Entities::Template
+ end
+ end
+
+ GLOBAL_TEMPLATE_TYPES.each do |template_type, klass|
# Get the list of the available template
#
# Example Request:
# GET /gitignores
# GET /gitlab_ci_ymls
- get template.to_s do
+ get template_type.to_s do
present klass.all, with: Entities::TemplatesList
end
- # Get the text for a specific template
+ # Get the text for a specific template present in local filesystem
#
# Parameters:
# name (required) - The name of a template
@@ -23,13 +30,10 @@ module API
# Example Request:
# GET /gitignores/Elixir
# GET /gitlab_ci_ymls/Ruby
- get "#{template}/:name" do
+ get "#{template_type}/:name" do
required_attributes! [:name]
-
new_template = klass.find(params[:name])
- not_found!(template.to_s.singularize) unless new_template
-
- present new_template, with: Entities::Template
+ render_response(template_type, new_template)
end
end
end
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index 26c24c3baff..19df13d8aac 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -61,9 +61,9 @@ module API
#
delete ':id' do
todo = current_user.todos.find(params[:id])
- todo.done
+ TodoService.new.mark_todos_as_done([todo], current_user)
- present todo, with: Entities::Todo, current_user: current_user
+ present todo.reload, with: Entities::Todo, current_user: current_user
end
# Mark all todos as done
@@ -73,9 +73,7 @@ module API
#
delete do
todos = find_todos
- todos.each(&:done)
-
- todos.length
+ TodoService.new.mark_todos_as_done(todos, current_user)
end
end
end
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index ca80aac5a08..6e13282d5f4 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -7,7 +7,7 @@ module Banzai
UNSAFE_PROTOCOLS = %w(data javascript vbscript).freeze
def whitelist
- whitelist = super
+ whitelist = super.dup
customize_whitelist(whitelist)
@@ -42,6 +42,8 @@ module Banzai
# Allow any protocol in `a` elements...
whitelist[:protocols].delete('a')
+ whitelist[:transformers] = whitelist[:transformers].dup
+
# ...but then remove links with unsafe protocols
whitelist[:transformers].push(remove_unsafe_links)
diff --git a/lib/gitlab/akismet_helper.rb b/lib/gitlab/akismet_helper.rb
deleted file mode 100644
index 207736b59db..00000000000
--- a/lib/gitlab/akismet_helper.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-module Gitlab
- module AkismetHelper
- def akismet_enabled?
- current_application_settings.akismet_enabled
- end
-
- def akismet_client
- @akismet_client ||= ::Akismet::Client.new(current_application_settings.akismet_api_key,
- Gitlab.config.gitlab.url)
- end
-
- def client_ip(env)
- env['action_dispatch.remote_ip'].to_s
- end
-
- def user_agent(env)
- env['HTTP_USER_AGENT']
- end
-
- def check_for_spam?(project)
- akismet_enabled? && project.public?
- end
-
- def is_spam?(environment, user, text)
- client = akismet_client
- ip_address = client_ip(environment)
- user_agent = user_agent(environment)
-
- params = {
- type: 'comment',
- text: text,
- created_at: DateTime.now,
- author: user.name,
- author_email: user.email,
- referrer: environment['HTTP_REFERER'],
- }
-
- begin
- is_spam, is_blatant = client.check(ip_address, user_agent, params)
- is_spam || is_blatant
- rescue => e
- Rails.logger.error("Unable to connect to Akismet: #{e}, skipping check")
- false
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/base.rb b/lib/gitlab/badge/base.rb
new file mode 100644
index 00000000000..909fa24fa90
--- /dev/null
+++ b/lib/gitlab/badge/base.rb
@@ -0,0 +1,21 @@
+module Gitlab
+ module Badge
+ class Base
+ def entity
+ raise NotImplementedError
+ end
+
+ def status
+ raise NotImplementedError
+ end
+
+ def metadata
+ raise NotImplementedError
+ end
+
+ def template
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/build.rb b/lib/gitlab/badge/build.rb
deleted file mode 100644
index 1de721a2269..00000000000
--- a/lib/gitlab/badge/build.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-module Gitlab
- module Badge
- ##
- # Build badge
- #
- class Build
- delegate :key_text, :value_text, to: :template
-
- def initialize(project, ref)
- @project = project
- @ref = ref
- @sha = @project.commit(@ref).try(:sha)
- end
-
- def status
- @project.pipelines
- .where(sha: @sha, ref: @ref)
- .status || 'unknown'
- end
-
- def metadata
- @metadata ||= Build::Metadata.new(@project, @ref)
- end
-
- def template
- @template ||= Build::Template.new(status)
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/build/metadata.rb b/lib/gitlab/badge/build/metadata.rb
index 553ef8d7b16..f87a7b7942e 100644
--- a/lib/gitlab/badge/build/metadata.rb
+++ b/lib/gitlab/badge/build/metadata.rb
@@ -1,25 +1,17 @@
module Gitlab
module Badge
- class Build
+ module Build
##
# Class that describes build badge metadata
#
- class Metadata
- include Gitlab::Application.routes.url_helpers
- include ActionView::Helpers::AssetTagHelper
- include ActionView::Helpers::UrlHelper
-
- def initialize(project, ref)
- @project = project
- @ref = ref
- end
-
- def to_html
- link_to(image_tag(image_url, alt: 'build status'), link_url)
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ @ref = badge.ref
end
- def to_markdown
- "[![build status](#{image_url})](#{link_url})"
+ def title
+ 'build status'
end
def image_url
diff --git a/lib/gitlab/badge/build/status.rb b/lib/gitlab/badge/build/status.rb
new file mode 100644
index 00000000000..50aa45e5406
--- /dev/null
+++ b/lib/gitlab/badge/build/status.rb
@@ -0,0 +1,37 @@
+module Gitlab
+ module Badge
+ module Build
+ ##
+ # Build status badge
+ #
+ class Status < Badge::Base
+ attr_reader :project, :ref
+
+ def initialize(project, ref)
+ @project = project
+ @ref = ref
+
+ @sha = @project.commit(@ref).try(:sha)
+ end
+
+ def entity
+ 'build'
+ end
+
+ def status
+ @project.pipelines
+ .where(sha: @sha, ref: @ref)
+ .status || 'unknown'
+ end
+
+ def metadata
+ @metadata ||= Build::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Build::Template.new(self)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/build/template.rb b/lib/gitlab/badge/build/template.rb
index deba3b669b3..2b95ddfcb53 100644
--- a/lib/gitlab/badge/build/template.rb
+++ b/lib/gitlab/badge/build/template.rb
@@ -1,12 +1,12 @@
module Gitlab
module Badge
- class Build
+ module Build
##
# Class that represents a build badge template.
#
# Template object will be passed to badge.svg.erb template.
#
- class Template
+ class Template < Badge::Template
STATUS_COLOR = {
success: '#4c1',
failed: '#e05d44',
@@ -17,16 +17,17 @@ module Gitlab
unknown: '#9f9f9f'
}
- def initialize(status)
- @status = status
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
end
def key_text
- 'build'
+ @entity.to_s
end
def value_text
- @status
+ @status.to_s
end
def key_width
@@ -37,25 +38,8 @@ module Gitlab
54
end
- def key_color
- '#555'
- end
-
def value_color
- STATUS_COLOR[@status.to_sym] ||
- STATUS_COLOR[:unknown]
- end
-
- def key_text_anchor
- key_width / 2
- end
-
- def value_text_anchor
- key_width + (value_width / 2)
- end
-
- def width
- key_width + value_width
+ STATUS_COLOR[@status.to_sym] || STATUS_COLOR[:unknown]
end
end
end
diff --git a/lib/gitlab/badge/coverage/metadata.rb b/lib/gitlab/badge/coverage/metadata.rb
new file mode 100644
index 00000000000..53588185622
--- /dev/null
+++ b/lib/gitlab/badge/coverage/metadata.rb
@@ -0,0 +1,30 @@
+module Gitlab
+ module Badge
+ module Coverage
+ ##
+ # Class that describes coverage badge metadata
+ #
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ @ref = badge.ref
+ @job = badge.job
+ end
+
+ def title
+ 'coverage report'
+ end
+
+ def image_url
+ coverage_namespace_project_badges_url(@project.namespace,
+ @project, @ref,
+ format: :svg)
+ end
+
+ def link_url
+ namespace_project_commits_url(@project.namespace, @project, id: @ref)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
new file mode 100644
index 00000000000..3d56ea3e47a
--- /dev/null
+++ b/lib/gitlab/badge/coverage/report.rb
@@ -0,0 +1,56 @@
+module Gitlab
+ module Badge
+ module Coverage
+ ##
+ # Test coverage report badge
+ #
+ class Report < Badge::Base
+ attr_reader :project, :ref, :job
+
+ def initialize(project, ref, job = nil)
+ @project = project
+ @ref = ref
+ @job = job
+
+ @pipeline = @project.pipelines
+ .where(ref: @ref)
+ .where(sha: @project.commit(@ref).try(:sha))
+ .first
+ end
+
+ def entity
+ 'coverage'
+ end
+
+ def status
+ @coverage ||= raw_coverage
+ return unless @coverage
+
+ @coverage.to_i
+ end
+
+ def metadata
+ @metadata ||= Coverage::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Coverage::Template.new(self)
+ end
+
+ private
+
+ def raw_coverage
+ return unless @pipeline
+
+ if @job.blank?
+ @pipeline.coverage
+ else
+ @pipeline.builds
+ .find_by(name: @job)
+ .try(:coverage)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/coverage/template.rb b/lib/gitlab/badge/coverage/template.rb
new file mode 100644
index 00000000000..06e0d084e9f
--- /dev/null
+++ b/lib/gitlab/badge/coverage/template.rb
@@ -0,0 +1,52 @@
+module Gitlab
+ module Badge
+ module Coverage
+ ##
+ # Class that represents a coverage badge template.
+ #
+ # Template object will be passed to badge.svg.erb template.
+ #
+ class Template < Badge::Template
+ STATUS_COLOR = {
+ good: '#4c1',
+ acceptable: '#a3c51c',
+ medium: '#dfb317',
+ low: '#e05d44',
+ unknown: '#9f9f9f'
+ }
+
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ end
+
+ def key_text
+ @entity.to_s
+ end
+
+ def value_text
+ @status ? "#{@status}%" : 'unknown'
+ end
+
+ def key_width
+ 62
+ end
+
+ def value_width
+ @status ? 36 : 58
+ end
+
+ def value_color
+ case @status
+ when 95..100 then STATUS_COLOR[:good]
+ when 90..95 then STATUS_COLOR[:acceptable]
+ when 75..90 then STATUS_COLOR[:medium]
+ when 0..75 then STATUS_COLOR[:low]
+ else
+ STATUS_COLOR[:unknown]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/metadata.rb b/lib/gitlab/badge/metadata.rb
new file mode 100644
index 00000000000..548f85b78bb
--- /dev/null
+++ b/lib/gitlab/badge/metadata.rb
@@ -0,0 +1,36 @@
+module Gitlab
+ module Badge
+ ##
+ # Abstract class for badge metadata
+ #
+ class Metadata
+ include Gitlab::Application.routes.url_helpers
+ include ActionView::Helpers::AssetTagHelper
+ include ActionView::Helpers::UrlHelper
+
+ def initialize(badge)
+ @badge = badge
+ end
+
+ def to_html
+ link_to(image_tag(image_url, alt: title), link_url)
+ end
+
+ def to_markdown
+ "[![#{title}](#{image_url})](#{link_url})"
+ end
+
+ def title
+ raise NotImplementedError
+ end
+
+ def image_url
+ raise NotImplementedError
+ end
+
+ def link_url
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/template.rb b/lib/gitlab/badge/template.rb
new file mode 100644
index 00000000000..bfeb0052642
--- /dev/null
+++ b/lib/gitlab/badge/template.rb
@@ -0,0 +1,49 @@
+module Gitlab
+ module Badge
+ ##
+ # Abstract template class for badges
+ #
+ class Template
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ end
+
+ def key_text
+ raise NotImplementedError
+ end
+
+ def value_text
+ raise NotImplementedError
+ end
+
+ def key_width
+ raise NotImplementedError
+ end
+
+ def value_width
+ raise NotImplementedError
+ end
+
+ def value_color
+ raise NotImplementedError
+ end
+
+ def key_color
+ '#555'
+ end
+
+ def key_text_anchor
+ key_width / 2
+ end
+
+ def value_text_anchor
+ key_width + (value_width / 2)
+ end
+
+ def width
+ key_width + value_width
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb
index 52f117e963b..4b32eb966aa 100644
--- a/lib/gitlab/checks/change_access.rb
+++ b/lib/gitlab/checks/change_access.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def exec
- error = protected_branch_checks || tag_checks || push_checks
+ error = push_checks || tag_checks || protected_branch_checks
if error
GitAccessStatus.new(false, error)
diff --git a/lib/gitlab/build_data_builder.rb b/lib/gitlab/data_builder/build.rb
index 9f45aefda0f..6548e6475c6 100644
--- a/lib/gitlab/build_data_builder.rb
+++ b/lib/gitlab/data_builder/build.rb
@@ -1,6 +1,8 @@
module Gitlab
- class BuildDataBuilder
- class << self
+ module DataBuilder
+ module Build
+ extend self
+
def build(build)
project = build.project
commit = build.pipeline
diff --git a/lib/gitlab/note_data_builder.rb b/lib/gitlab/data_builder/note.rb
index 8bdc89a7751..50fea1232af 100644
--- a/lib/gitlab/note_data_builder.rb
+++ b/lib/gitlab/data_builder/note.rb
@@ -1,6 +1,8 @@
module Gitlab
- class NoteDataBuilder
- class << self
+ module DataBuilder
+ module Note
+ extend self
+
# Produce a hash of post-receive data
#
# For all notes:
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
new file mode 100644
index 00000000000..06a783ebc1c
--- /dev/null
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -0,0 +1,62 @@
+module Gitlab
+ module DataBuilder
+ module Pipeline
+ extend self
+
+ def build(pipeline)
+ {
+ object_kind: 'pipeline',
+ object_attributes: hook_attrs(pipeline),
+ user: pipeline.user.try(:hook_attrs),
+ project: pipeline.project.hook_attrs(backward: false),
+ commit: pipeline.commit.try(:hook_attrs),
+ builds: pipeline.builds.map(&method(:build_hook_attrs))
+ }
+ end
+
+ def hook_attrs(pipeline)
+ {
+ id: pipeline.id,
+ ref: pipeline.ref,
+ tag: pipeline.tag,
+ sha: pipeline.sha,
+ before_sha: pipeline.before_sha,
+ status: pipeline.status,
+ stages: pipeline.stages,
+ created_at: pipeline.created_at,
+ finished_at: pipeline.finished_at,
+ duration: pipeline.duration
+ }
+ end
+
+ def build_hook_attrs(build)
+ {
+ id: build.id,
+ stage: build.stage,
+ name: build.name,
+ status: build.status,
+ created_at: build.created_at,
+ started_at: build.started_at,
+ finished_at: build.finished_at,
+ when: build.when,
+ manual: build.manual?,
+ user: build.user.try(:hook_attrs),
+ runner: build.runner && runner_hook_attrs(build.runner),
+ artifacts_file: {
+ filename: build.artifacts_file.filename,
+ size: build.artifacts_size
+ }
+ }
+ end
+
+ def runner_hook_attrs(runner)
+ {
+ id: runner.id,
+ description: runner.description,
+ active: runner.active?,
+ is_shared: runner.is_shared?
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/push_data_builder.rb b/lib/gitlab/data_builder/push.rb
index c8f12577112..4f81863da35 100644
--- a/lib/gitlab/push_data_builder.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -1,6 +1,8 @@
module Gitlab
- class PushDataBuilder
- class << self
+ module DataBuilder
+ module Push
+ extend self
+
# Produce a hash of post-receive data
#
# data = {
diff --git a/lib/gitlab/import_export/json_hash_builder.rb b/lib/gitlab/import_export/json_hash_builder.rb
index 008300bde45..0cc10f40087 100644
--- a/lib/gitlab/import_export/json_hash_builder.rb
+++ b/lib/gitlab/import_export/json_hash_builder.rb
@@ -57,19 +57,16 @@ module Gitlab
# +value+ existing model to be included in the hash
# +json_config_hash+ the original hash containing the root model
def create_model_value(current_key, value, json_config_hash)
- parsed_hash = { include: value }
- parse_hash(value, parsed_hash)
-
- json_config_hash[current_key] = parsed_hash
+ json_config_hash[current_key] = parse_hash(value) || { include: value }
end
# Calls attributes finder to parse the hash and add any attributes to it
#
# +value+ existing model to be included in the hash
# +parsed_hash+ the original hash
- def parse_hash(value, parsed_hash)
+ def parse_hash(value)
@attributes_finder.parse(value) do |hash|
- parsed_hash = { include: hash_or_merge(value, hash) }
+ { include: hash_or_merge(value, hash) }
end
end
diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb
index 760ff3e614a..7ebec8e2cff 100644
--- a/lib/gitlab/template/base_template.rb
+++ b/lib/gitlab/template/base_template.rb
@@ -1,8 +1,9 @@
module Gitlab
module Template
class BaseTemplate
- def initialize(path)
+ def initialize(path, project = nil)
@path = path
+ @finder = self.class.finder(project)
end
def name
@@ -10,23 +11,32 @@ module Gitlab
end
def content
- File.read(@path)
+ @finder.read(@path)
+ end
+
+ def to_json
+ { name: name, content: content }
end
class << self
- def all
- self.categories.keys.flat_map { |cat| by_category(cat) }
+ def all(project = nil)
+ if categories.any?
+ categories.keys.flat_map { |cat| by_category(cat, project) }
+ else
+ by_category("", project)
+ end
end
- def find(key)
- file_name = "#{key}#{self.extension}"
-
- directory = select_directory(file_name)
- directory ? new(File.join(category_directory(directory), file_name)) : nil
+ def find(key, project = nil)
+ path = self.finder(project).find(key)
+ path.present? ? new(path, project) : nil
end
+ # Set categories as sub directories
+ # Example: { "category_name_1" => "directory_path_1", "category_name_2" => "directory_name_2" }
+ # Default is no category with all files in base dir of each class
def categories
- raise NotImplementedError
+ {}
end
def extension
@@ -37,29 +47,40 @@ module Gitlab
raise NotImplementedError
end
- def by_category(category)
- templates_for_directory(category_directory(category))
+ # Defines which strategy will be used to get templates files
+ # RepoTemplateFinder - Finds templates on project repository, templates are filtered perproject
+ # GlobalTemplateFinder - Finds templates on gitlab installation source, templates can be used in all projects
+ def finder(project = nil)
+ raise NotImplementedError
end
- def category_directory(category)
- File.join(base_dir, categories[category])
+ def by_category(category, project = nil)
+ directory = category_directory(category)
+ files = finder(project).list_files_for(directory)
+
+ files.map { |f| new(f, project) }
end
- private
+ def category_directory(category)
+ return base_dir unless category.present?
- def select_directory(file_name)
- categories.keys.find do |category|
- File.exist?(File.join(category_directory(category), file_name))
- end
+ File.join(base_dir, categories[category])
end
- def templates_for_directory(dir)
- dir << '/' unless dir.end_with?('/')
- Dir.glob(File.join(dir, "*#{self.extension}")).select { |f| f =~ filter_regex }.map { |f| new(f) }
- end
+ # If template is organized by category it returns { category_name: [{ name: template_name }, { name: template2_name }] }
+ # If no category is present returns [{ name: template_name }, { name: template2_name}]
+ def dropdown_names(project = nil)
+ return [] if project && !project.repository.exists?
- def filter_regex
- @filter_reges ||= /#{Regexp.escape(extension)}\z/
+ if categories.any?
+ categories.keys.map do |category|
+ files = self.by_category(category, project)
+ [category, files.map { |t| { name: t.name } }]
+ end.to_h
+ else
+ files = self.all(project)
+ files.map { |t| { name: t.name } }
+ end
end
end
end
diff --git a/lib/gitlab/template/finders/base_template_finder.rb b/lib/gitlab/template/finders/base_template_finder.rb
new file mode 100644
index 00000000000..473b05257c6
--- /dev/null
+++ b/lib/gitlab/template/finders/base_template_finder.rb
@@ -0,0 +1,35 @@
+module Gitlab
+ module Template
+ module Finders
+ class BaseTemplateFinder
+ def initialize(base_dir)
+ @base_dir = base_dir
+ end
+
+ def list_files_for
+ raise NotImplementedError
+ end
+
+ def read
+ raise NotImplementedError
+ end
+
+ def find
+ raise NotImplementedError
+ end
+
+ def category_directory(category)
+ return @base_dir unless category.present?
+
+ @base_dir + @categories[category]
+ end
+
+ class << self
+ def filter_regex(extension)
+ /#{Regexp.escape(extension)}\z/
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/template/finders/global_template_finder.rb b/lib/gitlab/template/finders/global_template_finder.rb
new file mode 100644
index 00000000000..831da45191f
--- /dev/null
+++ b/lib/gitlab/template/finders/global_template_finder.rb
@@ -0,0 +1,38 @@
+# Searches and reads file present on Gitlab installation directory
+module Gitlab
+ module Template
+ module Finders
+ class GlobalTemplateFinder < BaseTemplateFinder
+ def initialize(base_dir, extension, categories = {})
+ @categories = categories
+ @extension = extension
+ super(base_dir)
+ end
+
+ def read(path)
+ File.read(path)
+ end
+
+ def find(key)
+ file_name = "#{key}#{@extension}"
+
+ directory = select_directory(file_name)
+ directory ? File.join(category_directory(directory), file_name) : nil
+ end
+
+ def list_files_for(dir)
+ dir << '/' unless dir.end_with?('/')
+ Dir.glob(File.join(dir, "*#{@extension}")).select { |f| f =~ self.class.filter_regex(@extension) }
+ end
+
+ private
+
+ def select_directory(file_name)
+ @categories.keys.find do |category|
+ File.exist?(File.join(category_directory(category), file_name))
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/template/finders/repo_template_finder.rb b/lib/gitlab/template/finders/repo_template_finder.rb
new file mode 100644
index 00000000000..22c39436cb2
--- /dev/null
+++ b/lib/gitlab/template/finders/repo_template_finder.rb
@@ -0,0 +1,59 @@
+# Searches and reads files present on each Gitlab project repository
+module Gitlab
+ module Template
+ module Finders
+ class RepoTemplateFinder < BaseTemplateFinder
+ # Raised when file is not found
+ class FileNotFoundError < StandardError; end
+
+ def initialize(project, base_dir, extension, categories = {})
+ @categories = categories
+ @extension = extension
+ @repository = project.repository
+ @commit = @repository.head_commit if @repository.exists?
+
+ super(base_dir)
+ end
+
+ def read(path)
+ blob = @repository.blob_at(@commit.id, path) if @commit
+ raise FileNotFoundError if blob.nil?
+ blob.data
+ end
+
+ def find(key)
+ file_name = "#{key}#{@extension}"
+ directory = select_directory(file_name)
+ raise FileNotFoundError if directory.nil?
+
+ category_directory(directory) + file_name
+ end
+
+ def list_files_for(dir)
+ return [] unless @commit
+
+ dir << '/' unless dir.end_with?('/')
+
+ entries = @repository.tree(:head, dir).entries
+
+ names = entries.map(&:name)
+ names.select { |f| f =~ self.class.filter_regex(@extension) }
+ end
+
+ private
+
+ def select_directory(file_name)
+ return [] unless @commit
+
+ # Insert root as directory
+ directories = ["", @categories.keys]
+
+ directories.find do |category|
+ path = category_directory(category) + file_name
+ @repository.blob_at(@commit.id, path)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/template/gitignore.rb b/lib/gitlab/template/gitignore_template.rb
index 964fbfd4de3..8d2a9d2305c 100644
--- a/lib/gitlab/template/gitignore.rb
+++ b/lib/gitlab/template/gitignore_template.rb
@@ -1,6 +1,6 @@
module Gitlab
module Template
- class Gitignore < BaseTemplate
+ class GitignoreTemplate < BaseTemplate
class << self
def extension
'.gitignore'
@@ -16,6 +16,10 @@ module Gitlab
def base_dir
Rails.root.join('vendor/gitignore')
end
+
+ def finder(project = nil)
+ Gitlab::Template::Finders::GlobalTemplateFinder.new(self.base_dir, self.extension, self.categories)
+ end
end
end
end
diff --git a/lib/gitlab/template/gitlab_ci_yml.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index 7f480fe33c0..8d1a1ed54c9 100644
--- a/lib/gitlab/template/gitlab_ci_yml.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -1,6 +1,6 @@
module Gitlab
module Template
- class GitlabCiYml < BaseTemplate
+ class GitlabCiYmlTemplate < BaseTemplate
def content
explanation = "# This file is a template, and might need editing before it works on your project."
[explanation, super].join("\n")
@@ -21,6 +21,10 @@ module Gitlab
def base_dir
Rails.root.join('vendor/gitlab-ci-yml')
end
+
+ def finder(project = nil)
+ Gitlab::Template::Finders::GlobalTemplateFinder.new(self.base_dir, self.extension, self.categories)
+ end
end
end
end
diff --git a/lib/gitlab/template/issue_template.rb b/lib/gitlab/template/issue_template.rb
new file mode 100644
index 00000000000..c6fa8d3eafc
--- /dev/null
+++ b/lib/gitlab/template/issue_template.rb
@@ -0,0 +1,19 @@
+module Gitlab
+ module Template
+ class IssueTemplate < BaseTemplate
+ class << self
+ def extension
+ '.md'
+ end
+
+ def base_dir
+ '.gitlab/issue_templates/'
+ end
+
+ def finder(project)
+ Gitlab::Template::Finders::RepoTemplateFinder.new(project, self.base_dir, self.extension, self.categories)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/template/merge_request_template.rb b/lib/gitlab/template/merge_request_template.rb
new file mode 100644
index 00000000000..f826c02f3b5
--- /dev/null
+++ b/lib/gitlab/template/merge_request_template.rb
@@ -0,0 +1,19 @@
+module Gitlab
+ module Template
+ class MergeRequestTemplate < BaseTemplate
+ class << self
+ def extension
+ '.md'
+ end
+
+ def base_dir
+ '.gitlab/merge_request_templates/'
+ end
+
+ def finder(project)
+ Gitlab::Template::Finders::RepoTemplateFinder.new(project, self.base_dir, self.extension, self.categories)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index c55a7fc4d3d..9858d2e7d83 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -32,7 +32,7 @@ module Gitlab
if project.protected_branch?(ref)
return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user)
- access_levels = project.protected_branches.matching(ref).map(&:push_access_level)
+ access_levels = project.protected_branches.matching(ref).map(&:push_access_levels).flatten
access_levels.any? { |access_level| access_level.check_access(user) }
else
user.can?(:push_code, project)
@@ -43,7 +43,7 @@ module Gitlab
return false unless user
if project.protected_branch?(ref)
- access_levels = project.protected_branches.matching(ref).map(&:merge_access_level)
+ access_levels = project.protected_branches.matching(ref).map(&:merge_access_levels).flatten
access_levels.any? { |access_level| access_level.check_access(user) }
else
user.can?(:push_code, project)