Commit 2f0d89ec authored by Zeger-Jan van de Weg's avatar Zeger-Jan van de Weg
Browse files

Merge branch 'master' into awardables

parents d8c27e4e 459af7ff
......@@ -937,10 +937,9 @@ Lint/Void:
##################### Performance ############################
# TODO: Enable Casecmp Cop.
# Use `casecmp` rather than `downcase ==`.
Performance/Casecmp:
Enabled: false
Enabled: true
# TODO: Enable DoubleStartEndWith Cop.
# Use `str.{start,end}_with?(x, ..., y, ...)` instead of
......@@ -990,11 +989,12 @@ Performance/RedundantSortBy:
# string.
Performance/StartWith:
Enabled: false
# Use `tr` instead of `gsub` when you are replacing the same number of
# characters. Use `delete` instead of `gsub` when you are deleting
# characters.
Performance/StringReplacement:
Enabled: false
Enabled: true
# TODO: Enable TimesMap Cop.
# Checks for `.times.map` calls.
......
Please view this file on the master branch, on stable branches it's out of date.
v 8.8.0 (unreleased)
- Fix error when using link to uploads in global snippets
- Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen)
- Use a case-insensitive comparison in sanitizing URI schemes
- Project#open_branches has been cleaned up and no longer loads entire records into memory.
......@@ -20,6 +21,7 @@ v 8.8.0 (unreleased)
- Fix error when visiting commit builds page before build was updated
- Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project
- Update SVG sanitizer to conform to SVG 1.1
- Speed up push emails with multiple recipients by only generating the email once
- Updated search UI
- Display informative message when new milestone is created
- Sanitize milestones and labels titles
......@@ -31,6 +33,7 @@ v 8.8.0 (unreleased)
- API: Expose Issue#user_notes_count. !3126 (Anton Popov)
- Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718
- Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes)
- Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724
- Added multiple colors for labels in dropdowns when dups happen.
- Improve description for the Two-factor Authentication sign-in screen. (Connor Shea)
- API support for the 'since' and 'until' operators on commit requests (Paco Guzman)
......@@ -38,10 +41,16 @@ v 8.8.0 (unreleased)
- Expire repository exists? and has_visible_content? caches after a push if necessary
- Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi)
- Fix adding a todo for private group members (Ahmad Sherif)
- Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3
v 8.7.4
- Fix always showing build notification message when switching between merge requests
- Links for Redmine issue references are generated correctly again (Benedikt Huss)
- Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss)
- Fix setting trusted proxies !3970
- Fix BitBucket importer bug when throwing exceptions !3941
- Use sign out path only if not empty !3989
- Running rake gitlab:db:drop_tables now drops tables with cascade !4020
- Running rake gitlab:db:drop_tables uses "IF EXISTS" as a precaution !4100
- Use a case-insensitive comparison in sanitizing URI schemes
v 8.7.3
- Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
......
......@@ -197,7 +197,7 @@ gem 'licensee', '~> 8.0.0'
gem "rack-attack", '~> 4.3.1'
# Ace editor
gem 'ace-rails-ap', '~> 2.0.1'
gem 'ace-rails-ap', '~> 4.0.2'
# Keyboard shortcuts
gem 'mousetrap-rails', '~> 1.4.6'
......@@ -218,7 +218,6 @@ gem 'gitlab_emoji', '~> 0.3.0'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0'
gem 'jquery-scrollto-rails', '~> 1.4.3'
gem 'jquery-ui-rails', '~> 5.0.0'
gem 'raphael-rails', '~> 2.1.2'
gem 'request_store', '~> 1.3.0'
......
......@@ -3,7 +3,7 @@ GEM
specs:
CFPropertyList (2.3.2)
RedCloth (4.2.9)
ace-rails-ap (2.0.1)
ace-rails-ap (4.0.2)
actionmailer (4.2.6)
actionpack (= 4.2.6)
actionview (= 4.2.6)
......@@ -432,8 +432,6 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-scrollto-rails (1.4.3)
railties (> 3.1, < 5.0)
jquery-turbolinks (2.1.0)
railties (>= 3.1.0)
turbolinks
......@@ -882,7 +880,7 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.2.9)
ace-rails-ap (~> 2.0.1)
ace-rails-ap (~> 4.0.2)
activerecord-deprecated_finders (~> 1.0.3)
activerecord-session_store (~> 0.1.0)
acts-as-taggable-on (~> 3.4)
......@@ -953,7 +951,6 @@ DEPENDENCIES
influxdb (~> 0.2)
jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 4.1.0)
jquery-scrollto-rails (~> 1.4.3)
jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0)
kaminari (~> 0.16.3)
......
# This is a manifest file that'll be compiled into application.js, which will include all the files
# listed below.
#
# Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
# or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
#
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
# the compiled file.
#
# WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
# GO AFTER THE REQUIRES BELOW.
#
#= require pager
#= require jquery_nested_form
#= require_tree .
#
$(document).on 'click', '.edit-runner-link', (event) ->
event.preventDefault()
descr = $(this).closest('.runner-description').first()
descr.addClass('hide')
form = descr.next('.runner-description-form')
descrInput = form.find('input.description')
originalValue = descrInput.val()
form.removeClass('hide')
form.find('.cancel').on 'click', (event) ->
event.preventDefault()
form.addClass('hide')
descrInput.val(originalValue)
descr.removeClass('hide')
$(document).on 'click', '.assign-all-runner', ->
$(this).replaceWith('<i class="fa fa-refresh fa-spin"></i> Assign in progress..')
......
......@@ -6,6 +6,10 @@ class @ShortcutsIssuable extends ShortcutsNavigation
super()
Mousetrap.bind('a', @openSidebarDropdown.bind(@, 'assignee'))
Mousetrap.bind('m', @openSidebarDropdown.bind(@, 'milestone'))
Mousetrap.bind('r', =>
@replyWithSelectedText()
return false
)
Mousetrap.bind('j', =>
@prevIssue()
return false
......
class Dashboard::LabelsController < Dashboard::ApplicationController
def index
labels = Label.where(project_id: projects).select(:title, :color).uniq(:title)
labels = Label.where(project_id: projects).select(:id, :title, :color).uniq(:title)
respond_to do |format|
format.json { render json: labels }
......
......@@ -28,7 +28,7 @@ def index
end
def starred
@projects = current_user.starred_projects.sorted_by_activity
@projects = current_user.viewable_starred_projects.sorted_by_activity
@projects = filter_projects(@projects)
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort])
......
......@@ -25,7 +25,7 @@ def activity
def load_events
projects =
if params[:filter] == "starred"
current_user.starred_projects
current_user.viewable_starred_projects
else
current_user.authorized_projects
end
......
......@@ -27,8 +27,10 @@ def test
if !@project.empty_repo?
status, message = TestHookService.new.execute(hook, current_user)
if status
flash[:notice] = 'Hook successfully executed.'
if status && status >= 200 && status < 400
flash[:notice] = "Hook executed successfully: HTTP #{status}"
elsif status
flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}"
else
flash[:alert] = "Hook execution failed: #{message}"
end
......
......@@ -59,9 +59,9 @@ def project_was_moved_email(project_id, user_id, old_path_with_namespace)
subject: subject("Project was moved"))
end
def repository_push_email(project_id, recipient, opts = {})
def repository_push_email(project_id, opts = {})
@message =
Gitlab::Email::Message::RepositoryPush.new(self, project_id, recipient, opts)
Gitlab::Email::Message::RepositoryPush.new(self, project_id, opts)
# used in notify layout
@target_url = @message.target_url
......@@ -72,7 +72,6 @@ def repository_push_email(project_id, recipient, opts = {})
mail(from: sender(@message.author_id, @message.send_from_committer_email?),
reply_to: @message.reply_to,
to: @message.recipient,
subject: @message.subject)
end
end
......
......@@ -38,7 +38,7 @@ def execute(data, hook_name)
basic_auth: auth)
end
[(response.code >= 200 && response.code < 300), ActionView::Base.full_sanitizer.sanitize(response.to_s)]
[response.code, response.to_s]
rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
logger.error("WebHook Error => #{e}")
[false, e.to_s]
......
......@@ -81,7 +81,7 @@ def has_visible_content?
def commit(id = 'HEAD')
return nil unless exists?
commit = Gitlab::Git::Commit.find(raw_repository, id)
commit = Commit.new(commit, @project) if commit
commit = ::Commit.new(commit, @project) if commit
commit
rescue Rugged::OdbError
nil
......@@ -453,7 +453,7 @@ def readme
def version
cache.fetch(:version) do
tree(:head).blobs.find do |file|
file.name.downcase == 'version'
file.name.casecmp('version').zero?
end
end
end
......
......@@ -382,6 +382,11 @@ def authorized_projects
Project.where("projects.id IN (#{projects_union.to_sql})")
end
def viewable_starred_projects
starred_projects.where("projects.visibility_level IN (?) OR projects.id IN (#{projects_union.to_sql})",
[Project::PUBLIC, Project::INTERNAL])
end
def owned_projects
@owned_projects ||=
Project.where('namespace_id IN (?) OR namespace_id = ?',
......
......@@ -35,7 +35,7 @@ def execute
end
end
log_info("Project \"#{project.name}\" was removed")
log_info("Project \"#{project.path_with_namespace}\" was removed")
system_hook_service.execute_hooks_for(project, :destroy)
true
end
......
......@@ -11,18 +11,10 @@
= link_to admin_runner_path(runner) do
= runner.short_sha
%td
.runner-description
= runner.description
%span (#{link_to 'edit', '#', class: 'edit-runner-link'})
.runner-description-form.hide
= form_for [:admin, runner], remote: true, html: { class: 'form-inline' } do |f|
.form-group
= f.text_field :description, class: 'form-control'
= f.submit 'Save', class: 'btn'
%span (#{link_to 'cancel', '#', class: 'cancel'})
= runner.description
%td
- if runner.shared?
\-
n/a
- else
= runner.projects.count(:all)
%td
......
......@@ -27,8 +27,9 @@
%li
= link_to dashboard_todos_path, title: 'Todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('bell fw')
%span.badge.todos-pending-count
= todos_pending_count
- unless todos_pending_count == 0
%span.badge.todos-pending-count
= todos_pending_count
- if current_user.can_create_project?
%li
= link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
......
class EmailsOnPushWorker
include Sidekiq::Worker
attr_reader :email, :skip_premailer
def perform(project_id, recipients, push_data, options = {})
options.symbolize_keys!
options.reverse_merge!(
......@@ -41,11 +43,11 @@ def perform(project_id, recipients, push_data, options = {})
end
end
recipients.split(" ").each do |recipient|
recipients.split.each do |recipient|
begin
Notify.repository_push_email(
project_id,
send_email(
recipient,
project_id,
author_id: author_id,
ref: ref,
action: action,
......@@ -53,14 +55,29 @@ def perform(project_id, recipients, push_data, options = {})
reverse_compare: reverse_compare,
send_from_committer_email: send_from_committer_email,
disable_diffs: disable_diffs
).deliver_now
)
# These are input errors and won't be corrected even if Sidekiq retries
rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e
logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}")
end
end
ensure
@email = nil
compare = nil
GC.start
end
private
def send_email(recipient, project_id, options)
# Generating the body of this email can be expensive, so only do it once
@skip_premailer ||= email.present?
@email ||= Notify.repository_push_email(project_id, options)
email.to = recipient
email.add_message_id
email.header[:skip_premailer] = true if skip_premailer
email.deliver_now
end
end
require File.expand_path('../boot', __FILE__)
require 'rails/all'
require 'devise'
I18n.config.enforce_available_locales = false
Bundler.require(:default, Rails.env)
require_relative '../lib/gitlab/redis'
module Gitlab
class Application < Rails::Application
require_dependency Rails.root.join('lib/gitlab/redis')
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths.push(*%W(#{config.root}/lib
#{config.root}/app/models/hooks
#{config.root}/app/models/concerns
#{config.root}/app/models/project_services
#{config.root}/app/models/members))
# Sidekiq uses eager loading, but directories not in the standard Rails
# directories must be added to the eager load paths:
# https://github.com/mperham/sidekiq/wiki/FAQ#why-doesnt-sidekiq-autoload-my-rails-application-code
# Also, there is no need to add `lib` to autoload_paths since autoloading is
# configured to check for eager loaded paths:
# https://github.com/rails/rails/blob/v4.2.6/railties/lib/rails/engine.rb#L687
# This is a nice reference article on autoloading/eager loading:
# http://blog.arkency.com/2014/11/dont-forget-about-eager-load-when-extending-autoload
config.eager_load_paths.push(*%W(#{config.root}/lib
#{config.root}/app/models/ci
#{config.root}/app/models/hooks
#{config.root}/app/models/members
#{config.root}/app/models/project_services))
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
......
require 'gitlab' # Load lib/gitlab.rb as soon as possible
require_dependency Rails.root.join('lib/gitlab') # Load Gitlab as soon as possible
class Settings < Settingslogic
source ENV.fetch('GITLAB_CONFIG') { "#{Rails.root}/config/gitlab.yml" }
......
# GIT over HTTP
require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
require_dependency Rails.root.join('lib/gitlab/backend/grack_auth')
# GIT over SSH
require Rails.root.join("lib", "gitlab", "backend", "shell")
require_dependency Rails.root.join('lib/gitlab/backend/shell')
# GitLab shell adapter
require Rails.root.join("lib", "gitlab", "backend", "shell_adapter")
require_dependency Rails.root.join('lib/gitlab/backend/shell_adapter')
required_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version_required)
current_version = Gitlab::VersionInfo.parse(Gitlab::Shell.new.version)
......
## This patch is from rails 4.2-stable. Remove it when 4.2.6 is released
## https://github.com/rails/rails/issues/21108
module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter < AbstractAdapter
# SHOW VARIABLES LIKE 'name'
def show_variable(name)
variables = select_all("select @@#{name} as 'Value'", 'SCHEMA')
variables.first['Value'] unless variables.empty?
rescue ActiveRecord::StatementInvalid
nil
end
# MySQL is too stupid to create a temporary table for use subquery, so we have
# to give it some prompting in the form of a subsubquery. Ugh!
def subquery_for(key, select)
subsubselect = select.clone
subsubselect.projections = [key]
subselect = Arel::SelectManager.new(select.engine)
subselect.project Arel.sql(key.name)
# Materialized subquery by adding distinct
# to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
subselect.from subsubselect.distinct.as('__active_record_temp')
end
end
end
end
module ActiveRecord
module ConnectionAdapters
class MysqlAdapter < AbstractMysqlAdapter
ADAPTER_NAME = 'MySQL'.freeze
# Get the client encoding for this database
def client_encoding
return @client_encoding if @client_encoding
result = exec_query(
"select @@character_set_client",
'SCHEMA')
@client_encoding = ENCODINGS[result.rows.last.last]
end
end
end
end
......@@ -13,6 +13,19 @@ You can configure webhooks to listen for specific events like pushes, issues or
Webhooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
## Webhook endpoint tips
If you are writing your own endpoint (web server) that will receive
GitLab webhooks keep in mind the following things:
- Your endpoint should send its HTTP response as fast as possible. If
you wait too long, GitLab may decide the hook failed and retry it.
- Your endpoint should ALWAYS return a valid HTTP response. If you do
not do this then GitLab will think the hook failed and retry it.
Most HTTP libraries take care of this for you automatically but if
you are writing a low-level hook this is important to remember.
- GitLab ignores the HTTP status code returned by your endpoint.
## SSL Verification
By default, the SSL certificate of the webhook endpoint is verified based on
......
......@@ -59,7 +59,7 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps
step 'hook should be triggered' do
expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project)
expect(page).to have_selector '.flash-notice',
text: 'Hook successfully executed.'
text: 'Hook executed successfully: HTTP 200'
end
step 'I should see hook error message' do
......
Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file}
module API
class API < Grape::API
include APIGuard
......@@ -25,38 +23,39 @@ class API < Grape::API
format :json
content_type :txt, "text/plain"
helpers Helpers
mount Groups
mount GroupMembers
mount Users
mount Projects
mount Repositories
mount Issues
mount Milestones
mount Session
mount MergeRequests
mount Notes
mount Internal
mount SystemHooks
mount ProjectSnippets
mount ProjectMembers
mount DeployKeys
mount ProjectHooks
mount Services
mount Files
mount Commits
mount CommitStatus
mount Namespaces
mount Branches
mount Labels
mount Settings
mount Keys
mount Tags
mount Triggers
mount Builds
mount Variables
mount Runners
mount Licenses
# Ensure the namespace is right, otherwise we might load Grape::API::Helpers
helpers ::API::Helpers
mount ::API::Groups
mount ::API::GroupMembers
mount ::API::Users
mount ::API::Projects
mount ::API::Repositories
mount ::API::Issues
mount ::API::Milestones
mount ::API::Session
mount ::API::MergeRequests
mount ::API::Notes
mount ::API::Internal
mount ::API::SystemHooks
mount ::API::ProjectSnippets
mount ::API::ProjectMembers
mount ::API::DeployKeys
mount ::API::ProjectHooks
mount ::API::Services
mount ::API::Files
mount ::API::Commits
mount ::API::CommitStatuses
mount ::API::Namespaces
mount ::API::Branches
mount ::API::Labels
mount ::API::Settings
mount ::API::Keys
mount ::API::Tags
mount ::API::Triggers
mount ::API::Builds
mount ::API::Variables
mount ::API::Runners
mount ::API::Licenses
end
end
......@@ -2,171 +2,175 @@
require 'rack/oauth2'
module APIGuard
extend ActiveSupport::Concern
module API
module APIGuard
extend ActiveSupport::Concern
included do |base|
# OAuth2 Resource Server Authentication
use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request|
# The authenticator only fetches the raw token string
included do |base|