summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG7
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.coffee7
-rw-r--r--app/assets/stylesheets/framework/mobile.scss4
-rw-r--r--app/assets/stylesheets/pages/groups.scss13
-rw-r--r--app/assets/stylesheets/pages/projects.scss12
-rw-r--r--app/controllers/admin/runner_projects_controller.rb2
-rw-r--r--app/controllers/admin/system_info_controller.rb49
-rw-r--r--app/controllers/projects/runner_projects_controller.rb3
-rw-r--r--app/controllers/projects_controller.rb7
-rw-r--r--app/models/ability.rb14
-rw-r--r--app/views/admin/runners/_runner.html.haml2
-rw-r--r--app/views/admin/runners/index.html.haml3
-rw-r--r--app/views/groups/show.html.haml9
-rw-r--r--app/views/layouts/_init_auto_complete.html.haml1
-rw-r--r--app/views/projects/_home_panel.html.haml2
-rw-r--r--app/views/shared/members/_access_request_buttons.html.haml4
-rw-r--r--config/initializers/metrics.rb3
-rw-r--r--doc/workflow/add-user/img/access_requests_management.pngbin15105 -> 15686 bytes
-rw-r--r--doc/workflow/groups.md2
-rw-r--r--doc/workflow/groups/access_requests_management.pngbin15193 -> 15829 bytes
-rw-r--r--doc/workflow/groups/request_access_button.pngbin30470 -> 49067 bytes
-rw-r--r--doc/workflow/groups/withdraw_access_request_button.pngbin31681 -> 49941 bytes
-rw-r--r--lib/api/branches.rb8
-rw-r--r--lib/api/tags.rb6
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb9
-rw-r--r--spec/features/admin/admin_runners_spec.rb42
26 files changed, 147 insertions, 62 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 4b754c2aba3..c71e54a9148 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,13 +22,20 @@ v 8.10.0 (unreleased)
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- PipelinesFinder uses git cache data
- Check for conflicts with existing Project's wiki path when creating a new project.
+ - Don't instantiate a git tree on Projects show default view
- Remove unused front-end variable -> default_issues_tracker
- Better caching of git calls on ProjectsController#show.
- Add API endpoint for a group issues !4520 (mahcsig)
- Add Bugzilla integration !4930 (iamtjg)
+ - Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
- Add basic system information like memory and disk usage to the admin panel
+v 8.9.5 (unreleased)
+ - Improve the request / withdraw access button. !4860
+ - Fix assigning shared runners as admins. !4961
+ - Show "locked" label for locked runners on runners admin. !4961
+
v 8.9.4
- Fix privilege escalation issue with OAuth external users.
- Ensure references to private repos aren't shown to logged-out users.
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee
index 190bb38504c..b7d040bae85 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.coffee
+++ b/app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -4,7 +4,7 @@ window.GitLab ?= {}
GitLab.GfmAutoComplete =
dataLoading: false
dataLoaded: false
-
+ cachedData: {}
dataSource: ''
# Emoji
@@ -55,7 +55,7 @@ GitLab.GfmAutoComplete =
@setupAtWho()
if @dataSource
- if !@dataLoading
+ if not @dataLoading and not @cachedData
@dataLoading = true
# We should wait until initializations are done
@@ -70,6 +70,8 @@ GitLab.GfmAutoComplete =
@loadData(data)
, 1000)
+ if @cachedData?
+ @loadData(@cachedData)
setupAtWho: ->
# Emoji
@@ -205,6 +207,7 @@ GitLab.GfmAutoComplete =
$.getJSON(dataSource)
loadData: (data) ->
+ @cachedData = data
@dataLoaded = true
# load members
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index c74682dfef4..367c7d01944 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -71,6 +71,10 @@
display: none;
}
+ .group-right-buttons {
+ display: none;
+ }
+
.container .title {
padding-left: 15px !important;
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index 101faf59174..3d79f4400e2 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -41,14 +41,17 @@
}
.groups-cover-block {
-
.container-fluid {
position: relative;
}
- .access-request-button {
- @include btn-gray;
- margin-right: 10px;
- text-transform: none;
+ .group-right-buttons {
+ position: absolute;
+ right: 16px;
+ .btn {
+ @include btn-gray;
+ padding: 3px 10px;
+ background-color: $background-color;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 89ce1b2df20..817c2982923 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -266,18 +266,6 @@
@media (max-width: $screen-md-max) {
top: 0;
}
-
- .access-request-button {
- position: absolute;
- right: 0;
- bottom: 61px;
-
- @media (max-width: $screen-md-max) {
- position: relative;
- bottom: 0;
- margin-right: 10px;
- }
- }
}
@media (max-width: $screen-md-max) {
diff --git a/app/controllers/admin/runner_projects_controller.rb b/app/controllers/admin/runner_projects_controller.rb
index bf20c5305a7..bc65dcc33d3 100644
--- a/app/controllers/admin/runner_projects_controller.rb
+++ b/app/controllers/admin/runner_projects_controller.rb
@@ -4,8 +4,6 @@ class Admin::RunnerProjectsController < Admin::ApplicationController
def create
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
- return head(403) if @runner.is_shared? || @runner.locked?
-
runner_project = @runner.assign_to(@project, current_user)
if runner_project.persisted?
diff --git a/app/controllers/admin/system_info_controller.rb b/app/controllers/admin/system_info_controller.rb
index cc63009cdc0..e4c73008826 100644
--- a/app/controllers/admin/system_info_controller.rb
+++ b/app/controllers/admin/system_info_controller.rb
@@ -1,27 +1,54 @@
class Admin::SystemInfoController < Admin::ApplicationController
- def show
- excluded_mounts = [
- "nobrowse",
- "read-only",
- "ro"
- ]
+ EXCLUDED_MOUNT_OPTIONS = [
+ 'nobrowse',
+ 'read-only',
+ 'ro'
+ ]
+
+ EXCLUDED_MOUNT_TYPES = [
+ 'autofs',
+ 'binfmt_misc',
+ 'cgroup',
+ 'debugfs',
+ 'devfs',
+ 'devpts',
+ 'devtmpfs',
+ 'efivarfs',
+ 'fuse.gvfsd-fuse',
+ 'fuseblk',
+ 'fusectl',
+ 'hugetlbfs',
+ 'mqueue',
+ 'proc',
+ 'pstore',
+ 'securityfs',
+ 'sysfs',
+ 'tmpfs',
+ 'tracefs',
+ 'vfat'
+ ]
+ def show
system_info = Vmstat.snapshot
mounts = Sys::Filesystem.mounts
@disks = []
mounts.each do |mount|
- options = mount.options.split(', ')
+ mount_options = mount.options.split(',')
- next unless excluded_mounts.each { |em| break if options.include?(em) }
+ next if (EXCLUDED_MOUNT_OPTIONS & mount_options).any?
+ next if (EXCLUDED_MOUNT_TYPES & [mount.mount_type]).any?
- disk = Sys::Filesystem.stat(mount.mount_point)
- @disks.push({
+ begin
+ disk = Sys::Filesystem.stat(mount.mount_point)
+ @disks.push({
bytes_total: disk.bytes_total,
bytes_used: disk.bytes_used,
disk_name: mount.name,
mount_path: disk.path
- })
+ })
+ rescue Sys::Filesystem::Error
+ end
end
@cpus = system_info.cpus.length
diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb
index dc1a18f8d42..8267b14941d 100644
--- a/app/controllers/projects/runner_projects_controller.rb
+++ b/app/controllers/projects/runner_projects_controller.rb
@@ -6,8 +6,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
def create
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
- return head(403) if @runner.is_shared? || @runner.locked?
- return head(403) unless current_user.ci_authorized_runners.include?(@runner)
+ return head(403) unless can?(current_user, :assign_runner, @runner)
path = runners_path(project)
runner_project = @runner.assign_to(project, current_user)
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 2b1f50fd01e..12e0d5a8413 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -4,7 +4,8 @@ class ProjectsController < Projects::ApplicationController
before_action :authenticate_user!, except: [:show, :activity, :refs]
before_action :project, except: [:new, :create]
before_action :repository, except: [:new, :create]
- before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists?
+ before_action :assign_ref_vars, only: [:show], if: :repo_exists?
+ before_action :tree, only: [:show], if: :project_view_files?
# Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
@@ -303,6 +304,10 @@ class ProjectsController < Projects::ApplicationController
project.repository_exists? && !project.empty_repo?
end
+ def project_view_files?
+ current_user && current_user.project_view == 'files'
+ end
+
# Override extract_ref from ExtractsPath, which returns the branch and file path
# for the blob/tree, which in this case is just the root of the default branch.
# This way we avoid to access the repository.ref_names.
diff --git a/app/models/ability.rb b/app/models/ability.rb
index f5950879ccb..ba1f2ae4075 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,5 +1,6 @@
class Ability
class << self
+ # rubocop: disable Metrics/CyclomaticComplexity
def allowed(user, subject)
return anonymous_abilities(user, subject) if user.nil?
return [] unless user.is_a?(User)
@@ -19,6 +20,7 @@ class Ability
when ProjectMember then project_member_abilities(user, subject)
when User then user_abilities
when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project)
+ when Ci::Runner then runner_abilities(user, subject)
else []
end.concat(global_abilities(user))
end
@@ -512,6 +514,18 @@ class Ability
rules
end
+ def runner_abilities(user, runner)
+ if user.is_admin?
+ [:assign_runner]
+ elsif runner.is_shared? || runner.locked?
+ []
+ elsif user.ci_authorized_runners.include?(runner)
+ [:assign_runner]
+ else
+ []
+ end
+ end
+
def user_abilities
[:read_user]
end
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index 36b21eefdee..64893b38c58 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -4,6 +4,8 @@
%span.label.label-success shared
- else
%span.label.label-info specific
+ - if runner.locked?
+ %span.label.label-warning locked
- unless runner.active?
%span.label.label-danger paused
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 114bea92fc2..a53876d6757 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -40,6 +40,9 @@
%span.label.label-info specific
\- run builds from assigned projects
%li
+ %span.label.label-warning locked
+ \- runner cannot be assigned to other projects
+ %li
%span.label.label-danger paused
\- runner will not receive any new builds
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 69f634e75b9..a83eb7e88bb 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -15,18 +15,15 @@
%span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, fw: false)
- %span.hidden-xs
+ .group-right-buttons.btn-group
+ - if current_user
+ .pull-left.append-right-10= render 'shared/members/access_request_buttons', source: @group
= render 'shared/notifications/button', notification_setting: @notification_setting
- - if current_user
- .pull-right
- = render 'shared/members/access_request_buttons', source: @group
-
- if @group.description.present?
.cover-desc.description
= markdown(@group.description, pipeline: :description)
-
%div{ class: container_class }
.top-area
%ul.nav-links
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 96b38485425..12e7ed0e792 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -3,4 +3,5 @@
- if @noteable
:javascript
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}"
+ GitLab.GfmAutoComplete.cachedData = undefined;
GitLab.GfmAutoComplete.setup();
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 8ce23379fb4..540efa4780f 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -31,7 +31,7 @@
.project-repo-buttons.btn-group.project-right-buttons
- if current_user
- = render 'shared/members/access_request_buttons', source: @project
+ .pull-left.append-right-10= render 'shared/members/access_request_buttons', source: @project
= render "projects/buttons/download"
= render 'projects/buttons/dropdown'
diff --git a/app/views/shared/members/_access_request_buttons.html.haml b/app/views/shared/members/_access_request_buttons.html.haml
index 480e8ba6c85..c56418f052a 100644
--- a/app/views/shared/members/_access_request_buttons.html.haml
+++ b/app/views/shared/members/_access_request_buttons.html.haml
@@ -7,8 +7,8 @@
= link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: remove_member_message(member) },
- class: 'btn access-request-button hidden-xs'
+ class: 'btn'
- else
= link_to 'Request Access', polymorphic_path([:request_access, source, :members]),
method: :post,
- class: 'btn access-request-button hidden-xs'
+ class: 'btn'
diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb
index 75f89d524e7..44601f2b2bd 100644
--- a/config/initializers/metrics.rb
+++ b/config/initializers/metrics.rb
@@ -132,6 +132,9 @@ if Gitlab::Metrics.enabled?
config.instrument_instance_methods(API::Helpers)
config.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker)
+
+ config.instrument_instance_methods(Rouge::Plugins::Redcarpet)
+ config.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
end
GC::Profiler.enable
diff --git a/doc/workflow/add-user/img/access_requests_management.png b/doc/workflow/add-user/img/access_requests_management.png
index e9641cb4f85..5c9b510ba9d 100644
--- a/doc/workflow/add-user/img/access_requests_management.png
+++ b/doc/workflow/add-user/img/access_requests_management.png
Binary files differ
diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md
index 1a316e80976..9b50286b179 100644
--- a/doc/workflow/groups.md
+++ b/doc/workflow/groups.md
@@ -51,7 +51,7 @@ If necessary, you can increase the access level of an individual user for a spec
![Barry effectively has 'Master' access to GitLab CI now](groups/override_access_level.png)
-## Request access to a group
+## Requesting access to a group
As a user, you can request to be a member of a group. Go to the group you'd
like to be a member of, and click the **Request Access** button on the right
diff --git a/doc/workflow/groups/access_requests_management.png b/doc/workflow/groups/access_requests_management.png
index ffede8e9bd6..5202434f00f 100644
--- a/doc/workflow/groups/access_requests_management.png
+++ b/doc/workflow/groups/access_requests_management.png
Binary files differ
diff --git a/doc/workflow/groups/request_access_button.png b/doc/workflow/groups/request_access_button.png
index ff0ac8747a7..0eec5cb937d 100644
--- a/doc/workflow/groups/request_access_button.png
+++ b/doc/workflow/groups/request_access_button.png
Binary files differ
diff --git a/doc/workflow/groups/withdraw_access_request_button.png b/doc/workflow/groups/withdraw_access_request_button.png
index 99d7a326ed8..b7de830a780 100644
--- a/doc/workflow/groups/withdraw_access_request_button.png
+++ b/doc/workflow/groups/withdraw_access_request_button.png
Binary files differ
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 231840148d9..9f9ae75ff65 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -25,7 +25,7 @@ module API
# branch (required) - The name of the branch
# Example Request:
# GET /projects/:id/repository/branches/:branch
- get ':id/repository/branches/:branch', requirements: { branch: /.*/ } do
+ get ':id/repository/branches/:branch', requirements: { branch: /.+/ } do
@branch = user_project.repository.branches.find { |item| item.name == params[:branch] }
not_found!("Branch") unless @branch
present @branch, with: Entities::RepoObject, project: user_project
@@ -39,7 +39,7 @@ module API
# Example Request:
# PUT /projects/:id/repository/branches/:branch/protect
put ':id/repository/branches/:branch/protect',
- requirements: { branch: /.*/ } do
+ requirements: { branch: /.+/ } do
authorize_admin_project
@@ -59,7 +59,7 @@ module API
# Example Request:
# PUT /projects/:id/repository/branches/:branch/unprotect
put ':id/repository/branches/:branch/unprotect',
- requirements: { branch: /.*/ } do
+ requirements: { branch: /.+/ } do
authorize_admin_project
@@ -101,7 +101,7 @@ module API
# Example Request:
# DELETE /projects/:id/repository/branches/:branch
delete ":id/repository/branches/:branch",
- requirements: { branch: /.*/ } do
+ requirements: { branch: /.+/ } do
authorize_push_project
result = DeleteBranchService.new(user_project, current_user).
execute(params[:branch])
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 3e1ed3fe5c7..7b675e05fbb 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -61,7 +61,7 @@ module API
# tag_name (required) - The name of the tag
# Example Request:
# DELETE /projects/:id/repository/tags/:tag
- delete ":id/repository/tags/:tag_name", requirements: { tag_name: /.*/ } do
+ delete ":id/repository/tags/:tag_name", requirements: { tag_name: /.+/ } do
authorize_push_project
result = DeleteTagService.new(user_project, current_user).
execute(params[:tag_name])
@@ -83,7 +83,7 @@ module API
# description (required) - Release notes with markdown support
# Example Request:
# POST /projects/:id/repository/tags/:tag_name/release
- post ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do
+ post ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.+/ } do
authorize_push_project
required_attributes! [:description]
result = CreateReleaseService.new(user_project, current_user).
@@ -104,7 +104,7 @@ module API
# description (required) - Release notes with markdown support
# Example Request:
# PUT /projects/:id/repository/tags/:tag_name/release
- put ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do
+ put ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.+/ } do
authorize_push_project
required_attributes! [:description]
result = UpdateReleaseService.new(user_project, current_user).
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 62a79c62e20..536b478979f 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -27,12 +27,17 @@ module Banzai
highlighted = "<pre>#{code}</pre>"
end
- # Replace the parent `pre` element with the entire highlighted block
- node.parent.replace(highlighted)
+ # Extracted to a method to measure it
+ replace_parent_pre_element(node, highlighted)
end
private
+ def replace_parent_pre_element(node, highlighted)
+ # Replace the parent `pre` element with the entire highlighted block
+ node.parent.replace(highlighted)
+ end
+
# Override Rouge::Plugins::Redcarpet#rouge_formatter
def rouge_formatter(lexer)
Rouge::Formatters::HTMLGitlab.new(
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 2d297776cb0..2f82fafc13a 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -62,19 +62,45 @@ describe "Admin Runners" do
end
describe 'enable/create' do
- before do
- @project1.runners << runner
- visit admin_runner_path(runner)
+ shared_examples 'assignable runner' do
+ it 'enables a runner for a project' do
+ within '.unassigned-projects' do
+ click_on 'Enable'
+ end
+
+ assigned_project = page.find('.assigned-projects')
+
+ expect(assigned_project).to have_content(@project2.path)
+ end
end
- it 'enables specific runner for project' do
- within '.unassigned-projects' do
- click_on 'Enable'
+ context 'with specific runner' do
+ before do
+ @project1.runners << runner
+ visit admin_runner_path(runner)
end
- assigned_project = page.find('.assigned-projects')
+ it_behaves_like 'assignable runner'
+ end
+
+ context 'with locked runner' do
+ before do
+ runner.update(locked: true)
+ @project1.runners << runner
+ visit admin_runner_path(runner)
+ end
+
+ it_behaves_like 'assignable runner'
+ end
+
+ context 'with shared runner' do
+ before do
+ @project1.destroy
+ runner.update(is_shared: true)
+ visit admin_runner_path(runner)
+ end
- expect(assigned_project).to have_content(@project2.path)
+ it_behaves_like 'assignable runner'
end
end