Resolve conflicts with latest workflow label changes
This commit is contained in:
commit
3e28cca574
|
|
@ -815,8 +815,6 @@ lint:javascript:report:
|
|||
- setup-test-env
|
||||
before_script: []
|
||||
script:
|
||||
- date
|
||||
- find app/ spec/ -name '*.js' -exec sed --in-place 's|/\* eslint-disable .*\*/||' {} \; # run report over all files
|
||||
- date
|
||||
- yarn run eslint-report || true # ignore exit code
|
||||
artifacts:
|
||||
|
|
|
|||
|
|
@ -27,25 +27,26 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
|
|||
- [Helping others](#helping-others)
|
||||
- [I want to contribute!](#i-want-to-contribute)
|
||||
- [Workflow labels](#workflow-labels)
|
||||
- [Type labels (~"feature proposal", ~bug, ~customer, etc.)](#type-labels-feature-proposal-bug-customer-etc)
|
||||
- [Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)](#subject-labels-wiki-container-registry-ldap-api-etc)
|
||||
- [Team labels (~"CI/CD", ~Discussion, ~Quality, ~Platform, etc.)](#team-labels-cicd-discussion-quality-platform-etc)
|
||||
- [Release Scoping labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#milestone-labels-deliverable-stretch-next-patch-release)
|
||||
- [Priority labels (~P1, ~P2, ~P3 , ~P4)](#bug-priority-labels-p1-p2-p3-p4)
|
||||
- [Severity labels (~S1, ~S2, ~S3 , ~S4)](#bug-severity-labels-s1-s2-s3-s4)
|
||||
- [Label for community contributors (~"Accepting Merge Requests")](#label-for-community-contributors-accepting-merge-requests)
|
||||
- [Implement design & UI elements](#implement-design--ui-elements)
|
||||
- [Type labels](#type-labels)
|
||||
- [Subject labels](#subject-labels)
|
||||
- [Team labels](#team-labels)
|
||||
- [Release Scoping labels](#release-scoping-labels)
|
||||
- [Bug Priority labels](#bug-priority-labels)
|
||||
- [Bug Severity labels](#bug-severity-labels)
|
||||
- [Severity impact guidance](#severity-impact-guidance)
|
||||
- [Label for community contributors](#label-for-community-contributors)
|
||||
- [Implement design & UI elements](#implement-design-ui-elements)
|
||||
- [Issue tracker](#issue-tracker)
|
||||
- [Issue triaging](#issue-triaging)
|
||||
- [Feature proposals](#feature-proposals)
|
||||
- [Issue tracker guidelines](#issue-tracker-guidelines)
|
||||
- [Issue weight](#issue-weight)
|
||||
- [Regression issues](#regression-issues)
|
||||
- [Technical and UX debt](#technical-and-ux-debt)
|
||||
- [Stewardship](#stewardship)
|
||||
- [Issue triaging](#issue-triaging)
|
||||
- [Feature proposals](#feature-proposals)
|
||||
- [Issue tracker guidelines](#issue-tracker-guidelines)
|
||||
- [Issue weight](#issue-weight)
|
||||
- [Regression issues](#regression-issues)
|
||||
- [Technical and UX debt](#technical-and-ux-debt)
|
||||
- [Stewardship](#stewardship)
|
||||
- [Merge requests](#merge-requests)
|
||||
- [Merge request guidelines](#merge-request-guidelines)
|
||||
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
|
||||
- [Merge request guidelines](#merge-request-guidelines)
|
||||
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
|
||||
- [Definition of done](#definition-of-done)
|
||||
- [Style guides](#style-guides)
|
||||
- [Code of conduct](#code-of-conduct)
|
||||
|
|
@ -145,7 +146,7 @@ labels, you can _always_ add the team and type, and often also the subject.
|
|||
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
|
||||
[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
|
||||
|
||||
### Type labels (~"feature proposal", ~bug, ~customer, etc.)
|
||||
### Type labels
|
||||
|
||||
Type labels are very important. They define what kind of issue this is. Every
|
||||
issue should have one or more.
|
||||
|
|
@ -161,28 +162,41 @@ already reserved for subject labels).
|
|||
|
||||
The descriptions on the [labels page][labels-page] explain what falls under each type label.
|
||||
|
||||
### Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)
|
||||
### Subject labels
|
||||
|
||||
Subject labels are labels that define what area or feature of GitLab this issue
|
||||
hits. They are not always necessary, but very convenient.
|
||||
|
||||
Examples of subject labels are ~wiki, ~ldap, ~api,
|
||||
~issues, ~"merge requests", ~labels, and ~"container registry".
|
||||
|
||||
If you are an expert in a particular area, it makes it easier to find issues to
|
||||
work on. You can also subscribe to those labels to receive an email each time an
|
||||
issue is labeled with a subject label corresponding to your expertise.
|
||||
|
||||
Examples of subject labels are ~wiki, ~"container registry", ~ldap, ~api,
|
||||
~issues, ~"merge requests", ~labels, and ~"container registry".
|
||||
|
||||
Subject labels are always all-lowercase.
|
||||
|
||||
### Team labels (~"CI/CD", ~Discussion, ~Quality, ~Platform, etc.)
|
||||
### Team labels
|
||||
|
||||
Team labels specify what team is responsible for this issue.
|
||||
Assigning a team label makes sure issues get the attention of the appropriate
|
||||
people.
|
||||
|
||||
The current team labels are ~Distribution, ~"CI/CD", ~Discussion, ~Documentation, ~Quality,
|
||||
~Geo, ~Gitaly, ~Monitoring, ~Platform, ~Release, ~"Security Products", ~"Configuration", and ~"UX".
|
||||
The current team labels are:
|
||||
|
||||
- ~Configuration
|
||||
- ~"CI/CD"
|
||||
- ~Discussion
|
||||
- ~Distribution
|
||||
- ~Documentation
|
||||
- ~Geo
|
||||
- ~Gitaly
|
||||
- ~Monitoring
|
||||
- ~Platform
|
||||
- ~Quality
|
||||
- ~Release
|
||||
- ~"Security Products"
|
||||
- ~UX
|
||||
|
||||
The descriptions on the [labels page][labels-page] explain what falls under the
|
||||
responsibility of each team.
|
||||
|
|
@ -193,7 +207,7 @@ indicate if an issue needs backend work, frontend work, or both.
|
|||
Team labels are always capitalized so that they show up as the first label for
|
||||
any issue.
|
||||
|
||||
### Release Scoping labels (~Deliverable, ~Stretch, ~"Next Patch Release")
|
||||
### Release Scoping labels
|
||||
|
||||
Release Scoping labels help us clearly communicate expectations of the work for the
|
||||
release. There are three levels of Release Scoping labels:
|
||||
|
|
@ -211,9 +225,9 @@ Each issue scheduled for the current milestone should be labeled ~Deliverable
|
|||
or ~"Stretch". Any open issue for a previous milestone should be labeled
|
||||
~"Next Patch Release", or otherwise rescheduled to a different milestone.
|
||||
|
||||
### Bug Priority labels (~P1, ~P2, ~P3, ~P4)
|
||||
### Bug Priority labels
|
||||
|
||||
Bug Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be.
|
||||
Bug Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be.
|
||||
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
|
||||
This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes.
|
||||
|
||||
|
|
@ -224,7 +238,7 @@ This label documents the planned timeline & urgency which is used to measure aga
|
|||
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) | |
|
||||
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) | The issue is prominent but does not impact user workflow and a workaround is documented |
|
||||
|
||||
### Bug Severity labels (~S1, ~S2, ~S3, ~S4)
|
||||
### Bug Severity labels
|
||||
|
||||
Severity labels help us clearly communicate the impact of a ~bug on users.
|
||||
|
||||
|
|
@ -240,11 +254,11 @@ Severity labels help us clearly communicate the impact of a ~bug on users.
|
|||
| Label | Security Impact | Availability / Performance Impact |
|
||||
|-------|---------------------------------------------------------------------|--------------------------------------------------------------|
|
||||
| ~S1 | >50% users impacted (possible company extinction level event) | |
|
||||
| ~S2 | Many users or multiple paid customers impacted (but not apocalyptic)| The issue is (almost) guaranteed to occur in the near future |
|
||||
| ~S2 | Many users or multiple paid customers impacted (but not apocalyptic)| The issue is (almost) guaranteed to occur in the near future |
|
||||
| ~S3 | A few users or a single paid customer impacted | The issue is likely to occur in the near future |
|
||||
| ~S4 | No paid users/customer impacted, or expected impact within 30 days | The issue _may_ occur but it's not likely |
|
||||
|
||||
### Label for community contributors (~"Accepting Merge Requests")
|
||||
### Label for community contributors
|
||||
|
||||
Issues that are beneficial to our users, 'nice to haves', that we currently do
|
||||
not have the capacity for or want to give the priority to, are labeled as
|
||||
|
|
@ -300,14 +314,14 @@ For guidance on UX implementation at GitLab, please refer to our [Design System]
|
|||
|
||||
The UX team uses labels to manage their workflow.
|
||||
|
||||
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
|
||||
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
|
||||
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux) of the handbook.
|
||||
|
||||
Once an issue has been worked on and is ready for development, a UXer removes the ~"UX" label and applies the ~"UX ready" label to that issue.
|
||||
|
||||
The UX team has a special type label called ~"design artifact". This label indicates that the final output
|
||||
The UX team has a special type label called ~"design artifact". This label indicates that the final output
|
||||
for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone.
|
||||
Any issue labeled ~"design artifact" should not also be labeled ~"frontend" or ~"backend" since no development is
|
||||
Any issue labeled ~"design artifact" should not also be labeled ~"frontend" or ~"backend" since no development is
|
||||
needed until the solution has been decided.
|
||||
|
||||
~"design artifact" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0.105.1
|
||||
0.107.0
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -419,7 +419,7 @@ group :ed25519 do
|
|||
end
|
||||
|
||||
# Gitaly GRPC client
|
||||
gem 'gitaly-proto', '~> 0.101.0', require: 'gitaly'
|
||||
gem 'gitaly-proto', '~> 0.102.0', require: 'gitaly'
|
||||
gem 'grpc', '~> 1.11.0'
|
||||
|
||||
# Locked until https://github.com/google/protobuf/issues/4210 is closed
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ GEM
|
|||
gettext_i18n_rails (>= 0.7.1)
|
||||
po_to_json (>= 1.0.0)
|
||||
rails (>= 3.2.0)
|
||||
gitaly-proto (0.101.0)
|
||||
gitaly-proto (0.102.0)
|
||||
google-protobuf (~> 3.1)
|
||||
grpc (~> 1.10)
|
||||
github-linguist (5.3.3)
|
||||
|
|
@ -803,7 +803,7 @@ GEM
|
|||
rubyzip (1.2.1)
|
||||
rufus-scheduler (3.4.0)
|
||||
et-orbi (~> 1.0)
|
||||
rugged (0.27.1)
|
||||
rugged (0.27.2)
|
||||
safe_yaml (1.0.4)
|
||||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
|
|
@ -1039,7 +1039,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.2.2)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.3)
|
||||
gitaly-proto (~> 0.101.0)
|
||||
gitaly-proto (~> 0.102.0)
|
||||
github-linguist (~> 5.3.3)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-gollum-lib (~> 4.2)
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ GEM
|
|||
gettext_i18n_rails (>= 0.7.1)
|
||||
po_to_json (>= 1.0.0)
|
||||
rails (>= 3.2.0)
|
||||
gitaly-proto (0.101.0)
|
||||
gitaly-proto (0.102.0)
|
||||
google-protobuf (~> 3.1)
|
||||
grpc (~> 1.10)
|
||||
github-linguist (5.3.3)
|
||||
|
|
@ -1049,7 +1049,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.2.2)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.3)
|
||||
gitaly-proto (~> 0.101.0)
|
||||
gitaly-proto (~> 0.102.0)
|
||||
github-linguist (~> 5.3.3)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-gollum-lib (~> 4.2)
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ export default class CreateMergeRequestDropdown {
|
|||
removeMessage(target) {
|
||||
const { input, message } = this.getTargetData(target);
|
||||
const inputClasses = ['gl-field-error-outline', 'gl-field-success-outline'];
|
||||
const messageClasses = ['gl-field-hint', 'gl-field-error-message', 'gl-field-success-message'];
|
||||
const messageClasses = ['text-muted', 'text-danger', 'text-success'];
|
||||
|
||||
inputClasses.forEach(cssClass => input.classList.remove(cssClass));
|
||||
messageClasses.forEach(cssClass => message.classList.remove(cssClass));
|
||||
|
|
@ -393,7 +393,7 @@ export default class CreateMergeRequestDropdown {
|
|||
|
||||
this.removeMessage(target);
|
||||
input.classList.add('gl-field-success-outline');
|
||||
message.classList.add('gl-field-success-message');
|
||||
message.classList.add('text-success');
|
||||
message.textContent = sprintf(__('%{text} is available'), { text });
|
||||
message.style.display = 'inline-block';
|
||||
}
|
||||
|
|
@ -403,7 +403,7 @@ export default class CreateMergeRequestDropdown {
|
|||
const text = target === 'branch' ? __('branch name') : __('source');
|
||||
|
||||
this.removeMessage(target);
|
||||
message.classList.add('gl-field-hint');
|
||||
message.classList.add('text-muted');
|
||||
message.textContent = sprintf(__('Checking %{text} availability…'), { text });
|
||||
message.style.display = 'inline-block';
|
||||
}
|
||||
|
|
@ -415,7 +415,7 @@ export default class CreateMergeRequestDropdown {
|
|||
|
||||
this.removeMessage(target);
|
||||
input.classList.add('gl-field-error-outline');
|
||||
message.classList.add('gl-field-error-message');
|
||||
message.classList.add('text-danger');
|
||||
message.textContent = text;
|
||||
message.style.display = 'inline-block';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,6 @@ export default {
|
|||
:author="author"
|
||||
:created-at="note.created_at"
|
||||
:note-id="note.id"
|
||||
action-text="commented"
|
||||
/>
|
||||
<note-actions
|
||||
:author-id="author.id"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<script>
|
||||
import { __ } from '~/locale';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
|
||||
/**
|
||||
* Port of detail_behavior expand button.
|
||||
*
|
||||
|
|
@ -12,6 +14,9 @@ import { __ } from '~/locale';
|
|||
*/
|
||||
export default {
|
||||
name: 'ExpandButton',
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isCollapsed: true,
|
||||
|
|
@ -22,6 +27,9 @@ export default {
|
|||
return __('Click to expand text');
|
||||
},
|
||||
},
|
||||
destroyed() {
|
||||
this.isCollapsed = true;
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
|
|
@ -37,7 +45,10 @@ export default {
|
|||
type="button"
|
||||
class="text-expander btn-blank"
|
||||
@click="onClick">
|
||||
...
|
||||
<icon
|
||||
:size="12"
|
||||
name="ellipsis_h"
|
||||
/>
|
||||
</button>
|
||||
<span v-if="!isCollapsed">
|
||||
<slot name="expanded"></slot>
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ a {
|
|||
color: $gl-link-color;
|
||||
}
|
||||
|
||||
a:not(.btn):focus,
|
||||
a:not(.btn):active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
hr {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@
|
|||
&:focus {
|
||||
background: $link-active-background;
|
||||
color: $gl-text-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,10 @@ label {
|
|||
}
|
||||
|
||||
.gl-show-field-errors {
|
||||
.form-control {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.gl-field-success-outline {
|
||||
border: 1px solid $green-600;
|
||||
|
||||
|
|
|
|||
|
|
@ -135,10 +135,10 @@
|
|||
}
|
||||
|
||||
.text-expander {
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
background: $white-light;
|
||||
color: $gl-text-color-secondary;
|
||||
padding: 0 4px;
|
||||
padding: 1px $gl-padding-4;
|
||||
cursor: pointer;
|
||||
border: 1px solid $border-gray-dark;
|
||||
border-radius: $border-radius-default;
|
||||
|
|
@ -180,6 +180,11 @@
|
|||
.commit-content {
|
||||
padding-right: 10px;
|
||||
white-space: normal;
|
||||
|
||||
.commit-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.commit-actions {
|
||||
|
|
@ -253,7 +258,6 @@
|
|||
.generic_commit_status {
|
||||
a,
|
||||
button {
|
||||
color: $gl-text-color;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
.btn {
|
||||
font-size: $gl-font-size;
|
||||
max-height: 26px;
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.3;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class Admin::HooksController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
@hook = SystemHook.new(hook_params)
|
||||
@hook = SystemHook.new(hook_params.to_h)
|
||||
|
||||
if @hook.save
|
||||
redirect_to admin_hooks_path, notice: 'Hook was successfully created.'
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
module UploadsActions
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include SendFileUpload
|
||||
|
||||
UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze
|
||||
|
||||
included do
|
||||
prepend_before_action :set_html_format, only: :show
|
||||
end
|
||||
|
||||
def create
|
||||
link_to_file = UploadService.new(model, params[:file], uploader_class).execute
|
||||
|
||||
|
|
@ -41,6 +47,13 @@ module UploadsActions
|
|||
|
||||
private
|
||||
|
||||
# Explicitly set the format.
|
||||
# Otherwise rails 5 will set it from a file extension.
|
||||
# See https://github.com/rails/rails/commit/84e8accd6fb83031e4c27e44925d7596655285f7#diff-2b8f2fbb113b55ca8e16001c393da8f1
|
||||
def set_html_format
|
||||
request.format = :html
|
||||
end
|
||||
|
||||
def uploader_class
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class DashboardController < Dashboard::ApplicationController
|
|||
return unless @no_filters_set
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.html { render }
|
||||
format.atom { head :bad_request }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
render
|
||||
# https://gitlab.com/gitlab-org/gitlab-ce/issues/48097
|
||||
Gitlab::GitalyClient.allow_n_plus_1_calls do
|
||||
render
|
||||
end
|
||||
end
|
||||
format.json do
|
||||
branches = BranchesFinder.new(@repository, params).execute
|
||||
|
|
|
|||
|
|
@ -247,13 +247,13 @@ class ProjectsController < Projects::ApplicationController
|
|||
|
||||
if find_branches
|
||||
branches = BranchesFinder.new(@repository, params).execute.take(100).map(&:name)
|
||||
options[s_('RefSwitcher|Branches')] = branches
|
||||
options['Branches'] = branches
|
||||
end
|
||||
|
||||
if find_tags && @repository.tag_count.nonzero?
|
||||
tags = TagsFinder.new(@repository, params).execute.take(100).map(&:name)
|
||||
|
||||
options[s_('RefSwitcher|Tags')] = tags
|
||||
options['Tags'] = tags
|
||||
end
|
||||
|
||||
# If reference is commit id - we should add it to branch/tag selectbox
|
||||
|
|
|
|||
|
|
@ -407,6 +407,7 @@ module ProjectsHelper
|
|||
@ref || @repository.try(:root_ref)
|
||||
end
|
||||
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/1235
|
||||
def sanitize_repo_path(project, message)
|
||||
return '' unless message.present?
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ module Clusters
|
|||
class Prometheus < ActiveRecord::Base
|
||||
include PrometheusAdapter
|
||||
|
||||
VERSION = "2.0.0".freeze
|
||||
VERSION = '6.7.3'.freeze
|
||||
|
||||
self.table_name = 'clusters_applications_prometheus'
|
||||
|
||||
|
|
@ -37,6 +37,7 @@ module Clusters
|
|||
Gitlab::Kubernetes::Helm::InstallCommand.new(
|
||||
name,
|
||||
chart: chart,
|
||||
version: version,
|
||||
values: values
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ module RedisCacheable
|
|||
|
||||
def cast_value_from_cache(attribute, value)
|
||||
if Gitlab.rails5?
|
||||
self.class.type_for_attribute(attribute).cast(value)
|
||||
self.class.type_for_attribute(attribute.to_s).cast(value)
|
||||
else
|
||||
self.class.column_for_attribute(attribute).type_cast_from_database(value)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class Project < ActiveRecord::Base
|
|||
include FastDestroyAll::Helpers
|
||||
include WithUploads
|
||||
include BatchDestroyDependentAssociations
|
||||
extend Gitlab::Cache::RequestCache
|
||||
|
||||
extend Gitlab::ConfigHelper
|
||||
|
||||
|
|
@ -2013,6 +2014,11 @@ class Project < ActiveRecord::Base
|
|||
@gitlab_deploy_token ||= deploy_tokens.gitlab_deploy_token
|
||||
end
|
||||
|
||||
def any_lfs_file_locks?
|
||||
lfs_file_locks.any?
|
||||
end
|
||||
request_cache(:any_lfs_file_locks?) { self.id }
|
||||
|
||||
private
|
||||
|
||||
def storage
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ class ChatNotificationService < Service
|
|||
end
|
||||
|
||||
def notify_for_ref?(data)
|
||||
return true if data[:object_kind] == 'tag_push'
|
||||
return true if data.dig(:object_attributes, :tag)
|
||||
return true unless notify_only_default_branch?
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,10 @@ class Repository
|
|||
|
||||
# Returns a list of commits that are not present in any reference
|
||||
def new_commits(newrev)
|
||||
refs = ::Gitlab::Git::RevList.new(raw, newrev: newrev).new_refs
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/1233
|
||||
refs = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
::Gitlab::Git::RevList.new(raw, newrev: newrev).new_refs
|
||||
end
|
||||
|
||||
refs.map { |sha| commit(sha.strip) }
|
||||
end
|
||||
|
|
@ -847,7 +850,7 @@ class Repository
|
|||
@root_ref_sha ||= commit(root_ref).sha
|
||||
end
|
||||
|
||||
delegate :merged_branch_names, :can_be_merged?, to: :raw_repository
|
||||
delegate :merged_branch_names, to: :raw_repository
|
||||
|
||||
def merge_base(first_commit_id, second_commit_id)
|
||||
first_commit_id = commit(first_commit_id).try(:id) || first_commit_id
|
||||
|
|
|
|||
|
|
@ -297,6 +297,7 @@ class ProjectPolicy < BasePolicy
|
|||
prevent(*create_read_update_admin_destroy(:build))
|
||||
prevent(*create_read_update_admin_destroy(:pipeline_schedule))
|
||||
prevent(*create_read_update_admin_destroy(:environment))
|
||||
prevent(*create_read_update_admin_destroy(:cluster))
|
||||
prevent(*create_read_update_admin_destroy(:deployment))
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@
|
|||
Unfortunately, your email message to GitLab could not be processed.
|
||||
|
||||
= markdown @reason
|
||||
= render_if_exists 'shared/additional_email_text'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
Unfortunately, your email message to GitLab could not be processed.
|
||||
\
|
||||
= @reason
|
||||
= render_if_exists 'shared/additional_email_text'
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
%p
|
||||
Assignee: #{@merge_request.assignee_name}
|
||||
|
||||
= render_if_exists 'notify/merge_request_approvers', merge_request: @merge_request
|
||||
|
||||
- if @merge_request.description
|
||||
%div
|
||||
= markdown(@merge_request.description, pipeline: :email, author: @merge_request.author)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ New Merge Request <%= @merge_request.to_reference %>
|
|||
<%= merge_path_description(@merge_request, 'to') %>
|
||||
Author: <%= @merge_request.author_name %>
|
||||
Assignee: <%= @merge_request.assignee_name %>
|
||||
<%= render_if_exists 'notify/merge_request_approvers', merge_request: @merge_request %>
|
||||
|
||||
<%= @merge_request.description %>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
|
||||
|
||||
.btn-group{ role: "group" }<
|
||||
= render_if_exists 'projects/blob/header_file_locks_link'
|
||||
= edit_blob_button
|
||||
= ide_edit_button
|
||||
- if current_user
|
||||
|
|
@ -18,3 +19,4 @@
|
|||
= delete_blob_link
|
||||
|
||||
= render 'projects/fork_suggestion'
|
||||
= render_if_exists 'projects/blob/header_file_locks', project: @project, path: @path
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
.d-block.d-sm-none
|
||||
= render_commit_status(commit, ref: ref)
|
||||
- if commit.description?
|
||||
%button.text-expander.d-none.d-sm-inline-block.js-toggle-button{ type: "button" } ...
|
||||
%button.text-expander.js-toggle-button
|
||||
= sprite_icon('ellipsis_h', size: 12)
|
||||
|
||||
.commiter
|
||||
- commit_author_link = commit_author_link(commit, avatar: false, size: 24)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
%label{ for: 'new-branch-name' }
|
||||
= _('Branch name')
|
||||
%input#new-branch-name.js-branch-name.form-control{ type: 'text', placeholder: "#{@issue.to_branch_name}", value: "#{@issue.to_branch_name}" }
|
||||
%span.js-branch-message.form-text.text-muted
|
||||
%span.js-branch-message.form-text
|
||||
|
||||
.form-group
|
||||
%label{ for: 'source-name' }
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@
|
|||
.wiki
|
||||
= markdown_field(@milestone, :description)
|
||||
|
||||
= render_if_exists 'shared/milestones/burndown', milestone: @milestone, project: @project
|
||||
|
||||
- if can?(current_user, :read_issue, @project) && @milestone.total_items_count(current_user).zero?
|
||||
.alert.alert-success.prepend-top-default
|
||||
%span Assign some issues to this milestone.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
= link_to @commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha js-details-short"
|
||||
= link_to("#", class: "js-details-expand d-none d-sm-none d-md-inline") do
|
||||
%span.text-expander
|
||||
\...
|
||||
= sprite_icon('ellipsis_h', size: 12)
|
||||
%span.js-details-content.hide
|
||||
= link_to @pipeline.sha, project_commit_path(@project, @pipeline.sha), class: "commit-sha commit-hash-full"
|
||||
= clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
row.find("td.tree-time-ago").html('#{escape_javascript time_ago_with_tooltip(commit.committed_date)}');
|
||||
row.find("td.tree-commit").html('#{escape_javascript render("projects/tree/tree_commit_column", commit: commit)}');
|
||||
|
||||
= render_if_exists 'projects/refs/logs_tree_lock_label', lock_label: content_data[:lock_label]
|
||||
|
||||
- if @more_log_url
|
||||
:plain
|
||||
if($('#tree-slider').length) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
%colgroup
|
||||
%col
|
||||
%col
|
||||
%col.d-none.d-sm-block
|
||||
%col
|
||||
%col{ width: "120" }
|
||||
%thead
|
||||
%tr
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
= note.author.to_reference
|
||||
%span.note-headline-light
|
||||
%span.note-headline-meta
|
||||
- unless note.system
|
||||
commented
|
||||
- if note.system
|
||||
%span.system-note-message
|
||||
= markdown_field(note, :note)
|
||||
|
|
|
|||
|
|
@ -8,28 +8,12 @@ class RepositoryForkWorker
|
|||
target_project_id = args.shift
|
||||
target_project = Project.find(target_project_id)
|
||||
|
||||
# By v10.8, we should've drained the queue of all jobs using the old arguments.
|
||||
# We can remove the else clause if we're no longer logging the message in that clause.
|
||||
# See https://gitlab.com/gitlab-org/gitaly/issues/1110
|
||||
if args.empty?
|
||||
source_project = target_project.forked_from_project
|
||||
unless source_project
|
||||
return target_project.mark_import_as_failed('Source project cannot be found.')
|
||||
end
|
||||
|
||||
fork_repository(target_project, source_project.repository_storage, source_project.disk_path)
|
||||
else
|
||||
Rails.logger.info("Project #{target_project.id} is being forked using old-style arguments.")
|
||||
|
||||
source_repository_storage_path, source_disk_path = *args
|
||||
|
||||
source_repository_storage_name = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
Gitlab.config.repositories.storages.find do |_, info|
|
||||
info.legacy_disk_path == source_repository_storage_path
|
||||
end&.first || raise("no shard found for path '#{source_repository_storage_path}'")
|
||||
end
|
||||
fork_repository(target_project, source_repository_storage_name, source_disk_path)
|
||||
source_project = target_project.forked_from_project
|
||||
unless source_project
|
||||
return target_project.mark_import_as_failed('Source project cannot be found.')
|
||||
end
|
||||
|
||||
fork_repository(target_project, source_project.repository_storage, source_project.disk_path)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix chat service tag notifications not sending when only default branch enabled
|
||||
merge_request: 19864
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Omits operartions and kubernetes item from project sidebar when repository or builds are disabled
|
||||
merge_request: 19835
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Fix branches are not shown in Merge Request dropdown when preferred language
|
||||
is not English
|
||||
merge_request: 20016
|
||||
author: Hiroyuki Sato
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Specify chart version when installing applications on Clusters
|
||||
merge_request: 20010
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: "[Rails5] Fix ActionCable '/cable' mountpoint conflict"
|
||||
merge_request: 20015
|
||||
author: "@blackst0ne"
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add filename filtering to code search
|
||||
merge_request: 19509
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Expose whether current user can push into a branch on branches API
|
||||
merge_request:
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Serve favicon image always from the main GitLab domain to avoid issues with CORS
|
||||
merge_request: 19810
|
||||
author: Alexis Reigel
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
title: Fixed pagination of groups API
|
||||
merge_request: 19665
|
||||
author: Marko, Peter
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Added id sorting option to GET groups and subgroups API
|
||||
merge_request: 19665
|
||||
author: Marko, Peter
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Rails5 fix format in uploads actions
|
||||
merge_request: 19907
|
||||
author: Jasper Maes
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: 'Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false})
|
||||
received: 0 times'
|
||||
merge_request: 20004
|
||||
author: Jasper Maes
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: 'Rails5 fix expected: 0 times with any arguments received: 1 time with arguments:
|
||||
DashboardController'
|
||||
merge_request: 20018
|
||||
author: Jasper Maes
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Rails5 fix Admin::HooksController
|
||||
merge_request: 20017
|
||||
author: Jasper Maes
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Rails5 fix Projects::PagesController spec
|
||||
merge_request: 20007
|
||||
author: Jasper Maes
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Bump rugged to 0.27.2
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Eliminate N+1 queries in LFS file locks checks during a push
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Updated the icon for expand buttons to ellipsis
|
||||
merge_request: 18793
|
||||
author: Constance Okoghenun
|
||||
type: changed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: migrate backup rake task to gitaly
|
||||
merge_request:
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -57,6 +57,13 @@ module Gitlab
|
|||
# Configure the default encoding used in templates for Ruby 1.9.
|
||||
config.encoding = "utf-8"
|
||||
|
||||
# ActionCable mount point.
|
||||
# The default Rails' mount point is `/cable` which may conflict with existing
|
||||
# namespaces/users.
|
||||
# https://github.com/rails/rails/blob/5-0-stable/actioncable/lib/action_cable.rb#L38
|
||||
# Please change this value when configuring ActionCable for real usage.
|
||||
config.action_cable.mount_path = "-" if rails5?
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
#
|
||||
# Parameters filtered:
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@ repositories_storages = Settings.repositories.storages.values
|
|||
repository_downloads_path = Settings.gitlab['repository_downloads_path'].to_s.gsub(%r{/$}, '')
|
||||
repository_downloads_full_path = File.expand_path(repository_downloads_path, Settings.gitlab['user_home'])
|
||||
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/1237
|
||||
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
if repository_downloads_path.blank? || repositories_storages.any? { |rs| [repository_downloads_path, repository_downloads_full_path].include?(rs.legacy_disk_path.gsub(%r{/$}, '')) }
|
||||
Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive')
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ def validate_storages_config
|
|||
end
|
||||
end
|
||||
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/1237
|
||||
def validate_storages_paths
|
||||
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
Gitlab.config.repositories.storages.each do |name, repository_storage|
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ Global Admins GitLab.org/GitLab INT/Global Groups/Global Admins
|
|||
|
||||
## GitLab LDAP configuration
|
||||
|
||||
The initial configuration of LDAP in GitLab requires changes to the `gitlab.rb` configuration file. Below is an example of a complete configuration using an Active Directory.
|
||||
The initial configuration of LDAP in GitLab requires changes to the `gitlab.rb` configuration file (`/etc/gitlab/gitlab.rb`). Below is an example of a complete configuration using an Active Directory.
|
||||
|
||||
The two Active Directory specific values are `active_directory: true` and `uid: 'sAMAccountName'`. `sAMAccountName` is an attribute returned by Active Directory used for GitLab usernames. See the example output from `ldapsearch` for a full list of attributes a "person" object (user) has in **AD** - [`ldapsearch` example](#using-ldapsearch-unix)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Example response:
|
|||
"protected": true,
|
||||
"developers_can_push": false,
|
||||
"developers_can_merge": false,
|
||||
"can_push": true,
|
||||
"commit": {
|
||||
"author_email": "john@example.com",
|
||||
"author_name": "John Smith",
|
||||
|
|
@ -76,6 +77,7 @@ Example response:
|
|||
"protected": true,
|
||||
"developers_can_push": false,
|
||||
"developers_can_merge": false,
|
||||
"can_push": true,
|
||||
"commit": {
|
||||
"author_email": "john@example.com",
|
||||
"author_name": "John Smith",
|
||||
|
|
@ -140,7 +142,8 @@ Example response:
|
|||
"merged": false,
|
||||
"protected": true,
|
||||
"developers_can_push": true,
|
||||
"developers_can_merge": true
|
||||
"developers_can_merge": true,
|
||||
"can_push": true
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -188,7 +191,8 @@ Example response:
|
|||
"merged": false,
|
||||
"protected": false,
|
||||
"developers_can_push": false,
|
||||
"developers_can_merge": false
|
||||
"developers_can_merge": false,
|
||||
"can_push": true
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -231,7 +235,8 @@ Example response:
|
|||
"merged": false,
|
||||
"protected": false,
|
||||
"developers_can_push": false,
|
||||
"developers_can_merge": false
|
||||
"developers_can_merge": false,
|
||||
"can_push": true
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Parameters:
|
|||
| `skip_groups` | array of integers | no | Skip the group IDs passed |
|
||||
| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin) |
|
||||
| `search` | string | no | Return the list of authorized groups matching the search criteria |
|
||||
| `order_by` | string | no | Order groups by `name` or `path`. Default is `name` |
|
||||
| `order_by` | string | no | Order groups by `name`, `path` or `id`. Default is `name` |
|
||||
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
|
||||
| `statistics` | boolean | no | Include group statistics (admins only) |
|
||||
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
|
||||
|
|
@ -96,7 +96,7 @@ Parameters:
|
|||
| `skip_groups` | array of integers | no | Skip the group IDs passed |
|
||||
| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin) |
|
||||
| `search` | string | no | Return the list of authorized groups matching the search criteria |
|
||||
| `order_by` | string | no | Order groups by `name` or `path`. Default is `name` |
|
||||
| `order_by` | string | no | Order groups by `name`, `path` or `id`. Default is `name` |
|
||||
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
|
||||
| `statistics` | boolean | no | Include group statistics (admins only) |
|
||||
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
|
||||
|
|
|
|||
|
|
@ -173,3 +173,7 @@ DELETE /projects/:id/members/:user_id
|
|||
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
|
||||
```
|
||||
|
||||
## Give a group access to a project
|
||||
|
||||
Look at [share project with group](projects.md#share-project-with-group)
|
||||
|
|
|
|||
|
|
@ -122,11 +122,11 @@ POST /projects/:id/pages/domains
|
|||
| `key` | file/string | no | The certificate key in PEM format. |
|
||||
|
||||
```bash
|
||||
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form="domain=ssl.domain.example" --form="certificate=@/path/to/cert.pem" --form="key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form="domain=ssl.domain.example" --form="certificate=$CERT_PEM" --form="key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
```
|
||||
|
||||
```json
|
||||
|
|
@ -158,11 +158,11 @@ PUT /projects/:id/pages/domains/:domain
|
|||
| `key` | file/string | no | The certificate key in PEM format. |
|
||||
|
||||
```bash
|
||||
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form="certificate=@/path/to/cert.pem" --form="key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form="certificate=$CERT_PEM" --form="key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
```
|
||||
|
||||
```json
|
||||
|
|
|
|||
|
|
@ -1198,7 +1198,7 @@ POST /projects/:id/share
|
|||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
|
||||
| `group_id` | integer | yes | The ID of the group to share with |
|
||||
| `group_access` | integer | yes | The permissions level to grant the group |
|
||||
| `group_access` | integer | yes | The [permissions level](members.md) to grant the group |
|
||||
| `expires_at` | string | no | Share expiration date in ISO 8601 format: 2016-09-26 |
|
||||
|
||||
## Delete a shared project link within a group
|
||||
|
|
|
|||
|
|
@ -776,6 +776,15 @@ Example response:
|
|||
|
||||
### Scope: blobs
|
||||
|
||||
Filters are available for this scope:
|
||||
- filename
|
||||
- path
|
||||
- extension
|
||||
|
||||
to use a filter simply include it in your query like so: `a query filename:some_name*`.
|
||||
|
||||
You may use wildcards (`*`) to use glob matching.
|
||||
|
||||
```bash
|
||||
curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=installation
|
||||
```
|
||||
|
|
|
|||
|
|
@ -88,18 +88,18 @@ The example below simply moves all files from the root of the project to the
|
|||
`public/` directory. The `.public` workaround is so `cp` doesn't also copy
|
||||
`public/` to itself in an infinite loop:
|
||||
|
||||
```
|
||||
```yaml
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- mkdir .public
|
||||
- cp -r * .public
|
||||
- mv .public public
|
||||
- mkdir .public
|
||||
- cp -r * .public
|
||||
- mv .public public
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
- master
|
||||
```
|
||||
|
||||
Read more on [GitLab Pages user documentation](../../user/project/pages/index.md).
|
||||
|
|
@ -131,15 +131,15 @@ if you set it per-job:
|
|||
|
||||
```yaml
|
||||
before_script:
|
||||
- global before script
|
||||
- global before script
|
||||
|
||||
job:
|
||||
before_script:
|
||||
- execute this instead of global before script
|
||||
- execute this instead of global before script
|
||||
script:
|
||||
- my command
|
||||
- my command
|
||||
after_script:
|
||||
- execute this after my script
|
||||
- execute this after my script
|
||||
```
|
||||
|
||||
## `stages`
|
||||
|
|
@ -409,18 +409,18 @@ fails, it will not stop the next stage from running, since it's marked with
|
|||
job1:
|
||||
stage: test
|
||||
script:
|
||||
- execute_script_that_will_fail
|
||||
- execute_script_that_will_fail
|
||||
allow_failure: true
|
||||
|
||||
job2:
|
||||
stage: test
|
||||
script:
|
||||
- execute_script_that_will_succeed
|
||||
- execute_script_that_will_succeed
|
||||
|
||||
job3:
|
||||
stage: deploy
|
||||
script:
|
||||
- deploy_to_staging
|
||||
- deploy_to_staging
|
||||
```
|
||||
|
||||
## `when`
|
||||
|
|
@ -442,38 +442,38 @@ For example:
|
|||
|
||||
```yaml
|
||||
stages:
|
||||
- build
|
||||
- cleanup_build
|
||||
- test
|
||||
- deploy
|
||||
- cleanup
|
||||
- build
|
||||
- cleanup_build
|
||||
- test
|
||||
- deploy
|
||||
- cleanup
|
||||
|
||||
build_job:
|
||||
stage: build
|
||||
script:
|
||||
- make build
|
||||
- make build
|
||||
|
||||
cleanup_build_job:
|
||||
stage: cleanup_build
|
||||
script:
|
||||
- cleanup build when failed
|
||||
- cleanup build when failed
|
||||
when: on_failure
|
||||
|
||||
test_job:
|
||||
stage: test
|
||||
script:
|
||||
- make test
|
||||
- make test
|
||||
|
||||
deploy_job:
|
||||
stage: deploy
|
||||
script:
|
||||
- make deploy
|
||||
- make deploy
|
||||
when: manual
|
||||
|
||||
cleanup_job:
|
||||
stage: cleanup
|
||||
script:
|
||||
- cleanup after jobs
|
||||
- cleanup after jobs
|
||||
when: always
|
||||
```
|
||||
|
||||
|
|
@ -734,8 +734,8 @@ rspec:
|
|||
script: test
|
||||
cache:
|
||||
paths:
|
||||
- binaries/*.apk
|
||||
- .config
|
||||
- binaries/*.apk
|
||||
- .config
|
||||
```
|
||||
|
||||
Locally defined cache overrides globally defined options. The following `rspec`
|
||||
|
|
@ -744,14 +744,14 @@ job will cache only `binaries/`:
|
|||
```yaml
|
||||
cache:
|
||||
paths:
|
||||
- my/files
|
||||
- my/files
|
||||
|
||||
rspec:
|
||||
script: test
|
||||
cache:
|
||||
key: rspec
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
Note that since cache is shared between jobs, if you're using different
|
||||
|
|
@ -786,7 +786,7 @@ For example, to enable per-branch caching:
|
|||
cache:
|
||||
key: "$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
If you use **Windows Batch** to run your shell scripts you need to replace
|
||||
|
|
@ -796,7 +796,7 @@ If you use **Windows Batch** to run your shell scripts you need to replace
|
|||
cache:
|
||||
key: "%CI_COMMIT_REF_SLUG%"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
### `cache:untracked`
|
||||
|
|
@ -819,7 +819,7 @@ rspec:
|
|||
cache:
|
||||
untracked: true
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
### `cache:policy`
|
||||
|
|
@ -897,8 +897,8 @@ Send all files in `binaries` and `.config`:
|
|||
```yaml
|
||||
artifacts:
|
||||
paths:
|
||||
- binaries/
|
||||
- .config
|
||||
- binaries/
|
||||
- .config
|
||||
```
|
||||
|
||||
To disable artifact passing, define the job with empty [dependencies](#dependencies):
|
||||
|
|
@ -927,7 +927,7 @@ release-job:
|
|||
- mvn package -U
|
||||
artifacts:
|
||||
paths:
|
||||
- target/*.war
|
||||
- target/*.war
|
||||
only:
|
||||
- tags
|
||||
```
|
||||
|
|
@ -949,7 +949,7 @@ job:
|
|||
artifacts:
|
||||
name: "$CI_JOB_NAME"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
To create an archive with a name of the current branch or tag including only
|
||||
|
|
@ -960,7 +960,7 @@ job:
|
|||
artifacts:
|
||||
name: "$CI_COMMIT_REF_NAME"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
To create an archive with a name of the current job and the current branch or
|
||||
|
|
@ -971,7 +971,7 @@ job:
|
|||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
To create an archive with a name of the current [stage](#stages) and branch name:
|
||||
|
|
@ -981,7 +981,7 @@ job:
|
|||
artifacts:
|
||||
name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -994,7 +994,7 @@ job:
|
|||
artifacts:
|
||||
name: "%CI_JOB_STAGE%-%CI_COMMIT_REF_NAME%"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
If you use **Windows PowerShell** to run your shell scripts you need to replace
|
||||
|
|
@ -1005,7 +1005,7 @@ job:
|
|||
artifacts:
|
||||
name: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_NAME"
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
### `artifacts:untracked`
|
||||
|
|
@ -1030,7 +1030,7 @@ Send all Git untracked files and files in `binaries`:
|
|||
artifacts:
|
||||
untracked: true
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
```
|
||||
|
||||
### `artifacts:when`
|
||||
|
|
@ -1120,26 +1120,26 @@ build:osx:
|
|||
script: make build:osx
|
||||
artifacts:
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
|
||||
build:linux:
|
||||
stage: build
|
||||
script: make build:linux
|
||||
artifacts:
|
||||
paths:
|
||||
- binaries/
|
||||
- binaries/
|
||||
|
||||
test:osx:
|
||||
stage: test
|
||||
script: make test:osx
|
||||
dependencies:
|
||||
- build:osx
|
||||
- build:osx
|
||||
|
||||
test:linux:
|
||||
stage: test
|
||||
script: make test:linux
|
||||
dependencies:
|
||||
- build:linux
|
||||
- build:linux
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
|
|
|
|||
|
|
@ -252,6 +252,53 @@ Keep in mind that the relation passed to
|
|||
`change_column_type_using_background_migration` _must_ include `EachBatch`,
|
||||
otherwise it will raise a `TypeError`.
|
||||
|
||||
This migration then needs to be followed in a separate release (_not_ a patch
|
||||
release) by a cleanup migration, which should steal from the queue and handle
|
||||
any remaining rows. For example:
|
||||
|
||||
```ruby
|
||||
class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
class Issue < ActiveRecord::Base
|
||||
self.table_name = 'issues'
|
||||
include EachBatch
|
||||
end
|
||||
|
||||
def up
|
||||
Gitlab::BackgroundMigration.steal('CopyColumn')
|
||||
Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange')
|
||||
|
||||
migrate_remaining_rows if migrate_column_type?
|
||||
end
|
||||
|
||||
def down
|
||||
# Previous migrations already revert the changes made here.
|
||||
end
|
||||
|
||||
def migrate_remaining_rows
|
||||
Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch|
|
||||
batch.update_all('closed_at_for_type_change = closed_at')
|
||||
end
|
||||
|
||||
cleanup_concurrent_column_type_change(:issues, :closed_at)
|
||||
end
|
||||
|
||||
def migrate_column_type?
|
||||
# Some environments may have already executed the previous version of this
|
||||
# migration, thus we don't need to migrate those environments again.
|
||||
column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
For more information, see [the documentation on cleaning up background
|
||||
migrations](background_migrations.md#cleaning-up).
|
||||
|
||||
## Adding Indexes
|
||||
|
||||
Adding indexes is an expensive process that blocks INSERT and UPDATE queries for
|
||||
|
|
|
|||
|
|
@ -154,12 +154,12 @@ page](https://golang.org/dl).
|
|||
|
||||
# Remove former Go installation folder
|
||||
sudo rm -rf /usr/local/go
|
||||
|
||||
curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
|
||||
echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
|
||||
sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
|
||||
|
||||
curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
|
||||
echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
|
||||
sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
|
||||
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
|
||||
rm go1.8.3.linux-amd64.tar.gz
|
||||
rm go1.10.3.linux-amd64.tar.gz
|
||||
|
||||
## 4. Node
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ want their accounts to be upgraded to full internal accounts.
|
|||
>**Note:**
|
||||
The following information only applies for installations from source.
|
||||
|
||||
GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already ships
|
||||
GitLab uses [Omniauth](https://github.com/omniauth/omniauth) for authentication and already ships
|
||||
with a few providers pre-installed (e.g. LDAP, GitHub, Twitter). But sometimes that
|
||||
is not enough and you need to integrate with other authentication solutions. For
|
||||
these cases you can use the Omniauth provider.
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ More information can be found on the [yarn website](https://yarnpkg.com/en/docs/
|
|||
|
||||
### 5. Update Go
|
||||
|
||||
NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
|
||||
1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
|
||||
NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
|
||||
1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
|
||||
|
||||
You can check which version you are running with `go version`.
|
||||
|
||||
|
|
@ -92,11 +92,11 @@ Download and install Go:
|
|||
# Remove former Go installation folder
|
||||
sudo rm -rf /usr/local/go
|
||||
|
||||
curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
|
||||
echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
|
||||
sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
|
||||
curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
|
||||
echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
|
||||
sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
|
||||
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
|
||||
rm go1.8.3.linux-amd64.tar.gz
|
||||
rm go1.10.3.linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
### 6. Get latest code
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ See our [product handbook on permissions](https://about.gitlab.com/handbook/prod
|
|||
|
||||
## Project members permissions
|
||||
|
||||
NOTE: **Note:**
|
||||
In GitLab 11.0, the Master role was renamed to Maintainer.
|
||||
|
||||
The following table depicts the various user permission levels in a project.
|
||||
|
||||
| Action | Guest | Reporter | Developer |Maintainer| Owner |
|
||||
|
|
@ -146,6 +149,9 @@ read through the documentation on [permissions and access to confidential issues
|
|||
|
||||
## Group members permissions
|
||||
|
||||
NOTE: **Note:**
|
||||
In GitLab 11.0, the Master role was renamed to Maintainer.
|
||||
|
||||
Any user can remove themselves from a group, unless they are the last Owner of
|
||||
the group. The following table depicts the various user permission levels in a
|
||||
group.
|
||||
|
|
@ -223,6 +229,9 @@ which visibility level you select on project settings.
|
|||
|
||||
## GitLab CI/CD permissions
|
||||
|
||||
NOTE: **Note:**
|
||||
In GitLab 11.0, the Master role was renamed to Maintainer.
|
||||
|
||||
GitLab CI/CD permissions rely on the role the user has in GitLab. There are four
|
||||
permission levels in total:
|
||||
|
||||
|
|
@ -250,6 +259,9 @@ instance and project. In addition, all admins can use the admin interface under
|
|||
|
||||
### Job permissions
|
||||
|
||||
NOTE: **Note:**
|
||||
In GitLab 11.0, the Master role was renamed to Maintainer.
|
||||
|
||||
>**Note:**
|
||||
GitLab 8.12 has a completely redesigned job permissions system.
|
||||
Read all about the [new model and its implications][new-mod].
|
||||
|
|
@ -301,4 +313,4 @@ Read through the documentation on [LDAP users permissions](https://docs.gitlab.c
|
|||
[ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994
|
||||
[new-mod]: project/new_ci_build_permissions_model.md
|
||||
[ee-998]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/998
|
||||
[eep]: https://about.gitlab.com/products/
|
||||
[eep]: https://about.gitlab.com/products/
|
||||
|
|
|
|||
|
|
@ -4,19 +4,14 @@ A user's profile preferences page allows the user to customize various aspects
|
|||
of GitLab to their liking.
|
||||
|
||||
To navigate to your profile's preferences, click your avatar icon in the top
|
||||
right corner and select **Settings**. From there on, choose the **Preferences**
|
||||
tab.
|
||||
|
||||

|
||||
right corner, select **Settings** and then choose **Preferences** from the
|
||||
left sidebar.
|
||||
|
||||
## Navigation theme
|
||||
|
||||
>**Note:**
|
||||
Navigation themes have been re-introduced with [GitLab 10.0](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/).
|
||||
|
||||
The GitLab navigation theme setting allows you to personalize your GitLab experience.
|
||||
You can choose from several color themes that add unique colors to the top navigation
|
||||
and left side navigation.
|
||||
and left side navigation.
|
||||
Using individual color themes might help you differentiate between your different
|
||||
GitLab instances.
|
||||
|
||||
|
|
@ -33,13 +28,13 @@ The default palette is Indigo. You can choose between 10 different themes:
|
|||
- Dark
|
||||
- Light
|
||||
|
||||

|
||||

|
||||
|
||||
## Syntax highlighting theme
|
||||
|
||||
>**Note:**
|
||||
GitLab uses the [rouge Ruby library][rouge] for syntax highlighting. For a
|
||||
list of supported languages visit the rouge website.
|
||||
NOTE: **Note:**
|
||||
GitLab uses the [rouge Ruby library](http://rouge.jneen.net/ "Rouge website")
|
||||
for syntax highlighting. For a list of supported languages visit the rouge website.
|
||||
|
||||
Changing this setting allows you to customize the color theme when viewing any
|
||||
syntax highlighted code on GitLab.
|
||||
|
|
@ -52,7 +47,7 @@ The default syntax theme is White, and you can choose among 5 different colors:
|
|||
- Solarized dark
|
||||
- Monokai
|
||||
|
||||

|
||||

|
||||
|
||||
## Behavior
|
||||
|
||||
|
|
@ -78,7 +73,7 @@ You have 8 options here that you can use for your default dashboard view:
|
|||
- Your projects' activity
|
||||
- Starred projects' activity
|
||||
- Your groups
|
||||
- Your [Todos]
|
||||
- Your [Todos](../../workflow/todos.md)
|
||||
- Assigned Issues
|
||||
- Assigned Merge Requests
|
||||
|
||||
|
|
@ -92,6 +87,3 @@ You can choose between 3 options:
|
|||
- Files and Readme (default)
|
||||
- Readme
|
||||
- Activity
|
||||
|
||||
[rouge]: http://rouge.jneen.net/ "Rouge website"
|
||||
[todos]: ../../workflow/todos.md
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ added directly to your configured cluster. Those applications are needed for
|
|||
| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps] or deploy your own web apps. |
|
||||
| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications |
|
||||
| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](#security-implications) before doing so. |
|
||||
| [JupyterHub](http://jupyter.org/) | 11.0+ | The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. |
|
||||
| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. |
|
||||
|
||||
## Getting the external IP address
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## On Microsoft Teams
|
||||
|
||||
To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft Teams by following the steps described in this [document](https://msdn.microsoft.com/en-us/microsoft-teams/connectors).
|
||||
To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft Teams by following the steps described in this [document](https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/connectors#setting-up-a-custom-incoming-webhook).
|
||||
|
||||
## On GitLab
|
||||
|
||||
|
|
|
|||
|
|
@ -176,4 +176,12 @@ Lock your files to prevent any conflicting changes.
|
|||
|
||||
You can access your repos via [repository API](../../../api/repositories.md).
|
||||
|
||||
## Clone in Apple Xcode
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/45820) in GitLab 11.0
|
||||
|
||||
Projects that contain a `.xcodeproj` or `.xcworkspace` directory can now be cloned
|
||||
in Xcode using the new **Open in Xcode** button, located next to the Git URL
|
||||
used for cloning your project. The button is only shown on macOS.
|
||||
|
||||
[jupyter]: https://jupyter.org
|
||||
|
|
|
|||
|
|
@ -349,6 +349,10 @@ module API
|
|||
expose :developers_can_merge do |repo_branch, options|
|
||||
options[:project].protected_branches.developers_can?(:merge, repo_branch.name)
|
||||
end
|
||||
|
||||
expose :can_push do |repo_branch, options|
|
||||
Gitlab::UserAccess.new(options[:current_user], project: options[:project]).can_push_to_branch?(repo_branch.name)
|
||||
end
|
||||
end
|
||||
|
||||
class TreeObject < Grape::Entity
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ module API
|
|||
optional :all_available, type: Boolean, desc: 'Show all group that you have access to'
|
||||
optional :search, type: String, desc: 'Search for a specific group'
|
||||
optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user'
|
||||
optional :order_by, type: String, values: %w[name path], default: 'name', desc: 'Order by name or path'
|
||||
optional :order_by, type: String, values: %w[name path id], default: 'name', desc: 'Order by name, path or id'
|
||||
optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
|
||||
use :pagination
|
||||
end
|
||||
|
|
@ -46,7 +46,9 @@ module API
|
|||
groups = GroupsFinder.new(current_user, find_params).execute
|
||||
groups = groups.search(params[:search]) if params[:search].present?
|
||||
groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
|
||||
groups = groups.reorder(params[:order_by] => params[:sort])
|
||||
order_options = { params[:order_by] => params[:sort] }
|
||||
order_options["id"] ||= "asc"
|
||||
groups = groups.reorder(order_options)
|
||||
|
||||
groups
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ require_relative 'helper'
|
|||
module Backup
|
||||
class Repository
|
||||
include Backup::Helper
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
|
||||
attr_reader :progress
|
||||
|
||||
|
|
@ -18,61 +17,26 @@ module Backup
|
|||
Project.find_each(batch_size: 1000) do |project|
|
||||
progress.print " * #{display_repo_path(project)} ... "
|
||||
|
||||
path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
path_to_repo(project)
|
||||
end
|
||||
path_to_project_bundle = path_to_bundle(project)
|
||||
|
||||
# Create namespace dir or hashed path if missing
|
||||
if project.hashed_storage?(:repository)
|
||||
FileUtils.mkdir_p(File.dirname(File.join(backup_repos_path, project.disk_path)))
|
||||
else
|
||||
FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace
|
||||
end
|
||||
|
||||
if empty_repo?(project)
|
||||
progress.puts "[SKIPPED]".color(:cyan)
|
||||
if !empty_repo?(project)
|
||||
backup_project(project)
|
||||
progress.puts "[DONE]".color(:green)
|
||||
else
|
||||
in_path(path_to_project_repo) do |dir|
|
||||
FileUtils.mkdir_p(path_to_tars(project))
|
||||
cmd = %W(tar -cf #{path_to_tars(project, dir)} -C #{path_to_project_repo} #{dir})
|
||||
output, status = Gitlab::Popen.popen(cmd)
|
||||
|
||||
unless status.zero?
|
||||
progress_warn(project, cmd.join(' '), output)
|
||||
end
|
||||
end
|
||||
|
||||
cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_project_repo} bundle create #{path_to_project_bundle} --all)
|
||||
output, status = Gitlab::Popen.popen(cmd)
|
||||
|
||||
if status.zero?
|
||||
progress.puts "[DONE]".color(:green)
|
||||
else
|
||||
progress_warn(project, cmd.join(' '), output)
|
||||
end
|
||||
progress.puts "[SKIPPED]".color(:cyan)
|
||||
end
|
||||
|
||||
wiki = ProjectWiki.new(project)
|
||||
path_to_wiki_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
path_to_repo(wiki)
|
||||
end
|
||||
path_to_wiki_bundle = path_to_bundle(wiki)
|
||||
|
||||
if File.exist?(path_to_wiki_repo)
|
||||
progress.print " * #{display_repo_path(wiki)} ... "
|
||||
|
||||
if empty_repo?(wiki)
|
||||
progress.puts " [SKIPPED]".color(:cyan)
|
||||
else
|
||||
cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_wiki_repo} bundle create #{path_to_wiki_bundle} --all)
|
||||
output, status = Gitlab::Popen.popen(cmd)
|
||||
if status.zero?
|
||||
progress.puts " [DONE]".color(:green)
|
||||
else
|
||||
progress_warn(wiki, cmd.join(' '), output)
|
||||
end
|
||||
end
|
||||
if !empty_repo?(wiki)
|
||||
backup_project(wiki)
|
||||
progress.puts "[DONE] Wiki".color(:green)
|
||||
else
|
||||
progress.puts "[SKIPPED] Wiki".color(:cyan)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -83,6 +47,38 @@ module Backup
|
|||
end
|
||||
end
|
||||
|
||||
def backup_project(project)
|
||||
gitaly_migrate(:repository_backup) do |is_enabled|
|
||||
if is_enabled
|
||||
backup_project_gitaly(project)
|
||||
else
|
||||
backup_project_local(project)
|
||||
end
|
||||
end
|
||||
|
||||
backup_custom_hooks(project)
|
||||
rescue => e
|
||||
progress_warn(project, e, 'Failed to backup repo')
|
||||
end
|
||||
|
||||
def backup_project_gitaly(project)
|
||||
path_to_project_bundle = path_to_bundle(project)
|
||||
Gitlab::GitalyClient::RepositoryService.new(project.repository)
|
||||
.create_bundle(path_to_project_bundle)
|
||||
end
|
||||
|
||||
def backup_project_local(project)
|
||||
path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
path_to_repo(project)
|
||||
end
|
||||
|
||||
path_to_project_bundle = path_to_bundle(project)
|
||||
|
||||
cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_project_repo} bundle create #{path_to_project_bundle} --all)
|
||||
output, status = Gitlab::Popen.popen(cmd)
|
||||
progress_warn(project, cmd.join(' '), output) unless status.zero?
|
||||
end
|
||||
|
||||
def delete_all_repositories(name, repository_storage)
|
||||
gitaly_migrate(:delete_all_repositories) do |is_enabled|
|
||||
if is_enabled
|
||||
|
|
@ -97,8 +93,6 @@ module Backup
|
|||
path = repository_storage.legacy_disk_path
|
||||
return unless File.exist?(path)
|
||||
|
||||
# Move all files in the existing repos directory except . and .. to
|
||||
# repositories.old.<timestamp> directory
|
||||
bk_repos_path = File.join(Gitlab.config.backup.path, "tmp", "#{name}-repositories.old." + Time.now.to_i.to_s)
|
||||
FileUtils.mkdir_p(bk_repos_path, mode: 0700)
|
||||
files = Dir.glob(File.join(path, "*"), File::FNM_DOTMATCH) - [File.join(path, "."), File.join(path, "..")]
|
||||
|
|
@ -129,13 +123,47 @@ module Backup
|
|||
.restore_custom_hooks(custom_hooks_path)
|
||||
end
|
||||
|
||||
def local_backup_custom_hooks(project)
|
||||
in_path(path_to_tars(project)) do |dir|
|
||||
path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
path_to_repo(project)
|
||||
end
|
||||
break unless File.exist?(File.join(path_to_project_repo, dir))
|
||||
|
||||
FileUtils.mkdir_p(path_to_tars(project))
|
||||
cmd = %W(tar -cf #{path_to_tars(project, dir)} -c #{path_to_project_repo} #{dir})
|
||||
output, status = Gitlab::Popen.popen(cmd)
|
||||
|
||||
unless status.zero?
|
||||
progress_warn(project, cmd.join(' '), output)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gitaly_backup_custom_hooks(project)
|
||||
FileUtils.mkdir_p(path_to_tars(project))
|
||||
custom_hooks_path = path_to_tars(project, 'custom_hooks')
|
||||
Gitlab::GitalyClient::RepositoryService.new(project.repository)
|
||||
.backup_custom_hooks(custom_hooks_path)
|
||||
end
|
||||
|
||||
def backup_custom_hooks(project)
|
||||
gitaly_migrate(:backup_custom_hooks) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_backup_custom_hooks(project)
|
||||
else
|
||||
local_backup_custom_hooks(project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def restore_custom_hooks(project)
|
||||
in_path(path_to_tars(project)) do |dir|
|
||||
gitaly_migrate(:restore_custom_hooks) do |is_enabled|
|
||||
if is_enabled
|
||||
local_restore_custom_hooks(project, dir)
|
||||
else
|
||||
gitaly_restore_custom_hooks(project, dir)
|
||||
else
|
||||
local_restore_custom_hooks(project, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -186,7 +214,6 @@ module Backup
|
|||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
protected
|
||||
|
||||
|
|
@ -224,9 +251,7 @@ module Backup
|
|||
|
||||
def prepare
|
||||
FileUtils.rm_rf(backup_repos_path)
|
||||
# Ensure the parent dir of backup_repos_path exists
|
||||
FileUtils.mkdir_p(Gitlab.config.backup.path)
|
||||
# Fail if somebody raced to create backup_repos_path before us
|
||||
FileUtils.mkdir(backup_repos_path, mode: 0700)
|
||||
end
|
||||
|
||||
|
|
@ -242,7 +267,6 @@ module Backup
|
|||
end
|
||||
|
||||
def empty_repo?(project_or_wiki)
|
||||
# Protect against stale caches
|
||||
project_or_wiki.repository.expire_emptiness_caches
|
||||
project_or_wiki.repository.empty?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ module Gitlab
|
|||
|
||||
def validate_lfs_file_locks?
|
||||
strong_memoize(:validate_lfs_file_locks) do
|
||||
project.lfs_enabled? && project.lfs_file_locks.any? && newrev && oldrev
|
||||
project.lfs_enabled? && newrev && oldrev && project.any_lfs_file_locks?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,18 +7,10 @@ module Gitlab
|
|||
# Created or deleted branch
|
||||
return false if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
|
||||
|
||||
GitalyClient.migrate(:force_push) do |is_enabled|
|
||||
if is_enabled
|
||||
!project
|
||||
.repository
|
||||
.gitaly_commit_client
|
||||
.ancestor?(oldrev, newrev)
|
||||
else
|
||||
Gitlab::Git::RevList.new(
|
||||
project.repository.raw, oldrev: oldrev, newrev: newrev
|
||||
).missed_ref.present?
|
||||
end
|
||||
end
|
||||
!project
|
||||
.repository
|
||||
.gitaly_commit_client
|
||||
.ancestor?(oldrev, newrev)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ module Gitlab
|
|||
class Favicon
|
||||
class << self
|
||||
def main
|
||||
return appearance_favicon.url if appearance_favicon.exists?
|
||||
|
||||
image_name =
|
||||
if Gitlab::Utils.to_boolean(ENV['CANARY'])
|
||||
if appearance_favicon.exists?
|
||||
appearance_favicon.url
|
||||
elsif Gitlab::Utils.to_boolean(ENV['CANARY'])
|
||||
'favicon-yellow.png'
|
||||
elsif Rails.env.development?
|
||||
'favicon-blue.png'
|
||||
|
|
@ -13,7 +13,7 @@ module Gitlab
|
|||
'favicon.png'
|
||||
end
|
||||
|
||||
ActionController::Base.helpers.image_path(image_name)
|
||||
ActionController::Base.helpers.image_path(image_name, host: host)
|
||||
end
|
||||
|
||||
def status_overlay(status_name)
|
||||
|
|
@ -22,7 +22,7 @@ module Gitlab
|
|||
"#{status_name}.png"
|
||||
)
|
||||
|
||||
ActionController::Base.helpers.image_path(path)
|
||||
ActionController::Base.helpers.image_path(path, host: host)
|
||||
end
|
||||
|
||||
def available_status_names
|
||||
|
|
@ -35,6 +35,16 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
# we only want to create full urls when there's a different asset_host
|
||||
# configured.
|
||||
def host
|
||||
if Gitlab::Application.config.asset_host.nil? || Gitlab::Application.config.asset_host == Gitlab.config.gitlab.base_url
|
||||
nil
|
||||
else
|
||||
Gitlab.config.gitlab.base_url
|
||||
end
|
||||
end
|
||||
|
||||
def appearance
|
||||
RequestStore.store[:appearance] ||= (Appearance.current || Appearance.new)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,14 +14,21 @@ module Gitlab
|
|||
end
|
||||
|
||||
def find(query)
|
||||
by_content = find_by_content(query)
|
||||
query = Gitlab::Search::Query.new(query) do
|
||||
filter :filename, matcher: ->(filter, blob) { blob.filename =~ /#{filter[:regex_value]}$/i }
|
||||
filter :path, matcher: ->(filter, blob) { blob.filename =~ /#{filter[:regex_value]}/i }
|
||||
filter :extension, matcher: ->(filter, blob) { blob.filename =~ /\.#{filter[:regex_value]}$/i }
|
||||
end
|
||||
|
||||
by_content = find_by_content(query.term)
|
||||
|
||||
already_found = Set.new(by_content.map(&:filename))
|
||||
by_filename = find_by_filename(query, except: already_found)
|
||||
by_filename = find_by_filename(query.term, except: already_found)
|
||||
|
||||
(by_content + by_filename)
|
||||
.sort_by(&:filename)
|
||||
.map { |blob| [blob.filename, blob] }
|
||||
files = (by_content + by_filename)
|
||||
.sort_by(&:filename)
|
||||
|
||||
query.filter_results(files).map { |blob| [blob.filename, blob] }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -7,67 +7,11 @@ module Gitlab
|
|||
end
|
||||
|
||||
def new_pointers(object_limit: nil, not_in: nil)
|
||||
@repository.gitaly_migrate(:blob_get_new_lfs_pointers) do |is_enabled|
|
||||
if is_enabled
|
||||
@repository.gitaly_blob_client.get_new_lfs_pointers(@newrev, object_limit, not_in)
|
||||
else
|
||||
git_new_pointers(object_limit, not_in)
|
||||
end
|
||||
end
|
||||
@repository.gitaly_blob_client.get_new_lfs_pointers(@newrev, object_limit, not_in)
|
||||
end
|
||||
|
||||
def all_pointers
|
||||
@repository.gitaly_migrate(:blob_get_all_lfs_pointers) do |is_enabled|
|
||||
if is_enabled
|
||||
@repository.gitaly_blob_client.get_all_lfs_pointers(@newrev)
|
||||
else
|
||||
git_all_pointers
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def git_new_pointers(object_limit, not_in)
|
||||
@new_pointers ||= begin
|
||||
rev_list.new_objects(rev_list_params(not_in: not_in)) do |object_ids|
|
||||
object_ids = object_ids.take(object_limit) if object_limit
|
||||
|
||||
Gitlab::Git::Blob.batch_lfs_pointers(@repository, object_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def git_all_pointers
|
||||
params = {}
|
||||
if rev_list_supports_new_options?
|
||||
params[:options] = ["--filter=blob:limit=#{Gitlab::Git::Blob::LFS_POINTER_MAX_SIZE}"]
|
||||
end
|
||||
|
||||
rev_list.all_objects(rev_list_params(params)) do |object_ids|
|
||||
Gitlab::Git::Blob.batch_lfs_pointers(@repository, object_ids)
|
||||
end
|
||||
end
|
||||
|
||||
def rev_list
|
||||
Gitlab::Git::RevList.new(@repository, newrev: @newrev)
|
||||
end
|
||||
|
||||
# We're passing the `--in-commit-order` arg to ensure we don't wait
|
||||
# for git to traverse all commits before returning pointers.
|
||||
# This is required in order to improve the performance of LFS integrity check
|
||||
def rev_list_params(params = {})
|
||||
params[:options] ||= []
|
||||
params[:options] << "--in-commit-order" if rev_list_supports_new_options?
|
||||
params[:require_path] = true
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def rev_list_supports_new_options?
|
||||
return @option_supported if defined?(@option_supported)
|
||||
|
||||
@option_supported = Gitlab::Git.version >= Gitlab::VersionInfo.parse('2.16.0')
|
||||
@repository.gitaly_blob_client.get_all_lfs_pointers(@newrev)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -472,13 +472,21 @@ module Gitlab
|
|||
end
|
||||
|
||||
def count_commits(options)
|
||||
count_commits_options = process_count_commits_options(options)
|
||||
options = process_count_commits_options(options.dup)
|
||||
|
||||
gitaly_migrate(:count_commits, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
|
||||
if is_enabled
|
||||
count_commits_by_gitaly(count_commits_options)
|
||||
wrapped_gitaly_errors do
|
||||
if options[:left_right]
|
||||
from = options[:from]
|
||||
to = options[:to]
|
||||
|
||||
right_count = gitaly_commit_client
|
||||
.commit_count("#{from}..#{to}", options)
|
||||
left_count = gitaly_commit_client
|
||||
.commit_count("#{to}..#{from}", options)
|
||||
|
||||
[left_count, right_count]
|
||||
else
|
||||
count_commits_by_shelling_out(count_commits_options)
|
||||
gitaly_commit_client.commit_count(options[:ref], options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -676,15 +684,9 @@ module Gitlab
|
|||
end
|
||||
|
||||
# Return total commits count accessible from passed ref
|
||||
#
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/330
|
||||
def commit_count(ref)
|
||||
gitaly_migrate(:commit_count, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_commit_client.commit_count(ref)
|
||||
else
|
||||
rugged_commit_count(ref)
|
||||
end
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_commit_client.commit_count(ref)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -984,21 +986,7 @@ module Gitlab
|
|||
def info_attributes
|
||||
return @info_attributes if @info_attributes
|
||||
|
||||
content =
|
||||
gitaly_migrate(:get_info_attributes, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_repository_client.info_attributes
|
||||
else
|
||||
attributes_path = File.join(File.expand_path(path), 'info', 'attributes')
|
||||
|
||||
if File.exist?(attributes_path)
|
||||
File.read(attributes_path)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
content = gitaly_repository_client.info_attributes
|
||||
@info_attributes = AttributesParser.new(content)
|
||||
end
|
||||
|
||||
|
|
@ -1054,18 +1042,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def license_short_name
|
||||
gitaly_migrate(:license_short_name,
|
||||
status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_repository_client.license_short_name
|
||||
else
|
||||
begin
|
||||
# The licensee gem creates a Rugged object from the path:
|
||||
# https://github.com/benbalter/licensee/blob/v8.7.0/lib/licensee/projects/git_project.rb
|
||||
Licensee.license(path).try(:key)
|
||||
rescue Rugged::Error
|
||||
end
|
||||
end
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_repository_client.license_short_name
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1252,12 +1230,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def rebase_in_progress?(rebase_id)
|
||||
gitaly_migrate(:rebase_in_progress) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_repository_client.rebase_in_progress?(rebase_id)
|
||||
else
|
||||
fresh_worktree?(worktree_path(REBASE_WORKTREE_PREFIX, rebase_id))
|
||||
end
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_repository_client.rebase_in_progress?(rebase_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1273,12 +1247,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def squash_in_progress?(squash_id)
|
||||
gitaly_migrate(:squash_in_progress, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_repository_client.squash_in_progress?(squash_id)
|
||||
else
|
||||
fresh_worktree?(worktree_path(SQUASH_WORKTREE_PREFIX, squash_id))
|
||||
end
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_repository_client.squash_in_progress?(squash_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1443,13 +1413,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def can_be_merged?(source_sha, target_branch)
|
||||
gitaly_migrate(:can_be_merged) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_can_be_merged?(source_sha, find_branch(target_branch, true).target)
|
||||
else
|
||||
rugged_can_be_merged?(source_sha, target_branch)
|
||||
end
|
||||
end
|
||||
target_sha = find_branch(target_branch, true).target
|
||||
!gitaly_conflicts_client(source_sha, target_sha).conflicts?
|
||||
end
|
||||
|
||||
def search_files_by_name(query, ref)
|
||||
|
|
@ -1514,10 +1479,6 @@ module Gitlab
|
|||
run_git!(args, lazy_block: block)
|
||||
end
|
||||
|
||||
def missed_ref(oldrev, newrev)
|
||||
run_git!(['rev-list', '--max-count=1', oldrev, "^#{newrev}"])
|
||||
end
|
||||
|
||||
def with_worktree(worktree_path, branch, sparse_checkout_files: nil, env:)
|
||||
base_args = %w(worktree add --detach)
|
||||
|
||||
|
|
@ -1621,21 +1582,6 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
# This function is duplicated in Gitaly-Go, don't change it!
|
||||
# https://gitlab.com/gitlab-org/gitaly/merge_requests/698
|
||||
def fresh_worktree?(path)
|
||||
File.exist?(path) && !clean_stuck_worktree(path)
|
||||
end
|
||||
|
||||
# This function is duplicated in Gitaly-Go, don't change it!
|
||||
# https://gitlab.com/gitlab-org/gitaly/merge_requests/698
|
||||
def clean_stuck_worktree(path)
|
||||
return false unless File.mtime(path) < 15.minutes.ago
|
||||
|
||||
FileUtils.rm_rf(path)
|
||||
true
|
||||
end
|
||||
|
||||
# Adding a worktree means checking out the repository. For large repos,
|
||||
# this can be very expensive, so set up sparse checkout for the worktree
|
||||
# to only check out the files we're interested in.
|
||||
|
|
@ -1902,71 +1848,6 @@ module Gitlab
|
|||
gitaly_repository_client.repository_size
|
||||
end
|
||||
|
||||
def count_commits_by_gitaly(options)
|
||||
if options[:left_right]
|
||||
from = options[:from]
|
||||
to = options[:to]
|
||||
|
||||
right_count = gitaly_commit_client
|
||||
.commit_count("#{from}..#{to}", options)
|
||||
left_count = gitaly_commit_client
|
||||
.commit_count("#{to}..#{from}", options)
|
||||
|
||||
[left_count, right_count]
|
||||
else
|
||||
gitaly_commit_client.commit_count(options[:ref], options)
|
||||
end
|
||||
end
|
||||
|
||||
def count_commits_by_shelling_out(options)
|
||||
cmd = count_commits_shelling_command(options)
|
||||
|
||||
raw_output, _status = run_git(cmd)
|
||||
|
||||
process_count_commits_raw_output(raw_output, options)
|
||||
end
|
||||
|
||||
def count_commits_shelling_command(options)
|
||||
cmd = %w[rev-list]
|
||||
cmd << "--after=#{options[:after].iso8601}" if options[:after]
|
||||
cmd << "--before=#{options[:before].iso8601}" if options[:before]
|
||||
cmd << "--max-count=#{options[:max_count]}" if options[:max_count]
|
||||
cmd << "--left-right" if options[:left_right]
|
||||
cmd << '--count'
|
||||
|
||||
cmd << if options[:all]
|
||||
'--all'
|
||||
elsif options[:ref]
|
||||
options[:ref]
|
||||
else
|
||||
raise ArgumentError, "Please specify a valid ref or set the 'all' attribute to true"
|
||||
end
|
||||
|
||||
cmd += %W[-- #{options[:path]}] if options[:path].present?
|
||||
cmd
|
||||
end
|
||||
|
||||
def process_count_commits_raw_output(raw_output, options)
|
||||
if options[:left_right]
|
||||
result = raw_output.scan(/\d+/).map(&:to_i)
|
||||
|
||||
if result.sum != options[:max_count]
|
||||
result
|
||||
else # Reaching max count, right is not accurate
|
||||
right_option =
|
||||
process_count_commits_options(options
|
||||
.except(:left_right, :from, :to)
|
||||
.merge(ref: options[:to]))
|
||||
|
||||
right = count_commits_by_shelling_out(right_option)
|
||||
|
||||
[result.first, right] # left should be accurate in the first call
|
||||
end
|
||||
else
|
||||
raw_output.to_i
|
||||
end
|
||||
end
|
||||
|
||||
def gitaly_ls_files(ref)
|
||||
gitaly_commit_client.ls_files(ref)
|
||||
end
|
||||
|
|
@ -2346,14 +2227,6 @@ module Gitlab
|
|||
run_git(['fetch', remote_name], env: env).last.zero?
|
||||
end
|
||||
|
||||
def gitaly_can_be_merged?(their_commit, our_commit)
|
||||
!gitaly_conflicts_client(our_commit, their_commit).conflicts?
|
||||
end
|
||||
|
||||
def rugged_can_be_merged?(their_commit, our_commit)
|
||||
!rugged.merge_commits(our_commit, their_commit).conflicts?
|
||||
end
|
||||
|
||||
def gitlab_projects_error
|
||||
raise CommandError, @gitlab_projects.output
|
||||
end
|
||||
|
|
@ -2393,16 +2266,6 @@ module Gitlab
|
|||
nil
|
||||
end
|
||||
|
||||
def rugged_commit_count(ref)
|
||||
walker = Rugged::Walker.new(rugged)
|
||||
walker.sorting(Rugged::SORT_TOPO | Rugged::SORT_REVERSE)
|
||||
oid = rugged.rev_parse_oid(ref)
|
||||
walker.push(oid)
|
||||
walker.count
|
||||
rescue Rugged::ReferenceError
|
||||
0
|
||||
end
|
||||
|
||||
def rev_list_param(spec)
|
||||
spec == :all ? ['--all'] : spec
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
# Gitaly note: JV: will probably be migrated indirectly by migrating the call sites.
|
||||
|
||||
module Gitlab
|
||||
module Git
|
||||
class RevList
|
||||
|
|
@ -45,13 +43,6 @@ module Gitlab
|
|||
&lazy_block)
|
||||
end
|
||||
|
||||
# This methods returns an array of missed references
|
||||
#
|
||||
# Should become obsolete after https://gitlab.com/gitlab-org/gitaly/issues/348.
|
||||
def missed_ref
|
||||
repository.missed_ref(oldrev, newrev).split("\n")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def execute(args)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Gitlab
|
|||
extend Gitlab::Git::Popen
|
||||
|
||||
def self.git_version
|
||||
Gitlab::VersionInfo.parse(popen(%W(#{Gitlab.config.git.bin_path} --version), nil).first)
|
||||
Gitlab::VersionInfo.parse(Gitaly::Server.all.first.git_binary_version)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -196,20 +196,21 @@ module Gitlab
|
|||
end
|
||||
|
||||
def create_bundle(save_path)
|
||||
request = Gitaly::CreateBundleRequest.new(repository: @gitaly_repo)
|
||||
response = GitalyClient.call(
|
||||
@storage,
|
||||
:repository_service,
|
||||
gitaly_fetch_stream_to_file(
|
||||
save_path,
|
||||
:create_bundle,
|
||||
request,
|
||||
timeout: GitalyClient.default_timeout
|
||||
Gitaly::CreateBundleRequest,
|
||||
GitalyClient.default_timeout
|
||||
)
|
||||
end
|
||||
|
||||
File.open(save_path, 'wb') do |f|
|
||||
response.each do |message|
|
||||
f.write(message.data)
|
||||
end
|
||||
end
|
||||
def backup_custom_hooks(save_path)
|
||||
gitaly_fetch_stream_to_file(
|
||||
save_path,
|
||||
:backup_custom_hooks,
|
||||
Gitaly::BackupCustomHooksRequest,
|
||||
GitalyClient.default_timeout
|
||||
)
|
||||
end
|
||||
|
||||
def create_from_bundle(bundle_path)
|
||||
|
|
@ -309,6 +310,25 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
def gitaly_fetch_stream_to_file(save_path, rpc_name, request_class, timeout)
|
||||
request = request_class.new(repository: @gitaly_repo)
|
||||
response = GitalyClient.call(
|
||||
@storage,
|
||||
:repository_service,
|
||||
rpc_name,
|
||||
request,
|
||||
timeout: timeout
|
||||
)
|
||||
|
||||
File.open(save_path, 'wb') do |f|
|
||||
response.each do |message|
|
||||
f.write(message.data)
|
||||
end
|
||||
end
|
||||
# If the file is empty means that we recieved an empty stream, we delete the file
|
||||
FileUtils.rm(save_path) if File.zero?(save_path)
|
||||
end
|
||||
|
||||
def gitaly_repo_stream_request(file_path, rpc_name, request_class, timeout)
|
||||
request = request_class.new(repository: @gitaly_repo)
|
||||
enum = Enumerator.new do |y|
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module Gitlab
|
||||
module HealthChecks
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/1218
|
||||
class FsShardsCheck
|
||||
extend BaseAbstractCheck
|
||||
RANDOM_STRING = SecureRandom.hex(1000).freeze
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ module Gitlab
|
|||
module Kubernetes
|
||||
module Helm
|
||||
class InstallCommand < BaseCommand
|
||||
attr_reader :name, :chart, :repository, :values
|
||||
attr_reader :name, :chart, :version, :repository, :values
|
||||
|
||||
def initialize(name, chart:, values:, repository: nil)
|
||||
def initialize(name, chart:, values:, version: nil, repository: nil)
|
||||
@name = name
|
||||
@chart = chart
|
||||
@version = version
|
||||
@values = values
|
||||
@repository = repository
|
||||
end
|
||||
|
|
@ -39,9 +40,13 @@ module Gitlab
|
|||
|
||||
def script_command
|
||||
<<~HEREDOC
|
||||
helm install #{chart} --name #{name} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null
|
||||
helm install #{chart} --name #{name}#{optional_version_flag} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null
|
||||
HEREDOC
|
||||
end
|
||||
|
||||
def optional_version_flag
|
||||
" --version #{version}" if version
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
module Gitlab
|
||||
module Search
|
||||
class ParsedQuery
|
||||
attr_reader :term, :filters
|
||||
|
||||
def initialize(term, filters)
|
||||
@term = term
|
||||
@filters = filters
|
||||
end
|
||||
|
||||
def filter_results(results)
|
||||
filters = @filters.reject { |filter| filter[:matcher].nil? }
|
||||
return unless filters
|
||||
|
||||
results.select do |result|
|
||||
filters.all? do |filter|
|
||||
filter[:matcher].call(filter, result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
module Gitlab
|
||||
module Search
|
||||
class Query < SimpleDelegator
|
||||
def initialize(query, filter_opts = {}, &block)
|
||||
@raw_query = query.dup
|
||||
@filters = []
|
||||
@filter_options = { default_parser: :downcase.to_proc }.merge(filter_opts)
|
||||
|
||||
self.instance_eval(&block) if block_given?
|
||||
|
||||
@query = Gitlab::Search::ParsedQuery.new(*extract_filters)
|
||||
# set the ParsedQuery as our default delegator thanks to SimpleDelegator
|
||||
super(@query)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filter(name, **attributes)
|
||||
filter = { parser: @filter_options[:default_parser], name: name }.merge(attributes)
|
||||
|
||||
@filters << filter
|
||||
end
|
||||
|
||||
def filter_options(**options)
|
||||
@filter_options.merge!(options)
|
||||
end
|
||||
|
||||
def extract_filters
|
||||
fragments = []
|
||||
|
||||
filters = @filters.each_with_object([]) do |filter, parsed_filters|
|
||||
match = @raw_query.split.find { |part| part =~ /\A#{filter[:name]}:/ }
|
||||
next unless match
|
||||
|
||||
input = match.split(':')[1..-1].join
|
||||
next if input.empty?
|
||||
|
||||
filter[:value] = parse_filter(filter, input)
|
||||
filter[:regex_value] = Regexp.escape(filter[:value]).gsub('\*', '.*?')
|
||||
fragments << match
|
||||
|
||||
parsed_filters << filter
|
||||
end
|
||||
|
||||
query = (@raw_query.split - fragments).join(' ')
|
||||
|
||||
[query, filters]
|
||||
end
|
||||
|
||||
def parse_filter(filter, input)
|
||||
filter[:parser].call(input)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -24,6 +24,7 @@ module Gitlab
|
|||
address = val['gitaly_address']
|
||||
end
|
||||
|
||||
# https://gitlab.com/gitlab-org/gitaly/issues/1238
|
||||
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
||||
storages << { name: key, path: val.legacy_disk_path }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
# Gitaly note: JV: two sets of straightforward RPC's. 1 Hard RPC: fork_repository.
|
||||
# SSH key operations are not part of Gitaly so will never be migrated.
|
||||
# Gitaly note: SSH key operations are not part of Gitaly so will never be migrated.
|
||||
|
||||
require 'securerandom'
|
||||
|
||||
|
|
@ -153,8 +152,6 @@ module Gitlab
|
|||
#
|
||||
# Ex.
|
||||
# mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new")
|
||||
#
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/873
|
||||
def mv_repository(storage, path, new_path)
|
||||
return false if path.empty? || new_path.empty?
|
||||
|
||||
|
|
@ -169,19 +166,11 @@ module Gitlab
|
|||
#
|
||||
# Ex.
|
||||
# fork_repository("nfs-file06", "gitlab/gitlab-ci", "nfs-file07", "new-namespace/gitlab-ci")
|
||||
#
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/817
|
||||
def fork_repository(forked_from_storage, forked_from_disk_path, forked_to_storage, forked_to_disk_path)
|
||||
forked_from_relative_path = "#{forked_from_disk_path}.git"
|
||||
fork_args = [forked_to_storage, "#{forked_to_disk_path}.git"]
|
||||
|
||||
gitaly_migrate(:fork_repository, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
|
||||
if is_enabled
|
||||
GitalyGitlabProjects.new(forked_from_storage, forked_from_relative_path).fork_repository(*fork_args)
|
||||
else
|
||||
gitlab_projects(forked_from_storage, forked_from_relative_path).fork_repository(*fork_args)
|
||||
end
|
||||
end
|
||||
GitalyGitlabProjects.new(forked_from_storage, forked_from_relative_path).fork_repository(*fork_args)
|
||||
end
|
||||
|
||||
# Removes a repository from file system, using rm_diretory which is an alias
|
||||
|
|
@ -193,8 +182,6 @@ module Gitlab
|
|||
#
|
||||
# Ex.
|
||||
# remove_repository("/path/to/storage", "gitlab/gitlab-ci")
|
||||
#
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/873
|
||||
def remove_repository(storage, name)
|
||||
return false if name.empty?
|
||||
|
||||
|
|
|
|||
|
|
@ -53,25 +53,34 @@ namespace :gettext do
|
|||
task :updated_check do
|
||||
# Removing all pre-translated files speeds up `gettext:find` as the
|
||||
# files don't need to be merged.
|
||||
`rm locale/*/gitlab.po`
|
||||
# Having `LC_MESSAGES/gitlab.mo files present also confuses the output.
|
||||
FileUtils.rm Dir['locale/**/gitlab.*']
|
||||
|
||||
# Make sure we start out with a clean pot.file
|
||||
`git checkout -- locale/gitlab.pot`
|
||||
|
||||
# `gettext:find` writes touches to temp files to `stderr` which would cause
|
||||
# `static-analysis` to report failures. We can ignore these
|
||||
silence_stream(STDERR) { Rake::Task['gettext:find'].invoke }
|
||||
# `static-analysis` to report failures. We can ignore these.
|
||||
silence_stream($stderr) do
|
||||
Rake::Task['gettext:find'].invoke
|
||||
end
|
||||
|
||||
changed_files = `git diff --name-only`.lines.map(&:strip)
|
||||
pot_diff = `git diff -- locale/gitlab.pot`.strip
|
||||
|
||||
# reset the locale folder for potential next tasks
|
||||
`git checkout -- locale`
|
||||
|
||||
if changed_files.include?('locale/gitlab.pot')
|
||||
if pot_diff.present?
|
||||
raise <<~MSG
|
||||
Newly translated strings found, please add them to `gitlab.pot` by running:
|
||||
|
||||
bundle exec rake gettext:find; git checkout -- locale/*/gitlab.po;
|
||||
rm locale/**/gitlab.*; bin/rake gettext:find; git checkout -- locale/*/gitlab.po
|
||||
|
||||
Then commit and push the resulting changes to `locale/gitlab.pot`.
|
||||
|
||||
The diff was:
|
||||
|
||||
#{pot_diff}
|
||||
MSG
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,13 +17,22 @@ unless Rails.env.production?
|
|||
Rake::Task['eslint'].invoke
|
||||
end
|
||||
|
||||
desc "GitLab | lint | Lint HAML files"
|
||||
task :haml do
|
||||
begin
|
||||
Rake::Task['haml_lint'].invoke
|
||||
rescue RuntimeError # The haml_lint tasks raise a RuntimeError
|
||||
exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
desc "GitLab | lint | Run several lint checks"
|
||||
task :all do
|
||||
status = 0
|
||||
|
||||
%w[
|
||||
config_lint
|
||||
haml_lint
|
||||
lint:haml
|
||||
scss_lint
|
||||
flay
|
||||
gettext:lint
|
||||
|
|
@ -39,13 +48,12 @@ unless Rails.env.production?
|
|||
$stderr.reopen(wr_err)
|
||||
|
||||
begin
|
||||
begin
|
||||
Rake::Task[task].invoke
|
||||
rescue RuntimeError # The haml_lint tasks raise a RuntimeError
|
||||
exit(1)
|
||||
end
|
||||
Rake::Task[task].invoke
|
||||
rescue SystemExit => ex
|
||||
msg = "*** Rake task #{task} failed with the following error(s):"
|
||||
msg = "*** Rake task #{task} exited:"
|
||||
raise ex
|
||||
rescue => ex
|
||||
msg = "*** Rake task #{task} raised #{ex.class}:"
|
||||
raise ex
|
||||
ensure
|
||||
$stdout.reopen(stdout)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"dev-server": "nodemon -w 'config/webpack.config.js' --exec 'webpack-dev-server --config config/webpack.config.js'",
|
||||
"eslint": "eslint --max-warnings 0 --ext .js,.vue .",
|
||||
"eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .",
|
||||
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .",
|
||||
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .",
|
||||
"karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
|
||||
"karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
|
||||
"karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
|
||||
|
|
|
|||
|
|
@ -26,54 +26,59 @@ module QA
|
|||
end
|
||||
|
||||
def initialize
|
||||
# The login page is usually the entry point for all the scenarios so
|
||||
# we need to wait for the instance to start. That said, in some cases
|
||||
# we are already logged-in so we check both cases here.
|
||||
wait(max: 500) do
|
||||
page.has_css?('.application')
|
||||
end
|
||||
end
|
||||
|
||||
def set_initial_password_if_present
|
||||
if page.has_content?('Change your password')
|
||||
fill_in :user_password, with: Runtime::User.password
|
||||
fill_in :user_password_confirmation, with: Runtime::User.password
|
||||
click_button 'Change your password'
|
||||
page.has_css?('.login-page') ||
|
||||
Page::Menu::Main.act { has_personal_area? }
|
||||
end
|
||||
end
|
||||
|
||||
def sign_in_using_credentials
|
||||
if Runtime::User.ldap_user?
|
||||
sign_in_using_ldap_credentials
|
||||
else
|
||||
sign_in_using_gitlab_credentials
|
||||
end
|
||||
end
|
||||
# Don't try to log-in if we're already logged-in
|
||||
return if Page::Menu::Main.act { has_personal_area? }
|
||||
|
||||
def sign_in_using_ldap_credentials
|
||||
using_wait_time 0 do
|
||||
set_initial_password_if_present
|
||||
|
||||
click_link 'LDAP'
|
||||
|
||||
fill_in :username, with: Runtime::User.ldap_username
|
||||
fill_in :password, with: Runtime::User.ldap_password
|
||||
click_button 'Sign in'
|
||||
end
|
||||
end
|
||||
|
||||
def sign_in_using_gitlab_credentials
|
||||
using_wait_time 0 do
|
||||
set_initial_password_if_present
|
||||
|
||||
click_link 'Standard' if page.has_content?('LDAP')
|
||||
|
||||
fill_in :user_login, with: Runtime::User.name
|
||||
fill_in :user_password, with: Runtime::User.password
|
||||
click_button 'Sign in'
|
||||
if Runtime::User.ldap_user?
|
||||
sign_in_using_ldap_credentials
|
||||
else
|
||||
sign_in_using_gitlab_credentials
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.path
|
||||
'/users/sign_in'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sign_in_using_ldap_credentials
|
||||
click_link 'LDAP'
|
||||
|
||||
fill_in :username, with: Runtime::User.ldap_username
|
||||
fill_in :password, with: Runtime::User.ldap_password
|
||||
click_button 'Sign in'
|
||||
end
|
||||
|
||||
def sign_in_using_gitlab_credentials
|
||||
click_link 'Standard' if page.has_content?('LDAP')
|
||||
|
||||
fill_in :user_login, with: Runtime::User.name
|
||||
fill_in :user_password, with: Runtime::User.password
|
||||
click_button 'Sign in'
|
||||
end
|
||||
|
||||
def set_initial_password_if_present
|
||||
return unless page.has_content?('Change your password')
|
||||
|
||||
fill_in :user_password, with: Runtime::User.password
|
||||
fill_in :user_password_confirmation, with: Runtime::User.password
|
||||
click_button 'Change your password'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue