From 35266de2f0e91ac73995ab8ced1bbcb12e35f773 Mon Sep 17 00:00:00 2001 From: Chris McKnight Date: Wed, 6 Jan 2016 11:20:52 -0600 Subject: Updates git lfs initialize command --- doc/workflow/lfs/manage_large_binaries_with_git_lfs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md index ba91685a20b..83db44c10b1 100644 --- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md +++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md @@ -44,7 +44,7 @@ check it into your Git repository: ```bash git clone git@gitlab.example.com:group/project.git -git lfs init # initialize the Git LFS project project +git lfs install # initialize the Git LFS project project git lfs track "*.iso" # select the file extensions that you want to treat as large files ``` @@ -152,4 +152,4 @@ If you are using OS X you can use `osxkeychain` to store and encrypt your creden For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases). More details about various methods of storing the user credentials can be found -on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). \ No newline at end of file +on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). -- cgit v1.2.1 From ff1e7474ed0f210df004c714e1b83c1c2eb0d91c Mon Sep 17 00:00:00 2001 From: Andrew Collett Date: Thu, 21 Apr 2016 10:30:27 +0000 Subject: Update cas.md to reflect the current syntax, and added that gitlab-ctl reconfigure should be run. --- doc/integration/cas.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/doc/integration/cas.md b/doc/integration/cas.md index e6b2071f193..e34e306f9ac 100644 --- a/doc/integration/cas.md +++ b/doc/integration/cas.md @@ -27,17 +27,18 @@ To enable the CAS OmniAuth provider you must register your application with your ```ruby gitlab_rails['omniauth_providers'] = [ { - name: "cas3", - label: "cas", - args: { - url: 'CAS_SERVER', - login_url: '/CAS_PATH/login', - service_validate_url: '/CAS_PATH/p3/serviceValidate', - logout_url: '/CAS_PATH/logout'} } - } + "name"=> "cas3", + "label"=> "cas", + "args"=> { + "url"=> 'CAS_SERVER', + "login_url"=> '/CAS_PATH/login', + "service_validate_url"=> '/CAS_PATH/p3/serviceValidate', + "logout_url"=> '/CAS_PATH/logout' + } } ] ``` + For installations from source: @@ -57,6 +58,8 @@ To enable the CAS OmniAuth provider you must register your application with your 1. Save the configuration file. +1. Run `gitlab-ctl reconfigure` for the omnibus package. + 1. Restart GitLab for the changes to take effect. On the sign in page there should now be a CAS tab in the sign in form. -- cgit v1.2.1 From 9ab70184e3299766165017267a74f53e80b03836 Mon Sep 17 00:00:00 2001 From: DJ Mountney Date: Thu, 28 Apr 2016 12:05:45 -0700 Subject: Pass trusted_proxies to action_dispatch as IPAddrs instead of strings Without this setting your own trusted_proxies does not work. --- config/initializers/trusted_proxies.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb index b8cc025bae2..d256a16d42b 100644 --- a/config/initializers/trusted_proxies.rb +++ b/config/initializers/trusted_proxies.rb @@ -1,2 +1,3 @@ -Rails.application.config.action_dispatch.trusted_proxies = +Rails.application.config.action_dispatch.trusted_proxies = ( [ '127.0.0.1', '::1' ] + Array(Gitlab.config.gitlab.trusted_proxies) +).map { |proxy| IPAddr.new(proxy) } -- cgit v1.2.1 From c0f02aad4a1a178109a235d34bd70218c0aec86c Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Mon, 2 May 2016 16:37:12 +0700 Subject: Add snippet tab under user profile --- app/assets/javascripts/user_tabs.js.coffee | 9 ++++++++- app/controllers/users_controller.rb | 22 ++++++++++++++++++++++ app/views/users/show.html.haml | 6 ++++++ config/routes.rb | 5 +++-- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/user_tabs.js.coffee b/app/assets/javascripts/user_tabs.js.coffee index 09b7eec9104..aa798b96ede 100644 --- a/app/assets/javascripts/user_tabs.js.coffee +++ b/app/assets/javascripts/user_tabs.js.coffee @@ -26,6 +26,10 @@ # Personal projects # # +#
  • +# +# +#
  • # # #
    @@ -41,6 +45,9 @@ #
    # Projects content #
    +#
    +# Snippets content +#
    #
    # #
    @@ -100,7 +107,7 @@ class @UserTabs if action is 'activity' @loadActivities(source) - if action in ['groups', 'contributed', 'projects'] + if action in ['groups', 'contributed', 'projects', 'snippets'] @loadTab(source, action) loadTab: (source, action) -> diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2ae180c8a12..799421c185b 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -58,6 +58,19 @@ class UsersController < ApplicationController end end + def snippets + load_snippets + + respond_to do |format| + format.html { render 'show' } + format.json do + render json: { + html: view_to_html_string("snippets/_snippets", collection: @snippets) + } + end + end + end + def calendar calendar = contributions_calendar @timestamps = calendar.timestamps @@ -116,6 +129,15 @@ class UsersController < ApplicationController @groups = JoinedGroupsFinder.new(user).execute(current_user) end + def load_snippets + @snippets = SnippetsFinder.new.execute( + current_user, + filter: :by_user, + user: user, + scope: params[:scope] + ).page(params[:page]) + end + def projects_for_current_user ProjectsFinder.new.execute(current_user) end diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 3028491e5b6..a453a7fedb7 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -81,6 +81,9 @@ %li.projects-tab = link_to user_projects_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do Personal projects + %li.snippets-tab + = link_to user_snippets_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do + Snippets %div{ class: container_class } .tab-content @@ -104,6 +107,9 @@ #projects.tab-pane - # This tab is always loaded via AJAX + #snippets.tab-pane + - # This tab is always loaded via AJAX + .loading-status = spinner diff --git a/config/routes.rb b/config/routes.rb index 2f820aafed1..f6a41331ecf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -89,8 +89,6 @@ Rails.application.routes.draw do end end - get '/s/:username' => 'snippets#index', as: :user_snippets, constraints: { username: /.*/ } - # # Invites # @@ -355,6 +353,9 @@ Rails.application.routes.draw do get 'u/:username/contributed' => 'users#contributed', as: :user_contributed_projects, constraints: { username: /.*/ } + get 'u/:username/snippets' => 'users#snippets', as: :user_snippets, + constraints: { username: /.*/ } + get '/u/:username' => 'users#show', as: :user, constraints: { username: /[a-zA-Z.0-9_\-]+(? Date: Tue, 3 May 2016 13:03:10 +0200 Subject: Improve documentation and web test for web hooks I wanted to share what I learned trying to debug web hooks using netcat. --- app/controllers/projects/hooks_controller.rb | 2 +- app/models/hooks/web_hook.rb | 2 +- doc/web_hooks/web_hooks.md | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index dfa9bd259e8..366373b0f0a 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -28,7 +28,7 @@ class Projects::HooksController < Projects::ApplicationController status, message = TestHookService.new.execute(hook, current_user) if status - flash[:notice] = 'Hook successfully executed.' + flash[:notice] = "Hook successfully executed, HTTP #{status} #{message}" else flash[:alert] = "Hook execution failed: #{message}" end diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 1e3b4815596..818abbf4cc4 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -59,7 +59,7 @@ class WebHook < ActiveRecord::Base basic_auth: auth) end - [(response.code >= 200 && response.code < 300), ActionView::Base.full_sanitizer.sanitize(response.to_s)] + [response.code, ActionView::Base.full_sanitizer.sanitize(response.to_s)] rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e logger.error("WebHook Error => #{e}") [false, e.to_s] diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index c1c51302e79..6ffdb18339e 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -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 web hooks 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 -- cgit v1.2.1 From 23a3e3756a4f44aa8bd69310a2e584c1d4f7af1d Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 3 May 2016 13:40:59 +0200 Subject: Inform user about questionable hook success --- app/controllers/projects/hooks_controller.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index 366373b0f0a..9869d90831c 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -27,8 +27,10 @@ class Projects::HooksController < Projects::ApplicationController if !@project.empty_repo? status, message = TestHookService.new.execute(hook, current_user) - if status - flash[:notice] = "Hook successfully executed, HTTP #{status} #{message}" + if status && status >= 200 && status < 400 + flash[:notice] = "Hook executed successfully" + elsif status + flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}" else flash[:alert] = "Hook execution failed: #{message}" end -- cgit v1.2.1 From 6957fb7c4f0993ba1e0cbd9949a7e96c2c2def32 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 3 May 2016 13:42:56 +0200 Subject: Always mention HTTP status --- app/controllers/projects/hooks_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index 9869d90831c..47524b1cf0b 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -28,7 +28,7 @@ class Projects::HooksController < Projects::ApplicationController status, message = TestHookService.new.execute(hook, current_user) if status && status >= 200 && status < 400 - flash[:notice] = "Hook executed successfully" + flash[:notice] = "Hook executed successfully: HTTP #{status}" elsif status flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}" else -- cgit v1.2.1 From faaab2aef8e7f6b06f8f04dc68596e1229d507db Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 3 May 2016 11:58:43 -0500 Subject: Add to label :id to response --- app/controllers/dashboard/labels_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb index 23a4ef21ea2..2a88350a4ca 100644 --- a/app/controllers/dashboard/labels_controller.rb +++ b/app/controllers/dashboard/labels_controller.rb @@ -1,6 +1,6 @@ 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 } -- cgit v1.2.1 From 17d23283a119fcfc2f6ac070bb5df8d913abf2e7 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 4 May 2016 12:46:53 -0500 Subject: Restore "r" shortcut --- app/assets/javascripts/shortcuts_issuable.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/shortcuts_issuable.coffee b/app/assets/javascripts/shortcuts_issuable.coffee index ad9b3c1c6bf..ccb42ab2168 100644 --- a/app/assets/javascripts/shortcuts_issuable.coffee +++ b/app/assets/javascripts/shortcuts_issuable.coffee @@ -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 -- cgit v1.2.1 From f18ec70743375024aa7ec7bb86c437ca9198e729 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 4 May 2016 17:05:16 -0400 Subject: Backport changes from gitlab-org/gitlab-ee!372 Mostly replaces several Spinach tests with RSpec Feature tests. --- app/helpers/projects_helper.rb | 3 +- features/project/create.feature | 16 +----- features/steps/project/create.rb | 26 +-------- spec/factories/projects.rb | 10 ++-- ...eloper_views_empty_project_instructions_spec.rb | 63 ++++++++++++++++++++++ spec/helpers/projects_helper_spec.rb | 10 ++-- 6 files changed, 80 insertions(+), 48 deletions(-) create mode 100644 spec/features/projects/developer_views_empty_project_instructions_spec.rb diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 3d5e61d2c18..62e8c03cc81 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -209,7 +209,8 @@ module ProjectsHelper end def default_url_to_repo(project = @project) - if default_clone_protocol == "ssh" + case default_clone_protocol + when 'ssh' project.ssh_url_to_repo else project.http_url_to_repo diff --git a/features/project/create.feature b/features/project/create.feature index 27136798e36..67336d73bf7 100644 --- a/features/project/create.feature +++ b/features/project/create.feature @@ -6,21 +6,9 @@ Feature: Project Create @javascript Scenario: User create a project - Given I sign in as a user - When I visit new project page - And I have an ssh key - And fill project form with valid data - Then I should see project page - And I should see empty project instuctions - - @javascript - Scenario: Empty project instructions Given I sign in as a user And I have an ssh key When I visit new project page And fill project form with valid data - Then I see empty project instuctions - And I click on HTTP - Then Remote url should update to http link - And If I click on SSH - Then Remote url should update to ssh link + Then I should see project page + And I should see empty project instructions diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb index 422b151eaa2..5f5f806df36 100644 --- a/features/steps/project/create.rb +++ b/features/steps/project/create.rb @@ -13,33 +13,9 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps expect(current_path).to eq namespace_project_path(Project.last.namespace, Project.last) end - step 'I should see empty project instuctions' do + step 'I should see empty project instructions' do expect(page).to have_content "git init" expect(page).to have_content "git remote" expect(page).to have_content Project.last.url_to_repo end - - step 'I see empty project instuctions' do - expect(page).to have_content "git init" - expect(page).to have_content "git remote" - expect(page).to have_content Project.last.url_to_repo - end - - step 'I click on HTTP' do - find('#clone-dropdown').click - find('.http-selector').click - end - - step 'Remote url should update to http link' do - expect(page).to have_content "git remote add origin #{Project.last.http_url_to_repo}" - end - - step 'If I click on SSH' do - find('#clone-dropdown').click - find('.ssh-selector').click - end - - step 'Remote url should update to ssh link' do - expect(page).to have_content "git remote add origin #{Project.last.url_to_repo}" - end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index c14b99606ba..5338c88dd84 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -61,6 +61,12 @@ FactoryGirl.define do trait :private do visibility_level Gitlab::VisibilityLevel::PRIVATE end + + trait :empty_repo do + after(:create) do |project| + project.create_repository + end + end end # Project with empty repository @@ -68,9 +74,7 @@ FactoryGirl.define do # This is a case when you just created a project # but not pushed any code there yet factory :project_empty_repo, parent: :empty_project do - after :create do |project| - project.create_repository - end + empty_repo end # Project with test repository diff --git a/spec/features/projects/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/developer_views_empty_project_instructions_spec.rb new file mode 100644 index 00000000000..0c51fe72ca4 --- /dev/null +++ b/spec/features/projects/developer_views_empty_project_instructions_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +feature 'Developer views empty project instructions', feature: true do + let(:project) { create(:empty_project, :empty_repo) } + let(:developer) { create(:user) } + + background do + project.team << [developer, :developer] + + login_as(developer) + end + + context 'without an SSH key' do + scenario 'defaults to HTTP' do + visit_project + + expect_instructions_for('http') + end + + scenario 'switches to SSH', js: true do + visit_project + + select_protocol('SSH') + + expect_instructions_for('ssh') + end + end + + context 'with an SSH key' do + background do + create(:personal_key, user: developer) + end + + scenario 'defaults to SSH' do + visit_project + + expect_instructions_for('ssh') + end + + scenario 'switches to HTTP', js: true do + visit_project + + select_protocol('HTTP') + + expect_instructions_for('http') + end + end + + def visit_project + visit namespace_project_path(project.namespace, project) + end + + def select_protocol(protocol) + find('#clone-dropdown').click + find(".#{protocol.downcase}-selector").click + end + + def expect_instructions_for(protocol) + msg = :"#{protocol.downcase}_url_to_repo" + + expect(page).to have_content("git clone #{project.send(msg)}") + end +end diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 62389188d2c..6f7e2ae78fd 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -88,18 +88,18 @@ describe ProjectsHelper do end describe 'default_clone_protocol' do - describe 'using HTTP' do + context 'when user is not logged in and gitlab protocol is HTTP' do it 'returns HTTP' do - expect(helper).to receive(:current_user).and_return(nil) + allow(helper).to receive(:current_user).and_return(nil) expect(helper.send(:default_clone_protocol)).to eq('http') end end - describe 'using HTTPS' do + context 'when user is not logged in and gitlab protocol is HTTPS' do it 'returns HTTPS' do - allow(Gitlab.config.gitlab).to receive(:protocol).and_return('https') - expect(helper).to receive(:current_user).and_return(nil) + stub_config_setting(protocol: 'https') + allow(helper).to receive(:current_user).and_return(nil) expect(helper.send(:default_clone_protocol)).to eq('https') end -- cgit v1.2.1 From e4c64855e8531a9375de1d64a95f2e593b80c2bd Mon Sep 17 00:00:00 2001 From: Jakub Jirutka Date: Wed, 27 Apr 2016 23:37:07 +0200 Subject: Don't read otp_secret_encryption_key from hardcoded path in models/user Variable `Gitlab::Application.config.secret_key_base` is set in config/initializers/secret_token.rb. It's very bad practice to use hard-coded paths inside an application and really unnecessary in this case. --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index ab48f8f1960..a468b6ea075 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -85,7 +85,7 @@ class User < ActiveRecord::Base default_value_for :theme_id, gitlab_config.default_theme devise :two_factor_authenticatable, - otp_secret_encryption_key: File.read(Rails.root.join('.secret')).chomp + otp_secret_encryption_key: Gitlab::Application.config.secret_key_base alias_attribute :two_factor_enabled, :otp_required_for_login devise :two_factor_backupable, otp_number_of_backup_codes: 10 -- cgit v1.2.1 From e37b31456774c92fd718f7ef0a576266ffcca894 Mon Sep 17 00:00:00 2001 From: DJ Mountney Date: Wed, 4 May 2016 15:49:39 -0700 Subject: Add tests for setting trusted_proxies Each test reloads the trusted_proxies initializer, which in turn will set Rails.application.config.action_dispatch.trusted_proxies to something new. This will leak into the other tests, but the middleware that it is used in has already been loaded for the whole test suite, so it should have no impact. --- spec/initializers/trusted_proxies_spec.rb | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 spec/initializers/trusted_proxies_spec.rb diff --git a/spec/initializers/trusted_proxies_spec.rb b/spec/initializers/trusted_proxies_spec.rb new file mode 100644 index 00000000000..4bb149f25ff --- /dev/null +++ b/spec/initializers/trusted_proxies_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe 'trusted_proxies', lib: true do + context 'with default config' do + before do + set_trusted_proxies([]) + end + + it 'preserves private IPs as remote_ip' do + request = stub_request('HTTP_X_FORWARDED_FOR' => '10.1.5.89') + expect(request.remote_ip).to eq('10.1.5.89') + end + + it 'filters out localhost from remote_ip' do + request = stub_request('HTTP_X_FORWARDED_FOR' => '1.1.1.1, 10.1.5.89, 127.0.0.1') + expect(request.remote_ip).to eq('10.1.5.89') + end + end + + context 'with private IP ranges added' do + before do + set_trusted_proxies([ "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" ]) + end + + it 'filters out private and local IPs from remote_ip' do + request = stub_request('HTTP_X_FORWARDED_FOR' => '1.2.3.6, 1.1.1.1, 10.1.5.89, 127.0.0.1') + expect(request.remote_ip).to eq('1.1.1.1') + end + end + + context 'with proxy IP added' do + before do + set_trusted_proxies([ "60.98.25.47" ]) + end + + it 'filters out proxy IP from remote_ip' do + request = stub_request('HTTP_X_FORWARDED_FOR' => '1.2.3.6, 1.1.1.1, 60.98.25.47, 127.0.0.1') + expect(request.remote_ip).to eq('1.1.1.1') + end + end + + def stub_request(headers = {}) + ActionDispatch::RemoteIp.new(Proc.new { }, false, Rails.application.config.action_dispatch.trusted_proxies).call(headers) + ActionDispatch::Request.new(headers) + end + + def set_trusted_proxies(proxies = []) + stub_config_setting('trusted_proxies' => proxies) + load File.join(__dir__, '../../config/initializers/trusted_proxies.rb') + end +end -- cgit v1.2.1 From 8dc19494c3fdae366daa8849b5e2a3f58f98878c Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Thu, 5 May 2016 13:26:36 +0700 Subject: Remove unused code, update spec, and update changelog --- CHANGELOG | 1 + app/controllers/snippets_controller.rb | 20 +------------------- spec/routing/routing_spec.rb | 8 -------- 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 558897ad892..6c044192d06 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.8.0 (unreleased) + - Snippets tab under user profile. !4001 (Long Nguyen) - Remove future dates from contribution calendar graph. - 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 diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 2daceed039b..f0bd842ca56 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -10,29 +10,11 @@ class SnippetsController < ApplicationController # Allow destroy snippet before_action :authorize_admin_snippet!, only: [:destroy] - skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw] + skip_before_action :authenticate_user!, only: [:show, :raw] layout 'snippets' respond_to :html - def index - if params[:username].present? - @user = User.find_by(username: params[:username]) - - render_404 and return unless @user - - @snippets = SnippetsFinder.new.execute(current_user, { - filter: :by_user, - user: @user, - scope: params[:scope] }). - page(params[:page]) - - render 'index' - else - redirect_to(current_user ? dashboard_snippets_path : explore_snippets_path) - end - end - def new @snippet = PersonalSnippet.new end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 1527eddfa48..9deffd0a1e3 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -27,18 +27,10 @@ end # PUT /snippets/:id(.:format) snippets#update # DELETE /snippets/:id(.:format) snippets#destroy describe SnippetsController, "routing" do - it "to #user_index" do - expect(get("/s/User")).to route_to('snippets#index', username: 'User') - end - it "to #raw" do expect(get("/snippets/1/raw")).to route_to('snippets#raw', id: '1') end - it "to #index" do - expect(get("/snippets")).to route_to('snippets#index') - end - it "to #create" do expect(post("/snippets")).to route_to('snippets#create') end -- cgit v1.2.1 From ae29ec31e4f71d722e975bfce945aaed7e0d0bd1 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Thu, 5 May 2016 14:57:34 +0700 Subject: Remove unused view and update redirect when destroy snippet --- app/controllers/snippets_controller.rb | 2 +- app/views/snippets/index.html.haml | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 app/views/snippets/index.html.haml diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index f0bd842ca56..2c038bdfda5 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -43,7 +43,7 @@ class SnippetsController < ApplicationController @snippet.destroy - redirect_to snippets_path + redirect_to dashboard_snippets_path end def raw diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml deleted file mode 100644 index 7e4918a6085..00000000000 --- a/app/views/snippets/index.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title "By #{@user.name}", "Snippets" - -%ol.breadcrumb - %li - = link_to snippets_path do - Snippets - %li - = @user.name - .pull-right.hidden-xs - = link_to user_path(@user) do - #{@user.name} profile page - -= render 'snippets' -- cgit v1.2.1 From e449a6c05c734ff9e38e13013591d07d03c0fff6 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 4 May 2016 13:14:11 +0200 Subject: Added documentation on how to instrument methods [ci skip] --- doc/development/instrumentation.md | 129 +++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 6 deletions(-) diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md index c1cf2e77c26..9168c70945a 100644 --- a/doc/development/instrumentation.md +++ b/doc/development/instrumentation.md @@ -1,12 +1,125 @@ # Instrumenting Ruby Code -GitLab Performance Monitoring allows instrumenting of custom blocks of Ruby -code. This can be used to measure the time spent in a specific part of a larger -chunk of code. The resulting data is stored as a field in the transaction that -executed the block. +GitLab Performance Monitoring allows instrumenting of both methods and custom +blocks of Ruby code. Method instrumentation is the primary form of +instrumentation with block-based instrumentation only being used when we want to +drill down to specific regions of code within a method. -To start measuring a block of Ruby code you should use `Gitlab::Metrics.measure` -and give it a name: +## Instrumenting Methods + +Instrumenting methods is done by using the `Gitlab::Metrics::Instrumentation` +module. This module offers a few different methods that can be used to +instrument code: + +* `instrument_method`: instruments a single class method. +* `instrument_instance_method`: instruments a single instance method. +* `instrument_class_hierarchy`: given a Class this method will recursively + instrument all sub-classes (both class and instance methods). +* `instrument_methods`: instruments all public class methods of a Module. +* `instrument_instance_methods`: instruments all public instance methods of a + Module. + +To remove the need for typing the full `Gitlab::Metrics::Instrumentation` +namespace you can use the `configure` class method. This method simply yields +the supplied block while passing `Gitlab::Metrics::Instrumentation` as its +argument. An example: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_method(Foo, :bar) + conf.instrument_method(Foo, :baz) +end +``` + +Using this method is in general preferred over directly calling the various +instrumentation methods. + +Method instrumentation should be added in the initializer +`config/initializers/metrics.rb`. + +### Examples + +Instrumenting a single method: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_method(User, :find_by) +end +``` + +Instrumenting an entire class hierarchy: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_class_hierarchy(ActiveRecord::Base) +end +``` + +Instrumenting all public class methods: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_methods(User) +end +``` + +### Checking Instrumented Methods + +The easiest way to check if a method has been instrumented is to check its +source location. For example: + +``` +method = Rugged::TagCollection.instance_method(:[]) + +method.source_location +``` + +If the source location points to `lib/gitlab/metrics/instrumentation.rb` you +know the method has been instrumented. + +If you're using Pry you can use the `$` command to display the source code of a +method (along with its source location), this is easier than running the above +Ruby code. In case of the above snippet you'd run the following: + +``` +$ Rugged::TagCollection#[] +``` + +This will print out something along the lines of: + +``` +From: /path/to/your/gitlab/lib/gitlab/metrics/instrumentation.rb @ line 148: +Owner: # +Visibility: public +Number of lines: 21 + +def #{name}(#{args_signature}) + trans = Gitlab::Metrics::Instrumentation.transaction + + if trans + start = Time.now + retval = super + duration = (Time.now - start) * 1000.0 + + if duration >= Gitlab::Metrics.method_call_threshold + trans.increment(:method_duration, duration) + + trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES, + { duration: duration }, + method: #{label.inspect}) + end + + retval + else + super + end +end +``` + +## Instrumenting Ruby Blocks + +Measuring blocks of Ruby code is done by calling `Gitlab::Metrics.measure` and +passing it a block. For example: ```ruby Gitlab::Metrics.measure(:foo) do @@ -14,6 +127,10 @@ Gitlab::Metrics.measure(:foo) do end ``` +The block is executed and the execution time is stored as a set of fields in the +currently running transaction. If no transaction is present the block is yielded +without measuring anything. + 3 values are measured for a block: 1. The real time elapsed, stored in NAME_real_time. -- cgit v1.2.1 From d028863eda8b97f6e4db129ef57f0d3a2130c9b3 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 4 May 2016 18:21:57 -0300 Subject: Sanitize milestones and label titles --- app/models/label.rb | 5 +++++ app/models/milestone.rb | 5 +++++ spec/lib/banzai/filter/milestone_reference_filter_spec.rb | 2 +- spec/models/label_spec.rb | 8 ++++++++ spec/models/milestone_spec.rb | 8 ++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/models/label.rb b/app/models/label.rb index 60bdce32952..0b34911a4e9 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -117,6 +117,11 @@ class Label < ActiveRecord::Base LabelsHelper::text_color_for_bg(self.color) end + def title= value + value = Sanitize.clean(value.to_s) if value + write_attribute(:title, Sanitize.clean(value)) + end + private def label_format_reference(format = :id) diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 986184dd301..ed81791c69c 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -129,6 +129,11 @@ class Milestone < ActiveRecord::Base nil end + def title= value + value = Sanitize.clean(value.to_s) if value + write_attribute(:title, value) + end + # Sorts the issues for the given IDs. # # This method runs a single SQL query using a CASE statement to update the diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb index ebf3d7489b5..5beb61dac5c 100644 --- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb @@ -43,7 +43,7 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do milestone.update_attribute(:title, %{">whateverwhatever" end it 'includes default classes' do diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 0614ca1e7c9..b61c55a3f6d 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -55,6 +55,14 @@ describe Label, models: true do end end + describe "#title" do + let(:label) { create(:label, title: "test") } + + it "sanitizes title" do + expect(label.title).to eq("test") + end + end + describe '#to_reference' do context 'using id' do it 'returns a String reference to the object' do diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 72a4ea70228..e2c89a4b3e6 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -34,6 +34,14 @@ describe Milestone, models: true do let(:issue) { create(:issue) } let(:user) { create(:user) } + describe "#title" do + let(:milestone) { create(:milestone, title: "test") } + + it "sanitizes title" do + expect(milestone.title).to eq("test") + end + end + describe "unique milestone title per project" do it "shouldn't accept the same title in a project twice" do new_milestone = Milestone.new(project: milestone.project, title: milestone.title) -- cgit v1.2.1 From ab4671f26ab789b1e3647754911197aaba1f81bb Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Sat, 7 May 2016 01:31:56 +0200 Subject: Fix adding a todo for private group members Fixes #14002 --- CHANGELOG | 1 + app/models/concerns/mentionable.rb | 4 ++-- spec/services/todo_service_spec.rb | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 78d6c1ec2b2..c68a11a91f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,7 @@ v 8.8.0 (unreleased) - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) - 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) v 8.7.3 - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 98f71ae8cb0..b381d225485 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -43,8 +43,8 @@ module Mentionable self end - def all_references(current_user = self.author, text = nil) - ext = Gitlab::ReferenceExtractor.new(self.project, current_user, self.author) + def all_references(current_user = nil, text = nil) + ext = Gitlab::ReferenceExtractor.new(self.project, current_user || self.author, self.author) if text ext.analyze(text) diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index 82b7fbfa816..a075496ee63 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -55,6 +55,25 @@ describe TodoService, services: true do should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) should_not_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) end + + context 'when a private group is mentioned' do + let(:group) { create :group, :private } + let(:project) { create :project, :private, group: group } + let(:issue) { create :issue, author: author, project: project, description: group.to_reference } + + before do + group.add_owner(author) + group.add_user(member, Gitlab::Access::DEVELOPER) + group.add_user(john_doe, Gitlab::Access::DEVELOPER) + + service.new_issue(issue, author) + end + + it 'creates a todo for group members' do + should_create_todo(user: member, target: issue) + should_create_todo(user: john_doe, target: issue) + end + end end describe '#update_issue' do -- cgit v1.2.1 From 8d8189be9d4121bb5a18489e1bee4992efc8f120 Mon Sep 17 00:00:00 2001 From: Morton Fox Date: Sat, 7 May 2016 00:06:06 -0400 Subject: Update Subscription and EE links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c1a29c3bb1e..d1e5bcf256c 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,11 @@ There are two editions of GitLab: On [about.gitlab.com](https://about.gitlab.com/) you can find more information about: -- [Subscriptions](https://about.gitlab.com/subscription/) +- [Subscriptions](https://about.gitlab.com/pricing/) - [Consultancy](https://about.gitlab.com/consultancy/) - [Community](https://about.gitlab.com/community/) - [Hosted GitLab.com](https://about.gitlab.com/gitlab-com/) use GitLab as a free service -- [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/) with additional features aimed at larger organizations. +- [GitLab Enterprise Edition](https://about.gitlab.com/features/#enterprise) with additional features aimed at larger organizations. - [GitLab CI](https://about.gitlab.com/gitlab-ci/) a continuous integration (CI) server that is easy to integrate with GitLab. ## Requirements -- cgit v1.2.1 From adf9a51899b02f7adc678dca7909201500f05026 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 7 May 2016 08:41:10 -0700 Subject: Escape HTML in commit titles in system note messages Closes #17348 --- CHANGELOG | 1 + app/services/system_note_service.rb | 6 +++++- spec/services/system_note_service_spec.rb | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 78d6c1ec2b2..ebc27c21575 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.8.0 (unreleased) - Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen) - Project#open_branches has been cleaned up and no longer loads entire records into memory. + - Escape HTML in commit titles in system note messages - Log to application.log when an admin starts and stops impersonating a user - Updated gitlab_git to 10.1.0 - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 82a0e2fd1f5..4bdb1b0c074 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -351,7 +351,7 @@ class SystemNoteService # Returns an Array of Strings def self.new_commit_summary(new_commits) new_commits.collect do |commit| - "* #{commit.short_id} - #{commit.title}" + "* #{commit.short_id} - #{escape_html(commit.title)}" end end @@ -433,4 +433,8 @@ class SystemNoteService body = "Moved #{direction} #{cross_reference}" create_note(noteable: noteable, project: project, author: author, note: body) end + + def self.escape_html(text) + Rack::Utils.escape_html(text) + end end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 240eae10052..5fbf2ae5247 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -506,6 +506,15 @@ describe SystemNoteService, services: true do end end + describe '.new_commit_summary' do + it 'escapes HTML titles' do + commit = double(title: '
    This is a test
    ', short_id: '12345678') + escaped = '* 12345678 - <pre>This is a test</pre>' + + expect(described_class.new_commit_summary([commit])).to eq([escaped]) + end + end + include JiraServiceHelper describe 'JIRA integration' do -- cgit v1.2.1 From ffda8a1a0eb273e62fcb0197f352400946571778 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Sun, 8 May 2016 15:27:33 +0700 Subject: user routings refactor --- app/controllers/snippets_controller.rb | 22 ++++++++++++-- app/views/search/results/_snippet_blob.html.haml | 2 +- app/views/search/results/_snippet_title.html.haml | 2 +- app/views/shared/snippets/_snippet.html.haml | 2 +- app/views/snippets/index.html.haml | 13 ++++++++ app/views/users/calendar.html.haml | 2 +- app/views/users/show.html.haml | 12 ++++---- config/routes.rb | 37 +++++++++++------------ spec/routing/routing_spec.rb | 4 +++ 9 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 app/views/snippets/index.html.haml diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 2c038bdfda5..2a17c1f34db 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -10,11 +10,29 @@ class SnippetsController < ApplicationController # Allow destroy snippet before_action :authorize_admin_snippet!, only: [:destroy] - skip_before_action :authenticate_user!, only: [:show, :raw] + skip_before_action :authenticate_user!, only: [:index, :show, :raw] layout 'snippets' respond_to :html + def index + if params[:username].present? + @user = User.find_by(username: params[:username]) + + render_404 and return unless @user + + @snippets = SnippetsFinder.new.execute(current_user, { + filter: :by_user, + user: @user, + scope: params[:scope] }). + page(params[:page]) + + render 'index' + else + redirect_to(current_user ? dashboard_snippets_path : explore_snippets_path) + end + end + def new @snippet = PersonalSnippet.new end @@ -43,7 +61,7 @@ class SnippetsController < ApplicationController @snippet.destroy - redirect_to dashboard_snippets_path + redirect_to snippets_path end def raw diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml index c9b7bd154af..6b7e06f2b21 100644 --- a/app/views/search/results/_snippet_blob.html.haml +++ b/app/views/search/results/_snippet_blob.html.haml @@ -6,7 +6,7 @@ %span = snippet.title by - = link_to user_snippets_path(snippet.author) do + = link_to snippets_user_path(snippet.author) do = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: '' = snippet.author_name %span.light #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml index c414acb6a11..8c884926db5 100644 --- a/app/views/search/results/_snippet_title.html.haml +++ b/app/views/search/results/_snippet_title.html.haml @@ -17,7 +17,7 @@ = "##{snippet_title.id}" %span by - = link_to user_snippets_path(snippet_title.author) do + = link_to snippets_user_path(snippet_title.author) do = image_tag avatar_icon(snippet_title.author_email), class: "avatar avatar-inline s16", alt: '' = snippet_title.author_name %span.light #{time_ago_with_tooltip(snippet_title.created_at)} diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml index c96dfefe17f..e6a7a7777b0 100644 --- a/app/views/shared/snippets/_snippet.html.haml +++ b/app/views/shared/snippets/_snippet.html.haml @@ -16,6 +16,6 @@ = link_to snippet.project.name_with_namespace, namespace_project_path(snippet.project.namespace, snippet.project) .snippet-info - = link_to user_snippets_path(snippet.author) do + = link_to snippets_user_path(snippet.author) do = snippet.author_name authored #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml new file mode 100644 index 00000000000..8aa3d490fa3 --- /dev/null +++ b/app/views/snippets/index.html.haml @@ -0,0 +1,13 @@ + - page_title "By #{@user.name}", "Snippets" + + %ol.breadcrumb + %li + = link_to snippets_path do + Snippets + %li + = @user.name + .pull-right.hidden-xs + = link_to user_path(@user) do + #{@user.name} profile page + + = render 'snippets' diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml index 1de71f37d1a..6ff4eb79b05 100644 --- a/app/views/users/calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -4,7 +4,7 @@ #{@timestamps.to_json}, #{@starting_year}, #{@starting_month}, - '#{user_calendar_activities_path}' + '#{calendar_activities_user_path}' ); .calendar-hint Summary of issues, merge requests, and push events diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 2ccdf843a6c..e894a8e9395 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -70,19 +70,19 @@ %ul.nav-links.center.user-profile-nav %li.js-activity-tab - = link_to user_calendar_activities_path, data: {target: 'div#activity', action: 'activity', toggle: 'tab'} do + = link_to calendar_activities_user_path, data: {target: 'div#activity', action: 'activity', toggle: 'tab'} do Activity %li.js-groups-tab - = link_to user_groups_path, data: {target: 'div#groups', action: 'groups', toggle: 'tab'} do + = link_to groups_user_path, data: {target: 'div#groups', action: 'groups', toggle: 'tab'} do Groups %li.js-contributed-tab - = link_to user_contributed_projects_path, data: {target: 'div#contributed', action: 'contributed', toggle: 'tab'} do + = link_to contributed_projects_user_path, data: {target: 'div#contributed', action: 'contributed', toggle: 'tab'} do Contributed projects %li.projects-tab - = link_to user_projects_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do + = link_to projects_user_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do Personal projects %li.snippets-tab - = link_to user_snippets_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do + = link_to snippets_user_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do Snippets %div{ class: container_class } @@ -90,7 +90,7 @@ #activity.tab-pane .gray-content-block.calender-block.white.second-block.hidden-xs %div{ class: container_class } - .user-calendar{data: {href: user_calendar_path}} + .user-calendar{data: {href: calendar_user_path}} %h4.center.light %i.fa.fa-spinner.fa-spin .user-calendar-activities diff --git a/config/routes.rb b/config/routes.rb index 2bfaa2c2af6..533c3b98e8e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,6 +91,9 @@ Rails.application.routes.draw do end end + get '/s/:username', to: redirect('/u/:username/snippets'), + constraints: { username: /[a-zA-Z.0-9_\-]+(? 'users#calendar', as: :user_calendar, - constraints: { username: /.*/ } - - get 'u/:username/calendar_activities' => 'users#calendar_activities', as: :user_calendar_activities, - constraints: { username: /.*/ } - - get 'u/:username/groups' => 'users#groups', as: :user_groups, - constraints: { username: /.*/ } - - get 'u/:username/projects' => 'users#projects', as: :user_projects, - constraints: { username: /.*/ } - - get 'u/:username/contributed' => 'users#contributed', as: :user_contributed_projects, - constraints: { username: /.*/ } - - get 'u/:username/snippets' => 'users#snippets', as: :user_snippets, - constraints: { username: /.*/ } - - get '/u/:username' => 'users#show', as: :user, - constraints: { username: /[a-zA-Z.0-9_\-]+(? Date: Sun, 8 May 2016 15:29:51 +0700 Subject: Fix routing error --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 533c3b98e8e..299b0dd1acf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,7 +91,7 @@ Rails.application.routes.draw do end end - get '/s/:username', to: redirect('/u/:username/snippets'), + get '/s/:username', to: redirect('/u/%{username}/snippets'), constraints: { username: /[a-zA-Z.0-9_\-]+(? Date: Sun, 8 May 2016 09:38:24 +0100 Subject: Update build triggers API documentation (#10153) Update build triggers API documentation [ci skip] * Ensure updated/deleted timestamps are consistent --- doc/api/build_triggers.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/api/build_triggers.md b/doc/api/build_triggers.md index 4a12e962b62..0881a7d7a90 100644 --- a/doc/api/build_triggers.md +++ b/doc/api/build_triggers.md @@ -101,8 +101,18 @@ DELETE /projects/:id/triggers/:token | Attribute | Type | required | Description | |-----------|---------|----------|--------------------------| | `id` | integer | yes | The ID of a project | -| `token` | string | yes | The `token` of a project | +| `token` | string | yes | The `token` of a trigger | ``` curl -X DELETE -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d" ``` + +```json +{ + "created_at": "2015-12-23T16:25:56.760Z", + "deleted_at": "2015-12-24T12:32:20.100Z", + "last_used": null, + "token": "7b9148c158980bbd9bcea92c17522d", + "updated_at": "2015-12-24T12:32:20.100Z" +} +``` -- cgit v1.2.1 From 29089352e388882a799daff7623fc7213f60e1c9 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Sun, 8 May 2016 20:48:07 +0700 Subject: Routing refactoring --- app/views/search/results/_snippet_blob.html.haml | 2 +- app/views/search/results/_snippet_title.html.haml | 2 +- app/views/shared/snippets/_snippet.html.haml | 2 +- app/views/users/calendar.html.haml | 2 +- app/views/users/show.html.haml | 12 ++++++------ config/routes.rb | 23 ++++++++++------------- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml index 6b7e06f2b21..c9b7bd154af 100644 --- a/app/views/search/results/_snippet_blob.html.haml +++ b/app/views/search/results/_snippet_blob.html.haml @@ -6,7 +6,7 @@ %span = snippet.title by - = link_to snippets_user_path(snippet.author) do + = link_to user_snippets_path(snippet.author) do = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: '' = snippet.author_name %span.light #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml index 8c884926db5..c414acb6a11 100644 --- a/app/views/search/results/_snippet_title.html.haml +++ b/app/views/search/results/_snippet_title.html.haml @@ -17,7 +17,7 @@ = "##{snippet_title.id}" %span by - = link_to snippets_user_path(snippet_title.author) do + = link_to user_snippets_path(snippet_title.author) do = image_tag avatar_icon(snippet_title.author_email), class: "avatar avatar-inline s16", alt: '' = snippet_title.author_name %span.light #{time_ago_with_tooltip(snippet_title.created_at)} diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml index e6a7a7777b0..c96dfefe17f 100644 --- a/app/views/shared/snippets/_snippet.html.haml +++ b/app/views/shared/snippets/_snippet.html.haml @@ -16,6 +16,6 @@ = link_to snippet.project.name_with_namespace, namespace_project_path(snippet.project.namespace, snippet.project) .snippet-info - = link_to snippets_user_path(snippet.author) do + = link_to user_snippets_path(snippet.author) do = snippet.author_name authored #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml index 6ff4eb79b05..1de71f37d1a 100644 --- a/app/views/users/calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -4,7 +4,7 @@ #{@timestamps.to_json}, #{@starting_year}, #{@starting_month}, - '#{calendar_activities_user_path}' + '#{user_calendar_activities_path}' ); .calendar-hint Summary of issues, merge requests, and push events diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index d5f482f7168..9017fd54fcc 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -70,19 +70,19 @@ %ul.nav-links.center.user-profile-nav %li.js-activity-tab - = link_to calendar_activities_user_path, data: {target: 'div#activity', action: 'activity', toggle: 'tab'} do + = link_to user_calendar_activities_path, data: {target: 'div#activity', action: 'activity', toggle: 'tab'} do Activity %li.js-groups-tab - = link_to groups_user_path, data: {target: 'div#groups', action: 'groups', toggle: 'tab'} do + = link_to user_groups_path, data: {target: 'div#groups', action: 'groups', toggle: 'tab'} do Groups %li.js-contributed-tab - = link_to contributed_projects_user_path, data: {target: 'div#contributed', action: 'contributed', toggle: 'tab'} do + = link_to user_contributed_projects_path, data: {target: 'div#contributed', action: 'contributed', toggle: 'tab'} do Contributed projects %li.projects-tab - = link_to projects_user_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do + = link_to user_projects_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do Personal projects %li.snippets-tab - = link_to snippets_user_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do + = link_to user_snippets_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do Snippets %div{ class: container_class } @@ -90,7 +90,7 @@ #activity.tab-pane .row-content-block.calender-block.white.second-block.hidden-xs %div{ class: container_class } - .user-calendar{data: {href: calendar_user_path}} + .user-calendar{data: {href: user_calendar_path}} %h4.center.light %i.fa.fa-spinner.fa-spin .user-calendar-activities diff --git a/config/routes.rb b/config/routes.rb index 299b0dd1acf..594bab204fd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -343,19 +343,16 @@ Rails.application.routes.draw do end end - resources(:users, - path: 'u', - param: :username, - constraints: { username: /[a-zA-Z.0-9_\-]+(? Date: Sun, 8 May 2016 22:06:19 +0700 Subject: Add specs for user routing and update spec for user controller --- spec/controllers/users_controller_spec.rb | 22 ++++++++++++++++++ spec/routing/routing_spec.rb | 37 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 8045c8b940d..c61ec174665 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -112,4 +112,26 @@ describe UsersController do expect(response).to render_template('calendar_activities') end end + + describe 'GET #snippets' do + before do + sign_in(user) + end + + context 'format html' do + it 'renders snippets page' do + get :snippets, username: user.username + expect(response.status).to eq(200) + expect(response).to render_template('show') + end + end + + context 'format json' do + it 'response with snippets json data' do + get :snippets, username: user.username, format: :json + expect(response.status).to eq(200) + expect(JSON.parse(response.body)).to have_key('html') + end + end + end end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 543088fa088..8530a2f31d5 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -1,5 +1,42 @@ require 'spec_helper' +# user GET /u/:username/ +# user_groups GET /u/:username/groups(.:format) +# user_projects GET /u/:username/projects(.:format) +# user_contributed_projects GET /u/:username/contributed(.:format) +# user_snippets GET /u/:username/snippets(.:format) +# user_calendar GET /u/:username/calendar(.:format) +# user_calendar_activities GET /u/:username/calendar_activities(.:format) +describe UsersController, "routing" do + it "to #show" do + expect(get("/u/User")).to route_to('users#show', username: 'User') + end + + it "to #groups" do + expect(get("/u/User/groups")).to route_to('users#groups', username: 'User') + end + + it "to #projects" do + expect(get("/u/User/projects")).to route_to('users#projects', username: 'User') + end + + it "to #contributed" do + expect(get("/u/User/contributed")).to route_to('users#contributed', username: 'User') + end + + it "to #snippets" do + expect(get("/u/User/snippets")).to route_to('users#snippets', username: 'User') + end + + it "to #calendar" do + expect(get("/u/User/calendar")).to route_to('users#calendar', username: 'User') + end + + it "to #calendar_activities" do + expect(get("/u/User/calendar_activities")).to route_to('users#calendar_activities', username: 'User') + end +end + # search GET /search(.:format) search#show describe SearchController, "routing" do it "to #show" do -- cgit v1.2.1 From ed2a7a1ec616fa948d3e24d77bfc7626ae55e9b9 Mon Sep 17 00:00:00 2001 From: Benedikt Huss Date: Sat, 7 May 2016 21:12:15 +0200 Subject: Fix build notification on merge request page change even if the build status didn't change --- CHANGELOG | 3 +++ app/assets/javascripts/merge_request_widget.js.coffee | 9 +++++---- app/views/projects/merge_requests/widget/_heading.html.haml | 7 +------ spec/javascripts/merge_request_widget_spec.js.coffee | 6 ++++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e9b3e7b097d..e9204d32bde 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,9 @@ 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) +v 8.7.4 + - Fix always showing build notification message when switching between merge requests + v 8.7.3 - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented - Merge request widget displays TeamCity build state and code coverage correctly again. diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index 17a5a057a94..f58647988a2 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -9,11 +9,12 @@ class @MergeRequestWidget constructor: (@opts) -> $('#modal_merge_info').modal(show: false) @firstCICheck = true - @readyForCICheck = true + @readyForCICheck = false clearInterval @fetchBuildStatusInterval @clearEventListeners() @addEventListeners() + @getCIStatus(false) @pollCIStatus() notifyPermissions() @@ -71,7 +72,7 @@ class @MergeRequestWidget if data.status is '' return - if @firstCiCheck || data.status isnt @opts.ci_status and data.status? + if @firstCICheck || data.status isnt @opts.ci_status and data.status? @opts.ci_status = data.status @showCIStatus data.status if data.coverage @@ -79,7 +80,7 @@ class @MergeRequestWidget # The first check should only update the UI, a notification # should only be displayed on status changes - if showNotification and not @firstCiCheck + if showNotification and not @firstCICheck status = @ciLabelForStatus(data.status) if status is "preparing" @@ -102,7 +103,7 @@ class @MergeRequestWidget @close() Turbolinks.visit _this.opts.builds_path ) - @firstCiCheck = false + @firstCICheck = false showCIStatus: (state) -> $('.ci_widget').hide() diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml index 2ec0d20a879..4d381754610 100644 --- a/app/views/projects/merge_requests/widget/_heading.html.haml +++ b/app/views/projects/merge_requests/widget/_heading.html.haml @@ -41,9 +41,4 @@ .ci_widget.ci-error{style: "display:none"} = icon("times-circle") - Could not connect to the CI server. Please check your settings and try again. - - :javascript - $(function() { - merge_request_widget.getCIStatus(false); - }); + Could not connect to the CI server. Please check your settings and try again. \ No newline at end of file diff --git a/spec/javascripts/merge_request_widget_spec.js.coffee b/spec/javascripts/merge_request_widget_spec.js.coffee index c0bd8a29e43..92b7eeb1116 100644 --- a/spec/javascripts/merge_request_widget_spec.js.coffee +++ b/spec/javascripts/merge_request_widget_spec.js.coffee @@ -47,3 +47,9 @@ describe 'MergeRequestWidget', -> spy = spyOn(@class, 'showCICoverage').and.stub() @class.getCIStatus(false) expect(spy).not.toHaveBeenCalled() + + it 'should not display a notification on the first check after the widget has been created', -> + spy = spyOn(window, 'notify') + @class = new MergeRequestWidget(@opts) + @class.getCIStatus(true) + expect(spy).not.toHaveBeenCalled() -- cgit v1.2.1 From 0e29653f51b439eb018cefe434a4a57db4239cf4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 8 May 2016 15:45:04 -0400 Subject: Remove `wall_enabled` field from Project --- app/models/project.rb | 2 -- config/gitlab.teatro.yml | 1 - db/migrate/20160508194200_remove_wall_enabled_from_projects.rb | 5 +++++ db/schema.rb | 3 +-- spec/factories/projects.rb | 1 - spec/models/project_spec.rb | 1 - 6 files changed, 6 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20160508194200_remove_wall_enabled_from_projects.rb diff --git a/app/models/project.rb b/app/models/project.rb index dfd1e54ecf7..86a7835c5f6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -10,7 +10,6 @@ # updated_at :datetime # creator_id :integer # issues_enabled :boolean default(TRUE), not null -# wall_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null # namespace_id :integer @@ -67,7 +66,6 @@ class Project < ActiveRecord::Base default_value_for :merge_requests_enabled, gitlab_config_features.merge_requests default_value_for :builds_enabled, gitlab_config_features.builds default_value_for :wiki_enabled, gitlab_config_features.wiki - default_value_for :wall_enabled, false default_value_for :snippets_enabled, gitlab_config_features.snippets default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled } diff --git a/config/gitlab.teatro.yml b/config/gitlab.teatro.yml index f0656400beb..01c8dc5ff98 100644 --- a/config/gitlab.teatro.yml +++ b/config/gitlab.teatro.yml @@ -15,7 +15,6 @@ production: &base issues: true merge_requests: true wiki: true - wall: false snippets: false visibility_level: "private" # can be "private" | "internal" | "public" diff --git a/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb b/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb new file mode 100644 index 00000000000..aa560bc0f0c --- /dev/null +++ b/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb @@ -0,0 +1,5 @@ +class RemoveWallEnabledFromProjects < ActiveRecord::Migration + def change + remove_column :projects, :wall_enabled, :boolean, default: true, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 7683aad968c..71d953afe30 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160421130527) do +ActiveRecord::Schema.define(version: 20160508194200) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -728,7 +728,6 @@ ActiveRecord::Schema.define(version: 20160421130527) do t.datetime "updated_at" t.integer "creator_id" t.boolean "issues_enabled", default: true, null: false - t.boolean "wall_enabled", default: true, null: false t.boolean "merge_requests_enabled", default: true, null: false t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index c14b99606ba..ecd0e44dd62 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -10,7 +10,6 @@ # updated_at :datetime # creator_id :integer # issues_enabled :boolean default(TRUE), not null -# wall_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null # namespace_id :integer diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 5b1cf71337e..3a8a6c2c166 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -10,7 +10,6 @@ # updated_at :datetime # creator_id :integer # issues_enabled :boolean default(TRUE), not null -# wall_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null # namespace_id :integer -- cgit v1.2.1 From 9cc0937b3a41caca89fa6722149248a8f7b0a447 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Sun, 8 May 2016 15:33:34 -0600 Subject: Enable the Rubocop DeprecatedClassMethods cop This reports uses of `File.exists?` and `Dir.exists?`, which were both deprecated in Ruby and will eventually be removed in favor of `.exist?`. Also fixes all existing uses of the deprecated methods. --- .rubocop.yml | 2 +- app/models/ci/build.rb | 2 +- app/models/merge_request.rb | 2 +- config/boot.rb | 2 +- config/initializers/carrierwave.rb | 2 +- lib/gitlab/backend/shell.rb | 2 +- lib/gitlab/redis.rb | 2 +- spec/config/mail_room_spec.rb | 2 +- spec/services/projects/create_service_spec.rb | 4 ++-- spec/services/projects/destroy_service_spec.rb | 8 ++++---- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 9f179efa3ce..b49b60d6767 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -770,7 +770,7 @@ Lint/DefEndAlignment: # Check for deprecated class method calls. Lint/DeprecatedClassMethods: - Enabled: false + Enabled: true # Check for duplicate method definitions. Lint/DuplicateMethods: diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 4bc3a225e2c..073ec9dd89e 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -238,7 +238,7 @@ module Ci end def recreate_trace_dir - unless Dir.exists?(dir_to_trace) + unless Dir.exist?(dir_to_trace) FileUtils.mkdir_p(dir_to_trace) end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 4175e1e5fba..365ccc90b40 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -544,7 +544,7 @@ class MergeRequest < ActiveRecord::Base end def ref_is_fetched? - File.exists?(File.join(project.repository.path_to_repo, ref_path)) + File.exist?(File.join(project.repository.path_to_repo, ref_path)) end def ensure_ref_fetched diff --git a/config/boot.rb b/config/boot.rb index 4489e58688c..f2830ae3166 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -3,4 +3,4 @@ require 'rubygems' # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index df28d30d750..0d278717d6e 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -2,7 +2,7 @@ CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/ aws_file = Rails.root.join('config', 'aws.yml') -if File.exists?(aws_file) +if File.exist?(aws_file) AWS_CONFIG = YAML.load(File.read(aws_file))[Rails.env] CarrierWave.configure do |config| diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 132f9cd1966..3e3986d6382 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -180,7 +180,7 @@ module Gitlab # exists?('gitlab/cookies.git') # def exists?(dir_name) - File.exists?(full_path(dir_name)) + File.exist?(full_path(dir_name)) end protected diff --git a/lib/gitlab/redis.rb b/lib/gitlab/redis.rb index 5c352c96de5..f7db7a6391c 100644 --- a/lib/gitlab/redis.rb +++ b/lib/gitlab/redis.rb @@ -42,7 +42,7 @@ module Gitlab config_file = File.expand_path('../../../config/resque.yml', __FILE__) @url = "redis://localhost:6379" - if File.exists?(config_file) + if File.exist?(config_file) @url =YAML.load_file(config_file)[rails_env] end end diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb index 462afb24f08..6fad7e2b9e7 100644 --- a/spec/config/mail_room_spec.rb +++ b/spec/config/mail_room_spec.rb @@ -43,7 +43,7 @@ describe "mail_room.yml" do redis_config_file = Rails.root.join('config', 'resque.yml') redis_url = - if File.exists?(redis_config_file) + if File.exist?(redis_config_file) YAML.load_file(redis_config_file)[Rails.env] else "redis://localhost:6379" diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index e43903dbd3c..fd114359467 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -64,7 +64,7 @@ describe Projects::CreateService, services: true do @path = ProjectWiki.new(@project, @user).send(:path_to_repo) end - it { expect(File.exists?(@path)).to be_truthy } + it { expect(File.exist?(@path)).to be_truthy } end context 'wiki_enabled false does not create wiki repository directory' do @@ -74,7 +74,7 @@ describe Projects::CreateService, services: true do @path = ProjectWiki.new(@project, @user).send(:path_to_repo) end - it { expect(File.exists?(@path)).to be_falsey } + it { expect(File.exist?(@path)).to be_falsey } end end diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index 1ec27077717..a5cb6f382e4 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -13,8 +13,8 @@ describe Projects::DestroyService, services: true do end it { expect(Project.all).not_to include(project) } - it { expect(Dir.exists?(path)).to be_falsey } - it { expect(Dir.exists?(remove_path)).to be_falsey } + it { expect(Dir.exist?(path)).to be_falsey } + it { expect(Dir.exist?(remove_path)).to be_falsey } end context 'Sidekiq fake' do @@ -24,8 +24,8 @@ describe Projects::DestroyService, services: true do end it { expect(Project.all).not_to include(project) } - it { expect(Dir.exists?(path)).to be_falsey } - it { expect(Dir.exists?(remove_path)).to be_truthy } + it { expect(Dir.exist?(path)).to be_falsey } + it { expect(Dir.exist?(remove_path)).to be_truthy } end def destroy_project(project, user, params) -- cgit v1.2.1 From 4be77d0b057e3b26f48fbaee947bf8f91a755f41 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 8 May 2016 19:09:33 -0700 Subject: Improve multiple branch push performance by memoizing permission checking If you attempt to push thousands of branches at once, the 60-second timeout will occur because GitAccess checking does a lot of work to check if the user has permission to push to a branch. This changes does two things: 1. Instead of making 1 DB query per branch push, use a memoized list of protected branches to check 2. Memoize what permissions the user has to perform on this project On a test of 10,000 branch pushes, this prevents gitlab-shell from hitting the 60-second timeout. Closes #17225 --- CHANGELOG | 1 + app/models/project.rb | 2 +- lib/gitlab/git_access.rb | 7 ++++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e85d3c88b28..822fa4be565 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ v 8.8.0 (unreleased) - Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen) - Project#open_branches has been cleaned up and no longer loads entire records into memory. - Escape HTML in commit titles in system note messages + - Improve multiple branch push performance by memoizing permission checking - Log to application.log when an admin starts and stops impersonating a user - Updated gitlab_git to 10.1.0 - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists diff --git a/app/models/project.rb b/app/models/project.rb index dfd1e54ecf7..5b556a22755 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -767,7 +767,7 @@ class Project < ActiveRecord::Base # Check if current branch name is marked as protected in the system def protected_branch?(branch_name) - protected_branches.where(name: branch_name).any? + protected_branch_names.include?(branch_name) end def developers_can_push_to_protected_branch?(branch_name) diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 6cb41239871..d2a0e316cbe 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -122,6 +122,11 @@ module Gitlab build_status_object(true) end + def can_user_do_action?(action) + @permission_cache ||= {} + @permission_cache[action] ||= user.can?(action, project) + end + def change_access_check(change) oldrev, newrev, ref = change.split(' ') @@ -135,7 +140,7 @@ module Gitlab :push_code end - unless user.can?(action, project) + unless can_user_do_action?(action) status = case action when :force_push_code_to_protected_branches -- cgit v1.2.1 From 14b36f91d9d803850f59fe49961d6d6a9d540aab Mon Sep 17 00:00:00 2001 From: Artem Sidorenko Date: Tue, 3 May 2016 17:33:43 +0200 Subject: Use the proper GitLab URL for links in Wiki --- CHANGELOG | 1 + app/models/project_wiki.rb | 2 +- lib/gitlab/url_builder.rb | 2 +- spec/lib/gitlab/url_builder_spec.rb | 2 +- spec/models/project_wiki_spec.rb | 4 +++- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 822fa4be565..b07b7da3300 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -36,6 +36,7 @@ v 8.8.0 (unreleased) v 8.7.4 - Fix always showing build notification message when switching between merge requests + - Fix links on wiki pages for relative url setups. !4026 (Artem Sidorenko) v 8.7.3 - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 7c1a61bb0bf..c91cb70ae25 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -40,7 +40,7 @@ class ProjectWiki end def wiki_base_path - ["/", @project.path_with_namespace, "/wikis"].join('') + [Gitlab.config.gitlab.url, "/", @project.path_with_namespace, "/wikis"].join('') end # Returns the Gollum::Wiki object. diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb index 2bbbd3074e8..67a09d5abf5 100644 --- a/lib/gitlab/url_builder.rb +++ b/lib/gitlab/url_builder.rb @@ -62,7 +62,7 @@ module Gitlab end def wiki_page_url - "#{Gitlab.config.gitlab.url}#{object.wiki.wiki_base_path}/#{object.slug}" + "#{object.wiki.wiki_base_path}/#{object.slug}" end end end diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index bf11472407a..c8d3bc01395 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -112,7 +112,7 @@ describe Gitlab::UrlBuilder, lib: true do wiki_page = build(:wiki_page) url = described_class.build(wiki_page) - expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}" + expect(url).to eq "#{Gitlab.config.gitlab.url}/#{wiki_page.wiki.project.path_with_namespace}/wikis/#{wiki_page.slug}" end end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 532e3f013fd..ea659f417f2 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -38,7 +38,9 @@ describe ProjectWiki, models: true do describe "#wiki_base_path" do it "returns the wiki base path" do - wiki_base_path = "/#{project.path_with_namespace}/wikis" + gitlab_url = Gitlab.config.gitlab.url + wiki_base_path = "#{gitlab_url}/#{project.path_with_namespace}/wikis" + expect(subject.wiki_base_path).to eq(wiki_base_path) end end -- cgit v1.2.1 From 5bd32954f619b521496bca200a0ed31615b8e736 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 9 May 2016 13:52:20 +0200 Subject: Remove space --- doc/web_hooks/web_hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 6ffdb18339e..45506ac1d7c 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -16,7 +16,7 @@ Webhooks can be used to update an external issue tracker, trigger CI builds, upd ## Webhook endpoint tips If you are writing your own endpoint (web server) that will receive -GitLab web hooks keep in mind the following things: +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. -- cgit v1.2.1 From 607996c664ddfb67befaf372b108081169ebeaea Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 9 May 2016 13:56:15 +0200 Subject: Remove broken inline runner description edit form --- app/assets/javascripts/ci/application.js.coffee | 28 ------------------------- app/views/admin/runners/_runner.html.haml | 12 ++--------- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/app/assets/javascripts/ci/application.js.coffee b/app/assets/javascripts/ci/application.js.coffee index 05aa0f366bb..ca24c1d759f 100644 --- a/app/assets/javascripts/ci/application.js.coffee +++ b/app/assets/javascripts/ci/application.js.coffee @@ -1,34 +1,6 @@ -# 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(' Assign in progress..') diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index 6745e58deca..97b6ec1f85d 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -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? - \- + = '-' - else = runner.projects.count(:all) %td -- cgit v1.2.1 From a19508d6b79aa3a399f479b09b52b35b5289a92a Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 9 May 2016 13:58:43 +0200 Subject: Fix test failures --- features/steps/project/hooks.rb | 2 +- spec/models/hooks/web_hook_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb index b1ffe7f7b4c..13c0713669a 100644 --- a/features/steps/project/hooks.rb +++ b/features/steps/project/hooks.rb @@ -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 diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index 37a27d73aab..f9bab487b96 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -95,13 +95,13 @@ describe WebHook, models: true do it "handles 200 status code" do WebMock.stub_request(:post, project_hook.url).to_return(status: 200, body: "Success") - expect(project_hook.execute(@data, 'push_hooks')).to eq([true, 'Success']) + expect(project_hook.execute(@data, 'push_hooks')).to eq([200, 'Success']) end it "handles 2xx status codes" do WebMock.stub_request(:post, project_hook.url).to_return(status: 201, body: "Success") - expect(project_hook.execute(@data, 'push_hooks')).to eq([true, 'Success']) + expect(project_hook.execute(@data, 'push_hooks')).to eq([201, 'Success']) end end end -- cgit v1.2.1 From 5364400741b7d041c945ccca98283bc465d5a87c Mon Sep 17 00:00:00 2001 From: cnam-dep Date: Wed, 24 Feb 2016 00:59:32 +0300 Subject: API: Expose Issue#user_notes_count --- CHANGELOG | 3 +++ app/models/concerns/issuable.rb | 4 ++++ doc/api/issues.md | 15 ++++++++++----- lib/api/entities.rb | 2 +- spec/requests/api/issues_spec.rb | 15 +++++++++++++++ 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b07b7da3300..567b5717171 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -51,6 +51,9 @@ v 8.7.2 - Label titles in filters are now escaped properly v 8.7.1 + - API: Expose Issue#user_notes_count (Anton Popov) + +v 8.7.1 (unreleased) - Throttle the update of `project.last_activity_at` to 1 minute. !3848 - Fix .gitlab-ci.yml parsing issue when hidde job is a template without script definition. !3849 - Fix license detection to detect all license files, not only known licenses. !3878 diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 2e4efc4e8d8..7a3db742030 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -160,6 +160,10 @@ module Issuable notes.awards.where(note: "thumbsup").count end + def user_notes_count + notes.user.count + end + def subscribed_without_subscriptions?(user) participants(user).include?(user) end diff --git a/doc/api/issues.md b/doc/api/issues.md index 3e78149f442..fc7a7ae0c0c 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -77,7 +77,8 @@ Example response: "created_at" : "2016-01-04T15:31:51.081Z", "iid" : 6, "labels" : [], - "subscribed" : false + "subscribed" : false, + "user_notes_count": 1 } ] ``` @@ -154,7 +155,8 @@ Example response: "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", - "subscribed" : false + "subscribed" : false, + "user_notes_count": 1 } ] ``` @@ -216,7 +218,8 @@ Example response: "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", - "subscribed": false + "subscribed": false, + "user_notes_count": 1 } ``` @@ -271,7 +274,8 @@ Example response: "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, - "subscribed" : true + "subscribed" : true, + "user_notes_count": 0 } ``` @@ -329,7 +333,8 @@ Example response: "id" : 85, "assignee" : null, "milestone" : null, - "subscribed" : true + "subscribed" : true, + "user_notes_count": 0 } ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 716ca6f7ed9..42f623c5a3a 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -170,10 +170,10 @@ module API expose :label_names, as: :labels expose :milestone, using: Entities::Milestone expose :assignee, :author, using: Entities::UserBasic - expose :subscribed do |issue, options| issue.subscribed?(options[:current_user]) end + expose :user_notes_count end class MergeRequest < ProjectEntity diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index f88e39cad9e..008bcae1747 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -39,6 +39,7 @@ describe API::API, api: true do let!(:empty_milestone) do create(:milestone, title: '2.0.0', project: project) end + let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) } before { project.team << [user, :reporter] } @@ -128,6 +129,13 @@ describe API::API, api: true do expect(json_response).to be_an Array expect(json_response.length).to eq(0) end + + it 'should return an count notes in issue' do + get api("/issues", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['user_notes_count']).to eq(1) + end end end @@ -229,6 +237,13 @@ describe API::API, api: true do expect(json_response.length).to eq(1) expect(json_response.first['id']).to eq(closed_issue.id) end + + it 'should return an count notes in issue' do + get api("#{base_url}/issues", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['user_notes_count']).to eq(1) + end end describe "GET /projects/:id/issues/:issue_id" do -- cgit v1.2.1 From f5240f9703fea9902ac4304b8e12daed5c21820d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 15 Mar 2016 16:17:24 +0100 Subject: Expose MergeRequest#user_notes_count in the API and use the method in issues list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- CHANGELOG | 4 +-- app/views/projects/issues/_issue.html.haml | 14 +++------ .../merge_requests/_merge_request.html.haml | 14 +++------ doc/api/merge_requests.md | 22 +++++++++----- lib/api/entities.rb | 2 +- spec/requests/api/issues_spec.rb | 34 +++++++++++++--------- spec/requests/api/merge_requests_spec.rb | 28 ++++++++++++++++++ 7 files changed, 73 insertions(+), 45 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 567b5717171..aeade934b46 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,7 @@ v 8.8.0 (unreleased) - Added button to toggle whitespaces changes on diff view - Backport GitHub Enterprise import support from EE - Create tags using Rugged for performance reasons. !3745 + - 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) - Added multiple colors for labels in dropdowns when dups happen. @@ -51,9 +52,6 @@ v 8.7.2 - Label titles in filters are now escaped properly v 8.7.1 - - API: Expose Issue#user_notes_count (Anton Popov) - -v 8.7.1 (unreleased) - Throttle the update of `project.last_activity_at` to 1 minute. !3848 - Fix .gitlab-ci.yml parsing issue when hidde job is a template without script definition. !3849 - Fix license detection to detect all license files, not only known licenses. !3878 diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 9ad86ed71c9..5cf70ea3bb7 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -28,16 +28,10 @@ = downvotes - note_count = issue.notes.user.nonawards.count - - if note_count > 0 - %li - = link_to issue_path(issue) + "#notes" do - = icon('comments') - = note_count - - else - %li - = link_to issue_path(issue) + "#notes", class: "issue-no-comments" do - = icon('comments') - = note_count + %li + = link_to issue_path(issue, anchor: 'notes'), class: ('issue-no-comments' if note_count.zero?) do + = icon('comments') + = note_count .issue-info #{issue.to_reference} · diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index e740fe8c84d..73c6a95f5ca 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -36,16 +36,10 @@ = downvotes - note_count = merge_request.mr_and_commit_notes.user.nonawards.count - - if note_count > 0 - %li - = link_to merge_request_path(merge_request) + "#notes" do - = icon('comments') - = note_count - - else - %li - = link_to merge_request_path(merge_request) + "#notes", class: "merge-request-no-comments" do - = icon('comments') - = note_count + %li + = link_to merge_request_path(merge_request, anchor: 'notes'), class: ('merge-request-no-comments' if note_count.zero?) do + = icon('comments') + = note_count .merge-request-info #{merge_request.to_reference} · diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 2057f9d77aa..8217e30fe25 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -67,7 +67,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : false + "subscribed" : false, + "user_notes_count": 1 } ] ``` @@ -130,7 +131,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -230,6 +232,7 @@ Parameters: "merge_when_build_succeeds": true, "merge_status": "can_be_merged", "subscribed" : true, + "user_notes_count": 1, "changes": [ { "old_path": "VERSION", @@ -308,7 +311,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 0 } ``` @@ -378,7 +382,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -472,7 +477,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -537,7 +543,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -602,7 +609,8 @@ Example response: "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "created_at" : "2016-01-04T15:31:51.081Z", "iid" : 6, - "labels" : [] + "labels" : [], + "user_notes_count": 1 }, ] ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 42f623c5a3a..2870a6a40ef 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -187,10 +187,10 @@ module API expose :milestone, using: Entities::Milestone expose :merge_when_build_succeeds expose :merge_status - expose :subscribed do |merge_request, options| merge_request.subscribed?(options[:current_user]) end + expose :user_notes_count end class MergeRequestChanges < MergeRequest diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 008bcae1747..9dd43f4fab3 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -39,7 +39,7 @@ describe API::API, api: true do let!(:empty_milestone) do create(:milestone, title: '2.0.0', project: project) end - let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) } + let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) } before { project.team << [user, :reporter] } @@ -129,13 +129,6 @@ describe API::API, api: true do expect(json_response).to be_an Array expect(json_response.length).to eq(0) end - - it 'should return an count notes in issue' do - get api("/issues", user) - expect(response.status).to eq(200) - expect(json_response).to be_an Array - expect(json_response.first['user_notes_count']).to eq(1) - end end end @@ -237,18 +230,31 @@ describe API::API, api: true do expect(json_response.length).to eq(1) expect(json_response.first['id']).to eq(closed_issue.id) end + end + + describe "GET /projects/:id/issues/:issue_id" do + it 'exposes known attributes' do + get api("/projects/#{project.id}/issues/#{issue.id}", user) - it 'should return an count notes in issue' do - get api("#{base_url}/issues", user) expect(response.status).to eq(200) - expect(json_response).to be_an Array - expect(json_response.first['user_notes_count']).to eq(1) + expect(json_response['id']).to eq(issue.id) + expect(json_response['iid']).to eq(issue.iid) + expect(json_response['project_id']).to eq(issue.project.id) + expect(json_response['title']).to eq(issue.title) + expect(json_response['description']).to eq(issue.description) + expect(json_response['state']).to eq(issue.state) + expect(json_response['created_at']).to be_present + expect(json_response['updated_at']).to be_present + expect(json_response['labels']).to eq(issue.label_names) + expect(json_response['milestone']).to be_a Hash + expect(json_response['assignee']).to be_a Hash + expect(json_response['author']).to be_a Hash + expect(json_response['user_notes_count']).to be(1) end - end - describe "GET /projects/:id/issues/:issue_id" do it "should return a project issue by id" do get api("/projects/#{project.id}/issues/#{issue.id}", user) + expect(response.status).to eq(200) expect(json_response['title']).to eq(issue.title) expect(json_response['iid']).to eq(issue.iid) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 1fa7e76894f..4b0111df149 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -113,6 +113,34 @@ describe API::API, api: true do end describe "GET /projects/:id/merge_requests/:merge_request_id" do + it 'exposes known attributes' do + get api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user) + + expect(response.status).to eq(200) + expect(json_response['id']).to eq(merge_request.id) + expect(json_response['iid']).to eq(merge_request.iid) + expect(json_response['project_id']).to eq(merge_request.project.id) + expect(json_response['title']).to eq(merge_request.title) + expect(json_response['description']).to eq(merge_request.description) + expect(json_response['state']).to eq(merge_request.state) + expect(json_response['created_at']).to be_present + expect(json_response['updated_at']).to be_present + expect(json_response['labels']).to eq(merge_request.label_names) + expect(json_response['milestone']).to be_nil + expect(json_response['assignee']).to be_a Hash + expect(json_response['author']).to be_a Hash + expect(json_response['target_branch']).to eq(merge_request.target_branch) + expect(json_response['source_branch']).to eq(merge_request.source_branch) + expect(json_response['upvotes']).to eq(0) + expect(json_response['downvotes']).to eq(0) + expect(json_response['source_project_id']).to eq(merge_request.source_project.id) + expect(json_response['target_project_id']).to eq(merge_request.target_project.id) + expect(json_response['work_in_progress']).to be_falsy + expect(json_response['merge_when_build_succeeds']).to be_falsy + expect(json_response['merge_status']).to eq('can_be_merged') + expect(json_response['user_notes_count']).to be(2) + end + it "should return merge_request" do get api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user) expect(response.status).to eq(200) -- cgit v1.2.1 From 32811d98fe2893a0671fe22c4aebf8bd254b7709 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 9 May 2016 11:58:20 -0300 Subject: Make model sanitization methods one liners --- CHANGELOG | 1 + app/models/label.rb | 5 ++--- app/models/milestone.rb | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 925740e5d98..fe56dd97ee6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ v 8.8.0 (unreleased) - Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project - Updated search UI - Display informative message when new milestone is created + - Sanitize milestones and labels titles - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea) - Added button to toggle whitespaces changes on diff view - Backport GitLab Enterprise support from EE diff --git a/app/models/label.rb b/app/models/label.rb index 0b34911a4e9..c551ceef64e 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -117,9 +117,8 @@ class Label < ActiveRecord::Base LabelsHelper::text_color_for_bg(self.color) end - def title= value - value = Sanitize.clean(value.to_s) if value - write_attribute(:title, Sanitize.clean(value)) + def title=(value) + write_attribute(:title, Sanitize.clean(value.to_s)) if value.present? end private diff --git a/app/models/milestone.rb b/app/models/milestone.rb index ed81791c69c..15a786210fa 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -129,9 +129,8 @@ class Milestone < ActiveRecord::Base nil end - def title= value - value = Sanitize.clean(value.to_s) if value - write_attribute(:title, value) + def title=(value) + write_attribute(:title, Sanitize.clean(value.to_s)) if value.present? end # Sorts the issues for the given IDs. -- cgit v1.2.1 From 63c45fa75b2fb6519106417d58fe879db352b812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 9 May 2016 15:21:23 +0000 Subject: Revert "Merge branch 'patch-1' into 'master'" This reverts merge request !4030 --- doc/api/notes.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/api/notes.md b/doc/api/notes.md index a6b5b1787fd..7aa1c2155bf 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -15,7 +15,7 @@ GET /projects/:id/issues/:issue_id/notes Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of an issue (not ID) +- `issue_id` (required) - The ID of an issue ```json [ @@ -73,7 +73,7 @@ GET /projects/:id/issues/:issue_id/notes/:note_id Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of a project issue (not ID) +- `issue_id` (required) - The ID of a project issue - `note_id` (required) - The ID of an issue note ### Create new issue note @@ -87,7 +87,7 @@ POST /projects/:id/issues/:issue_id/notes Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of an issue (not ID) +- `issue_id` (required) - The ID of an issue - `body` (required) - The content of a note - `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z @@ -102,7 +102,7 @@ PUT /projects/:id/issues/:issue_id/notes/:note_id Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of an issue (not ID) +- `issue_id` (required) - The ID of an issue - `note_id` (required) - The ID of a note - `body` (required) - The content of a note @@ -120,7 +120,7 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `id` | integer | yes | The ID of a project | -| `issue_id` | integer | yes | The IID of an issue | +| `issue_id` | integer | yes | The ID of an issue | | `note_id` | integer | yes | The ID of a note | ```bash -- cgit v1.2.1 From f1479b56b71bef63517b90fcde99e6508e9c54af Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Mon, 9 May 2016 18:00:28 +0200 Subject: Remove the annotate gem and delete old annotations In 8278b763d96ef10c6494409b18b7eb541463af29 the default behaviour of annotation has changes, which was causing a lot of noise in diffs. We decided in #17382 that it is better to get rid of the whole annotate gem, and instead let people look at schema.rb for the columns in a table. Fixes: #17382 --- Gemfile | 1 - Gemfile.lock | 6 +- app/models/abuse_report.rb | 12 ---- app/models/appearance.rb | 13 ----- app/models/application_setting.rb | 52 ----------------- app/models/audit_event.rb | 14 ----- app/models/broadcast_message.rb | 14 ----- app/models/ci/build.rb | 37 ------------ app/models/ci/commit.rb | 22 -------- app/models/ci/runner.rb | 19 ------- app/models/ci/runner_project.rb | 12 ---- app/models/ci/trigger.rb | 13 ----- app/models/ci/trigger_request.rb | 12 ---- app/models/ci/variable.rb | 14 ----- app/models/commit_status.rb | 37 ------------ app/models/deploy_key.rb | 15 ----- app/models/deploy_keys_project.rb | 11 ---- app/models/email.rb | 11 ---- app/models/event.rb | 16 ------ app/models/forked_project_link.rb | 11 ---- app/models/generic_commit_status.rb | 37 ------------ app/models/group.rb | 17 ------ app/models/hooks/project_hook.rb | 22 -------- app/models/hooks/service_hook.rb | 22 -------- app/models/hooks/system_hook.rb | 22 -------- app/models/hooks/web_hook.rb | 22 -------- app/models/identity.rb | 12 ---- app/models/issue.rb | 24 -------- app/models/key.rb | 15 ----- app/models/label.rb | 14 ----- app/models/label_link.rb | 12 ---- app/models/lfs_object.rb | 12 ---- app/models/lfs_objects_project.rb | 11 ---- app/models/member.rb | 19 ------- app/models/members/group_member.rb | 19 ------- app/models/members/project_member.rb | 19 ------- app/models/merge_request.rb | 30 ---------- app/models/merge_request_diff.rb | 15 ----- app/models/milestone.rb | 15 ----- app/models/namespace.rb | 17 ------ app/models/note.rb | 21 ------- app/models/notification_setting.rb | 13 ----- app/models/oauth_access_token.rb | 15 ----- app/models/personal_snippet.rb | 16 ------ app/models/project.rb | 45 --------------- app/models/project_group_link.rb | 12 ---- app/models/project_import_data.rb | 12 ---- app/models/project_services/asana_service.rb | 24 -------- app/models/project_services/assembla_service.rb | 24 -------- app/models/project_services/bamboo_service.rb | 24 -------- app/models/project_services/buildkite_service.rb | 24 -------- .../project_services/builds_email_service.rb | 24 -------- app/models/project_services/campfire_service.rb | 24 -------- app/models/project_services/ci_service.rb | 24 -------- .../custom_issue_tracker_service.rb | 24 -------- app/models/project_services/drone_ci_service.rb | 24 -------- .../project_services/emails_on_push_service.rb | 24 -------- .../project_services/external_wiki_service.rb | 24 -------- app/models/project_services/flowdock_service.rb | 24 -------- app/models/project_services/gemnasium_service.rb | 24 -------- app/models/project_services/gitlab_ci_service.rb | 24 -------- .../gitlab_issue_tracker_service.rb | 24 -------- app/models/project_services/hipchat_service.rb | 24 -------- app/models/project_services/irker_service.rb | 24 -------- .../project_services/issue_tracker_service.rb | 24 -------- app/models/project_services/jira_service.rb | 24 -------- .../project_services/pivotaltracker_service.rb | 24 -------- app/models/project_services/pushover_service.rb | 24 -------- app/models/project_services/redmine_service.rb | 24 -------- app/models/project_services/slack_service.rb | 24 -------- app/models/project_services/teamcity_service.rb | 24 -------- app/models/project_snippet.rb | 16 ------ app/models/protected_branch.rb | 12 ---- app/models/release.rb | 12 ---- app/models/security_event.rb | 14 ----- app/models/sent_notification.rb | 14 ----- app/models/service.rb | 24 -------- app/models/snippet.rb | 16 ------ app/models/spam_log.rb | 17 ------ app/models/subscription.rb | 13 ----- app/models/todo.rb | 18 ------ app/models/user.rb | 65 ---------------------- app/models/users_star_project.rb | 11 ---- spec/factories/abuse_reports.rb | 12 ---- spec/factories/broadcast_messages.rb | 14 ----- spec/factories/forked_project_links.rb | 11 ---- spec/factories/label_links.rb | 12 ---- spec/factories/labels.rb | 13 ----- spec/factories/lfs_objects.rb | 12 ---- spec/factories/lfs_objects_projects.rb | 11 ---- spec/factories/merge_requests.rb | 29 ---------- spec/factories/notes.rb | 21 ------- spec/factories/oauth_access_tokens.rb | 15 ----- spec/factories/projects.rb | 39 ------------- spec/factories/releases.rb | 12 ---- spec/factories/todos.rb | 18 ------ spec/models/abuse_report_spec.rb | 12 ---- spec/models/application_setting_spec.rb | 46 --------------- spec/models/broadcast_message_spec.rb | 14 ----- spec/models/ci/commit_spec.rb | 18 ------ spec/models/ci/runner_project_spec.rb | 12 ---- spec/models/ci/runner_spec.rb | 19 ------- spec/models/ci/trigger_spec.rb | 13 ----- spec/models/ci/variable_spec.rb | 14 ----- spec/models/commit_status_spec.rb | 34 ----------- spec/models/deploy_key_spec.rb | 15 ----- spec/models/deploy_keys_project_spec.rb | 11 ---- spec/models/email_spec.rb | 11 ---- spec/models/event_spec.rb | 16 ------ spec/models/forked_project_link_spec.rb | 11 ---- spec/models/generic_commit_status_spec.rb | 34 ----------- spec/models/group_spec.rb | 15 ----- spec/models/identity_spec.rb | 12 ---- spec/models/issue_spec.rb | 20 ------- spec/models/key_spec.rb | 15 ----- spec/models/label_link_spec.rb | 12 ---- spec/models/label_spec.rb | 13 ----- spec/models/member_spec.rb | 19 ------- spec/models/merge_request_spec.rb | 29 ---------- spec/models/milestone_spec.rb | 15 ----- spec/models/namespace_spec.rb | 15 ----- spec/models/note_spec.rb | 21 ------- spec/models/project_snippet_spec.rb | 16 ------ spec/models/project_spec.rb | 39 ------------- spec/models/protected_branch_spec.rb | 12 ---- spec/models/release_spec.rb | 12 ---- spec/models/service_spec.rb | 21 ------- spec/models/snippet_spec.rb | 16 ------ spec/models/todo_spec.rb | 18 ------ spec/models/user_spec.rb | 63 --------------------- 130 files changed, 1 insertion(+), 2541 deletions(-) diff --git a/Gemfile b/Gemfile index 1137ef4d72b..3e5c604ae06 100644 --- a/Gemfile +++ b/Gemfile @@ -242,7 +242,6 @@ group :development do gem "foreman" gem 'brakeman', '~> 3.2.0', require: false - gem "annotate", "~> 2.7.0" gem 'letter_opener_web', '~> 1.3.0' gem 'quiet_assets', '~> 1.0.2' gem 'rerun', '~> 0.11.0' diff --git a/Gemfile.lock b/Gemfile.lock index fe083c2b566..86b9142ef27 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -51,9 +51,6 @@ GEM activerecord (>= 3.0) akismet (2.0.0) allocations (1.0.4) - annotate (2.7.0) - activerecord (>= 3.2, < 6.0) - rake (~> 10.4) arel (6.0.3) asana (0.4.0) faraday (~> 0.9) @@ -893,7 +890,6 @@ DEPENDENCIES after_commit_queue akismet (~> 2.0) allocations (~> 1.0) - annotate (~> 2.7.0) asana (~> 0.4.0) asciidoctor (~> 1.5.2) attr_encrypted (~> 1.3.4) @@ -1061,4 +1057,4 @@ DEPENDENCIES wikicloth (= 0.8.1) BUNDLED WITH - 1.12.1 + 1.12.3 diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index b61f5123127..b01a244032d 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: abuse_reports -# -# id :integer not null, primary key -# reporter_id :integer -# user_id :integer -# message :text -# created_at :datetime -# updated_at :datetime -# - class AbuseReport < ActiveRecord::Base belongs_to :reporter, class_name: 'User' belongs_to :user diff --git a/app/models/appearance.rb b/app/models/appearance.rb index 4528760fefa..4cf8dd9a8ce 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: appearances -# -# id :integer not null, primary key -# title :string -# description :text -# header_logo :string -# logo :string -# created_at :datetime not null -# updated_at :datetime not null -# - class Appearance < ActiveRecord::Base validates :title, presence: true validates :description, presence: true diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 72ec91d2909..7039db2d41e 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -1,55 +1,3 @@ -# == Schema Information -# -# Table name: application_settings -# -# id :integer not null, primary key -# default_projects_limit :integer -# signup_enabled :boolean -# signin_enabled :boolean -# gravatar_enabled :boolean -# sign_in_text :text -# created_at :datetime -# updated_at :datetime -# home_page_url :string -# default_branch_protection :integer default(2) -# restricted_visibility_levels :text -# version_check_enabled :boolean default(TRUE) -# max_attachment_size :integer default(10), not null -# default_project_visibility :integer -# default_snippet_visibility :integer -# restricted_signup_domains :text -# user_oauth_applications :boolean default(TRUE) -# after_sign_out_path :string -# session_expire_delay :integer default(10080), not null -# import_sources :text -# help_page_text :text -# admin_notification_email :string -# shared_runners_enabled :boolean default(TRUE), not null -# max_artifacts_size :integer default(100), not null -# runners_registration_token :string -# require_two_factor_authentication :boolean default(FALSE) -# two_factor_grace_period :integer default(48) -# metrics_enabled :boolean default(FALSE) -# metrics_host :string default("localhost") -# metrics_pool_size :integer default(16) -# metrics_timeout :integer default(10) -# metrics_method_call_threshold :integer default(10) -# recaptcha_enabled :boolean default(FALSE) -# recaptcha_site_key :string -# recaptcha_private_key :string -# metrics_port :integer default(8089) -# metrics_sample_interval :integer default(15) -# sentry_enabled :boolean default(FALSE) -# sentry_dsn :string -# akismet_enabled :boolean default(FALSE) -# akismet_api_key :string -# email_author_in_body :boolean default(FALSE) -# default_group_visibility :integer -# repository_checks_enabled :boolean default(FALSE) -# metrics_packet_size :integer default(1) -# shared_runners_text :text -# - class ApplicationSetting < ActiveRecord::Base include TokenAuthenticatable add_authentication_token_field :runners_registration_token diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb index 44b090260e7..967ffd46db0 100644 --- a/app/models/audit_event.rb +++ b/app/models/audit_event.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: audit_events -# -# id :integer not null, primary key -# author_id :integer not null -# type :string not null -# entity_id :integer not null -# entity_type :string not null -# details :text -# created_at :datetime -# updated_at :datetime -# - class AuditEvent < ActiveRecord::Base serialize :details, Hash diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb index 075ac733bfc..61498140f27 100644 --- a/app/models/broadcast_message.rb +++ b/app/models/broadcast_message.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: broadcast_messages -# -# id :integer not null, primary key -# message :text not null -# starts_at :datetime -# ends_at :datetime -# created_at :datetime -# updated_at :datetime -# color :string -# font :string -# - class BroadcastMessage < ActiveRecord::Base include Sortable diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 4bc3a225e2c..c9506dd3057 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -1,40 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string -# user_id :integer -# type :string -# target_url :string -# description :string -# artifacts_file :text -# gl_project_id :integer -# artifacts_metadata :text -# erased_by_id :integer -# erased_at :datetime -# - module Ci class Build < CommitStatus belongs_to :runner, class_name: 'Ci::Runner' diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 4ac4e0fb8b2..f4b61c75ab6 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: ci_commits -# -# id :integer not null, primary key -# project_id :integer -# ref :string -# sha :string -# before_sha :string -# push_data :text -# created_at :datetime -# updated_at :datetime -# tag :boolean default(FALSE) -# yaml_errors :text -# committed_at :datetime -# gl_project_id :integer -# status :string -# started_at :datetime -# finished_at :datetime -# duration :integer -# - module Ci class Commit < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index add59a08892..0cdb64d6c33 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: ci_runners -# -# id :integer not null, primary key -# token :string -# created_at :datetime -# updated_at :datetime -# description :string -# contacted_at :datetime -# active :boolean default(TRUE), not null -# is_shared :boolean default(FALSE) -# name :string -# version :string -# revision :string -# platform :string -# architecture :string -# - module Ci class Runner < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb index 7b16f207a26..4b44ffa886e 100644 --- a/app/models/ci/runner_project.rb +++ b/app/models/ci/runner_project.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: ci_runner_projects -# -# id :integer not null, primary key -# runner_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# gl_project_id :integer -# - module Ci class RunnerProject < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb index 4f3f4d79fac..a0b19b51a12 100644 --- a/app/models/ci/trigger.rb +++ b/app/models/ci/trigger.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: ci_triggers -# -# id :integer not null, primary key -# token :string -# project_id :integer -# deleted_at :datetime -# created_at :datetime -# updated_at :datetime -# gl_project_id :integer -# - module Ci class Trigger < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb index 9973d2e5ade..872d5fb31de 100644 --- a/app/models/ci/trigger_request.rb +++ b/app/models/ci/trigger_request.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: ci_trigger_requests -# -# id :integer not null, primary key -# trigger_id :integer not null -# variables :text -# created_at :datetime -# updated_at :datetime -# commit_id :integer -# - module Ci class TriggerRequest < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index 4229fe085a1..10802f64813 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: ci_variables -# -# id :integer not null, primary key -# project_id :integer -# key :string -# value :text -# encrypted_value :text -# encrypted_value_salt :string -# encrypted_value_iv :string -# gl_project_id :integer -# - module Ci class Variable < ActiveRecord::Base extend Ci::Model diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 1260c448de3..cacbc13b391 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -1,40 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string -# user_id :integer -# type :string -# target_url :string -# description :string -# artifacts_file :text -# gl_project_id :integer -# artifacts_metadata :text -# erased_by_id :integer -# erased_at :datetime -# - class CommitStatus < ActiveRecord::Base include Statuseable diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index 43cf625f770..2c525d4cd7a 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: keys -# -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string -# type :string -# fingerprint :string -# public :boolean default(FALSE), not null -# - class DeployKey < Key has_many :deploy_keys_projects, dependent: :destroy has_many :projects, through: :deploy_keys_projects diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb index 18db521741f..ae8486bd9ac 100644 --- a/app/models/deploy_keys_project.rb +++ b/app/models/deploy_keys_project.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: deploy_keys_projects -# -# id :integer not null, primary key -# deploy_key_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class DeployKeysProject < ActiveRecord::Base belongs_to :project belongs_to :deploy_key diff --git a/app/models/email.rb b/app/models/email.rb index eae2472f337..32a412ab878 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: emails -# -# id :integer not null, primary key -# user_id :integer not null -# email :string not null -# created_at :datetime -# updated_at :datetime -# - class Email < ActiveRecord::Base include Sortable diff --git a/app/models/event.rb b/app/models/event.rb index 25c7c3e6dc7..17ee48b91a8 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: events -# -# id :integer not null, primary key -# target_type :string -# target_id :integer -# title :string -# data :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# action :integer -# author_id :integer -# - class Event < ActiveRecord::Base include Sortable default_scope { where.not(author_id: nil) } diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb index 9b0c6263a96..9803bae0bee 100644 --- a/app/models/forked_project_link.rb +++ b/app/models/forked_project_link.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: forked_project_links -# -# id :integer not null, primary key -# forked_to_project_id :integer not null -# forked_from_project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class ForkedProjectLink < ActiveRecord::Base belongs_to :forked_to_project, class_name: Project belongs_to :forked_from_project, class_name: Project diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb index d4afd8cbe84..fa54e3540d0 100644 --- a/app/models/generic_commit_status.rb +++ b/app/models/generic_commit_status.rb @@ -1,40 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string -# user_id :integer -# type :string -# target_url :string -# description :string -# artifacts_file :text -# gl_project_id :integer -# artifacts_metadata :text -# erased_by_id :integer -# erased_at :datetime -# - class GenericCommitStatus < CommitStatus before_validation :set_default_values diff --git a/app/models/group.rb b/app/models/group.rb index cff76877958..aec92e335e6 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -1,20 +1,3 @@ -# == Schema Information -# -# Table name: namespaces -# -# id :integer not null, primary key -# name :string not null -# path :string not null -# owner_id :integer -# created_at :datetime -# updated_at :datetime -# type :string -# description :string default(""), not null -# avatar :string -# share_with_group_lock :boolean default(FALSE) -# visibility_level :integer default(20), not null -# - require 'carrierwave/orm/activerecord' class Group < Namespace diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index 2b8f34a0568..ba42a8eeb70 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class ProjectHook < WebHook belongs_to :project diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb index 0e176de5ef8..eef24052a06 100644 --- a/app/models/hooks/service_hook.rb +++ b/app/models/hooks/service_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class ServiceHook < WebHook belongs_to :service diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb index ad508cbbcb8..777bad1e724 100644 --- a/app/models/hooks/system_hook.rb +++ b/app/models/hooks/system_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class SystemHook < WebHook def async_execute(data, hook_name) Sidekiq::Client.enqueue(SystemHookWorker, id, data, hook_name) diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 8e58c9583ab..fde05f729dc 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class WebHook < ActiveRecord::Base include Sortable include HTTParty diff --git a/app/models/identity.rb b/app/models/identity.rb index ef4d5f99091..3bacc450e6e 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: identities -# -# id :integer not null, primary key -# extern_uid :string -# provider :string -# user_id :integer -# created_at :datetime -# updated_at :datetime -# - class Identity < ActiveRecord::Base include Sortable include CaseSensitivity diff --git a/app/models/issue.rb b/app/models/issue.rb index abaa509707c..2d4a9b9f19a 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: issues -# -# id :integer not null, primary key -# title :string -# assignee_id :integer -# author_id :integer -# project_id :integer -# created_at :datetime -# updated_at :datetime -# position :integer default(0) -# branch_name :string -# description :text -# milestone_id :integer -# state :string -# iid :integer -# updated_by_id :integer -# moved_to_id :integer -# confidential :boolean default(FALSE) -# deleted_at :datetime -# due_date :date -# - require 'carrierwave/orm/activerecord' class Issue < ActiveRecord::Base diff --git a/app/models/key.rb b/app/models/key.rb index b2b57849f8a..d52afda67d1 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: keys -# -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string -# type :string -# fingerprint :string -# public :boolean default(FALSE), not null -# - require 'digest/md5' class Key < ActiveRecord::Base diff --git a/app/models/label.rb b/app/models/label.rb index 9a22398d952..83375db88cc 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: labels -# -# id :integer not null, primary key -# title :string -# color :string -# project_id :integer -# created_at :datetime -# updated_at :datetime -# template :boolean default(FALSE) -# description :string -# - class Label < ActiveRecord::Base include Referable include Subscribable diff --git a/app/models/label_link.rb b/app/models/label_link.rb index 7b8e872b6dd..47bd6eaf35f 100644 --- a/app/models/label_link.rb +++ b/app/models/label_link.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: label_links -# -# id :integer not null, primary key -# label_id :integer -# target_id :integer -# target_type :string -# created_at :datetime -# updated_at :datetime -# - class LabelLink < ActiveRecord::Base belongs_to :target, polymorphic: true belongs_to :label diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index 927e764af92..18657c3e1c8 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects -# -# id :integer not null, primary key -# oid :string not null -# size :integer not null -# created_at :datetime -# updated_at :datetime -# file :string -# - class LfsObject < ActiveRecord::Base has_many :lfs_objects_projects, dependent: :destroy has_many :projects, through: :lfs_objects_projects diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb index 890736bfc80..0fd5f089db9 100644 --- a/app/models/lfs_objects_project.rb +++ b/app/models/lfs_objects_project.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects_projects -# -# id :integer not null, primary key -# lfs_object_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class LfsObjectsProject < ActiveRecord::Base belongs_to :project belongs_to :lfs_object diff --git a/app/models/member.rb b/app/models/member.rb index cca82da89f1..d3060f07fc0 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string not null -# user_id :integer -# notification_level :integer not null -# type :string -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string -# invite_token :string -# invite_accepted_at :datetime -# - class Member < ActiveRecord::Base include Sortable include Gitlab::Access diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index a48c1943e6f..f63a0debf1a 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string not null -# user_id :integer -# notification_level :integer not null -# type :string -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string -# invite_token :string -# invite_accepted_at :datetime -# - class GroupMember < Member SOURCE_TYPE = 'Namespace' diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 143350a0b55..8dae3bb2ef2 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string not null -# user_id :integer -# notification_level :integer not null -# type :string -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string -# invite_token :string -# invite_accepted_at :datetime -# - class ProjectMember < Member SOURCE_TYPE = 'Project' diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 4175e1e5fba..5460935366c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1,33 +1,3 @@ -# == Schema Information -# -# Table name: merge_requests -# -# id :integer not null, primary key -# target_branch :string not null -# source_branch :string not null -# source_project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string -# created_at :datetime -# updated_at :datetime -# milestone_id :integer -# state :string -# merge_status :string -# target_project_id :integer not null -# iid :integer -# description :text -# position :integer default(0) -# locked_at :datetime -# updated_by_id :integer -# merge_error :string -# merge_params :text -# merge_when_build_succeeds :boolean default(FALSE), not null -# merge_user_id :integer -# merge_commit_sha :string -# deleted_at :datetime -# - class MergeRequest < ActiveRecord::Base include InternalId include Issuable diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 8951e92a0b8..eb42c07b9b9 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: merge_request_diffs -# -# id :integer not null, primary key -# state :string -# st_commits :text -# st_diffs :text -# merge_request_id :integer not null -# created_at :datetime -# updated_at :datetime -# base_commit_sha :string -# real_size :string -# - class MergeRequestDiff < ActiveRecord::Base include Sortable diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 5ee8a965ad8..97705a374d7 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: milestones -# -# id :integer not null, primary key -# title :string not null -# project_id :integer not null -# description :text -# due_date :date -# created_at :datetime -# updated_at :datetime -# state :string -# iid :integer -# - class Milestone < ActiveRecord::Base # Represents a "No Milestone" state used for filtering Issues and Merge # Requests that have no milestone assigned. diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 741e912171d..9c942a8f4e3 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -1,20 +1,3 @@ -# == Schema Information -# -# Table name: namespaces -# -# id :integer not null, primary key -# name :string not null -# path :string not null -# owner_id :integer -# created_at :datetime -# updated_at :datetime -# type :string -# description :string default(""), not null -# avatar :string -# share_with_group_lock :boolean default(FALSE) -# visibility_level :integer default(20), not null -# - class Namespace < ActiveRecord::Base include Sortable include Gitlab::ShellAdapter diff --git a/app/models/note.rb b/app/models/note.rb index deee2b9e885..f26aa1bf63f 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: notes -# -# id :integer not null, primary key -# note :text -# noteable_type :string -# author_id :integer -# created_at :datetime -# updated_at :datetime -# project_id :integer -# attachment :string -# line_code :string -# commit_id :string -# noteable_id :integer -# system :boolean default(FALSE), not null -# st_diff :text -# updated_by_id :integer -# is_award :boolean default(FALSE), not null -# - require 'carrierwave/orm/activerecord' class Note < ActiveRecord::Base diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb index 846773752a6..5001738f411 100644 --- a/app/models/notification_setting.rb +++ b/app/models/notification_setting.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: notification_settings -# -# id :integer not null, primary key -# user_id :integer not null -# source_id :integer not null -# source_type :string not null -# level :integer default(0), not null -# created_at :datetime not null -# updated_at :datetime not null -# - class NotificationSetting < ActiveRecord::Base enum level: { disabled: 0, participating: 1, watch: 2, global: 3, mention: 4 } diff --git a/app/models/oauth_access_token.rb b/app/models/oauth_access_token.rb index c78c7f4aa0e..116fb71ac08 100644 --- a/app/models/oauth_access_token.rb +++ b/app/models/oauth_access_token.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: oauth_access_tokens -# -# id :integer not null, primary key -# resource_owner_id :integer -# application_id :integer -# token :string not null -# refresh_token :string -# expires_in :integer -# revoked_at :datetime -# created_at :datetime not null -# scopes :string -# - class OauthAccessToken < ActiveRecord::Base belongs_to :resource_owner, class_name: 'User' belongs_to :application, class_name: 'Doorkeeper::Application' diff --git a/app/models/personal_snippet.rb b/app/models/personal_snippet.rb index 1d5f4c50254..82c1c4de3a0 100644 --- a/app/models/personal_snippet.rb +++ b/app/models/personal_snippet.rb @@ -1,18 +1,2 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string -# type :string -# visibility_level :integer default(0), not null -# - class PersonalSnippet < Snippet end diff --git a/app/models/project.rb b/app/models/project.rb index 05e14185a3e..418b85e028a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,48 +1,3 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string -# path :string -# description :text -# created_at :datetime -# updated_at :datetime -# creator_id :integer -# issues_enabled :boolean default(TRUE), not null -# merge_requests_enabled :boolean default(TRUE), not null -# wiki_enabled :boolean default(TRUE), not null -# namespace_id :integer -# issues_tracker :string default("gitlab"), not null -# issues_tracker_id :string -# snippets_enabled :boolean default(TRUE), not null -# last_activity_at :datetime -# import_url :string -# visibility_level :integer default(0), not null -# archived :boolean default(FALSE), not null -# avatar :string -# import_status :string -# repository_size :float default(0.0) -# star_count :integer default(0), not null -# import_type :string -# import_source :string -# commit_count :integer default(0) -# import_error :text -# ci_id :integer -# builds_enabled :boolean default(TRUE), not null -# shared_runners_enabled :boolean default(TRUE), not null -# runners_token :string -# build_coverage_regex :string -# build_allow_git_fetch :boolean default(TRUE), not null -# build_timeout :integer default(3600), not null -# pending_delete :boolean default(FALSE) -# public_builds :boolean default(TRUE), not null -# main_language :string -# pushes_since_gc :integer default(0) -# last_repository_check_failed :boolean -# last_repository_check_at :datetime -# - require 'carrierwave/orm/activerecord' class Project < ActiveRecord::Base diff --git a/app/models/project_group_link.rb b/app/models/project_group_link.rb index 66f5a609bf5..e52a6bd7c84 100644 --- a/app/models/project_group_link.rb +++ b/app/models/project_group_link.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: project_group_links -# -# id :integer not null, primary key -# project_id :integer not null -# group_id :integer not null -# created_at :datetime -# updated_at :datetime -# group_access :integer default(30), not null -# - class ProjectGroupLink < ActiveRecord::Base GUEST = 10 REPORTER = 20 diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb index 7830f764ed3..e2f9ffb69ac 100644 --- a/app/models/project_import_data.rb +++ b/app/models/project_import_data.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: project_import_data -# -# id :integer not null, primary key -# project_id :integer -# data :text -# encrypted_credentials :text -# encrypted_credentials_iv :string -# encrypted_credentials_salt :string -# - require 'carrierwave/orm/activerecord' class ProjectImportData < ActiveRecord::Base diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 368485a060a..7c23b766763 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require 'asana' class AsanaService < Service diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb index ffb7455b014..d839221d315 100644 --- a/app/models/project_services/assembla_service.rb +++ b/app/models/project_services/assembla_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class AssemblaService < Service include HTTParty diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index c36ee95e378..1d1780dcfbf 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class BambooService < CiService include HTTParty diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb index f9f4897a065..86a06321e21 100644 --- a/app/models/project_services/buildkite_service.rb +++ b/app/models/project_services/buildkite_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require "addressable/uri" class BuildkiteService < CiService diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb index 20cdfcaffb2..54da4d74fc5 100644 --- a/app/models/project_services/builds_email_service.rb +++ b/app/models/project_services/builds_email_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class BuildsEmailService < Service prop_accessor :recipients boolean_accessor :add_pusher diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index 28c969fe57f..511b2eac792 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class CampfireService < Service prop_accessor :token, :subdomain, :room validates :token, presence: true, if: :activated? diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index 9bc8f982da6..596c00705ad 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - # Base class for CI services # List methods you need to implement to get your CI service # working with GitLab Merge Requests diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb index 4d1319eb6f8..6b2b1daa724 100644 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class CustomIssueTrackerService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index d8e00e018cc..966dbc41d73 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class DroneCiService < CiService prop_accessor :drone_url, :token, :enable_ssl_verification diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb index 2dbd29062df..e0083c43adb 100644 --- a/app/models/project_services/emails_on_push_service.rb +++ b/app/models/project_services/emails_on_push_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class EmailsOnPushService < Service prop_accessor :send_from_committer_email prop_accessor :disable_diffs diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index 5469049bb5e..f042bfc5210 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class ExternalWikiService < Service include HTTParty diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 3dc1e0fbe8b..dd00275187f 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require "flowdock-git-hook" class FlowdockService < Service diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb index b4c311cf664..598aca5e06d 100644 --- a/app/models/project_services/gemnasium_service.rb +++ b/app/models/project_services/gemnasium_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require "gemnasium/gitlab_service" class GemnasiumService < Service diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index a92f7226083..bbc312f5215 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - # TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed class GitlabCiService < CiService # We override the active accessor to always make GitLabCiService disabled diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 1adaeeb3b2b..5d17c358330 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class GitlabIssueTrackerService < IssueTrackerService include Gitlab::Routing.url_helpers diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index f9ddf588722..0ff4f4c8dd2 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class HipchatService < Service MAX_COMMITS = 3 diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb index b9a592d7096..91015e6c9b1 100644 --- a/app/models/project_services/irker_service.rb +++ b/app/models/project_services/irker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require 'uri' class IrkerService < Service diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 98a3a7c6b86..6ae9b16d3ce 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class IssueTrackerService < Service validates :project_url, :issues_url, :new_issue_url, presence: true, url: true, if: :activated? diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index ba68658f0bd..beda89d3963 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class JiraService < IssueTrackerService include HTTParty include Gitlab::Routing.url_helpers diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb index acaa0c39365..ad19b7795da 100644 --- a/app/models/project_services/pivotaltracker_service.rb +++ b/app/models/project_services/pivotaltracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class PivotaltrackerService < Service include HTTParty diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index a640c8cb440..3dd878e4c7d 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class PushoverService < Service include HTTParty base_uri 'https://api.pushover.net/1' diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index e2137e92c62..11cce3e0561 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class RedmineService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index 83ffa53a407..cf9e4d5a8b6 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class SlackService < Service prop_accessor :webhook, :username, :channel boolean_accessor :notify_only_broken_builds diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index 4015da31509..b0dcb52eba1 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class TeamcityService < CiService include HTTParty diff --git a/app/models/project_snippet.rb b/app/models/project_snippet.rb index b4b2807eba4..5fba6baa204 100644 --- a/app/models/project_snippet.rb +++ b/app/models/project_snippet.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string -# type :string -# visibility_level :integer default(0), not null -# - class ProjectSnippet < Snippet belongs_to :project belongs_to :author, class_name: "User" diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 3d2052c892c..33cf046fa75 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: protected_branches -# -# id :integer not null, primary key -# project_id :integer not null -# name :string not null -# created_at :datetime -# updated_at :datetime -# developers_can_push :boolean default(FALSE), not null -# - class ProtectedBranch < ActiveRecord::Base include Gitlab::ShellAdapter diff --git a/app/models/release.rb b/app/models/release.rb index dc700d1ea5a..e196b84eb18 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: releases -# -# id :integer not null, primary key -# tag :string -# description :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# - class Release < ActiveRecord::Base belongs_to :project diff --git a/app/models/security_event.rb b/app/models/security_event.rb index 0bee03974f1..d131c11cb6c 100644 --- a/app/models/security_event.rb +++ b/app/models/security_event.rb @@ -1,16 +1,2 @@ -# == Schema Information -# -# Table name: audit_events -# -# id :integer not null, primary key -# author_id :integer not null -# type :string not null -# entity_id :integer not null -# entity_type :string not null -# details :text -# created_at :datetime -# updated_at :datetime -# - class SecurityEvent < AuditEvent end diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb index 99279a2e083..375f195dba7 100644 --- a/app/models/sent_notification.rb +++ b/app/models/sent_notification.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: sent_notifications -# -# id :integer not null, primary key -# project_id :integer -# noteable_id :integer -# noteable_type :string -# recipient_id :integer -# commit_id :string -# reply_key :string not null -# line_code :string -# - class SentNotification < ActiveRecord::Base belongs_to :project belongs_to :noteable, polymorphic: true diff --git a/app/models/service.rb b/app/models/service.rb index bf16a545307..de3fd24584a 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - # To add new service you should build a class inherited from Service # and implement a set of methods class Service < ActiveRecord::Base diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 2f905a90942..0a3c3b57669 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string -# type :string -# visibility_level :integer default(0), not null -# - class Snippet < ActiveRecord::Base include Gitlab::VisibilityLevel include Linguist::BlobHelper diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index f49eb7d88e2..12df68ef83b 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -1,20 +1,3 @@ -# == Schema Information -# -# Table name: spam_logs -# -# id :integer not null, primary key -# user_id :integer -# source_ip :string -# user_agent :string -# via_api :boolean -# project_id :integer -# noteable_type :string -# title :string -# description :text -# created_at :datetime not null -# updated_at :datetime not null -# - class SpamLog < ActiveRecord::Base belongs_to :user diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 242faa7d32e..3b8aa1eb866 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: subscriptions -# -# id :integer not null, primary key -# user_id :integer -# subscribable_id :integer -# subscribable_type :string -# subscribed :boolean -# created_at :datetime -# updated_at :datetime -# - class Subscription < ActiveRecord::Base belongs_to :user belongs_to :subscribable, polymorphic: true diff --git a/app/models/todo.rb b/app/models/todo.rb index d85f7bfdf57..f8b59fe4126 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: todos -# -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# target_id :integer -# target_type :string not null -# author_id :integer -# action :integer not null -# state :string not null -# created_at :datetime -# updated_at :datetime -# note_id :integer -# commit_id :string -# - class Todo < ActiveRecord::Base ASSIGNED = 1 MENTIONED = 2 diff --git a/app/models/user.rb b/app/models/user.rb index 56d6de610f0..1e4814641d1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,68 +1,3 @@ -# == Schema Information -# -# Table name: users -# -# id :integer not null, primary key -# email :string default(""), not null -# encrypted_password :string default(""), not null -# reset_password_token :string -# reset_password_sent_at :datetime -# remember_created_at :datetime -# sign_in_count :integer default(0) -# current_sign_in_at :datetime -# last_sign_in_at :datetime -# current_sign_in_ip :string -# last_sign_in_ip :string -# created_at :datetime -# updated_at :datetime -# name :string -# admin :boolean default(FALSE), not null -# projects_limit :integer default(10) -# skype :string default(""), not null -# linkedin :string default(""), not null -# twitter :string default(""), not null -# authentication_token :string -# theme_id :integer default(1), not null -# bio :string -# failed_attempts :integer default(0) -# locked_at :datetime -# username :string -# can_create_group :boolean default(TRUE), not null -# can_create_team :boolean default(TRUE), not null -# state :string -# color_scheme_id :integer default(1), not null -# notification_level :integer default(1), not null -# password_expires_at :datetime -# created_by_id :integer -# last_credential_check_at :datetime -# avatar :string -# confirmation_token :string -# confirmed_at :datetime -# confirmation_sent_at :datetime -# unconfirmed_email :string -# hide_no_ssh_key :boolean default(FALSE) -# website_url :string default(""), not null -# notification_email :string -# hide_no_password :boolean default(FALSE) -# password_automatically_set :boolean default(FALSE) -# location :string -# encrypted_otp_secret :string -# encrypted_otp_secret_iv :string -# encrypted_otp_secret_salt :string -# otp_required_for_login :boolean default(FALSE), not null -# otp_backup_codes :text -# public_email :string default(""), not null -# dashboard :integer default(0) -# project_view :integer default(0) -# consumed_timestep :integer -# layout :integer default(0) -# hide_project_limit :boolean default(FALSE) -# unlock_token :string -# otp_grace_period_started_at :datetime -# ldap_email :boolean default(FALSE), not null -# external :boolean default(FALSE) -# - require 'carrierwave/orm/activerecord' class User < ActiveRecord::Base diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb index 413f3f485a8..0dfe597317e 100644 --- a/app/models/users_star_project.rb +++ b/app/models/users_star_project.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: users_star_projects -# -# id :integer not null, primary key -# project_id :integer not null -# user_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class UsersStarProject < ActiveRecord::Base belongs_to :project, counter_cache: :star_count, touch: true belongs_to :user diff --git a/spec/factories/abuse_reports.rb b/spec/factories/abuse_reports.rb index d0e8c778518..8f6422a7825 100644 --- a/spec/factories/abuse_reports.rb +++ b/spec/factories/abuse_reports.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: abuse_reports -# -# id :integer not null, primary key -# reporter_id :integer -# user_id :integer -# message :text -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :abuse_report do reporter factory: :user diff --git a/spec/factories/broadcast_messages.rb b/spec/factories/broadcast_messages.rb index c80e7366551..efe9803b1a7 100644 --- a/spec/factories/broadcast_messages.rb +++ b/spec/factories/broadcast_messages.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: broadcast_messages -# -# id :integer not null, primary key -# message :text not null -# starts_at :datetime -# ends_at :datetime -# created_at :datetime -# updated_at :datetime -# color :string(255) -# font :string(255) -# - FactoryGirl.define do factory :broadcast_message do message "MyText" diff --git a/spec/factories/forked_project_links.rb b/spec/factories/forked_project_links.rb index 19a54946fe0..b16c1272e68 100644 --- a/spec/factories/forked_project_links.rb +++ b/spec/factories/forked_project_links.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: forked_project_links -# -# id :integer not null, primary key -# forked_to_project_id :integer not null -# forked_from_project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :forked_project_link do association :forked_to_project, factory: :project diff --git a/spec/factories/label_links.rb b/spec/factories/label_links.rb index 2939d4307c5..3580174e873 100644 --- a/spec/factories/label_links.rb +++ b/spec/factories/label_links.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: label_links -# -# id :integer not null, primary key -# label_id :integer -# target_id :integer -# target_type :string(255) -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :label_link do label diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index ea2be8928d5..eb489099854 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: labels -# -# id :integer not null, primary key -# title :string(255) -# color :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# template :boolean default(FALSE) -# - FactoryGirl.define do factory :label do sequence(:title) { |n| "label#{n}" } diff --git a/spec/factories/lfs_objects.rb b/spec/factories/lfs_objects.rb index 327858ce435..a81645acd2b 100644 --- a/spec/factories/lfs_objects.rb +++ b/spec/factories/lfs_objects.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects -# -# id :integer not null, primary key -# oid :string(255) not null -# size :integer not null -# created_at :datetime -# updated_at :datetime -# file :string(255) -# - include ActionDispatch::TestProcess FactoryGirl.define do diff --git a/spec/factories/lfs_objects_projects.rb b/spec/factories/lfs_objects_projects.rb index 50b45843c99..1ed0355c8e4 100644 --- a/spec/factories/lfs_objects_projects.rb +++ b/spec/factories/lfs_objects_projects.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects_projects -# -# id :integer not null, primary key -# lfs_object_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :lfs_objects_project do lfs_object diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index e281e2f227b..c6a08d78b78 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -1,32 +1,3 @@ -# == Schema Information -# -# Table name: merge_requests -# -# id :integer not null, primary key -# target_branch :string(255) not null -# source_branch :string(255) not null -# source_project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string(255) -# created_at :datetime -# updated_at :datetime -# milestone_id :integer -# state :string(255) -# merge_status :string(255) -# target_project_id :integer not null -# iid :integer -# description :text -# position :integer default(0) -# locked_at :datetime -# updated_by_id :integer -# merge_error :string(255) -# merge_params :text -# merge_when_build_succeeds :boolean default(FALSE), not null -# merge_user_id :integer -# merge_commit_sha :string -# - FactoryGirl.define do factory :merge_request do title diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index e5dcb159014..840b13196a6 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: notes -# -# id :integer not null, primary key -# note :text -# noteable_type :string(255) -# author_id :integer -# created_at :datetime -# updated_at :datetime -# project_id :integer -# attachment :string(255) -# line_code :string(255) -# commit_id :string(255) -# noteable_id :integer -# system :boolean default(FALSE), not null -# st_diff :text -# updated_by_id :integer -# is_award :boolean default(FALSE), not null -# - require_relative '../support/repo_helpers' include ActionDispatch::TestProcess diff --git a/spec/factories/oauth_access_tokens.rb b/spec/factories/oauth_access_tokens.rb index 7700b15d538..ccf02d0719b 100644 --- a/spec/factories/oauth_access_tokens.rb +++ b/spec/factories/oauth_access_tokens.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: oauth_access_tokens -# -# id :integer not null, primary key -# resource_owner_id :integer -# application_id :integer -# token :string not null -# refresh_token :string -# expires_in :integer -# revoked_at :datetime -# created_at :datetime not null -# scopes :string -# - FactoryGirl.define do factory :oauth_access_token do resource_owner diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 4d61345696a..da8d97c9f82 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -1,42 +1,3 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) -# path :string(255) -# description :text -# created_at :datetime -# updated_at :datetime -# creator_id :integer -# issues_enabled :boolean default(TRUE), not null -# merge_requests_enabled :boolean default(TRUE), not null -# wiki_enabled :boolean default(TRUE), not null -# namespace_id :integer -# issues_tracker :string(255) default("gitlab"), not null -# issues_tracker_id :string(255) -# snippets_enabled :boolean default(TRUE), not null -# last_activity_at :datetime -# import_url :string(255) -# visibility_level :integer default(0), not null -# archived :boolean default(FALSE), not null -# avatar :string(255) -# import_status :string(255) -# repository_size :float default(0.0) -# star_count :integer default(0), not null -# import_type :string(255) -# import_source :string(255) -# commit_count :integer default(0) -# import_error :text -# ci_id :integer -# builds_enabled :boolean default(TRUE), not null -# shared_runners_enabled :boolean default(TRUE), not null -# runners_token :string -# build_coverage_regex :string -# build_allow_git_fetch :boolean default(TRUE), not null -# build_timeout :integer default(3600), not null -# - FactoryGirl.define do # Project without repository # diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb index 7f331c37256..74497dc82c0 100644 --- a/spec/factories/releases.rb +++ b/spec/factories/releases.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: releases -# -# id :integer not null, primary key -# tag :string(255) -# description :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :release do tag "v1.1.0" diff --git a/spec/factories/todos.rb b/spec/factories/todos.rb index 7ae06c27840..e3681ae93a5 100644 --- a/spec/factories/todos.rb +++ b/spec/factories/todos.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: todos -# -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# target_id :integer -# target_type :string not null -# author_id :integer -# action :integer not null -# state :string not null -# created_at :datetime -# updated_at :datetime -# note_id :integer -# commit_id :string -# - FactoryGirl.define do factory :todo do project diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index ac12ab6c757..305f8bc88cc 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: abuse_reports -# -# id :integer not null, primary key -# reporter_id :integer -# user_id :integer -# message :text -# created_at :datetime -# updated_at :datetime -# - require 'rails_helper' RSpec.describe AbuseReport, type: :model do diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 520cf1b75de..1ce22feed5c 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -1,49 +1,3 @@ -# == Schema Information -# -# Table name: application_settings -# -# id :integer not null, primary key -# default_projects_limit :integer -# signup_enabled :boolean -# signin_enabled :boolean -# gravatar_enabled :boolean -# sign_in_text :text -# created_at :datetime -# updated_at :datetime -# home_page_url :string(255) -# default_branch_protection :integer default(2) -# restricted_visibility_levels :text -# version_check_enabled :boolean default(TRUE) -# max_attachment_size :integer default(10), not null -# default_project_visibility :integer -# default_snippet_visibility :integer -# restricted_signup_domains :text -# user_oauth_applications :boolean default(TRUE) -# after_sign_out_path :string(255) -# session_expire_delay :integer default(10080), not null -# import_sources :text -# help_page_text :text -# admin_notification_email :string(255) -# shared_runners_enabled :boolean default(TRUE), not null -# max_artifacts_size :integer default(100), not null -# runners_registration_token :string -# require_two_factor_authentication :boolean default(FALSE) -# two_factor_grace_period :integer default(48) -# metrics_enabled :boolean default(FALSE) -# metrics_host :string default("localhost") -# metrics_username :string -# metrics_password :string -# metrics_pool_size :integer default(16) -# metrics_timeout :integer default(10) -# metrics_method_call_threshold :integer default(10) -# recaptcha_enabled :boolean default(FALSE) -# recaptcha_site_key :string -# recaptcha_private_key :string -# metrics_port :integer default(8089) -# sentry_enabled :boolean default(FALSE) -# sentry_dsn :string -# - require 'spec_helper' describe ApplicationSetting, models: true do diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index f6f84db57e6..6ad8bfef4f2 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: broadcast_messages -# -# id :integer not null, primary key -# message :text not null -# starts_at :datetime -# ends_at :datetime -# created_at :datetime -# updated_at :datetime -# color :string(255) -# font :string(255) -# - require 'spec_helper' describe BroadcastMessage, models: true do diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb index a747aa08447..dc071ad1c90 100644 --- a/spec/models/ci/commit_spec.rb +++ b/spec/models/ci/commit_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: ci_commits -# -# id :integer not null, primary key -# project_id :integer -# ref :string(255) -# sha :string(255) -# before_sha :string(255) -# push_data :text -# created_at :datetime -# updated_at :datetime -# tag :boolean default(FALSE) -# yaml_errors :text -# committed_at :datetime -# gl_project_id :integer -# - require 'spec_helper' describe Ci::Commit, models: true do diff --git a/spec/models/ci/runner_project_spec.rb b/spec/models/ci/runner_project_spec.rb index 000a732db77..95fc160b238 100644 --- a/spec/models/ci/runner_project_spec.rb +++ b/spec/models/ci/runner_project_spec.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: ci_runner_projects -# -# id :integer not null, primary key -# runner_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# gl_project_id :integer -# - require 'spec_helper' describe Ci::RunnerProject, models: true do diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 25e9e5eca48..eaa94228922 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: ci_runners -# -# id :integer not null, primary key -# token :string(255) -# created_at :datetime -# updated_at :datetime -# description :string(255) -# contacted_at :datetime -# active :boolean default(TRUE), not null -# is_shared :boolean default(FALSE) -# name :string(255) -# version :string(255) -# revision :string(255) -# platform :string(255) -# architecture :string(255) -# - require 'spec_helper' describe Ci::Runner, models: true do diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb index 159be939300..474b0b1621d 100644 --- a/spec/models/ci/trigger_spec.rb +++ b/spec/models/ci/trigger_spec.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: ci_triggers -# -# id :integer not null, primary key -# token :string(255) -# project_id :integer -# deleted_at :datetime -# created_at :datetime -# updated_at :datetime -# gl_project_id :integer -# - require 'spec_helper' describe Ci::Trigger, models: true do diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb index 71e84091cb7..c712d211b0f 100644 --- a/spec/models/ci/variable_spec.rb +++ b/spec/models/ci/variable_spec.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: ci_variables -# -# id :integer not null, primary key -# project_id :integer -# key :string(255) -# value :text -# encrypted_value :text -# encrypted_value_salt :string(255) -# encrypted_value_iv :string(255) -# gl_project_id :integer -# - require 'spec_helper' describe Ci::Variable, models: true do diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 971e6750375..434e58cfd06 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -1,37 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string(255) -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string(255) -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string(255) -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string(255) -# user_id :integer -# type :string(255) -# target_url :string(255) -# description :string(255) -# artifacts_file :text -# gl_project_id :integer -# - require 'spec_helper' describe CommitStatus, models: true do diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index 64ba778afea..6a90598a629 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: keys -# -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string(255) -# type :string(255) -# fingerprint :string(255) -# public :boolean default(FALSE), not null -# - require 'spec_helper' describe DeployKey, models: true do diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb index 8aedbfb8636..8a1e337c1a3 100644 --- a/spec/models/deploy_keys_project_spec.rb +++ b/spec/models/deploy_keys_project_spec.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: deploy_keys_projects -# -# id :integer not null, primary key -# deploy_key_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - require 'spec_helper' describe DeployKeysProject, models: true do diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb index a20a6149649..5d0bd31db5a 100644 --- a/spec/models/email_spec.rb +++ b/spec/models/email_spec.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: emails -# -# id :integer not null, primary key -# user_id :integer not null -# email :string(255) not null -# created_at :datetime -# updated_at :datetime -# - require 'spec_helper' describe Email, models: true do diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 0c3cd13f399..b0e76fec693 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: events -# -# id :integer not null, primary key -# target_type :string(255) -# target_id :integer -# title :string(255) -# data :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# action :integer -# author_id :integer -# - require 'spec_helper' describe Event, models: true do diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb index d90fbfe1ea5..3b817608ce0 100644 --- a/spec/models/forked_project_link_spec.rb +++ b/spec/models/forked_project_link_spec.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: forked_project_links -# -# id :integer not null, primary key -# forked_to_project_id :integer not null -# forked_from_project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - require 'spec_helper' describe ForkedProjectLink, "add link on fork" do diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb index 5b0883d8702..0caf5869c24 100644 --- a/spec/models/generic_commit_status_spec.rb +++ b/spec/models/generic_commit_status_spec.rb @@ -1,37 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string(255) -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string(255) -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string(255) -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string(255) -# user_id :integer -# type :string(255) -# target_url :string(255) -# description :string(255) -# artifacts_file :text -# gl_project_id :integer -# - require 'spec_helper' describe GenericCommitStatus, models: true do diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 7bfca1e72c3..6fa16be7f04 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: namespaces -# -# id :integer not null, primary key -# name :string(255) not null -# path :string(255) not null -# owner_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) -# description :string(255) default(""), not null -# avatar :string(255) -# - require 'spec_helper' describe Group, models: true do diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb index 5afe042e154..1b987588f59 100644 --- a/spec/models/identity_spec.rb +++ b/spec/models/identity_spec.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: identities -# -# id :integer not null, primary key -# extern_uid :string(255) -# provider :string(255) -# user_id :integer -# created_at :datetime -# updated_at :datetime -# - require 'spec_helper' RSpec.describe Identity, models: true do diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 060e6599104..8ab00c70f9d 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: issues -# -# id :integer not null, primary key -# title :string(255) -# assignee_id :integer -# author_id :integer -# project_id :integer -# created_at :datetime -# updated_at :datetime -# position :integer default(0) -# branch_name :string(255) -# description :text -# milestone_id :integer -# state :string(255) -# iid :integer -# updated_by_id :integer -# - require 'spec_helper' describe Issue, models: true do diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index c962b83644a..26fbedbef2f 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: keys -# -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string(255) -# type :string(255) -# fingerprint :string(255) -# public :boolean default(FALSE), not null -# - require 'spec_helper' describe Key, models: true do diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb index dc7510b1de3..5e6f8ca1528 100644 --- a/spec/models/label_link_spec.rb +++ b/spec/models/label_link_spec.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: label_links -# -# id :integer not null, primary key -# label_id :integer -# target_id :integer -# target_type :string(255) -# created_at :datetime -# updated_at :datetime -# - require 'spec_helper' describe LabelLink, models: true do diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 0614ca1e7c9..eff8ee222ac 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: labels -# -# id :integer not null, primary key -# title :string(255) -# color :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# template :boolean default(FALSE) -# - require 'spec_helper' describe Label, models: true do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 2d8f1cc1ad3..6e51730eecd 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string(255) not null -# user_id :integer -# notification_level :integer not null -# type :string(255) -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string(255) -# invite_token :string(255) -# invite_accepted_at :datetime -# - require 'spec_helper' describe Member, models: true do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index d7884cea336..c8578749b21 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1,32 +1,3 @@ -# == Schema Information -# -# Table name: merge_requests -# -# id :integer not null, primary key -# target_branch :string(255) not null -# source_branch :string(255) not null -# source_project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string(255) -# created_at :datetime -# updated_at :datetime -# milestone_id :integer -# state :string(255) -# merge_status :string(255) -# target_project_id :integer not null -# iid :integer -# description :text -# position :integer default(0) -# locked_at :datetime -# updated_by_id :integer -# merge_error :string(255) -# merge_params :text -# merge_when_build_succeeds :boolean default(FALSE), not null -# merge_user_id :integer -# merge_commit_sha :string -# - require 'spec_helper' describe MergeRequest, models: true do diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 72a4ea70228..26bfd2e1241 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: milestones -# -# id :integer not null, primary key -# title :string(255) not null -# project_id :integer not null -# description :text -# due_date :date -# created_at :datetime -# updated_at :datetime -# state :string(255) -# iid :integer -# - require 'spec_helper' describe Milestone, models: true do diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 3c3a580942a..4074f966299 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: namespaces -# -# id :integer not null, primary key -# name :string(255) not null -# path :string(255) not null -# owner_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) -# description :string(255) default(""), not null -# avatar :string(255) -# - require 'spec_helper' describe Namespace, models: true do diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 6b18936edb1..4b788b57882 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: notes -# -# id :integer not null, primary key -# note :text -# noteable_type :string(255) -# author_id :integer -# created_at :datetime -# updated_at :datetime -# project_id :integer -# attachment :string(255) -# line_code :string(255) -# commit_id :string(255) -# noteable_id :integer -# system :boolean default(FALSE), not null -# st_diff :text -# updated_by_id :integer -# is_award :boolean default(FALSE), not null -# - require 'spec_helper' describe Note, models: true do diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb index e0feb606f78..d9d7c0b0aaa 100644 --- a/spec/models/project_snippet_spec.rb +++ b/spec/models/project_snippet_spec.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string(255) -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string(255) -# type :string(255) -# visibility_level :integer default(0), not null -# - require 'spec_helper' describe ProjectSnippet, models: true do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 3a8a6c2c166..f6e5b132643 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1,42 +1,3 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) -# path :string(255) -# description :text -# created_at :datetime -# updated_at :datetime -# creator_id :integer -# issues_enabled :boolean default(TRUE), not null -# merge_requests_enabled :boolean default(TRUE), not null -# wiki_enabled :boolean default(TRUE), not null -# namespace_id :integer -# issues_tracker :string(255) default("gitlab"), not null -# issues_tracker_id :string(255) -# snippets_enabled :boolean default(TRUE), not null -# last_activity_at :datetime -# import_url :string(255) -# visibility_level :integer default(0), not null -# archived :boolean default(FALSE), not null -# avatar :string(255) -# import_status :string(255) -# repository_size :float default(0.0) -# star_count :integer default(0), not null -# import_type :string(255) -# import_source :string(255) -# commit_count :integer default(0) -# import_error :text -# ci_id :integer -# builds_enabled :boolean default(TRUE), not null -# shared_runners_enabled :boolean default(TRUE), not null -# runners_token :string -# build_coverage_regex :string -# build_allow_git_fetch :boolean default(TRUE), not null -# build_timeout :integer default(3600), not null -# - require 'spec_helper' describe Project, models: true do diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb index 7e956cf6779..b523834c6e9 100644 --- a/spec/models/protected_branch_spec.rb +++ b/spec/models/protected_branch_spec.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: protected_branches -# -# id :integer not null, primary key -# project_id :integer not null -# name :string(255) not null -# created_at :datetime -# updated_at :datetime -# developers_can_push :boolean default(FALSE), not null -# - require 'spec_helper' describe ProtectedBranch, models: true do diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 72ecb442a36..527005b2b69 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: releases -# -# id :integer not null, primary key -# tag :string(255) -# description :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# - require 'rails_helper' RSpec.describe Release, type: :model do diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 173628c08d0..8592e112c50 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# - require 'spec_helper' describe Service, models: true do diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 5077ac7b62b..7a613e360d4 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string(255) -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string(255) -# type :string(255) -# visibility_level :integer default(0), not null -# - require 'spec_helper' describe Snippet, models: true do diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb index d9b86b9368f..623b82c01d8 100644 --- a/spec/models/todo_spec.rb +++ b/spec/models/todo_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: todos -# -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# target_id :integer -# target_type :string not null -# author_id :integer -# action :integer not null -# state :string not null -# created_at :datetime -# updated_at :datetime -# note_id :integer -# commit_id :string -# - require 'spec_helper' describe Todo, models: true do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 8b2fb77e28e..26d4e139396 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,66 +1,3 @@ -# == Schema Information -# -# Table name: users -# -# id :integer not null, primary key -# email :string(255) default(""), not null -# encrypted_password :string(255) default(""), not null -# reset_password_token :string(255) -# reset_password_sent_at :datetime -# remember_created_at :datetime -# sign_in_count :integer default(0) -# current_sign_in_at :datetime -# last_sign_in_at :datetime -# current_sign_in_ip :string(255) -# last_sign_in_ip :string(255) -# created_at :datetime -# updated_at :datetime -# name :string(255) -# admin :boolean default(FALSE), not null -# projects_limit :integer default(10) -# skype :string(255) default(""), not null -# linkedin :string(255) default(""), not null -# twitter :string(255) default(""), not null -# authentication_token :string(255) -# theme_id :integer default(1), not null -# bio :string(255) -# failed_attempts :integer default(0) -# locked_at :datetime -# username :string(255) -# can_create_group :boolean default(TRUE), not null -# can_create_team :boolean default(TRUE), not null -# state :string(255) -# color_scheme_id :integer default(1), not null -# notification_level :integer default(1), not null -# password_expires_at :datetime -# created_by_id :integer -# last_credential_check_at :datetime -# avatar :string(255) -# confirmation_token :string(255) -# confirmed_at :datetime -# confirmation_sent_at :datetime -# unconfirmed_email :string(255) -# hide_no_ssh_key :boolean default(FALSE) -# website_url :string(255) default(""), not null -# notification_email :string(255) -# hide_no_password :boolean default(FALSE) -# password_automatically_set :boolean default(FALSE) -# location :string(255) -# encrypted_otp_secret :string(255) -# encrypted_otp_secret_iv :string(255) -# encrypted_otp_secret_salt :string(255) -# otp_required_for_login :boolean default(FALSE), not null -# otp_backup_codes :text -# public_email :string(255) default(""), not null -# dashboard :integer default(0) -# project_view :integer default(0) -# consumed_timestep :integer -# layout :integer default(0) -# hide_project_limit :boolean default(FALSE) -# unlock_token :string -# otp_grace_period_started_at :datetime -# - require 'spec_helper' describe User, models: true do -- cgit v1.2.1 From baef6728fa4e8e515ccdeba1ea54da996f322aab Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 19:59:45 +0300 Subject: Send trace to a browser incrementally when build is running We send a state of ansi2html to client, client needs to send this state back. The state describes the configuration of generator and position within trace. --- app/controllers/projects/builds_controller.rb | 15 ++++ app/models/ci/build.rb | 8 +- app/views/projects/builds/show.html.haml | 7 +- config/routes.rb | 1 + lib/ci/ansi2html.rb | 78 +++++++++++++----- spec/lib/ci/ansi2html_spec.rb | 111 ++++++++++++++++++-------- 6 files changed, 162 insertions(+), 58 deletions(-) diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index b8b9e78427d..3c9a52a5ddd 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -38,6 +38,14 @@ class Projects::BuildsController < Projects::ApplicationController end end + def trace + respond_to do |format| + format.json do + render json: @build.trace_with_state(params_state).merge!(id: @build.id, status: @build.status) + end + end + end + def retry unless @build.retryable? return render_404 @@ -72,6 +80,13 @@ class Projects::BuildsController < Projects::ApplicationController private + def params_state + begin + JSON.parse(params[:state], symbolize_names: true) + rescue + end + end + def build @build ||= project.builds.unscoped.find_by!(id: params[:id]) end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 4bc3a225e2c..1eb6a0d9023 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -132,8 +132,12 @@ module Ci end def trace_html - html = Ci::Ansi2html::convert(trace) if trace.present? - html || '' + trace_with_state[:html] + end + + def trace_with_state(state = nil) + trace_with_state = Ci::Ansi2html::convert(trace, state) if trace.present? + trace_with_state || {} end def timeout diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index c0f7a7686f0..0da0477bdd0 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,5 +1,6 @@ - page_title "#{@build.name} (##{@build.id})", "Builds" = render "header_title" +- trace = build.trace_for_state .build-page .row-content-block.top-block @@ -85,7 +86,9 @@ %pre.trace#build-trace %code.bash = preserve do - = raw @build.trace_html + = raw trace[:html] + - if @build.active? + %i{:class => "fa fa-refresh fa-spin"} %div#down-build-trace @@ -216,4 +219,4 @@ :javascript - new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}") + new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace[:state]}") diff --git a/config/routes.rb b/config/routes.rb index dafecc94648..e5c7d656da7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -672,6 +672,7 @@ Rails.application.routes.draw do post :cancel post :retry post :erase + get :trace get :raw end diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index ac6d667cf8d..d29e68570ff 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -23,8 +23,8 @@ module Ci cross: 0x10, } - def self.convert(ansi) - Converter.new().convert(ansi) + def self.convert(ansi, state = nil) + Converter.new.convert(ansi, state) end class Converter @@ -84,22 +84,36 @@ module Ci def on_107(s) set_bg_color(7, 'l') end def on_109(s) set_bg_color(9, 'l') end - def convert(ansi) - @out = "" - @n_open_tags = 0 - reset() + attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask + + STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask] + + def convert(raw, new_state) + reset_state + restore_state(new_state) if new_state && new_state[:offset].to_i < raw.length + + start = @offset + ansi = raw[@offset..-1] + + open_new_tag - s = StringScanner.new(ansi.gsub("<", "<")) + s = StringScanner.new(ansi) while(!s.eos?) if s.scan(/\e([@-_])(.*?)([@-~])/) handle_sequence(s) + elsif s.scan(/\e(([@-_])(.*?)?)?$/) + break + elsif s.scan(/ 0 } end def handle_sequence(s) @@ -121,6 +135,20 @@ module Ci evaluate_command_stack(commands) + open_new_tag + end + + def evaluate_command_stack(stack) + return unless command = stack.shift() + + if self.respond_to?("on_#{command}", true) + self.send("on_#{command}", stack) + end + + evaluate_command_stack(stack) + end + + def open_new_tag css_classes = [] unless @fg_color.nil? @@ -138,20 +166,8 @@ module Ci css_classes << "term-#{css_class}" if @style_mask & flag != 0 end - open_new_tag(css_classes) if css_classes.length > 0 - end - - def evaluate_command_stack(stack) - return unless command = stack.shift() - - if self.respond_to?("on_#{command}", true) - self.send("on_#{command}", stack) - end - - evaluate_command_stack(stack) - end + return if css_classes.empty? - def open_new_tag(css_classes) @out << %{} @n_open_tags += 1 end @@ -163,6 +179,26 @@ module Ci end end + def reset_state + @offset = 0 + @n_open_tags = 0 + @out = '' + reset + end + + def state + STATE_PARAMS.inject({}) do |h, param| + h[param] = send(param) + h + end + end + + def restore_state(new_state) + STATE_PARAMS.each do |param| + send("#{param}=".to_sym, new_state[param]) + end + end + def reset @fg_color = nil @bg_color = nil diff --git a/spec/lib/ci/ansi2html_spec.rb b/spec/lib/ci/ansi2html_spec.rb index 3a2b568f4c7..04afbd06929 100644 --- a/spec/lib/ci/ansi2html_spec.rb +++ b/spec/lib/ci/ansi2html_spec.rb @@ -4,131 +4,176 @@ describe Ci::Ansi2html, lib: true do subject { Ci::Ansi2html } it "prints non-ansi as-is" do - expect(subject.convert("Hello")).to eq('Hello') + expect(subject.convert("Hello")[:html]).to eq('Hello') end it "strips non-color-changing controll sequences" do - expect(subject.convert("Hello \e[2Kworld")).to eq('Hello world') + expect(subject.convert("Hello \e[2Kworld")[:html]).to eq('Hello world') end it "prints simply red" do - expect(subject.convert("\e[31mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[31mHello\e[0m")[:html]).to eq('Hello') end it "prints simply red without trailing reset" do - expect(subject.convert("\e[31mHello")).to eq('Hello') + expect(subject.convert("\e[31mHello")[:html]).to eq('Hello') end it "prints simply yellow" do - expect(subject.convert("\e[33mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[33mHello\e[0m")[:html]).to eq('Hello') end it "prints default on blue" do - expect(subject.convert("\e[39;44mHello")).to eq('Hello') + expect(subject.convert("\e[39;44mHello")[:html]).to eq('Hello') end it "prints red on blue" do - expect(subject.convert("\e[31;44mHello")).to eq('Hello') + expect(subject.convert("\e[31;44mHello")[:html]).to eq('Hello') end it "resets colors after red on blue" do - expect(subject.convert("\e[31;44mHello\e[0m world")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello\e[0m world")[:html]).to eq('Hello world') end it "performs color change from red/blue to yellow/blue" do - expect(subject.convert("\e[31;44mHello \e[33mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello \e[33mworld")[:html]).to eq('Hello world') end it "performs color change from red/blue to yellow/green" do - expect(subject.convert("\e[31;44mHello \e[33;42mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello \e[33;42mworld")[:html]).to eq('Hello world') end it "performs color change from red/blue to reset to yellow/green" do - expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")[:html]).to eq('Hello world') end it "ignores unsupported codes" do - expect(subject.convert("\e[51mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[51mHello\e[0m")[:html]).to eq('Hello') end it "prints light red" do - expect(subject.convert("\e[91mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[91mHello\e[0m")[:html]).to eq('Hello') end it "prints default on light red" do - expect(subject.convert("\e[101mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[101mHello\e[0m")[:html]).to eq('Hello') end it "performs color change from red/blue to default/blue" do - expect(subject.convert("\e[31;44mHello \e[39mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello \e[39mworld")[:html]).to eq('Hello world') end it "performs color change from light red/blue to default/blue" do - expect(subject.convert("\e[91;44mHello \e[39mworld")).to eq('Hello world') + expect(subject.convert("\e[91;44mHello \e[39mworld")[:html]).to eq('Hello world') end it "prints bold text" do - expect(subject.convert("\e[1mHello")).to eq('Hello') + expect(subject.convert("\e[1mHello")[:html]).to eq('Hello') end it "resets bold text" do - expect(subject.convert("\e[1mHello\e[21m world")).to eq('Hello world') - expect(subject.convert("\e[1mHello\e[22m world")).to eq('Hello world') + expect(subject.convert("\e[1mHello\e[21m world")[:html]).to eq('Hello world') + expect(subject.convert("\e[1mHello\e[22m world")[:html]).to eq('Hello world') end it "prints italic text" do - expect(subject.convert("\e[3mHello")).to eq('Hello') + expect(subject.convert("\e[3mHello")[:html]).to eq('Hello') end it "resets italic text" do - expect(subject.convert("\e[3mHello\e[23m world")).to eq('Hello world') + expect(subject.convert("\e[3mHello\e[23m world")[:html]).to eq('Hello world') end it "prints underlined text" do - expect(subject.convert("\e[4mHello")).to eq('Hello') + expect(subject.convert("\e[4mHello")[:html]).to eq('Hello') end it "resets underlined text" do - expect(subject.convert("\e[4mHello\e[24m world")).to eq('Hello world') + expect(subject.convert("\e[4mHello\e[24m world")[:html]).to eq('Hello world') end it "prints concealed text" do - expect(subject.convert("\e[8mHello")).to eq('Hello') + expect(subject.convert("\e[8mHello")[:html]).to eq('Hello') end it "resets concealed text" do - expect(subject.convert("\e[8mHello\e[28m world")).to eq('Hello world') + expect(subject.convert("\e[8mHello\e[28m world")[:html]).to eq('Hello world') end it "prints crossed-out text" do - expect(subject.convert("\e[9mHello")).to eq('Hello') + expect(subject.convert("\e[9mHello")[:html]).to eq('Hello') end it "resets crossed-out text" do - expect(subject.convert("\e[9mHello\e[29m world")).to eq('Hello world') + expect(subject.convert("\e[9mHello\e[29m world")[:html]).to eq('Hello world') end it "can print 256 xterm fg colors" do - expect(subject.convert("\e[38;5;16mHello")).to eq('Hello') + expect(subject.convert("\e[38;5;16mHello")[:html]).to eq('Hello') end it "can print 256 xterm fg colors on normal magenta background" do - expect(subject.convert("\e[38;5;16;45mHello")).to eq('Hello') + expect(subject.convert("\e[38;5;16;45mHello")[:html]).to eq('Hello') end it "can print 256 xterm bg colors" do - expect(subject.convert("\e[48;5;240mHello")).to eq('Hello') + expect(subject.convert("\e[48;5;240mHello")[:html]).to eq('Hello') end it "can print 256 xterm bg colors on normal magenta foreground" do - expect(subject.convert("\e[48;5;16;35mHello")).to eq('Hello') + expect(subject.convert("\e[48;5;16;35mHello")[:html]).to eq('Hello') end it "prints bold colored text vividly" do - expect(subject.convert("\e[1;31mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[1;31mHello\e[0m")[:html]).to eq('Hello') end it "prints bold light colored text correctly" do - expect(subject.convert("\e[1;91mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[1;91mHello\e[0m")[:html]).to eq('Hello') + end + + it "prints <" do + expect(subject.convert("<")[:html]).to eq('<') + end + + describe "incremental update" do + shared_examples 'stateable converter' do + let(:pass1) { subject.convert(pre_text) } + let(:pass2) { subject.convert(pre_text + text, pass1[:state]) } + + it "to returns html to append" do + expect(pass2[:append]).to be_truthy + expect(pass2[:html]).to eq(html) + expect(pass1[:text] + pass2[:text]).to eq(pre_text + text) + expect(pass1[:html] + pass2[:html]).to eq(pre_html + html) + end + end + + context "with split word" do + let(:pre_text) { "\e[1mHello" } + let(:pre_html) { "Hello" } + let(:text) { "\e[1mWorld" } + let(:html) { "World" } + + it_behaves_like 'stateable converter' + end + + context "with split sequence" do + let(:pre_text) { "\e[1m" } + let(:pre_html) { "" } + let(:text) { "Hello" } + let(:html) { "Hello" } + + it_behaves_like 'stateable converter' + end + + context "with partial sequence" do + let(:pre_text) { "Hello\e" } + let(:pre_html) { "Hello" } + let(:text) { "[1m World" } + let(:html) { " World" } + + it_behaves_like 'stateable converter' + end end end -- cgit v1.2.1 From 74520f23db51c95b4aea8856fb51c4246785f776 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 20:19:27 +0300 Subject: Encode state as base64 string --- app/assets/javascripts/ci/build.coffee | 21 ++++++++++++++------- app/controllers/projects/builds_controller.rb | 9 +-------- app/views/projects/builds/show.html.haml | 6 +++--- lib/ci/ansi2html.rb | 13 +++++++++---- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee index 7afe8bf79e2..fca0c3bae5c 100644 --- a/app/assets/javascripts/ci/build.coffee +++ b/app/assets/javascripts/ci/build.coffee @@ -1,9 +1,12 @@ class CiBuild @interval: null + @state: null - constructor: (build_url, build_status) -> + constructor: (build_url, build_status, build_state) -> clearInterval(CiBuild.interval) + @state = build_state + @initScrollButtonAffix() if build_status == "running" || build_status == "pending" @@ -26,14 +29,18 @@ class CiBuild CiBuild.interval = setInterval => if window.location.href.split("#").first() is build_url $.ajax - url: build_url + url: build_url + "/trace.json?state=" + encodeURIComponent(@state) dataType: "json" - success: (build) => - if build.status == "running" - $('#build-trace code').html build.trace_html - $('#build-trace code').append '' + success: (log) => + @state = log.state + if log.status is "running" + if log.append + $('.fa-refresh').before log.html + else + $('#build-trace code').html log.html + $('#build-trace code').append '' @checkAutoscroll() - else if build.status != build_status + else if log.status isnt build_status Turbolinks.visit build_url , 4000 diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 3c9a52a5ddd..bb1f6c5e980 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -41,7 +41,7 @@ class Projects::BuildsController < Projects::ApplicationController def trace respond_to do |format| format.json do - render json: @build.trace_with_state(params_state).merge!(id: @build.id, status: @build.status) + render json: @build.trace_with_state(params[:state]).merge!(id: @build.id, status: @build.status) end end end @@ -80,13 +80,6 @@ class Projects::BuildsController < Projects::ApplicationController private - def params_state - begin - JSON.parse(params[:state], symbolize_names: true) - rescue - end - end - def build @build ||= project.builds.unscoped.find_by!(id: params[:id]) end diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 0da0477bdd0..c7b9c36a3ab 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,6 +1,6 @@ - page_title "#{@build.name} (##{@build.id})", "Builds" = render "header_title" -- trace = build.trace_for_state +- trace_with_state = @build.trace_with_state .build-page .row-content-block.top-block @@ -86,7 +86,7 @@ %pre.trace#build-trace %code.bash = preserve do - = raw trace[:html] + = raw trace_with_state[:html] - if @build.active? %i{:class => "fa fa-refresh fa-spin"} @@ -219,4 +219,4 @@ :javascript - new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace[:state]}") + new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index d29e68570ff..5fed43aaebd 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -90,7 +90,7 @@ module Ci def convert(raw, new_state) reset_state - restore_state(new_state) if new_state && new_state[:offset].to_i < raw.length + restore_state(raw, new_state) if new_state start = @offset ansi = raw[@offset..-1] @@ -187,15 +187,20 @@ module Ci end def state - STATE_PARAMS.inject({}) do |h, param| + state = STATE_PARAMS.inject({}) do |h, param| h[param] = send(param) h end + Base64.urlsafe_encode64(state.to_json) end - def restore_state(new_state) + def restore_state(raw, new_state) + state = Base64.urlsafe_decode64(new_state) + state = JSON.parse(state, symbolize_names: true) + return if state[:offset].to_i > raw.length + STATE_PARAMS.each do |param| - send("#{param}=".to_sym, new_state[param]) + send("#{param}=".to_sym, state[param]) end end -- cgit v1.2.1 From 10d4d5842bed749fa3477fb8808ec1c7cc05be75 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Mon, 9 May 2016 12:20:18 -0500 Subject: Add if exists to drop command --- lib/tasks/gitlab/db.rake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake index 1c706dc11b3..e473b756023 100644 --- a/lib/tasks/gitlab/db.rake +++ b/lib/tasks/gitlab/db.rake @@ -29,10 +29,12 @@ namespace :gitlab do tables.delete 'schema_migrations' # Truncate schema_migrations to ensure migrations re-run connection.execute('TRUNCATE schema_migrations') + # Drop tables with cascade to avoid dependent table errors # PG: http://www.postgresql.org/docs/current/static/ddl-depend.html # MySQL: http://dev.mysql.com/doc/refman/5.7/en/drop-table.html - tables.each { |t| connection.execute("DROP TABLE #{t} CASCADE") } + # Add `IF EXISTS` because cascade could have already deleted a table. + tables.each { |t| connection.execute("DROP TABLE IF EXISTS #{t} CASCADE") } end end end -- cgit v1.2.1 From 849cc380d8f2ed895bde11c01987e6633bc3d567 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 7 May 2016 10:56:08 -0700 Subject: Use a case-insensitive comparison in sanitizing URI schemes Closes #1625 --- CHANGELOG | 1 + lib/banzai/filter/sanitization_filter.rb | 2 +- spec/lib/banzai/filter/sanitization_filter_spec.rb | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 63077523aaa..917f9ed3a87 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.8.0 (unreleased) - 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. - Escape HTML in commit titles in system note messages - Improve multiple branch push performance by memoizing permission checking diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index 42dbab9d27e..ca80aac5a08 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -63,7 +63,7 @@ module Banzai begin uri = Addressable::URI.parse(node['href']) - uri.scheme.strip! if uri.scheme + uri.scheme = uri.scheme.strip.downcase if uri.scheme node.remove_attribute('href') if UNSAFE_PROTOCOLS.include?(uri.scheme) rescue Addressable::URI::InvalidURIError diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb index 27ce312b11c..b38e3b17e64 100644 --- a/spec/lib/banzai/filter/sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb @@ -22,6 +22,12 @@ describe Banzai::Filter::SanitizationFilter, lib: true do expect(filter(act).to_html).to eq exp end + it 'sanitizes mixed-cased javascript in attributes' do + act = %q(
    Text) + exp = 'Text' + expect(filter(act).to_html).to eq exp + end + it 'allows whitelisted HTML tags from the user' do exp = act = "
    \n
    Term
    \n
    Definition
    \n
    " expect(filter(act).to_html).to eq exp -- cgit v1.2.1 From bf0fd3ea1bcbf0245c973411d8e5b28a15ef206f Mon Sep 17 00:00:00 2001 From: Benedikt Huss Date: Thu, 5 May 2016 01:16:16 +0200 Subject: Links for redmine issue references are generated correctly again --- CHANGELOG | 1 + lib/banzai/filter/issue_reference_filter.rb | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 63077523aaa..1c6e24bc10f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -40,6 +40,7 @@ v 8.8.0 (unreleased) v 8.7.4 - Fix always showing build notification message when switching between merge requests - Fix links on wiki pages for relative url setups. !4026 (Artem Sidorenko) + - Links for Redmine issue references are generated correctly again (Benedikt Huss) v 8.7.3 - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb index 2732e0b5145..59c5e89c546 100644 --- a/lib/banzai/filter/issue_reference_filter.rb +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -10,6 +10,9 @@ module Banzai end def self.user_can_see_reference?(user, node, context) + # It is not possible to check access rights for external issue trackers + return true if context[:project].try(:external_issue_tracker) + issue = Issue.find(node.attr('data-issue')) rescue nil Ability.abilities.allowed?(user, :read_issue, issue) end -- cgit v1.2.1 From 8eb31c40fc854ee5c1290c429d71ceb77bc5f6ba Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 9 May 2016 18:53:25 -0500 Subject: Hide navbar on mobile --- app/assets/javascripts/application.js.coffee | 1 + app/assets/javascripts/sidebar.js.coffee | 2 +- app/assets/stylesheets/framework/header.scss | 50 +++++++++++++++++++++++-- app/assets/stylesheets/framework/sidebar.scss | 40 ++++++++++++++++++++ app/assets/stylesheets/framework/variables.scss | 1 + app/assets/stylesheets/pages/profile.scss | 2 +- app/views/layouts/header/_default.html.haml | 5 ++- 7 files changed, 95 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 5bac8eef1cb..bffce5a0c0f 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -204,6 +204,7 @@ $ -> $('.header-content .title').toggle() $('.header-content .navbar-collapse').toggle() $('.navbar-toggle').toggleClass('active') + $('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left") # Show/hide comments on diff $("body").on "click", ".js-toggle-diff-comments", (e) -> diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index 860d4f438d0..ea4ac52da31 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -12,7 +12,7 @@ toggleSidebar = -> niceScrollBars.updateScrollBar(); ), 300 -$(document).on("click", '.toggle-nav-collapse', (e) -> +$(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) -> e.preventDefault() toggleSidebar() diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 97f9d582007..3bcaa17fa75 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -8,7 +8,7 @@ header { &.navbar-empty { height: 58px; background: #fff; - border-bottom: 1px solid #eee; + border-bottom: 1px solid $btn-gray-hover; .center-logo { margin: 11px 0; @@ -30,6 +30,10 @@ header { border: none; border-bottom: 1px solid $border-color; + @media (max-width: $screen-xs-min) { + padding: 0 16px; + } + &.with-horizontal-nav { border-bottom: none; } @@ -60,16 +64,44 @@ header { margin: 6px 0; border-radius: 0; position: absolute; - right: 2px; + right: -10px; + padding: 6px 10px; &:hover { - background-color: #eee; + background-color: $btn-gray-hover; } + &.active { color: $gl-icon-color; } } } + + &.header-collapsed { + padding: 0 16px; + } + + .side-nav-toggle { + display: none; + position: absolute; + left: -10px; + margin: 6px 0; + padding: 6px 10px; + border: none; + background-color: $background-color; + + &:hover { + background-color: $btn-gray-hover; + } + + &:focus { + outline: none; + } + + @media (max-width: $screen-xs-min) { + display: block; + } + } } .header-content { @@ -77,6 +109,10 @@ header { height: $header-height; padding-right: 40px; + @media (max-width: $screen-xs-min) { + padding-left: 40px; + } + @media (min-width: $screen-sm-min) { padding-right: 0; } @@ -145,6 +181,10 @@ header { @media (min-width: $screen-md-min) { @include collapsed-header; } + + @media (max-width: $screen-xs-min) { + margin-left: 0; + } } .header-expanded { @@ -153,6 +193,10 @@ header { @media (min-width: $screen-md-min) { margin-left: $sidebar_width; } + + @media (max-width: $screen-xs-min) { + margin-left: 0; + } } @media (max-width: $screen-xs-max) { diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index e940fd7286e..f4b79911b66 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -210,15 +210,33 @@ } } +.sidebar-wrapper { + &.hidden-nav { + width: 0; + } +} + .page-sidebar-collapsed { padding-left: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + padding-left: 0; + } + .sidebar-wrapper { width: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + width: 0; + } + .header-logo { width: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + width: 0; + } + a { padding-left: ($sidebar_collapsed_width - 36) / 2; @@ -244,12 +262,22 @@ .collapse-nav a { width: $sidebar_collapsed_width; + + @media (max-width: $screen-xs-min) { + width: 0; + } } .sidebar-user { padding-left: ($sidebar_collapsed_width - 36) / 2; width: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + width: 0; + padding-left: 0; + padding-right: 0; + } + .username { display: none; } @@ -258,6 +286,10 @@ .layout-nav { padding-right: $sidebar_collapsed_width; + + @media (max-width: $screen-xs-min) { + padding-right: 0;; + } } } @@ -268,6 +300,10 @@ padding-left: $sidebar_width; } + @media (max-width: $screen-xs-min) { + padding-left: 0; + } + .sidebar-wrapper { width: $sidebar_width; @@ -288,6 +324,10 @@ .layout-nav { padding-right: $sidebar_width; + + @media (max-width: $screen-xs-min) { + padding-right: 0;; + } } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index ccb4e5381b7..84e74db06b0 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -215,6 +215,7 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color; $btn-active-gray: #ececec; $btn-placeholder-gray: #c7c7c7; $btn-white-active: #848484; +$btn-gray-hover: #eee; /* * Award emoji diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index abc5a0e9877..843379a3f54 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -218,7 +218,7 @@ .btn { display: inline-block; - width: 48%; + width: 46%; } } } diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 86930d4eaaf..172579dafda 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -1,9 +1,12 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } %div{ class: fluid_layout ? "container-fluid" : "container-fluid" } .header-content - %button.navbar-toggle{type: 'button'} + %button.side-nav-toggle{type: 'button'} %span.sr-only Toggle navigation = icon('bars') + %button.navbar-toggle{type: 'button'} + %span.sr-only Toggle navigation + = icon('angle-left') .navbar-collapse.collapse %ul.nav.navbar-nav -- cgit v1.2.1 From 36f60982ce2361844e405052c597b23f66299897 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 9 May 2016 19:34:41 -0500 Subject: Fix media queries for absolutely positioned nav element --- app/assets/stylesheets/framework/header.scss | 2 +- app/assets/stylesheets/framework/nav.scss | 6 +++++- app/assets/stylesheets/framework/sidebar.scss | 10 ++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 3bcaa17fa75..51b54ceb4bd 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -22,7 +22,7 @@ header { } &.navbar-gitlab { - padding: 0 20px; + padding: 0 16px; z-index: 100; margin-bottom: 0; min-height: $header-height; diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 7c18e93a261..f2d7dc625e0 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -201,9 +201,13 @@ border-bottom: 1px solid $border-color; transition-duration: .3s; + .container-fluid { + position: relative; + } + .controls { float: right; - padding: 7px 5px 0 0; + padding: 7px 0 0; i { color: $layout-link-gray; diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index f4b79911b66..593f65aaf63 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -323,11 +323,17 @@ } .layout-nav { - padding-right: $sidebar_width; - @media (max-width: $screen-xs-min) { padding-right: 0;; } + + @media (min-width: $screen-xs-min) and (max-width: $screen-md-min) { + padding-right: 62px; + } + + @media (min-width: $screen-md-min) { + padding-right: $sidebar_width; + } } } -- cgit v1.2.1 From dd1ad6bf3e5a378eb8698e95b73e58f935eb0956 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Tue, 10 May 2016 09:56:12 +0700 Subject: Code improve --- app/views/snippets/index.html.haml | 22 +++++++++++----------- config/routes.rb | 15 ++++++++------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml index 8aa3d490fa3..7e4918a6085 100644 --- a/app/views/snippets/index.html.haml +++ b/app/views/snippets/index.html.haml @@ -1,13 +1,13 @@ - - page_title "By #{@user.name}", "Snippets" +- page_title "By #{@user.name}", "Snippets" - %ol.breadcrumb - %li - = link_to snippets_path do - Snippets - %li - = @user.name - .pull-right.hidden-xs - = link_to user_path(@user) do - #{@user.name} profile page +%ol.breadcrumb + %li + = link_to snippets_path do + Snippets + %li + = @user.name + .pull-right.hidden-xs + = link_to user_path(@user) do + #{@user.name} profile page - = render 'snippets' += render 'snippets' diff --git a/config/routes.rb b/config/routes.rb index 594bab204fd..881de37f10e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -344,15 +344,16 @@ Rails.application.routes.draw do end scope(path: 'u/:username', + as: :user, constraints: { username: /[a-zA-Z.0-9_\-]+(? Date: Tue, 10 May 2016 07:36:44 +0200 Subject: Remove the annotate rake task --- lib/tasks/auto_annotate_models.rake | 44 ------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 lib/tasks/auto_annotate_models.rake diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake deleted file mode 100644 index 16bad4bd2bd..00000000000 --- a/lib/tasks/auto_annotate_models.rake +++ /dev/null @@ -1,44 +0,0 @@ -if Rails.env.development? - task :set_annotation_options do - # You can override any of these by setting an environment variable of the - # same name. - Annotate.set_defaults( - 'routes' => 'false', - 'position_in_routes' => 'before', - 'position_in_class' => 'before', - 'position_in_test' => 'before', - 'position_in_fixture' => 'before', - 'position_in_factory' => 'before', - 'position_in_serializer' => 'before', - 'show_foreign_keys' => 'true', - 'show_indexes' => 'false', - 'simple_indexes' => 'false', - 'model_dir' => 'app/models', - 'root_dir' => '', - 'include_version' => 'false', - 'require' => '', - 'exclude_tests' => 'true', - 'exclude_fixtures' => 'true', - 'exclude_factories' => 'true', - 'exclude_serializers' => 'true', - 'exclude_scaffolds' => 'true', - 'exclude_controllers' => 'true', - 'exclude_helpers' => 'true', - 'ignore_model_sub_dir' => 'false', - 'ignore_columns' => nil, - 'ignore_unknown_models' => 'false', - 'hide_limit_column_types' => 'integer,boolean', - 'skip_on_db_migrate' => 'false', - 'format_bare' => 'true', - 'format_rdoc' => 'false', - 'format_markdown' => 'false', - 'sort' => 'false', - 'force' => 'false', - 'trace' => 'false', - 'wrapper_open' => nil, - 'wrapper_close' => nil, - ) - end - - Annotate.load_tasks -end -- cgit v1.2.1 From f52a15e022fb451fa9074495897cdd10dbeeceb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 10 May 2016 10:56:58 +0200 Subject: Revert "Merge branch 'wiki-fix' into 'master' " MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4cc85a58e8ca00f5a4ecbd2bca40a0cad867b817, reversing changes made to 90ae445ba930068d04adc5a009dbdeabe4cb3e34. Signed-off-by: Rémy Coutable --- CHANGELOG | 1 - app/models/project_wiki.rb | 2 +- lib/gitlab/url_builder.rb | 2 +- spec/lib/gitlab/url_builder_spec.rb | 2 +- spec/models/project_wiki_spec.rb | 4 +--- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1c6e24bc10f..6a5b1dce5c7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -39,7 +39,6 @@ v 8.8.0 (unreleased) v 8.7.4 - Fix always showing build notification message when switching between merge requests - - Fix links on wiki pages for relative url setups. !4026 (Artem Sidorenko) - Links for Redmine issue references are generated correctly again (Benedikt Huss) v 8.7.3 diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index c91cb70ae25..7c1a61bb0bf 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -40,7 +40,7 @@ class ProjectWiki end def wiki_base_path - [Gitlab.config.gitlab.url, "/", @project.path_with_namespace, "/wikis"].join('') + ["/", @project.path_with_namespace, "/wikis"].join('') end # Returns the Gollum::Wiki object. diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb index 67a09d5abf5..2bbbd3074e8 100644 --- a/lib/gitlab/url_builder.rb +++ b/lib/gitlab/url_builder.rb @@ -62,7 +62,7 @@ module Gitlab end def wiki_page_url - "#{object.wiki.wiki_base_path}/#{object.slug}" + "#{Gitlab.config.gitlab.url}#{object.wiki.wiki_base_path}/#{object.slug}" end end end diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index c8d3bc01395..bf11472407a 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -112,7 +112,7 @@ describe Gitlab::UrlBuilder, lib: true do wiki_page = build(:wiki_page) url = described_class.build(wiki_page) - expect(url).to eq "#{Gitlab.config.gitlab.url}/#{wiki_page.wiki.project.path_with_namespace}/wikis/#{wiki_page.slug}" + expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}" end end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index ea659f417f2..532e3f013fd 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -38,9 +38,7 @@ describe ProjectWiki, models: true do describe "#wiki_base_path" do it "returns the wiki base path" do - gitlab_url = Gitlab.config.gitlab.url - wiki_base_path = "#{gitlab_url}/#{project.path_with_namespace}/wikis" - + wiki_base_path = "/#{project.path_with_namespace}/wikis" expect(subject.wiki_base_path).to eq(wiki_base_path) end end -- cgit v1.2.1 From ebf80db3abcaf4a0e08273bf180aa33368610b8a Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 10 May 2016 11:14:46 +0200 Subject: Remove extra sanitization Robert Speicher and I believe this string gets sanitized further down the stack anyway. Doing this in a model class feels wrong. --- app/models/hooks/web_hook.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 818abbf4cc4..a5ac8bee6b9 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -59,7 +59,7 @@ class WebHook < ActiveRecord::Base basic_auth: auth) end - [response.code, 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] -- cgit v1.2.1 From f95a8e450c37e89b2d03b1c7bd2ca609a1d288e7 Mon Sep 17 00:00:00 2001 From: Calin Seciu Date: Tue, 16 Feb 2016 13:13:47 +0200 Subject: Replace text field with textarea in 'New Tag' view and display tag message in `
    `
    
    ---
     app/views/projects/tags/new.html.haml  | 2 +-
     app/views/projects/tags/show.html.haml | 7 +++----
     2 files changed, 4 insertions(+), 5 deletions(-)
    
    diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
    index b40a6e5cb2d..f9306453297 100644
    --- a/app/views/projects/tags/new.html.haml
    +++ b/app/views/projects/tags/new.html.haml
    @@ -23,7 +23,7 @@
       .form-group
         = label_tag :message, nil, class: 'control-label'
         .col-sm-10
    -      = text_field_tag :message, nil, required: false, tabindex: 3, class: 'form-control'
    +      = text_area_tag :message, nil, required: false, tabindex: 3, class: 'form-control', rows: 5
           .help-block Optionally, enter a message to create an annotated tag.
       %hr
       .form-group
    diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
    index 9c916fd02de..0442b339582 100644
    --- a/app/views/projects/tags/show.html.haml
    +++ b/app/views/projects/tags/show.html.haml
    @@ -19,14 +19,13 @@
               %i.fa.fa-trash-o
       .title
         %span.item-title= @tag.name
    -    - if @tag.message.present?
    -      %span.light
    -         
    -        = strip_gpg_signature(@tag.message)
       - if @commit
         = render 'projects/branches/commit', commit: @commit, project: @project
       - else
         Cant find HEAD commit for this tag
    +  - if @tag.message.present?
    +    %pre.body
    +      = strip_gpg_signature(@tag.message)
     
     
     .append-bottom-default.prepend-top-default
    -- 
    cgit v1.2.1
    
    
    From 1026f2ad0982493cb5465404ef4ebe71a0082bc0 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?R=C3=A9my=20Coutable?= 
    Date: Wed, 20 Apr 2016 14:34:28 +0200
    Subject: Add integration specs for tags
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Signed-off-by: Rémy Coutable 
    ---
     CHANGELOG                                     |  1 +
     app/views/projects/tags/show.html.haml        |  1 -
     features/project/commits/tags.feature         | 46 --------------
     features/steps/project/commits/tags.rb        | 90 ---------------------------
     spec/features/tags/master_creates_tag_spec.rb | 62 ++++++++++++++++++
     spec/features/tags/master_deletes_tag_spec.rb | 41 ++++++++++++
     spec/features/tags/master_updates_tag_spec.rb | 42 +++++++++++++
     spec/features/tags/master_views_tags_spec.rb  | 73 ++++++++++++++++++++++
     8 files changed, 219 insertions(+), 137 deletions(-)
     delete mode 100644 features/project/commits/tags.feature
     delete mode 100644 features/steps/project/commits/tags.rb
     create mode 100644 spec/features/tags/master_creates_tag_spec.rb
     create mode 100644 spec/features/tags/master_deletes_tag_spec.rb
     create mode 100644 spec/features/tags/master_updates_tag_spec.rb
     create mode 100644 spec/features/tags/master_views_tags_spec.rb
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 1c6e24bc10f..8159d3258a8 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -22,6 +22,7 @@ v 8.8.0 (unreleased)
       - Updated search UI
       - Display informative message when new milestone is created
       - Sanitize milestones and labels titles
    +  - Support multi-line tag messages. !3833 (Calin Seciu)
       - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea)
       - Added button to toggle whitespaces changes on diff view
       - Backport GitHub Enterprise import support from EE
    diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
    index 0442b339582..9f1424aecc7 100644
    --- a/app/views/projects/tags/show.html.haml
    +++ b/app/views/projects/tags/show.html.haml
    @@ -27,7 +27,6 @@
         %pre.body
           = strip_gpg_signature(@tag.message)
     
    -
     .append-bottom-default.prepend-top-default
       - if @release.description.present?
         .description
    diff --git a/features/project/commits/tags.feature b/features/project/commits/tags.feature
    deleted file mode 100644
    index a4be39b2d40..00000000000
    --- a/features/project/commits/tags.feature
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -@project_commits
    -Feature: Project Commits Tags
    -  Background:
    -    Given I sign in as a user
    -    And I own project "Shop"
    -    Given I visit project tags page
    -
    -  Scenario: I can see all git tags
    -    Then I should see "Shop" all tags list
    -
    -  Scenario: I create a tag
    -    And I click new tag link
    -    And I submit new tag form
    -    Then I should see new tag created
    -
    -  Scenario: I create a tag with release notes
    -    Given I click new tag link
    -    And I submit new tag form with release notes
    -    Then I should see new tag created
    -    And I should see tag release notes
    -
    -  Scenario: I create a tag with invalid name
    -    And I click new tag link
    -    And I submit new tag form with invalid name
    -    Then I should see new an error that tag is invalid
    -
    -  Scenario: I create a tag with invalid reference
    -    And I click new tag link
    -    And I submit new tag form with invalid reference
    -    Then I should see new an error that tag ref is invalid
    -
    -  Scenario: I create a tag that already exists
    -    And I click new tag link
    -    And I submit new tag form with tag that already exists
    -    Then I should see new an error that tag already exists
    -
    -  Scenario: I delete a tag
    -    Given I visit tag 'v1.1.0' page
    -    Given I delete tag 'v1.1.0'
    -    Then I should not see tag 'v1.1.0'
    -
    -  Scenario: I add release notes to the tag
    -    Given I visit tag 'v1.1.0' page
    -    When I click edit tag link
    -    And I fill release notes and submit form
    -    Then I should see tag release notes
    diff --git a/features/steps/project/commits/tags.rb b/features/steps/project/commits/tags.rb
    deleted file mode 100644
    index 912ba580efd..00000000000
    --- a/features/steps/project/commits/tags.rb
    +++ /dev/null
    @@ -1,90 +0,0 @@
    -class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps
    -  include SharedAuthentication
    -  include SharedProject
    -  include SharedPaths
    -
    -  step 'I should see "Shop" all tags list' do
    -    expect(page).to have_content "Tags"
    -    expect(page).to have_content "v1.0.0"
    -  end
    -
    -  step 'I click new tag link' do
    -    click_link 'New tag'
    -  end
    -
    -  step 'I submit new tag form' do
    -    fill_in 'tag_name', with: 'v7.0'
    -    fill_in 'ref', with: 'master'
    -    click_button 'Create tag'
    -  end
    -
    -  step 'I submit new tag form with release notes' do
    -    fill_in 'tag_name', with: 'v7.0'
    -    fill_in 'ref', with: 'master'
    -    fill_in 'release_description', with: 'Awesome release notes'
    -    click_button 'Create tag'
    -  end
    -
    -  step 'I fill release notes and submit form' do
    -    fill_in 'release_description', with: 'Awesome release notes'
    -    click_button 'Save changes'
    -  end
    -
    -  step 'I submit new tag form with invalid name' do
    -    fill_in 'tag_name', with: 'v 1.0'
    -    fill_in 'ref', with: 'master'
    -    click_button 'Create tag'
    -  end
    -
    -  step 'I submit new tag form with invalid reference' do
    -    fill_in 'tag_name', with: 'foo'
    -    fill_in 'ref', with: 'foo'
    -    click_button 'Create tag'
    -  end
    -
    -  step 'I submit new tag form with tag that already exists' do
    -    fill_in 'tag_name', with: 'v1.0.0'
    -    fill_in 'ref', with: 'master'
    -    click_button 'Create tag'
    -  end
    -
    -  step 'I should see new tag created' do
    -    expect(page).to have_content 'v7.0'
    -  end
    -
    -  step 'I should see new an error that tag is invalid' do
    -    expect(page).to have_content 'Tag name invalid'
    -  end
    -
    -  step 'I should see new an error that tag ref is invalid' do
    -    expect(page).to have_content 'Target foo is invalid'
    -  end
    -
    -  step 'I should see new an error that tag already exists' do
    -    expect(page).to have_content 'Tag v1.0.0 already exists'
    -  end
    -
    -  step "I visit tag 'v1.1.0' page" do
    -    click_link 'v1.1.0'
    -  end
    -
    -  step "I delete tag 'v1.1.0'" do
    -    page.within('.content') do
    -      first('.btn-remove').click
    -    end
    -  end
    -
    -  step "I should not see tag 'v1.1.0'" do
    -    page.within '.tags' do
    -      expect(page).not_to have_link 'v1.1.0'
    -    end
    -  end
    -
    -  step 'I click edit tag link' do
    -    click_link 'Edit release notes'
    -  end
    -
    -  step 'I should see tag release notes' do
    -    expect(page).to have_content 'Awesome release notes'
    -  end
    -end
    diff --git a/spec/features/tags/master_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb
    new file mode 100644
    index 00000000000..08a97085a9c
    --- /dev/null
    +++ b/spec/features/tags/master_creates_tag_spec.rb
    @@ -0,0 +1,62 @@
    +require 'spec_helper'
    +
    +feature 'Master creates tag', feature: true do
    +  let(:user) { create(:user) }
    +  let(:project) { create(:project, namespace: user.namespace) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +    visit namespace_project_tags_path(project.namespace, project)
    +  end
    +
    +  scenario 'with an invalid name displays an error' do
    +    create_tag_in_form(tag: 'v 1.0', ref: 'master')
    +
    +    expect(page).to have_content 'Tag name invalid'
    +  end
    +
    +  scenario 'with an invalid reference displays an error' do
    +    create_tag_in_form(tag: 'v2.0', ref: 'foo')
    +
    +    expect(page).to have_content 'Target foo is invalid'
    +  end
    +
    +  scenario 'that already exists displays an error' do
    +    create_tag_in_form(tag: 'v1.1.0', ref: 'master')
    +
    +    expect(page).to have_content 'Tag v1.1.0 already exists'
    +  end
    +
    +  scenario 'with multiline message displays the message in a 
     block' do
    +    create_tag_in_form(tag: 'v3.0', ref: 'master', message: "Awesome tag message\n\n- hello\n- world")
    +
    +    expect(current_path).to eq(
    +      namespace_project_tag_path(project.namespace, project, 'v3.0'))
    +    expect(page).to have_content 'v3.0'
    +    page.within 'pre.body' do
    +      expect(page).to have_content "Awesome tag message\n\n- hello\n- world"
    +    end
    +  end
    +
    +  scenario 'with multiline release notes parses the release note as Markdown' do
    +    create_tag_in_form(tag: 'v4.0', ref: 'master', desc: "Awesome release notes\n\n- hello\n- world")
    +
    +    expect(current_path).to eq(
    +      namespace_project_tag_path(project.namespace, project, 'v4.0'))
    +    expect(page).to have_content 'v4.0'
    +    page.within '.description' do
    +      expect(page).to have_content 'Awesome release notes'
    +      expect(page).to have_selector('ul li', count: 2)
    +    end
    +  end
    +
    +  def create_tag_in_form(tag:, ref:, message: nil, desc: nil)
    +    click_link 'New tag'
    +    fill_in 'tag_name', with: tag
    +    fill_in 'ref', with: ref
    +    fill_in 'message', with: message unless message.nil?
    +    fill_in 'release_description', with: desc unless desc.nil?
    +    click_button 'Create tag'
    +  end
    +end
    diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb
    new file mode 100644
    index 00000000000..f0990118e3c
    --- /dev/null
    +++ b/spec/features/tags/master_deletes_tag_spec.rb
    @@ -0,0 +1,41 @@
    +require 'spec_helper'
    +
    +feature 'Master deletes tag', feature: true do
    +  let(:user) { create(:user) }
    +  let(:project) { create(:project, namespace: user.namespace) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +    visit namespace_project_tags_path(project.namespace, project)
    +  end
    +
    +  context 'from the tags list page' do
    +    scenario 'deletes the tag' do
    +      expect(page).to have_content 'v1.1.0'
    +
    +      page.within('.content') do
    +        first('.btn-remove').click
    +      end
    +
    +      expect(current_path).to eq(
    +        namespace_project_tags_path(project.namespace, project))
    +      expect(page).not_to have_content 'v1.1.0'
    +    end
    +
    +  end
    +
    +  context 'from a specific tag page' do
    +    scenario 'deletes the tag' do
    +      click_on 'v1.0.0'
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +
    +      click_on 'Delete tag'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tags_path(project.namespace, project))
    +      expect(page).not_to have_content 'v1.0.0'
    +    end
    +  end
    +end
    diff --git a/spec/features/tags/master_updates_tag_spec.rb b/spec/features/tags/master_updates_tag_spec.rb
    new file mode 100644
    index 00000000000..c926e9841f3
    --- /dev/null
    +++ b/spec/features/tags/master_updates_tag_spec.rb
    @@ -0,0 +1,42 @@
    +require 'spec_helper'
    +
    +feature 'Master updates tag', feature: true do
    +  let(:user) { create(:user) }
    +  let(:project) { create(:project, namespace: user.namespace) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +    visit namespace_project_tags_path(project.namespace, project)
    +  end
    +
    +  context 'from the tags list page' do
    +    scenario 'updates the release notes' do
    +      page.within(first('.controls')) do
    +        click_link 'Edit release notes'
    +      end
    +
    +      fill_in 'release_description', with: 'Awesome release notes'
    +      click_button 'Save changes'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.1.0'))
    +      expect(page).to have_content 'v1.1.0'
    +      expect(page).to have_content 'Awesome release notes'
    +    end
    +  end
    +
    +  context 'from a specific tag page' do
    +    scenario 'updates the release notes' do
    +      click_on 'v1.1.0'
    +      click_link 'Edit release notes'
    +      fill_in 'release_description', with: 'Awesome release notes'
    +      click_button 'Save changes'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.1.0'))
    +      expect(page).to have_content 'v1.1.0'
    +      expect(page).to have_content 'Awesome release notes'
    +    end
    +  end
    +end
    diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb
    new file mode 100644
    index 00000000000..29d2c244720
    --- /dev/null
    +++ b/spec/features/tags/master_views_tags_spec.rb
    @@ -0,0 +1,73 @@
    +require 'spec_helper'
    +
    +feature 'Master views tags', feature: true do
    +  let(:user) { create(:user) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +  end
    +
    +  context 'when project has no tags' do
    +    let(:project) { create(:project_empty_repo) }
    +    before do
    +      visit namespace_project_path(project.namespace, project)
    +      click_on 'README'
    +      fill_in :commit_message, with: 'Add a README file', visible: true
    +      # Remove pre-receive hook so we can push without auth
    +      FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive'))
    +      click_button 'Commit Changes'
    +      visit namespace_project_tags_path(project.namespace, project)
    +    end
    +
    +    scenario 'displays a specific message' do
    +      expect(page).to have_content 'Repository has no tags yet.'
    +    end
    +  end
    +
    +  context 'when project has tags' do
    +    let(:project) { create(:project, namespace: user.namespace) }
    +    before do
    +      visit namespace_project_tags_path(project.namespace, project)
    +    end
    +
    +    scenario 'views the tags list page' do
    +      expect(page).to have_content 'v1.0.0'
    +    end
    +
    +    scenario 'views a specific tag page' do
    +      click_on 'v1.0.0'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +      expect(page).to have_content 'v1.0.0'
    +      expect(page).to have_content 'This tag has no release notes.'
    +    end
    +
    +    describe 'links on the tag page' do
    +      scenario 'has a button to browse files' do
    +        click_on 'v1.0.0'
    +
    +        expect(current_path).to eq(
    +          namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +
    +        click_on 'Browse files'
    +
    +        expect(current_path).to eq(
    +          namespace_project_tree_path(project.namespace, project, 'v1.0.0'))
    +      end
    +
    +      scenario 'has a button to browse commits' do
    +        click_on 'v1.0.0'
    +
    +        expect(current_path).to eq(
    +          namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +
    +        click_on 'Browse commits'
    +
    +        expect(current_path).to eq(
    +          namespace_project_commits_path(project.namespace, project, 'v1.0.0'))
    +      end
    +    end
    +  end
    +end
    -- 
    cgit v1.2.1
    
    
    From 6da3388569b3bf31ac72663a4c13dba83d064356 Mon Sep 17 00:00:00 2001
    From: Stan Hu 
    Date: Tue, 5 Apr 2016 09:43:48 -0700
    Subject: Add eager load paths to help prevent dependency load issues with
     Sidekiq workers
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Attempts to address #13521, #14825
    
    Signed-off-by: Rémy Coutable 
    ---
     CHANGELOG             |  2 ++
     config/application.rb | 19 +++++++++++++------
     2 files changed, 15 insertions(+), 6 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 6a5b1dce5c7..80ed7d2020a 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -91,6 +91,8 @@ v 8.7.0
       - Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524
       - Improved Markdown rendering performance !3389
       - Make shared runners text in box configurable
    +  - Add eager load paths to help prevent dependency load issues with Sidekiq workers (Stan Hu)
    +  - Improved Markdown rendering performance !3389 (Yorick Peterse)
       - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu)
       - API: Ability to subscribe and unsubscribe from issues and merge requests (Robert Schilling)
       - Expose project badges in project settings
    diff --git a/config/application.rb b/config/application.rb
    index b602e2b6168..b33e57f5fcd 100644
    --- a/config/application.rb
    +++ b/config/application.rb
    @@ -12,12 +12,19 @@ module Gitlab
         # 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/hooks
    +                                     #{config.root}/app/models/concerns
    +                                     #{config.root}/app/models/project_services
    +                                     #{config.root}/app/models/members))
     
         # 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.
    -- 
    cgit v1.2.1
    
    
    From 5589dcf8db0daf2235158724f6b18115a9abfa42 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?R=C3=A9my=20Coutable?= 
    Date: Fri, 15 Apr 2016 17:35:40 +0200
    Subject: Fix a few places where autoloading would fail
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    - Fix naming of API::CommitStatuses
    - Ensure we use require_dependency instead of require
    - Ensure the namespace is right in lib/api/api.rb, otherwise, we
      might require Grape::API::Helpers which defines the `#params` method.
      This is to avoid requiring a file multiple times and getting an "Already
      initialized constant" error.
    
    Signed-off-by: Rémy Coutable 
    ---
     CHANGELOG                                 |   3 +-
     app/models/repository.rb                  |   2 +-
     config/application.rb                     |  12 +-
     config/initializers/1_settings.rb         |   2 +-
     config/initializers/5_backend.rb          |   6 +-
     lib/api/api.rb                            |  69 ++++----
     lib/api/api_guard.rb                      | 270 +++++++++++++++---------------
     lib/api/commit_statuses.rb                |   2 +-
     lib/ci/api/api.rb                         |  10 +-
     lib/gitlab.rb                             |   2 +-
     spec/requests/api/commit_status_spec.rb   | 210 -----------------------
     spec/requests/api/commit_statuses_spec.rb | 210 +++++++++++++++++++++++
     12 files changed, 399 insertions(+), 399 deletions(-)
     delete mode 100644 spec/requests/api/commit_status_spec.rb
     create mode 100644 spec/requests/api/commit_statuses_spec.rb
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 80ed7d2020a..1cd428323d8 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -29,6 +29,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)
    @@ -91,8 +92,6 @@ v 8.7.0
       - Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524
       - Improved Markdown rendering performance !3389
       - Make shared runners text in box configurable
    -  - Add eager load paths to help prevent dependency load issues with Sidekiq workers (Stan Hu)
    -  - Improved Markdown rendering performance !3389 (Yorick Peterse)
       - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu)
       - API: Ability to subscribe and unsubscribe from issues and merge requests (Robert Schilling)
       - Expose project badges in project settings
    diff --git a/app/models/repository.rb b/app/models/repository.rb
    index 7aebfe279fb..a4b42d7226d 100644
    --- a/app/models/repository.rb
    +++ b/app/models/repository.rb
    @@ -81,7 +81,7 @@ class Repository
       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
    diff --git a/config/application.rb b/config/application.rb
    index b33e57f5fcd..cba80f38f1f 100644
    --- a/config/application.rb
    +++ b/config/application.rb
    @@ -1,13 +1,13 @@
     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.
    @@ -21,10 +21,10 @@ module Gitlab
         # 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/concerns
    -                                     #{config.root}/app/models/project_services
    -                                     #{config.root}/app/models/members))
    +                                     #{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.
    diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
    index 8db2c05fe45..23c8cea038a 100644
    --- a/config/initializers/1_settings.rb
    +++ b/config/initializers/1_settings.rb
    @@ -1,4 +1,4 @@
    -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" }
    diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
    index 80d641d73a3..e026151a032 100644
    --- a/config/initializers/5_backend.rb
    +++ b/config/initializers/5_backend.rb
    @@ -1,11 +1,11 @@
     # 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)
    diff --git a/lib/api/api.rb b/lib/api/api.rb
    index cc1004f8005..5fd9c30cb42 100644
    --- a/lib/api/api.rb
    +++ b/lib/api/api.rb
    @@ -1,5 +1,3 @@
    -Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file}
    -
     module API
       class API < Grape::API
         include APIGuard
    @@ -25,38 +23,39 @@ module 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
    diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
    index b9994fcefda..7e67edb203a 100644
    --- a/lib/api/api_guard.rb
    +++ b/lib/api/api_guard.rb
    @@ -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|
    +      # OAuth2 Resource Server Authentication
    +      use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request|
    +        # The authenticator only fetches the raw token string
     
    -      # Must yield access token to store it in the env
    -      request.access_token
    -    end
    +        # Must yield access token to store it in the env
    +        request.access_token
    +      end
     
    -    helpers HelperMethods
    +      helpers HelperMethods
     
    -    install_error_responders(base)
    -  end
    +      install_error_responders(base)
    +    end
     
    -  # Helper Methods for Grape Endpoint
    -  module HelperMethods
    -    # Invokes the doorkeeper guard.
    -    #
    -    # If token is presented and valid, then it sets @current_user.
    -    #
    -    # If the token does not have sufficient scopes to cover the requred scopes,
    -    # then it raises InsufficientScopeError.
    -    #
    -    # If the token is expired, then it raises ExpiredError.
    -    #
    -    # If the token is revoked, then it raises RevokedError.
    -    #
    -    # If the token is not found (nil), then it raises TokenNotFoundError.
    -    #
    -    # Arguments:
    -    #
    -    #   scopes: (optional) scopes required for this guard.
    -    #           Defaults to empty array.
    -    #
    -    def doorkeeper_guard!(scopes: [])
    -      if (access_token = find_access_token).nil?
    -        raise TokenNotFoundError
    -
    -      else
    -        case validate_access_token(access_token, scopes)
    -        when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
    -          raise InsufficientScopeError.new(scopes)
    -        when Oauth2::AccessTokenValidationService::EXPIRED
    -          raise ExpiredError
    -        when Oauth2::AccessTokenValidationService::REVOKED
    -          raise RevokedError
    -        when Oauth2::AccessTokenValidationService::VALID
    -          @current_user = User.find(access_token.resource_owner_id)
    +    # Helper Methods for Grape Endpoint
    +    module HelperMethods
    +      # Invokes the doorkeeper guard.
    +      #
    +      # If token is presented and valid, then it sets @current_user.
    +      #
    +      # If the token does not have sufficient scopes to cover the requred scopes,
    +      # then it raises InsufficientScopeError.
    +      #
    +      # If the token is expired, then it raises ExpiredError.
    +      #
    +      # If the token is revoked, then it raises RevokedError.
    +      #
    +      # If the token is not found (nil), then it raises TokenNotFoundError.
    +      #
    +      # Arguments:
    +      #
    +      #   scopes: (optional) scopes required for this guard.
    +      #           Defaults to empty array.
    +      #
    +      def doorkeeper_guard!(scopes: [])
    +        if (access_token = find_access_token).nil?
    +          raise TokenNotFoundError
    +
    +        else
    +          case validate_access_token(access_token, scopes)
    +          when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
    +            raise InsufficientScopeError.new(scopes)
    +          when Oauth2::AccessTokenValidationService::EXPIRED
    +            raise ExpiredError
    +          when Oauth2::AccessTokenValidationService::REVOKED
    +            raise RevokedError
    +          when Oauth2::AccessTokenValidationService::VALID
    +            @current_user = User.find(access_token.resource_owner_id)
    +          end
             end
           end
    -    end
     
    -    def doorkeeper_guard(scopes: [])
    -      if access_token = find_access_token
    -        case validate_access_token(access_token, scopes)
    -        when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
    -          raise InsufficientScopeError.new(scopes)
    +      def doorkeeper_guard(scopes: [])
    +        if access_token = find_access_token
    +          case validate_access_token(access_token, scopes)
    +          when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
    +            raise InsufficientScopeError.new(scopes)
     
    -        when Oauth2::AccessTokenValidationService::EXPIRED
    -          raise ExpiredError
    +          when Oauth2::AccessTokenValidationService::EXPIRED
    +            raise ExpiredError
     
    -        when Oauth2::AccessTokenValidationService::REVOKED
    -          raise RevokedError
    +          when Oauth2::AccessTokenValidationService::REVOKED
    +            raise RevokedError
     
    -        when Oauth2::AccessTokenValidationService::VALID
    -          @current_user = User.find(access_token.resource_owner_id)
    +          when Oauth2::AccessTokenValidationService::VALID
    +            @current_user = User.find(access_token.resource_owner_id)
    +          end
             end
           end
    -    end
     
    -    def current_user
    -      @current_user
    -    end
    +      def current_user
    +        @current_user
    +      end
     
    -    private
    -    def find_access_token
    -      @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods)
    -    end
    +      private
     
    -    def doorkeeper_request
    -      @doorkeeper_request ||= ActionDispatch::Request.new(env)
    -    end
    +      def find_access_token
    +        @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods)
    +      end
     
    -    def validate_access_token(access_token, scopes)
    -      Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes)
    -    end
    -  end
    +      def doorkeeper_request
    +        @doorkeeper_request ||= ActionDispatch::Request.new(env)
    +      end
     
    -  module ClassMethods
    -    # Installs the doorkeeper guard on the whole Grape API endpoint.
    -    #
    -    # Arguments:
    -    #
    -    #   scopes: (optional) scopes required for this guard.
    -    #           Defaults to empty array.
    -    #
    -    def guard_all!(scopes: [])
    -      before do
    -        guard! scopes: scopes
    +      def validate_access_token(access_token, scopes)
    +        Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes)
           end
         end
     
    -    private
    -    def install_error_responders(base)
    -      error_classes = [ MissingTokenError, TokenNotFoundError,
    -                        ExpiredError, RevokedError, InsufficientScopeError]
    +    module ClassMethods
    +      # Installs the doorkeeper guard on the whole Grape API endpoint.
    +      #
    +      # Arguments:
    +      #
    +      #   scopes: (optional) scopes required for this guard.
    +      #           Defaults to empty array.
    +      #
    +      def guard_all!(scopes: [])
    +        before do
    +          guard! scopes: scopes
    +        end
    +      end
     
    -      base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
    -    end
    +      private
     
    -    def oauth2_bearer_token_error_handler
    -      Proc.new do |e|
    -        response =
    -          case e
    -          when MissingTokenError
    -            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new
    -
    -          when TokenNotFoundError
    -            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
    -              :invalid_token,
    -              "Bad Access Token.")
    -
    -          when ExpiredError
    -            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
    -              :invalid_token,
    -              "Token is expired. You can either do re-authorization or token refresh.")
    -
    -          when RevokedError
    -            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
    -              :invalid_token,
    -              "Token was revoked. You have to re-authorize from the user.")
    -
    -          when InsufficientScopeError
    -            # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2)
    -            # does not include WWW-Authenticate header, which breaks the standard.
    -            Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(
    -              :insufficient_scope,
    -              Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope],
    -              { scope: e.scopes })
    -          end
    +      def install_error_responders(base)
    +        error_classes = [ MissingTokenError, TokenNotFoundError,
    +                          ExpiredError, RevokedError, InsufficientScopeError]
     
    -        response.finish
    +        base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
    +      end
    +
    +      def oauth2_bearer_token_error_handler
    +        Proc.new do |e|
    +          response =
    +            case e
    +            when MissingTokenError
    +              Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new
    +
    +            when TokenNotFoundError
    +              Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
    +                :invalid_token,
    +                "Bad Access Token.")
    +
    +            when ExpiredError
    +              Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
    +                :invalid_token,
    +                "Token is expired. You can either do re-authorization or token refresh.")
    +
    +            when RevokedError
    +              Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
    +                :invalid_token,
    +                "Token was revoked. You have to re-authorize from the user.")
    +
    +            when InsufficientScopeError
    +              # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2)
    +              # does not include WWW-Authenticate header, which breaks the standard.
    +              Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(
    +                :insufficient_scope,
    +                Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope],
    +                { scope: e.scopes })
    +            end
    +
    +          response.finish
    +        end
           end
         end
    -  end
     
    -  #
    -  # Exceptions
    -  #
    +    #
    +    # Exceptions
    +    #
     
    -  class MissingTokenError < StandardError; end
    +    class MissingTokenError < StandardError; end
     
    -  class TokenNotFoundError < StandardError; end
    +    class TokenNotFoundError < StandardError; end
     
    -  class ExpiredError < StandardError; end
    +    class ExpiredError < StandardError; end
     
    -  class RevokedError < StandardError; end
    +    class RevokedError < StandardError; end
     
    -  class InsufficientScopeError < StandardError
    -    attr_reader :scopes
    -    def initialize(scopes)
    -      @scopes = scopes
    +    class InsufficientScopeError < StandardError
    +      attr_reader :scopes
    +      def initialize(scopes)
    +        @scopes = scopes
    +      end
         end
       end
     end
    diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
    index 7388ed2f4ea..9bcd33ff19e 100644
    --- a/lib/api/commit_statuses.rb
    +++ b/lib/api/commit_statuses.rb
    @@ -2,7 +2,7 @@ require 'mime/types'
     
     module API
       # Project commit statuses API
    -  class CommitStatus < Grape::API
    +  class CommitStatuses < Grape::API
         resource :projects do
           before { authenticate! }
     
    diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb
    index 353c4ddebf8..17bb99a2ae5 100644
    --- a/lib/ci/api/api.rb
    +++ b/lib/ci/api/api.rb
    @@ -1,9 +1,7 @@
    -Dir["#{Rails.root}/lib/ci/api/*.rb"].each {|file| require file}
    -
     module Ci
       module API
         class API < Grape::API
    -      include APIGuard
    +      include ::API::APIGuard
           version 'v1', using: :path
     
           rescue_from ActiveRecord::RecordNotFound do
    @@ -31,9 +29,9 @@ module Ci
           helpers ::API::Helpers
           helpers Gitlab::CurrentSettings
     
    -      mount Builds
    -      mount Runners
    -      mount Triggers
    +      mount ::Ci::API::Builds
    +      mount ::Ci::API::Runners
    +      mount ::Ci::API::Triggers
         end
       end
     end
    diff --git a/lib/gitlab.rb b/lib/gitlab.rb
    index 7479e729db1..37f4c34054f 100644
    --- a/lib/gitlab.rb
    +++ b/lib/gitlab.rb
    @@ -1,4 +1,4 @@
    -require 'gitlab/git'
    +require_dependency 'gitlab/git'
     
     module Gitlab
       def self.com?
    diff --git a/spec/requests/api/commit_status_spec.rb b/spec/requests/api/commit_status_spec.rb
    deleted file mode 100644
    index f3785b19362..00000000000
    --- a/spec/requests/api/commit_status_spec.rb
    +++ /dev/null
    @@ -1,210 +0,0 @@
    -require 'spec_helper'
    -
    -describe API::CommitStatus, api: true do
    -  include ApiHelpers
    -
    -  let!(:project) { create(:project) }
    -  let(:commit) { project.repository.commit }
    -  let(:commit_status) { create(:commit_status, commit: ci_commit) }
    -  let(:guest) { create_user(:guest) }
    -  let(:reporter) { create_user(:reporter) }
    -  let(:developer) { create_user(:developer) }
    -  let(:sha) { commit.id }
    -
    -
    -  describe "GET /projects/:id/repository/commits/:sha/statuses" do
    -    let(:get_url) { "/projects/#{project.id}/repository/commits/#{sha}/statuses" }
    -
    -    context 'ci commit exists' do
    -      let!(:master) { project.ci_commits.create(sha: commit.id, ref: 'master') }
    -      let!(:develop) { project.ci_commits.create(sha: commit.id, ref: 'develop') }
    -
    -      it_behaves_like 'a paginated resources' do
    -        let(:request) { get api(get_url, reporter) }
    -      end
    -
    -      context "reporter user" do
    -        let(:statuses_id) { json_response.map { |status| status['id'] } }
    -
    -        def create_status(commit, opts = {})
    -          create(:commit_status, { commit: commit, ref: commit.ref }.merge(opts))
    -        end
    -
    -        let!(:status1) { create_status(master, status: 'running') }
    -        let!(:status2) { create_status(master, name: 'coverage', status: 'pending') }
    -        let!(:status3) { create_status(develop, status: 'running', allow_failure: true) }
    -        let!(:status4) { create_status(master, name: 'coverage', status: 'success') }
    -        let!(:status5) { create_status(develop, name: 'coverage', status: 'success') }
    -        let!(:status6) { create_status(master, status: 'success') }
    -
    -        context 'latest commit statuses' do
    -          before { get api(get_url, reporter) }
    -
    -          it 'returns latest commit statuses' do
    -            expect(response.status).to eq(200)
    -
    -            expect(json_response).to be_an Array
    -            expect(statuses_id).to contain_exactly(status3.id, status4.id, status5.id, status6.id)
    -            json_response.sort_by!{ |status| status['id'] }
    -            expect(json_response.map{ |status| status['allow_failure'] }).to eq([true, false, false, false])
    -          end
    -        end
    -
    -        context 'all commit statuses' do
    -          before { get api(get_url, reporter), all: 1 }
    -
    -          it 'returns all commit statuses' do
    -            expect(response.status).to eq(200)
    -
    -            expect(json_response).to be_an Array
    -            expect(statuses_id).to contain_exactly(status1.id, status2.id,
    -                                                   status3.id, status4.id,
    -                                                   status5.id, status6.id)
    -          end
    -        end
    -
    -        context 'latest commit statuses for specific ref' do
    -          before { get api(get_url, reporter), ref: 'develop' }
    -
    -          it 'returns latest commit statuses for specific ref' do
    -            expect(response.status).to eq(200)
    -
    -            expect(json_response).to be_an Array
    -            expect(statuses_id).to contain_exactly(status3.id, status5.id)
    -          end
    -        end
    -
    -        context 'latest commit statues for specific name' do
    -          before { get api(get_url, reporter), name: 'coverage' }
    -
    -          it 'return latest commit statuses for specific name' do
    -            expect(response.status).to eq(200)
    -
    -            expect(json_response).to be_an Array
    -            expect(statuses_id).to contain_exactly(status4.id, status5.id)
    -          end
    -        end
    -      end
    -    end
    -
    -    context 'ci commit does not exist' do
    -      before { get api(get_url, reporter) }
    -
    -      it 'returns empty array' do
    -        expect(response.status).to eq 200
    -        expect(json_response).to be_an Array
    -        expect(json_response).to be_empty
    -      end
    -    end
    -
    -    context "guest user" do
    -      before { get api(get_url, guest) }
    -
    -      it "should not return project commits" do
    -        expect(response.status).to eq(403)
    -      end
    -    end
    -
    -    context "unauthorized user" do
    -      before { get api(get_url) }
    -
    -      it "should not return project commits" do
    -        expect(response.status).to eq(401)
    -      end
    -    end
    -  end
    -
    -  describe 'POST /projects/:id/statuses/:sha' do
    -    let(:post_url) { "/projects/#{project.id}/statuses/#{sha}" }
    -
    -    context 'developer user' do
    -      context 'only required parameters' do
    -        before { post api(post_url, developer), state: 'success' }
    -
    -        it 'creates commit status' do
    -          expect(response.status).to eq(201)
    -          expect(json_response['sha']).to eq(commit.id)
    -          expect(json_response['status']).to eq('success')
    -          expect(json_response['name']).to eq('default')
    -          expect(json_response['ref']).to be_nil
    -          expect(json_response['target_url']).to be_nil
    -          expect(json_response['description']).to be_nil
    -        end
    -      end
    -
    -      context 'with all optional parameters' do
    -        before do
    -          optional_params = { state: 'success', context: 'coverage',
    -                              ref: 'develop', target_url: 'url', description: 'test' }
    -
    -          post api(post_url, developer), optional_params
    -        end
    -
    -        it 'creates commit status' do
    -          expect(response.status).to eq(201)
    -          expect(json_response['sha']).to eq(commit.id)
    -          expect(json_response['status']).to eq('success')
    -          expect(json_response['name']).to eq('coverage')
    -          expect(json_response['ref']).to eq('develop')
    -          expect(json_response['target_url']).to eq('url')
    -          expect(json_response['description']).to eq('test')
    -        end
    -      end
    -
    -      context 'invalid status' do
    -        before { post api(post_url, developer), state: 'invalid' }
    -
    -        it 'does not create commit status' do
    -          expect(response.status).to eq(400)
    -        end
    -      end
    -
    -      context 'request without state' do
    -        before { post api(post_url, developer) }
    -
    -        it 'does not create commit status' do
    -          expect(response.status).to eq(400)
    -        end
    -      end
    -
    -      context 'invalid commit' do
    -        let(:sha) { 'invalid_sha' }
    -        before { post api(post_url, developer), state: 'running' }
    -
    -        it 'returns not found error' do
    -          expect(response.status).to eq(404)
    -        end
    -      end
    -    end
    -
    -    context 'reporter user' do
    -      before { post api(post_url, reporter) }
    -
    -      it 'should not create commit status' do
    -        expect(response.status).to eq(403)
    -      end
    -    end
    -
    -    context 'guest user' do
    -      before { post api(post_url, guest) }
    -
    -      it 'should not create commit status' do
    -        expect(response.status).to eq(403)
    -      end
    -    end
    -
    -    context 'unauthorized user' do
    -      before { post api(post_url) }
    -
    -      it 'should not create commit status' do
    -        expect(response.status).to eq(401)
    -      end
    -    end
    -  end
    -
    -  def create_user(access_level_trait)
    -    user = create(:user)
    -    create(:project_member, access_level_trait, user: user, project: project)
    -    user
    -  end
    -end
    diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
    new file mode 100644
    index 00000000000..633927c8c3e
    --- /dev/null
    +++ b/spec/requests/api/commit_statuses_spec.rb
    @@ -0,0 +1,210 @@
    +require 'spec_helper'
    +
    +describe API::CommitStatuses, api: true do
    +  include ApiHelpers
    +
    +  let!(:project) { create(:project) }
    +  let(:commit) { project.repository.commit }
    +  let(:commit_status) { create(:commit_status, commit: ci_commit) }
    +  let(:guest) { create_user(:guest) }
    +  let(:reporter) { create_user(:reporter) }
    +  let(:developer) { create_user(:developer) }
    +  let(:sha) { commit.id }
    +
    +
    +  describe "GET /projects/:id/repository/commits/:sha/statuses" do
    +    let(:get_url) { "/projects/#{project.id}/repository/commits/#{sha}/statuses" }
    +
    +    context 'ci commit exists' do
    +      let!(:master) { project.ci_commits.create(sha: commit.id, ref: 'master') }
    +      let!(:develop) { project.ci_commits.create(sha: commit.id, ref: 'develop') }
    +
    +      it_behaves_like 'a paginated resources' do
    +        let(:request) { get api(get_url, reporter) }
    +      end
    +
    +      context "reporter user" do
    +        let(:statuses_id) { json_response.map { |status| status['id'] } }
    +
    +        def create_status(commit, opts = {})
    +          create(:commit_status, { commit: commit, ref: commit.ref }.merge(opts))
    +        end
    +
    +        let!(:status1) { create_status(master, status: 'running') }
    +        let!(:status2) { create_status(master, name: 'coverage', status: 'pending') }
    +        let!(:status3) { create_status(develop, status: 'running', allow_failure: true) }
    +        let!(:status4) { create_status(master, name: 'coverage', status: 'success') }
    +        let!(:status5) { create_status(develop, name: 'coverage', status: 'success') }
    +        let!(:status6) { create_status(master, status: 'success') }
    +
    +        context 'latest commit statuses' do
    +          before { get api(get_url, reporter) }
    +
    +          it 'returns latest commit statuses' do
    +            expect(response.status).to eq(200)
    +
    +            expect(json_response).to be_an Array
    +            expect(statuses_id).to contain_exactly(status3.id, status4.id, status5.id, status6.id)
    +            json_response.sort_by!{ |status| status['id'] }
    +            expect(json_response.map{ |status| status['allow_failure'] }).to eq([true, false, false, false])
    +          end
    +        end
    +
    +        context 'all commit statuses' do
    +          before { get api(get_url, reporter), all: 1 }
    +
    +          it 'returns all commit statuses' do
    +            expect(response.status).to eq(200)
    +
    +            expect(json_response).to be_an Array
    +            expect(statuses_id).to contain_exactly(status1.id, status2.id,
    +                                                   status3.id, status4.id,
    +                                                   status5.id, status6.id)
    +          end
    +        end
    +
    +        context 'latest commit statuses for specific ref' do
    +          before { get api(get_url, reporter), ref: 'develop' }
    +
    +          it 'returns latest commit statuses for specific ref' do
    +            expect(response.status).to eq(200)
    +
    +            expect(json_response).to be_an Array
    +            expect(statuses_id).to contain_exactly(status3.id, status5.id)
    +          end
    +        end
    +
    +        context 'latest commit statues for specific name' do
    +          before { get api(get_url, reporter), name: 'coverage' }
    +
    +          it 'return latest commit statuses for specific name' do
    +            expect(response.status).to eq(200)
    +
    +            expect(json_response).to be_an Array
    +            expect(statuses_id).to contain_exactly(status4.id, status5.id)
    +          end
    +        end
    +      end
    +    end
    +
    +    context 'ci commit does not exist' do
    +      before { get api(get_url, reporter) }
    +
    +      it 'returns empty array' do
    +        expect(response.status).to eq 200
    +        expect(json_response).to be_an Array
    +        expect(json_response).to be_empty
    +      end
    +    end
    +
    +    context "guest user" do
    +      before { get api(get_url, guest) }
    +
    +      it "should not return project commits" do
    +        expect(response.status).to eq(403)
    +      end
    +    end
    +
    +    context "unauthorized user" do
    +      before { get api(get_url) }
    +
    +      it "should not return project commits" do
    +        expect(response.status).to eq(401)
    +      end
    +    end
    +  end
    +
    +  describe 'POST /projects/:id/statuses/:sha' do
    +    let(:post_url) { "/projects/#{project.id}/statuses/#{sha}" }
    +
    +    context 'developer user' do
    +      context 'only required parameters' do
    +        before { post api(post_url, developer), state: 'success' }
    +
    +        it 'creates commit status' do
    +          expect(response.status).to eq(201)
    +          expect(json_response['sha']).to eq(commit.id)
    +          expect(json_response['status']).to eq('success')
    +          expect(json_response['name']).to eq('default')
    +          expect(json_response['ref']).to be_nil
    +          expect(json_response['target_url']).to be_nil
    +          expect(json_response['description']).to be_nil
    +        end
    +      end
    +
    +      context 'with all optional parameters' do
    +        before do
    +          optional_params = { state: 'success', context: 'coverage',
    +                              ref: 'develop', target_url: 'url', description: 'test' }
    +
    +          post api(post_url, developer), optional_params
    +        end
    +
    +        it 'creates commit status' do
    +          expect(response.status).to eq(201)
    +          expect(json_response['sha']).to eq(commit.id)
    +          expect(json_response['status']).to eq('success')
    +          expect(json_response['name']).to eq('coverage')
    +          expect(json_response['ref']).to eq('develop')
    +          expect(json_response['target_url']).to eq('url')
    +          expect(json_response['description']).to eq('test')
    +        end
    +      end
    +
    +      context 'invalid status' do
    +        before { post api(post_url, developer), state: 'invalid' }
    +
    +        it 'does not create commit status' do
    +          expect(response.status).to eq(400)
    +        end
    +      end
    +
    +      context 'request without state' do
    +        before { post api(post_url, developer) }
    +
    +        it 'does not create commit status' do
    +          expect(response.status).to eq(400)
    +        end
    +      end
    +
    +      context 'invalid commit' do
    +        let(:sha) { 'invalid_sha' }
    +        before { post api(post_url, developer), state: 'running' }
    +
    +        it 'returns not found error' do
    +          expect(response.status).to eq(404)
    +        end
    +      end
    +    end
    +
    +    context 'reporter user' do
    +      before { post api(post_url, reporter) }
    +
    +      it 'should not create commit status' do
    +        expect(response.status).to eq(403)
    +      end
    +    end
    +
    +    context 'guest user' do
    +      before { post api(post_url, guest) }
    +
    +      it 'should not create commit status' do
    +        expect(response.status).to eq(403)
    +      end
    +    end
    +
    +    context 'unauthorized user' do
    +      before { post api(post_url) }
    +
    +      it 'should not create commit status' do
    +        expect(response.status).to eq(401)
    +      end
    +    end
    +  end
    +
    +  def create_user(access_level_trait)
    +    user = create(:user)
    +    create(:project_member, access_level_trait, user: user, project: project)
    +    user
    +  end
    +end
    -- 
    cgit v1.2.1
    
    
    From bbc94e15a3f66852ac3283388327e25d92ae9c0a Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Tue, 10 May 2016 13:07:14 +0200
    Subject: Use abbrevation in runners table in admin area
    
    ---
     app/views/admin/runners/_runner.html.haml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
    index 97b6ec1f85d..36b21eefdee 100644
    --- a/app/views/admin/runners/_runner.html.haml
    +++ b/app/views/admin/runners/_runner.html.haml
    @@ -14,7 +14,7 @@
         = runner.description
       %td
         - if runner.shared?
    -      = '-'
    +      n/a
         - else
           = runner.projects.count(:all)
       %td
    -- 
    cgit v1.2.1
    
    
    From 0f1cf1d87b74aa1e6ca2c28fdfa21d189bd68181 Mon Sep 17 00:00:00 2001
    From: Dmitriy Zaporozhets 
    Date: Tue, 10 May 2016 13:16:09 +0200
    Subject: Minor consistency fixes to sidebar & header
    
    Signed-off-by: Dmitriy Zaporozhets 
    ---
     app/assets/stylesheets/framework/header.scss  | 2 +-
     app/assets/stylesheets/framework/sidebar.scss | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
    index 51b54ceb4bd..8190a97ed58 100644
    --- a/app/assets/stylesheets/framework/header.scss
    +++ b/app/assets/stylesheets/framework/header.scss
    @@ -25,7 +25,7 @@ header {
         padding: 0 16px;
         z-index: 100;
         margin-bottom: 0;
    -    min-height: $header-height;
    +    height: $header-height;
         background-color: $background-color;
         border: none;
         border-bottom: 1px solid $border-color;
    diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
    index 593f65aaf63..bd91f51708c 100644
    --- a/app/assets/stylesheets/framework/sidebar.scss
    +++ b/app/assets/stylesheets/framework/sidebar.scss
    @@ -98,7 +98,7 @@
       }
     
       .sidebar-user {
    -    padding: 9px 22px;
    +    padding: 7px 22px;
         position: fixed;
         bottom: 40px;
         width: $sidebar_width;
    -- 
    cgit v1.2.1
    
    
    From 98d8e3fe9ff4d120469378490c41381ae751597e Mon Sep 17 00:00:00 2001
    From: Dmitriy Zaporozhets 
    Date: Tue, 10 May 2016 13:24:53 +0200
    Subject: Change dashboard button color to white on hover
    
    Signed-off-by: Dmitriy Zaporozhets 
    ---
     app/assets/stylesheets/framework/gitlab-theme.scss | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
    index c83cf881596..dc4668877f2 100644
    --- a/app/assets/stylesheets/framework/gitlab-theme.scss
    +++ b/app/assets/stylesheets/framework/gitlab-theme.scss
    @@ -24,6 +24,10 @@
             background-color: $color-darker;
             a {
               color: #fff;
    +
    +          h3 {
    +            color: #fff;
    +          }
             }
           }
         }
    -- 
    cgit v1.2.1
    
    
    From 4c506c4498192b6d60a3731ad5428e2354b777cb Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Sat, 7 May 2016 21:28:04 +0200
    Subject: Fix using link to uploads in global snippets
    
    Closes #17342, closes #17363
    ---
     lib/banzai/filter/upload_link_filter.rb           |  4 +++-
     spec/lib/banzai/filter/upload_link_filter_spec.rb | 18 ++++++++++++++++++
     2 files changed, 21 insertions(+), 1 deletion(-)
    
    diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb
    index 7edfe5ade2d..483d40c46df 100644
    --- a/lib/banzai/filter/upload_link_filter.rb
    +++ b/lib/banzai/filter/upload_link_filter.rb
    @@ -31,7 +31,9 @@ module Banzai
           end
     
           def build_url(uri)
    -        File.join(Gitlab.config.gitlab.url, context[:project].path_with_namespace, uri)
    +        return '#' unless project = context[:project]
    +
    +        File.join(Gitlab.config.gitlab.url, project.path_with_namespace, uri)
           end
     
           # Ensure that a :project key exists in context
    diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb
    index 3b073a90a95..7a7103079ea 100644
    --- a/spec/lib/banzai/filter/upload_link_filter_spec.rb
    +++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb
    @@ -8,6 +8,10 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do
           project: project
         })
     
    +    raw_filter(doc, contexts)
    +  end
    +
    +  def raw_filter(doc, contexts = {})
         described_class.call(doc, contexts)
       end
     
    @@ -70,4 +74,18 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do
           expect(doc.at_css('img')['src']).to match "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/%ED%95%9C%EA%B8%80.png"
         end
       end
    +
    +  context 'when project context does not exist' do
    +    let(:upload_link) { link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg') }
    +
    +    it 'does not raise error' do
    +      expect { raw_filter(upload_link, project: nil) }.to_not raise_error
    +    end
    +
    +    it 'provides an empty link' do
    +      doc = raw_filter(upload_link, project: nil)
    +
    +      expect(doc.at_css('a')['href']).to eq '#'
    +    end
    +  end
     end
    -- 
    cgit v1.2.1
    
    
    From c97a81d274ff0e7b792ed409385318c4ec25d92e Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Sat, 7 May 2016 21:34:30 +0200
    Subject: Add Changelog entry for upload link in snippet fix
    
    ---
     CHANGELOG | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index b07b7da3300..841f5870d55 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -1,6 +1,7 @@
     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)
       - Project#open_branches has been cleaned up and no longer loads entire records into memory.
       - Escape HTML in commit titles in system note messages
    -- 
    cgit v1.2.1
    
    
    From 535be93a77ec677dbb561f8c1545a60d0d908832 Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Tue, 10 May 2016 13:46:04 +0200
    Subject: Do not process upload links if no project context
    
    ---
     lib/banzai/filter/upload_link_filter.rb           | 8 ++++++--
     spec/lib/banzai/filter/upload_link_filter_spec.rb | 6 +++---
     2 files changed, 9 insertions(+), 5 deletions(-)
    
    diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb
    index 483d40c46df..c0f503c9af3 100644
    --- a/lib/banzai/filter/upload_link_filter.rb
    +++ b/lib/banzai/filter/upload_link_filter.rb
    @@ -8,6 +8,8 @@ module Banzai
         #
         class UploadLinkFilter < HTML::Pipeline::Filter
           def call
    +        return doc unless project
    +
             doc.search('a').each do |el|
               process_link_attr el.attribute('href')
             end
    @@ -31,11 +33,13 @@ module Banzai
           end
     
           def build_url(uri)
    -        return '#' unless project = context[:project]
    -
             File.join(Gitlab.config.gitlab.url, project.path_with_namespace, uri)
           end
     
    +      def project
    +        context[:project]
    +      end
    +
           # Ensure that a :project key exists in context
           #
           # Note that while the key might exist, its value could be nil!
    diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb
    index 7a7103079ea..b83be54746c 100644
    --- a/spec/lib/banzai/filter/upload_link_filter_spec.rb
    +++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb
    @@ -79,13 +79,13 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do
         let(:upload_link) { link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg') }
     
         it 'does not raise error' do
    -      expect { raw_filter(upload_link, project: nil) }.to_not raise_error
    +      expect { raw_filter(upload_link, project: nil) }.not_to raise_error
         end
     
    -    it 'provides an empty link' do
    +    it 'does not rewrite link' do
           doc = raw_filter(upload_link, project: nil)
     
    -      expect(doc.at_css('a')['href']).to eq '#'
    +      expect(doc.to_html).to eq upload_link
         end
       end
     end
    -- 
    cgit v1.2.1
    
    
    From 732e98eee7da718d282903844649d02f935fd2be Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Mon, 9 May 2016 12:47:44 +0200
    Subject: Reuse runners edit form in admin and project area
    
    ---
     app/views/admin/runners/show.html.haml     | 22 +++-------------------
     app/views/projects/runners/_form.html.haml | 25 +++++++++++++++++++++++++
     app/views/projects/runners/edit.html.haml  | 26 +-------------------------
     3 files changed, 29 insertions(+), 44 deletions(-)
     create mode 100644 app/views/projects/runners/_form.html.haml
    
    diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
    index 8700b4820cd..4dfb3ed05bb 100644
    --- a/app/views/admin/runners/show.html.haml
    +++ b/app/views/admin/runners/show.html.haml
    @@ -22,25 +22,9 @@
         %h4 This runner will process builds only from ASSIGNED projects
         %p You can't make this a shared runner.
     %hr
    -= form_for @runner, url: admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f|
    -  .form-group
    -    = label_tag :token, class: 'control-label' do
    -      Token
    -    .col-sm-10
    -      = f.text_field :token, class: 'form-control', readonly: true
    -  .form-group
    -    = label_tag :description, class: 'control-label' do
    -      Description
    -    .col-sm-10
    -      = f.text_field :description, class: 'form-control'
    -  .form-group
    -    = label_tag :tag_list, class: 'control-label' do
    -      Tags
    -    .col-sm-10
    -      = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
    -      .help-block You can setup builds to only use runners with specific tags
    -  .form-actions
    -    = f.submit 'Save', class: 'btn btn-save'
    +
    +.append-bottom-20
    +  = render '/projects/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner)
     
     .row
       .col-md-6
    diff --git a/app/views/projects/runners/_form.html.haml b/app/views/projects/runners/_form.html.haml
    new file mode 100644
    index 00000000000..2d6c964ae94
    --- /dev/null
    +++ b/app/views/projects/runners/_form.html.haml
    @@ -0,0 +1,25 @@
    += form_for runner, url: runner_form_url, html: { class: 'form-horizontal' } do |f|
    +  .form-group
    +    = label :active, "Active", class: 'control-label'
    +    .col-sm-10
    +      .checkbox
    +        = f.check_box :active
    +        %span.light Paused runners don't accept new builds
    +  .form-group
    +    = label_tag :token, class: 'control-label' do
    +      Token
    +    .col-sm-10
    +      = f.text_field :token, class: 'form-control', readonly: true
    +  .form-group
    +    = label_tag :description, class: 'control-label' do
    +      Description
    +    .col-sm-10
    +      = f.text_field :description, class: 'form-control'
    +  .form-group
    +    = label_tag :tag_list, class: 'control-label' do
    +      Tags
    +    .col-sm-10
    +      = f.text_field :tag_list, value: runner.tag_list.to_s, class: 'form-control'
    +      .help-block You can setup jobs to only use runners with specific tags
    +  .form-actions
    +    = f.submit 'Save changes', class: 'btn btn-save'
    diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
    index eba03028af8..771947d7908 100644
    --- a/app/views/projects/runners/edit.html.haml
    +++ b/app/views/projects/runners/edit.html.haml
    @@ -2,28 +2,4 @@
     
     %h4 Runner ##{@runner.id}
     %hr
    -= form_for @runner, url: runner_path(@runner), html: { class: 'form-horizontal' } do |f|
    -  .form-group
    -    = label :active, "Active", class: 'control-label'
    -    .col-sm-10
    -      .checkbox
    -        = f.check_box :active
    -        %span.light Paused runners don't accept new builds
    -  .form-group
    -    = label_tag :token, class: 'control-label' do
    -      Token
    -    .col-sm-10
    -      = f.text_field :token, class: 'form-control', readonly: true
    -  .form-group
    -    = label_tag :description, class: 'control-label' do
    -      Description
    -    .col-sm-10
    -      = f.text_field :description, class: 'form-control'
    -  .form-group
    -    = label_tag :tag_list, class: 'control-label' do
    -      Tags
    -    .col-sm-10
    -      = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
    -      .help-block You can setup jobs to only use runners with specific tags
    -  .form-actions
    -    = f.submit 'Save changes', class: 'btn btn-save'
    + = render 'form', runner: @runner, runner_form_url: runner_path(@runner)
    -- 
    cgit v1.2.1
    
    
    From 7d6d3421d64085c05c8b7a17dcf0b70fbdd478b5 Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Mon, 9 May 2016 13:07:10 +0200
    Subject: Share form editable attributes mf runner via model
    
    ---
     app/controllers/admin/runners_controller.rb    | 2 +-
     app/controllers/projects/runners_controller.rb | 2 +-
     app/models/ci/runner.rb                        | 1 +
     3 files changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
    index a701d49b844..8b8a7320072 100644
    --- a/app/controllers/admin/runners_controller.rb
    +++ b/app/controllers/admin/runners_controller.rb
    @@ -58,6 +58,6 @@ class Admin::RunnersController < Admin::ApplicationController
       end
     
       def runner_params
    -    params.require(:runner).permit(:token, :description, :tag_list, :active)
    +    params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
       end
     end
    diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
    index 0dd2d6a99be..3a9d67aff64 100644
    --- a/app/controllers/projects/runners_controller.rb
    +++ b/app/controllers/projects/runners_controller.rb
    @@ -64,6 +64,6 @@ class Projects::RunnersController < Projects::ApplicationController
       end
     
       def runner_params
    -    params.require(:runner).permit(:description, :tag_list, :active)
    +    params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
       end
     end
    diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
    index add59a08892..d27963e8ec5 100644
    --- a/app/models/ci/runner.rb
    +++ b/app/models/ci/runner.rb
    @@ -23,6 +23,7 @@ module Ci
     
         LAST_CONTACT_TIME = 5.minutes.ago
         AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online']
    +    FORM_EDITABLE = [:description, :tag_list, :active]
     
         has_many :builds, class_name: 'Ci::Build'
         has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
    -- 
    cgit v1.2.1
    
    
    From 67dc3b9c1131b5a7f3f861a0fe35169fda5cd398 Mon Sep 17 00:00:00 2001
    From: DJ Mountney 
    Date: Fri, 22 Apr 2016 09:50:08 -0700
    Subject: Add the health_check gem end expose the health_check route
    
    ---
     Gemfile                             |  3 +++
     Gemfile.lock                        |  3 +++
     config/initializers/health_check.rb | 28 ++++++++++++++++++++++++++++
     config/routes.rb                    |  3 +++
     4 files changed, 37 insertions(+)
     create mode 100644 config/initializers/health_check.rb
    
    diff --git a/Gemfile b/Gemfile
    index 3e5c604ae06..204d19f7115 100644
    --- a/Gemfile
    +++ b/Gemfile
    @@ -333,3 +333,6 @@ gem 'oauth2', '~> 1.0.0'
     
     # Soft deletion
     gem "paranoia", "~> 2.0"
    +
    +# Health check
    +gem 'health_check', '~> 1.5.1'
    diff --git a/Gemfile.lock b/Gemfile.lock
    index 86b9142ef27..de0f536641b 100644
    --- a/Gemfile.lock
    +++ b/Gemfile.lock
    @@ -402,6 +402,8 @@ GEM
           html2haml (>= 1.0.1)
           railties (>= 4.0.1)
         hashie (3.4.3)
    +    health_check (1.5.1)
    +      rails (>= 2.3.0)
         highline (1.7.8)
         hipchat (1.5.2)
           httparty
    @@ -947,6 +949,7 @@ DEPENDENCIES
       grape (~> 0.13.0)
       grape-entity (~> 0.4.2)
       haml-rails (~> 0.9.0)
    +  health_check (~> 1.5.1)
       hipchat (~> 1.5.0)
       html-pipeline (~> 1.11.0)
       httparty (~> 0.13.3)
    diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
    new file mode 100644
    index 00000000000..c111cfdf5ce
    --- /dev/null
    +++ b/config/initializers/health_check.rb
    @@ -0,0 +1,28 @@
    +# HealthCheck.setup do |config|
    +#   # Text output upon success
    +#   config.success = 'success'
    +#
    +#   # Timeout in seconds used when checking smtp server
    +#   config.smtp_timeout = 30.0
    +#
    +#   # http status code used when plain text error message is output
    +#   # Set to 200 if you want your want to distinguish between partial (text does not include success) and
    +#   # total failure of rails application (http status of 500 etc)
    +#   config.http_status_for_error_text = 500
    +#
    +#   # http status code used when an error object is output (json or xml)
    +#   # Set to 200 if you want your want to distinguish between partial (healthy property == false) and
    +#   # total failure of rails application (http status of 500 etc)
    +#   config.http_status_for_error_object = 500
    +#
    +#   # You can customize which checks happen on a standard health check
    +#   config.standard_checks = [ 'database', 'migrations', 'custom' ]
    +#
    +#   # You can set what tests are run with the 'full' or 'all' parameter
    +#   config.full_checks = ['database', 'migrations', 'custom', 'email', 'cache']
    +#
    +#   # Add one or more custom checks that return a blank string if ok, or an error message if there is an error
    +#   config.add_custom_check do
    +#      any code that returns blank on success and non blank string upon failure
    +#   end
    +# end
    diff --git a/config/routes.rb b/config/routes.rb
    index dafecc94648..cac800b9a9c 100644
    --- a/config/routes.rb
    +++ b/config/routes.rb
    @@ -73,6 +73,9 @@ Rails.application.routes.draw do
         mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
       end
     
    +  # Health check
    +  health_check_routes
    +
       # Enable Grack support
       mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post, :put]
     
    -- 
    cgit v1.2.1
    
    
    From 9898f9b4e6b80edaa914675edfa9b229498b31fe Mon Sep 17 00:00:00 2001
    From: DJ Mountney 
    Date: Thu, 5 May 2016 12:25:02 -0700
    Subject: Set the standard health_check options to include the cache check.
    
    ---
     config/initializers/health_check.rb | 31 +++----------------------------
     1 file changed, 3 insertions(+), 28 deletions(-)
    
    diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
    index c111cfdf5ce..a93e4273030 100644
    --- a/config/initializers/health_check.rb
    +++ b/config/initializers/health_check.rb
    @@ -1,28 +1,3 @@
    -# HealthCheck.setup do |config|
    -#   # Text output upon success
    -#   config.success = 'success'
    -#
    -#   # Timeout in seconds used when checking smtp server
    -#   config.smtp_timeout = 30.0
    -#
    -#   # http status code used when plain text error message is output
    -#   # Set to 200 if you want your want to distinguish between partial (text does not include success) and
    -#   # total failure of rails application (http status of 500 etc)
    -#   config.http_status_for_error_text = 500
    -#
    -#   # http status code used when an error object is output (json or xml)
    -#   # Set to 200 if you want your want to distinguish between partial (healthy property == false) and
    -#   # total failure of rails application (http status of 500 etc)
    -#   config.http_status_for_error_object = 500
    -#
    -#   # You can customize which checks happen on a standard health check
    -#   config.standard_checks = [ 'database', 'migrations', 'custom' ]
    -#
    -#   # You can set what tests are run with the 'full' or 'all' parameter
    -#   config.full_checks = ['database', 'migrations', 'custom', 'email', 'cache']
    -#
    -#   # Add one or more custom checks that return a blank string if ok, or an error message if there is an error
    -#   config.add_custom_check do
    -#      any code that returns blank on success and non blank string upon failure
    -#   end
    -# end
    +HealthCheck.setup do |config|
    +  config.standard_checks = [ 'database', 'migrations', 'cache' ]
    +end
    -- 
    cgit v1.2.1
    
    
    From 160ef66d1bbbbc593516c7575d6b02ddb019c000 Mon Sep 17 00:00:00 2001
    From: DJ Mountney 
    Date: Mon, 9 May 2016 16:21:22 -0700
    Subject: Add health_check access token, and enforce on the health_check
     endpoint
    
    Also added a health check page to the admin section for resetting the token.
    ---
     .../admin/application_settings_controller.rb       |  6 ++++
     app/controllers/admin/health_check_controller.rb   |  9 +++++
     app/controllers/health_check_controller.rb         | 13 +++++++
     app/models/application_setting.rb                  |  6 ++++
     app/views/admin/health_check/show.html.haml        | 40 ++++++++++++++++++++++
     app/views/layouts/nav/_admin.html.haml             |  5 +++
     config/routes.rb                                   |  4 ++-
     ...h_check_access_token_to_application_settings.rb |  5 +++
     db/schema.rb                                       |  3 +-
     9 files changed, 89 insertions(+), 2 deletions(-)
     create mode 100644 app/controllers/admin/health_check_controller.rb
     create mode 100644 app/controllers/health_check_controller.rb
     create mode 100644 app/views/admin/health_check/show.html.haml
     create mode 100644 db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
    
    diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
    index ec22548ddeb..7b9a88cd319 100644
    --- a/app/controllers/admin/application_settings_controller.rb
    +++ b/app/controllers/admin/application_settings_controller.rb
    @@ -19,6 +19,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
         redirect_to admin_runners_path
       end
     
    +  def reset_health_check_token
    +    @application_setting.reset_health_check_access_token!
    +    flash[:notice] = 'New health check access token has been generated!'
    +    redirect_to :back
    +  end
    +
       def clear_repository_check_states
         RepositoryCheck::ClearWorker.perform_async
     
    diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb
    new file mode 100644
    index 00000000000..3153a765e35
    --- /dev/null
    +++ b/app/controllers/admin/health_check_controller.rb
    @@ -0,0 +1,9 @@
    +class Admin::HealthCheckController < Admin::ApplicationController
    +  def show
    +    begin
    +      @errors = HealthCheck::Utils.process_checks('standard')
    +    rescue => e
    +      @errors = e.message.blank? ? e.class.to_s : e.message.to_s
    +    end
    +  end
    +end
    diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb
    new file mode 100644
    index 00000000000..b974489836f
    --- /dev/null
    +++ b/app/controllers/health_check_controller.rb
    @@ -0,0 +1,13 @@
    +class HealthCheckController < HealthCheck::HealthCheckController
    +  before_action :validate_health_check_access!
    +
    +  protected
    +
    +  def validate_health_check_access!
    +    return render_404 unless params[:token].presence && params[:token] == current_application_settings.health_check_access_token
    +  end
    +
    +  def render_404
    +    render file: Rails.root.join("public", "404"), layout: false, status: "404"
    +  end
    +end
    diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
    index 7039db2d41e..bf88326c116 100644
    --- a/app/models/application_setting.rb
    +++ b/app/models/application_setting.rb
    @@ -1,6 +1,7 @@
     class ApplicationSetting < ActiveRecord::Base
       include TokenAuthenticatable
       add_authentication_token_field :runners_registration_token
    +  add_authentication_token_field :health_check_access_token
     
       CACHE_KEY = 'application_setting.last'
     
    @@ -70,6 +71,7 @@ class ApplicationSetting < ActiveRecord::Base
       end
     
       before_save :ensure_runners_registration_token
    +  before_save :ensure_health_check_access_token
     
       after_commit do
         Rails.cache.write(CACHE_KEY, self)
    @@ -133,4 +135,8 @@ class ApplicationSetting < ActiveRecord::Base
       def runners_registration_token
         ensure_runners_registration_token!
       end
    +
    +  def health_check_access_token
    +    ensure_health_check_access_token!
    +  end
     end
    diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
    new file mode 100644
    index 00000000000..70e5d04e356
    --- /dev/null
    +++ b/app/views/admin/health_check/show.html.haml
    @@ -0,0 +1,40 @@
    +- page_title "Health Check"
    +
    +%h3.page-title
    +  Health Check
    +%p.light
    +  Health information can be reteived as plain text, json, or xml using:
    +  %ul
    +    %li
    +      %code= "/health_check?token=#{current_application_settings.health_check_access_token}"
    +    %li
    +      %code= "/health_check.json?token=#{current_application_settings.health_check_access_token}"
    +    %li
    +      %code= "/health_check.xml?token=#{current_application_settings.health_check_access_token}"
    +
    +.bs-callout.clearfix
    +  .pull-left
    +    %p
    +      You can reset the health check access token by pressing the button below.
    +    %p
    +      = button_to reset_health_check_token_admin_application_settings_path,
    +        method: :put, class: 'btn btn-default',
    +        data: { confirm: 'Are you sure you want to reset the health check token?' } do
    +        = icon('refresh')
    +        Reset health check access token
    +
    +%hr
    +.panel.panel-default
    +  .panel-heading
    +    Current Status:
    +    - if @errors.blank?
    +      = icon('circle', class: 'cgreen')
    +      Healthy
    +    - else
    +      = icon('warning', class: 'cred')
    +      Unhealthy
    +  .panel-body
    +    - if @errors.blank?
    +      No Health Problems Detected
    +    - else
    +      = @errors
    diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml
    index 280a1b93729..f292730fe45 100644
    --- a/app/views/layouts/nav/_admin.html.haml
    +++ b/app/views/layouts/nav/_admin.html.haml
    @@ -41,6 +41,11 @@
           = icon('file-text fw')
           %span
             Logs
    +  = nav_link(controller: :health_check) do
    +    = link_to admin_health_check_path, title: 'Health Check' do
    +      = icon('medkit fw')
    +      %span
    +        Health Check
       = nav_link(controller: :broadcast_messages) do
         = link_to admin_broadcast_messages_path, title: 'Messages' do
           = icon('bullhorn fw')
    diff --git a/config/routes.rb b/config/routes.rb
    index cac800b9a9c..c81bf294a53 100644
    --- a/config/routes.rb
    +++ b/config/routes.rb
    @@ -74,7 +74,7 @@ Rails.application.routes.draw do
       end
     
       # Health check
    -  health_check_routes
    +  get 'health_check(/:checks)(.:format)'  => 'health_check#index'
     
       # Enable Grack support
       mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post, :put]
    @@ -256,6 +256,7 @@ Rails.application.routes.draw do
         end
     
         resource :logs, only: [:show]
    +    resource :health_check, controller: 'health_check', only: [:show]
         resource :background_jobs, controller: 'background_jobs', only: [:show]
     
         resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
    @@ -287,6 +288,7 @@ Rails.application.routes.draw do
         resource :application_settings, only: [:show, :update] do
           resources :services
           put :reset_runners_token
    +      put :reset_health_check_token
           put :clear_repository_check_states
         end
     
    diff --git a/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
    new file mode 100644
    index 00000000000..9d729fec189
    --- /dev/null
    +++ b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
    @@ -0,0 +1,5 @@
    +class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration
    +  def change
    +    add_column :application_settings, :health_check_access_token, :string
    +  end
    +end
    diff --git a/db/schema.rb b/db/schema.rb
    index 71d953afe30..8ac3eeae62d 100644
    --- a/db/schema.rb
    +++ b/db/schema.rb
    @@ -11,7 +11,7 @@
     #
     # It's strongly recommended that you check this file into your version control system.
     
    -ActiveRecord::Schema.define(version: 20160508194200) do
    +ActiveRecord::Schema.define(version: 20160509201028) do
     
       # These are extensions that must be enabled in order to support this database
       enable_extension "plpgsql"
    @@ -80,6 +80,7 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.boolean  "repository_checks_enabled",         default: false
         t.text     "shared_runners_text"
         t.integer  "metrics_packet_size",               default: 1
    +    t.string   "health_check_access_token"
       end
     
       create_table "audit_events", force: :cascade do |t|
    -- 
    cgit v1.2.1
    
    
    From a278b36ab0f30e8bfa491256bddf9de1c0572382 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?R=C3=A9my=20Coutable?= 
    Date: Fri, 22 Apr 2016 18:32:08 +0200
    Subject: Fix an issue when filtering merge requests with more than one label
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Signed-off-by: Rémy Coutable 
    ---
     CHANGELOG                                          |   1 +
     app/models/concerns/issuable.rb                    |   4 +-
     .../user_lists_merge_requests_spec.rb              | 137 +++++++++++++++++++++
     3 files changed, 140 insertions(+), 2 deletions(-)
     create mode 100644 spec/features/merge_requests/user_lists_merge_requests_spec.rb
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 1c21ad36b69..499febdfd08 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -43,6 +43,7 @@ v 8.8.0 (unreleased)
     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)
    +  - Fix an issue when filtering merge requests with more than one label. !3886
     
     v 8.7.3
       - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
    diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
    index 7a3db742030..c1248b53031 100644
    --- a/app/models/concerns/issuable.rb
    +++ b/app/models/concerns/issuable.rb
    @@ -124,8 +124,8 @@ module Issuable
         end
     
         def with_label(title)
    -      if title.is_a?(Array) && title.count > 1
    -        joins(:labels).where(labels: { title: title }).group('issues.id').having("count(distinct labels.title) = #{title.count}")
    +      if title.is_a?(Array) && title.size > 1
    +        joins(:labels).where(labels: { title: title }).group(arel_table[:id]).having("COUNT(DISTINCT labels.title) = #{title.size}")
           else
             joins(:labels).where(labels: { title: title })
           end
    diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
    new file mode 100644
    index 00000000000..cc7f78e7325
    --- /dev/null
    +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
    @@ -0,0 +1,137 @@
    +require 'spec_helper'
    +
    +describe 'Projects > Merge requests > User lists merge requests', feature: true do
    +  include SortingHelper
    +
    +  let(:project) { create(:project, :public) }
    +  let(:user) { create(:user) }
    +
    +  before do
    +    @fix = create(:merge_request,
    +                  title: 'fix',
    +                  source_project: project,
    +                  source_branch: 'fix',
    +                  assignee: user,
    +                  milestone: create(:milestone, due_date: '2013-12-11'),
    +                  created_at: 1.minute.ago,
    +                  updated_at: 1.minute.ago)
    +    create(:merge_request,
    +           title: 'markdown',
    +           source_project: project,
    +           source_branch: 'markdown',
    +           assignee: user,
    +           milestone: create(:milestone, due_date: '2013-12-12'),
    +           created_at: 2.minutes.ago,
    +           updated_at: 2.minutes.ago)
    +    create(:merge_request,
    +           title: 'lfs',
    +           source_project: project,
    +           source_branch: 'lfs',
    +           created_at: 3.minutes.ago,
    +           updated_at: 10.seconds.ago)
    +  end
    +
    +  it 'filters on no assignee' do
    +    visit_merge_requests(project, assignee_id: IssuableFinder::NONE)
    +
    +    expect(current_path).to eq(namespace_project_merge_requests_path(project.namespace, project))
    +    expect(page).to have_content 'lfs'
    +    expect(page).not_to have_content 'fix'
    +    expect(page).not_to have_content 'markdown'
    +  end
    +
    +  it 'filters on a specific assignee' do
    +    visit_merge_requests(project, assignee_id: user.id)
    +
    +    expect(page).not_to have_content 'lfs'
    +    expect(page).to have_content 'fix'
    +    expect(page).to have_content 'markdown'
    +  end
    +
    +  it 'sorts by newest' do
    +    visit_merge_requests(project, sort: sort_value_recently_created)
    +
    +    expect(first_merge_request).to include('lfs')
    +    expect(last_merge_request).to include('fix')
    +  end
    +
    +  it 'sorts by oldest' do
    +    visit_merge_requests(project, sort: sort_value_oldest_created)
    +
    +    expect(first_merge_request).to include('fix')
    +    expect(last_merge_request).to include('lfs')
    +  end
    +
    +  it 'sorts by last updated' do
    +    visit_merge_requests(project, sort: sort_value_recently_updated)
    +
    +    expect(first_merge_request).to include('lfs')
    +  end
    +
    +  it 'sorts by oldest updated' do
    +    visit_merge_requests(project, sort: sort_value_oldest_updated)
    +
    +    expect(first_merge_request).to include('markdown')
    +  end
    +
    +  it 'sorts by milestone due soon' do
    +    visit_merge_requests(project, sort: sort_value_milestone_soon)
    +
    +    expect(first_merge_request).to include('fix')
    +  end
    +
    +  it 'sorts by milestone due later' do
    +    visit_merge_requests(project, sort: sort_value_milestone_later)
    +
    +    expect(first_merge_request).to include('markdown')
    +  end
    +
    +  it 'filters on one label and sorts by due soon' do
    +    label = create(:label, project: project)
    +    create(:label_link, label: label, target: @fix)
    +
    +    visit_merge_requests(project, label_name: [label.name],
    +                                  sort: sort_value_due_date_soon)
    +
    +    expect(first_merge_request).to include('fix')
    +  end
    +
    +  context 'while filtering on two labels' do
    +    let(:label) { create(:label, project: project) }
    +    let(:label2) { create(:label, project: project) }
    +
    +    before do
    +      create(:label_link, label: label, target: @fix)
    +      create(:label_link, label: label2, target: @fix)
    +    end
    +
    +    it 'sorts by due soon' do
    +      visit_merge_requests(project, label_name: [label.name, label2.name],
    +                                    sort: sort_value_due_date_soon)
    +
    +      expect(first_merge_request).to include('fix')
    +    end
    +
    +    context 'filter on assignee and' do
    +      it 'sorts by due soon' do
    +        visit_merge_requests(project, label_name: [label.name, label2.name],
    +                                      assignee_id: user.id,
    +                                      sort: sort_value_due_date_soon)
    +
    +        expect(first_merge_request).to include('fix')
    +      end
    +    end
    +  end
    +
    +  def visit_merge_requests(project, opts = {})
    +    visit namespace_project_merge_requests_path(project.namespace, project, opts)
    +  end
    +
    +  def first_merge_request
    +    page.all('ul.mr-list > li').first.text
    +  end
    +
    +  def last_merge_request
    +    page.all('ul.mr-list > li').last.text
    +  end
    +end
    -- 
    cgit v1.2.1
    
    
    From 97424ea544d0954e582a356586270e983d3bbb7a Mon Sep 17 00:00:00 2001
    From: Sean McGivern 
    Date: Tue, 10 May 2016 18:03:55 +0100
    Subject: Restrict starred projects to viewable ones
    
    `User#starred_projects` doesn't perform any visibility checks. This has
    a couple of problems:
    
    1. It assumes a user can always view all of their starred projects in
       perpetuity (project not changed to private, access revoked, etc.).
    2. It assumes that we'll only ever allow a user to star a project they
       can view. This is currently the case, but bugs happen.
    
    Add `User#viewable_starred_projects` to filter the starred projects by
    those the user either has explicit access to, or are public or
    internal. Then use that in all places where we list the user's starred
    projects.
    ---
     app/controllers/dashboard/projects_controller.rb |  2 +-
     app/controllers/dashboard_controller.rb          |  2 +-
     app/models/user.rb                               |  5 +++++
     lib/api/projects.rb                              |  2 +-
     spec/models/user_spec.rb                         | 24 ++++++++++++++++++++++++
     spec/requests/api/projects_spec.rb               | 21 +++++++++------------
     6 files changed, 41 insertions(+), 15 deletions(-)
    
    diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
    index 71acc244a91..c08eb811532 100644
    --- a/app/controllers/dashboard/projects_controller.rb
    +++ b/app/controllers/dashboard/projects_controller.rb
    @@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
       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])
    diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
    index 1dce4a21729..4dda4e51f6a 100644
    --- a/app/controllers/dashboard_controller.rb
    +++ b/app/controllers/dashboard_controller.rb
    @@ -25,7 +25,7 @@ class DashboardController < Dashboard::ApplicationController
       def load_events
         projects =
           if params[:filter] == "starred"
    -        current_user.starred_projects
    +        current_user.viewable_starred_projects
           else
             current_user.authorized_projects
           end
    diff --git a/app/models/user.rb b/app/models/user.rb
    index 1e4814641d1..a0115957f00 100644
    --- a/app/models/user.rb
    +++ b/app/models/user.rb
    @@ -381,6 +381,11 @@ class User < ActiveRecord::Base
         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})",
    +                           [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::INTERNAL])
    +  end
    +
       def owned_projects
         @owned_projects ||=
           Project.where('namespace_id IN (?) OR namespace_id = ?',
    diff --git a/lib/api/projects.rb b/lib/api/projects.rb
    index cc2c7a0c503..9b595772675 100644
    --- a/lib/api/projects.rb
    +++ b/lib/api/projects.rb
    @@ -44,7 +44,7 @@ module API
           # Example Request:
           #   GET /projects/starred
           get '/starred' do
    -        @projects = current_user.starred_projects
    +        @projects = current_user.viewable_starred_projects
             @projects = filter_projects(@projects)
             @projects = paginate @projects
             present @projects, with: Entities::Project
    diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
    index 26d4e139396..06d1ca3b7da 100644
    --- a/spec/models/user_spec.rb
    +++ b/spec/models/user_spec.rb
    @@ -233,6 +233,8 @@ describe User, models: true do
           @project = create :project, namespace: @user.namespace
           @project_2 = create :project, group: create(:group) # Grant MASTER access to the user
           @project_3 = create :project, group: create(:group) # Grant DEVELOPER access to the user
    +      @project_4 = create :project, group: create(:group)
    +      @project_5 = create :project, group: create(:group)
     
           @project_2.team << [@user, :master]
           @project_3.team << [@user, :developer]
    @@ -782,4 +784,26 @@ describe User, models: true do
     
         it { is_expected.to eq([private_project]) }
       end
    +
    +  describe '#viewable_starred_projects' do
    +    let(:user) { create(:user) }
    +    let(:public_project) { create(:project, :public) }
    +    let(:private_project) { create(:project, :private) }
    +    let(:private_viewable_project) { create(:project, :private) }
    +    let(:viewable?) { -> (project) { user.can?(:read_project, project) } }
    +    let(:projects) { [public_project, private_project, private_viewable_project] }
    +
    +    before do
    +      private_viewable_project.team << [user, Gitlab::Access::MASTER]
    +      projects.each { |project| user.toggle_star(project) }
    +    end
    +
    +    it 'returns only starred projects the user can view' do
    +      expect(user.viewable_starred_projects).to all(satisfy(&viewable?))
    +    end
    +
    +    it 'rejects only starred projects the user can not view' do
    +      expect(projects - user.viewable_starred_projects).not_to include(satisfy(&viewable?))
    +    end
    +  end
     end
    diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
    index 66193eac051..f167813e07d 100644
    --- a/spec/requests/api/projects_spec.rb
    +++ b/spec/requests/api/projects_spec.rb
    @@ -10,20 +10,20 @@ describe API::API, api: true  do
       let(:admin) { create(:admin) }
       let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
       let(:project2) { create(:project, path: 'project2', creator_id: user.id, namespace: user.namespace) }
    -  let(:project3) { create(:project, path: 'project3', creator_id: user.id, namespace: user.namespace) }
       let(:snippet) { create(:project_snippet, :public, author: user, project: project, title: 'example') }
       let(:project_member) { create(:project_member, :master, user: user, project: project) }
       let(:project_member2) { create(:project_member, :developer, user: user3, project: project) }
       let(:user4) { create(:user) }
       let(:project3) do
         create(:project,
    +    :private,
         name: 'second_project',
         path: 'second_project',
         creator_id: user.id,
         namespace: user.namespace,
         merge_requests_enabled: false,
         issues_enabled: false, wiki_enabled: false,
    -    snippets_enabled: false, visibility_level: 0)
    +    snippets_enabled: false)
       end
       let(:project_member3) do
         create(:project_member,
    @@ -164,21 +164,18 @@ describe API::API, api: true  do
       end
     
       describe 'GET /projects/starred' do
    +    let(:public_project) { create(:project, :public) }
    +
         before do
    -      admin.starred_projects << project
    -      admin.save!
    +      project_member2
    +      user3.update_attributes(starred_projects: [project, project2, project3, public_project])
         end
     
    -    it 'should return the starred projects' do
    -      get api('/projects/all', admin)
    +    it 'should return the starred projects viewable by the user' do
    +      get api('/projects/starred', user3)
           expect(response.status).to eq(200)
           expect(json_response).to be_an Array
    -
    -      expect(json_response).to satisfy do |response|
    -        response.one? do |entry|
    -          entry['name'] == project.name
    -        end
    -      end
    +      expect(json_response.map { |project| project['id'] }).to contain_exactly(project.id, public_project.id)
         end
       end
     
    -- 
    cgit v1.2.1
    
    
    From 53568da9ed6e2c4bae3c06b0fb1d595033921334 Mon Sep 17 00:00:00 2001
    From: Alfredo Sumaran 
    Date: Mon, 9 May 2016 16:15:01 -0500
    Subject: Update Ace Editor
    
    ---
     Gemfile      | 2 +-
     Gemfile.lock | 4 ++--
     2 files changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/Gemfile b/Gemfile
    index 3e5c604ae06..77d351419f0 100644
    --- a/Gemfile
    +++ b/Gemfile
    @@ -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'
    diff --git a/Gemfile.lock b/Gemfile.lock
    index 86b9142ef27..c02698bcca7 100644
    --- a/Gemfile.lock
    +++ b/Gemfile.lock
    @@ -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)
    @@ -882,7 +882,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)
    -- 
    cgit v1.2.1
    
    
    From 77f1b9dcd44d5017502a6a0807ccdab643a32ede Mon Sep 17 00:00:00 2001
    From: Alfredo Sumaran 
    Date: Mon, 9 May 2016 16:15:08 -0500
    Subject: Update CHANGELOG
    
    ---
     CHANGELOG | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 1c21ad36b69..5490af3a147 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -39,6 +39,7 @@ 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
    -- 
    cgit v1.2.1
    
    
    From e689d9fb70d7484de708f8f436b294b40a9f6486 Mon Sep 17 00:00:00 2001
    From: Annabel Dunstone 
    Date: Tue, 10 May 2016 16:32:59 -0500
    Subject: Reduce width of side nav
    
    ---
     app/assets/stylesheets/framework/sidebar.scss   | 11 +++++++----
     app/assets/stylesheets/framework/variables.scss |  2 +-
     2 files changed, 8 insertions(+), 5 deletions(-)
    
    diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
    index bd91f51708c..a509ef2f149 100644
    --- a/app/assets/stylesheets/framework/sidebar.scss
    +++ b/app/assets/stylesheets/framework/sidebar.scss
    @@ -63,7 +63,7 @@
           float: left;
           height: $header-height;
           width: 100%;
    -      padding-left: 22px;
    +      padding-left: 16px;
           overflow: hidden;
           outline: none;
           transition-duration: .3s;
    @@ -78,7 +78,7 @@
           }
     
           .gitlab-text-container {
    -        width: 230px;
    +        width: 220px;
     
             h3 {
               width: 158px;
    @@ -146,12 +146,12 @@
     
         a {
           padding: 7px 15px;
    +      transition-duration: .3s;
           font-size: $gl-font-size;
           line-height: 24px;
           color: $gray;
           display: block;
           text-decoration: none;
    -      padding-left: 23px;
           font-weight: normal;
           outline: none;
     
    @@ -253,6 +253,9 @@
             width: auto;
     
             a {
    +          padding-left: 23px;
    +          transition-duration: .3s;
    +
               span {
                 display: none;
               }
    @@ -312,7 +315,7 @@
         }
     
         .nav-sidebar li a {
    -      width: 230px;
    +      width: 220px;
     
           &.back-link {
             i {
    diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
    index 84e74db06b0..5fa4c266607 100644
    --- a/app/assets/stylesheets/framework/variables.scss
    +++ b/app/assets/stylesheets/framework/variables.scss
    @@ -2,7 +2,7 @@
      * Layout
      */
     $sidebar_collapsed_width: 62px;
    -$sidebar_width: 230px;
    +$sidebar_width: 220px;
     $gutter_collapsed_width: 62px;
     $gutter_width: 290px;
     $gutter_inner_width: 258px;
    -- 
    cgit v1.2.1
    
    
    From a51064906bd4dcb29ea61c2278e2c32e848a5de6 Mon Sep 17 00:00:00 2001
    From: Annabel Dunstone 
    Date: Tue, 10 May 2016 16:51:57 -0500
    Subject: No extra link padding at xs screen size
    
    ---
     app/assets/stylesheets/framework/sidebar.scss | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
    index a509ef2f149..c243dd8a424 100644
    --- a/app/assets/stylesheets/framework/sidebar.scss
    +++ b/app/assets/stylesheets/framework/sidebar.scss
    @@ -253,8 +253,10 @@
             width: auto;
     
             a {
    -          padding-left: 23px;
    -          transition-duration: .3s;
    +          @media (min-width: $screen-xs-min) {
    +            padding-left: 23px;
    +            transition-duration: .3s;
    +          }
     
               span {
                 display: none;
    -- 
    cgit v1.2.1
    
    
    From 0e0caf4d17c28b6b0f3488b25efa265ce2804cc4 Mon Sep 17 00:00:00 2001
    From: DJ Mountney 
    Date: Tue, 10 May 2016 16:19:16 -0700
    Subject: Add tests for the health check feature
    
    ---
     app/views/admin/health_check/show.html.haml      |  3 +
     spec/controllers/health_check_controller_spec.rb | 90 ++++++++++++++++++++++++
     spec/features/admin/admin_health_check_spec.rb   | 55 +++++++++++++++
     spec/routing/admin_routing_spec.rb               |  7 ++
     spec/routing/routing_spec.rb                     | 10 +++
     5 files changed, 165 insertions(+)
     create mode 100644 spec/controllers/health_check_controller_spec.rb
     create mode 100644 spec/features/admin/admin_health_check_spec.rb
    
    diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
    index 70e5d04e356..23a931995ab 100644
    --- a/app/views/admin/health_check/show.html.haml
    +++ b/app/views/admin/health_check/show.html.haml
    @@ -2,6 +2,9 @@
     
     %h3.page-title
       Health Check
    +%p.light
    +  Access token is
    +  %code{ id:'health-check-token' }= "#{current_application_settings.health_check_access_token}"
     %p.light
       Health information can be reteived as plain text, json, or xml using:
       %ul
    diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
    new file mode 100644
    index 00000000000..3b9cc5c98f5
    --- /dev/null
    +++ b/spec/controllers/health_check_controller_spec.rb
    @@ -0,0 +1,90 @@
    +require 'spec_helper'
    +
    +describe HealthCheckController do
    +  let(:token) { current_application_settings.health_check_access_token }
    +  let(:json_response) { JSON.parse(response.body) }
    +  let(:xml_response) { Hash.from_xml(response.body)['hash'] }
    +
    +  describe 'GET #index' do
    +    context 'when services are up but NO access token' do
    +      it 'returns a not found page' do
    +        get :index
    +        expect(response).to be_not_found
    +      end
    +    end
    +
    +    context 'when services are up and an access token is provided' do
    +      it 'supports successful plaintest response' do
    +        get :index, token: token
    +        expect(response).to be_success
    +        expect(response.content_type).to eq 'text/plain'
    +      end
    +
    +      it 'supports successful json response' do
    +        get :index, token: token, format: :json
    +        expect(response).to be_success
    +        expect(response.content_type).to eq 'application/json'
    +        expect(json_response['healthy']).to be true
    +      end
    +
    +      it 'supports successful xml response' do
    +        get :index, token: token, format: :xml
    +        expect(response).to be_success
    +        expect(response.content_type).to eq 'application/xml'
    +        expect(xml_response['healthy']).to be true
    +      end
    +
    +      it 'supports successful responses for specific checks' do
    +        get :index, token: token, checks: 'email', format: :json
    +        expect(response).to be_success
    +        expect(response.content_type).to eq 'application/json'
    +        expect(json_response['healthy']).to be true
    +      end
    +    end
    +
    +    context 'when a service is down but NO access token' do
    +      it 'returns a not found page' do
    +        get :index
    +        expect(response).to be_not_found
    +      end
    +    end
    +
    +    context 'when a service is down and an access token is provided' do
    +      before do
    +        allow(HealthCheck::Utils).to receive(:process_checks).with('standard').and_return('The server is on fire')
    +        allow(HealthCheck::Utils).to receive(:process_checks).with('email').and_return('Email is on fire')
    +      end
    +
    +      it 'supports failure plaintest response' do
    +        get :index, token: token
    +        expect(response.status).to eq(500)
    +        expect(response.content_type).to eq 'text/plain'
    +        expect(response.body).to include('The server is on fire')
    +      end
    +
    +      it 'supports failure json response' do
    +        get :index, token: token, format: :json
    +        expect(response.status).to eq(500)
    +        expect(response.content_type).to eq 'application/json'
    +        expect(json_response['healthy']).to be false
    +        expect(json_response['message']).to include('The server is on fire')
    +      end
    +
    +      it 'supports failure xml response' do
    +        get :index, token: token, format: :xml
    +        expect(response.status).to eq(500)
    +        expect(response.content_type).to eq 'application/xml'
    +        expect(xml_response['healthy']).to be false
    +        expect(xml_response['message']).to include('The server is on fire')
    +      end
    +
    +      it 'supports failure responses for specific checks' do
    +        get :index, token: token, checks: 'email', format: :json
    +        expect(response.status).to eq(500)
    +        expect(response.content_type).to eq 'application/json'
    +        expect(json_response['healthy']).to be false
    +        expect(json_response['message']).to include('Email is on fire')
    +      end
    +    end
    +  end
    +end
    diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
    new file mode 100644
    index 00000000000..4fde04b609b
    --- /dev/null
    +++ b/spec/features/admin/admin_health_check_spec.rb
    @@ -0,0 +1,55 @@
    +require 'spec_helper'
    +
    +feature "Admin Health Check", feature: true do
    +  include WaitForAjax
    +
    +  before do
    +    login_as :admin
    +  end
    +
    +  describe '#show' do
    +    before do
    +      visit admin_health_check_path
    +    end
    +
    +    it { page.has_text? 'Health Check' }
    +    it { page.has_text? 'Health information can be reteived' }
    +
    +    it 'has a health check access token' do
    +      token = current_application_settings.health_check_access_token
    +      expect(page).to have_content("Access token is #{token}")
    +      expect(page).to have_selector('#health-check-token', text: token)
    +    end
    +
    +    describe 'reload access token', js: true do
    +      it 'changes the access token' do
    +        orig_token = current_application_settings.health_check_access_token
    +        click_button 'Reset health check access token'
    +        wait_for_ajax
    +        expect(find('#health-check-token').text).not_to eq orig_token
    +      end
    +    end
    +  end
    +
    +  context 'when services are up' do
    +    before do
    +      visit admin_health_check_path
    +    end
    +
    +    it 'shows healthy status' do
    +      expect(page).to have_content('Current Status: Healthy')
    +    end
    +  end
    +
    +  context 'when a service is down' do
    +    before do
    +      allow(HealthCheck::Utils).to receive(:process_checks).and_return('The server is on fire')
    +      visit admin_health_check_path
    +    end
    +
    +    it 'shows unhealthy status' do
    +      expect(page).to have_content('Current Status: Unhealthy')
    +      expect(page).to have_content('The server is on fire')
    +    end
    +  end
    +end
    diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
    index cd16a8e6322..b5ed8584c8a 100644
    --- a/spec/routing/admin_routing_spec.rb
    +++ b/spec/routing/admin_routing_spec.rb
    @@ -118,3 +118,10 @@ describe Admin::DashboardController, "routing" do
         expect(get("/admin")).to route_to('admin/dashboard#index')
       end
     end
    +
    +# admin_health_check GET    /admin/health_check(.:format) admin/health_check#show
    +describe Admin::HealthCheckController, "routing" do
    +  it "to #show" do
    +    expect(get("/admin/health_check")).to route_to('admin/health_check#show')
    +  end
    +end
    diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
    index 1527eddfa48..e4dfd4bca35 100644
    --- a/spec/routing/routing_spec.rb
    +++ b/spec/routing/routing_spec.rb
    @@ -243,3 +243,13 @@ describe "Groups", "routing" do
         expect(get('/1')).to route_to('namespaces#show', id: '1')
       end
     end
    +
    +describe HealthCheckController, 'routing' do
    +  it 'to #index' do
    +    expect(get('/health_check')).to route_to('health_check#index')
    +  end
    +
    +  it 'also supports passing checks in the url' do
    +    expect(get('/health_check/email')).to route_to('health_check#index', checks: 'email')
    +  end
    +end
    -- 
    cgit v1.2.1
    
    
    From 377583a361988d9884808a3c3f5375497a9d5b56 Mon Sep 17 00:00:00 2001
    From: Connor Shea 
    Date: Wed, 27 Apr 2016 16:52:32 -0600
    Subject: Enable Rubocop Casecmp Performance Cop.
    
    Also fixes the errors caused by enabling the cop. casecmp is more performant than `.downcase` and `==`.
    ---
     .rubocop.yml                | 3 +--
     app/models/repository.rb    | 2 +-
     lib/gitlab/database.rb      | 4 ++--
     lib/gitlab/markup_helper.rb | 2 +-
     4 files changed, 5 insertions(+), 6 deletions(-)
    
    diff --git a/.rubocop.yml b/.rubocop.yml
    index 9f179efa3ce..f07d2184be4 100644
    --- a/.rubocop.yml
    +++ b/.rubocop.yml
    @@ -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
    diff --git a/app/models/repository.rb b/app/models/repository.rb
    index 7aebfe279fb..5f562750d1f 100644
    --- a/app/models/repository.rb
    +++ b/app/models/repository.rb
    @@ -453,7 +453,7 @@ class Repository
       def version
         cache.fetch(:version) do
           tree(:head).blobs.find do |file|
    -        file.name.downcase == 'version'
    +        file.name.casecmp('version').zero?
           end
         end
       end
    diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
    index 6f9da69983a..42bec913a45 100644
    --- a/lib/gitlab/database.rb
    +++ b/lib/gitlab/database.rb
    @@ -5,11 +5,11 @@ module Gitlab
         end
     
         def self.mysql?
    -      adapter_name.downcase == 'mysql2'
    +      adapter_name.casecmp('mysql2').zero?
         end
     
         def self.postgresql?
    -      adapter_name.downcase == 'postgresql'
    +      adapter_name.casecmp('postgresql').zero?
         end
     
         def self.version
    diff --git a/lib/gitlab/markup_helper.rb b/lib/gitlab/markup_helper.rb
    index a5f767b134d..dda371e6554 100644
    --- a/lib/gitlab/markup_helper.rb
    +++ b/lib/gitlab/markup_helper.rb
    @@ -40,7 +40,7 @@ module Gitlab
         # Returns boolean
         def plain?(filename)
           filename.downcase.end_with?('.txt') ||
    -        filename.downcase == 'readme'
    +        filename.casecmp('readme').zero?
         end
     
         def previewable?(filename)
    -- 
    cgit v1.2.1
    
    
    From 976a70522f47bd57f3545efe5d71a58bb2596649 Mon Sep 17 00:00:00 2001
    From: Connor Shea 
    Date: Sun, 8 May 2016 15:44:14 -0600
    Subject: Removes jquery-scrollto-rails.
    
    Instead the script is now included directly from the vendor directory.
    
    Resolves #17166.
    ---
     Gemfile                                      |   1 -
     Gemfile.lock                                 |   3 -
     vendor/assets/javascripts/jquery.scrollTo.js | 210 +++++++++++++++++++++++++++
     3 files changed, 210 insertions(+), 4 deletions(-)
     create mode 100755 vendor/assets/javascripts/jquery.scrollTo.js
    
    diff --git a/Gemfile b/Gemfile
    index 77d351419f0..2854bf8a57b 100644
    --- a/Gemfile
    +++ b/Gemfile
    @@ -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'
    diff --git a/Gemfile.lock b/Gemfile.lock
    index c02698bcca7..bc47533e5bb 100644
    --- a/Gemfile.lock
    +++ b/Gemfile.lock
    @@ -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
    @@ -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)
    diff --git a/vendor/assets/javascripts/jquery.scrollTo.js b/vendor/assets/javascripts/jquery.scrollTo.js
    new file mode 100755
    index 00000000000..7ba17766b70
    --- /dev/null
    +++ b/vendor/assets/javascripts/jquery.scrollTo.js
    @@ -0,0 +1,210 @@
    +/*!
    + * jQuery.scrollTo
    + * Copyright (c) 2007-2015 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com
    + * Licensed under MIT
    + * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
    + * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery
    + * @author Ariel Flesler
    + * @version 2.1.2
    + */
    +;(function(factory) {
    +	'use strict';
    +	if (typeof define === 'function' && define.amd) {
    +		// AMD
    +		define(['jquery'], factory);
    +	} else if (typeof module !== 'undefined' && module.exports) {
    +		// CommonJS
    +		module.exports = factory(require('jquery'));
    +	} else {
    +		// Global
    +		factory(jQuery);
    +	}
    +})(function($) {
    +	'use strict';
    +
    +	var $scrollTo = $.scrollTo = function(target, duration, settings) {
    +		return $(window).scrollTo(target, duration, settings);
    +	};
    +
    +	$scrollTo.defaults = {
    +		axis:'xy',
    +		duration: 0,
    +		limit:true
    +	};
    +
    +	function isWin(elem) {
    +		return !elem.nodeName ||
    +			$.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;
    +	}		
    +
    +	$.fn.scrollTo = function(target, duration, settings) {
    +		if (typeof duration === 'object') {
    +			settings = duration;
    +			duration = 0;
    +		}
    +		if (typeof settings === 'function') {
    +			settings = { onAfter:settings };
    +		}
    +		if (target === 'max') {
    +			target = 9e9;
    +		}
    +
    +		settings = $.extend({}, $scrollTo.defaults, settings);
    +		// Speed is still recognized for backwards compatibility
    +		duration = duration || settings.duration;
    +		// Make sure the settings are given right
    +		var queue = settings.queue && settings.axis.length > 1;
    +		if (queue) {
    +			// Let's keep the overall duration
    +			duration /= 2;
    +		}
    +		settings.offset = both(settings.offset);
    +		settings.over = both(settings.over);
    +
    +		return this.each(function() {
    +			// Null target yields nothing, just like jQuery does
    +			if (target === null) return;
    +
    +			var win = isWin(this),
    +				elem = win ? this.contentWindow || window : this,
    +				$elem = $(elem),
    +				targ = target, 
    +				attr = {},
    +				toff;
    +
    +			switch (typeof targ) {
    +				// A number will pass the regex
    +				case 'number':
    +				case 'string':
    +					if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {
    +						targ = both(targ);
    +						// We are done
    +						break;
    +					}
    +					// Relative/Absolute selector
    +					targ = win ? $(targ) : $(targ, elem);
    +					/* falls through */
    +				case 'object':
    +					if (targ.length === 0) return;
    +					// DOMElement / jQuery
    +					if (targ.is || targ.style) {
    +						// Get the real position of the target
    +						toff = (targ = $(targ)).offset();
    +					}
    +			}
    +
    +			var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;
    +
    +			$.each(settings.axis.split(''), function(i, axis) {
    +				var Pos	= axis === 'x' ? 'Left' : 'Top',
    +					pos = Pos.toLowerCase(),
    +					key = 'scroll' + Pos,
    +					prev = $elem[key](),
    +					max = $scrollTo.max(elem, axis);
    +
    +				if (toff) {// jQuery / DOMElement
    +					attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);
    +
    +					// If it's a dom element, reduce the margin
    +					if (settings.margin) {
    +						attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;
    +						attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;
    +					}
    +
    +					attr[key] += offset[pos] || 0;
    +
    +					if (settings.over[pos]) {
    +						// Scroll to a fraction of its width/height
    +						attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];
    +					}
    +				} else {
    +					var val = targ[pos];
    +					// Handle percentage values
    +					attr[key] = val.slice && val.slice(-1) === '%' ?
    +						parseFloat(val) / 100 * max
    +						: val;
    +				}
    +
    +				// Number or 'number'
    +				if (settings.limit && /^\d+$/.test(attr[key])) {
    +					// Check the limits
    +					attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);
    +				}
    +
    +				// Don't waste time animating, if there's no need.
    +				if (!i && settings.axis.length > 1) {
    +					if (prev === attr[key]) {
    +						// No animation needed
    +						attr = {};
    +					} else if (queue) {
    +						// Intermediate animation
    +						animate(settings.onAfterFirst);
    +						// Don't animate this axis again in the next iteration.
    +						attr = {};
    +					}
    +				}
    +			});
    +
    +			animate(settings.onAfter);
    +
    +			function animate(callback) {
    +				var opts = $.extend({}, settings, {
    +					// The queue setting conflicts with animate()
    +					// Force it to always be true
    +					queue: true,
    +					duration: duration,
    +					complete: callback && function() {
    +						callback.call(elem, targ, settings);
    +					}
    +				});
    +				$elem.animate(attr, opts);
    +			}
    +		});
    +	};
    +
    +	// Max scrolling position, works on quirks mode
    +	// It only fails (not too badly) on IE, quirks mode.
    +	$scrollTo.max = function(elem, axis) {
    +		var Dim = axis === 'x' ? 'Width' : 'Height',
    +			scroll = 'scroll'+Dim;
    +
    +		if (!isWin(elem))
    +			return elem[scroll] - $(elem)[Dim.toLowerCase()]();
    +
    +		var size = 'client' + Dim,
    +			doc = elem.ownerDocument || elem.document,
    +			html = doc.documentElement,
    +			body = doc.body;
    +
    +		return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);
    +	};
    +
    +	function both(val) {
    +		return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };
    +	}
    +
    +	// Add special hooks so that window scroll properties can be animated
    +	$.Tween.propHooks.scrollLeft = 
    +	$.Tween.propHooks.scrollTop = {
    +		get: function(t) {
    +			return $(t.elem)[t.prop]();
    +		},
    +		set: function(t) {
    +			var curr = this.get(t);
    +			// If interrupt is true and user scrolled, stop animating
    +			if (t.options.interrupt && t._last && t._last !== curr) {
    +				return $(t.elem).stop();
    +			}
    +			var next = Math.round(t.now);
    +			// Don't waste CPU
    +			// Browsers don't render floating point scroll
    +			if (curr !== next) {
    +				$(t.elem)[t.prop](next);
    +				t._last = this.get(t);
    +			}
    +		}
    +	};
    +
    +	// AMD requirement
    +	return $scrollTo;
    +});
    -- 
    cgit v1.2.1
    
    
    From 4995302df64b71846370aa80f5b12a2d73112421 Mon Sep 17 00:00:00 2001
    From: Connor Shea 
    Date: Wed, 27 Apr 2016 18:22:46 -0600
    Subject: Enable the StringReplacement cop.
    
    Also fix one use of `gsub` that would be faster as `delete`.
    
    Use `tr` instead of `gsub` when you are replacing the same number of
    characters. Use `delete` instead of `gsub` when you are deleting
    characters.
    ---
     .rubocop.yml              | 3 ++-
     lib/gitlab/diff/parser.rb | 2 +-
     2 files changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/.rubocop.yml b/.rubocop.yml
    index 9f179efa3ce..c96c7123c16 100644
    --- a/.rubocop.yml
    +++ b/.rubocop.yml
    @@ -990,11 +990,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.
    diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
    index d0815fc7eea..6fe7faa547a 100644
    --- a/lib/gitlab/diff/parser.rb
    +++ b/lib/gitlab/diff/parser.rb
    @@ -18,7 +18,7 @@ module Gitlab
               @lines.each do |line|
                 next if filename?(line)
       
    -            full_line = line.gsub(/\n/, '')
    +            full_line = line.delete("\n")
       
                 if line.match(/^@@ -/)
                   type = "match"
    -- 
    cgit v1.2.1
    
    
    From b42f39d2c27ec2a87e21dea7414d9845f2512144 Mon Sep 17 00:00:00 2001
    From: Connor Shea 
    Date: Thu, 28 Apr 2016 19:44:56 -0600
    Subject: Remove activerecord-deprecated_finders gem
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    We don’t use any of the deprecated finders, so it should be safe to
    remove.
    
    Resolves #17015.
    ---
     Gemfile      | 1 -
     Gemfile.lock | 2 --
     2 files changed, 3 deletions(-)
    
    diff --git a/Gemfile b/Gemfile
    index 77d351419f0..8de96025100 100644
    --- a/Gemfile
    +++ b/Gemfile
    @@ -324,7 +324,6 @@ gem "mail_room", "~> 0.7"
     gem 'email_reply_parser', '~> 0.5.8'
     
     ## CI
    -gem 'activerecord-deprecated_finders', '~> 1.0.3'
     gem 'activerecord-session_store', '~> 0.1.0'
     gem "nested_form", '~> 0.3.2'
     
    diff --git a/Gemfile.lock b/Gemfile.lock
    index c02698bcca7..45d6de18f26 100644
    --- a/Gemfile.lock
    +++ b/Gemfile.lock
    @@ -33,7 +33,6 @@ GEM
           activemodel (= 4.2.6)
           activesupport (= 4.2.6)
           arel (~> 6.0)
    -    activerecord-deprecated_finders (1.0.4)
         activerecord-session_store (0.1.2)
           actionpack (>= 4.0.0, < 5)
           activerecord (>= 4.0.0, < 5)
    @@ -883,7 +882,6 @@ PLATFORMS
     DEPENDENCIES
       RedCloth (~> 4.2.9)
       ace-rails-ap (~> 4.0.2)
    -  activerecord-deprecated_finders (~> 1.0.3)
       activerecord-session_store (~> 0.1.0)
       acts-as-taggable-on (~> 3.4)
       addressable (~> 2.3.8)
    -- 
    cgit v1.2.1
    
    
    From 51e198fb38428387a976385cae2d5e4fc455ee9e Mon Sep 17 00:00:00 2001
    From: Connor Shea 
    Date: Tue, 10 May 2016 21:56:40 -0600
    Subject: Don't show the Todo count if there aren't any Todos.
    
    When there are 0 Todos, the Todos icon still had the blue badge with a "0" in it, which made me think I had a new Todo left. This makes it less annoying.
    
    Follow-up on !4077.
    ---
     app/views/layouts/header/_default.html.haml | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
    index 172579dafda..c33740e23fa 100644
    --- a/app/views/layouts/header/_default.html.haml
    +++ b/app/views/layouts/header/_default.html.haml
    @@ -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
    -- 
    cgit v1.2.1
    
    
    From f2548f3f2b3dcd1c6ecbae20af28933f3ab88fdd Mon Sep 17 00:00:00 2001
    From: Stan Hu 
    Date: Tue, 10 May 2016 22:07:13 -0700
    Subject: Improve log message when a project is destroyed to include the
     namespace
    
    ---
     app/services/projects/destroy_service.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
    index 19aab999e00..48a6131b444 100644
    --- a/app/services/projects/destroy_service.rb
    +++ b/app/services/projects/destroy_service.rb
    @@ -35,7 +35,7 @@ module Projects
             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
    -- 
    cgit v1.2.1
    
    
    From acd8930c46c06312f87c5ea0bb549b5435feece8 Mon Sep 17 00:00:00 2001
    From: Sean McGivern 
    Date: Wed, 11 May 2016 09:03:23 +0100
    Subject: Tidy up user project specs
    
    ---
     app/models/user.rb       |  2 +-
     spec/models/user_spec.rb | 21 ++++++++-------------
     2 files changed, 9 insertions(+), 14 deletions(-)
    
    diff --git a/app/models/user.rb b/app/models/user.rb
    index a0115957f00..489bff3fa4a 100644
    --- a/app/models/user.rb
    +++ b/app/models/user.rb
    @@ -383,7 +383,7 @@ class User < ActiveRecord::Base
     
       def viewable_starred_projects
         starred_projects.where("projects.visibility_level IN (?) OR projects.id IN (#{projects_union.to_sql})",
    -                           [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::INTERNAL])
    +                           [Project::PUBLIC, Project::INTERNAL])
       end
     
       def owned_projects
    diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
    index 06d1ca3b7da..10e7e693571 100644
    --- a/spec/models/user_spec.rb
    +++ b/spec/models/user_spec.rb
    @@ -233,8 +233,6 @@ describe User, models: true do
           @project = create :project, namespace: @user.namespace
           @project_2 = create :project, group: create(:group) # Grant MASTER access to the user
           @project_3 = create :project, group: create(:group) # Grant DEVELOPER access to the user
    -      @project_4 = create :project, group: create(:group)
    -      @project_5 = create :project, group: create(:group)
     
           @project_2.team << [@user, :master]
           @project_3.team << [@user, :developer]
    @@ -787,23 +785,20 @@ describe User, models: true do
     
       describe '#viewable_starred_projects' do
         let(:user) { create(:user) }
    -    let(:public_project) { create(:project, :public) }
    -    let(:private_project) { create(:project, :private) }
    -    let(:private_viewable_project) { create(:project, :private) }
    -    let(:viewable?) { -> (project) { user.can?(:read_project, project) } }
    -    let(:projects) { [public_project, private_project, private_viewable_project] }
    +    let(:public_project) { create(:empty_project, :public) }
    +    let(:private_project) { create(:empty_project, :private) }
    +    let(:private_viewable_project) { create(:empty_project, :private) }
     
         before do
           private_viewable_project.team << [user, Gitlab::Access::MASTER]
    -      projects.each { |project| user.toggle_star(project) }
    -    end
     
    -    it 'returns only starred projects the user can view' do
    -      expect(user.viewable_starred_projects).to all(satisfy(&viewable?))
    +      [public_project, private_project, private_viewable_project].each do |project|
    +        user.toggle_star(project)
    +      end
         end
     
    -    it 'rejects only starred projects the user can not view' do
    -      expect(projects - user.viewable_starred_projects).not_to include(satisfy(&viewable?))
    +    it 'returns only starred projects the user can view' do
    +      expect(user.viewable_starred_projects).not_to include(private_project)
         end
       end
     end
    -- 
    cgit v1.2.1
    
    
    From 5f27e26bb4d073c04fd6d3f4116fc1a122db8c00 Mon Sep 17 00:00:00 2001
    From: Sean McGivern 
    Date: Fri, 6 May 2016 13:16:53 +0100
    Subject: Only generate repository push email once
    
    The repository push email can be very expensive to generate, especially
    with syntax-highlighted diffs. Instead of generating the email for each
    recipient, generate one email object and reset the Message-Id and To
    headers for each recipient. (Cloning would also be expensive in the case
    of large emails, although probably not as bad as generating from
    scratch.)
    ---
     CHANGELOG                                          |  1 +
     app/mailers/emails/projects.rb                     |  5 +-
     app/workers/emails_on_push_worker.rb               | 25 +++++++--
     lib/gitlab/email/message/repository_push.rb        |  4 +-
     .../gitlab/email/message/repository_push_spec.rb   |  2 +-
     spec/mailers/notify_spec.rb                        | 36 ++----------
     spec/workers/emails_on_push_worker_spec.rb         | 65 +++++++++++++++++-----
     7 files changed, 83 insertions(+), 55 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 1c21ad36b69..96643fc88a3 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -21,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
    diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
    index 377c2999d6c..5489283432b 100644
    --- a/app/mailers/emails/projects.rb
    +++ b/app/mailers/emails/projects.rb
    @@ -59,9 +59,9 @@ module Emails
                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 @@ module Emails
     
           mail(from:      sender(@message.author_id, @message.send_from_committer_email?),
                reply_to:  @message.reply_to,
    -           to:        @message.recipient,
                subject:   @message.subject)
         end
       end
    diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
    index c4d8595d45d..6ebcba5f39b 100644
    --- a/app/workers/emails_on_push_worker.rb
    +++ b/app/workers/emails_on_push_worker.rb
    @@ -1,6 +1,8 @@
     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 @@ class EmailsOnPushWorker
           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 @@ class EmailsOnPushWorker
               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
    diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb
    index 8f9be6cd9a3..2c91a0487c3 100644
    --- a/lib/gitlab/email/message/repository_push.rb
    +++ b/lib/gitlab/email/message/repository_push.rb
    @@ -2,7 +2,6 @@ module Gitlab
       module Email
         module Message
           class RepositoryPush
    -        attr_accessor :recipient
             attr_reader :author_id, :ref, :action
     
             include Gitlab::Routing.url_helpers
    @@ -11,13 +10,12 @@ module Gitlab
             delegate :name, to: :author, prefix: :author
             delegate :username, to: :author, prefix: :author
     
    -        def initialize(notify, project_id, recipient, opts = {})
    +        def initialize(notify, project_id, opts = {})
               raise ArgumentError, 'Missing options: author_id, ref, action' unless
                 opts[:author_id] && opts[:ref] && opts[:action]
     
               @notify = notify
               @project_id = project_id
    -          @recipient = recipient
               @opts = opts.dup
     
               @author_id = @opts.delete(:author_id)
    diff --git a/spec/lib/gitlab/email/message/repository_push_spec.rb b/spec/lib/gitlab/email/message/repository_push_spec.rb
    index b2d7a799810..7d6cce6daec 100644
    --- a/spec/lib/gitlab/email/message/repository_push_spec.rb
    +++ b/spec/lib/gitlab/email/message/repository_push_spec.rb
    @@ -8,7 +8,7 @@ describe Gitlab::Email::Message::RepositoryPush do
       let!(:author) { create(:author, name: 'Author') }
     
       let(:message) do
    -    described_class.new(Notify, project.id, 'recipient@example.com', opts)
    +    described_class.new(Notify, project.id, opts)
       end
     
       context 'new commits have been pushed to repository' do
    diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
    index 495c5cbac00..5f7e4a526e6 100644
    --- a/spec/mailers/notify_spec.rb
    +++ b/spec/mailers/notify_spec.rb
    @@ -593,7 +593,7 @@ describe Notify do
         let(:user) { create(:user) }
         let(:tree_path) { namespace_project_tree_path(project.namespace, project, "master") }
     
    -    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) }
    +    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :create) }
     
         it_behaves_like 'it should not have Gmail Actions links'
         it_behaves_like "a user cannot unsubscribe through footer link"
    @@ -606,10 +606,6 @@ describe Notify do
           expect(sender.address).to eq(gitlab_sender)
         end
     
    -    it 'is sent to recipient' do
    -      is_expected.to deliver_to 'devs@company.name'
    -    end
    -
         it 'has the correct subject' do
           is_expected.to have_subject /Pushed new branch master/
         end
    @@ -624,7 +620,7 @@ describe Notify do
         let(:user) { create(:user) }
         let(:tree_path) { namespace_project_tree_path(project.namespace, project, "v1.0") }
     
    -    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
    +    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
     
         it_behaves_like 'it should not have Gmail Actions links'
         it_behaves_like "a user cannot unsubscribe through footer link"
    @@ -637,10 +633,6 @@ describe Notify do
           expect(sender.address).to eq(gitlab_sender)
         end
     
    -    it 'is sent to recipient' do
    -      is_expected.to deliver_to 'devs@company.name'
    -    end
    -
         it 'has the correct subject' do
           is_expected.to have_subject /Pushed new tag v1\.0/
         end
    @@ -654,7 +646,7 @@ describe Notify do
         let(:example_site_path) { root_path }
         let(:user) { create(:user) }
     
    -    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) }
    +    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :delete) }
     
         it_behaves_like 'it should not have Gmail Actions links'
         it_behaves_like "a user cannot unsubscribe through footer link"
    @@ -667,10 +659,6 @@ describe Notify do
           expect(sender.address).to eq(gitlab_sender)
         end
     
    -    it 'is sent to recipient' do
    -      is_expected.to deliver_to 'devs@company.name'
    -    end
    -
         it 'has the correct subject' do
           is_expected.to have_subject /Deleted branch master/
         end
    @@ -680,7 +668,7 @@ describe Notify do
         let(:example_site_path) { root_path }
         let(:user) { create(:user) }
     
    -    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
    +    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
     
         it_behaves_like 'it should not have Gmail Actions links'
         it_behaves_like "a user cannot unsubscribe through footer link"
    @@ -693,10 +681,6 @@ describe Notify do
           expect(sender.address).to eq(gitlab_sender)
         end
     
    -    it 'is sent to recipient' do
    -      is_expected.to deliver_to 'devs@company.name'
    -    end
    -
         it 'has the correct subject' do
           is_expected.to have_subject /Deleted tag v1\.0/
         end
    @@ -710,7 +694,7 @@ describe Notify do
         let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
         let(:send_from_committer_email) { false }
     
    -    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) }
    +    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) }
     
         it_behaves_like 'it should not have Gmail Actions links'
         it_behaves_like "a user cannot unsubscribe through footer link"
    @@ -723,10 +707,6 @@ describe Notify do
           expect(sender.address).to eq(gitlab_sender)
         end
     
    -    it 'is sent to recipient' do
    -      is_expected.to deliver_to 'devs@company.name'
    -    end
    -
         it 'has the correct subject' do
           is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
         end
    @@ -818,7 +798,7 @@ describe Notify do
         let(:commits) { Commit.decorate(compare.commits, nil) }
         let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
     
    -    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) }
    +    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) }
     
         it_behaves_like 'it should show Gmail Actions View Commit link'
         it_behaves_like "a user cannot unsubscribe through footer link"
    @@ -831,10 +811,6 @@ describe Notify do
           expect(sender.address).to eq(gitlab_sender)
         end
     
    -    it 'is sent to recipient' do
    -      is_expected.to deliver_to 'devs@company.name'
    -    end
    -
         it 'has the correct subject' do
           is_expected.to have_subject /#{commits.first.title}/
         end
    diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb
    index 3600c771075..439da765c2c 100644
    --- a/spec/workers/emails_on_push_worker_spec.rb
    +++ b/spec/workers/emails_on_push_worker_spec.rb
    @@ -6,29 +6,66 @@ describe EmailsOnPushWorker do
       let(:project) { create(:project) }
       let(:user) { create(:user) }
       let(:data) { Gitlab::PushDataBuilder.build_sample(project, user) }
    +  let(:recipients) { user.email }
    +  let(:perform) { subject.perform(project.id, recipients, data.stringify_keys) }
     
       subject { EmailsOnPushWorker.new }
     
    -  before do
    -    allow(Project).to receive(:find).and_return(project)
    -  end
    -
       describe "#perform" do
    -    it "sends mail" do
    -      subject.perform(project.id, user.email, data.stringify_keys)
    +    context "when there are no errors in sending" do
    +      let(:email) { ActionMailer::Base.deliveries.last }
    +
    +      before { perform }
     
    -      email = ActionMailer::Base.deliveries.last
    -      expect(email.subject).to include('Change some files')
    -      expect(email.to).to eq([user.email])
    +      it "sends a mail with the correct subject" do
    +        expect(email.subject).to include('Change some files')
    +      end
    +
    +      it "sends the mail to the correct recipient" do
    +        expect(email.to).to eq([user.email])
    +      end
         end
     
    -    it "gracefully handles an input SMTP error" do
    -      ActionMailer::Base.deliveries.clear
    -      allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError)
    +    context "when there is an SMTP error" do
    +      before do
    +        ActionMailer::Base.deliveries.clear
    +        allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError)
    +        perform
    +      end
    +
    +      it "gracefully handles an input SMTP error" do
    +        expect(ActionMailer::Base.deliveries.count).to eq(0)
    +      end
    +    end
    +
    +    context "when there are multiple recipients" do
    +      let(:recipients) do
    +        1.upto(5).map { |i| user.email.sub('@', "+#{i}@") }.join("\n")
    +      end
    +
    +      before do
    +        # This is a hack because we modify the mail object before sending, for efficency,
    +        # but the TestMailer adapter just appends the objects to an array. To clone a mail
    +        # object, create a new one!
    +        #   https://github.com/mikel/mail/issues/314#issuecomment-12750108
    +        allow_any_instance_of(Mail::TestMailer).to receive(:deliver!).and_wrap_original do |original, mail|
    +          original.call(Mail.new(mail.encoded))
    +        end
    +
    +        ActionMailer::Base.deliveries.clear
    +      end
     
    -      subject.perform(project.id, user.email, data.stringify_keys)
    +      it "sends the mail to each of the recipients" do
    +        perform
    +        expect(ActionMailer::Base.deliveries.count).to eq(5)
    +        expect(ActionMailer::Base.deliveries.map(&:to).flatten).to contain_exactly(*recipients.split)
    +      end
     
    -      expect(ActionMailer::Base.deliveries.count).to eq(0)
    +      it "only generates the mail once" do
    +        expect(Notify).to receive(:repository_push_email).once.and_call_original
    +        expect(Premailer::Rails::CustomizedPremailer).to receive(:new).once.and_call_original
    +        perform
    +      end
         end
       end
     end
    -- 
    cgit v1.2.1
    
    
    From d9574a7b93de7e88c77ed1351650843749da60f0 Mon Sep 17 00:00:00 2001
    From: Sean McGivern 
    Date: Thu, 5 May 2016 10:00:31 +0100
    Subject: Group commits by date in server timezone
    
    `Time#to_date` just takes the (timezone-less) year, date, and month, and
    creates a new date from that. Because the commits in the list are
    grouped by date, rather than chunked when the date changes, a commit can
    be shown in the wrong order if its CommitDate has a timezone-less date
    that's different to other commits around it.
    
    Convert all CommitDates to the server timezone before grouping, as that
    will at least produce consistent results. Users can still see a
    timestamp on the commit that doesn't match the date it's grouped under,
    because the timestamp shown uses the user's local timezone, and the
    grouping uses the server's timezone, but that was an issue anyway.
    ---
     CHANGELOG                                     | 1 +
     app/views/projects/commits/_commits.html.haml | 2 +-
     2 files changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index e989e622b97..ab41545548b 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -19,6 +19,7 @@ v 8.8.0 (unreleased)
       - 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)
       - Added multiple colors for labels in dropdowns when dups happen.
    +  - Always group commits by server timezone, not commit timestamp
       - 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)
       - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko)
    diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
    index 64e8da9201d..82f39e59284 100644
    --- a/app/views/projects/commits/_commits.html.haml
    +++ b/app/views/projects/commits/_commits.html.haml
    @@ -3,7 +3,7 @@
     
     - commits, hidden = limited_commits(@commits)
     
    -- commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
    +- commits.group_by { |c| c.committed_date.in_time_zone.to_date }.sort.reverse.each do |day, commits|
       .row.commits-row
         .col-md-2.hidden-xs.hidden-sm
           %h5.commits-row-date
    -- 
    cgit v1.2.1
    
    
    From 941301339dd8d1e282c3e225808875ef86b45f2b Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?R=C3=A9my=20Coutable?= 
    Date: Wed, 11 May 2016 12:32:48 +0200
    Subject: Remove Rails monkey-patches now that we're using Rails 4.2.6
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Signed-off-by: Rémy Coutable 
    ---
     config/initializers/monkey_patch.rb | 48 -------------------------------------
     1 file changed, 48 deletions(-)
     delete mode 100644 config/initializers/monkey_patch.rb
    
    diff --git a/config/initializers/monkey_patch.rb b/config/initializers/monkey_patch.rb
    deleted file mode 100644
    index 62b05a55285..00000000000
    --- a/config/initializers/monkey_patch.rb
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -## 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
    -- 
    cgit v1.2.1
    
    
    From a2934f45317ed64beb948b8487199251a987c4a1 Mon Sep 17 00:00:00 2001
    From: Grzegorz Bizon 
    Date: Wed, 11 May 2016 12:39:07 +0200
    Subject: Use % notation for arrays in runner model constants
    
    ---
     app/models/ci/runner.rb | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
    index d27963e8ec5..e598a132869 100644
    --- a/app/models/ci/runner.rb
    +++ b/app/models/ci/runner.rb
    @@ -22,8 +22,8 @@ module Ci
         extend Ci::Model
     
         LAST_CONTACT_TIME = 5.minutes.ago
    -    AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online']
    -    FORM_EDITABLE = [:description, :tag_list, :active]
    +    AVAILABLE_SCOPES = %w[specific shared active paused online]
    +    FORM_EDITABLE = %i[description tag_list active]
     
         has_many :builds, class_name: 'Ci::Build'
         has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
    -- 
    cgit v1.2.1
    
    
    From c446a86510a6586c69a306ae09e41053f20d11a1 Mon Sep 17 00:00:00 2001
    From: Yorick Peterse 
    Date: Wed, 11 May 2016 14:19:30 +0200
    Subject: Updated 8.7.4 CHANGELOG entries
    
    [ci skip]
    ---
     CHANGELOG | 10 +++++++---
     1 file changed, 7 insertions(+), 3 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 54c79551b1d..caa0923573a 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -43,9 +43,13 @@ v 8.8.0 (unreleased)
       - 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)
    -  - Fix an issue when filtering merge requests with more than one label. !3886
    +  - 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
    -- 
    cgit v1.2.1
    
    
    From 973cd0fec7b69d1398a86df67d10f7c38a9a4ced Mon Sep 17 00:00:00 2001
    From: Valery Sizov 
    Date: Wed, 11 May 2016 18:08:17 +0300
    Subject: Update 8.8 guides
    
    ---
     doc/install/installation.md |   2 +-
     doc/update/8.7-to-8.8.md    | 154 ++++++++++++++++++++++++++++++++++++++++++++
     2 files changed, 155 insertions(+), 1 deletion(-)
     create mode 100644 doc/update/8.7-to-8.8.md
    
    diff --git a/doc/install/installation.md b/doc/install/installation.md
    index e3af3022262..44ae0be406c 100644
    --- a/doc/install/installation.md
    +++ b/doc/install/installation.md
    @@ -269,7 +269,7 @@ sudo usermod -aG redis git
     ### Clone the Source
     
         # Clone GitLab repository
    -    sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-7-stable gitlab
    +    sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-8-stable gitlab
     
     **Note:** You can change `8-7-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
     
    diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md
    new file mode 100644
    index 00000000000..b4d9212289c
    --- /dev/null
    +++ b/doc/update/8.7-to-8.8.md
    @@ -0,0 +1,154 @@
    +# From 8.7 to 8.8
    +
    +Make sure you view this update guide from the tag (version) of GitLab you would
    +like to install. In most cases this should be the highest numbered production
    +tag (without rc in it). You can select the tag in the version dropdown at the
    +top left corner of GitLab (below the menu bar).
    +
    +If the highest number stable branch is unclear please check the
    +[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
    +guide links by version.
    +
    +### 1. Stop server
    +
    +    sudo service gitlab stop
    +
    +### 2. Backup
    +
    +```bash
    +cd /home/git/gitlab
    +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
    +```
    +
    +### 3. Get latest code
    +
    +```bash
    +sudo -u git -H git fetch --all
    +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
    +```
    +
    +For GitLab Community Edition:
    +
    +```bash
    +sudo -u git -H git checkout 8-8-stable
    +```
    +
    +OR
    +
    +For GitLab Enterprise Edition:
    +
    +```bash
    +sudo -u git -H git checkout 8-8-stable-ee
    +```
    +
    +### 4. Update gitlab-shell
    +
    +```bash
    +cd /home/git/gitlab-shell
    +sudo -u git -H git fetch --all --tags
    +sudo -u git -H git checkout v2.7.2
    +```
    +
    +### 5. Update gitlab-workhorse
    +
    +Install and compile gitlab-workhorse. This requires
    +[Go 1.5](https://golang.org/dl) which should already be on your system from
    +GitLab 8.1.
    +
    +```bash
    +cd /home/git/gitlab-workhorse
    +sudo -u git -H git fetch --all
    +sudo -u git -H git checkout v0.7.1
    +sudo -u git -H make
    +```
    +
    +### 6. Install libs, migrations, etc.
    +
    +```bash
    +cd /home/git/gitlab
    +
    +# MySQL installations (note: the line below states '--without postgres')
    +sudo -u git -H bundle install --without postgres development test --deployment
    +
    +# PostgreSQL installations (note: the line below states '--without mysql')
    +sudo -u git -H bundle install --without mysql development test --deployment
    +
    +# Optional: clean up old gems
    +sudo -u git -H bundle clean
    +
    +# Run database migrations
    +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
    +
    +# Clean up assets and cache
    +sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
    +
    +```
    +
    +### 7. Update configuration files
    +
    +#### Git configuration
    +
    +Disable `git gc --auto` because GitLab runs `git gc` for us already.
    +
    +```sh
    +sudo -u git -H git config --global gc.auto 0
    +```
    +
    +#### Nginx configuration
    +
    +Ensure you're still up-to-date with the latest NGINX configuration changes:
    +
    +```sh
    +# For HTTPS configurations
    +git diff origin/8-7-stable:lib/support/nginx/gitlab-ssl origin/8-8-stable:lib/support/nginx/gitlab-ssl
    +
    +# For HTTP configurations
    +git diff origin/8-7-stable:lib/support/nginx/gitlab origin/8-8-stable:lib/support/nginx/gitlab
    +```
    +
    +If you are using Apache instead of NGINX please see the updated [Apache templates].
    +Also note that because Apache does not support upstreams behind Unix sockets you
    +will need to let gitlab-workhorse listen on a TCP port. You can do this
    +via [/etc/default/gitlab].
    +
    +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
    +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/lib/support/init.d/gitlab.default.example#L37
    +
    +#### Init script
    +
    +Ensure you're still up-to-date with the latest init script changes:
    +
    +    sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
    +
    +### 8. Start application
    +
    +    sudo service gitlab start
    +    sudo service nginx restart
    +
    +### 9. Check application status
    +
    +Check if GitLab and its environment are configured correctly:
    +
    +    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
    +
    +To make sure you didn't miss anything run a more thorough check:
    +
    +    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
    +
    +If all items are green, then congratulations, the upgrade is complete!
    +
    +## Things went south? Revert to previous version (8.6)
    +
    +### 1. Revert the code to the previous version
    +
    +Follow the [upgrade guide from 8.6 to 8.7](8.6-to-8.7.md), except for the
    +database migration (the backup is already migrated to the previous version).
    +
    +### 2. Restore from the backup
    +
    +```bash
    +cd /home/git/gitlab
    +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
    +```
    +
    +If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
    -- 
    cgit v1.2.1
    
    
    From b523dec83dc832029c6e40daaeb121920bbcd394 Mon Sep 17 00:00:00 2001
    From: Robert Speicher 
    Date: Sun, 8 May 2016 14:11:28 -0400
    Subject: Remove unused `icon_for_event` helper
    
    ---
     app/helpers/events_helper.rb | 9 ---------
     1 file changed, 9 deletions(-)
    
    diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
    index 592bad8ba24..0bf328e7d19 100644
    --- a/app/helpers/events_helper.rb
    +++ b/app/helpers/events_helper.rb
    @@ -39,15 +39,6 @@ module EventsHelper
         end
       end
     
    -  def icon_for_event
    -    {
    -      EventFilter.push     => 'upload',
    -      EventFilter.merged   => 'check-square-o',
    -      EventFilter.comments => 'comments',
    -      EventFilter.team     => 'user',
    -    }
    -  end
    -
       def event_preposition(event)
         if event.push? || event.commented? || event.target
           "at"
    -- 
    cgit v1.2.1
    
    
    From c8f23bd2edc19f968446b149120df1f7798eb4b1 Mon Sep 17 00:00:00 2001
    From: DJ Mountney 
    Date: Wed, 11 May 2016 17:27:08 -0700
    Subject: Support token header for health check token, and general cleanup of
     the health_check feature.
    
    ---
     app/controllers/health_check_controller.rb       | 15 ++++++++--
     app/views/admin/health_check/show.html.haml      | 36 ++++++++++++++----------
     config/initializers/health_check.rb              |  2 +-
     config/routes.rb                                 |  2 +-
     spec/controllers/health_check_controller_spec.rb | 15 ++++++++++
     5 files changed, 50 insertions(+), 20 deletions(-)
    
    diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb
    index b974489836f..037da7d2bce 100644
    --- a/app/controllers/health_check_controller.rb
    +++ b/app/controllers/health_check_controller.rb
    @@ -1,13 +1,22 @@
     class HealthCheckController < HealthCheck::HealthCheckController
       before_action :validate_health_check_access!
     
    -  protected
    +  private
     
       def validate_health_check_access!
    -    return render_404 unless params[:token].presence && params[:token] == current_application_settings.health_check_access_token
    +    render_404 unless token_valid?
    +  end
    +
    +  def token_valid?
    +    token = params[:token].presence || request.headers['TOKEN']
    +    token.present? &&
    +      ActiveSupport::SecurityUtils.variable_size_secure_compare(
    +        token,
    +        current_application_settings.health_check_access_token
    +      )
       end
     
       def render_404
    -    render file: Rails.root.join("public", "404"), layout: false, status: "404"
    +    render file: Rails.root.join('public', '404'), layout: false, status: '404'
       end
     end
    diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
    index 23a931995ab..ed7025f7a0b 100644
    --- a/app/views/admin/health_check/show.html.haml
    +++ b/app/views/admin/health_check/show.html.haml
    @@ -2,29 +2,35 @@
     
     %h3.page-title
       Health Check
    -%p.light
    +.bs-callout.clearfix
    +  .pull-left
    +    %p
       Access token is
    -  %code{ id:'health-check-token' }= "#{current_application_settings.health_check_access_token}"
    +  %code#health-check-token= current_application_settings.health_check_access_token
    +  = button_to reset_health_check_token_admin_application_settings_path,
    +    method: :put, class: 'btn btn-default',
    +    data: { confirm: 'Are you sure you want to reset the health check token?' } do
    +    = icon('refresh')
    +    Reset health check access token
     %p.light
       Health information can be reteived as plain text, json, or xml using:
       %ul
         %li
    -      %code= "/health_check?token=#{current_application_settings.health_check_access_token}"
    +      %code= health_check_url(token:current_application_settings.health_check_access_token)
         %li
    -      %code= "/health_check.json?token=#{current_application_settings.health_check_access_token}"
    +      %code= health_check_url(token:current_application_settings.health_check_access_token, format: :json)
         %li
    -      %code= "/health_check.xml?token=#{current_application_settings.health_check_access_token}"
    +      %code= health_check_url(token:current_application_settings.health_check_access_token, format: :xml)
     
    -.bs-callout.clearfix
    -  .pull-left
    -    %p
    -      You can reset the health check access token by pressing the button below.
    -    %p
    -      = button_to reset_health_check_token_admin_application_settings_path,
    -        method: :put, class: 'btn btn-default',
    -        data: { confirm: 'Are you sure you want to reset the health check token?' } do
    -        = icon('refresh')
    -        Reset health check access token
    +%p.light
    +  You can also ask for the status of specific services:
    +  %ul
    +    %li
    +      %code= health_check_url(token:current_application_settings.health_check_access_token, checks: :cache)
    +    %li
    +      %code= health_check_url(token:current_application_settings.health_check_access_token, checks: :database)
    +    %li
    +      %code= health_check_url(token:current_application_settings.health_check_access_token, checks: :migrations)
     
     %hr
     .panel.panel-default
    diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
    index a93e4273030..79e2d23ab2e 100644
    --- a/config/initializers/health_check.rb
    +++ b/config/initializers/health_check.rb
    @@ -1,3 +1,3 @@
     HealthCheck.setup do |config|
    -  config.standard_checks = [ 'database', 'migrations', 'cache' ]
    +  config.standard_checks = ['database', 'migrations', 'cache']
     end
    diff --git a/config/routes.rb b/config/routes.rb
    index c81bf294a53..f794a881f71 100644
    --- a/config/routes.rb
    +++ b/config/routes.rb
    @@ -74,7 +74,7 @@ Rails.application.routes.draw do
       end
     
       # Health check
    -  get 'health_check(/:checks)(.:format)'  => 'health_check#index'
    +  get 'health_check(/:checks)'  => 'health_check#index', as: :health_check
     
       # Enable Grack support
       mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post, :put]
    diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
    index 3b9cc5c98f5..0d8a68bb51a 100644
    --- a/spec/controllers/health_check_controller_spec.rb
    +++ b/spec/controllers/health_check_controller_spec.rb
    @@ -14,6 +14,13 @@ describe HealthCheckController do
         end
     
         context 'when services are up and an access token is provided' do
    +      it 'supports passing the token in the header' do
    +        request.headers['TOKEN'] = token
    +        get :index
    +        expect(response).to be_success
    +        expect(response.content_type).to eq 'text/plain'
    +      end
    +
           it 'supports successful plaintest response' do
             get :index, token: token
             expect(response).to be_success
    @@ -55,6 +62,14 @@ describe HealthCheckController do
             allow(HealthCheck::Utils).to receive(:process_checks).with('email').and_return('Email is on fire')
           end
     
    +      it 'supports passing the token in the header' do
    +        request.headers['TOKEN'] = token
    +        get :index
    +        expect(response.status).to eq(500)
    +        expect(response.content_type).to eq 'text/plain'
    +        expect(response.body).to include('The server is on fire')
    +      end
    +
           it 'supports failure plaintest response' do
             get :index, token: token
             expect(response.status).to eq(500)
    -- 
    cgit v1.2.1
    
    
    From a59ad3936a0bdbfd64d9c54af631a272317fe680 Mon Sep 17 00:00:00 2001
    From: Timothy Andrew 
    Date: Thu, 5 May 2016 15:38:01 +0530
    Subject: Add a spec for `WikiLinkFilter`
    
    - And fix behavior for non-file hierarchical links.
    ---
     lib/banzai/filter/wiki_link_filter.rb           | 11 +++-
     spec/lib/banzai/filter/wiki_link_filter_spec.rb | 77 +++++++++++++++++++++++++
     2 files changed, 85 insertions(+), 3 deletions(-)
     create mode 100644 spec/lib/banzai/filter/wiki_link_filter_spec.rb
    
    diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
    index 06d10c98501..7dc771afd71 100644
    --- a/lib/banzai/filter/wiki_link_filter.rb
    +++ b/lib/banzai/filter/wiki_link_filter.rb
    @@ -25,7 +25,7 @@ module Banzai
           end
     
           def process_link_attr(html_attr)
    -        return if html_attr.blank? || file_reference?(html_attr)
    +        return if html_attr.blank? || file_reference?(html_attr) || hierarchical_link?(html_attr)
     
             uri = URI(html_attr.value)
             if uri.relative? && uri.path.present?
    @@ -40,12 +40,17 @@ module Banzai
             uri
           end
     
    +      def project_wiki
    +        context[:project_wiki]
    +      end
    +
           def file_reference?(html_attr)
             !File.extname(html_attr.value).blank?
           end
     
    -      def project_wiki
    -        context[:project_wiki]
    +      # Of the form `./link`, `../link`, or similar
    +      def hierarchical_link?(html_attr)
    +        html_attr.value[0] == '.'
           end
     
           def project_wiki_base_path
    diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
    new file mode 100644
    index 00000000000..56b1a267390
    --- /dev/null
    +++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
    @@ -0,0 +1,77 @@
    +require 'spec_helper'
    +
    +describe Banzai::Filter::WikiLinkFilter, lib: true do
    +  include FilterSpecHelper
    +
    +  let(:namespace) { build(:namespace, name: "wiki_link_ns") }
    +  let(:project)   { build(:empty_project, :public, name: "wiki_link_project", namespace: namespace) }
    +  let(:user) { double }
    +  let(:project_wiki) { ProjectWiki.new(project, user) }
    +
    +  describe "links within the wiki (relative)" do
    +    describe "hierarchical links to the current directory" do
    +      it "doesn't rewrite non-file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('./page')
    +      end
    +
    +      it "doesn't rewrite file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('./page.md')
    +      end
    +    end
    +
    +    describe "hierarchical links to the parent directory" do
    +      it "doesn't rewrite non-file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('../page')
    +      end
    +
    +      it "doesn't rewrite file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('../page.md')
    +      end
    +    end
    +
    +    describe "hierarchical links to a sub-directory" do
    +      it "doesn't rewrite non-file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('./subdirectory/page')
    +      end
    +
    +      it "doesn't rewrite file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('./subdirectory/page.md')
    +      end
    +    end
    +
    +    describe "non-hierarchical links" do
    +      it 'rewrites non-file links to be at the scope of the wiki root' do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
    +        expect(filtered_link.attribute('href').value).to match('/wiki_link_ns/wiki_link_project/wikis/page')
    +      end
    +
    +      it "doesn't rewrite file links" do
    +        link = "Link to Page"
    +        filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +        expect(filtered_link.attribute('href').value).to eq('page.md')
    +      end
    +    end
    +  end
    +
    +  describe "links outside the wiki (absolute)" do
    +    it "doesn't rewrite links" do
    +      link = "Link to Page"
    +      filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +      expect(filtered_link.attribute('href').value).to eq('http://example.com/page')
    +    end
    +  end
    +end
    -- 
    cgit v1.2.1
    
    
    From a4ee7d25e398f9d2e2311703fbbcf5f6b9bdf728 Mon Sep 17 00:00:00 2001
    From: Timothy Andrew 
    Date: Mon, 9 May 2016 16:04:05 +0530
    Subject: Implement @rymai's feedback after review.
    
    - Separate 'exercise' and 'verify' steps of tests.
    - Use `build_stubbed` instead of `build`
    ---
     spec/lib/banzai/filter/wiki_link_filter_spec.rb | 12 ++++++++++--
     1 file changed, 10 insertions(+), 2 deletions(-)
    
    diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
    index 56b1a267390..185abbb2108 100644
    --- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
    +++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
    @@ -3,8 +3,8 @@ require 'spec_helper'
     describe Banzai::Filter::WikiLinkFilter, lib: true do
       include FilterSpecHelper
     
    -  let(:namespace) { build(:namespace, name: "wiki_link_ns") }
    -  let(:project)   { build(:empty_project, :public, name: "wiki_link_project", namespace: namespace) }
    +  let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") }
    +  let(:project)   { build_stubbed(:empty_project, :public, name: "wiki_link_project", namespace: namespace) }
       let(:user) { double }
       let(:project_wiki) { ProjectWiki.new(project, user) }
     
    @@ -13,12 +13,14 @@ describe Banzai::Filter::WikiLinkFilter, lib: true do
           it "doesn't rewrite non-file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('./page')
           end
     
           it "doesn't rewrite file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('./page.md')
           end
         end
    @@ -27,12 +29,14 @@ describe Banzai::Filter::WikiLinkFilter, lib: true do
           it "doesn't rewrite non-file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('../page')
           end
     
           it "doesn't rewrite file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('../page.md')
           end
         end
    @@ -41,12 +45,14 @@ describe Banzai::Filter::WikiLinkFilter, lib: true do
           it "doesn't rewrite non-file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('./subdirectory/page')
           end
     
           it "doesn't rewrite file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('./subdirectory/page.md')
           end
         end
    @@ -62,6 +68,7 @@ describe Banzai::Filter::WikiLinkFilter, lib: true do
           it "doesn't rewrite file links" do
             link = "Link to Page"
             filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
             expect(filtered_link.attribute('href').value).to eq('page.md')
           end
         end
    @@ -71,6 +78,7 @@ describe Banzai::Filter::WikiLinkFilter, lib: true do
         it "doesn't rewrite links" do
           link = "Link to Page"
           filtered_link = filter(link, project_wiki: project_wiki).children[0]
    +
           expect(filtered_link.attribute('href').value).to eq('http://example.com/page')
         end
       end
    -- 
    cgit v1.2.1
    
    
    From 555610b619b552ca058a7656f373743db4d34765 Mon Sep 17 00:00:00 2001
    From: Timothy Andrew 
    Date: Tue, 10 May 2016 09:04:14 +0530
    Subject: Add CHANGELOG entry.
    
    ---
     CHANGELOG | 3 +++
     1 file changed, 3 insertions(+)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index d5ab79602f2..187011c6016 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -44,6 +44,9 @@ v 8.8.0 (unreleased)
       - 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.5
    +  - Fix relative links in wiki pages. !4050
    +
     v 8.7.4
       - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss)
       - Fix setting trusted proxies !3970
    -- 
    cgit v1.2.1
    
    
    From 7db3fb5a0b6c07b65c61c920e18f056f6c127932 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:05:34 +0300
    Subject: disabled_oauth_sign_in_sources column
    
    ---
     ...942_add_disabled_oauth_sign_in_sources_to_application_settings.rb | 5 +++++
     db/schema.rb                                                         | 1 +
     2 files changed, 6 insertions(+)
     create mode 100644 db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
    
    diff --git a/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
    new file mode 100644
    index 00000000000..facd33875ba
    --- /dev/null
    +++ b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
    @@ -0,0 +1,5 @@
    +class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration
    +  def change
    +    add_column :application_settings, :disabled_oauth_sign_in_sources, :text
    +  end
    +end
    diff --git a/db/schema.rb b/db/schema.rb
    index 71d953afe30..74facd12088 100644
    --- a/db/schema.rb
    +++ b/db/schema.rb
    @@ -80,6 +80,7 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.boolean  "repository_checks_enabled",         default: false
         t.text     "shared_runners_text"
         t.integer  "metrics_packet_size",               default: 1
    +    t.text     "disabled_oauth_sign_in_sources"
       end
     
       create_table "audit_events", force: :cascade do |t|
    -- 
    cgit v1.2.1
    
    
    From ca288587256b8995105b601ef02850f388d59ff9 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:06:18 +0300
    Subject: serialize the disabled_oauth_sign_in_sources
    
    ---
     app/models/application_setting.rb | 50 +++++++++++++++++++++++++++++++++++++++
     1 file changed, 50 insertions(+)
    
    diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
    index 7039db2d41e..39f74b2082e 100644
    --- a/app/models/application_setting.rb
    +++ b/app/models/application_setting.rb
    @@ -1,3 +1,52 @@
    +# == Schema Information
    +#
    +# Table name: application_settings
    +#
    +#  id                                :integer          not null, primary key
    +#  default_projects_limit            :integer
    +#  signup_enabled                    :boolean
    +#  signin_enabled                    :boolean
    +#  gravatar_enabled                  :boolean
    +#  sign_in_text                      :text
    +#  created_at                        :datetime
    +#  updated_at                        :datetime
    +#  home_page_url                     :string(255)
    +#  default_branch_protection         :integer          default(2)
    +#  restricted_visibility_levels      :text
    +#  version_check_enabled             :boolean          default(TRUE)
    +#  max_attachment_size               :integer          default(10), not null
    +#  default_project_visibility        :integer
    +#  default_snippet_visibility        :integer
    +#  default_group_visibility          :integer
    +#  restricted_signup_domains         :text
    +#  user_oauth_applications           :boolean          default(TRUE)
    +#  after_sign_out_path               :string(255)
    +#  session_expire_delay              :integer          default(10080), not null
    +#  import_sources                    :text
    +#  disabled_oauth_sign_in_sources    :text
    +#  help_page_text                    :text
    +#  admin_notification_email          :string(255)
    +#  shared_runners_enabled            :boolean          default(TRUE), not null
    +#  max_artifacts_size                :integer          default(100), not null
    +#  runners_registration_token        :string
    +#  require_two_factor_authentication :boolean          default(FALSE)
    +#  two_factor_grace_period           :integer          default(48)
    +#  metrics_enabled                   :boolean          default(FALSE)
    +#  metrics_host                      :string           default("localhost")
    +#  metrics_username                  :string
    +#  metrics_password                  :string
    +#  metrics_pool_size                 :integer          default(16)
    +#  metrics_timeout                   :integer          default(10)
    +#  metrics_method_call_threshold     :integer          default(10)
    +#  recaptcha_enabled                 :boolean          default(FALSE)
    +#  recaptcha_site_key                :string
    +#  recaptcha_private_key             :string
    +#  metrics_port                      :integer          default(8089)
    +#  sentry_enabled                    :boolean          default(FALSE)
    +#  sentry_dsn                        :string
    +#  email_author_in_body              :boolean          default(FALSE)
    +#
    +
     class ApplicationSetting < ActiveRecord::Base
       include TokenAuthenticatable
       add_authentication_token_field :runners_registration_token
    @@ -6,6 +55,7 @@ class ApplicationSetting < ActiveRecord::Base
     
       serialize :restricted_visibility_levels
       serialize :import_sources
    +  serialize :disabled_oauth_sign_in_sources
       serialize :restricted_signup_domains, Array
       attr_accessor :restricted_signup_domains_raw
     
    -- 
    cgit v1.2.1
    
    
    From e5ddd6d21eb6125605d3f47ea5db884b54514796 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:08:06 +0300
    Subject: disabled_oauth_sign_in_sources parameter handling in
     ApplicationSettingsController
    
    ---
     app/controllers/admin/application_settings_controller.rb | 12 +++++++++++-
     1 file changed, 11 insertions(+), 1 deletion(-)
    
    diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
    index ec22548ddeb..cebc01a2afc 100644
    --- a/app/controllers/admin/application_settings_controller.rb
    +++ b/app/controllers/admin/application_settings_controller.rb
    @@ -53,6 +53,15 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
           end
         end
     
    +    disabled_oauth_sign_in_sources = params[:application_setting][:disabled_oauth_sign_in_sources]
    +    if disabled_oauth_sign_in_sources.nil?
    +      params[:application_setting][:disabled_oauth_sign_in_sources] = []
    +    else
    +      disabled_oauth_sign_in_sources.map! do |source|
    +        source.to_str
    +      end
    +    end
    +
         params.require(:application_setting).permit(
           :default_projects_limit,
           :default_branch_protection,
    @@ -95,7 +104,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
           :repository_checks_enabled,
           :metrics_packet_size,
           restricted_visibility_levels: [],
    -      import_sources: []
    +      import_sources: [],
    +      disabled_oauth_sign_in_sources: []
         )
       end
     end
    -- 
    cgit v1.2.1
    
    
    From d8085d8e128e4ef50443f7a58bfbe7bf21565ab0 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:32:33 +0300
    Subject: default value for disabled_oauth_sign_in_sources in
     create_from_defaults @ ApplicationSetting
    
    ---
     app/models/application_setting.rb | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
    index 39f74b2082e..a48deccb029 100644
    --- a/app/models/application_setting.rb
    +++ b/app/models/application_setting.rb
    @@ -157,6 +157,7 @@ class ApplicationSetting < ActiveRecord::Base
           recaptcha_enabled: false,
           akismet_enabled: false,
           repository_checks_enabled: true,
    +      disabled_oauth_sign_in_sources: []
         )
       end
     
    -- 
    cgit v1.2.1
    
    
    From cf300443147f1a9ba3acf83ce839afdffa5173bd Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:33:33 +0300
    Subject: OAuth Providers disable from the ApplicationSettings page
    
    ---
     app/helpers/application_settings_helper.rb           | 15 +++++++++++++++
     app/views/admin/application_settings/_form.html.haml | 10 ++++++++++
     2 files changed, 25 insertions(+)
    
    diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
    index 914b0ef6042..17d73899878 100644
    --- a/app/helpers/application_settings_helper.rb
    +++ b/app/helpers/application_settings_helper.rb
    @@ -60,4 +60,19 @@ module ApplicationSettingsHelper
           end
         end
       end
    +
    +  def oauth_providers_checkboxes(help_block_id)
    +    button_based_providers.map do |source|
    +      checked = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s)
    +      css_class = 'btn'
    +      css_class += ' active' if checked
    +      checkbox_name = 'application_setting[disabled_oauth_sign_in_sources][]'
    +
    +      label_tag(checkbox_name, class: css_class) do
    +        check_box_tag(checkbox_name, source, checked,
    +                      autocomplete: 'off',
    +                      'aria-describedby' => help_block_id) + Gitlab::OAuth::Provider.label_for(source)
    +      end
    +    end
    +  end
     end
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index e0d8d16a954..057b237c066 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -109,6 +109,16 @@
               = f.label :signin_enabled do
                 = f.check_box :signin_enabled
                 Sign-in enabled
    +    .form-group
    +      = f.label :disable_oauth_signin_sources, class: 'control-label col-sm-2'
    +      .col-sm-10
    +        - data_attrs = { toggle: 'buttons' }
    +        .btn-group{ data: data_attrs }
    +          - oauth_providers_checkboxes('oauth-providers-help').each do |source|
    +            = source
    +        %span.help-block#oauth-providers-help
    +          Enabled OmniAuth must be configured for GitHub
    +          = link_to "(?)", help_page_path("integration", "github")
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
           .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From 8d26836e945f3e66a46370905b9fb34244a0ff91 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:35:03 +0300
    Subject: method to get the enabled_button_based_providers
    
    ---
     app/helpers/auth_helper.rb | 6 ++++++
     1 file changed, 6 insertions(+)
    
    diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
    index b4f80fd9b3e..24eb813d0ba 100644
    --- a/app/helpers/auth_helper.rb
    +++ b/app/helpers/auth_helper.rb
    @@ -38,6 +38,12 @@ module AuthHelper
         auth_providers.reject { |provider| form_based_provider?(provider) }
       end
     
    +  def enabled_button_based_providers
    +    disabled_providers = current_application_settings.disabled_oauth_sign_in_sources || []
    +
    +    button_based_providers.map(&:to_s) - disabled_providers
    +  end
    +
       def provider_image_tag(provider, size = 64)
         label = label_for_provider(provider)
     
    -- 
    cgit v1.2.1
    
    
    From d943e5f691ad9c59e349eab95f1a21bd0f85ab1b Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:36:15 +0300
    Subject: method to check if oauth button based providers are enabled
    
    ---
     app/helpers/auth_helper.rb | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
    index 24eb813d0ba..3e1f4209254 100644
    --- a/app/helpers/auth_helper.rb
    +++ b/app/helpers/auth_helper.rb
    @@ -44,6 +44,10 @@ module AuthHelper
         button_based_providers.map(&:to_s) - disabled_providers
       end
     
    +  def button_based_providers_enabled?
    +    !enabled_button_based_providers.empty?
    +  end
    +
       def provider_image_tag(provider, size = 64)
         label = label_for_provider(provider)
     
    -- 
    cgit v1.2.1
    
    
    From 284eccb5e68c863ea8e1001a24af33dd0da5e201 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:36:57 +0300
    Subject: render the omniauth_box if there are any button_based_providers
    
    ---
     app/views/devise/sessions/new.html.haml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
    index d65fa60025c..28194506acc 100644
    --- a/app/views/devise/sessions/new.html.haml
    +++ b/app/views/devise/sessions/new.html.haml
    @@ -4,7 +4,7 @@
         = render 'devise/shared/signin_box'
     
       -# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box
    -  - if omniauth_enabled? && devise_mapping.omniauthable?
    +  - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
         .clearfix.prepend-top-20
           = render 'devise/shared/omniauth_box'
     
    -- 
    cgit v1.2.1
    
    
    From 28da3a88de339a95d49e171da87494f65219cb21 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 13:37:18 +0300
    Subject: show only the eanbled oauth providers
    
    ---
     app/views/devise/shared/_omniauth_box.html.haml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
    index ecf680e7b23..de18bc2d844 100644
    --- a/app/views/devise/shared/_omniauth_box.html.haml
    +++ b/app/views/devise/shared/_omniauth_box.html.haml
    @@ -1,7 +1,7 @@
     %p
       %span.light
         Sign in with  
    -  - providers = button_based_providers
    +  - providers = enabled_button_based_providers
       - providers.each do |provider|
         %span.light
           - has_icon = provider_has_icon?(provider)
    -- 
    cgit v1.2.1
    
    
    From 7c7c5b7e40ff4fed64a9f62beed027064c292eaf Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 15:22:24 +0300
    Subject: text for the disable_oauth_signin_sources label
    
    ---
     app/views/admin/application_settings/_form.html.haml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 057b237c066..729c2ff563d 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -110,7 +110,7 @@
                 = f.check_box :signin_enabled
                 Sign-in enabled
         .form-group
    -      = f.label :disable_oauth_signin_sources, class: 'control-label col-sm-2'
    +      = f.label :disable_oauth_signin_sources, 'Disable OAuth Sign-In sources', class: 'control-label col-sm-2'
           .col-sm-10
             - data_attrs = { toggle: 'buttons' }
             .btn-group{ data: data_attrs }
    -- 
    cgit v1.2.1
    
    
    From 47ee5125e881694b7713f187b48589a2f4bbd747 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 15:57:00 +0300
    Subject: validate disabled_oauth_sign_in_sources in ApplicationSe
    
    ---
     app/models/application_setting.rb       | 10 ++++++++++
     spec/models/application_setting_spec.rb |  3 +++
     2 files changed, 13 insertions(+)
    
    diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
    index a48deccb029..d565dbc71d0 100644
    --- a/app/models/application_setting.rb
    +++ b/app/models/application_setting.rb
    @@ -119,6 +119,16 @@ class ApplicationSetting < ActiveRecord::Base
         end
       end
     
    +  validates_each :disabled_oauth_sign_in_sources do |record, attr, value|
    +    unless value.nil?
    +      value.each do |source|
    +        unless Devise.omniauth_providers.include?(source.to_sym)
    +          record.errors.add(attr, "'#{source}' is not an ouath sign-in source")
    +        end
    +      end
    +    end
    +  end
    +
       before_save :ensure_runners_registration_token
     
       after_commit do
    diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
    index 1ce22feed5c..fb3ea491df7 100644
    --- a/spec/models/application_setting_spec.rb
    +++ b/spec/models/application_setting_spec.rb
    @@ -20,6 +20,9 @@ describe ApplicationSetting, models: true do
         it { is_expected.to allow_value(https).for(:after_sign_out_path) }
         it { is_expected.not_to allow_value(ftp).for(:after_sign_out_path) }
     
    +    it { is_expected.to allow_value([:github]).for(:disabled_oauth_sign_in_sources) }
    +    it { is_expected.not_to allow_value([:test]).for(:disabled_oauth_sign_in_sources) }
    +
         it { is_expected.to validate_presence_of(:max_attachment_size) }
     
         it do
    -- 
    cgit v1.2.1
    
    
    From 8c2b72b1c80e8bbd082ac8e1aedb21a1aad07235 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 17:04:54 +0300
    Subject: tests for enabled_button_based_providers helper method of AuthHelper
    
    ---
     spec/helpers/auth_helper_spec.rb | 22 +++++++++++++++++++++-
     1 file changed, 21 insertions(+), 1 deletion(-)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index e47a54fdac5..5d66c92d26e 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -2,7 +2,9 @@ require "spec_helper"
     
     describe AuthHelper do
       describe "button_based_providers" do
    -    it 'returns all enabled providers' do
    +    let(:settings) { ApplicationSetting.create_from_defaults }
    +
    +    it 'returns all enabled providers from devise' do
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
           expect(helper.button_based_providers).to include(*[:twitter, :github])
         end
    @@ -16,5 +18,23 @@ describe AuthHelper do
           allow(helper).to receive(:auth_providers) { [] }
           expect(helper.button_based_providers).to eq([])
         end
    +
    +    it 'returns all the enabled providers from settings' do
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +      expect(helper.enabled_button_based_providers).to include(*['twitter', 'github'])
    +    end
    +
    +    it 'should not return github as provider because it\'s disabled from settings' do
    +      settings.update_attribute(
    +        :disabled_oauth_sign_in_sources,
    +        ['github']
    +      )
    +
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +      allow(helper).to receive(:current_application_settings) {  settings }
    +
    +      expect(helper.enabled_button_based_providers).to include('twitter')
    +      expect(helper.enabled_button_based_providers).to_not include('github')
    +    end
       end
     end
    -- 
    cgit v1.2.1
    
    
    From 6f69f6a1ab70bd2252803a64927d0c8df1d03612 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 4 May 2016 17:06:07 +0300
    Subject: tests for button_based_providers_enabled? helper method of AuthHelper
    
    ---
     spec/helpers/auth_helper_spec.rb | 18 ++++++++++++++++++
     1 file changed, 18 insertions(+)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index 5d66c92d26e..a6a366bc19a 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -36,5 +36,23 @@ describe AuthHelper do
           expect(helper.enabled_button_based_providers).to include('twitter')
           expect(helper.enabled_button_based_providers).to_not include('github')
         end
    +
    +    it 'returns true for button_based_providers_enabled? because there providers' do
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +
    +      expect(helper.button_based_providers_enabled?).to be true
    +    end
    +
    +    it 'returns false for button_based_providers_enabled? because there providers' do
    +      settings.update_attribute(
    +        :disabled_oauth_sign_in_sources,
    +        ['github', 'twitter']
    +      )
    +
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +      allow(helper).to receive(:current_application_settings) {  settings }
    +
    +      expect(helper.button_based_providers_enabled?).to be false
    +    end
       end
     end
    -- 
    cgit v1.2.1
    
    
    From deca3da1a7f4e59c97c27bedf7aa26185a4d883b Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Thu, 5 May 2016 10:34:51 +0300
    Subject: stub Devise.omniauth_providers to return GitHub even if the
     gitlab.yml has no omniauth provider enabled This will fix failing tests in
     case gitlab.yml file has no omniauth providers enabled
    
    ---
     spec/models/application_setting_spec.rb | 10 ++++++++--
     1 file changed, 8 insertions(+), 2 deletions(-)
    
    diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
    index fb3ea491df7..d84f3e998f5 100644
    --- a/spec/models/application_setting_spec.rb
    +++ b/spec/models/application_setting_spec.rb
    @@ -20,8 +20,14 @@ describe ApplicationSetting, models: true do
         it { is_expected.to allow_value(https).for(:after_sign_out_path) }
         it { is_expected.not_to allow_value(ftp).for(:after_sign_out_path) }
     
    -    it { is_expected.to allow_value([:github]).for(:disabled_oauth_sign_in_sources) }
    -    it { is_expected.not_to allow_value([:test]).for(:disabled_oauth_sign_in_sources) }
    +    describe 'disabled_oauth_sign_in_sources validations' do
    +      before do
    +        allow(Devise).to receive(:omniauth_providers).and_return([:github])
    +      end
    +
    +      it { is_expected.to allow_value(['github']).for(:disabled_oauth_sign_in_sources) }
    +      it { is_expected.not_to allow_value(['test']).for(:disabled_oauth_sign_in_sources) }
    +    end
     
         it { is_expected.to validate_presence_of(:max_attachment_size) }
     
    -- 
    cgit v1.2.1
    
    
    From 2e4c914ae88b77c8a3871f8415163a51e23254e5 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 10:31:25 +0300
    Subject: between ""
    
    ---
     spec/helpers/auth_helper_spec.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index a6a366bc19a..6dc1135927d 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -24,7 +24,7 @@ describe AuthHelper do
           expect(helper.enabled_button_based_providers).to include(*['twitter', 'github'])
         end
     
    -    it 'should not return github as provider because it\'s disabled from settings' do
    +    it "should not return github as provider because it's disabled from settings" do
           settings.update_attribute(
             :disabled_oauth_sign_in_sources,
             ['github']
    -- 
    cgit v1.2.1
    
    
    From fc88527c9e21f99a9411423f1c8a6475957c02f3 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 10:40:27 +0300
    Subject: use stub_application_setting instead
    
    ---
     spec/helpers/auth_helper_spec.rb | 14 ++++----------
     1 file changed, 4 insertions(+), 10 deletions(-)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index 6dc1135927d..e6af074a780 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -2,8 +2,6 @@ require "spec_helper"
     
     describe AuthHelper do
       describe "button_based_providers" do
    -    let(:settings) { ApplicationSetting.create_from_defaults }
    -
         it 'returns all enabled providers from devise' do
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
           expect(helper.button_based_providers).to include(*[:twitter, :github])
    @@ -25,13 +23,11 @@ describe AuthHelper do
         end
     
         it "should not return github as provider because it's disabled from settings" do
    -      settings.update_attribute(
    -        :disabled_oauth_sign_in_sources,
    -        ['github']
    +      stub_application_setting(
    +        disabled_oauth_sign_in_sources: ['github']
           )
     
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    -      allow(helper).to receive(:current_application_settings) {  settings }
     
           expect(helper.enabled_button_based_providers).to include('twitter')
           expect(helper.enabled_button_based_providers).to_not include('github')
    @@ -44,13 +40,11 @@ describe AuthHelper do
         end
     
         it 'returns false for button_based_providers_enabled? because there providers' do
    -      settings.update_attribute(
    -        :disabled_oauth_sign_in_sources,
    -        ['github', 'twitter']
    +      stub_application_setting(
    +        disabled_oauth_sign_in_sources: ['github', 'twitter']
           )
     
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    -      allow(helper).to receive(:current_application_settings) {  settings }
     
           expect(helper.button_based_providers_enabled?).to be false
         end
    -- 
    cgit v1.2.1
    
    
    From 3922e7ee2249bb5a683b7474b281d8e83d465740 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 10:42:57 +0300
    Subject: enabled_button_based_providers into their own describe section
    
    ---
     spec/helpers/auth_helper_spec.rb | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index e6af074a780..04b51282795 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -16,7 +16,9 @@ describe AuthHelper do
           allow(helper).to receive(:auth_providers) { [] }
           expect(helper.button_based_providers).to eq([])
         end
    +  end
     
    +  describe 'enabled_button_based_providers' do
         it 'returns all the enabled providers from settings' do
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
           expect(helper.enabled_button_based_providers).to include(*['twitter', 'github'])
    -- 
    cgit v1.2.1
    
    
    From 038dbb6803948e050484ed3f34c99b2f3bf7a6c5 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 10:51:24 +0300
    Subject: DRYing enabled_button_based_providers tests
    
    ---
     spec/helpers/auth_helper_spec.rb | 11 ++++-------
     1 file changed, 4 insertions(+), 7 deletions(-)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index 04b51282795..a6df8204213 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -19,8 +19,11 @@ describe AuthHelper do
       end
     
       describe 'enabled_button_based_providers' do
    -    it 'returns all the enabled providers from settings' do
    +    before do
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +    end
    +
    +    it 'returns all the enabled providers from settings' do
           expect(helper.enabled_button_based_providers).to include(*['twitter', 'github'])
         end
     
    @@ -29,15 +32,11 @@ describe AuthHelper do
             disabled_oauth_sign_in_sources: ['github']
           )
     
    -      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    -
           expect(helper.enabled_button_based_providers).to include('twitter')
           expect(helper.enabled_button_based_providers).to_not include('github')
         end
     
         it 'returns true for button_based_providers_enabled? because there providers' do
    -      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    -
           expect(helper.button_based_providers_enabled?).to be true
         end
     
    @@ -46,8 +45,6 @@ describe AuthHelper do
             disabled_oauth_sign_in_sources: ['github', 'twitter']
           )
     
    -      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    -
           expect(helper.button_based_providers_enabled?).to be false
         end
       end
    -- 
    cgit v1.2.1
    
    
    From 3c3bc93747ebe5864a50d7b8203b357a40012ed4 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 19:32:01 +0300
    Subject: if omniauth is enabled and if there are button_based_providers
     available show the disable OAuth sources
    
    ---
     .../admin/application_settings/_form.html.haml      | 21 +++++++++++----------
     1 file changed, 11 insertions(+), 10 deletions(-)
    
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 729c2ff563d..81c232b7e92 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -109,16 +109,17 @@
               = f.label :signin_enabled do
                 = f.check_box :signin_enabled
                 Sign-in enabled
    -    .form-group
    -      = f.label :disable_oauth_signin_sources, 'Disable OAuth Sign-In sources', class: 'control-label col-sm-2'
    -      .col-sm-10
    -        - data_attrs = { toggle: 'buttons' }
    -        .btn-group{ data: data_attrs }
    -          - oauth_providers_checkboxes('oauth-providers-help').each do |source|
    -            = source
    -        %span.help-block#oauth-providers-help
    -          Enabled OmniAuth must be configured for GitHub
    -          = link_to "(?)", help_page_path("integration", "github")
    +      - if omniauth_enabled? && !button_based_providers.empty?
    +        .form-group
    +          = f.label :disable_oauth_signin_sources, 'Disable OAuth Sign-In sources', class: 'control-label col-sm-2'
    +          .col-sm-10
    +            - data_attrs = { toggle: 'buttons' }
    +            .btn-group{ data: data_attrs }
    +              - oauth_providers_checkboxes('oauth-providers-help').each do |source|
    +                = source
    +            %span.help-block#oauth-providers-help
    +              Enabled OmniAuth must be configured for GitHub
    +              = link_to "(?)", help_page_path("integration", "github")
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
           .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From dad501a2367a35f6d791efac9002e487176f2c9e Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 19:34:44 +0300
    Subject: no need to show the help about Github or the other authentication
     sources
    
    ---
     app/views/admin/application_settings/_form.html.haml | 3 ---
     1 file changed, 3 deletions(-)
    
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 81c232b7e92..99f86e5244b 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -117,9 +117,6 @@
                 .btn-group{ data: data_attrs }
                   - oauth_providers_checkboxes('oauth-providers-help').each do |source|
                     = source
    -            %span.help-block#oauth-providers-help
    -              Enabled OmniAuth must be configured for GitHub
    -              = link_to "(?)", help_page_path("integration", "github")
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
           .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From a2d4c349b5772231d7428cf32ac8a66d70beb627 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Mon, 9 May 2016 19:38:07 +0300
    Subject: unindent 1 level the Disable OAuth form
    
    ---
     app/views/admin/application_settings/_form.html.haml | 16 ++++++++--------
     1 file changed, 8 insertions(+), 8 deletions(-)
    
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 99f86e5244b..383f206079d 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -109,14 +109,14 @@
               = f.label :signin_enabled do
                 = f.check_box :signin_enabled
                 Sign-in enabled
    -      - if omniauth_enabled? && !button_based_providers.empty?
    -        .form-group
    -          = f.label :disable_oauth_signin_sources, 'Disable OAuth Sign-In sources', class: 'control-label col-sm-2'
    -          .col-sm-10
    -            - data_attrs = { toggle: 'buttons' }
    -            .btn-group{ data: data_attrs }
    -              - oauth_providers_checkboxes('oauth-providers-help').each do |source|
    -                = source
    +    - if omniauth_enabled? && !button_based_providers.empty?
    +      .form-group
    +        = f.label :disable_oauth_signin_sources, 'Disable OAuth Sign-In sources', class: 'control-label col-sm-2'
    +        .col-sm-10
    +          - data_attrs = { toggle: 'buttons' }
    +          .btn-group{ data: data_attrs }
    +            - oauth_providers_checkboxes('oauth-providers-help').each do |source|
    +              = source
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
           .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From 81d0a4a47390f3810b03528182d3eea68ab46112 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 10:21:14 +0300
    Subject: typo
    
    ---
     app/models/application_setting.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
    index d565dbc71d0..667b45335b5 100644
    --- a/app/models/application_setting.rb
    +++ b/app/models/application_setting.rb
    @@ -123,7 +123,7 @@ class ApplicationSetting < ActiveRecord::Base
         unless value.nil?
           value.each do |source|
             unless Devise.omniauth_providers.include?(source.to_sym)
    -          record.errors.add(attr, "'#{source}' is not an ouath sign-in source")
    +          record.errors.add(attr, "'#{source}' is not an OAuth sign-in source")
             end
           end
         end
    -- 
    cgit v1.2.1
    
    
    From 96122034cfc2eb7039ae75b20b729f35e9aa832e Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 11:17:37 +0300
    Subject: more readable specs for enabled_button_based_providers and
     button_based_providers_enabled?
    
    ---
     spec/helpers/auth_helper_spec.rb | 44 ++++++++++++++++++++++++++--------------
     1 file changed, 29 insertions(+), 15 deletions(-)
    
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index a6df8204213..16fbb5dcecb 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -23,29 +23,43 @@ describe AuthHelper do
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
         end
     
    -    it 'returns all the enabled providers from settings' do
    -      expect(helper.enabled_button_based_providers).to include(*['twitter', 'github'])
    +    context 'all providers are enabled to sign in' do
    +      it 'returns all the enabled providers from settings' do
    +        expect(helper.enabled_button_based_providers).to include('twitter', 'github')
    +      end
         end
     
    -    it "should not return github as provider because it's disabled from settings" do
    -      stub_application_setting(
    -        disabled_oauth_sign_in_sources: ['github']
    -      )
    +    context 'GitHub OAuth sign in is disabled from application setting' do
    +      it "doesn't return github as provider" do
    +        stub_application_setting(
    +          disabled_oauth_sign_in_sources: ['github']
    +        )
     
    -      expect(helper.enabled_button_based_providers).to include('twitter')
    -      expect(helper.enabled_button_based_providers).to_not include('github')
    +        expect(helper.enabled_button_based_providers).to include('twitter')
    +        expect(helper.enabled_button_based_providers).to_not include('github')
    +      end
    +    end
    +  end
    +
    +  describe 'button_based_providers_enabled?' do
    +    before do
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
         end
     
    -    it 'returns true for button_based_providers_enabled? because there providers' do
    -      expect(helper.button_based_providers_enabled?).to be true
    +    context 'button based providers enabled' do
    +      it 'returns true' do
    +        expect(helper.button_based_providers_enabled?).to be true
    +      end
         end
     
    -    it 'returns false for button_based_providers_enabled? because there providers' do
    -      stub_application_setting(
    -        disabled_oauth_sign_in_sources: ['github', 'twitter']
    -      )
    +    context 'all the button based providers are disabled via application_setting' do
    +      it 'returns false' do
    +        stub_application_setting(
    +          disabled_oauth_sign_in_sources: ['github', 'twitter']
    +        )
     
    -      expect(helper.button_based_providers_enabled?).to be false
    +        expect(helper.button_based_providers_enabled?).to be false
    +      end
         end
       end
     end
    -- 
    cgit v1.2.1
    
    
    From 7818f7329a436d86b30dff003b60ab8a15a4f0db Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 11:29:19 +0300
    Subject: On Application Settings Page let the user select the enabled OAuth
     Sign in sources instead of the disabled ones
    
    ---
     app/controllers/admin/application_settings_controller.rb | 16 ++++++++--------
     app/helpers/application_settings_helper.rb               |  8 ++++----
     app/views/admin/application_settings/_form.html.haml     |  2 +-
     3 files changed, 13 insertions(+), 13 deletions(-)
    
    diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
    index cebc01a2afc..d7a052700ac 100644
    --- a/app/controllers/admin/application_settings_controller.rb
    +++ b/app/controllers/admin/application_settings_controller.rb
    @@ -53,14 +53,13 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
           end
         end
     
    -    disabled_oauth_sign_in_sources = params[:application_setting][:disabled_oauth_sign_in_sources]
    -    if disabled_oauth_sign_in_sources.nil?
    -      params[:application_setting][:disabled_oauth_sign_in_sources] = []
    -    else
    -      disabled_oauth_sign_in_sources.map! do |source|
    -        source.to_str
    -      end
    -    end
    +    enabled_oauth_sign_in_sources = params[:application_setting][:enabled_oauth_sign_in_sources]
    +
    +    params[:application_setting][:disabled_oauth_sign_in_sources] =
    +      AuthHelper.button_based_providers.map(&:to_s) -
    +      (enabled_oauth_sign_in_sources.nil? ? [] : enabled_oauth_sign_in_sources)
    +
    +    params[:application_setting].delete(:enabled_oauth_sign_in_sources)
     
         params.require(:application_setting).permit(
           :default_projects_limit,
    @@ -105,6 +104,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
           :metrics_packet_size,
           restricted_visibility_levels: [],
           import_sources: [],
    +      enabled_oauth_sign_in_sources: [],
           disabled_oauth_sign_in_sources: []
         )
       end
    diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
    index 17d73899878..ced8e16de74 100644
    --- a/app/helpers/application_settings_helper.rb
    +++ b/app/helpers/application_settings_helper.rb
    @@ -63,13 +63,13 @@ module ApplicationSettingsHelper
     
       def oauth_providers_checkboxes(help_block_id)
         button_based_providers.map do |source|
    -      checked = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s)
    +      disabled = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s)
           css_class = 'btn'
    -      css_class += ' active' if checked
    -      checkbox_name = 'application_setting[disabled_oauth_sign_in_sources][]'
    +      css_class += ' active' unless disabled
    +      checkbox_name = 'application_setting[enabled_oauth_sign_in_sources][]'
     
           label_tag(checkbox_name, class: css_class) do
    -        check_box_tag(checkbox_name, source, checked,
    +        check_box_tag(checkbox_name, source, !disabled,
                           autocomplete: 'off',
                           'aria-describedby' => help_block_id) + Gitlab::OAuth::Provider.label_for(source)
           end
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 383f206079d..ecd032acfd0 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -111,7 +111,7 @@
                 Sign-in enabled
         - if omniauth_enabled? && !button_based_providers.empty?
           .form-group
    -        = f.label :disable_oauth_signin_sources, 'Disable OAuth Sign-In sources', class: 'control-label col-sm-2'
    +        = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth Sign-In sources', class: 'control-label col-sm-2'
             .col-sm-10
               - data_attrs = { toggle: 'buttons' }
               .btn-group{ data: data_attrs }
    -- 
    cgit v1.2.1
    
    
    From bc099d799ea502c9fd8f1a09f07af70cdcf51156 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 11:50:53 +0300
    Subject: Allow Admins to remove the Login with buttons for OAuth services and
     still be able to import on the changelog
    
    ---
     CHANGELOG | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 187011c6016..8d70ef9944e 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -55,6 +55,8 @@ v 8.7.4
       - 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
    +  - Merge request widget displays TeamCity build state and code coverage correctly again.
    +  - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034
     
     v 8.7.3
       - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
    -- 
    cgit v1.2.1
    
    
    From 3a91f5081eeeef8dca52a418aba2d786cbc8ddf4 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 11:53:22 +0300
    Subject: documentation for enabling or disabling OAuth sign in
    
    ---
     doc/integration/img/enabled-oauth-sign-in-sources.png | Bin 0 -> 49081 bytes
     doc/integration/omniauth.md                           |  14 ++++++++++++++
     2 files changed, 14 insertions(+)
     create mode 100644 doc/integration/img/enabled-oauth-sign-in-sources.png
    
    diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png
    new file mode 100644
    index 00000000000..95f8bbdcd24
    Binary files /dev/null and b/doc/integration/img/enabled-oauth-sign-in-sources.png differ
    diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
    index cab329c0dec..f0d7394005c 100644
    --- a/doc/integration/omniauth.md
    +++ b/doc/integration/omniauth.md
    @@ -11,6 +11,7 @@ of the configured mechanisms.
     - [Supported Providers](#supported-providers)
     - [Enable OmniAuth for an Existing User](#enable-omniauth-for-an-existing-user)
     - [OmniAuth configuration sample when using Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master#omniauth-google-twitter-github-login)
    +- [Enable or disable Sign In with an OmniAuth provider without disabling import sources](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources)
     
     ## Supported Providers
     
    @@ -191,3 +192,16 @@ experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/w
     
     While we can't officially support every possible authentication mechanism out there,
     we'd like to at least help those with specific needs.
    +
    +## Enable or disable Sign In with an OmniAuth provider without disabling import sources
    +>**Note:**
    +This setting was introduced with version 8.8 of GitLab
    +
    +Administrators are able to enable or disable Sign In via some OmniAuth providers.
    +
    +>**Note:**
    +By default Sign In is enabled via all the OAuth Providers that have been configured in config/gitlab.yml.
    +
    +In order to enable/disable an OmniAuth provider go to Admin Area -> Settings-> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable.
    +
    +![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png)
    -- 
    cgit v1.2.1
    
    
    From 2a99c51590da3c430b27538a1f570d34209d51c7 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:39:27 +0300
    Subject: corrections to the Enable or disable Sign In with OmniAuth
    
    ---
     doc/integration/omniauth.md | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
    index f0d7394005c..f3e891fa457 100644
    --- a/doc/integration/omniauth.md
    +++ b/doc/integration/omniauth.md
    @@ -194,14 +194,15 @@ While we can't officially support every possible authentication mechanism out th
     we'd like to at least help those with specific needs.
     
     ## Enable or disable Sign In with an OmniAuth provider without disabling import sources
    +
     >**Note:**
    -This setting was introduced with version 8.8 of GitLab
    +This setting was introduced with version 8.8 of GitLab.
     
     Administrators are able to enable or disable Sign In via some OmniAuth providers.
     
     >**Note:**
     By default Sign In is enabled via all the OAuth Providers that have been configured in config/gitlab.yml.
     
    -In order to enable/disable an OmniAuth provider go to Admin Area -> Settings-> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable.
    +In order to enable/disable an OmniAuth provider, go to Admin Area -> Settings -> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable.
     
     ![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png)
    -- 
    cgit v1.2.1
    
    
    From 4372043392d735db506f1e696c213c3ece47bc1a Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:40:20 +0300
    Subject: credits for !4034
    
    ---
     CHANGELOG | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 8d70ef9944e..7cd8f63321f 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -43,6 +43,7 @@ v 8.8.0 (unreleased)
       - 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
    +  - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga)
     
     v 8.7.5
       - Fix relative links in wiki pages. !4050
    @@ -55,8 +56,6 @@ v 8.7.4
       - 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
    -  - Merge request widget displays TeamCity build state and code coverage correctly again.
    -  - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034
     
     v 8.7.3
       - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
    -- 
    cgit v1.2.1
    
    
    From 9bfa74fcfe79c244fe4fd7d074b87bb22ba7971f Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:43:54 +0300
    Subject: enabled_oauth_sign_in_sources param doesn't need permit
    
    ---
     app/controllers/admin/application_settings_controller.rb | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
    index d7a052700ac..a2dfed0b7a6 100644
    --- a/app/controllers/admin/application_settings_controller.rb
    +++ b/app/controllers/admin/application_settings_controller.rb
    @@ -104,7 +104,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
           :metrics_packet_size,
           restricted_visibility_levels: [],
           import_sources: [],
    -      enabled_oauth_sign_in_sources: [],
           disabled_oauth_sign_in_sources: []
         )
       end
    -- 
    cgit v1.2.1
    
    
    From ab7f9c9ae1281857bef655a1af64774c628befa1 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:45:39 +0300
    Subject: Array(enabled_oauth_sign_in_sources) instead of the if
    
    ---
     app/controllers/admin/application_settings_controller.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
    index a2dfed0b7a6..c3005602366 100644
    --- a/app/controllers/admin/application_settings_controller.rb
    +++ b/app/controllers/admin/application_settings_controller.rb
    @@ -57,7 +57,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
     
         params[:application_setting][:disabled_oauth_sign_in_sources] =
           AuthHelper.button_based_providers.map(&:to_s) -
    -      (enabled_oauth_sign_in_sources.nil? ? [] : enabled_oauth_sign_in_sources)
    +      Array(enabled_oauth_sign_in_sources)
     
         params[:application_setting].delete(:enabled_oauth_sign_in_sources)
     
    -- 
    cgit v1.2.1
    
    
    From 25ff3fd5bdd8645f45254aa52397f8d6b49386b5 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:46:40 +0300
    Subject: button_based_providers.any? instead of !button_based_providers.empty?
    
    ---
     app/views/admin/application_settings/_form.html.haml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index ecd032acfd0..909339f7bce 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -109,7 +109,7 @@
               = f.label :signin_enabled do
                 = f.check_box :signin_enabled
                 Sign-in enabled
    -    - if omniauth_enabled? && !button_based_providers.empty?
    +    - if omniauth_enabled? && button_based_providers.any?
           .form-group
             = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth Sign-In sources', class: 'control-label col-sm-2'
             .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From e87c96eef6d8d837bf4475e2681f4c5c5e40488d Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:48:08 +0300
    Subject: enabled_button_based_providers.any? instead of ! empty? for
     button_based_providers_enabled?
    
    ---
     app/helpers/auth_helper.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
    index 3e1f4209254..b05fa0a14d6 100644
    --- a/app/helpers/auth_helper.rb
    +++ b/app/helpers/auth_helper.rb
    @@ -45,7 +45,7 @@ module AuthHelper
       end
     
       def button_based_providers_enabled?
    -    !enabled_button_based_providers.empty?
    +    enabled_button_based_providers.any?
       end
     
       def provider_image_tag(provider, size = 64)
    -- 
    cgit v1.2.1
    
    
    From 46064cb84c579bd1657baffe24f5a515759bff67 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:50:03 +0300
    Subject: << instead of +=
    
    ---
     app/helpers/application_settings_helper.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
    index ced8e16de74..878b1b254ce 100644
    --- a/app/helpers/application_settings_helper.rb
    +++ b/app/helpers/application_settings_helper.rb
    @@ -65,7 +65,7 @@ module ApplicationSettingsHelper
         button_based_providers.map do |source|
           disabled = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s)
           css_class = 'btn'
    -      css_class += ' active' unless disabled
    +      css_class << ' active' unless disabled
           checkbox_name = 'application_setting[enabled_oauth_sign_in_sources][]'
     
           label_tag(checkbox_name, class: css_class) do
    -- 
    cgit v1.2.1
    
    
    From 6bd8d3ad48b9151c0bcb69bfbce0bc2551cdf184 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Tue, 10 May 2016 18:53:02 +0300
    Subject: inline btn-group{ data: { toggle: 'buttons' } }
    
    ---
     app/views/admin/application_settings/_form.html.haml | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 909339f7bce..576509e3f2b 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -113,8 +113,7 @@
           .form-group
             = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth Sign-In sources', class: 'control-label col-sm-2'
             .col-sm-10
    -          - data_attrs = { toggle: 'buttons' }
    -          .btn-group{ data: data_attrs }
    +          .btn-group{ data: { toggle: 'buttons' } }
                 - oauth_providers_checkboxes('oauth-providers-help').each do |source|
                   = source
         .form-group
    -- 
    cgit v1.2.1
    
    
    From 9079b56bf4f149054e347aa09ad151ab617ef123 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 11 May 2016 10:35:18 +0300
    Subject: Revert "no need to show the help about Github or the other
     authentication sources"
    
    This reverts commit 78a832d0fd7ff445c707809134dbb2a42d2a9e03.
    
    Show help only for the enabled OAuth Providers on oauth-providers-help block
    
    aria: { describedby: help_block_id } instead of 'aria-describedby' => help_block_id
    
    provider and not p
    
    a more simple approach to the OmniAuth helper links for oauth-providers-help
    ---
     app/helpers/application_settings_helper.rb           | 9 ++++++++-
     app/views/admin/application_settings/_form.html.haml | 3 +++
     2 files changed, 11 insertions(+), 1 deletion(-)
    
    diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
    index 878b1b254ce..82056a4c977 100644
    --- a/app/helpers/application_settings_helper.rb
    +++ b/app/helpers/application_settings_helper.rb
    @@ -71,8 +71,15 @@ module ApplicationSettingsHelper
           label_tag(checkbox_name, class: css_class) do
             check_box_tag(checkbox_name, source, !disabled,
                           autocomplete: 'off',
    -                      'aria-describedby' => help_block_id) + Gitlab::OAuth::Provider.label_for(source)
    +                      aria: { describedby: help_block_id }) + Gitlab::OAuth::Provider.label_for(source)
           end
         end
       end
    +
    +  def oauth_providers_with_help_links
    +    button_based_providers.map do |provider|
    +      Gitlab::OAuth::Provider.label_for(provider) + ' ' +
    +        link_to("(?)", help_page_path("integration", provider))
    +    end
    +  end
     end
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 576509e3f2b..f3681bc96e3 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -116,6 +116,9 @@
               .btn-group{ data: { toggle: 'buttons' } }
                 - oauth_providers_checkboxes('oauth-providers-help').each do |source|
                   = source
    +          %span.help-block#oauth-providers-help
    +            Enabled OmniAuth must be configured for
    +            = oauth_providers_with_help_links.to_sentence.html_safe
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
           .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From 2576a55e35f06d2d59783867be5e7e2ccbed982e Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 11 May 2016 19:52:06 +0300
    Subject: config/gitlab.yml between ``
    
    ---
     doc/integration/omniauth.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
    index f3e891fa457..820f40f81a9 100644
    --- a/doc/integration/omniauth.md
    +++ b/doc/integration/omniauth.md
    @@ -201,7 +201,7 @@ This setting was introduced with version 8.8 of GitLab.
     Administrators are able to enable or disable Sign In via some OmniAuth providers.
     
     >**Note:**
    -By default Sign In is enabled via all the OAuth Providers that have been configured in config/gitlab.yml.
    +By default Sign In is enabled via all the OAuth Providers that have been configured in `config/gitlab.yml`.
     
     In order to enable/disable an OmniAuth provider, go to Admin Area -> Settings -> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable.
     
    -- 
    cgit v1.2.1
    
    
    From c0c2cd4ed72cda88e182f3eafb472687d9d075f1 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 11 May 2016 19:55:24 +0300
    Subject: new screenshot for the docs on how to enabled/disable OmniAuth Sign
     In
    
    ---
     .../img/enabled-oauth-sign-in-sources.png           | Bin 49081 -> 92674 bytes
     1 file changed, 0 insertions(+), 0 deletions(-)
    
    diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png
    index 95f8bbdcd24..08155a4fade 100644
    Binary files a/doc/integration/img/enabled-oauth-sign-in-sources.png and b/doc/integration/img/enabled-oauth-sign-in-sources.png differ
    -- 
    cgit v1.2.1
    
    
    From 9e5042e40f657c8e8145cbce95ad424ccad6e6aa Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 11 May 2016 20:20:27 +0300
    Subject: Revert "disabled_oauth_sign_in_sources column" and keep on schema
     only the disabled_oauth_sign_in_sources column
    
    This reverts commit 95358e0095403ad44149d11922d52e4590285a20.
    ---
     db/schema.rb | 18 +++++++++---------
     1 file changed, 9 insertions(+), 9 deletions(-)
    
    diff --git a/db/schema.rb b/db/schema.rb
    index 74facd12088..b21cc162892 100644
    --- a/db/schema.rb
    +++ b/db/schema.rb
    @@ -70,16 +70,16 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.string   "recaptcha_site_key"
         t.string   "recaptcha_private_key"
         t.integer  "metrics_port",                      default: 8089
    -    t.boolean  "akismet_enabled",                   default: false
    -    t.string   "akismet_api_key"
         t.integer  "metrics_sample_interval",           default: 15
         t.boolean  "sentry_enabled",                    default: false
         t.string   "sentry_dsn"
    +    t.boolean  "akismet_enabled",                   default: false
    +    t.string   "akismet_api_key"
         t.boolean  "email_author_in_body",              default: false
         t.integer  "default_group_visibility"
         t.boolean  "repository_checks_enabled",         default: false
    -    t.text     "shared_runners_text"
         t.integer  "metrics_packet_size",               default: 1
    +    t.text     "shared_runners_text"
         t.text     "disabled_oauth_sign_in_sources"
       end
     
    @@ -427,10 +427,10 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.string   "state"
         t.integer  "iid"
         t.integer  "updated_by_id"
    +    t.integer  "moved_to_id"
         t.boolean  "confidential",  default: false
         t.datetime "deleted_at"
         t.date     "due_date"
    -    t.integer  "moved_to_id"
       end
     
       add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
    @@ -717,8 +717,8 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.integer "project_id"
         t.text    "data"
         t.text    "encrypted_credentials"
    -    t.string  "encrypted_credentials_iv"
    -    t.string  "encrypted_credentials_salt"
    +    t.text    "encrypted_credentials_iv"
    +    t.text    "encrypted_credentials_salt"
       end
     
       create_table "projects", force: :cascade do |t|
    @@ -816,9 +816,9 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.string   "type"
         t.string   "title"
         t.integer  "project_id"
    -    t.datetime "created_at"
    -    t.datetime "updated_at"
    -    t.boolean  "active",                default: false,    null: false
    +    t.datetime "created_at",                               null: false
    +    t.datetime "updated_at",                               null: false
    +    t.boolean  "active",                                   null: false
         t.text     "properties"
         t.boolean  "template",              default: false
         t.boolean  "push_events",           default: true
    -- 
    cgit v1.2.1
    
    
    From 8313476f5e1f1b51b3857ba065a65a707f5ca8af Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Wed, 11 May 2016 23:39:07 +0300
    Subject: no schema info for ApplicationSetting
    
    ---
     app/models/application_setting.rb | 49 ---------------------------------------
     1 file changed, 49 deletions(-)
    
    diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
    index 667b45335b5..c143cf215e6 100644
    --- a/app/models/application_setting.rb
    +++ b/app/models/application_setting.rb
    @@ -1,52 +1,3 @@
    -# == Schema Information
    -#
    -# Table name: application_settings
    -#
    -#  id                                :integer          not null, primary key
    -#  default_projects_limit            :integer
    -#  signup_enabled                    :boolean
    -#  signin_enabled                    :boolean
    -#  gravatar_enabled                  :boolean
    -#  sign_in_text                      :text
    -#  created_at                        :datetime
    -#  updated_at                        :datetime
    -#  home_page_url                     :string(255)
    -#  default_branch_protection         :integer          default(2)
    -#  restricted_visibility_levels      :text
    -#  version_check_enabled             :boolean          default(TRUE)
    -#  max_attachment_size               :integer          default(10), not null
    -#  default_project_visibility        :integer
    -#  default_snippet_visibility        :integer
    -#  default_group_visibility          :integer
    -#  restricted_signup_domains         :text
    -#  user_oauth_applications           :boolean          default(TRUE)
    -#  after_sign_out_path               :string(255)
    -#  session_expire_delay              :integer          default(10080), not null
    -#  import_sources                    :text
    -#  disabled_oauth_sign_in_sources    :text
    -#  help_page_text                    :text
    -#  admin_notification_email          :string(255)
    -#  shared_runners_enabled            :boolean          default(TRUE), not null
    -#  max_artifacts_size                :integer          default(100), not null
    -#  runners_registration_token        :string
    -#  require_two_factor_authentication :boolean          default(FALSE)
    -#  two_factor_grace_period           :integer          default(48)
    -#  metrics_enabled                   :boolean          default(FALSE)
    -#  metrics_host                      :string           default("localhost")
    -#  metrics_username                  :string
    -#  metrics_password                  :string
    -#  metrics_pool_size                 :integer          default(16)
    -#  metrics_timeout                   :integer          default(10)
    -#  metrics_method_call_threshold     :integer          default(10)
    -#  recaptcha_enabled                 :boolean          default(FALSE)
    -#  recaptcha_site_key                :string
    -#  recaptcha_private_key             :string
    -#  metrics_port                      :integer          default(8089)
    -#  sentry_enabled                    :boolean          default(FALSE)
    -#  sentry_dsn                        :string
    -#  email_author_in_body              :boolean          default(FALSE)
    -#
    -
     class ApplicationSetting < ActiveRecord::Base
       include TokenAuthenticatable
       add_authentication_token_field :runners_registration_token
    -- 
    cgit v1.2.1
    
    
    From b17cca1d9460a00510a2e9f04300f07cfb5eb95a Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Thu, 12 May 2016 09:37:15 +0300
    Subject: delete the enabled_oauth_sign_in_sources after getting it's value
     into enabled_oauth_sign_in_sources
    
    just delete enabled_oauth_sign_in_sources and get it's value
    ---
     app/controllers/admin/application_settings_controller.rb | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
    index c3005602366..b9eb7ae7921 100644
    --- a/app/controllers/admin/application_settings_controller.rb
    +++ b/app/controllers/admin/application_settings_controller.rb
    @@ -53,14 +53,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
           end
         end
     
    -    enabled_oauth_sign_in_sources = params[:application_setting][:enabled_oauth_sign_in_sources]
    +    enabled_oauth_sign_in_sources = params[:application_setting].delete(:enabled_oauth_sign_in_sources)
     
         params[:application_setting][:disabled_oauth_sign_in_sources] =
           AuthHelper.button_based_providers.map(&:to_s) -
           Array(enabled_oauth_sign_in_sources)
     
    -    params[:application_setting].delete(:enabled_oauth_sign_in_sources)
    -
         params.require(:application_setting).permit(
           :default_projects_limit,
           :default_branch_protection,
    -- 
    cgit v1.2.1
    
    
    From 5553ad24e4fe42670ba0f4e2010819abac499e7d Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Thu, 12 May 2016 13:37:44 +0300
    Subject: Revert "new screenshot for the docs on how to enabled/disable
     OmniAuth Sign In" [ci skip]
    
    This reverts commit 7b295370efc124360d52e37e8e709914028f6443.
    ---
     .../img/enabled-oauth-sign-in-sources.png           | Bin 92674 -> 49081 bytes
     1 file changed, 0 insertions(+), 0 deletions(-)
    
    diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png
    index 08155a4fade..95f8bbdcd24 100644
    Binary files a/doc/integration/img/enabled-oauth-sign-in-sources.png and b/doc/integration/img/enabled-oauth-sign-in-sources.png differ
    -- 
    cgit v1.2.1
    
    
    From 6cdce04937837de8014b1c044c91ed5b32bdc90a Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Thu, 12 May 2016 13:40:24 +0300
    Subject: Revert "Revert "no need to show the help about Github or the other
     authentication sources""
    
    This reverts commit 075ace5686c63d40f7e9fa02bf37e1bd3168f7e7.
    ---
     app/helpers/application_settings_helper.rb           | 9 +--------
     app/views/admin/application_settings/_form.html.haml | 3 ---
     2 files changed, 1 insertion(+), 11 deletions(-)
    
    diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
    index 82056a4c977..878b1b254ce 100644
    --- a/app/helpers/application_settings_helper.rb
    +++ b/app/helpers/application_settings_helper.rb
    @@ -71,15 +71,8 @@ module ApplicationSettingsHelper
           label_tag(checkbox_name, class: css_class) do
             check_box_tag(checkbox_name, source, !disabled,
                           autocomplete: 'off',
    -                      aria: { describedby: help_block_id }) + Gitlab::OAuth::Provider.label_for(source)
    +                      'aria-describedby' => help_block_id) + Gitlab::OAuth::Provider.label_for(source)
           end
         end
       end
    -
    -  def oauth_providers_with_help_links
    -    button_based_providers.map do |provider|
    -      Gitlab::OAuth::Provider.label_for(provider) + ' ' +
    -        link_to("(?)", help_page_path("integration", provider))
    -    end
    -  end
     end
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index f3681bc96e3..576509e3f2b 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -116,9 +116,6 @@
               .btn-group{ data: { toggle: 'buttons' } }
                 - oauth_providers_checkboxes('oauth-providers-help').each do |source|
                   = source
    -          %span.help-block#oauth-providers-help
    -            Enabled OmniAuth must be configured for
    -            = oauth_providers_with_help_links.to_sentence.html_safe
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
           .col-sm-10
    -- 
    cgit v1.2.1
    
    
    From 260c88a75865a1b849a4bac8a14c897fbe522047 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Thu, 12 May 2016 13:43:12 +0300
    Subject: no need to define the help block since there's no help block
    
    ---
     app/helpers/application_settings_helper.rb           | 5 ++---
     app/views/admin/application_settings/_form.html.haml | 2 +-
     2 files changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
    index 878b1b254ce..03080d25931 100644
    --- a/app/helpers/application_settings_helper.rb
    +++ b/app/helpers/application_settings_helper.rb
    @@ -61,7 +61,7 @@ module ApplicationSettingsHelper
         end
       end
     
    -  def oauth_providers_checkboxes(help_block_id)
    +  def oauth_providers_checkboxes
         button_based_providers.map do |source|
           disabled = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s)
           css_class = 'btn'
    @@ -70,8 +70,7 @@ module ApplicationSettingsHelper
     
           label_tag(checkbox_name, class: css_class) do
             check_box_tag(checkbox_name, source, !disabled,
    -                      autocomplete: 'off',
    -                      'aria-describedby' => help_block_id) + Gitlab::OAuth::Provider.label_for(source)
    +                      autocomplete: 'off') + Gitlab::OAuth::Provider.label_for(source)
           end
         end
       end
    diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
    index 576509e3f2b..f7c799c968f 100644
    --- a/app/views/admin/application_settings/_form.html.haml
    +++ b/app/views/admin/application_settings/_form.html.haml
    @@ -114,7 +114,7 @@
             = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth Sign-In sources', class: 'control-label col-sm-2'
             .col-sm-10
               .btn-group{ data: { toggle: 'buttons' } }
    -            - oauth_providers_checkboxes('oauth-providers-help').each do |source|
    +            - oauth_providers_checkboxes.each do |source|
                   = source
         .form-group
           = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
    -- 
    cgit v1.2.1
    
    
    From d66833bca5ae0347751ceab99062b638965eab78 Mon Sep 17 00:00:00 2001
    From: Andrei Gliga 
    Date: Thu, 12 May 2016 13:56:04 +0300
    Subject: =?UTF-8?q?schema=20fix=20=F0=9F=98=93?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     db/schema.rb | 18 +++++++++---------
     1 file changed, 9 insertions(+), 9 deletions(-)
    
    diff --git a/db/schema.rb b/db/schema.rb
    index b21cc162892..74facd12088 100644
    --- a/db/schema.rb
    +++ b/db/schema.rb
    @@ -70,16 +70,16 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.string   "recaptcha_site_key"
         t.string   "recaptcha_private_key"
         t.integer  "metrics_port",                      default: 8089
    +    t.boolean  "akismet_enabled",                   default: false
    +    t.string   "akismet_api_key"
         t.integer  "metrics_sample_interval",           default: 15
         t.boolean  "sentry_enabled",                    default: false
         t.string   "sentry_dsn"
    -    t.boolean  "akismet_enabled",                   default: false
    -    t.string   "akismet_api_key"
         t.boolean  "email_author_in_body",              default: false
         t.integer  "default_group_visibility"
         t.boolean  "repository_checks_enabled",         default: false
    -    t.integer  "metrics_packet_size",               default: 1
         t.text     "shared_runners_text"
    +    t.integer  "metrics_packet_size",               default: 1
         t.text     "disabled_oauth_sign_in_sources"
       end
     
    @@ -427,10 +427,10 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.string   "state"
         t.integer  "iid"
         t.integer  "updated_by_id"
    -    t.integer  "moved_to_id"
         t.boolean  "confidential",  default: false
         t.datetime "deleted_at"
         t.date     "due_date"
    +    t.integer  "moved_to_id"
       end
     
       add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
    @@ -717,8 +717,8 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.integer "project_id"
         t.text    "data"
         t.text    "encrypted_credentials"
    -    t.text    "encrypted_credentials_iv"
    -    t.text    "encrypted_credentials_salt"
    +    t.string  "encrypted_credentials_iv"
    +    t.string  "encrypted_credentials_salt"
       end
     
       create_table "projects", force: :cascade do |t|
    @@ -816,9 +816,9 @@ ActiveRecord::Schema.define(version: 20160508194200) do
         t.string   "type"
         t.string   "title"
         t.integer  "project_id"
    -    t.datetime "created_at",                               null: false
    -    t.datetime "updated_at",                               null: false
    -    t.boolean  "active",                                   null: false
    +    t.datetime "created_at"
    +    t.datetime "updated_at"
    +    t.boolean  "active",                default: false,    null: false
         t.text     "properties"
         t.boolean  "template",              default: false
         t.boolean  "push_events",           default: true
    -- 
    cgit v1.2.1
    
    
    From 945c5b3fe6e0552f77da8b1a1efe75cd04434f53 Mon Sep 17 00:00:00 2001
    From: Yorick Peterse 
    Date: Thu, 12 May 2016 15:14:14 +0200
    Subject: Removed tracking of total method execution times
    
    Because method call timings are inclusive (that is, they include the
    time of any sub method calls) this would lead to the total method
    execution time often being far greater than the total transaction time.
    Because this is incredibly confusing it's best to simply _not_ track the
    total method execution time, after all it's not that useful to begin
    with.
    
    Fixes gitlab-org/gitlab-ce#17239
    ---
     CHANGELOG                                       | 1 +
     lib/gitlab/metrics/instrumentation.rb           | 2 --
     spec/lib/gitlab/metrics/instrumentation_spec.rb | 6 ------
     3 files changed, 1 insertion(+), 8 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 187011c6016..985e25aab37 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -43,6 +43,7 @@ v 8.8.0 (unreleased)
       - 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
    +  - Total method execution timings are no longer tracked
     
     v 8.7.5
       - Fix relative links in wiki pages. !4050
    diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
    index 708ef79f304..0f115893a15 100644
    --- a/lib/gitlab/metrics/instrumentation.rb
    +++ b/lib/gitlab/metrics/instrumentation.rb
    @@ -154,8 +154,6 @@ module Gitlab
                   duration = (Time.now - start) * 1000.0
     
                   if duration >= Gitlab::Metrics.method_call_threshold
    -                trans.increment(:method_duration, duration)
    -
                     trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES,
                                      { duration: duration },
                                      method: #{label.inspect})
    diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb
    index 5c885a7a982..7b86450a223 100644
    --- a/spec/lib/gitlab/metrics/instrumentation_spec.rb
    +++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb
    @@ -56,9 +56,6 @@ describe Gitlab::Metrics::Instrumentation do
             allow(described_class).to receive(:transaction).
               and_return(transaction)
     
    -        expect(transaction).to receive(:increment).
    -          with(:method_duration, a_kind_of(Numeric))
    -
             expect(transaction).to receive(:add_metric).
               with(described_class::SERIES, an_instance_of(Hash),
                    method: 'Dummy.foo')
    @@ -139,9 +136,6 @@ describe Gitlab::Metrics::Instrumentation do
             allow(described_class).to receive(:transaction).
               and_return(transaction)
     
    -        expect(transaction).to receive(:increment).
    -          with(:method_duration, a_kind_of(Numeric))
    -
             expect(transaction).to receive(:add_metric).
               with(described_class::SERIES, an_instance_of(Hash),
                    method: 'Dummy#bar')
    -- 
    cgit v1.2.1
    
    
    From 5bd356eb31fb4684199f6f681f4901ebe025ed92 Mon Sep 17 00:00:00 2001
    From: Kamil Trzcinski 
    Date: Thu, 12 May 2016 09:27:58 -0500
    Subject: Fix specs
    
    ---
     app/models/ci/build.rb | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
    index 01236b8e3c7..4a3f92ad34a 100644
    --- a/app/models/ci/build.rb
    +++ b/app/models/ci/build.rb
    @@ -95,7 +95,7 @@ module Ci
         end
     
         def trace_html
    -      trace_with_state[:html]
    +      trace_with_state[:html] || ''
         end
     
         def trace_with_state(state = nil)
    -- 
    cgit v1.2.1
    
    
    From 827fbc10f6147c3c86278ed7f1675b085cc2a3cb Mon Sep 17 00:00:00 2001
    From: Sean McGivern 
    Date: Tue, 3 May 2016 13:58:50 +0100
    Subject: Only show forks for users who can download code
    
    The ForksController enforces this, so don't show the link if it won't go
    anywhere.
    ---
     CHANGELOG                      | 1 +
     app/helpers/projects_helper.rb | 4 ++--
     2 files changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 187011c6016..878453e861b 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -32,6 +32,7 @@ v 8.8.0 (unreleased)
       - Backport GitHub Enterprise import support from EE
       - Create tags using Rugged for performance reasons. !3745
       - API: Expose Issue#user_notes_count. !3126 (Anton Popov)
    +  - Don't show forks button when user can't view forks
       - 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
    diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
    index 85f8854d2eb..e1ab78df69e 100644
    --- a/app/helpers/projects_helper.rb
    +++ b/app/helpers/projects_helper.rb
    @@ -138,10 +138,10 @@ module ProjectsHelper
       private
     
       def get_project_nav_tabs(project, current_user)
    -    nav_tabs = [:home, :forks]
    +    nav_tabs = [:home]
     
         if !project.empty_repo? && can?(current_user, :download_code, project)
    -      nav_tabs << [:files, :commits, :network, :graphs]
    +      nav_tabs << [:files, :commits, :network, :graphs, :forks]
         end
     
         if project.repo_exists? && can?(current_user, :read_merge_request, project)
    -- 
    cgit v1.2.1
    
    
    From ad77ab0376fabf3dfadea86c716358964b526956 Mon Sep 17 00:00:00 2001
    From: DJ Mountney 
    Date: Thu, 12 May 2016 09:04:04 -0700
    Subject: Add Changelog entry
    
    and drop exception handling around HealthCheck::Utils.process_checks, it wasn't needed
    ---
     CHANGELOG                                        |  1 +
     app/controllers/admin/health_check_controller.rb |  6 +-----
     app/views/admin/health_check/show.html.haml      | 12 ++++++------
     3 files changed, 8 insertions(+), 11 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 7d5f424eaec..7ded902776c 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -12,6 +12,7 @@ v 8.8.0 (unreleased)
       - Reduce delay in destroying a project from 1-minute to immediately
       - Make build status canceled if any of the jobs was canceled and none failed
       - Upgrade Sidekiq to 4.1.2
    +  - Added /health_check endpoint for checking service status
       - Sanitize repo paths in new project error message
       - Bump mail_room to 0.7.0 to fix stuck IDLE connections
       - Remove future dates from contribution calendar graph.
    diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb
    index 3153a765e35..241c7be0ea1 100644
    --- a/app/controllers/admin/health_check_controller.rb
    +++ b/app/controllers/admin/health_check_controller.rb
    @@ -1,9 +1,5 @@
     class Admin::HealthCheckController < Admin::ApplicationController
       def show
    -    begin
    -      @errors = HealthCheck::Utils.process_checks('standard')
    -    rescue => e
    -      @errors = e.message.blank? ? e.class.to_s : e.message.to_s
    -    end
    +    @errors = HealthCheck::Utils.process_checks('standard')
       end
     end
    diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
    index ed7025f7a0b..ad79fd26d0b 100644
    --- a/app/views/admin/health_check/show.html.haml
    +++ b/app/views/admin/health_check/show.html.haml
    @@ -16,21 +16,21 @@
       Health information can be reteived as plain text, json, or xml using:
       %ul
         %li
    -      %code= health_check_url(token:current_application_settings.health_check_access_token)
    +      %code= health_check_url(token: current_application_settings.health_check_access_token)
         %li
    -      %code= health_check_url(token:current_application_settings.health_check_access_token, format: :json)
    +      %code= health_check_url(token: current_application_settings.health_check_access_token, format: :json)
         %li
    -      %code= health_check_url(token:current_application_settings.health_check_access_token, format: :xml)
    +      %code= health_check_url(token: current_application_settings.health_check_access_token, format: :xml)
     
     %p.light
       You can also ask for the status of specific services:
       %ul
         %li
    -      %code= health_check_url(token:current_application_settings.health_check_access_token, checks: :cache)
    +      %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :cache)
         %li
    -      %code= health_check_url(token:current_application_settings.health_check_access_token, checks: :database)
    +      %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :database)
         %li
    -      %code= health_check_url(token:current_application_settings.health_check_access_token, checks: :migrations)
    +      %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :migrations)
     
     %hr
     .panel.panel-default
    -- 
    cgit v1.2.1
    
    
    From 0641fe6f72a3d42f94062fd00b1cf8a0d643e6a4 Mon Sep 17 00:00:00 2001
    From: Yorick Peterse 
    Date: Thu, 12 May 2016 18:11:03 +0200
    Subject: Updated CHANGELOG for 8.7.5
    
    [ci skip]
    ---
     CHANGELOG | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 1d8712ae925..5dc5e057057 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -48,6 +48,8 @@ v 8.8.0 (unreleased)
     
     v 8.7.5
       - Fix relative links in wiki pages. !4050
    +  - Fix always showing build notification message when switching between merge requests !4086
    +  - Fix an issue when filtering merge requests with more than one label. !3886
     
     v 8.7.4
       - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss)
    -- 
    cgit v1.2.1
    
    
    From 18fdbf0a035b6feec3b576c01ee1a2f3a95e4305 Mon Sep 17 00:00:00 2001
    From: Takuya Noguchi 
    Date: Wed, 11 May 2016 23:46:19 +0900
    Subject: Fix a description for default scope on builds
    
    ---
     CHANGELOG                                 | 1 +
     app/views/admin/builds/index.html.haml    | 2 +-
     app/views/projects/builds/index.html.haml | 2 +-
     spec/features/admin/admin_builds_spec.rb  | 1 +
     spec/features/builds_spec.rb              | 1 +
     5 files changed, 5 insertions(+), 2 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 777b211daab..8d993e3013e 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -51,6 +51,7 @@ v 8.7.5
       - Fix relative links in wiki pages. !4050
       - Fix always showing build notification message when switching between merge requests !4086
       - Fix an issue when filtering merge requests with more than one label. !3886
    +  - Fix short note for the default scope on build page (Takuya Noguchi)
     
     v 8.7.4
       - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss)
    diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml
    index 804d7851bdb..ed24757087b 100644
    --- a/app/views/admin/builds/index.html.haml
    +++ b/app/views/admin/builds/index.html.haml
    @@ -20,7 +20,7 @@
           = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
     
     .row-content-block.second-block
    -  #{(@scope || 'running').capitalize} builds
    +  #{(@scope || 'all').capitalize} builds
     
     %ul.content-list
       - if @builds.blank?
    diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml
    index 2e8015d119b..98f4a9416e5 100644
    --- a/app/views/projects/builds/index.html.haml
    +++ b/app/views/projects/builds/index.html.haml
    @@ -36,7 +36,7 @@
             %span CI Lint
     
     .row-content-block
    -  #{(@scope || 'running').capitalize} builds from this project
    +  #{(@scope || 'all').capitalize} builds from this project
     
     %ul.content-list
       - if @builds.blank?
    diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb
    index 2e9851fb442..7bbe20fec43 100644
    --- a/spec/features/admin/admin_builds_spec.rb
    +++ b/spec/features/admin/admin_builds_spec.rb
    @@ -19,6 +19,7 @@ describe 'Admin Builds' do
               visit admin_builds_path
     
               expect(page).to have_selector('.nav-links li.active', text: 'All')
    +          expect(page).to have_selector('.row-content-block', text: 'All builds')
               expect(page.all('.build-link').size).to eq(4)
               expect(page).to have_link 'Cancel all'
             end
    diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb
    index 090a941958f..f83a78308e3 100644
    --- a/spec/features/builds_spec.rb
    +++ b/spec/features/builds_spec.rb
    @@ -43,6 +43,7 @@ describe "Builds" do
           end
     
           it { expect(page).to have_selector('.nav-links li.active', text: 'All') }
    +      it { expect(page).to have_selector('.row-content-block', text: 'All builds from this project') }
           it { expect(page).to have_content @build.short_sha }
           it { expect(page).to have_content @build.ref }
           it { expect(page).to have_content @build.name }
    -- 
    cgit v1.2.1
    
    
    From 0c22698bd4dbe7d0d3e4a6c8bc946ac6f5de1c12 Mon Sep 17 00:00:00 2001
    From: Ahmad Sherif 
    Date: Thu, 12 May 2016 22:48:09 +0200
    Subject: Add API endpoints for un/subscribing from/to a label
    
    Closes #15638
    ---
     CHANGELOG                                 |  1 +
     app/models/concerns/subscribable.rb       |  6 +++
     doc/api/labels.md                         | 70 ++++++++++++++++++++++++++
     lib/api/api.rb                            |  1 +
     lib/api/entities.rb                       |  4 ++
     lib/api/helpers.rb                        | 11 +++++
     lib/api/issues.rb                         | 39 +--------------
     lib/api/labels.rb                         |  6 +--
     lib/api/merge_requests.rb                 | 36 --------------
     lib/api/subscriptions.rb                  | 60 ++++++++++++++++++++++
     spec/models/concerns/subscribable_spec.rb | 10 ++++
     spec/requests/api/issues_spec.rb          | 12 +++++
     spec/requests/api/labels_spec.rb          | 82 +++++++++++++++++++++++++++++++
     13 files changed, 261 insertions(+), 77 deletions(-)
     create mode 100644 lib/api/subscriptions.rb
    
    diff --git a/CHANGELOG b/CHANGELOG
    index efb6dc6f610..aedd9f8ebdf 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -47,6 +47,7 @@ v 8.8.0 (unreleased)
       - 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
       - Total method execution timings are no longer tracked
       - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga)
    +  - Add API endpoints for un/subscribing from/to a label. !4051 (Ahmad Sherif)
     
     v 8.7.5
       - Fix relative links in wiki pages. !4050
    diff --git a/app/models/concerns/subscribable.rb b/app/models/concerns/subscribable.rb
    index d5a881b2445..083257f1005 100644
    --- a/app/models/concerns/subscribable.rb
    +++ b/app/models/concerns/subscribable.rb
    @@ -36,6 +36,12 @@ module Subscribable
           update(subscribed: !subscribed?(user))
       end
     
    +  def subscribe(user)
    +    subscriptions.
    +      find_or_initialize_by(user_id: user.id).
    +      update(subscribed: true)
    +  end
    +
       def unsubscribe(user)
         subscriptions.
           find_or_initialize_by(user_id: user.id).
    diff --git a/doc/api/labels.md b/doc/api/labels.md
    index 3730c07c5a7..b857d81768e 100644
    --- a/doc/api/labels.md
    +++ b/doc/api/labels.md
    @@ -165,3 +165,73 @@ Example response:
        "description": "Documentation"
     }
     ```
    +
    +## Subscribe to a label
    +
    +Subscribes the authenticated user to a label to receive notifications. If the
    +operation is successful, status code `201` together with the updated label is
    +returned. If the user is already subscribed to the label, the status code `304`
    +is returned. If the project or label is not found, status code `404` is
    +returned.
    +
    +```
    +POST /projects/:id/labels/:label_id/subscription
    +```
    +
    +| Attribute  | Type              | Required | Description                          |
    +| ---------- | ----------------- | -------- | ------------------------------------ |
    +| `id`       | integer           | yes      | The ID of a project                  |
    +| `label_id` | integer or string | yes      | The ID or title of a project's label |
    +
    +```bash
    +curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription
    +```
    +
    +Example response:
    +
    +```json
    +{
    +    "name": "Docs",
    +    "color": "#cc0033",
    +    "description": "",
    +    "open_issues_count": 0,
    +    "closed_issues_count": 0,
    +    "open_merge_requests_count": 0,
    +    "subscribed": true
    +}
    +```
    +
    +## Unsubscribe from a label
    +
    +Unsubscribes the authenticated user from a label to not receive notifications
    +from it. If the operation is successful, status code `200` together with the
    +updated label is returned. If the user is not subscribed to the label, the
    +status code `304` is returned. If the project or label is not found, status code
    +`404` is returned.
    +
    +```
    +DELETE /projects/:id/labels/:label_id/subscription
    +```
    +
    +| Attribute  | Type              | Required | Description                          |
    +| ---------- | ----------------- | -------- | ------------------------------------ |
    +| `id`       | integer           | yes      | The ID of a project                  |
    +| `label_id` | integer or string | yes      | The ID or title of a project's label |
    +
    +```bash
    +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription
    +```
    +
    +Example response:
    +
    +```json
    +{
    +    "name": "Docs",
    +    "color": "#cc0033",
    +    "description": "",
    +    "open_issues_count": 0,
    +    "closed_issues_count": 0,
    +    "open_merge_requests_count": 0,
    +    "subscribed": false
    +}
    +```
    diff --git a/lib/api/api.rb b/lib/api/api.rb
    index 5fd9c30cb42..360fb41a721 100644
    --- a/lib/api/api.rb
    +++ b/lib/api/api.rb
    @@ -57,5 +57,6 @@ module API
         mount ::API::Variables
         mount ::API::Runners
         mount ::API::Licenses
    +    mount ::API::Subscriptions
       end
     end
    diff --git a/lib/api/entities.rb b/lib/api/entities.rb
    index 2870a6a40ef..406f5ea9139 100644
    --- a/lib/api/entities.rb
    +++ b/lib/api/entities.rb
    @@ -307,6 +307,10 @@ module API
         class Label < Grape::Entity
           expose :name, :color, :description
           expose :open_issues_count, :closed_issues_count, :open_merge_requests_count
    +
    +      expose :subscribed do |label, options|
    +        label.subscribed?(options[:current_user])
    +      end
         end
     
         class Compare < Grape::Entity
    diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
    index 40c967453fb..5e638dbe16a 100644
    --- a/lib/api/helpers.rb
    +++ b/lib/api/helpers.rb
    @@ -95,6 +95,17 @@ module API
           end
         end
     
    +    def find_project_label(id)
    +      label = user_project.labels.find_by_id(id) || user_project.labels.find_by_title(id)
    +      label || not_found!('Label')
    +    end
    +
    +    def find_project_issue(id)
    +      issue = user_project.issues.find(id)
    +      not_found! unless can?(current_user, :read_issue, issue)
    +      issue
    +    end
    +
         def paginate(relation)
           relation.page(params[:page]).per(params[:per_page].to_i).tap do |data|
             add_pagination_headers(data)
    diff --git a/lib/api/issues.rb b/lib/api/issues.rb
    index 40928749481..f59a4d6c012 100644
    --- a/lib/api/issues.rb
    +++ b/lib/api/issues.rb
    @@ -103,8 +103,7 @@ module API
           # Example Request:
           #   GET /projects/:id/issues/:issue_id
           get ":id/issues/:issue_id" do
    -        @issue = user_project.issues.find(params[:issue_id])
    -        not_found! unless can?(current_user, :read_issue, @issue)
    +        @issue = find_project_issue(params[:issue_id])
             present @issue, with: Entities::Issue, current_user: current_user
           end
     
    @@ -234,42 +233,6 @@ module API
             authorize!(:destroy_issue, issue)
             issue.destroy
           end
    -
    -      # Subscribes to a project issue
    -      #
    -      # Parameters:
    -      #  id (required)       - The ID of a project
    -      #  issue_id (required) - The ID of a project issue
    -      # Example Request:
    -      #   POST /projects/:id/issues/:issue_id/subscription
    -      post ':id/issues/:issue_id/subscription' do
    -        issue = user_project.issues.find(params[:issue_id])
    -
    -        if issue.subscribed?(current_user)
    -          not_modified!
    -        else
    -          issue.toggle_subscription(current_user)
    -          present issue, with: Entities::Issue, current_user: current_user
    -        end
    -      end
    -
    -      # Unsubscribes from a project issue
    -      #
    -      # Parameters:
    -      #  id (required)       - The ID of a project
    -      #  issue_id (required) - The ID of a project issue
    -      # Example Request:
    -      #   DELETE /projects/:id/issues/:issue_id/subscription
    -      delete ':id/issues/:issue_id/subscription' do
    -        issue = user_project.issues.find(params[:issue_id])
    -
    -        if issue.subscribed?(current_user)
    -          issue.unsubscribe(current_user)
    -          present issue, with: Entities::Issue, current_user: current_user
    -        else
    -          not_modified!
    -        end
    -      end
         end
       end
     end
    diff --git a/lib/api/labels.rb b/lib/api/labels.rb
    index 4af6bef0fa7..c806829d69e 100644
    --- a/lib/api/labels.rb
    +++ b/lib/api/labels.rb
    @@ -11,7 +11,7 @@ module API
           # Example Request:
           #   GET /projects/:id/labels
           get ':id/labels' do
    -        present user_project.labels, with: Entities::Label
    +        present user_project.labels, with: Entities::Label, current_user: current_user
           end
     
           # Creates a new label
    @@ -36,7 +36,7 @@ module API
             label = user_project.labels.create(attrs)
     
             if label.valid?
    -          present label, with: Entities::Label
    +          present label, with: Entities::Label, current_user: current_user
             else
               render_validation_error!(label)
             end
    @@ -90,7 +90,7 @@ module API
             attrs[:name] = attrs.delete(:new_name) if attrs.key?(:new_name)
     
             if label.update(attrs)
    -          present label, with: Entities::Label
    +          present label, with: Entities::Label, current_user: current_user
             else
               render_validation_error!(label)
             end
    diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
    index 7e78609ecb9..4e7de8867b4 100644
    --- a/lib/api/merge_requests.rb
    +++ b/lib/api/merge_requests.rb
    @@ -327,42 +327,6 @@ module API
               issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user))
               present paginate(issues), with: Entities::Issue, current_user: current_user
             end
    -
    -        # Subscribes to a merge request
    -        #
    -        # Parameters:
    -        #  id (required)               - The ID of a project
    -        #  merge_request_id (required) - The ID of a merge request
    -        # Example Request:
    -        #   POST /projects/:id/issues/:merge_request_id/subscription
    -        post "#{path}/subscription" do
    -          merge_request = user_project.merge_requests.find(params[:merge_request_id])
    -
    -          if merge_request.subscribed?(current_user)
    -            not_modified!
    -          else
    -            merge_request.toggle_subscription(current_user)
    -            present merge_request, with: Entities::MergeRequest, current_user: current_user
    -          end
    -        end
    -
    -        # Unsubscribes from a merge request
    -        #
    -        # Parameters:
    -        #  id (required)               - The ID of a project
    -        #  merge_request_id (required) - The ID of a merge request
    -        # Example Request:
    -        #   DELETE /projects/:id/merge_requests/:merge_request_id/subscription
    -        delete "#{path}/subscription" do
    -          merge_request = user_project.merge_requests.find(params[:merge_request_id])
    -
    -          if merge_request.subscribed?(current_user)
    -            merge_request.unsubscribe(current_user)
    -            present merge_request, with: Entities::MergeRequest, current_user: current_user
    -          else
    -            not_modified!
    -          end
    -        end
           end
         end
       end
    diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
    new file mode 100644
    index 00000000000..c49e2a21b82
    --- /dev/null
    +++ b/lib/api/subscriptions.rb
    @@ -0,0 +1,60 @@
    +module API
    +  class Subscriptions < Grape::API
    +    before { authenticate! }
    +
    +    subscribable_types = {
    +      'merge_request' => proc { |id| user_project.merge_requests.find(id) },
    +      'merge_requests' => proc { |id| user_project.merge_requests.find(id) },
    +      'issues' => proc { |id| find_project_issue(id) },
    +      'labels' => proc { |id| find_project_label(id) },
    +    }
    +
    +    resource :projects do
    +      subscribable_types.each do |type, finder|
    +        type_singularized = type.singularize
    +        type_id_str = :"#{type_singularized}_id"
    +        entity_class = Entities.const_get(type_singularized.camelcase)
    +
    +        # Subscribe to a resource
    +        #
    +        # Parameters:
    +        #   id (required) - The ID of a project
    +        #   subscribable_id (required) - The ID of a resource
    +        # 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)
    +            not_modified!
    +          else
    +            resource.subscribe(current_user)
    +            present resource, with: entity_class, current_user: current_user
    +          end
    +        end
    +
    +        # Unsubscribe from a resource
    +        #
    +        # Parameters:
    +        #   id (required) - The ID of a project
    +        #   subscribable_id (required) - The ID of a resource
    +        # 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)
    +            not_modified!
    +          else
    +            resource.unsubscribe(current_user)
    +            present resource, with: entity_class, current_user: current_user
    +          end
    +        end
    +      end
    +    end
    +  end
    +end
    diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb
    index e31fdb0bffb..b7fc5a92497 100644
    --- a/spec/models/concerns/subscribable_spec.rb
    +++ b/spec/models/concerns/subscribable_spec.rb
    @@ -44,6 +44,16 @@ describe Subscribable, 'Subscribable' do
         end
       end
     
    +  describe '#subscribe' do
    +    it 'subscribes the given user' do
    +      expect(resource.subscribed?(user)).to be_falsey
    +
    +      resource.subscribe(user)
    +
    +      expect(resource.subscribed?(user)).to be_truthy
    +    end
    +  end
    +
       describe '#unsubscribe' do
         it 'unsubscribes the given current user' do
           resource.subscriptions.create(user: user, subscribed: true)
    diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
    index 9dd43f4fab3..37ab9cc8cfe 100644
    --- a/spec/requests/api/issues_spec.rb
    +++ b/spec/requests/api/issues_spec.rb
    @@ -623,6 +623,12 @@ describe API::API, api: true  do
     
           expect(response.status).to eq(404)
         end
    +
    +    it 'returns 404 if the issue is confidential' do
    +      post api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscription", non_member)
    +
    +      expect(response.status).to eq(404)
    +    end
       end
     
       describe 'DELETE :id/issues/:issue_id/subscription' do
    @@ -644,5 +650,11 @@ describe API::API, api: true  do
     
           expect(response.status).to eq(404)
         end
    +
    +    it 'returns 404 if the issue is confidential' do
    +      delete api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscription", non_member)
    +
    +      expect(response.status).to eq(404)
    +    end
       end
     end
    diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
    index 6943ff9d26c..b2c7f8d9acb 100644
    --- a/spec/requests/api/labels_spec.rb
    +++ b/spec/requests/api/labels_spec.rb
    @@ -190,4 +190,86 @@ describe API::API, api: true  do
           expect(json_response['message']['color']).to eq(['must be a valid color code'])
         end
       end
    +
    +  describe "POST /projects/:id/labels/:label_id/subscription" do
    +    context "when label_id is a label title" do
    +      it "should subscribe to the label" do
    +        post api("/projects/#{project.id}/labels/#{label1.title}/subscription", user)
    +
    +        expect(response.status).to eq(201)
    +        expect(json_response["name"]).to eq(label1.title)
    +        expect(json_response["subscribed"]).to be_truthy
    +      end
    +    end
    +
    +    context "when label_id is a label ID" do
    +      it "should subscribe to the label" do
    +        post api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
    +
    +        expect(response.status).to eq(201)
    +        expect(json_response["name"]).to eq(label1.title)
    +        expect(json_response["subscribed"]).to be_truthy
    +      end
    +    end
    +
    +    context "when user is already subscribed to label" do
    +      before { label1.subscribe(user) }
    +
    +      it "should return 304" do
    +        post api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
    +
    +        expect(response.status).to eq(304)
    +      end
    +    end
    +
    +    context "when label ID is not found" do
    +      it "should a return 404 error" do
    +        post api("/projects/#{project.id}/labels/1234/subscription", user)
    +
    +        expect(response.status).to eq(404)
    +      end
    +    end
    +  end
    +
    +  describe "DELETE /projects/:id/labels/:label_id/subscription" do
    +    before { label1.subscribe(user) }
    +
    +    context "when label_id is a label title" do
    +      it "should unsubscribe from the label" do
    +        delete api("/projects/#{project.id}/labels/#{label1.title}/subscription", user)
    +
    +        expect(response.status).to eq(200)
    +        expect(json_response["name"]).to eq(label1.title)
    +        expect(json_response["subscribed"]).to be_falsey
    +      end
    +    end
    +
    +    context "when label_id is a label ID" do
    +      it "should unsubscribe from the label" do
    +        delete api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
    +
    +        expect(response.status).to eq(200)
    +        expect(json_response["name"]).to eq(label1.title)
    +        expect(json_response["subscribed"]).to be_falsey
    +      end
    +    end
    +
    +    context "when user is already unsubscribed from label" do
    +      before { label1.unsubscribe(user) }
    +
    +      it "should return 304" do
    +        delete api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
    +
    +        expect(response.status).to eq(304)
    +      end
    +    end
    +
    +    context "when label ID is not found" do
    +      it "should a return 404 error" do
    +        delete api("/projects/#{project.id}/labels/1234/subscription", user)
    +
    +        expect(response.status).to eq(404)
    +      end
    +    end
    +  end
     end
    -- 
    cgit v1.2.1
    
    
    From e4d3e949555c51cf54ead163bf001b4ec86a2733 Mon Sep 17 00:00:00 2001
    From: Annabel Dunstone 
    Date: Thu, 12 May 2016 16:22:21 -0500
    Subject: Move broadcast msg into content-wrapper
    
    ---
     app/views/layouts/_page.html.haml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
    index 3c3bc41bf0e..3c0660d34f4 100644
    --- a/app/views/layouts/_page.html.haml
    +++ b/app/views/layouts/_page.html.haml
    @@ -1,5 +1,4 @@
     .page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" }
    -  = render "layouts/broadcast"
       .sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
         .header-logo
           %a#logo
    @@ -27,6 +26,7 @@
           .container-fluid
             = render "layouts/nav/#{nav}"
       .content-wrapper{ class: ('page-with-layout-nav' if defined?(nav) && nav) }
    +    = render "layouts/broadcast"
         = render "layouts/flash"
         = yield :flash_message
         %div{ class: (container_class unless @no_container) }
    -- 
    cgit v1.2.1
    
    
    From 05bbad5817c567b547177441769643042d699d8a Mon Sep 17 00:00:00 2001
    From: Robert Speicher 
    Date: Wed, 11 May 2016 15:17:16 -0500
    Subject: Clean up EventsHelper spec
    
    ---
     spec/helpers/events_helper_spec.rb | 95 +++++++++++++++++++-------------------
     1 file changed, 48 insertions(+), 47 deletions(-)
    
    diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
    index e68a5ec29ab..c0d2be98e85 100644
    --- a/spec/helpers/events_helper_spec.rb
    +++ b/spec/helpers/events_helper_spec.rb
    @@ -1,64 +1,65 @@
     require 'spec_helper'
     
     describe EventsHelper do
    -  include ApplicationHelper
    -  include GitlabMarkdownHelper
    +  describe '#event_note' do
    +    before do
    +      allow(helper).to receive(:current_user).and_return(double)
    +    end
     
    -  let(:current_user) { create(:user, email: "current@email.com") }
    +    it 'should display one line of plain text without alteration' do
    +      input = 'A short, plain note'
    +      expect(helper.event_note(input)).to match(input)
    +      expect(helper.event_note(input)).not_to match(/\.\.\.\z/)
    +    end
     
    -  it 'should display one line of plain text without alteration' do
    -    input = 'A short, plain note'
    -    expect(event_note(input)).to match(input)
    -    expect(event_note(input)).not_to match(/\.\.\.\z/)
    -  end
    +    it 'should display inline code' do
    +      input = 'A note with `inline code`'
    +      expected = 'A note with inline code'
     
    -  it 'should display inline code' do
    -    input = 'A note with `inline code`'
    -    expected = 'A note with inline code'
    +      expect(helper.event_note(input)).to match(expected)
    +    end
     
    -    expect(event_note(input)).to match(expected)
    -  end
    +    it 'should truncate a note with multiple paragraphs' do
    +      input = "Paragraph 1\n\nParagraph 2"
    +      expected = 'Paragraph 1...'
     
    -  it 'should truncate a note with multiple paragraphs' do
    -    input = "Paragraph 1\n\nParagraph 2"
    -    expected = 'Paragraph 1...'
    +      expect(helper.event_note(input)).to match(expected)
    +    end
     
    -    expect(event_note(input)).to match(expected)
    -  end
    +    it 'should display the first line of a code block' do
    +      input = "```\nCode block\nwith two lines\n```"
    +      expected = %r{Code block\.\.\.
    } - it 'should display the first line of a code block' do - input = "```\nCode block\nwith two lines\n```" - expected = %r{Code block\.\.\.
    } + expect(helper.event_note(input)).to match(expected) + end - expect(event_note(input)).to match(expected) - end + it 'should truncate a single long line of text' do + text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars + input = text * 4 + expected = (text * 2).sub(/.{3}/, '...') - it 'should truncate a single long line of text' do - text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars - input = "#{text}#{text}#{text}#{text}" # 200 chars - expected = "#{text}#{text}".sub(/.{3}/, '...') + expect(helper.event_note(input)).to match(expected) + end - expect(event_note(input)).to match(expected) - end - - it 'should preserve a link href when link text is truncated' do - text = 'The quick brown fox jumped over the lazy dog' # 44 chars - input = "#{text}#{text}#{text} " # 133 chars - link_url = 'http://example.com/foo/bar/baz' # 30 chars - input << link_url - expected_link_text = 'http://example...' + it 'should preserve a link href when link text is truncated' do + text = 'The quick brown fox jumped over the lazy dog' # 44 chars + input = "#{text}#{text}#{text} " # 133 chars + link_url = 'http://example.com/foo/bar/baz' # 30 chars + input << link_url + expected_link_text = 'http://example...' - expect(event_note(input)).to match(link_url) - expect(event_note(input)).to match(expected_link_text) - end + expect(helper.event_note(input)).to match(link_url) + expect(helper.event_note(input)).to match(expected_link_text) + end - it 'should preserve code color scheme' do - input = "```ruby\ndef test\n 'hello world'\nend\n```" - expected = '
    ' \
    -      "def test\n" \
    -      "  \'hello world\'\n" \
    -      "end" \
    -      '
    ' - expect(event_note(input)).to eq(expected) + it 'should preserve code color scheme' do + input = "```ruby\ndef test\n 'hello world'\nend\n```" + expected = '
    ' \
    +        "def test\n" \
    +        "  \'hello world\'\n" \
    +        "end" \
    +        '
    ' + expect(helper.event_note(input)).to eq(expected) + end end end -- cgit v1.2.1 From 7bc594735b7923d1e57eb504f09716bbb72c8c06 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Thu, 12 May 2016 17:06:47 -0500 Subject: Undo changes; reduce sidebar internal width --- app/assets/stylesheets/framework/sidebar.scss | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index c243dd8a424..f90d7a806d3 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -63,7 +63,7 @@ float: left; height: $header-height; width: 100%; - padding-left: 16px; + padding-left: 22px; overflow: hidden; outline: none; transition-duration: .3s; @@ -78,7 +78,7 @@ } .gitlab-text-container { - width: 220px; + width: 230px; h3 { width: 158px; @@ -146,12 +146,12 @@ a { padding: 7px 15px; - transition-duration: .3s; font-size: $gl-font-size; line-height: 24px; color: $gray; display: block; text-decoration: none; + padding-left: 23px; font-weight: normal; outline: none; @@ -253,11 +253,6 @@ width: auto; a { - @media (min-width: $screen-xs-min) { - padding-left: 23px; - transition-duration: .3s; - } - span { display: none; } @@ -317,7 +312,7 @@ } .nav-sidebar li a { - width: 220px; + width: $sidebar_width; &.back-link { i { -- cgit v1.2.1 From 4fea5cda0bf7ff56dafae90306441b0d65f3ca05 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Thu, 12 May 2016 17:11:37 -0500 Subject: Fix minor typos in admin health check page --- app/views/admin/health_check/show.html.haml | 2 +- spec/features/admin/admin_health_check_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml index ad79fd26d0b..c2313986a7f 100644 --- a/app/views/admin/health_check/show.html.haml +++ b/app/views/admin/health_check/show.html.haml @@ -13,7 +13,7 @@ = icon('refresh') Reset health check access token %p.light - Health information can be reteived as plain text, json, or xml using: + Health information can be retrieved as plain text, JSON, or XML using: %ul %li %code= health_check_url(token: current_application_settings.health_check_access_token) diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb index 4fde04b609b..dec2dedf2b5 100644 --- a/spec/features/admin/admin_health_check_spec.rb +++ b/spec/features/admin/admin_health_check_spec.rb @@ -13,7 +13,7 @@ feature "Admin Health Check", feature: true do end it { page.has_text? 'Health Check' } - it { page.has_text? 'Health information can be reteived' } + it { page.has_text? 'Health information can be retrieved' } it 'has a health check access token' do token = current_application_settings.health_check_access_token -- cgit v1.2.1 From 311fb58c44fe6dd14709c8eb8f9346ec73e03aff Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Tue, 10 May 2016 23:24:23 -0300 Subject: Require space around operators --- .rubocop.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 3fb2f2df592..562197300b4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -276,7 +276,7 @@ Style/IdenticalConditionalBranches: Enabled: false # Checks the indentation of the first line of the right-hand-side of a -# multi-line assignment. +# multi-line assignment. Style/IndentAssignment: Enabled: false @@ -531,7 +531,7 @@ Style/SpaceAroundKeyword: # Use a single space around operators. Style/SpaceAroundOperators: - Enabled: false + Enabled: true # Checks that the left block brace has or doesn't have space before it. Style/SpaceBeforeBlockBraces: -- cgit v1.2.1 From f5a0ac0fc197bae2eb5fe1045ed237cdbbaf6ea4 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Tue, 10 May 2016 23:58:06 -0300 Subject: Codestyle: make sure we have space around operators --- app/controllers/application_controller.rb | 2 +- app/controllers/concerns/creates_commit.rb | 2 +- app/helpers/search_helper.rb | 2 +- app/helpers/selects_helper.rb | 2 +- app/models/project_services/external_wiki_service.rb | 2 +- app/models/project_wiki.rb | 2 +- app/models/repository.rb | 4 ++-- app/services/merge_requests/build_service.rb | 2 +- app/services/system_hooks_service.rb | 2 +- config/environments/test.rb | 2 +- config/initializers/1_settings.rb | 18 +++++++++--------- config/initializers/carrierwave.rb | 2 +- config/initializers/devise.rb | 2 +- config/routes.rb | 2 +- features/steps/dashboard/issues.rb | 2 +- features/steps/dashboard/merge_requests.rb | 2 +- features/steps/profile/profile.rb | 2 +- features/steps/project/team_management.rb | 2 +- lib/api/helpers.rb | 2 +- lib/gitlab/email/reply_parser.rb | 2 +- lib/gitlab/redis.rb | 6 +++--- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 4 ++-- .../gitlab/ci/build/artifacts/metadata/entry_spec.rb | 4 ++-- spec/lib/gitlab/lfs/lfs_router_spec.rb | 4 ++-- spec/models/commit_spec.rb | 2 +- spec/models/hooks/service_hook_spec.rb | 4 ++-- spec/models/hooks/system_hook_spec.rb | 20 ++++++++++---------- .../slack_service/note_message_spec.rb | 4 ++-- spec/requests/api/builds_spec.rb | 4 ++-- spec/requests/api/group_members_spec.rb | 10 +++++----- spec/requests/ci/api/builds_spec.rb | 4 ++-- spec/support/jira_service_helper.rb | 10 +++++----- spec/support/stub_gitlab_calls.rb | 20 ++++++++++---------- 33 files changed, 77 insertions(+), 77 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 17b3f49aed1..1429ee40bb7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -176,7 +176,7 @@ class ApplicationController < ActionController::Base end def check_password_expiration - if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? + if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? redirect_to new_profile_password_path and return end end diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index 787416c17ab..dacb5679dd3 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -122,7 +122,7 @@ module CreatesCommit # Merge request from fork to this project @mr_source_project = @tree_edit_project @mr_target_project = @project - @mr_target_branch ||= @ref + @mr_target_branch ||= @ref end end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 24c4c098c65..d2f94d4ae6f 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -59,7 +59,7 @@ module SearchHelper # Autocomplete results for the current project, if it's defined def project_autocomplete if @project && @project.repository.exists? && @project.repository.root_ref - ref = @ref || @project.repository.root_ref + ref = @ref || @project.repository.root_ref [ { category: "Current Project", label: "Files", url: namespace_project_tree_path(@project.namespace, @project, ref) }, diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb index e951a87a212..bb395e37884 100644 --- a/app/helpers/selects_helper.rb +++ b/app/helpers/selects_helper.rb @@ -18,7 +18,7 @@ module SelectsHelper first_user: first_user, current_user: opts[:current_user] || false, "push-code-to-protected-branches" => opts[:push_code_to_protected_branches], - author_id: opts[:author_id] || '' + author_id: opts[:author_id] || '' } } diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index f042bfc5210..d7b6e505191 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -25,7 +25,7 @@ class ExternalWikiService < Service def execute(_data) @response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil - if @response !=200 + if @response != 200 nil end end diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 7c1a61bb0bf..060ed9b44ec 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -113,7 +113,7 @@ class ProjectWiki end def page_title_and_dir(title) - title_array = title.split("/") + title_array = title.split("/") title = title_array.pop [title, title_array.join("/")] end diff --git a/app/models/repository.rb b/app/models/repository.rb index de7e163078d..0eff74320f3 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -795,7 +795,7 @@ class Repository def check_revert_content(commit, base_branch) source_sha = find_branch(base_branch).target args = [commit.id, source_sha] - args << { mainline: 1 } if commit.merge_commit? + args << { mainline: 1 } if commit.merge_commit? revert_index = rugged.revert_commit(*args) return false if revert_index.conflicts? @@ -809,7 +809,7 @@ class Repository def check_cherry_pick_content(commit, base_branch) source_sha = find_branch(base_branch).target args = [commit.id, source_sha] - args << 1 if commit.merge_commit? + args << 1 if commit.merge_commit? cherry_pick_index = rugged.cherrypick_commit(*args) return false if cherry_pick_index.conflicts? diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index cd4230aa5e4..1b48899bb0a 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -66,7 +66,7 @@ module MergeRequests commits = merge_request.compare_commits if commits && commits.count == 1 commit = commits.first - merge_request.title = commit.title + merge_request.title = commit.title merge_request.description ||= commit.description.try(:strip) elsif iid && (issue = merge_request.target_project.get_issue(iid)) && !issue.try(:confidential?) case issue diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index e43b5b51e5b..1fb72cf89e9 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -85,7 +85,7 @@ class SystemHooksService path_with_namespace: model.path_with_namespace, project_id: model.id, owner_name: owner.name, - owner_email: owner.respond_to?(:email) ? owner.email : "", + owner_email: owner.respond_to?(:email) ? owner.email : "", project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase } end diff --git a/config/environments/test.rb b/config/environments/test.rb index a703c0934f7..fb25d3a8b14 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -20,7 +20,7 @@ Rails.application.configure do config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment - config.action_controller.allow_forgery_protection = false + config.action_controller.allow_forgery_protection = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 23c8cea038a..a69b933d811 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -126,7 +126,7 @@ end Settings['omniauth'] ||= Settingslogic.new({}) -Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? +Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil? Settings.omniauth['allow_single_sign_on'] = false if Settings.omniauth['allow_single_sign_on'].nil? Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_providers'].nil? @@ -134,7 +134,7 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? Settings.omniauth['auto_link_saml_user'] = false if Settings.omniauth['auto_link_saml_user'].nil? -Settings.omniauth['providers'] ||= [] +Settings.omniauth['providers'] ||= [] Settings.omniauth['cas3'] ||= Settingslogic.new({}) Settings.omniauth.cas3['session_duration'] ||= 8.hours Settings.omniauth['session_tickets'] ||= Settingslogic.new({}) @@ -168,7 +168,7 @@ end Settings['shared'] ||= Settingslogic.new({}) Settings.shared['path'] = File.expand_path(Settings.shared['path'] || "shared", Rails.root) -Settings['issues_tracker'] ||= {} +Settings['issues_tracker'] ||= {} # # GitLab @@ -183,7 +183,7 @@ Settings.gitlab['ssh_host'] ||= Settings.gitlab.host Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80 Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' -Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" +Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil? Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}" Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab' @@ -196,7 +196,7 @@ Settings.gitlab['user_home'] ||= begin rescue ArgumentError # no user configured '/home/' + Settings.gitlab['user'] end -Settings.gitlab['time_zone'] ||= nil +Settings.gitlab['time_zone'] ||= nil Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) @@ -211,7 +211,7 @@ Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.g Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil? Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil? Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil? -Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) +Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive') if Settings.gitlab['repository_downloads_path'].nil? Settings.gitlab['restricted_signup_domains'] ||= [] Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'] @@ -225,8 +225,8 @@ Settings['gitlab_ci'] ||= Settingslogic.new({}) Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['shared_runners_enabled'].nil? Settings.gitlab_ci['all_broken_builds'] = true if Settings.gitlab_ci['all_broken_builds'].nil? Settings.gitlab_ci['add_pusher'] = false if Settings.gitlab_ci['add_pusher'].nil? -Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url) Settings.gitlab_ci['builds_path'] = File.expand_path(Settings.gitlab_ci['builds_path'] || "builds/", Rails.root) +Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url) # # Reply by email @@ -240,7 +240,7 @@ Settings.incoming_email['enabled'] = false if Settings.incoming_email['enabled'] Settings['artifacts'] ||= Settingslogic.new({}) Settings.artifacts['enabled'] = true if Settings.artifacts['enabled'].nil? Settings.artifacts['path'] = File.expand_path(Settings.artifacts['path'] || File.join(Settings.shared['path'], "artifacts"), Rails.root) -Settings.artifacts['max_size'] ||= 100 # in megabytes +Settings.artifacts['max_size'] ||= 100 # in megabytes # # Git LFS @@ -298,7 +298,7 @@ Settings['backup'] ||= Settingslogic.new({}) Settings.backup['keep_time'] ||= 0 Settings.backup['pg_schema'] = nil Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) -Settings.backup['archive_permissions'] ||= 0600 +Settings.backup['archive_permissions'] ||= 0600 Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil }) # Convert upload connection settings to use symbol keys, to make Fog happy if Settings.backup['upload']['connection'] diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index 0d278717d6e..1933afcbfb1 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -20,7 +20,7 @@ if File.exist?(aws_file) config.fog_public = false # optional, defaults to {} - config.fog_attributes = { 'Cache-Control'=>'max-age=315576000' } + config.fog_attributes = { 'Cache-Control' => 'max-age=315576000' } # optional time (in seconds) that authenticated urls will be valid. # when fog_public is false and provider is AWS or Google, defaults to 600 diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 31dceaebcad..021bdb11251 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -243,7 +243,7 @@ Devise.setup do |config| when Hash # Add procs for handling SLO if provider['name'] == 'cas3' - provider['args'][:on_single_sign_out] = lambda do |request| + provider['args'][:on_single_sign_out] = lambda do |request| ticket = request.params[:session_index] raise "Service Ticket not found." unless Gitlab::OAuth::Session.valid?(:cas3, ticket) Gitlab::OAuth::Session.destroy(:cas3, ticket) diff --git a/config/routes.rb b/config/routes.rb index ec876eba345..0c01c529210 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -83,7 +83,7 @@ Rails.application.routes.draw do get 'help' => 'help#index' get 'help/:category/:file' => 'help#show', as: :help_page, constraints: { category: /.*/, file: /[^\/\.]+/ } get 'help/shortcuts' - get 'help/ui' => 'help#ui' + get 'help/ui' => 'help#ui' # # Global snippets diff --git a/features/steps/dashboard/issues.rb b/features/steps/dashboard/issues.rb index e21af72a777..8706f0e8e78 100644 --- a/features/steps/dashboard/issues.rb +++ b/features/steps/dashboard/issues.rb @@ -74,7 +74,7 @@ class Spinach::Features::DashboardIssues < Spinach::FeatureSteps def project @project ||= begin - project =create :project + project = create :project project.team << [current_user, :master] project end diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb index a2adc87f8ef..06db36c7014 100644 --- a/features/steps/dashboard/merge_requests.rb +++ b/features/steps/dashboard/merge_requests.rb @@ -100,7 +100,7 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps def project @project ||= begin - project =create :project + project = create :project project.team << [current_user, :master] project end diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb index 909de31a479..b1a87b96efd 100644 --- a/features/steps/profile/profile.rb +++ b/features/steps/profile/profile.rb @@ -166,7 +166,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps end step 'I have group with projects' do - @group = create(:group) + @group = create(:group) @group.add_owner(current_user) @project = create(:project, namespace: @group) @event = create(:closed_issue_event, project: @project) diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb index 3fbcf770b62..c6ced747370 100644 --- a/features/steps/project/team_management.rb +++ b/features/steps/project/team_management.rb @@ -126,7 +126,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps step 'I share project with group "OpenSource"' do project = Project.find_by(name: 'Shop') - os_group = create(:group, name: 'OpenSource') + os_group = create(:group, name: 'OpenSource') create(:project, group: os_group) @os_user1 = create(:user) @os_user2 = create(:user) diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 5e638dbe16a..cadf9f98fe3 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -2,7 +2,7 @@ module API module Helpers PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" PRIVATE_TOKEN_PARAM = :private_token - SUDO_HEADER ="HTTP_SUDO" + SUDO_HEADER = "HTTP_SUDO" SUDO_PARAM = :sudo def parse_boolean(value) diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb index 6ed36b51f12..3411eb1d9ce 100644 --- a/lib/gitlab/email/reply_parser.rb +++ b/lib/gitlab/email/reply_parser.rb @@ -65,7 +65,7 @@ module Gitlab (l =~ /On \w+ \d+,? \d+,?.*wrote:/) # Headers on subsequent lines - break if (0..2).all? { |off| lines[idx+off] =~ REPLYING_HEADER_REGEX } + break if (0..2).all? { |off| lines[idx + off] =~ REPLYING_HEADER_REGEX } # Headers on the same line break if REPLYING_HEADER_LABELS.count { |label| l.include?(label) } >= 3 diff --git a/lib/gitlab/redis.rb b/lib/gitlab/redis.rb index f7db7a6391c..40766f35f77 100644 --- a/lib/gitlab/redis.rb +++ b/lib/gitlab/redis.rb @@ -25,7 +25,7 @@ module Gitlab end @pool.with { |redis| yield redis } end - + def self.redis_store_options url = new.url redis_config_hash = ::Redis::Store::Factory.extract_host_options_from_uri(url) @@ -40,10 +40,10 @@ module Gitlab def initialize(rails_env=nil) rails_env ||= Rails.env config_file = File.expand_path('../../../config/resque.yml', __FILE__) - + @url = "redis://localhost:6379" if File.exist?(config_file) - @url =YAML.load_file(config_file)[rails_env] + @url = YAML.load_file(config_file)[rails_env] end end end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index c7ab3185378..9eef8ea0976 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -443,12 +443,12 @@ module Ci context 'when job variables are defined' do context 'when syntax is correct' do it 'returns job variables' do - variables = { + variables = { KEY1: 'value1', SOME_KEY_2: 'value2' } - config = YAML.dump( + config = YAML.dump( { before_script: ['pwd'], rspec: { variables: variables, diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb index acca0b08bab..46a5b7fce65 100644 --- a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb +++ b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb @@ -10,8 +10,8 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do 'path/dir_1/subdir/subfile' => { size: 10 }, 'path/second_dir' => {}, 'path/second_dir/dir_3/file_2' => { size: 10 }, - 'path/second_dir/dir_3/file_3'=> { size: 10 }, - 'another_directory/'=> {}, + 'path/second_dir/dir_3/file_3' => { size: 10 }, + 'another_directory/' => {}, 'another_file' => {}, '/file/with/absolute_path' => {} } end diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb index 5852b31ab3a..3325190789b 100644 --- a/spec/lib/gitlab/lfs/lfs_router_spec.rb +++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb @@ -26,8 +26,8 @@ describe Gitlab::Lfs::Router, lib: true do let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" } let(:sample_size) { 499013 } - let(:respond_with_deprecated) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} - let(:respond_with_disabled) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} + let(:respond_with_deprecated) {[ 501, { "Content-Type" => "application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} + let(:respond_with_disabled) {[ 501, { "Content-Type" => "application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} describe 'when lfs is disabled' do before do diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index ad47e338a33..ccb100cd96f 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -56,7 +56,7 @@ describe Commit, models: true do end it "does not truncates a message with a newline after 80 but less 100 characters" do - message =<'application/json', 'X-Gitlab-Event'=>'Service Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Service Hook' } ).once end it "POSTs the data as JSON" do @service_hook.execute(@data) expect(WebMock).to have_requested(:post, @service_hook.url).with( - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'Service Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Service Hook' } ).once end diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index 56a9fbe9720..4078b9e4ff5 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -33,7 +33,7 @@ describe SystemHook, models: true do Projects::CreateService.new(user, name: 'empty').execute expect(WebMock).to have_requested(:post, system_hook.url).with( body: /project_create/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -42,7 +42,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /project_destroy/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -51,7 +51,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_create/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -60,7 +60,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_destroy/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -69,7 +69,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_add_to_team/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -79,7 +79,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_remove_from_team/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -88,7 +88,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /group_create/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -97,7 +97,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /group_destroy/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -106,7 +106,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_add_to_group/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end @@ -116,7 +116,7 @@ describe SystemHook, models: true do expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_remove_from_group/, - headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'System Hook' } + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end end diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb index d37590cab75..379c3e1219c 100644 --- a/spec/models/project_services/slack_service/note_message_spec.rb +++ b/spec/models/project_services/slack_service/note_message_spec.rb @@ -65,7 +65,7 @@ describe SlackService::NoteMessage, models: true do expect(message.pretext).to eq("Test User commented on " \ " in : " \ "*merge request title*") - expected_attachments = [ + expected_attachments = [ { text: "comment on a merge request", color: color, @@ -117,7 +117,7 @@ describe SlackService::NoteMessage, models: true do expect(message.pretext).to eq("Test User commented on " \ " in : " \ "*snippet title*") - expected_attachments = [ + expected_attachments = [ { text: "comment on a snippet", color: color, diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 5ead735be48..0fbc984c061 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -106,8 +106,8 @@ describe API::API, api: true do context 'authorized user' do let(:download_headers) do - { 'Content-Transfer-Encoding'=>'binary', - 'Content-Disposition'=>'attachment; filename=ci_build_artifacts.zip' } + { 'Content-Transfer-Encoding' => 'binary', + 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' } end it 'should return specific build artifacts' do diff --git a/spec/requests/api/group_members_spec.rb b/spec/requests/api/group_members_spec.rb index 96d89e69209..02553d0f8e2 100644 --- a/spec/requests/api/group_members_spec.rb +++ b/spec/requests/api/group_members_spec.rb @@ -34,11 +34,11 @@ describe API::API, api: true do expect(response.status).to eq(200) expect(json_response).to be_an Array expect(json_response.size).to eq(5) - expect(json_response.find { |e| e['id']==owner.id }['access_level']).to eq(GroupMember::OWNER) - expect(json_response.find { |e| e['id']==reporter.id }['access_level']).to eq(GroupMember::REPORTER) - expect(json_response.find { |e| e['id']==developer.id }['access_level']).to eq(GroupMember::DEVELOPER) - expect(json_response.find { |e| e['id']==master.id }['access_level']).to eq(GroupMember::MASTER) - expect(json_response.find { |e| e['id']==guest.id }['access_level']).to eq(GroupMember::GUEST) + expect(json_response.find { |e| e['id'] == owner.id }['access_level']).to eq(GroupMember::OWNER) + expect(json_response.find { |e| e['id'] == reporter.id }['access_level']).to eq(GroupMember::REPORTER) + expect(json_response.find { |e| e['id'] == developer.id }['access_level']).to eq(GroupMember::DEVELOPER) + expect(json_response.find { |e| e['id'] == master.id }['access_level']).to eq(GroupMember::MASTER) + expect(json_response.find { |e| e['id'] == guest.id }['access_level']).to eq(GroupMember::GUEST) end end diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index dfd361a2cdd..cae4656010f 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -402,8 +402,8 @@ describe Ci::API::API do context 'build has artifacts' do let(:build) { create(:ci_build, :artifacts) } let(:download_headers) do - { 'Content-Transfer-Encoding'=>'binary', - 'Content-Disposition'=>'attachment; filename=ci_build_artifacts.zip' } + { 'Content-Transfer-Encoding' => 'binary', + 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' } end it 'should download artifact' do diff --git a/spec/support/jira_service_helper.rb b/spec/support/jira_service_helper.rb index a3f496359b1..5ebe095743b 100644 --- a/spec/support/jira_service_helper.rb +++ b/spec/support/jira_service_helper.rb @@ -2,11 +2,11 @@ module JiraServiceHelper def jira_service_settings properties = { - "title"=>"JIRA tracker", - "project_url"=>"http://jira.example/issues/?jql=project=A", - "issues_url"=>"http://jira.example/browse/JIRA-1", - "new_issue_url"=>"http://jira.example/secure/CreateIssue.jspa", - "api_url"=>"http://jira.example/rest/api/2" + "title" => "JIRA tracker", + "project_url" => "http://jira.example/issues/?jql=project=A", + "issues_url" => "http://jira.example/browse/JIRA-1", + "new_issue_url" => "http://jira.example/secure/CreateIssue.jspa", + "api_url" => "http://jira.example/rest/api/2" } jira_tracker.update_attributes(properties: properties, active: true) diff --git a/spec/support/stub_gitlab_calls.rb b/spec/support/stub_gitlab_calls.rb index eec2e681117..b5ca34bc028 100644 --- a/spec/support/stub_gitlab_calls.rb +++ b/spec/support/stub_gitlab_calls.rb @@ -36,20 +36,20 @@ module StubGitlabCalls stub_request(:post, "#{gitlab_url}api/v3/session.json"). with(body: "{\"email\":\"test@test.com\",\"password\":\"123456\"}", - headers: { 'Content-Type'=>'application/json' }). - to_return(status: 201, body: f, headers: { 'Content-Type'=>'application/json' }) + headers: { 'Content-Type' => 'application/json' }). + to_return(status: 201, body: f, headers: { 'Content-Type' => 'application/json' }) end def stub_user f = File.read(Rails.root.join('spec/support/gitlab_stubs/user.json')) stub_request(:get, "#{gitlab_url}api/v3/user?private_token=Wvjy2Krpb7y8xi93owUz"). - with(headers: { 'Content-Type'=>'application/json' }). - to_return(status: 200, body: f, headers: { 'Content-Type'=>'application/json' }) + with(headers: { 'Content-Type' => 'application/json' }). + to_return(status: 200, body: f, headers: { 'Content-Type' => 'application/json' }) stub_request(:get, "#{gitlab_url}api/v3/user?access_token=some_token"). - with(headers: { 'Content-Type'=>'application/json' }). - to_return(status: 200, body: f, headers: { 'Content-Type'=>'application/json' }) + with(headers: { 'Content-Type' => 'application/json' }). + to_return(status: 200, body: f, headers: { 'Content-Type' => 'application/json' }) end def stub_project_8 @@ -66,19 +66,19 @@ module StubGitlabCalls f = File.read(Rails.root.join('spec/support/gitlab_stubs/projects.json')) stub_request(:get, "#{gitlab_url}api/v3/projects.json?archived=false&ci_enabled_first=true&private_token=Wvjy2Krpb7y8xi93owUz"). - with(headers: { 'Content-Type'=>'application/json' }). - to_return(status: 200, body: f, headers: { 'Content-Type'=>'application/json' }) + with(headers: { 'Content-Type' => 'application/json' }). + to_return(status: 200, body: f, headers: { 'Content-Type' => 'application/json' }) end def stub_projects_owned stub_request(:get, "#{gitlab_url}api/v3/projects/owned.json?archived=false&ci_enabled_first=true&private_token=Wvjy2Krpb7y8xi93owUz"). - with(headers: { 'Content-Type'=>'application/json' }). + with(headers: { 'Content-Type' => 'application/json' }). to_return(status: 200, body: "", headers: {}) end def stub_ci_enable stub_request(:put, "#{gitlab_url}api/v3/projects/2/services/gitlab-ci.json?private_token=Wvjy2Krpb7y8xi93owUz"). - with(headers: { 'Content-Type'=>'application/json' }). + with(headers: { 'Content-Type' => 'application/json' }). to_return(status: 200, body: "", headers: {}) end -- cgit v1.2.1 From 8d58e691c69f623878522c4f0dccf9f24229e9ce Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Fri, 13 May 2016 04:51:13 -0300 Subject: remove extra space to fix codestyle --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 0c01c529210..9e776a1f541 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,7 +74,7 @@ Rails.application.routes.draw do end # Health check - get 'health_check(/:checks)' => 'health_check#index', as: :health_check + get 'health_check(/:checks)' => 'health_check#index', as: :health_check # Enable Grack support mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post, :put] -- cgit v1.2.1 From ae89161db5d6294948990b1d87f4fa306f2a1be9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 May 2016 09:25:38 -0500 Subject: Remove background color differentiation from gitlab logo/text in sidebar Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/gitlab-theme.scss | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index dc4668877f2..51a17d1469e 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -9,9 +9,6 @@ @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { .page-with-sidebar { .header-logo { - background-color: $color; - border-color: $color; - a { color: $color-light; @@ -21,7 +18,7 @@ } &:hover { - background-color: $color-darker; + background-color: $color-dark; a { color: #fff; -- cgit v1.2.1 From 6da24056030ccf45ec39f2f3b6addc6f0ffe1d1f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 May 2016 10:05:52 -0500 Subject: Add UI changes in 8.8 to changelog Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 588a4b4eef6..30d4955c9f3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -49,6 +49,8 @@ v 8.8.0 (unreleased) - Total method execution timings are no longer tracked - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga) - Add API endpoints for un/subscribing from/to a label. !4051 (Ahmad Sherif) + - Hide left sidebar on phone screens to give more space for content + - Redesign navigation for profile and group pages v 8.7.5 - Fix relative links in wiki pages. !4050 -- cgit v1.2.1 From 16b1d3a34f665776bbdfca041326b9c2d569e59b Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Fri, 13 May 2016 11:12:49 -0500 Subject: Fix mobile dropdown bug --- app/assets/stylesheets/framework/nav.scss | 19 +++++++++++++++++++ app/helpers/nav_helper.rb | 8 ++++++++ app/views/layouts/_page.html.haml | 2 +- app/views/layouts/nav/_group_settings.html.haml | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index f2d7dc625e0..a81fcb1c6b3 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -209,6 +209,15 @@ float: right; padding: 7px 0 0; + @media (max-width: $screen-xs-min) { + float: none; + padding: 0 9px; + + .dropdown-new { + width: 100%; + } + } + i { color: $layout-link-gray; } @@ -225,6 +234,10 @@ .dropdown { margin-left: 7px; + + @media (max-width: $screen-xs-min) { + margin-left: 0; + } } } @@ -260,4 +273,10 @@ .page-with-layout-nav { margin-top: 50px; + + &.controls-dropdown-visible { + @media (max-width: $screen-xs-min) { + margin-top: 96px; + } + } } diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 3aa41030453..fbb799eecd3 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -43,4 +43,12 @@ module NavHelper class_name += " with-horizontal-nav" if defined?(nav) && nav class_name end + + def layout_nav_class + "page-with-layout-nav" if defined?(nav) && nav + end + + def layout_dropdown_class + "controls-dropdown-visible" if current_user + end end diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 3c0660d34f4..5be0b546a62 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -25,7 +25,7 @@ .layout-nav .container-fluid = render "layouts/nav/#{nav}" - .content-wrapper{ class: ('page-with-layout-nav' if defined?(nav) && nav) } + .content-wrapper{ class: "#{layout_nav_class} #{layout_dropdown_class}" } = render "layouts/broadcast" = render "layouts/flash" = yield :flash_message diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml index e391ec7f2b7..0b2673f1a82 100644 --- a/app/views/layouts/nav/_group_settings.html.haml +++ b/app/views/layouts/nav/_group_settings.html.haml @@ -1,7 +1,7 @@ - if current_user - if access = @group.users.find_by(id: current_user.id) .controls - %span.dropdown.group-settings-dropdown + .dropdown.group-settings-dropdown %a.dropdown-new.btn.btn-default#group-settings-button{href: '#', 'data-toggle' => 'dropdown'} = icon('cog') = icon('caret-down') -- cgit v1.2.1 From 2148566b3dce96f36bbf86555ef0d68758044429 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 May 2016 11:21:31 -0500 Subject: Fix issue sidebar top position after header height change Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/header.scss | 4 ++-- app/assets/stylesheets/pages/issuable.scss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 8190a97ed58..0da96c4017d 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -6,12 +6,12 @@ header { transition-duration: .3s; &.navbar-empty { - height: 58px; + height: $header-height; background: #fff; border-bottom: 1px solid $btn-gray-hover; .center-logo { - margin: 11px 0; + margin: 8px 0; text-align: center; #tanuki-logo, img { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 1cf3023ecc9..d06086a581b 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -125,7 +125,7 @@ .right-sidebar { position: fixed; - top: 58px; + top: $header-height; bottom: 0; right: 0; z-index: 10; -- cgit v1.2.1 From 9a7a0415535da7541095de363dee37b9f09fe702 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 May 2016 11:24:00 -0500 Subject: Fix login btn vertical align Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/common.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 3386523dbf7..f8aecd0558d 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -289,7 +289,7 @@ table { text-shadow: none; @media (min-width: $screen-sm-min) { - margin-top: 11px; + margin-top: 8px; } } -- cgit v1.2.1 From 935c684ad3427069431a1130d364a4481af6cb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 13 May 2016 18:39:32 +0200 Subject: Revert "Merge branch 'doc-fix-db-gem-install-instructions' into 'master' " This reverts commit 66d8ef1ad9d5952b7e7f026658f71aafc861950e, reversing changes made to 6a8359f3d3be01af6f5b124b61af7ee1c77c17d0. The `--with` option was added in Bundler 1.10 but in this case it shouldn't even be needed: I've tested the original command locally and the pg gem was installed, so I believe the user that opened the original MR ran the wrong command (i.e. `sudo -u git -H bundle install --without development test postgres --deployment` instead of `sudo -u git -H bundle install --without development test mysql --deployment`. See discussion at https://gitlab.com/gitlab-org/gitlab-ce/commit/66d8ef1ad9d5952b7e7f026658f71aafc861950e for more context. --- doc/update/patch_versions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index b4283a526f3..60729316cde 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -57,10 +57,10 @@ sudo -u git -H make cd /home/git/gitlab # PostgreSQL -sudo -u git -H bundle install --without development test mysql --with postgres --deployment +sudo -u git -H bundle install --without development test mysql --deployment # MySQL -sudo -u git -H bundle install --without development test postgres --with mysql --deployment +sudo -u git -H bundle install --without development test postgres --deployment # Optional: clean up old gems sudo -u git -H bundle clean -- cgit v1.2.1