Merge branch 'master' into sh-headless-chrome-support
|
@ -6,6 +6,7 @@
|
|||
},
|
||||
"extends": "airbnb-base",
|
||||
"globals": {
|
||||
"__webpack_public_path__": true,
|
||||
"_": false,
|
||||
"gl": false,
|
||||
"gon": false,
|
||||
|
|
174
CHANGELOG.md
|
@ -2,6 +2,180 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 9.5.1 (2017-08-23)
|
||||
|
||||
- [FIXED] Fix merge request pipeline status when pipeline has errors. !13664
|
||||
- [FIXED] Commit rows would occasionally render with the wrong language.
|
||||
- [FIXED] Fix caching of future broadcast messages.
|
||||
- [FIXED] Only require Sidekiq throttling library when enabled, to reduce cache misses.
|
||||
- Raise Housekeeping timeout to 24 hours. !13719
|
||||
|
||||
## 9.5.0 (2017-08-22)
|
||||
|
||||
- [FIXED] Fix timeouts when creating projects in groups with many members. !13508
|
||||
- [FIXED] Improve API pagination headers when no record found. !13629 (Jordan Patterson)
|
||||
- [FIXED] Fix deleting GitLab Pages files when a project is removed. !13631
|
||||
- [FIXED] Fix commit list not loading the correct page when scrolling.
|
||||
- [OTHER] Cache the number of forks of a project. !13535
|
||||
- GPG signed commits integration. !9546 (Alexis Reigel)
|
||||
- Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes. !9707 (Hiroyuki Sato)
|
||||
- Add custom linter for inline JavaScript to haml_lint. !9742 (winniehell)
|
||||
- Add /shrug and /tableflip commands. !10068 (Alex Ives)
|
||||
- Allow wiki pages to be renamed in the UI. !10069 (wendy0402)
|
||||
- Insert user name directly without encoding. !10085 (Nathan Neulinger <nneul@neulinger.org>)
|
||||
- Avoid plucking Todo ids in TodoService. !10845
|
||||
- Handle errors while a project is being deleted asynchronously. !11088
|
||||
- Decrease ABC threshold to 56.96. !11227 (Maxim Rydkin)
|
||||
- Remove Mattermost team when deleting a group. !11362
|
||||
- Block access to failing repository storage. !11449
|
||||
- Add coordinator url to admin area runner page. !11603
|
||||
- Allow testing any events for project hooks and system hooks. !11728 (Alexander Randa (@randaalex))
|
||||
- Disallow running the pipeline if ref is protected and user cannot merge the branch or create the tag. !11910
|
||||
- Remove project_key from the Jira configuration. !12050
|
||||
- Add CSRF token verification to API. !12154 (Vitaliy @blackst0ne Klachkov)
|
||||
- Fixes needed when GitLab sign-in is not enabled. !12491 (Robin Bobbitt)
|
||||
- Lazy load images for better Frontend performance. !12503
|
||||
- Replaces dashboard/event_filters.feature spinach with rspec. !12651 (Alexander Randa (@randaalex))
|
||||
- Toggle import description with import_sources_enabled. !12691 (Brianna Kicia)
|
||||
- Bump scss-lint to 0.54.0. !12733 (Takuya Noguchi)
|
||||
- Enable SpaceAfterComma in scss-lint. !12734 (Takuya Noguchi)
|
||||
- Remove CSS for nprogress removed. !12737 (Takuya Noguchi)
|
||||
- Enable UnnecessaryParentReference in scss-lint. !12738 (Takuya Noguchi)
|
||||
- Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper. !12742 (Jacopo Beschi @jacopo-beschi)
|
||||
- Enable ImportPath in scss-lint. !12749 (Takuya Noguchi)
|
||||
- Enable PropertySpelling in scss-lint. !12752 (Takuya Noguchi)
|
||||
- Add API for protected branches to allow for wildcard matching and no access restrictions. !12756 (Eric Yu)
|
||||
- refactor initializations in dropzone_input.js. !12768 (Brandon Everett)
|
||||
- Improve CSS for global nav dropdown UI. !12772 (Takuya Noguchi)
|
||||
- Remove public/ci/favicon.ico. !12803 (Takuya Noguchi)
|
||||
- Enable DeclarationOrder in scss-lint. !12805 (Takuya Noguchi)
|
||||
- Increase width of dropdown menus automatically. !12809 (Thomas Wucher)
|
||||
- Enable BangFormat in scss-lint [ci skip]. !12815 (Takuya Noguchi)
|
||||
- Added /duplicate quick action to close a duplicate issue. !12845 (Ryan Scott)
|
||||
- Make all application-settings accessible through the API. !12851
|
||||
- Remove Inactive Personal Access Tokens list from Access Tokens page. !12866
|
||||
- Replaces dashboard/dashboard.feature spinach with rspec. !12876 (Alexander Randa (@randaalex))
|
||||
- Reduce memory usage of the GitHub importer. !12886
|
||||
- Bump fog-core to 1.44.3 and fog providers' plugins to latest. !12897 (Takuya Noguchi)
|
||||
- Use only CSS to truncate commit message in blame. !12900 (Takuya Noguchi)
|
||||
- Protect manual actions against protected tag too. !12908
|
||||
- Allow to configure automatic retry of a failed CI/CD job. !12909
|
||||
- Remove help message about prioritized labels for non-members. !12912 (Takuya Noguchi)
|
||||
- Add link to doc/api/ci/lint.md. !12914 (Takuya Noguchi)
|
||||
- Add RequestCache which makes caching with RequestStore easier. !12920
|
||||
- Free up some top level words, reject top level groups named like files in the public folder. !12932
|
||||
- Extend API for Group Secret Variable. !12936
|
||||
- Hide description about protected branches to non-member. !12945 (Takuya Noguchi)
|
||||
- Support custom directory in gitlab:backup:create task. !12984 (Markus Koller)
|
||||
- Raise guessed encoding confidence threshold to 50. !12990
|
||||
- Add author_id & assignee_id param to /issues API. !13004
|
||||
- Fix today day highlight in calendar. !13048
|
||||
- Prevent LDAP login callback from being called with a GET request. !13059
|
||||
- Add top-level merge_requests API endpoint. !13060
|
||||
- Handle maximum pages artifacts size correctly. !13072
|
||||
- Enable gitaly_post_upload_pack by default. !13078
|
||||
- Add Prometheus metrics exporter to Sidekiq. !13082
|
||||
- Fix improperly skipped backups of wikis. !13096
|
||||
- Projects can be created from templates. !13108
|
||||
- Fix the /projects/:id/repository/branches endpoint to handle dots in the branch name when the project full path contains a `/`. !13115
|
||||
- Fix project logos that are not centered vertically on list pages. !13124 (Florian Lemaitre)
|
||||
- Derive project path from import URL. !13131
|
||||
- Fix deletion of deploy keys linked to other projects. !13162
|
||||
- repository archive download url now ends with selected file extension. !13178 (haseebeqx)
|
||||
- Show auto-generated avatars for Groups without avatars. !13188
|
||||
- Allow any logged in users to read_users_list even if it's restricted. !13201
|
||||
- Unlock stuck merge request and set the proper state. !13207
|
||||
- Fix timezone inconsistencies in user contribution graph. !13208
|
||||
- Fix Issue board when using Ruby 2.4. !13220
|
||||
- Don't rename namespace called system when upgrading from 9.1.x to 9.5. !13228
|
||||
- Fix encoding error for WebHook logging. !13230 (Alexander Randa (@randaalex))
|
||||
- Uniquify reserved word usernames on OAuth user creation. !13244 (Robin Bobbitt)
|
||||
- Expose target_iid in Events API. !13247 (sue445)
|
||||
- Add star for action scope, in order to delete image from registry. !13248 (jean)
|
||||
- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
|
||||
- Fix an order of operations for CI connection error message in merge request widget. !13252
|
||||
- Don't send rejection mails for all auto-generated mails. !13254
|
||||
- Expose noteable_iid in Note. !13265 (sue445)
|
||||
- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
|
||||
- Move some code from services to workers in order to improve performance. !13326
|
||||
- Fix destroy of case-insensitive conflicting redirects. !13357
|
||||
- Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name when the project full path contains a `/`. !13368
|
||||
- Fix the /projects/:id/repository/commits endpoint to handle dots in the ref name when the project full path contains a `/`. !13370
|
||||
- Project pending delete no longer return 500 error in admins projects view. !13389
|
||||
- Use full path of user's avatar in webhooks. !13401 (Vitaliy @blackst0ne Klachkov)
|
||||
- Make GPGME temporary directory handling thread safe. !13481 (Alexis Reigel)
|
||||
- Add support for kube_namespace in Metrics queries. !16169
|
||||
- Fix bar chart does not display label at 0 hour. !35136 (Jason Dai)
|
||||
- Use project_ref_path to create the link to a branch to fix links that 404.
|
||||
- Declare related resources into V4 API entities.
|
||||
- Add Slack and JIRA services counts to Usage Data.
|
||||
- Prevent web hook and project service background jobs from going to the dead jobs queue.
|
||||
- Display specific error message when JIRA test fails.
|
||||
- clean up merge request widget UI.
|
||||
- Associate Issues tab only with internal issues tracker.
|
||||
- Remove events column from notification settings table.
|
||||
- Clarifies and rearranges the input variables on the kubernetes integration page and adjusts the docs slightly to meet the same order.
|
||||
- Respect blockquote line breaks in markdown.
|
||||
- Update confidential issue UI - add confidential visibility and settings to sidebar.
|
||||
- Add icons to contextual sidebars.
|
||||
- Make contextual sidebar collapsible.
|
||||
- Update Pipeline's badge count in Merge Request and Commits view to match real-time content.
|
||||
- Added link to the MR widget that directs to the monitoring dashboard.
|
||||
- Use jQuery to control scroll behavior in job log for cross browser consistency.
|
||||
- move edit comment button outside of dropdown.
|
||||
- Updates vue resource and code according to breaking changes.
|
||||
- Add GitHub imported projects count to usage data.
|
||||
- Rename about to overview for group and project page.
|
||||
- Prevent disabled pagination button to be clicked.
|
||||
- Remove coffee-rails gem. (Takuya Noguchi)
|
||||
- Remove net-ssh gem. (Takuya Noguchi)
|
||||
- Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1. (Takuya Noguchi)
|
||||
- improve file upload/replace experience.
|
||||
- allow closing Cycle Analytics intro box in firefox.
|
||||
- Fix label creation from new list for subgroup projects.
|
||||
- fix transient js error in rspec tests.
|
||||
- fix jump to next discussion button.
|
||||
- Fix translations for Star/Unstar in JS file.
|
||||
- Improve mobile sidebar.
|
||||
- Rename Pipelines tab to CI / CD in new navigation.
|
||||
- Fix display of new diff comments after changing b between diff views.
|
||||
- Store & use ConvDev percentages returned by the Version app.
|
||||
- Fixes new issue button for failed job returning 404.
|
||||
- Align OR separator to center in new project page.
|
||||
- Add filtered search to group issue dashboard.
|
||||
- Cache Appearance instances in Redis.
|
||||
- Fixed breadcrumbs title aggressively collapsing.
|
||||
- Better caching and indexing of broadcast messages.
|
||||
- Moved diff changed files into a dropdown.
|
||||
- Improve performance of large (initial) push into default branch.
|
||||
- Improve performance of checking for projects on the projects dashboard.
|
||||
- Eager load project creators for project dashboards.
|
||||
- Modify if condition to be more readable.
|
||||
- Fix links to group milestones from issue and merge request sidebar.
|
||||
- Remove hidden symlinks from project import files.
|
||||
- Fixed sign-in restrictions buttons not toggling active state.
|
||||
- Fix replying to commit comments on merge requests created from forks.
|
||||
- Support Markdown references, autocomplete, and quick actions for group milestones.
|
||||
- Cache recent projects for group-level new resource creation.
|
||||
- Fix API responses when dealing with txt files.
|
||||
- Fix project milestones import when projects belongs to a group.
|
||||
- Fix Mattermost integration.
|
||||
- Memoize the number of personal projects a user has to reduce COUNT queries.
|
||||
- Merge issuable "reopened" state into "opened".
|
||||
- Migrate events into a new format to reduce the storage necessary and improve performance.
|
||||
- MR branch link now links to tree instead of commits.
|
||||
- Use Prev/Next pagination for exploring projects.
|
||||
- Pass before_script and script as-is preserving arrays.
|
||||
- Change project FK migration to skip existing FKs.
|
||||
- Remove redundant query when retrieving the most recent push of a user.
|
||||
- Re-organise "issues" indexes for faster ordering.
|
||||
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
|
||||
- Fix search box losing focus when typing.
|
||||
- Add structured logging for Rails processes.
|
||||
- Skip oAuth authorization for trusted applications.
|
||||
- Use a specialized class for querying events to improve performance.
|
||||
- Update build badges to be pipeline badges and display passing instead of success.
|
||||
|
||||
## 9.4.5 (2017-08-14)
|
||||
|
||||
- Fix deletion of deploy keys linked to other projects. !13162
|
||||
|
|
4
Gemfile
|
@ -396,12 +396,12 @@ gem 'net-ssh', '~> 4.1.0'
|
|||
# Required for ED25519 SSH host key support
|
||||
group :ed25519 do
|
||||
gem 'rbnacl-libsodium'
|
||||
gem 'rbnacl', '~> 3.2'
|
||||
gem 'rbnacl', '~> 4.0'
|
||||
gem 'bcrypt_pbkdf', '~> 1.0'
|
||||
end
|
||||
|
||||
# Gitaly GRPC client
|
||||
gem 'gitaly', '~> 0.29.0'
|
||||
gem 'gitaly', '~> 0.30.0'
|
||||
|
||||
gem 'toml-rb', '~> 0.3.15', require: false
|
||||
|
||||
|
|
10
Gemfile.lock
|
@ -204,7 +204,7 @@ GEM
|
|||
multi_json
|
||||
fast_gettext (1.4.0)
|
||||
ffaker (2.4.0)
|
||||
ffi (1.9.10)
|
||||
ffi (1.9.18)
|
||||
flay (2.8.1)
|
||||
erubis (~> 2.7.0)
|
||||
path_expander (~> 1.0)
|
||||
|
@ -276,7 +276,7 @@ GEM
|
|||
po_to_json (>= 1.0.0)
|
||||
rails (>= 3.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
gitaly (0.29.0)
|
||||
gitaly (0.30.0)
|
||||
google-protobuf (~> 3.1)
|
||||
grpc (~> 1.0)
|
||||
github-linguist (4.7.6)
|
||||
|
@ -679,7 +679,7 @@ GEM
|
|||
rake (12.0.0)
|
||||
rblineprof (0.3.6)
|
||||
debugger-ruby_core_source (~> 1.3)
|
||||
rbnacl (3.4.0)
|
||||
rbnacl (4.0.2)
|
||||
ffi
|
||||
rbnacl-libsodium (1.0.11)
|
||||
rbnacl (>= 3.0.1)
|
||||
|
@ -1016,7 +1016,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.2.2)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.2.0)
|
||||
gitaly (~> 0.29.0)
|
||||
gitaly (~> 0.30.0)
|
||||
github-linguist (~> 4.7.0)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-markup (~> 1.5.1)
|
||||
|
@ -1103,7 +1103,7 @@ DEPENDENCIES
|
|||
rainbow (~> 2.2)
|
||||
raindrops (~> 0.18)
|
||||
rblineprof (~> 0.3.6)
|
||||
rbnacl (~> 3.2)
|
||||
rbnacl (~> 4.0)
|
||||
rbnacl-libsodium
|
||||
rdoc (~> 4.2)
|
||||
re2 (~> 1.1.1)
|
||||
|
|
2
VERSION
|
@ -1 +1 @@
|
|||
9.5.0-pre
|
||||
9.6.0-pre
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
/* eslint-disable no-underscore-dangle, camelcase */
|
||||
/* global __webpack_public_path__ */
|
||||
|
||||
import monacoContext from 'monaco-editor/dev/vs/loader';
|
||||
|
||||
monacoContext.require.config({
|
||||
paths: {
|
||||
vs: `${__webpack_public_path__}monaco-editor/vs`,
|
||||
vs: `${__webpack_public_path__}monaco-editor/vs`, // eslint-disable-line camelcase
|
||||
},
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
window.__monaco_context__ = monacoContext;
|
||||
export default monacoContext.require;
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
*/
|
||||
|
||||
if (gon && gon.webpack_public_path) {
|
||||
__webpack_public_path__ = gon.webpack_public_path; // eslint-disable-line
|
||||
__webpack_public_path__ = gon.webpack_public_path; // eslint-disable-line camelcase
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
img {
|
||||
/*max-width: 100%;*/
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
img.lazy {
|
||||
min-width: 200px;
|
||||
min-height: 100px;
|
||||
background-color: $gray-lightest;
|
||||
|
|
|
@ -286,6 +286,9 @@
|
|||
|
||||
|
||||
.gpg-status-box {
|
||||
padding: 2px 10px;
|
||||
margin-right: $gl-padding;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
@ -314,7 +317,6 @@
|
|||
&.valid {
|
||||
svg {
|
||||
border: 1px solid $brand-success;
|
||||
|
||||
fill: $brand-success;
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +324,6 @@
|
|||
&.invalid {
|
||||
svg {
|
||||
border: 1px solid $common-gray-light;
|
||||
|
||||
fill: $common-gray-light;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,11 @@
|
|||
class Admin::LogsController < Admin::ApplicationController
|
||||
def show
|
||||
@loggers = [
|
||||
Gitlab::AppLogger,
|
||||
Gitlab::GitLogger,
|
||||
Gitlab::EnvironmentLogger,
|
||||
Gitlab::SidekiqLogger,
|
||||
Gitlab::RepositoryCheckLogger
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,13 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
def new
|
||||
@group = Group.new
|
||||
|
||||
if params[:parent_id].present?
|
||||
parent = Group.find_by(id: params[:parent_id])
|
||||
if can?(current_user, :create_subgroup, parent)
|
||||
@group.parent = parent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -4,7 +4,6 @@ class Projects::ServicesController < Projects::ApplicationController
|
|||
# Authorize
|
||||
before_action :authorize_admin_project!
|
||||
before_action :service, only: [:edit, :update, :test]
|
||||
before_action :update_service, only: [:update, :test]
|
||||
|
||||
respond_to :html
|
||||
|
||||
|
@ -14,6 +13,8 @@ class Projects::ServicesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
@service.attributes = service_params[:service]
|
||||
|
||||
if @service.save(context: :manual_change)
|
||||
redirect_to(project_settings_integrations_path(@project), notice: success_message)
|
||||
else
|
||||
|
@ -24,7 +25,7 @@ class Projects::ServicesController < Projects::ApplicationController
|
|||
def test
|
||||
message = {}
|
||||
|
||||
if @service.can_test?
|
||||
if @service.can_test? && @service.update_attributes(service_params[:service])
|
||||
data = @service.test_data(project, current_user)
|
||||
outcome = @service.test(data)
|
||||
|
||||
|
@ -50,10 +51,6 @@ class Projects::ServicesController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def update_service
|
||||
@service.assign_attributes(service_params[:service])
|
||||
end
|
||||
|
||||
def service
|
||||
@service ||= @project.find_or_initialize_service(params[:id])
|
||||
end
|
||||
|
|
|
@ -116,6 +116,7 @@ module ApplicationSettingsHelper
|
|||
:email_author_in_body,
|
||||
:enabled_git_access_protocol,
|
||||
:gravatar_enabled,
|
||||
:hashed_storage_enabled,
|
||||
:help_page_hide_commercial_content,
|
||||
:help_page_support_url,
|
||||
:help_page_text,
|
||||
|
|
|
@ -12,11 +12,18 @@ module AvatarsHelper
|
|||
avatar_size = options[:size] || 16
|
||||
user_name = options[:user].try(:name) || options[:user_name]
|
||||
avatar_url = options[:url] || avatar_icon(options[:user] || options[:user_email], avatar_size)
|
||||
data_attributes = { container: 'body' }
|
||||
has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip]
|
||||
data_attributes = {}
|
||||
css_class = %W[avatar s#{avatar_size}].push(*options[:css_class])
|
||||
|
||||
if has_tooltip
|
||||
css_class.push('has-tooltip')
|
||||
data_attributes = { container: 'body' }
|
||||
end
|
||||
|
||||
image_tag(
|
||||
avatar_url,
|
||||
class: %W[avatar has-tooltip s#{avatar_size}].push(*options[:css_class]),
|
||||
class: css_class,
|
||||
alt: "#{user_name}'s avatar",
|
||||
title: user_name,
|
||||
data: data_attributes,
|
||||
|
|
|
@ -114,7 +114,7 @@ module CommitsHelper
|
|||
end
|
||||
|
||||
def commit_signature_badge_classes(additional_classes)
|
||||
%w(btn status-box gpg-status-box) + Array(additional_classes)
|
||||
%w(btn gpg-status-box) + Array(additional_classes)
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -181,6 +181,7 @@ module EventsHelper
|
|||
end
|
||||
|
||||
def event_commit_title(message)
|
||||
message ||= ''
|
||||
(message.split("\n").first || "").truncate(70)
|
||||
rescue
|
||||
"--broken encoding"
|
||||
|
|
|
@ -19,11 +19,21 @@ class BroadcastMessage < ActiveRecord::Base
|
|||
after_commit :flush_redis_cache
|
||||
|
||||
def self.current
|
||||
Rails.cache.fetch(CACHE_KEY) do
|
||||
where('ends_at > :now AND starts_at <= :now', now: Time.zone.now)
|
||||
.reorder(id: :asc)
|
||||
.to_a
|
||||
end
|
||||
messages = Rails.cache.fetch(CACHE_KEY) { current_and_future_messages.to_a }
|
||||
|
||||
return messages if messages.empty?
|
||||
|
||||
now_or_future = messages.select(&:now_or_future?)
|
||||
|
||||
# If there are cached entries but none are to be displayed we'll purge the
|
||||
# cache so we don't keep running this code all the time.
|
||||
Rails.cache.delete(CACHE_KEY) if now_or_future.empty?
|
||||
|
||||
now_or_future.select(&:now?)
|
||||
end
|
||||
|
||||
def self.current_and_future_messages
|
||||
where('ends_at > :now', now: Time.zone.now).reorder(id: :asc)
|
||||
end
|
||||
|
||||
def active?
|
||||
|
@ -38,6 +48,18 @@ class BroadcastMessage < ActiveRecord::Base
|
|||
ends_at < Time.zone.now
|
||||
end
|
||||
|
||||
def now?
|
||||
(starts_at..ends_at).cover?(Time.zone.now)
|
||||
end
|
||||
|
||||
def future?
|
||||
starts_at > Time.zone.now
|
||||
end
|
||||
|
||||
def now_or_future?
|
||||
now? || future?
|
||||
end
|
||||
|
||||
def flush_redis_cache
|
||||
Rails.cache.delete(CACHE_KEY)
|
||||
end
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
module Storage
|
||||
module LegacyProject
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def disk_path
|
||||
full_path
|
||||
end
|
||||
|
||||
def ensure_storage_path_exist
|
||||
gitlab_shell.add_namespace(repository_storage_path, namespace.full_path)
|
||||
end
|
||||
|
||||
def rename_repo
|
||||
path_was = previous_changes['path'].first
|
||||
old_path_with_namespace = File.join(namespace.full_path, path_was)
|
||||
new_path_with_namespace = File.join(namespace.full_path, path)
|
||||
|
||||
Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}"
|
||||
|
||||
if has_container_registry_tags?
|
||||
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!"
|
||||
|
||||
# we currently doesn't support renaming repository if it contains images in container registry
|
||||
raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
|
||||
end
|
||||
|
||||
expire_caches_before_rename(old_path_with_namespace)
|
||||
|
||||
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
|
||||
# If repository moved successfully we need to send update instructions to users.
|
||||
# However we cannot allow rollback since we moved repository
|
||||
# So we basically we mute exceptions in next actions
|
||||
begin
|
||||
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
|
||||
send_move_instructions(old_path_with_namespace)
|
||||
expires_full_path_cache
|
||||
|
||||
@old_path_with_namespace = old_path_with_namespace
|
||||
|
||||
SystemHooksService.new.execute_hooks_for(self, :rename)
|
||||
|
||||
@repository = nil
|
||||
rescue => e
|
||||
Rails.logger.error "Exception renaming #{old_path_with_namespace} -> #{new_path_with_namespace}: #{e}"
|
||||
# Returning false does not rollback after_* transaction but gives
|
||||
# us information about failing some of tasks
|
||||
false
|
||||
end
|
||||
else
|
||||
Rails.logger.error "Repository could not be renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
|
||||
|
||||
# if we cannot move namespace directory we should rollback
|
||||
# db changes in order to prevent out of sync between db and fs
|
||||
raise StandardError.new('repository cannot be renamed')
|
||||
end
|
||||
|
||||
Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
|
||||
|
||||
Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path)
|
||||
Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path)
|
||||
end
|
||||
|
||||
def create_repository(force: false)
|
||||
# Forked import is handled asynchronously
|
||||
return if forked? && !force
|
||||
|
||||
if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
|
||||
repository.after_create
|
||||
true
|
||||
else
|
||||
errors.add(:base, 'Failed to create repository via gitlab-shell')
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -406,7 +406,7 @@ class Event < ActiveRecord::Base
|
|||
|
||||
def body?
|
||||
if push?
|
||||
push_with_commits? || rm_ref?
|
||||
push_with_commits?
|
||||
elsif note?
|
||||
true
|
||||
else
|
||||
|
|
|
@ -50,7 +50,10 @@ class Issue < ActiveRecord::Base
|
|||
|
||||
scope :preload_associations, -> { preload(:labels, project: :namespace) }
|
||||
|
||||
scope :public_only, -> { where(confidential: false) }
|
||||
|
||||
after_save :expire_etag_cache
|
||||
after_commit :update_project_counter_caches, on: :destroy
|
||||
|
||||
attr_spammable :title, spam_title: true
|
||||
attr_spammable :description, spam_description: true
|
||||
|
@ -266,6 +269,10 @@ class Issue < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def update_project_counter_caches
|
||||
Projects::OpenIssuesCountService.new(project).refresh_cache
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns `true` if the given User can read the current Issue.
|
||||
|
|
|
@ -31,6 +31,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
|
||||
after_create :ensure_merge_request_diff, unless: :importing?
|
||||
after_update :reload_diff_if_branch_changed
|
||||
after_commit :update_project_counter_caches, on: :destroy
|
||||
|
||||
# When this attribute is true some MR validation is ignored
|
||||
# It allows us to close or modify broken merge requests
|
||||
|
@ -936,6 +937,10 @@ class MergeRequest < ActiveRecord::Base
|
|||
true
|
||||
end
|
||||
|
||||
def update_project_counter_caches
|
||||
Projects::OpenMergeRequestsCountService.new(target_project).refresh_cache
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def write_ref
|
||||
|
|
|
@ -17,7 +17,6 @@ class Project < ActiveRecord::Base
|
|||
include ProjectFeaturesCompatibility
|
||||
include SelectForProjectAuthorization
|
||||
include Routable
|
||||
include Storage::LegacyProject
|
||||
|
||||
extend Gitlab::ConfigHelper
|
||||
|
||||
|
@ -25,6 +24,7 @@ class Project < ActiveRecord::Base
|
|||
|
||||
NUMBER_OF_PERMITTED_BOARDS = 1
|
||||
UNKNOWN_IMPORT_URL = 'http://unknown.git'.freeze
|
||||
LATEST_STORAGE_VERSION = 1
|
||||
|
||||
cache_markdown_field :description, pipeline: :description
|
||||
|
||||
|
@ -32,6 +32,8 @@ class Project < ActiveRecord::Base
|
|||
:merge_requests_enabled?, :issues_enabled?, to: :project_feature,
|
||||
allow_nil: true
|
||||
|
||||
delegate :base_dir, :disk_path, :ensure_storage_path_exists, to: :storage
|
||||
|
||||
default_value_for :archived, false
|
||||
default_value_for :visibility_level, gitlab_config_features.visibility_level
|
||||
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
|
||||
|
@ -44,32 +46,24 @@ class Project < ActiveRecord::Base
|
|||
default_value_for :snippets_enabled, gitlab_config_features.snippets
|
||||
default_value_for :only_allow_merge_if_all_discussions_are_resolved, false
|
||||
|
||||
after_create :ensure_storage_path_exist
|
||||
after_create :create_project_feature, unless: :project_feature
|
||||
add_authentication_token_field :runners_token
|
||||
before_save :ensure_runners_token
|
||||
|
||||
after_save :update_project_statistics, if: :namespace_id_changed?
|
||||
|
||||
# set last_activity_at to the same as created_at
|
||||
after_create :create_project_feature, unless: :project_feature
|
||||
after_create :set_last_activity_at
|
||||
def set_last_activity_at
|
||||
update_column(:last_activity_at, self.created_at)
|
||||
end
|
||||
|
||||
after_create :set_last_repository_updated_at
|
||||
def set_last_repository_updated_at
|
||||
update_column(:last_repository_updated_at, self.created_at)
|
||||
end
|
||||
after_update :update_forks_visibility_level
|
||||
|
||||
before_destroy :remove_private_deploy_keys
|
||||
after_destroy -> { run_after_commit { remove_pages } }
|
||||
|
||||
# update visibility_level of forks
|
||||
after_update :update_forks_visibility_level
|
||||
|
||||
after_validation :check_pending_delete
|
||||
|
||||
# Legacy Storage specific hooks
|
||||
|
||||
after_save :ensure_storage_path_exist, if: :namespace_id_changed?
|
||||
# Storage specific hooks
|
||||
after_initialize :use_hashed_storage
|
||||
after_create :ensure_storage_path_exists
|
||||
after_save :ensure_storage_path_exists, if: :namespace_id_changed?
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
|
@ -238,9 +232,6 @@ class Project < ActiveRecord::Base
|
|||
presence: true,
|
||||
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
|
||||
|
||||
add_authentication_token_field :runners_token
|
||||
before_save :ensure_runners_token
|
||||
|
||||
mount_uploader :avatar, AvatarUploader
|
||||
has_many :uploads, as: :model, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
||||
|
||||
|
@ -487,6 +478,10 @@ class Project < ActiveRecord::Base
|
|||
@repository ||= Repository.new(full_path, self, disk_path: disk_path)
|
||||
end
|
||||
|
||||
def reload_repository!
|
||||
@repository = nil
|
||||
end
|
||||
|
||||
def container_registry_url
|
||||
if Gitlab.config.registry.enabled
|
||||
"#{Gitlab.config.registry.host_port}/#{full_path.downcase}"
|
||||
|
@ -1004,12 +999,25 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def create_repository(force: false)
|
||||
# Forked import is handled asynchronously
|
||||
return if forked? && !force
|
||||
|
||||
if gitlab_shell.add_repository(repository_storage_path, disk_path)
|
||||
repository.after_create
|
||||
true
|
||||
else
|
||||
errors.add(:base, 'Failed to create repository via gitlab-shell')
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def hook_attrs(backward: true)
|
||||
attrs = {
|
||||
name: name,
|
||||
description: description,
|
||||
web_url: web_url,
|
||||
avatar_url: avatar_url,
|
||||
avatar_url: avatar_url(only_path: false),
|
||||
git_ssh_url: ssh_url_to_repo,
|
||||
git_http_url: http_url_to_repo,
|
||||
namespace: namespace.name,
|
||||
|
@ -1086,6 +1094,7 @@ class Project < ActiveRecord::Base
|
|||
!!repository.exists?
|
||||
end
|
||||
|
||||
# update visibility_level of forks
|
||||
def update_forks_visibility_level
|
||||
return unless visibility_level < visibility_level_was
|
||||
|
||||
|
@ -1158,7 +1167,11 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def open_issues_count
|
||||
issues.opened.count
|
||||
Projects::OpenIssuesCountService.new(self).count
|
||||
end
|
||||
|
||||
def open_merge_requests_count
|
||||
Projects::OpenMergeRequestsCountService.new(self).count
|
||||
end
|
||||
|
||||
def visibility_level_allowed_as_fork?(level = self.visibility_level)
|
||||
|
@ -1213,7 +1226,8 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def pages_path
|
||||
File.join(Settings.pages.path, disk_path)
|
||||
# TODO: when we migrate Pages to work with new storage types, change here to use disk_path
|
||||
File.join(Settings.pages.path, full_path)
|
||||
end
|
||||
|
||||
def public_pages_path
|
||||
|
@ -1252,6 +1266,50 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def rename_repo
|
||||
new_full_path = build_full_path
|
||||
|
||||
Rails.logger.error "Attempting to rename #{full_path_was} -> #{new_full_path}"
|
||||
|
||||
if has_container_registry_tags?
|
||||
Rails.logger.error "Project #{full_path_was} cannot be renamed because container registry tags are present!"
|
||||
|
||||
# we currently doesn't support renaming repository if it contains images in container registry
|
||||
raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
|
||||
end
|
||||
|
||||
expire_caches_before_rename(full_path_was)
|
||||
|
||||
if storage.rename_repo
|
||||
Gitlab::AppLogger.info "Project was renamed: #{full_path_was} -> #{new_full_path}"
|
||||
rename_repo_notify!
|
||||
after_rename_repo
|
||||
else
|
||||
Rails.logger.error "Repository could not be renamed: #{full_path_was} -> #{new_full_path}"
|
||||
|
||||
# if we cannot move namespace directory we should rollback
|
||||
# db changes in order to prevent out of sync between db and fs
|
||||
raise StandardError.new('repository cannot be renamed')
|
||||
end
|
||||
end
|
||||
|
||||
def rename_repo_notify!
|
||||
send_move_instructions(full_path_was)
|
||||
expires_full_path_cache
|
||||
|
||||
self.old_path_with_namespace = full_path_was
|
||||
SystemHooksService.new.execute_hooks_for(self, :rename)
|
||||
|
||||
reload_repository!
|
||||
end
|
||||
|
||||
def after_rename_repo
|
||||
path_before_change = previous_changes['path'].first
|
||||
|
||||
Gitlab::UploadsTransfer.new.rename_project(path_before_change, self.path, namespace.full_path)
|
||||
Gitlab::PagesTransfer.new.rename_project(path_before_change, self.path, namespace.full_path)
|
||||
end
|
||||
|
||||
def running_or_pending_build_count(force: false)
|
||||
Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do
|
||||
builds.running_or_pending.count(:all)
|
||||
|
@ -1410,6 +1468,10 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def full_path_was
|
||||
File.join(namespace.full_path, previous_changes['path'].first)
|
||||
end
|
||||
|
||||
alias_method :name_with_namespace, :full_name
|
||||
alias_method :human_name, :full_name
|
||||
# @deprecated cannot remove yet because it has an index with its name in elasticsearch
|
||||
|
@ -1419,8 +1481,36 @@ class Project < ActiveRecord::Base
|
|||
Projects::ForksCountService.new(self).count
|
||||
end
|
||||
|
||||
def legacy_storage?
|
||||
self.storage_version.nil?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def storage
|
||||
@storage ||=
|
||||
if self.storage_version && self.storage_version >= 1
|
||||
Storage::HashedProject.new(self)
|
||||
else
|
||||
Storage::LegacyProject.new(self)
|
||||
end
|
||||
end
|
||||
|
||||
def use_hashed_storage
|
||||
if self.new_record? && current_application_settings.hashed_storage_enabled
|
||||
self.storage_version = LATEST_STORAGE_VERSION
|
||||
end
|
||||
end
|
||||
|
||||
# set last_activity_at to the same as created_at
|
||||
def set_last_activity_at
|
||||
update_column(:last_activity_at, self.created_at)
|
||||
end
|
||||
|
||||
def set_last_repository_updated_at
|
||||
update_column(:last_repository_updated_at, self.created_at)
|
||||
end
|
||||
|
||||
def cross_namespace_reference?(from)
|
||||
case from
|
||||
when Project
|
||||
|
|
|
@ -24,6 +24,8 @@ class KubernetesService < DeploymentService
|
|||
validates :token
|
||||
end
|
||||
|
||||
before_validation :enforce_namespace_to_lower_case
|
||||
|
||||
validates :namespace,
|
||||
allow_blank: true,
|
||||
length: 1..63,
|
||||
|
@ -207,4 +209,8 @@ class KubernetesService < DeploymentService
|
|||
max_session_time: current_application_settings.terminal_max_session_time
|
||||
}
|
||||
end
|
||||
|
||||
def enforce_namespace_to_lower_case
|
||||
self.namespace = self.namespace&.downcase
|
||||
end
|
||||
end
|
||||
|
|
42
app/models/storage/hashed_project.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
module Storage
|
||||
class HashedProject
|
||||
attr_accessor :project
|
||||
delegate :gitlab_shell, :repository_storage_path, to: :project
|
||||
|
||||
ROOT_PATH_PREFIX = '@hashed'.freeze
|
||||
|
||||
def initialize(project)
|
||||
@project = project
|
||||
end
|
||||
|
||||
# Base directory
|
||||
#
|
||||
# @return [String] directory where repository is stored
|
||||
def base_dir
|
||||
"#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}" if disk_hash
|
||||
end
|
||||
|
||||
# Disk path is used to build repository and project's wiki path on disk
|
||||
#
|
||||
# @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
|
||||
def disk_path
|
||||
"#{base_dir}/#{disk_hash}" if disk_hash
|
||||
end
|
||||
|
||||
def ensure_storage_path_exists
|
||||
gitlab_shell.add_namespace(repository_storage_path, base_dir)
|
||||
end
|
||||
|
||||
def rename_repo
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generates the hash for the project path and name on disk
|
||||
# If you need to refer to the repository on disk, use the `#disk_path`
|
||||
def disk_hash
|
||||
@disk_hash ||= Digest::SHA2.hexdigest(project.id.to_s) if project.id
|
||||
end
|
||||
end
|
||||
end
|
51
app/models/storage/legacy_project.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
module Storage
|
||||
class LegacyProject
|
||||
attr_accessor :project
|
||||
delegate :namespace, :gitlab_shell, :repository_storage_path, to: :project
|
||||
|
||||
def initialize(project)
|
||||
@project = project
|
||||
end
|
||||
|
||||
# Base directory
|
||||
#
|
||||
# @return [String] directory where repository is stored
|
||||
def base_dir
|
||||
namespace.full_path
|
||||
end
|
||||
|
||||
# Disk path is used to build repository and project's wiki path on disk
|
||||
#
|
||||
# @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
|
||||
def disk_path
|
||||
project.full_path
|
||||
end
|
||||
|
||||
def ensure_storage_path_exists
|
||||
return unless namespace
|
||||
|
||||
gitlab_shell.add_namespace(repository_storage_path, base_dir)
|
||||
end
|
||||
|
||||
def rename_repo
|
||||
new_full_path = project.build_full_path
|
||||
|
||||
if gitlab_shell.mv_repository(repository_storage_path, project.full_path_was, new_full_path)
|
||||
# If repository moved successfully we need to send update instructions to users.
|
||||
# However we cannot allow rollback since we moved repository
|
||||
# So we basically we mute exceptions in next actions
|
||||
begin
|
||||
gitlab_shell.mv_repository(repository_storage_path, "#{project.full_path_was}.wiki", "#{new_full_path}.wiki")
|
||||
return true
|
||||
rescue => e
|
||||
Rails.logger.error "Exception renaming #{project.full_path_was} -> #{new_full_path}: #{e}"
|
||||
# Returning false does not rollback after_* transaction but gives
|
||||
# us information about failing some of tasks
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,6 +13,8 @@ class GroupPolicy < BasePolicy
|
|||
condition(:master) { access_level >= GroupMember::MASTER }
|
||||
condition(:reporter) { access_level >= GroupMember::REPORTER }
|
||||
|
||||
condition(:nested_groups_supported, scope: :global) { Group.supports_nested_groups? }
|
||||
|
||||
condition(:has_projects) do
|
||||
GroupProjectsFinder.new(group: @subject, current_user: @user).execute.any?
|
||||
end
|
||||
|
@ -42,7 +44,7 @@ class GroupPolicy < BasePolicy
|
|||
enable :change_visibility_level
|
||||
end
|
||||
|
||||
rule { owner & can_create_group }.enable :create_subgroup
|
||||
rule { owner & can_create_group & nested_groups_supported }.enable :create_subgroup
|
||||
|
||||
rule { public_group | logged_in_viewable }.enable :view_globally
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@ module Groups
|
|||
return @group
|
||||
end
|
||||
|
||||
if @group.parent && !can?(current_user, :admin_group, @group.parent)
|
||||
if @group.parent && !can?(current_user, :create_subgroup, @group.parent)
|
||||
@group.parent = nil
|
||||
@group.errors.add(:parent_id, 'manage access required to create subgroup')
|
||||
@group.errors.add(:parent_id, 'You don’t have permission to create a subgroup in this group.')
|
||||
|
||||
return @group
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ module Groups
|
|||
# Execute the destruction of the models immediately to ensure atomic cleanup.
|
||||
# Skip repository removal because we remove directory with namespace
|
||||
# that contain all these repositories
|
||||
::Projects::DestroyService.new(project, current_user, skip_repo: true).execute
|
||||
::Projects::DestroyService.new(project, current_user, skip_repo: project.legacy_storage?).execute
|
||||
end
|
||||
|
||||
group.children.each do |group|
|
||||
|
|
45
app/services/groups/nested_create_service.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
module Groups
|
||||
class NestedCreateService < Groups::BaseService
|
||||
attr_reader :group_path
|
||||
|
||||
def initialize(user, params)
|
||||
@current_user, @params = user, params.dup
|
||||
|
||||
@group_path = @params.delete(:group_path)
|
||||
end
|
||||
|
||||
def execute
|
||||
return nil unless group_path
|
||||
|
||||
if group = Group.find_by_full_path(group_path)
|
||||
return group
|
||||
end
|
||||
|
||||
create_group_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_group_path
|
||||
group_path_segments = group_path.split('/')
|
||||
|
||||
last_group = nil
|
||||
partial_path_segments = []
|
||||
while subgroup_name = group_path_segments.shift
|
||||
partial_path_segments << subgroup_name
|
||||
partial_path = partial_path_segments.join('/')
|
||||
|
||||
new_params = params.reverse_merge(
|
||||
path: subgroup_name,
|
||||
name: subgroup_name,
|
||||
parent: last_group
|
||||
)
|
||||
new_params[:visibility_level] ||= Gitlab::CurrentSettings.current_application_settings.default_group_visibility
|
||||
|
||||
last_group = Group.find_by_full_path(partial_path) || Groups::CreateService.new(current_user, new_params).execute
|
||||
end
|
||||
|
||||
last_group
|
||||
end
|
||||
end
|
||||
end
|
|
@ -192,6 +192,8 @@ class IssuableBaseService < BaseService
|
|||
|
||||
def after_create(issuable)
|
||||
# To be overridden by subclasses
|
||||
|
||||
issuable.update_project_counter_caches
|
||||
end
|
||||
|
||||
def before_update(issuable)
|
||||
|
@ -200,6 +202,8 @@ class IssuableBaseService < BaseService
|
|||
|
||||
def after_update(issuable)
|
||||
# To be overridden by subclasses
|
||||
|
||||
issuable.update_project_counter_caches
|
||||
end
|
||||
|
||||
def update(issuable)
|
||||
|
|
|
@ -27,6 +27,8 @@ module Issues
|
|||
todo_service.new_issue(issuable, current_user)
|
||||
user_agent_detail_service.create
|
||||
resolve_discussions_with_issue(issuable)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def resolve_discussions_with_issue(issue)
|
||||
|
|
|
@ -28,6 +28,8 @@ module MergeRequests
|
|||
todo_service.new_merge_request(issuable, current_user)
|
||||
issuable.cache_merge_request_closes_issues!(current_user)
|
||||
update_merge_requests_head_pipeline(issuable)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
|
|
43
app/services/projects/count_service.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
module Projects
|
||||
# Base class for the various service classes that count project data (e.g.
|
||||
# issues or forks).
|
||||
class CountService
|
||||
def initialize(project)
|
||||
@project = project
|
||||
end
|
||||
|
||||
def relation_for_count
|
||||
raise(
|
||||
NotImplementedError,
|
||||
'"relation_for_count" must be implemented and return an ActiveRecord::Relation'
|
||||
)
|
||||
end
|
||||
|
||||
def count
|
||||
Rails.cache.fetch(cache_key) { uncached_count }
|
||||
end
|
||||
|
||||
def refresh_cache
|
||||
Rails.cache.write(cache_key, uncached_count)
|
||||
end
|
||||
|
||||
def uncached_count
|
||||
relation_for_count.count
|
||||
end
|
||||
|
||||
def delete_cache
|
||||
Rails.cache.delete(cache_key)
|
||||
end
|
||||
|
||||
def cache_key_name
|
||||
raise(
|
||||
NotImplementedError,
|
||||
'"cache_key_name" must be implemented and return a String'
|
||||
)
|
||||
end
|
||||
|
||||
def cache_key
|
||||
['projects', @project.id, cache_key_name]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,30 +1,12 @@
|
|||
module Projects
|
||||
# Service class for getting and caching the number of forks of a project.
|
||||
class ForksCountService
|
||||
def initialize(project)
|
||||
@project = project
|
||||
class ForksCountService < CountService
|
||||
def relation_for_count
|
||||
@project.forks
|
||||
end
|
||||
|
||||
def count
|
||||
Rails.cache.fetch(cache_key) { uncached_count }
|
||||
end
|
||||
|
||||
def refresh_cache
|
||||
Rails.cache.write(cache_key, uncached_count)
|
||||
end
|
||||
|
||||
def delete_cache
|
||||
Rails.cache.delete(cache_key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def uncached_count
|
||||
@project.forks.count
|
||||
end
|
||||
|
||||
def cache_key
|
||||
['projects', @project.id, 'forks_count']
|
||||
def cache_key_name
|
||||
'forks_count'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,8 @@ module Projects
|
|||
class HousekeepingService < BaseService
|
||||
include Gitlab::CurrentSettings
|
||||
|
||||
LEASE_TIMEOUT = 3600
|
||||
# Timeout set to 24h
|
||||
LEASE_TIMEOUT = 86400
|
||||
|
||||
class LeaseTaken < StandardError
|
||||
def to_s
|
||||
|
|
15
app/services/projects/open_issues_count_service.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
module Projects
|
||||
# Service class for counting and caching the number of open issues of a
|
||||
# project.
|
||||
class OpenIssuesCountService < CountService
|
||||
def relation_for_count
|
||||
# We don't include confidential issues in this number since this would
|
||||
# expose the number of confidential issues to non project members.
|
||||
@project.issues.opened.public_only
|
||||
end
|
||||
|
||||
def cache_key_name
|
||||
'open_issues_count'
|
||||
end
|
||||
end
|
||||
end
|
13
app/services/projects/open_merge_requests_count_service.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module Projects
|
||||
# Service class for counting and caching the number of open merge requests of
|
||||
# a project.
|
||||
class OpenMergeRequestsCountService < CountService
|
||||
def relation_for_count
|
||||
@project.merge_requests.opened
|
||||
end
|
||||
|
||||
def cache_key_name
|
||||
'open_merge_requests_count'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -35,16 +35,18 @@ module Users
|
|||
Groups::DestroyService.new(group, current_user).execute
|
||||
end
|
||||
|
||||
namespace = user.namespace
|
||||
namespace.prepare_for_destroy
|
||||
|
||||
user.personal_projects.each do |project|
|
||||
# Skip repository removal because we remove directory with namespace
|
||||
# that contain all this repositories
|
||||
::Projects::DestroyService.new(project, current_user, skip_repo: true).execute
|
||||
::Projects::DestroyService.new(project, current_user, skip_repo: project.legacy_storage?).execute
|
||||
end
|
||||
|
||||
MigrateToGhostUserService.new(user).execute unless options[:hard_delete]
|
||||
|
||||
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
|
||||
namespace = user.namespace
|
||||
user_data = user.destroy
|
||||
namespace.really_destroy!
|
||||
|
||||
|
|
|
@ -492,6 +492,16 @@
|
|||
|
||||
%fieldset
|
||||
%legend Repository Storage
|
||||
.form-group
|
||||
.col-sm-offset-2.col-sm-10
|
||||
.checkbox
|
||||
= f.label :hashed_storage_enabled do
|
||||
= f.check_box :hashed_storage_enabled
|
||||
Create new projects using hashed storage paths
|
||||
.help-block
|
||||
Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents
|
||||
repositories from having to be moved or renamed when the Project URL changes and may improve disk I/O performance.
|
||||
%em (EXPERIMENTAL)
|
||||
.form-group
|
||||
= f.label :repository_storages, 'Storage paths for new projects', class: 'control-label col-sm-2'
|
||||
.col-sm-10
|
||||
|
@ -501,6 +511,7 @@
|
|||
= succeed "." do
|
||||
= link_to "repository storages documentation", help_page_path("administration/repository_storages")
|
||||
|
||||
|
||||
%fieldset
|
||||
%legend Repository Checks
|
||||
.form-group
|
||||
|
|
|
@ -1,25 +1,21 @@
|
|||
- @no_container = true
|
||||
- page_title "Logs"
|
||||
- loggers = [Gitlab::GitLogger, Gitlab::AppLogger,
|
||||
Gitlab::EnvironmentLogger, Gitlab::SidekiqLogger,
|
||||
Gitlab::RepositoryCheckLogger]
|
||||
= render 'admin/monitoring/head'
|
||||
|
||||
%div{ class: container_class }
|
||||
%ul.nav-links.log-tabs
|
||||
- loggers.each do |klass|
|
||||
%li{ class: active_when(klass == Gitlab::GitLogger) }>
|
||||
= link_to klass::file_name, "##{klass::file_name_noext}",
|
||||
'data-toggle' => 'tab'
|
||||
- @loggers.each do |klass|
|
||||
%li{ class: active_when(klass == @loggers.first) }>
|
||||
= link_to klass.file_name, "##{klass.file_name_noext}", data: { toggle: 'tab' }
|
||||
.row-content-block
|
||||
To prevent performance issues admin logs output the last 2000 lines
|
||||
.tab-content
|
||||
- loggers.each do |klass|
|
||||
.tab-pane{ class: active_when(klass == Gitlab::GitLogger), id: klass::file_name_noext }
|
||||
- @loggers.each do |klass|
|
||||
.tab-pane{ class: active_when(klass == @loggers.first), id: klass.file_name_noext }
|
||||
.file-holder#README
|
||||
.js-file-title.file-title
|
||||
%i.fa.fa-file
|
||||
= klass::file_name
|
||||
= klass.file_name
|
||||
.pull-right
|
||||
= link_to '#', class: 'log-bottom' do
|
||||
%i.fa.fa-arrow-down
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
%i
|
||||
at
|
||||
= event.created_at.to_s(:short)
|
||||
%blockquote= markdown(escape_once(event.commit_title), pipeline: :atom, project: event.project, author: event.author)
|
||||
- if event.commits_count > 1
|
||||
%p
|
||||
%i
|
||||
\... and
|
||||
= pluralize(event.commits_count - 1, "more commit")
|
||||
- unless event.rm_ref?
|
||||
%blockquote= markdown(escape_once(event.commit_title), pipeline: :atom, project: event.project, author: event.author)
|
||||
- if event.commits_count > 1
|
||||
%p
|
||||
%i
|
||||
\... and
|
||||
= pluralize(event.commits_count - 1, "more commit")
|
||||
|
|
|
@ -41,7 +41,3 @@
|
|||
%li.commits-stat
|
||||
= link_to create_mr_path(project.default_branch, event.ref_name, project) do
|
||||
Create Merge Request
|
||||
- elsif event.rm_ref?
|
||||
.event-body
|
||||
%ul.well-list.event_commits
|
||||
= render "events/commit", project: project, event: event
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
= hidden_field_tag :namespace_id, value: current_user.namespace_id
|
||||
.form-group.col-xs-12.col-sm-6.project-path
|
||||
= label_tag :path, 'Project name', class: 'label-light'
|
||||
= text_field_tag :path, nil, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
|
||||
= text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
|
||||
|
||||
.row
|
||||
.form-group.col-md-12
|
||||
|
@ -33,7 +33,6 @@
|
|||
.row
|
||||
.form-group.col-sm-12
|
||||
= hidden_field_tag :namespace_id, @namespace.id
|
||||
= hidden_field_tag :path, @path
|
||||
= label_tag :file, 'GitLab project export', class: 'label-light'
|
||||
.form-group
|
||||
= file_field_tag :file, class: ''
|
||||
|
|
|
@ -86,7 +86,8 @@
|
|||
%span.nav-item-name
|
||||
Issues
|
||||
- if @project.issues_enabled?
|
||||
%span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
||||
%span.badge.count.issue_counter
|
||||
= number_with_delimiter(@project.open_issues_count)
|
||||
|
||||
%ul.sidebar-sub-level-items
|
||||
= nav_link(controller: :issues) do
|
||||
|
@ -116,7 +117,8 @@
|
|||
= custom_icon('mr_bold')
|
||||
%span.nav-item-name
|
||||
Merge Requests
|
||||
%span.badge.count.merge_counter.js-merge-counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
||||
%span.badge.count.merge_counter.js-merge-counter
|
||||
= number_with_delimiter(@project.open_merge_requests_count)
|
||||
|
||||
- if project_nav_tab? :pipelines
|
||||
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
%span
|
||||
Issues
|
||||
- if @project.issues_enabled?
|
||||
%span.badge.count.issue_counter= number_with_delimiter(issuables_count_for_state(:issues, :opened, finder: IssuesFinder.new(current_user, project_id: @project.id)))
|
||||
%span.badge.count.issue_counter
|
||||
= number_with_delimiter(@project.open_issues_count)
|
||||
|
||||
- if project_nav_tab? :merge_requests
|
||||
- controllers = [:merge_requests, 'projects/merge_requests/conflicts']
|
||||
|
@ -37,7 +38,8 @@
|
|||
= link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
|
||||
%span
|
||||
Merge Requests
|
||||
%span.badge.count.merge_counter.js-merge-counter= number_with_delimiter(issuables_count_for_state(:merge_requests, :opened, finder: MergeRequestsFinder.new(current_user, project_id: @project.id)))
|
||||
%span.badge.count.merge_counter.js-merge-counter
|
||||
= number_with_delimiter(@project.open_merge_requests_count)
|
||||
|
||||
- if project_nav_tab? :pipelines
|
||||
= nav_link(controller: [:pipelines, :builds, :environments, :artifacts]) do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.project-templates-buttons.import-buttons{ data: { toggle: "buttons" } }
|
||||
.btn.blank-option.active
|
||||
%input{ type: "radio", autocomplete: "off", name: "project_templates", id: "blank", checked: "true" }
|
||||
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: "blank", checked: "true", value: "" }
|
||||
= icon('file-o', class: 'btn-template-icon')
|
||||
Blank
|
||||
- Gitlab::ProjectTemplate.all.each do |template|
|
||||
|
|
|
@ -37,14 +37,14 @@
|
|||
|
||||
|
||||
.commit-actions.hidden-xs
|
||||
- if commit.status(ref)
|
||||
= render_commit_status(commit, ref: ref)
|
||||
|
||||
- if request.xhr?
|
||||
= render partial: 'projects/commit/signature', object: commit.signature
|
||||
- else
|
||||
= render partial: 'projects/commit/ajax_signature', locals: { commit: commit }
|
||||
|
||||
- if commit.status(ref)
|
||||
= render_commit_status(commit, ref: ref)
|
||||
|
||||
= link_to commit.short_id, project_commit_path(project, commit), class: "commit-sha btn btn-transparent"
|
||||
= clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard"))
|
||||
= link_to_browse_code(project, commit)
|
||||
|
|
|
@ -202,8 +202,6 @@
|
|||
.sub-section.rename-respository
|
||||
%h4.warning-title
|
||||
Rename repository
|
||||
%p
|
||||
Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.
|
||||
= render 'projects/errors'
|
||||
= form_for([@project.namespace.becomes(Namespace), @project]) do |f|
|
||||
.form-group.project_name_holder
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- content_for :page_specific_javascripts do
|
||||
= page_specific_javascript_bundle_tag('group')
|
||||
- parent = GroupFinder.new(current_user).execute(id: params[:parent_id] || @group.parent_id)
|
||||
- parent = @group.parent
|
||||
- group_path = root_url
|
||||
- group_path << parent.full_path + '/' if parent
|
||||
|
||||
|
@ -13,13 +13,12 @@
|
|||
%span>= root_url
|
||||
- if parent
|
||||
%strong= parent.full_path + '/'
|
||||
= f.hidden_field :parent_id
|
||||
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
|
||||
autofocus: local_assigns[:autofocus] || false, required: true,
|
||||
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
|
||||
title: 'Please choose a group path with no special characters.',
|
||||
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
|
||||
- if parent
|
||||
= f.hidden_field :parent_id, value: parent.id
|
||||
|
||||
- if @group.persisted?
|
||||
.alert.alert-warning.prepend-top-10
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><g fill-rule="evenodd"><path fill-rule="nonzero" d="m0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7m1 0c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6"/><path d="m7 6h-2.702c-.154 0-.298.132-.298.295v1.41c0 .164.133.295.298.295h2.702v1.694c0 .18.095.209.213.09l2.539-2.568c.115-.116.118-.312 0-.432l-2.539-2.568c-.115-.116-.213-.079-.213.09v1.694"/></g></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 6h-7a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586a1 1 0 0 0 -1.707.707z" fill-rule="evenodd"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 237 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1472 930v318q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-10 10-23 10-3 0-9-2-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-254q0-13 9-22l64-64q10-10 23-10 6 0 12 3 20 8 20 29zm231-489l-814 814q-24 24-57 24t-57-24l-430-430q-24-24-24-57t24-57l110-110q24-24 57-24t57 24l263 263 647-647q24-24 57-24t57 24l110 110q24 24 24 57t-24 57z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 373 B |
|
@ -1 +1 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1024 544v448q0 14-9 23t-23 9h-320q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h224v-352q0-14 9-23t23-9h64q14 0 23 9t9 23zm416 352q0-148-73-273t-198-198-273-73-273 73-198 198-73 273 73 273 198 198 273 73 273-73 198-198 73-273zm224 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1c.552 0 1 .448 1 1s-.448 1-1 1H8c-.276 0-.526-.112-.707-.293S7 8.277 7 8V5c0-.552.448-1 1-1s1 .448 1 1zm-1 9c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
|
||||
|
|
Before Width: | Height: | Size: 469 B After Width: | Height: | Size: 336 B |
|
@ -1,3 +1,2 @@
|
|||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" viewBox="0 0 14 14">
|
||||
<path d="M13 12.75v-8.5q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h8.5q0.102 0 0.176-0.074t0.074-0.176zM14 4.25v8.5q0 0.516-0.367 0.883t-0.883 0.367h-8.5q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883zM11 1.25v1.25h-1v-1.25q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h1.25v1h-1.25q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883z"></path>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 735 B After Width: | Height: | Size: 421 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M672 1472q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm0-1152q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm640 128q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm96 0q0 52-26 96.5t-70 69.5q-2 287-226 414-68 38-203 81-128 40-169.5 71t-41.5 100v26q44 25 70 69.5t26 96.5q0 80-56 136t-136 56-136-56-56-136q0-52 26-96.5t70-69.5v-820q-44-25-70-69.5t-26-96.5q0-80 56-136t136-56 136 56 56 136q0 52-26 96.5t-70 69.5v497q54-26 154-57 55-17 87.5-29.5t70.5-31 59-39.5 40.5-51 28-69.5 8.5-91.5q-44-25-70-69.5t-26-96.5q0-80 56-136t136-56 136 56 56 136z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 676 B After Width: | Height: | Size: 409 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M896 384q-204 0-381.5 69.5t-282 187.5-104.5 255q0 112 71.5 213.5t201.5 175.5l87 50-27 96q-24 91-70 172 152-63 275-171l43-38 57 6q69 8 130 8 204 0 381.5-69.5t282-187.5 104.5-255-104.5-255-282-187.5-381.5-69.5zm896 512q0 174-120 321.5t-326 233-450 85.5q-70 0-145-8-198 175-460 242-49 14-114 22h-5q-15 0-27-10.5t-16-27.5v-1q-3-4-.5-12t2-10 4.5-9.5l6-9 7-8.5 8-9q7-8 31-34.5t34.5-38 31-39.5 32.5-51 27-59 26-76q-157-89-247.5-220t-90.5-281q0-174 120-321.5t326-233 450-85.5 450 85.5 326 233 120 321.5z"/></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.707 15.707c-.63.63-1.707.184-1.707-.707v-12a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1 -3 3h-7.586zm.293-3.121 2.293-2.293a1 1 0 0 1 .707-.293h8a1 1 0 0 0 1-1v-6a1 1 0 0 0 -1-1h-10a1 1 0 0 0 -1 1z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 605 B After Width: | Height: | Size: 303 B |
|
@ -1 +1,2 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 18" enable-background="new 0 0 36 18"><path d="m34 7h-7.2c-.9-4-4.5-7-8.8-7s-7.9 3-8.8 7h-7.2c-1.1 0-2 .9-2 2 0 1.1.9 2 2 2h7.2c.9 4 4.5 7 8.8 7s7.9-3 8.8-7h7.2c1.1 0 2-.9 2-2 0-1.1-.9-2-2-2m-16 7c-2.8 0-5-2.2-5-5s2.2-5 5-5 5 2.2 5 5-2.2 5-5 5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3.876-1.008a4.002 4.002 0 0 1-7.752 0A1.01 1.01 0 0 1 4 9H1a1 1 0 1 1 0-2h3c.042 0 .083.003.124.008a4.002 4.002 0 0 1 7.752 0A1.01 1.01 0 0 1 12 7h3a1 1 0 0 1 0 2h-3a1.01 1.01 0 0 1-.124-.008z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 330 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M888 1184l116-116-152-152-116 116v56h96v96h56zm440-720q-16-16-33 1l-350 350q-17 17-1 33t33-1l350-350q17-17 1-33zm80 594v190q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-14 14-32 8-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-126q0-13 9-22l64-64q15-15 35-7t20 29zm-96-738l288 288-672 672h-288v-288zm444 132l-92 92-288-288 92-92q28-28 68-28t68 28l152 152q28 28 28 68t-28 68z"/></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.436 1.413 1.415 1.414a1 1 0 0 1 0 1.414l-10.316 10.315a1 1 0 0 1 -.703.293l-2.407.008-.008-2.421a1 1 0 0 1 .293-.71l10.312-10.314a1 1 0 0 1 1.414 0zm-9.608 12.436 10.315-10.315-1.413-1.414-10.313 10.312.005 1.422zm7.486-10.313 1.414 1.414-7.778 7.778-1.407.007-.007-1.421zm1.414-1.415 1.414 1.415-.707.707-1.414-1.415z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 617 B After Width: | Height: | Size: 426 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5t-316.5 131.5-316.5-131.5-131.5-316.5q0-121 61-225-229 117-381 353 133 205 333.5 326.5t434.5 121.5 434.5-121.5 333.5-326.5zm-720-384q0-20-14-34t-34-14q-125 0-214.5 89.5t-89.5 214.5q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5t-499.5 138.5-499.5-139-376.5-368q-20-35-20-69t20-69q140-229 376.5-368t499.5-139 499.5 139 376.5 368q20 35 20 69z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 428 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M555 1335l78-141q-87-63-136-159t-49-203q0-121 61-225-229 117-381 353 167 258 427 375zm389-759q0-20-14-34t-34-14q-125 0-214.5 89.5t-89.5 214.5q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm363-191q0 7-1 9-105 188-315 566t-316 567l-49 89q-10 16-28 16-12 0-134-70-16-10-16-28 0-12 44-87-143-65-263.5-173t-208.5-245q-20-31-20-69t20-69q153-235 380-371t496-136q89 0 180 17l54-97q10-16 28-16 5 0 18 6t31 15.5 33 18.5 31.5 18.5 19.5 11.5q16 10 16 27zm37 447q0 139-79 253.5t-209 164.5l280-502q8 45 8 84zm448 128q0 35-20 69-39 64-109 145-150 172-347.5 267t-419.5 95l74-132q212-18 392.5-137t301.5-307q-115-179-282-294l63-112q95 64 182.5 153t144.5 184q20 34 20 69z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 782 B After Width: | Height: | Size: 690 B |
|
@ -1 +1,2 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m2 3c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1m.761.85c.154 2.556 1.987 4.692 4.45 5.255.328-.655 1.01-1.105 1.789-1.105 1.105 0 2 .895 2 2 0 1.105-.895 2-2 2-.89 0-1.645-.582-1.904-1.386-1.916-.376-3.548-1.5-4.596-3.044v4.493c.863.222 1.5 1.01 1.5 1.937 0 1.105-.895 2-2 2-1.105 0-2-.895-2-2 0-.74.402-1.387 1-1.732v-8.535c-.598-.346-1-.992-1-1.732 0-1.105.895-2 2-2 1.105 0 2 .895 2 2 0 .835-.512 1.551-1.239 1.85m6.239 7.15c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1m-7 4c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1" transform="translate(3)"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 706 B After Width: | Height: | Size: 377 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 373 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M666 481q-60 92-137 273-22-45-37-72.5t-40.5-63.5-51-56.5-63-35-81.5-14.5h-224q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h224q250 0 410 225zm1126 799q0 14-9 23l-320 320q-9 9-23 9-13 0-22.5-9.5t-9.5-22.5v-192q-32 0-85 .5t-81 1-73-1-71-5-64-10.5-63-18.5-58-28.5-59-40-55-53.5-56-69.5q59-93 136-273 22 45 37 72.5t40.5 63.5 51 56.5 63 35 81.5 14.5h256v-192q0-14 9-23t23-9q12 0 24 10l319 319q9 9 9 23zm0-896q0 14-9 23l-320 320q-9 9-23 9-13 0-22.5-9.5t-9.5-22.5v-192h-256q-48 0-87 15t-69 45-51 61.5-45 77.5q-32 62-78 171-29 66-49.5 111t-54 105-64 100-74 83-90 68.5-106.5 42-128 16.5h-224q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h224q48 0 87-15t69-45 51-61.5 45-77.5q32-62 78-171 29-66 49.5-111t54-105 64-100 74-83 90-68.5 106.5-42 128-16.5h256v-192q0-14 9-23t23-9q12 0 24 10l319 319q9 9 9 23z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 885 B After Width: | Height: | Size: 402 B |
|
@ -1 +1 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7z"/><path d="M1 7c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6z" fill="#FFF"/><rect x="3.36" y="6.16" width="7.28" height="1.68" rx=".84"/></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.83c.39-.39 1.024-.39 1.414 0 .39.392.39 1.025 0 1.416l-3.535 3.535c-.196.195-.452.293-.707.293-.256 0-.512-.097-.708-.292l-2.12-2.12c-.39-.392-.39-1.025 0-1.415s1.023-.39 1.413 0zM8 16c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
|
||||
|
|
Before Width: | Height: | Size: 353 B After Width: | Height: | Size: 427 B |
|
@ -1 +1,2 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M384 448q0-53-37.5-90.5t-90.5-37.5-90.5 37.5-37.5 90.5 37.5 90.5 90.5 37.5 90.5-37.5 37.5-90.5zm1067 576q0 53-37 90l-491 492q-39 37-91 37-53 0-90-37l-715-716q-38-37-64.5-101t-26.5-117v-416q0-52 38-90t90-38h416q53 0 117 26.5t102 64.5l715 714q37 39 37 91zm384 0q0 53-37 90l-491 492q-39 37-91 37-36 0-59-14t-53-45l470-470q37-37 37-90 0-52-37-91l-715-714q-38-38-102-64.5t-117-26.5h224q53 0 117 26.5t102 64.5l715 714q37 39 37 91z"/></svg>
|
||||
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m7.222.222c1.657 0 3 1.343 3 3v8.327c0 .631-.298 1.226-.805 1.603l-3 2.237c-.709.529-1.682.529-2.391 0l-3-2.237c-.506-.377-.805-.972-.805-1.603v-8.327c0-1.657 1.343-3 3-3h4m-5 3v8.08c0 .158.075.306.201.401l2.5 1.864c.177.132.42.132.598 0l2.5-1.864c.127-.094.201-.243.201-.401v-8.08c0-.552-.448-1-1-1h-4c-.552 0-1 .448-1 1m2.778 7.778c-.552 0-1-.448-1-1s .448-1 1-1 1 .448 1 1-.448 1-1 1" transform="matrix(-.70711 .70711 -.70711 -.70711 17.05 9.767)"/></svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 529 B |
|
@ -1 +1 @@
|
|||
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1600 1405q0 120-73 189.5t-194 69.5h-874q-121 0-194-69.5t-73-189.5q0-53 3.5-103.5t14-109 26.5-108.5 43-97.5 62-81 85.5-53.5 111.5-20q9 0 42 21.5t74.5 48 108 48 133.5 21.5 133.5-21.5 108-48 74.5-48 42-21.5q61 0 111.5 20t85.5 53.5 62 81 43 97.5 26.5 108.5 14 109 3.5 103.5zm-320-893q0 159-112.5 271.5t-271.5 112.5-271.5-112.5-112.5-271.5 112.5-271.5 271.5-112.5 271.5 112.5 112.5 271.5z"/></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 7C6.343 7 5 5.657 5 4s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48S14.888 15 8 15z" fill-rule="evenodd"/></svg>
|
||||
|
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 268 B |
|
@ -4,7 +4,7 @@
|
|||
%li.filter-dropdown-item{ class: ('js-current-user' if user == current_user) }
|
||||
%button.btn.btn-link.dropdown-user{ type: :button }
|
||||
.avatar-container.s40
|
||||
= user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40).gsub('/images/{{avatar_url}}','{{avatar_url}}').html_safe
|
||||
= user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40, has_tooltip: false).gsub('/images/{{avatar_url}}','{{avatar_url}}').html_safe
|
||||
.dropdown-user-details
|
||||
%span
|
||||
= user.name
|
||||
|
|
|
@ -4,18 +4,25 @@ class AuthorizedProjectsWorker
|
|||
|
||||
# Schedules multiple jobs and waits for them to be completed.
|
||||
def self.bulk_perform_and_wait(args_list)
|
||||
job_ids = bulk_perform_async(args_list)
|
||||
waiter = Gitlab::JobWaiter.new(args_list.size)
|
||||
|
||||
Gitlab::JobWaiter.new(job_ids).wait
|
||||
# Point all the bulk jobs at the same JobWaiter. Converts, [[1], [2], [3]]
|
||||
# into [[1, "key"], [2, "key"], [3, "key"]]
|
||||
waiting_args_list = args_list.map { |args| args << waiter.key }
|
||||
bulk_perform_async(waiting_args_list)
|
||||
|
||||
waiter.wait
|
||||
end
|
||||
|
||||
def self.bulk_perform_async(args_list)
|
||||
Sidekiq::Client.push_bulk('class' => self, 'queue' => sidekiq_options['queue'], 'args' => args_list)
|
||||
end
|
||||
|
||||
def perform(user_id)
|
||||
def perform(user_id, notify_key = nil)
|
||||
user = User.find_by(id: user_id)
|
||||
|
||||
user&.refresh_authorized_projects
|
||||
ensure
|
||||
Gitlab::JobWaiter.notify(notify_key, jid) if notify_key
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,8 @@ class NamespacelessProjectDestroyWorker
|
|||
rescue ActiveRecord::RecordNotFound
|
||||
return
|
||||
end
|
||||
return unless project.namespace_id.nil? # Reject doing anything for projects that *do* have a namespace
|
||||
|
||||
return if project.namespace # Reject doing anything for projects that *do* have a namespace
|
||||
|
||||
project.team.truncate
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "Insert user name directly without encoding"
|
||||
merge_request: 10085
|
||||
author: Nathan Neulinger <nneul@neulinger.org>
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Expose target_iid in Events API
|
||||
merge_request: 13247
|
||||
author: sue445
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Expose noteable_iid in Note
|
||||
merge_request: 13265
|
||||
author: sue445
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes.
|
||||
merge_request: 9707
|
||||
author: Hiroyuki Sato
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Remove Inactive Personal Access Tokens list from Access Tokens page
|
||||
merge_request: 12866
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Add coordinator url to admin area runner page
|
||||
merge_request: 11603
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Declare related resources into V4 API entities
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Replaces dashboard/event_filters.feature spinach with rspec
|
||||
merge_request: 12651
|
||||
author: Alexander Randa (@randaalex)
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Replaces dashboard/dashboard.feature spinach with rspec
|
||||
merge_request: 12876
|
||||
author: Alexander Randa (@randaalex)
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Added /duplicate quick action to close a duplicate issue
|
||||
merge_request: 12845
|
||||
author: Ryan Scott
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Fix timezone inconsistencies in user contribution graph
|
||||
merge_request: 13208
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Decrease ABC threshold to 56.96
|
||||
merge_request: 11227
|
||||
author: Maxim Rydkin
|
4
changelogs/unreleased/28283-uuid-storage.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Hashed Storage support for Repositories (EXPERIMENTAL)
|
||||
merge_request: 13246
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Don't send rejection mails for all auto-generated mails
|
||||
merge_request: 13254
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Handle errors while a project is being deleted asynchronously.
|
||||
merge_request: 11088
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Add /shrug and /tableflip commands
|
||||
merge_request: 10068
|
||||
author: Alex Ives
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: refactor initializations in dropzone_input.js
|
||||
merge_request: 12768
|
||||
author: Brandon Everett
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Disallow running the pipeline if ref is protected and user cannot merge the
|
||||
branch or create the tag
|
||||
merge_request: 11910
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Remove project_key from the Jira configuration
|
||||
merge_request: 12050
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Unlock stuck merge request and set the proper state
|
||||
merge_request: 13207
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Add Slack and JIRA services counts to Usage Data
|
||||
merge_request:
|
||||
author:
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Prevent web hook and project service background jobs from going to the dead
|
||||
jobs queue
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Display specific error message when JIRA test fails
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Move some code from services to workers in order to improve performance
|
||||
merge_request: 13326
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: clean up merge request widget UI
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Associate Issues tab only with internal issues tracker
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Add CSRF token verification to API
|
||||
merge_request: 12154
|
||||
author: Vitaliy @blackst0ne Klachkov
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Remove events column from notification settings table
|
||||
merge_request:
|
||||
author:
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Clarifies and rearranges the input variables on the kubernetes integration
|
||||
page and adjusts the docs slightly to meet the same order
|
||||
merge_request: !12188
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Respect blockquote line breaks in markdown
|
||||
merge_request:
|
||||
author:
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Update confidential issue UI - add confidential visibility and settings to
|
||||
sidebar
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Add icons to contextual sidebars
|
||||
merge_request:
|
||||
author:
|