Commit 46ad82aa authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

Merge remote-tracking branch 'upstream/8-5-stable' into 8-5-nxd

parents 827d3914 46bb47ac
...@@ -12,6 +12,25 @@ v 8.6.0 (unreleased) ...@@ -12,6 +12,25 @@ v 8.6.0 (unreleased)
- Allow search for logged out users - Allow search for logged out users
- Don't show Issues/MRs from archived projects in Groups view - Don't show Issues/MRs from archived projects in Groups view
- Increase the notes polling timeout over time (Roberto Dip) - Increase the notes polling timeout over time (Roberto Dip)
- Add shortcut to toggle markdown preview (Florent Baldino)
- Show labels in dashboard and group milestone views
- Add main language of a project in the list of projects (Tiago Botelho)
- Add ability to show archived projects on dashboard, explore and group pages
v 8.5.8
- Bump Git version requirement to 2.7.4
v 8.5.7
- Bump Git version requirement to 2.7.3
v 8.5.6
- Obtain a lease before querying LDAP
v 8.5.5
- Ensure removing a project removes associated Todo entries
- Prevent a 500 error in Todos when author was removed
- Fix pagination for filtered dashboard and explore pages
- Fix "Show all" link behavior
v 8.5.4 v 8.5.4
- Do not cache requests for badges (including builds badge) - Do not cache requests for badges (including builds badge)
......
...@@ -68,7 +68,7 @@ GitLab is a Ruby on Rails application that runs on the following software: ...@@ -68,7 +68,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL - Ubuntu/Debian/CentOS/RHEL
- Ruby (MRI) 2.1 - Ruby (MRI) 2.1
- Git 1.7.10+ - Git 2.7.4+
- Redis 2.8+ - Redis 2.8+
- MySQL or PostgreSQL - MySQL or PostgreSQL
......
8.5.3 8.5.8
\ No newline at end of file \ No newline at end of file
...@@ -2,20 +2,26 @@ class @ProjectsList ...@@ -2,20 +2,26 @@ class @ProjectsList
constructor: -> constructor: ->
$(".projects-list .js-expand").on 'click', (e) -> $(".projects-list .js-expand").on 'click', (e) ->
e.preventDefault() e.preventDefault()
list = $(this).closest('.projects-list') $projectsList = $(this).closest('.projects-list')
ProjectsList.showPagination($projectsList)
$projectsList.find('li.bottom').hide()
$("#filter_projects").on 'keyup', -> $("#filter_projects").on 'keyup', ->
ProjectsList.filter_results($("#filter_projects")) ProjectsList.filter_results($("#filter_projects"))
@showPagination: ($projectsList) ->
$projectsList.find('li').show()
$('.gl-pagination').show()
@filter_results: ($element) -> @filter_results: ($element) ->
terms = $element.val() terms = $element.val()
filterSelector = $element.data('filter-selector') || 'span.filter-title' filterSelector = $element.data('filter-selector') || 'span.filter-title'
$projectsList = $('.projects-list')
if not terms if not terms
$(".projects-list li").show() ProjectsList.showPagination($projectsList)
$('.gl-pagination').show()
else else
$(".projects-list li").each (index) -> $projectsList.find('li').each (index) ->
$this = $(this) $this = $(this)
name = $this.find(filterSelector).text() name = $this.find(filterSelector).text()
......
...@@ -246,6 +246,8 @@ class ApplicationController < ActionController::Base ...@@ -246,6 +246,8 @@ class ApplicationController < ActionController::Base
def ldap_security_check def ldap_security_check
if current_user && current_user.requires_ldap_check? if current_user && current_user.requires_ldap_check?
return unless current_user.try_obtain_ldap_lease
unless Gitlab::LDAP::Access.allowed?(current_user) unless Gitlab::LDAP::Access.allowed?(current_user)
sign_out current_user sign_out current_user
flash[:alert] = "Access denied for your LDAP account." flash[:alert] = "Access denied for your LDAP account."
......
...@@ -12,7 +12,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -12,7 +12,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = @projects.search(terms) @projects = @projects.search(terms)
end end
@projects = @projects.page(params[:page]).per(PER_PAGE) if terms.blank? @projects = @projects.page(params[:page]).per(PER_PAGE)
@last_push = current_user.recent_push @last_push = current_user.recent_push
respond_to do |format| respond_to do |format|
...@@ -41,7 +41,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -41,7 +41,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = @projects.search(terms) @projects = @projects.search(terms)
end end
@projects = @projects.page(params[:page]).per(PER_PAGE) if terms.blank? @projects = @projects.page(params[:page]).per(PER_PAGE)
@last_push = current_user.recent_push @last_push = current_user.recent_push
@groups = [] @groups = []
......
...@@ -8,7 +8,7 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -8,7 +8,7 @@ class Explore::ProjectsController < Explore::ApplicationController
@projects = @projects.search(params[:search]) if params[:search].present? @projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present? @projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE)
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -24,7 +24,7 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -24,7 +24,7 @@ class Explore::ProjectsController < Explore::ApplicationController
@projects = TrendingProjectsFinder.new.execute(current_user) @projects = TrendingProjectsFinder.new.execute(current_user)
@projects = @projects.non_archived @projects = @projects.non_archived
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present? @projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.page(params[:page]).per(PER_PAGE)
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -40,7 +40,7 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -40,7 +40,7 @@ class Explore::ProjectsController < Explore::ApplicationController
@projects = ProjectsFinder.new.execute(current_user) @projects = ProjectsFinder.new.execute(current_user)
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present? @projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.reorder('star_count DESC') @projects = @projects.reorder('star_count DESC')
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.page(params[:page]).per(PER_PAGE)
respond_to do |format| respond_to do |format|
format.html format.html
......
...@@ -72,7 +72,7 @@ module ApplicationHelper ...@@ -72,7 +72,7 @@ module ApplicationHelper
if user_or_email.is_a?(User) if user_or_email.is_a?(User)
user = user_or_email user = user_or_email
else else
user = User.find_by(email: user_or_email.downcase) user = User.find_by(email: user_or_email.try(:downcase))
end end
if user if user
......
...@@ -151,6 +151,7 @@ class Project < ActiveRecord::Base ...@@ -151,6 +151,7 @@ class Project < ActiveRecord::Base
has_many :releases, dependent: :destroy has_many :releases, dependent: :destroy
has_many :lfs_objects_projects, dependent: :destroy has_many :lfs_objects_projects, dependent: :destroy
has_many :lfs_objects, through: :lfs_objects_projects has_many :lfs_objects, through: :lfs_objects_projects
has_many :todos, dependent: :destroy
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
......
...@@ -603,6 +603,13 @@ class User < ActiveRecord::Base ...@@ -603,6 +603,13 @@ class User < ActiveRecord::Base
end end
end end
def try_obtain_ldap_lease
# After obtaining this lease LDAP checks will be blocked for 600 seconds
# (10 minutes) for this user.
lease = Gitlab::ExclusiveLease.new("user_ldap_check:#{id}", timeout: 600)
lease.try_obtain
end
def solo_owned_groups def solo_owned_groups
@solo_owned_groups ||= owned_groups.select do |group| @solo_owned_groups ||= owned_groups.select do |group|
group.owners == [self] group.owners == [self]
......
...@@ -3,9 +3,12 @@ ...@@ -3,9 +3,12 @@
= image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:'' = image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:''
.todo-title .todo-title
%span.author_name %span.author-name
= link_to_author todo - if todo.author
%span.todo_label = link_to_author(todo)
- else
(removed)
%span.todo-label
= todo_action_name(todo) = todo_action_name(todo)
= todo_target_link(todo) = todo_target_link(todo)
......
- user = member.user - user = member.user
- return unless user || member.invite? - return unless user || member.invite?
- show_roles = local_assigns.fetch(:show_roles, true)
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)} %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
%span{class: ("list-item-name" if show_controls)} %span{class: ("list-item-name" if show_controls)}
...@@ -28,7 +29,7 @@ ...@@ -28,7 +29,7 @@
= link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do = link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do
Resend invite Resend invite
- if should_user_see_group_roles?(current_user, @group) - if show_roles && should_user_see_group_roles?(current_user, @group)
%span.pull-right %span.pull-right
%strong.member-access-level= member.human_access %strong.member-access-level= member.human_access
- if show_controls - if show_controls
......
# This is a quick hack to get ExclusiveLease working in GitLab 8.5
module Gitlab
REDIS_URL = begin
redis_config_file = Rails.root.join('config/resque.yml')
if File.exists?(redis_config_file)
YAML.load_file(redis_config_file)[Rails.env]
else
'redis://localhost:6379'
end
end
end
class FixTodos < ActiveRecord::Migration
def up
execute <<-SQL
DELETE FROM todos
WHERE todos.target_type IN ('Commit', 'ProjectSnippet')
OR NOT EXISTS (
SELECT *
FROM projects
WHERE projects.id = todos.project_id
)
SQL
end
def down
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160222153918) do ActiveRecord::Schema.define(version: 20160309140734) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
......
...@@ -76,7 +76,7 @@ Make sure you have the right version of Git installed ...@@ -76,7 +76,7 @@ Make sure you have the right version of Git installed
# Install Git # Install Git
sudo apt-get install -y git-core sudo apt-get install -y git-core
# Make sure Git is version 1.7.10 or higher, for example 1.7.12 or 2.0.0 # Make sure Git is version 2.7.4 or higher
git --version git --version
Is the system packaged Git too old? Remove it and compile from source. Is the system packaged Git too old? Remove it and compile from source.
...@@ -89,8 +89,9 @@ Is the system packaged Git too old? Remove it and compile from source. ...@@ -89,8 +89,9 @@ Is the system packaged Git too old? Remove it and compile from source.
# Download and compile from source # Download and compile from source
cd /tmp cd /tmp
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.4.3.tar.gz | tar xz curl -O --progress https://www.kernel.org/pub/software/scm/git/git-2.7.4.tar.gz
cd git-2.4.3/ echo '7104c4f5d948a75b499a954524cb281fe30c6649d8abe20982936f75ec1f275b git-2.7.4.tar.gz' | shasum -a256 -c - && tar -xzf git-2.7.4.tar.gz
cd git-2.7.4/
./configure ./configure
make prefix=/usr/local all make prefix=/usr/local all
...@@ -143,7 +144,7 @@ use 64-bit Linux. You can find downloads for other platforms at the [Go download ...@@ -143,7 +144,7 @@ use 64-bit Linux. You can find downloads for other platforms at the [Go download
page](https://golang.org/dl). page](https://golang.org/dl).
curl -O --progress https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz curl -O --progress https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz
echo '43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53 go1.5.3.linux-amd64.tar.gz' | shasum -c - && \ echo '43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53 go1.5.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.5.3.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.5.3.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
rm go1.5.3.linux-amd64.tar.gz rm go1.5.3.linux-amd64.tar.gz
......
module Gitlab
# This class implements an 'exclusive lease'. We call it a 'lease'
# because it has a set expiry time. We call it 'exclusive' because only
# one caller may obtain a lease for a given key at a time. The
# implementation is intended to work across GitLab processes and across
# servers. It is a 'cheap' alternative to using SQL queries and updates:
# you do not need to change the SQL schema to start using
# ExclusiveLease.
#
# It is important to choose the timeout wisely. If the timeout is very
# high (1 hour) then the throughput of your operation gets very low (at
# most once an hour). If the timeout is lower than how long your
# operation may take then you cannot count on exclusivity. For example,
# if the timeout is 10 seconds and you do an operation which may take 20
# seconds then two overlapping operations may hold a lease for the same
# key at the same time.
#
class ExclusiveLease
def initialize(key, timeout:)
@key, @timeout = key, timeout
end
# Try to obtain the lease. Return true on success,
# false if the lease is already taken.
def try_obtain
# Performing a single SET is atomic
!!redis.set(redis_key, '1', nx: true, ex: @timeout)
end
private
def redis
# Maybe someday we want to use a connection pool...
@redis ||= Redis.new(url: Gitlab::REDIS_URL)
end
def redis_key
"gitlab:exclusive_lease:#{@key}"
end
end
end
...@@ -3,7 +3,7 @@ module Gitlab ...@@ -3,7 +3,7 @@ module Gitlab
def self.allowed?(user) def self.allowed?(user)
return false if user.blocked? return false if user.blocked?
if user.requires_ldap_check? if user.requires_ldap_check? && user.try_obtain_ldap_lease
return false unless Gitlab::LDAP::Access.allowed?(user) return false unless Gitlab::LDAP::Access.allowed?(user)
end end
......
...@@ -928,7 +928,7 @@ namespace :gitlab do ...@@ -928,7 +928,7 @@ namespace :gitlab do
end end
def check_git_version def check_git_version
required_version = Gitlab::VersionInfo.new(1, 7, 10) required_version = Gitlab::VersionInfo.new(2, 7, 3)
current_version = Gitlab::VersionInfo.parse(run(%W(#{Gitlab.config.git.bin_path} --version))) current_version = Gitlab::VersionInfo.parse(run(%W(#{Gitlab.config.git.bin_path} --version)))
puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
......
require 'spec_helper'
describe Gitlab::ExclusiveLease do
it 'cannot obtain twice before the lease has expired' do
lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600)
expect(lease.try_obtain).to eq(true)
expect(lease.try_obtain).to eq(false)
end
it 'can obtain after the lease has expired' do
timeout = 1
lease = Gitlab::ExclusiveLease.new(unique_key, timeout: timeout)
lease.try_obtain # start the lease
sleep(2 * timeout) # lease should have expired now
expect(lease.try_obtain).to eq(true)
end
def unique_key
SecureRandom.hex(10)
end
end
...@@ -68,6 +68,7 @@ describe Project, models: true do ...@@ -68,6 +68,7 @@ describe Project, models: true do
it { is_expected.to have_many(:runners) } it { is_expected.to have_many(:runners) }
it { is_expected.to have_many(:variables) } it { is_expected.to have_many(:variables) }
it { is_expected.to have_many(:triggers) } it { is_expected.to have_many(:triggers) }
it { is_expected.to have_many(:todos).dependent(:destroy) }
end end
describe 'modules' do describe 'modules' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment