diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ba840d1ced0..630c82bcc5c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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 diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index 7c9c08e3e18..a73edd3f65f 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -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 diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 72de3b5d726..22b062563b5 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -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) { diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 3007b5f1518..15bb35dd0be 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -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 diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index 427fd3e7d85..2932e558a37 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -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 diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb index b7f7e617825..733d21daec1 100644 --- a/app/helpers/avatars_helper.rb +++ b/app/helpers/avatars_helper.rb @@ -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) diff --git a/app/models/commit.rb b/app/models/commit.rb index 57069280ef7..aae49c36899 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -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 } diff --git a/changelogs/unreleased/12564-email-regex.yml b/changelogs/unreleased/12564-email-regex.yml new file mode 100644 index 00000000000..68f489d31ef --- /dev/null +++ b/changelogs/unreleased/12564-email-regex.yml @@ -0,0 +1,5 @@ +--- +title: Adjust placeholder to solve misleading regex +merge_request: 18235 +author: +type: fixed diff --git a/changelogs/unreleased/id-blame-controller-performance.yml b/changelogs/unreleased/id-blame-controller-performance.yml new file mode 100644 index 00000000000..2f7477adfde --- /dev/null +++ b/changelogs/unreleased/id-blame-controller-performance.yml @@ -0,0 +1,5 @@ +--- +title: Optimize SQL requests for BlameController and CommitsController +merge_request: 18342 +author: +type: performance diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md index 9b6c753375e..9e47f7767fe 100644 --- a/doc/administration/gitaly/praefect.md +++ b/doc/administration/gitaly/praefect.md @@ -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 diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index f2df6209492..6520c7dbbcf 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -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` diff --git a/doc/ssh/README.md b/doc/ssh/README.md index aacc1e4edd3..07b426b7f28 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -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 + ssh-keygen -p -f ``` +### 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 diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md index d3d4bf30438..dc6f859e881 100644 --- a/doc/user/clusters/applications.md +++ b/doc/user/clusters/applications.md @@ -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. diff --git a/lib/gitlab/blame.rb b/lib/gitlab/blame.rb index f1a653a9d95..5382bdab7eb 100644 --- a/lib/gitlab/blame.rb +++ b/lib/gitlab/blame.rb @@ -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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0efaa04625c..be2ab49fc4c 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/scripts/review_apps/base-config.yaml b/scripts/review_apps/base-config.yaml index e839ccc2417..de5e14af4d4 100644 --- a/scripts/review_apps/base-config.yaml +++ b/scripts/review_apps/base-config.yaml @@ -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: diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 2fc79272c21..2b923df40c5 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -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) diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb index f7b35e76925..a0bf48f218a 100644 --- a/spec/finders/todos_finder_spec.rb +++ b/spec/finders/todos_finder_spec.rb @@ -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) }