Commit fd40843a authored by Robert Speicher's avatar Robert Speicher

Merge branch 'ce-to-ee-2018-09-05' into 'master'

CE upstream - 2018-09-05 15:23 UTC

See merge request gitlab-org/gitlab-ee!7252
parents e952f958 cb677592
......@@ -37,7 +37,7 @@
</script>
<template>
<div class="groups-list-tree-container">
<div class="groups-list-tree-container qa-groups-list-tree-container">
<div
v-if="searchEmpty"
class="has-no-search-results"
......
......@@ -66,6 +66,7 @@ class Projects::HooksController < Projects::ApplicationController
:enable_ssl_verification,
:token,
:url,
:push_events_branch_filter,
*ProjectHook.triggers.values
)
end
......
......@@ -110,10 +110,12 @@ module EventsHelper
event.note_target)
elsif event.note?
if event.note_target
event_note_target_path(event)
event_note_target_url(event)
end
elsif event.push?
push_event_feed_url(event)
elsif event.created_project?
project_url(event.project)
end
end
......@@ -145,14 +147,14 @@ module EventsHelper
end
end
def event_note_target_path(event)
def event_note_target_url(event)
if event.commit_note?
project_commit_path(event.project, event.note_target, anchor: dom_id(event.target))
project_commit_url(event.project, event.note_target, anchor: dom_id(event.target))
elsif event.project_snippet_note?
project_snippet_path(event.project, event.note_target, anchor: dom_id(event.target))
project_snippet_url(event.project, event.note_target, anchor: dom_id(event.target))
else
polymorphic_path([event.project.namespace.becomes(Namespace),
event.project, event.note_target],
polymorphic_url([event.project.namespace.becomes(Namespace),
event.project, event.note_target],
anchor: dom_id(event.target))
end
end
......@@ -166,7 +168,7 @@ module EventsHelper
event.note_target_reference
end
link_to(text, event_note_target_path(event), title: event.target_title, class: 'has-tooltip')
link_to(text, event_note_target_url(event), title: event.target_title, class: 'has-tooltip')
else
content_tag(:strong, '(deleted)')
end
......
......@@ -90,7 +90,7 @@ module Ci
end
def hashed_path?
super || self.file_location.nil?
super || self.try(:file_location).nil?
end
def expire_in
......
......@@ -50,14 +50,20 @@ module ProtectedRef
.map(&:"#{action}_access_levels").flatten
end
# Returns all protected refs that match the given ref name.
# This checks all records from the scope built up so far, and does
# _not_ return a relation.
#
# This method optionally takes in a list of `protected_refs` to search
# through, to avoid calling out to the database.
def matching(ref_name, protected_refs: nil)
ProtectedRefMatcher.matching(self, ref_name, protected_refs: protected_refs)
(protected_refs || self.all).select { |protected_ref| protected_ref.matches?(ref_name) }
end
end
private
def ref_matcher
@ref_matcher ||= ProtectedRefMatcher.new(self)
@ref_matcher ||= RefMatcher.new(self.name)
end
end
......@@ -29,6 +29,12 @@ module TriggerableHooks
public_send(trigger) # rubocop:disable GitlabSecurity/PublicSend
end
def select_active(hooks_scope, data)
select do |hook|
ActiveHookFilter.new(hook).matches?(hooks_scope, data)
end
end
private
def triggerable_hooks(hooks)
......
class ActiveHookFilter
def initialize(hook)
@hook = hook
@push_events_filter_matcher = RefMatcher.new(@hook.push_events_branch_filter)
end
def matches?(hooks_scope, data)
return true if hooks_scope != :push_hooks
return true if @hook.push_events_branch_filter.blank?
branch_name = Gitlab::Git.branch_name(data[:ref])
@push_events_filter_matcher.matches?(branch_name)
end
end
......@@ -9,6 +9,7 @@ class WebHook < ActiveRecord::Base
allow_local_network: lambda(&:allow_local_requests?) }
validates :token, format: { without: /\n/ }
validates :push_events_branch_filter, branch_filter: true
def execute(data, hook_name)
WebHookService.new(self, data, hook_name).execute
......
......@@ -1201,10 +1201,9 @@ class Project < ActiveRecord::Base
def execute_hooks(data, hooks_scope = :push_hooks)
run_after_commit_or_now do
hooks.hooks_for(hooks_scope).each do |hook|
hooks.hooks_for(hooks_scope).select_active(hooks_scope, data).each do |hook|
hook.async_execute(data, hooks_scope.to_s)
end
SystemHooksService.new.execute_hooks(data, hooks_scope)
end
end
......
# frozen_string_literal: true
class ProtectedRefMatcher
def initialize(protected_ref)
@protected_ref = protected_ref
end
# Returns all protected refs that match the given ref name.
# This checks all records from the scope built up so far, and does
# _not_ return a relation.
#
# This method optionally takes in a list of `protected_refs` to search
# through, to avoid calling out to the database.
def self.matching(type, ref_name, protected_refs: nil)
(protected_refs || type.all).select { |protected_ref| protected_ref.matches?(ref_name) }
class RefMatcher
def initialize(ref_name_or_pattern)
@ref_name_or_pattern = ref_name_or_pattern
end
# Returns all branches/tags (among the given list of refs [`Gitlab::Git::Branch`])
# that match the current protected ref.
def matching(refs)
refs.select { |ref| @protected_ref.matches?(ref.name) }
refs.select { |ref| matches?(ref.name) }
end
# Checks if the protected ref matches the given ref name.
def matches?(ref_name)
return false if @protected_ref.name.blank?
return false if @ref_name_or_pattern.blank?
exact_match?(ref_name) || wildcard_match?(ref_name)
end
# Checks if this protected ref contains a wildcard
def wildcard?
@protected_ref.name && @protected_ref.name.include?('*')
@ref_name_or_pattern && @ref_name_or_pattern.include?('*')
end
protected
def exact_match?(ref_name)
@protected_ref.name == ref_name
@ref_name_or_pattern == ref_name
end
def wildcard_match?(ref_name)
......@@ -47,7 +37,7 @@ class ProtectedRefMatcher
def wildcard_regex
@wildcard_regex ||= begin
name = @protected_ref.name.gsub('*', 'STAR_DONT_ESCAPE')
name = @ref_name_or_pattern.gsub('*', 'STAR_DONT_ESCAPE')
quoted_name = Regexp.quote(name)
regex_string = quoted_name.gsub('STAR_DONT_ESCAPE', '.*?')
/\A#{regex_string}\z/
......
# BranchFilterValidator
#
# Custom validator for branch names. Squishes whitespace and ignores empty
# string. This only checks that a string is a valid git branch name. It does
# not check whether a branch already exists.
#
# Example:
#
# class Webhook < ActiveRecord::Base
# validates :push_events_branch_filter, branch_name: true
# end
#
class BranchFilterValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
value.squish! unless value.nil?
if value.present?
value_without_wildcards = value.tr('*', 'x')
unless Gitlab::GitRefValidator.validate(value_without_wildcards)
record.errors[attribute] << "is not a valid branch name"
end
unless value.length <= 4000
record.errors[attribute] << "is longer than the allowed length of 4000 characters."
end
end
end
private
def contains_wildcard?(value)
value.include?('*')
end
end
%div{ xmlns: "http://www.w3.org/1999/xhtml" }
%p
%strong= event.author_name
= link_to "(#{truncate_sha(event.commit_id)})", project_commit_path(event.project, event.commit_id)
= link_to "(#{truncate_sha(event.commit_id)})", event_feed_url(event)
%i
at
= event.created_at.to_s(:short)
......
......@@ -5,7 +5,7 @@
- else
- search_path_url = search_path
%header.navbar.navbar-gitlab.navbar-gitlab-new.qa-navbar.navbar-expand-sm
%header.navbar.navbar-gitlab.qa-navbar.navbar-expand-sm.navbar-gitlab-new
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
.header-content
......
......@@ -3,7 +3,10 @@
- @content_class = "limit-container-width" unless fluid_layout
= render "projects/default_branch/show"
<<<<<<< HEAD
= render "projects/push_rules/index"
=======
>>>>>>> upstream/master
= render "projects/mirrors/show"
-# Protected branches & tags use a lot of nested partials.
......
.groups-empty-state
.groups-empty-state.qa-groups-empty-state
= custom_icon("icon_empty_groups")
.text-content
......
......@@ -17,6 +17,7 @@
%strong Push events
%p.light.ml-1
This URL will be triggered by a push to the repository
= form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%li
= form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, class: 'list-label form-check-label ml-1' do
......
......@@ -18,7 +18,7 @@
= event_action_name(event)
%strong
- if event.note?
= link_to event.note_target.to_reference, event_note_target_path(event), class: 'has-tooltip', title: event.target_title
= link_to event.note_target.to_reference, event_note_target_url(event), class: 'has-tooltip', title: event.target_title
- elsif event.target
= link_to event.target.to_reference, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title
......
---
title: Adds diverged_commits_count field to GET api/v4/projects/:project_id/merge_requests/:merge_request_iid
merge_request: 21405
author: Jacopo Beschi @jacopo-beschi
type: added
---
title: Fix links in RSS feed elements
merge_request: 21424
author: Marc Schwede
type: fixed
---
title: Add branch filter to project webhooks
merge_request: 20338
author: Duana Saskia
type: added
---
title: 'Rails 5: fix hashed_path? method that looks up file_location that doesn''t
exist when running certain migration specs'
merge_request: 21510
author: Jasper Maes
type: other
---
title: Ignore irrelevant sql commands in metrics
merge_request: 21498
author:
type: other
......@@ -235,8 +235,9 @@
:why: https://github.com/component/inherit/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:41.804804000 Z
- - :approve
- - :license
- fsevents
- MIT
- :who: Matt Lee
:why: https://github.com/strongloop/fsevents/blob/master/LICENSE
:versions: []
......@@ -380,8 +381,9 @@
:why: https://github.com/Tjatse/ansi-html/blob/master/LICENSE
:versions: []
:when: 2017-04-10 05:42:12.898178000 Z
- - :approve
- - :license
- map-stream
- MIT
- :who: Mike Greiling
:why: https://github.com/dominictarr/map-stream/blob/master/LICENCE
:versions: []
......@@ -458,8 +460,9 @@
:why: CC0 1.0 - https://github.com/jonathantneal/svg4everybody/blob/master/LICENSE.md
:versions: []
:when: 2017-09-13 17:31:16.425819400 Z
- - :approve
- - :license
- "@gitlab-org/gitlab-svgs"
- MIT
- :who: Tim Zallmann
:why: Our own library - GitLab License https://gitlab.com/gitlab-org/gitlab-svgs
:versions: []
......@@ -528,8 +531,9 @@
:why: https://github.com/mafintosh/cyclist/blob/master/LICENSE
:versions: []
:when: 2018-02-20 21:37:43.774978000 Z
- - :approve
- - :license
- bitsyntax
- MIT
- :who: Mike Greiling
:why: https://github.com/squaremo/bitsyntax-js/blob/master/LICENSE-MIT
:versions: []
......@@ -540,8 +544,9 @@
:why: https://github.com/xtuc/webassemblyjs/blob/master/LICENSE
:versions: []
:when: 2018-06-08 05:30:56.764116000 Z
- - :approve
- - :license
- "@gitlab-org/gitlab-ui"
- MIT
- :who: Clement Ho
:why: Our own library
:versions: []
......@@ -552,20 +557,23 @@
:why: https://github.com/pieroxy/lz-string/blob/master/LICENSE.txt
:versions: []
:when: 2018-08-03 08:22:44.973457000 Z
- - :approve
- - :license
- smooshpack
- LGPL
- :who: Phil Hughes
:why: https://github.com/CompuIves/codesandbox-client/blob/master/packages/sandpack/LICENSE.md
:versions: []
:when: 2018-08-03 08:24:29.578991000 Z
- - :approve
- - :license
- codesandbox-import-util-types
- LGPL
- :who: Phil Hughes
:why: https://github.com/codesandbox-app/codesandbox-importers/blob/master/packages/types/LICENSE
:versions: []
:when: 2018-08-03 12:22:47.574421000 Z
- - :approve
- - :license
- codesandbox-import-utils
- LGPL
- :who: Phil Hughes
:why: https://github.com/codesandbox-app/codesandbox-importers/blob/master/packages/import-utils/LICENSE
:versions: []
......@@ -573,7 +581,7 @@
- - :ignore_group
- devDependencies
- :who: Winnie Hellmann
:why: NPM packages used for development are not distributed with the final product and are therefore
exempt.
:why: NPM packages used for development are not distributed with the final product
and are therefore exempt.
:versions: []
:when: 2018-08-30 12:06:35.668181000 Z
......@@ -7,11 +7,12 @@
# the old Rails 4 schema layout is still used
module MysqlSetLengthForBinaryIndex
def add_index(table_name, column_names, options = {})
options[:length] ||= {}
Array(column_names).each do |column_name|
column = ActiveRecord::Base.connection.columns(table_name).find { |c| c.name == column_name }
if column&.type == :binary
options[:length] = 20
options[:length][column_name] = 20
end
end
......@@ -27,11 +28,12 @@ if Gitlab.rails5?
module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema
# This method is used in Rails 5 schema loading as t.index
def index(column_names, options = {})
options[:length] ||= {}
Array(column_names).each do |column_name|
column = columns.find { |c| c.name == column_name }
if column&.type == :binary
options[:length] = 20
options[:length][column_name] = 20
end
end
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddPushEventsBranchFilterToWebHooks < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :web_hooks, :push_events_branch_filter, :text
end
end
......@@ -2965,6 +2965,7 @@ ActiveRecord::Schema.define(version: 20180831152625) do
t.boolean "repository_update_events", default: false, null: false
t.boolean "job_events", default: false, null: false
t.boolean "confidential_note_events"
t.text "push_events_branch_filter"
end
add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree
......
......@@ -353,6 +353,7 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `merge_request_iid` (required) - The internal ID of the merge request
- `render_html` (optional) - If `true` response includes rendered HTML for title and description
- `include_diverged_commits_count` (optional) - If `true` response includes the commits behind the target branch
```json
{
......@@ -437,7 +438,8 @@ Parameters:
"username" : "root",
"id" : 1,
"name" : "Administrator"
}
},
"diverged_commits_count": 2
}
```
......
......@@ -1367,6 +1367,7 @@ GET /projects/:id/hooks/:hook_id
"url": "http://example.com/hook",
"project_id": 3,
"push_events": true,
"push_events_branch_filter": "",
"issues_events": true,
"confidential_issues_events": true,
"merge_requests_events": true,
......@@ -1393,6 +1394,7 @@ POST /projects/:id/hooks
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `url` | string | yes | The hook URL |
| `push_events` | boolean | no | Trigger hook on push events |
| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
| `issues_events` | boolean | no | Trigger hook on issues events |
| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
......@@ -1418,6 +1420,7 @@ PUT /projects/:id/hooks/:hook_id
| `hook_id` | integer | yes | The ID of the project hook |
| `url` | string | yes | The hook URL |
| `push_events` | boolean | no | Trigger hook on push events |
| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
| `issues_events` | boolean | no | Trigger hook on issues events |
| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
......
......@@ -95,6 +95,8 @@ Gitlab::Git::DiffCollection.collection_limits[:max_bytes] = Gitlab::Git::DiffCol
No more files will be rendered at all if 5 megabytes have already been rendered.
*Note:* All collection limit parameters are currently sent and applied on Gitaly. That is, once the limit is surpassed,
Gitaly will only return the safe amount of data to be persisted on `merge_request_diff_files`.
### Individual diff file limits
......@@ -106,12 +108,17 @@ Gitlab::Git::Diff::COLLAPSE_LIMIT = 10.kilobytes
File diff will be collapsed (but be expandable) if it is larger than 10 kilobytes.
*Note:* Although this nomenclature (Collapsing) is also used on Gitaly, this limit is only used on GitLab (hardcoded - not sent to Gitaly).
Gitaly will only return `Diff.Collapsed` (RPC) when surpassing collection limits.
```ruby
Gitlab::Git::Diff::SIZE_LIMIT = 100.kilobytes
```
File diff will not be rendered if it's larger than 100 kilobytes.
*Note:* This limit is currently hardcoded and applied on Gitaly and the RPC returns `Diff.TooLarge` when this limit is surpassed.
Although we're still also applying it on GitLab, we should remove the redundancy from GitLab once we're confident with the Gitaly integration.
```ruby
Commit::DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines] = 5000
......@@ -119,6 +126,8 @@ Commit::DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines
File diff will be suppressed (technically different from collapsed, but behaves the same, and is expandable) if it has more than 5000 lines.
*Note:* This limit is currently hardcoded and only applied on GitLab.
## Viewers
Diff Viewers, which can be found on `models/diff_viewer/*` are classes used to map metadata about each type of Diff File. It has information
......
......@@ -90,8 +90,8 @@ Below are described the supported events.
Triggered when you push to the repository except when pushing tags.
> **Note:** When more than 20 commits are pushed at once, the `commits` web hook
attribute will only contain the first 20 for performance reasons. Loading
> **Note:** When more than 20 commits are pushed at once, the `commits` web hook
attribute will only contain the first 20 for performance reasons. Loading
detailed commit data is expensive. Note that despite only 20 commits being
present in the `commits` attribute, the `total_commits_count` attribute will
contain the actual total.
......
......@@ -105,6 +105,7 @@ module API
expose :project_id, :issues_events, :confidential_issues_events
expose :note_events, :confidential_note_events, :pipeline_events, :wiki_page_events
expose :job_events
expose :push_events_branch_filter
end
class SharedGroup < Grape::Entity
......@@ -689,6 +690,8 @@ module API
expose :diff_refs, using: Entities::DiffRefs
expose :diverged_commits_count, as: :diverged_commits_count, if: -> (_, options) { options[:include_diverged_commits_count] }
def build_available?(options)
options[:project]&.feature_available?(:builds, options[:current_user])
end
......
......@@ -235,6 +235,7 @@ module API
params do
requires :merge_request_iid, type: Integer, desc: 'The IID of a merge request'
optional :render_html, type: Boolean, desc: 'Returns the description and title rendered HTML'
optional :include_diverged_commits_count, type: Boolean, desc: 'Returns the commits count behind the target branch'
end
desc 'Get a single merge request' do
success Entities::MergeRequest
......@@ -242,7 +243,7 @@ module API
get ':id/merge_requests/:merge_request_iid' do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project, render_html: params[:render_html]
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project, render_html: params[:render_html], include_diverged_commits_count: params[:include_diverged_commits_count]
end
desc 'Get the participants of a merge request' do
......
......@@ -20,6 +20,7 @@ module API
optional :wiki_page_events, type: Boolean, desc: "Trigger hook on wiki events"
optional :enable_ssl_verification, type: Boolean, desc: "Do SSL verification when triggering the hook"
optional :token, type: String, desc: "Secret token to validate received payloads; this will not be returned in the response"
optional :push_events_branch_filter, type: String, desc: "Trigger hook on specified branch only"
end
end
......@@ -63,6 +64,7 @@ module API
present hook, with: Entities::ProjectHook
else
error!("Invalid url given", 422) if hook.errors[:url].present?
error!("Invalid branch filter given", 422) if hook.errors[:push_events_branch_filter].present?
not_found!("Project hook #{hook.errors.messages}")
end
......@@ -84,6 +86,7 @@ module API
present hook, with: Entities::ProjectHook
else
error!("Invalid url given", 422) if hook.errors[:url].present?
error!("Invalid branch filter given", 422) if hook.errors[:push_events_branch_filter].present?
not_found!("Project hook #{hook.errors.messages}")
end
......
......@@ -6,9 +6,15 @@ module Gitlab
include Gitlab::Metrics::Methods
attach_to :active_record
IGNORABLE_SQL = %w{BEGIN COMMIT}.freeze
def sql(event)
return unless current_transaction
payload = event.payload
return if payload[:name] == 'SCHEMA' || IGNORABLE_SQL.include?(payload[:sql])
self.class.gitlab_sql_duration_seconds.observe(current_transaction.labels, event.duration / 1000.0)
current_transaction.increment(:sql_duration, event.duration, false)
......
......@@ -250,6 +250,7 @@ module QA
module Component
autoload :ClonePanel, 'qa/page/component/clone_panel'
autoload :Dropzone, 'qa/page/component/dropzone'
autoload :GroupsFilter, 'qa/page/component/groups_filter'
autoload :Select2, 'qa/page/component/select2'
end
end
......
......@@ -2,7 +2,7 @@ module QA
module Factory
module Resource
class Group < Factory::Base
attr_writer :path, :description
attr_accessor :path, :description
dependency Factory::Resource::Sandbox, as: :sandbox
......@@ -14,17 +14,23 @@ module QA
def fabricate!
sandbox.visit!
Page::Group::Show.perform do |page|
if page.has_subgroup?(@path)
page.go_to_subgroup(@path)
Page::Group::Show.perform do |group_show|
if group_show.has_subgroup?(path)
group_show.go_to_subgroup(path)
else
page.go_to_new_subgroup
group_show.go_to_new_subgroup
Page::Group::New.perform do |group|
group.set_path(@path)
group.set_description(@description)
group.set_visibility('Public')
group.create
Page::Group::New.perform do |group_new|
group_new.set_path(path)
group_new.set_description(description)
group_new.set_visibility('Public')
group_new.create
end
# Ensure that the group was actually created
group_show.wait(time: 1) do
group_show.has_text?(path) &&
group_show.has_new_project_or_subgroup_dropdown?
end
end
end
......
# frozen_string_literal: true
module QA
module Page
module Component
module GroupsFilter
def self.included(base)
base.view 'app/views/shared/groups/_search_form.html.haml' do
element :groups_filter, 'search_field_tag :filter'
element :groups_filter_placeholder, 'Filter by name...'
end
base.view 'app/views/shared/groups/_empty_state.html.haml' do</