Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
429d1abad2
commit
8c30d396c5
18 changed files with 148 additions and 84 deletions
|
@ -15,7 +15,7 @@ variables:
|
|||
RAILS_ENV: "test"
|
||||
NODE_ENV: "test"
|
||||
SIMPLECOV: "true"
|
||||
GIT_DEPTH: "20"
|
||||
GIT_DEPTH: "50"
|
||||
GIT_SUBMODULE_STRATEGY: "none"
|
||||
GET_SOURCES_ATTEMPTS: "3"
|
||||
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/report-master.json
|
||||
|
|
|
@ -72,5 +72,3 @@ schedule:package-and-qa:
|
|||
- .only-code-qa-changes
|
||||
- .only-canonical-schedules
|
||||
needs: ["build-qa-image", "gitlab:assets:compile"]
|
||||
# Allowed to fail until https://gitlab.com/gitlab-org/gitlab/issues/33272 is fixed.
|
||||
allow_failure: true
|
||||
|
|
|
@ -32,7 +32,6 @@ export default class LabelsSelect {
|
|||
$selectbox,
|
||||
$sidebarCollapsedValue,
|
||||
$value,
|
||||
$dropdownMenu,
|
||||
abilityName,
|
||||
defaultLabel,
|
||||
issueUpdateURL,
|
||||
|
@ -68,7 +67,6 @@ export default class LabelsSelect {
|
|||
$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span');
|
||||
$sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip');
|
||||
$value = $block.find('.value');
|
||||
$dropdownMenu = $dropdown.parent().find('.dropdown-menu');
|
||||
$loading = $block.find('.block-loading').fadeOut();
|
||||
fieldName = $dropdown.data('fieldName');
|
||||
initialSelected = $selectbox
|
||||
|
@ -456,21 +454,9 @@ export default class LabelsSelect {
|
|||
}
|
||||
|
||||
$loading.fadeIn();
|
||||
const oldLabels = boardsStore.detail.issue.labels;
|
||||
|
||||
boardsStore.detail.issue
|
||||
.update($dropdown.attr('data-issue-update'))
|
||||
.then(() => {
|
||||
if (isScopedLabel(label)) {
|
||||
const prevIds = oldLabels.map(label => label.id);
|
||||
const newIds = boardsStore.detail.issue.labels.map(label => label.id);
|
||||
const differentIds = _.difference(prevIds, newIds);
|
||||
$dropdown.data('marked', newIds);
|
||||
$dropdownMenu
|
||||
.find(differentIds.map(id => `[data-label-id="${id}"]`).join(','))
|
||||
.removeClass('is-active');
|
||||
}
|
||||
})
|
||||
.then(fadeOutLoader)
|
||||
.catch(fadeOutLoader);
|
||||
} else if (handleClick) {
|
||||
|
|
|
@ -72,6 +72,8 @@ class Projects::CommitsController < Projects::ApplicationController
|
|||
@repository.commits(@ref, path: @path, limit: @limit, offset: @offset)
|
||||
end
|
||||
|
||||
@commits.each(&:lazy_author) # preload authors
|
||||
|
||||
@commits = @commits.with_latest_pipeline(@ref)
|
||||
@commits = set_commits_for_rendering(@commits)
|
||||
end
|
||||
|
|
|
@ -65,8 +65,20 @@ class TodosFinder
|
|||
params[:action_id]
|
||||
end
|
||||
|
||||
def action_array_provided?
|
||||
params[:action].is_a?(Array)
|
||||
end
|
||||
|
||||
def map_actions_to_ids
|
||||
params[:action].map { |item| Todo::ACTION_NAMES.key(item.to_sym) }
|
||||
end
|
||||
|
||||
def to_action_id
|
||||
Todo::ACTION_NAMES.key(action.to_sym)
|
||||
if action_array_provided?
|
||||
map_actions_to_ids
|
||||
else
|
||||
Todo::ACTION_NAMES.key(action.to_sym)
|
||||
end
|
||||
end
|
||||
|
||||
def action?
|
||||
|
@ -133,9 +145,19 @@ class TodosFinder
|
|||
end
|
||||
end
|
||||
|
||||
def action_id_array_provided?
|
||||
params[:action_id].is_a?(Array) && params[:action_id].any?
|
||||
end
|
||||
|
||||
def by_action_ids(items)
|
||||
items.for_action(action_id)
|
||||
end
|
||||
|
||||
def by_action_id(items)
|
||||
return by_action_ids(items) if action_id_array_provided?
|
||||
|
||||
if action_id?
|
||||
items.for_action(action_id)
|
||||
by_action_ids(items)
|
||||
else
|
||||
items
|
||||
end
|
||||
|
|
|
@ -56,16 +56,6 @@ module AvatarsHelper
|
|||
}))
|
||||
end
|
||||
|
||||
def user_avatar_url_for(only_path: true, **options)
|
||||
if options[:url]
|
||||
options[:url]
|
||||
elsif options[:user]
|
||||
avatar_icon_for_user(options[:user], options[:size], only_path: only_path)
|
||||
else
|
||||
avatar_icon_for_email(options[:user_email], options[:size], only_path: only_path)
|
||||
end
|
||||
end
|
||||
|
||||
def user_avatar_without_link(options = {})
|
||||
avatar_size = options[:size] || 16
|
||||
user_name = options[:user].try(:name) || options[:user_name]
|
||||
|
@ -111,6 +101,19 @@ module AvatarsHelper
|
|||
|
||||
private
|
||||
|
||||
def user_avatar_url_for(only_path: true, **options)
|
||||
return options[:url] if options[:url]
|
||||
|
||||
email = options[:user_email]
|
||||
user = options.key?(:user) ? options[:user] : User.find_by_any_email(email)
|
||||
|
||||
if user
|
||||
avatar_icon_for_user(user, options[:size], only_path: only_path)
|
||||
else
|
||||
gravatar_icon(email, options[:size])
|
||||
end
|
||||
end
|
||||
|
||||
def source_icon(source, options = {})
|
||||
avatar_url = source.try(:avatar_url)
|
||||
|
||||
|
|
|
@ -257,10 +257,9 @@ class Commit
|
|||
end
|
||||
|
||||
def author
|
||||
# We use __sync so that we get the actual objects back (including an actual
|
||||
# nil), instead of a wrapper, as returning a wrapped nil breaks a lot of
|
||||
# code.
|
||||
lazy_author.__sync
|
||||
strong_memoize(:author) do
|
||||
lazy_author&.itself
|
||||
end
|
||||
end
|
||||
request_cache(:author) { author_email.downcase }
|
||||
|
||||
|
|
5
changelogs/unreleased/12564-email-regex.yml
Normal file
5
changelogs/unreleased/12564-email-regex.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Adjust placeholder to solve misleading regex
|
||||
merge_request: 18235
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Optimize SQL requests for BlameController and CommitsController
|
||||
merge_request: 18342
|
||||
author:
|
||||
type: performance
|
|
@ -3,6 +3,19 @@
|
|||
NOTE: **Note:** Praefect is an experimental service, and for testing purposes only at
|
||||
this time.
|
||||
|
||||
Praefect is an optional reverse-proxy for [Gitaly](../index.md) to manage a
|
||||
cluster of Gitaly nodes for high availability through replication.
|
||||
If a Gitaly node becomes unavailable, it will be possible to fail over to a
|
||||
warm Gitaly replica.
|
||||
|
||||
The first minimal version will support:
|
||||
|
||||
- Eventual consistency of the secondary replicas.
|
||||
- Manual fail over from the primary to the secondary.
|
||||
|
||||
Follow the [HA Gitaly epic](https://gitlab.com/groups/gitlab-org/-/epics/1489)
|
||||
for updates and roadmap.
|
||||
|
||||
## Omnibus
|
||||
|
||||
### Architecture
|
||||
|
|
|
@ -58,7 +58,7 @@ each pipeline includes the following [variables](../ci/variables/README.md):
|
|||
- `RAILS_ENV: "test"`
|
||||
- `NODE_ENV: "test"`
|
||||
- `SIMPLECOV: "true"`
|
||||
- `GIT_DEPTH: "20"`
|
||||
- `GIT_DEPTH: "50"`
|
||||
- `GIT_SUBMODULE_STRATEGY: "none"`
|
||||
- `GET_SOURCES_ATTEMPTS: "3"`
|
||||
- `KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json`
|
||||
|
|
|
@ -83,20 +83,6 @@ The minimum key size is 1024 bits, defaulting to 2048. If you wish to generate a
|
|||
stronger RSA key pair, specify the `-b` flag with a higher bit value than the
|
||||
default.
|
||||
|
||||
The old, default password encoding for SSH private keys is
|
||||
[insecure](https://latacora.micro.blog/the-default-openssh/);
|
||||
it's only a single round of an MD5 hash. Since OpenSSH version 6.5, you should
|
||||
use the `-o` option to `ssh-keygen` to encode your private key in a new, more
|
||||
secure format.
|
||||
|
||||
If you already have an RSA SSH key pair to use with GitLab, consider upgrading it
|
||||
to use the more secure password encryption format by using the following command
|
||||
on the private key:
|
||||
|
||||
```bash
|
||||
ssh-keygen -o -f ~/.ssh/id_rsa
|
||||
```
|
||||
|
||||
## Generating a new SSH key pair
|
||||
|
||||
Before creating an SSH key pair, make sure to understand the
|
||||
|
@ -114,7 +100,7 @@ To create a new SSH key pair:
|
|||
Or, if you want to use RSA:
|
||||
|
||||
```bash
|
||||
ssh-keygen -o -t rsa -b 4096 -C "email@example.com"
|
||||
ssh-keygen -t rsa -b 4096 -C "email@example.com"
|
||||
```
|
||||
|
||||
The `-C` flag adds a comment in the key in case you have multiple of them
|
||||
|
@ -139,9 +125,31 @@ To create a new SSH key pair:
|
|||
you can use the `-p` flag:
|
||||
|
||||
```
|
||||
ssh-keygen -p -o -f <keyname>
|
||||
ssh-keygen -p -f <keyname>
|
||||
```
|
||||
|
||||
### OpenSSH < v7.8
|
||||
|
||||
Pre OpenSSH 7.8, default password encoding for SSH private keys was
|
||||
[insecure](https://latacora.micro.blog/the-default-openssh/);
|
||||
it's only a single round of an MD5 hash. For OpenSSH version 6.5 to version 7.8, you should
|
||||
use the `-o` option to `ssh-keygen` to [encode your private key in a new, more
|
||||
secure format.](https://superuser.com/questions/1455735/what-does-ssh-keygen-o-do#answer-1455738)
|
||||
|
||||
If you already have an RSA SSH key pair to use with GitLab, consider upgrading it
|
||||
to use the more secure password encryption format by using the following command
|
||||
on the private key:
|
||||
|
||||
```bash
|
||||
ssh-keygen -o -f ~/.ssh/id_rsa
|
||||
```
|
||||
|
||||
Or generate a new RSA key:
|
||||
|
||||
```bash
|
||||
ssh-keygen -o -t rsa -b 4096 -C "email@example.com"
|
||||
```
|
||||
|
||||
Now, it's time to add the newly created public key to your GitLab account.
|
||||
|
||||
## Adding an SSH key to your GitLab account
|
||||
|
|
|
@ -132,13 +132,17 @@ chart is used to install this application with a
|
|||
[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/ingress/values.yaml)
|
||||
file.
|
||||
|
||||
#### Modsecurity Application Firewall
|
||||
#### Web Application Firewall (ModSecurity)
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/65192) in GitLab 12.3 (enabled using `ingress_modsecurity` [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development)).
|
||||
|
||||
GitLab supports
|
||||
Out of the box, GitLab provides you real-time security monitoring with
|
||||
[`modsecurity`](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#modsecurity)
|
||||
to check requests against [OWASP's Core Rule Set](https://www.modsecurity.org/CRS/Documentation/).
|
||||
|
||||
Modsecurity is a toolkit for real-time web application monitoring, logging,
|
||||
and access control. With GitLab's offering, the [OWASP's Core Rule Set](https://www.modsecurity.org/CRS/Documentation/), which provides generic attack detection capabilities,
|
||||
is automatically applied.
|
||||
|
||||
This feature:
|
||||
|
||||
- Runs in "Detection-only mode" unless configured otherwise.
|
||||
|
|
|
@ -17,6 +17,7 @@ module Gitlab
|
|||
i = 0
|
||||
blame.each do |commit, line|
|
||||
commit = Commit.new(commit, project)
|
||||
commit.lazy_author # preload author
|
||||
|
||||
sha = commit.sha
|
||||
if prev_sha != sha
|
||||
|
|
|
@ -6519,6 +6519,9 @@ msgstr ""
|
|||
msgid "Everything you need to create a GitLab Pages site using plain HTML."
|
||||
msgstr ""
|
||||
|
||||
msgid "Example: @sub\\.company\\.com$"
|
||||
msgstr ""
|
||||
|
||||
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -67,6 +67,11 @@ gitlab:
|
|||
limits:
|
||||
cpu: 1.2G
|
||||
memory: 2.8G
|
||||
deployment:
|
||||
readinessProbe:
|
||||
initialDelaySeconds: 5 # Default is 0
|
||||
periodSeconds: 15 # Default is 10
|
||||
timeoutSeconds: 5 # Default is 2
|
||||
workhorse:
|
||||
resources:
|
||||
requests:
|
||||
|
@ -75,6 +80,10 @@ gitlab:
|
|||
limits:
|
||||
cpu: 200m
|
||||
memory: 200M
|
||||
readinessProbe:
|
||||
initialDelaySeconds: 5 # Default is 0
|
||||
periodSeconds: 15 # Default is 10
|
||||
timeoutSeconds: 5 # Default is 2
|
||||
gitlab-runner:
|
||||
resources:
|
||||
requests:
|
||||
|
|
|
@ -14,8 +14,6 @@ describe 'Issue Boards', :js do
|
|||
let!(:bug) { create(:label, project: project, name: 'Bug') }
|
||||
let!(:regression) { create(:label, project: project, name: 'Regression') }
|
||||
let!(:stretch) { create(:label, project: project, name: 'Stretch') }
|
||||
let!(:scoped_label_1) { create(:label, project: project, name: 'Scoped::Label1') }
|
||||
let!(:scoped_label_2) { create(:label, project: project, name: 'Scoped::Label2') }
|
||||
let!(:issue1) { create(:labeled_issue, project: project, assignees: [user], milestone: milestone, labels: [development], relative_position: 2) }
|
||||
let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
|
||||
let(:board) { create(:board, project: project) }
|
||||
|
@ -29,8 +27,6 @@ describe 'Issue Boards', :js do
|
|||
end
|
||||
|
||||
before do
|
||||
stub_licensed_features(scoped_labels: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
|
||||
sign_in(user)
|
||||
|
@ -313,33 +309,6 @@ describe 'Issue Boards', :js do
|
|||
expect(card).to have_content(bug.title)
|
||||
end
|
||||
|
||||
it 'removes existing scoped label' do
|
||||
click_card(card)
|
||||
|
||||
page.within('.labels') do
|
||||
click_link 'Edit'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
click_link scoped_label_1.title
|
||||
click_link scoped_label_2.title
|
||||
|
||||
wait_for_requests
|
||||
|
||||
find('.dropdown-menu-close-icon').click
|
||||
|
||||
page.within('.value') do
|
||||
expect(page).to have_selector('.badge', count: 3)
|
||||
expect(page).not_to have_content(scoped_label_1.title)
|
||||
expect(page).to have_content(scoped_label_2.title)
|
||||
end
|
||||
end
|
||||
|
||||
expect(card).to have_selector('.badge', count: 3)
|
||||
expect(card).not_to have_content(scoped_label_1.title)
|
||||
expect(card).to have_content(scoped_label_2.title)
|
||||
end
|
||||
|
||||
it 'adds a multiple labels' do
|
||||
click_card(card)
|
||||
|
||||
|
|
|
@ -36,6 +36,43 @@ describe TodosFinder do
|
|||
expect(todos).to match_array([todo1])
|
||||
end
|
||||
|
||||
context 'when filtering for actions' do
|
||||
let!(:todo1) { create(:todo, user: user, project: project, target: issue, action: Todo::ASSIGNED) }
|
||||
let!(:todo2) { create(:todo, user: user, group: group, target: merge_request, action: Todo::DIRECTLY_ADDRESSED) }
|
||||
|
||||
context 'by action ids' do
|
||||
it 'returns the expected todos' do
|
||||
todos = finder.new(user, { action_id: Todo::DIRECTLY_ADDRESSED }).execute
|
||||
|
||||
expect(todos).to match_array([todo2])
|
||||
end
|
||||
|
||||
context 'multiple actions' do
|
||||
it 'returns the expected todos' do
|
||||
todos = finder.new(user, { action_id: [Todo::DIRECTLY_ADDRESSED, Todo::ASSIGNED] }).execute
|
||||
|
||||
expect(todos).to match_array([todo2, todo1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'by action names' do
|
||||
it 'returns the expected todos' do
|
||||
todos = finder.new(user, { action: :directly_addressed }).execute
|
||||
|
||||
expect(todos).to match_array([todo2])
|
||||
end
|
||||
|
||||
context 'multiple actions' do
|
||||
it 'returns the expected todos' do
|
||||
todos = finder.new(user, { action: [:directly_addressed, :assigned] }).execute
|
||||
|
||||
expect(todos).to match_array([todo2, todo1])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with subgroups' do
|
||||
let(:subgroup) { create(:group, parent: group) }
|
||||
let!(:todo3) { create(:todo, user: user, group: subgroup, target: issue) }
|
||||
|
|
Loading…
Reference in a new issue