Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
edf2742812
commit
a2f16969fa
40 changed files with 333 additions and 80 deletions
|
@ -70,8 +70,8 @@ docs-lint links:
|
|||
# Don't delete the documentation/index.md, which is a false positive for the simple grep.
|
||||
- grep -rl "redirect_to:" /tmp/gitlab-docs/content/ee/ | grep -v "development/documentation/index.md" | xargs rm -f
|
||||
- bundle exec nanoc
|
||||
- echo -e "\e[96mThe following test fails when a doc links to a redirect file."
|
||||
- echo -e "\e[96mMake sure all links point to the correct page."
|
||||
- echo -e "\e[1;96mThe following test fails when a doc links to a redirect file."
|
||||
- echo -e "\e[1;96mMake sure all links point to the correct page."
|
||||
- bundle exec nanoc check internal_links
|
||||
# Check the internal anchor links
|
||||
- bundle exec nanoc check internal_anchors
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -466,7 +466,7 @@ group :ed25519 do
|
|||
end
|
||||
|
||||
# Gitaly GRPC protocol definitions
|
||||
gem 'gitaly', '~> 13.6.1'
|
||||
gem 'gitaly', '~> 13.7.0.pre.rc1'
|
||||
|
||||
gem 'grpc', '~> 1.30.2'
|
||||
|
||||
|
|
|
@ -422,7 +422,7 @@ GEM
|
|||
rails (>= 3.2.0)
|
||||
git (1.7.0)
|
||||
rchardet (~> 1.8)
|
||||
gitaly (13.6.1)
|
||||
gitaly (13.7.0.pre.rc1)
|
||||
grpc (~> 1.0)
|
||||
github-markup (1.7.0)
|
||||
gitlab-chronic (0.10.5)
|
||||
|
@ -1349,7 +1349,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.3)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.3)
|
||||
gitaly (~> 13.6.1)
|
||||
gitaly (~> 13.7.0.pre.rc1)
|
||||
github-markup (~> 1.7.0)
|
||||
gitlab-chronic (~> 0.10.5)
|
||||
gitlab-fog-azure-rm (~> 1.0)
|
||||
|
|
|
@ -539,6 +539,7 @@ export default {
|
|||
<template #total>{{ diffFiles.length }}</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
<gl-loading-icon v-else-if="retrievingBatches" size="lg" />
|
||||
</template>
|
||||
<no-changes v-else :changes-empty-state-illustration="changesEmptyStateIllustration" />
|
||||
</div>
|
||||
|
|
|
@ -75,22 +75,33 @@ export const setBaseConfig = ({ commit }, options) => {
|
|||
};
|
||||
|
||||
export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
|
||||
const diffsGradualLoad = window.gon?.features?.diffsGradualLoad;
|
||||
let perPage = DIFFS_PER_PAGE;
|
||||
let increaseAmount = 1.4;
|
||||
|
||||
if (diffsGradualLoad) {
|
||||
perPage = state.viewDiffsFileByFile ? 1 : 5;
|
||||
}
|
||||
|
||||
const startPage = diffsGradualLoad ? 0 : 1;
|
||||
const id = window?.location?.hash;
|
||||
const isNoteLink = id.indexOf('#note') === 0;
|
||||
const urlParams = {
|
||||
per_page: DIFFS_PER_PAGE,
|
||||
w: state.showWhitespace ? '0' : '1',
|
||||
view: 'inline',
|
||||
};
|
||||
let totalLoaded = 0;
|
||||
|
||||
commit(types.SET_BATCH_LOADING, true);
|
||||
commit(types.SET_RETRIEVING_BATCHES, true);
|
||||
eventHub.$emit(EVT_PERF_MARK_DIFF_FILES_START);
|
||||
|
||||
const getBatch = (page = 1) =>
|
||||
const getBatch = (page = startPage) =>
|
||||
axios
|
||||
.get(mergeUrlParams({ ...urlParams, page }, state.endpointBatch))
|
||||
.get(mergeUrlParams({ ...urlParams, page, per_page: perPage }, state.endpointBatch))
|
||||
.then(({ data: { pagination, diff_files } }) => {
|
||||
totalLoaded += diff_files.length;
|
||||
|
||||
commit(types.SET_DIFF_DATA_BATCH, { diff_files });
|
||||
commit(types.SET_BATCH_LOADING, false);
|
||||
|
||||
|
@ -102,7 +113,10 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
|
|||
dispatch('setCurrentDiffFileIdFromNote', id.split('_').pop());
|
||||
}
|
||||
|
||||
if (!pagination.next_page) {
|
||||
if (
|
||||
(diffsGradualLoad && totalLoaded === pagination.total_pages) ||
|
||||
(!diffsGradualLoad && !pagination.next_page)
|
||||
) {
|
||||
commit(types.SET_RETRIEVING_BATCHES, false);
|
||||
|
||||
// We need to check that the currentDiffFileId points to a file that exists
|
||||
|
@ -128,6 +142,16 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
|
|||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (diffsGradualLoad) {
|
||||
const nextPage = page + perPage;
|
||||
perPage = Math.min(Math.ceil(perPage * increaseAmount), 30);
|
||||
increaseAmount = Math.min(increaseAmount + 0.2, 2);
|
||||
|
||||
return nextPage;
|
||||
}
|
||||
|
||||
return pagination.next_page;
|
||||
|
|
|
@ -42,6 +42,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
push_frontend_feature_flag(:core_security_mr_widget_counts, @project)
|
||||
push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true)
|
||||
push_frontend_feature_flag(:test_failure_history, @project)
|
||||
push_frontend_feature_flag(:diffs_gradual_load, @project)
|
||||
|
||||
record_experiment_user(:invite_members_version_a)
|
||||
record_experiment_user(:invite_members_version_b)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
= form_for [:admin, @group] do |f|
|
||||
= form_errors(@group)
|
||||
= render 'shared/group_form', f: f
|
||||
= render 'shared/group_form_description', f: f
|
||||
|
||||
= render_if_exists 'shared/old_repository_size_limit_setting', form: f, type: :group
|
||||
= render_if_exists 'admin/namespace_plan', f: f
|
||||
|
|
|
@ -2,11 +2,6 @@
|
|||
= render 'shared/group_form', f: f, autofocus: true
|
||||
|
||||
.row
|
||||
.form-group.group-description-holder.col-sm-12
|
||||
= f.label :avatar, _("Group avatar"), class: 'label-bold'
|
||||
%div
|
||||
= render 'shared/choose_avatar_button', f: f
|
||||
|
||||
.form-group.col-sm-12
|
||||
%label.label-bold
|
||||
= _('Visibility level')
|
||||
|
|
|
@ -47,11 +47,3 @@
|
|||
= f.label :id, class: 'label-bold' do
|
||||
= _("Group ID")
|
||||
= f.text_field :id, class: 'form-control', readonly: true
|
||||
|
||||
.row
|
||||
.form-group.group-description-holder.col-sm-8
|
||||
= f.label :description, class: 'label-bold' do
|
||||
= _("Group description")
|
||||
%span (optional)
|
||||
= f.text_area :description, maxlength: 250,
|
||||
class: 'form-control js-gfm-input', rows: 4
|
||||
|
|
5
app/views/shared/_group_form_description.html.haml
Normal file
5
app/views/shared/_group_form_description.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
.row
|
||||
.form-group.group-description-holder.col-sm-8
|
||||
= f.label :description, _('Group description (optional)'), class: 'label-bold'
|
||||
= f.text_area :description, maxlength: 250,
|
||||
class: 'form-control js-gfm-input', rows: 4
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Refine group creation form
|
||||
merge_request: 48490
|
||||
author:
|
||||
type: changed
|
5
changelogs/unreleased/281586_monorepo_nodejsscan.yml
Normal file
5
changelogs/unreleased/281586_monorepo_nodejsscan.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update nodejs-scan rule to wildcard prefix
|
||||
merge_request: 48902
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: diff_check_with_paths_changed_rpc
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46116
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/288827
|
||||
milestone: '13.7'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
8
config/feature_flags/development/diffs_gradual_load.yml
Normal file
8
config/feature_flags/development/diffs_gradual_load.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: diffs_gradual_load
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48253/
|
||||
rollout_issue_url:
|
||||
milestone: '13.7'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
|
@ -1004,9 +1004,6 @@ docker build:
|
|||
allow_failure: true
|
||||
```
|
||||
|
||||
Additional job configuration may be added to rules in the future. If something
|
||||
useful is not available, please [open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues).
|
||||
|
||||
#### Rules clauses
|
||||
|
||||
Available rule clauses are:
|
||||
|
@ -1612,8 +1609,8 @@ Feature.enable(:allow_unsafe_ruby_regexp)
|
|||
|
||||
### `only`/`except` (advanced)
|
||||
|
||||
GitLab supports both simple and complex strategies, so it's possible to use an
|
||||
array and a hash configuration scheme.
|
||||
GitLab supports multiple strategies, and it's possible to use an
|
||||
array or a hash configuration scheme.
|
||||
|
||||
Four keys are available:
|
||||
|
||||
|
@ -2556,9 +2553,6 @@ To follow progress on support for GitLab-managed clusters, see the
|
|||
|
||||
#### Dynamic environments
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21971) in GitLab 8.12 and GitLab Runner 1.6.
|
||||
> - The `$CI_ENVIRONMENT_SLUG` was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22864) in GitLab 8.15.
|
||||
|
||||
Use CI/CD [variables](../variables/README.md) to dynamically name environments.
|
||||
|
||||
For example:
|
||||
|
@ -3273,8 +3267,6 @@ and bring back the old behavior.
|
|||
|
||||
### `coverage`
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20428) in GitLab 8.17.
|
||||
|
||||
Use `coverage` to configure how code coverage is extracted from the
|
||||
job output.
|
||||
|
||||
|
@ -3513,9 +3505,9 @@ In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201938) and later
|
|||
can use [`when:manual`](#whenmanual) in the same job as `trigger`. In GitLab 13.4 and
|
||||
earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
|
||||
|
||||
#### Simple `trigger` syntax for multi-project pipelines
|
||||
#### Basic `trigger` syntax for multi-project pipelines
|
||||
|
||||
The simplest way to configure a downstream trigger is to use `trigger` keyword
|
||||
You can configure a downstream trigger by using the `trigger` keyword
|
||||
with a full path to a downstream project:
|
||||
|
||||
```yaml
|
||||
|
|
|
@ -216,6 +216,29 @@ cron worker sequentially.
|
|||
|
||||
Any update to the Elastic index mappings should be replicated in [`Elastic::Latest::Config`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/elastic/latest/config.rb).
|
||||
|
||||
### Migration options supported by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
|
||||
|
||||
- `batched!` - Allow the migration to run in batches. If set, the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
|
||||
will re-enqueue itself with a delay which is set using the `throttle_delay` option described below. The batching
|
||||
must be handled within the `migrate` method, this setting controls the re-enqueuing only.
|
||||
|
||||
- `throttle_delay` - Sets the wait time in between batch runs. This time should be set high enough to allow each migration batch
|
||||
enough time to finish. Additionally, the time should be less than 30 minutes since that is how often the
|
||||
[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
|
||||
cron worker runs. Default value is 5 minutes.
|
||||
|
||||
```ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
class BatchedMigrationName < Elastic::Migration
|
||||
# Declares a migration should be run in batches
|
||||
batched!
|
||||
throttle_delay 10.minutes
|
||||
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
## Performance Monitoring
|
||||
|
||||
### Prometheus
|
||||
|
|
|
@ -17,17 +17,26 @@ module Gitlab
|
|||
|
||||
file_paths = []
|
||||
|
||||
process_commits do |commit|
|
||||
validate_once(commit) do
|
||||
commit.raw_deltas.each do |diff|
|
||||
file_paths.concat([diff.new_path, diff.old_path].compact)
|
||||
if ::Feature.enabled?(:diff_check_with_paths_changed_rpc, project)
|
||||
paths = project.repository.find_changed_paths(commits.map(&:sha))
|
||||
paths.each do |path|
|
||||
file_paths.concat([path.path])
|
||||
|
||||
validate_diff(diff)
|
||||
validate_diff(path)
|
||||
end
|
||||
else
|
||||
process_commits do |commit|
|
||||
validate_once(commit) do
|
||||
commit.raw_deltas.each do |diff|
|
||||
file_paths.concat([diff.new_path, diff.old_path].compact)
|
||||
|
||||
validate_diff(diff)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
validate_file_paths(file_paths)
|
||||
validate_file_paths(file_paths.uniq)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -173,7 +173,7 @@ nodejs-scan-sast:
|
|||
- if: $CI_COMMIT_BRANCH &&
|
||||
$SAST_DEFAULT_ANALYZERS =~ /nodejs-scan/
|
||||
exists:
|
||||
- 'package.json'
|
||||
- '**/package.json'
|
||||
|
||||
phpcs-security-audit-sast:
|
||||
extends: .sast-analyzer
|
||||
|
|
|
@ -11,7 +11,7 @@ module Gitlab
|
|||
#
|
||||
class MergeRequestDiffBatch < MergeRequestDiffBase
|
||||
DEFAULT_BATCH_PAGE = 1
|
||||
DEFAULT_BATCH_SIZE = 20
|
||||
DEFAULT_BATCH_SIZE = 30
|
||||
|
||||
attr_reader :pagination_data
|
||||
|
||||
|
@ -21,9 +21,9 @@ module Gitlab
|
|||
@paginated_collection = load_paginated_collection(batch_page, batch_size, diff_options)
|
||||
|
||||
@pagination_data = {
|
||||
current_page: @paginated_collection.current_page,
|
||||
next_page: @paginated_collection.next_page,
|
||||
total_pages: @paginated_collection.total_pages
|
||||
current_page: batch_gradual_load? ? nil : @paginated_collection.current_page,
|
||||
next_page: batch_gradual_load? ? nil : @paginated_collection.next_page,
|
||||
total_pages: batch_gradual_load? ? relation.size : @paginated_collection.total_pages
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -62,17 +62,28 @@ module Gitlab
|
|||
@merge_request_diff.merge_request_diff_files
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def load_paginated_collection(batch_page, batch_size, diff_options)
|
||||
batch_page ||= DEFAULT_BATCH_PAGE
|
||||
batch_size ||= DEFAULT_BATCH_SIZE
|
||||
|
||||
paths = diff_options&.fetch(:paths, nil)
|
||||
|
||||
paginated_collection = relation.page(batch_page).per(batch_size)
|
||||
paginated_collection = if batch_gradual_load?
|
||||
relation.offset(batch_page).limit([batch_size.to_i, DEFAULT_BATCH_SIZE].min)
|
||||
else
|
||||
relation.page(batch_page).per(batch_size)
|
||||
end
|
||||
|
||||
paginated_collection = paginated_collection.by_paths(paths) if paths
|
||||
|
||||
paginated_collection
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def batch_gradual_load?
|
||||
Feature.enabled?(:diffs_gradual_load, @merge_request_diff.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -467,6 +467,18 @@ module Gitlab
|
|||
empty_diff_stats
|
||||
end
|
||||
|
||||
def find_changed_paths(commits)
|
||||
processed_commits = commits.reject { |ref| ref.blank? || Gitlab::Git.blank_ref?(ref) }
|
||||
|
||||
return [] if processed_commits.empty?
|
||||
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_commit_client.find_changed_paths(processed_commits)
|
||||
end
|
||||
rescue CommandError, TypeError, NoRepository
|
||||
[]
|
||||
end
|
||||
|
||||
# Returns a RefName for a given SHA
|
||||
def ref_name_for_sha(ref_path, sha)
|
||||
raise ArgumentError, "sha can't be empty" unless sha.present?
|
||||
|
|
|
@ -216,6 +216,23 @@ module Gitlab
|
|||
response.flat_map(&:stats)
|
||||
end
|
||||
|
||||
def find_changed_paths(commits)
|
||||
request = Gitaly::FindChangedPathsRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
commits: commits
|
||||
)
|
||||
|
||||
response = GitalyClient.call(@repository.storage, :diff_service, :find_changed_paths, request, timeout: GitalyClient.medium_timeout)
|
||||
response.flat_map do |msg|
|
||||
msg.paths.map do |path|
|
||||
OpenStruct.new(
|
||||
status: path.status,
|
||||
path: EncodingHelper.encode!(path.path)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_all_commits(opts = {})
|
||||
request = Gitaly::FindAllCommitsRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
|
|
|
@ -21,6 +21,8 @@ module Quality
|
|||
config
|
||||
db
|
||||
dependencies
|
||||
elastic
|
||||
elastic_integration
|
||||
factories
|
||||
finders
|
||||
frontend
|
||||
|
@ -46,7 +48,6 @@ module Quality
|
|||
validators
|
||||
views
|
||||
workers
|
||||
elastic_integration
|
||||
tooling
|
||||
],
|
||||
integration: %w[
|
||||
|
|
|
@ -13241,9 +13241,6 @@ msgstr ""
|
|||
msgid "Group by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Group description"
|
||||
msgstr ""
|
||||
|
||||
msgid "Group description (optional)"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ module QA
|
|||
view 'app/views/shared/_group_form.html.haml' do
|
||||
element :group_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern
|
||||
element :group_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
|
||||
element :group_description_field, 'text_area :description' # rubocop:disable QA/ElementWithPattern
|
||||
end
|
||||
|
||||
view 'app/views/groups/_new_group_fields.html.haml' do
|
||||
|
@ -20,10 +19,6 @@ module QA
|
|||
fill_in 'group_name', with: path
|
||||
end
|
||||
|
||||
def set_description(description)
|
||||
fill_in 'group_description', with: description
|
||||
end
|
||||
|
||||
def set_visibility(visibility)
|
||||
choose visibility
|
||||
end
|
||||
|
|
|
@ -31,6 +31,8 @@ module QA
|
|||
end
|
||||
|
||||
def wait_for_latest_pipeline_status
|
||||
wait_until(max_duration: 30, reload: true, sleep_interval: 5) { has_pipeline? }
|
||||
|
||||
wait_until(reload: false, max_duration: 360) do
|
||||
within_element_by_index(:pipeline_commit_status, 0) { yield }
|
||||
end
|
||||
|
|
|
@ -36,7 +36,6 @@ module QA
|
|||
|
||||
Page::Group::New.perform do |group_new|
|
||||
group_new.set_path(path)
|
||||
group_new.set_description(description)
|
||||
group_new.set_visibility('Public')
|
||||
group_new.create
|
||||
end
|
||||
|
|
|
@ -31,7 +31,6 @@ module QA
|
|||
|
||||
Page::Group::New.perform do |group|
|
||||
group.set_path(path)
|
||||
group.set_description('GitLab QA Sandbox Group')
|
||||
group.set_visibility('Public')
|
||||
group.create
|
||||
end
|
||||
|
|
|
@ -74,6 +74,8 @@ RSpec.describe Projects::MergeRequests::DiffsController do
|
|||
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(diffs_gradual_load: false)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
|
|
@ -7,9 +7,10 @@ RSpec.describe 'Admin Groups' do
|
|||
include Spec::Support::Helpers::Features::MembersHelpers
|
||||
|
||||
let(:internal) { Gitlab::VisibilityLevel::INTERNAL }
|
||||
let(:user) { create :user }
|
||||
let!(:group) { create :group }
|
||||
let!(:current_user) { create(:admin) }
|
||||
|
||||
let_it_be(:user) { create :user }
|
||||
let_it_be(:group) { create :group }
|
||||
let_it_be(:current_user) { create(:admin) }
|
||||
|
||||
before do
|
||||
sign_in(current_user)
|
||||
|
@ -26,6 +27,17 @@ RSpec.describe 'Admin Groups' do
|
|||
end
|
||||
|
||||
describe 'create a group' do
|
||||
describe 'with expected fields' do
|
||||
it 'renders from as expected', :aggregate_failures do
|
||||
visit new_admin_group_path
|
||||
|
||||
expect(page).to have_field('name')
|
||||
expect(page).to have_field('group_path')
|
||||
expect(page).to have_field('group_visibility_level_0')
|
||||
expect(page).to have_field('description')
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates new group' do
|
||||
visit admin_groups_path
|
||||
|
||||
|
|
|
@ -17,14 +17,11 @@ RSpec.describe 'Dashboard Group' do
|
|||
visit dashboard_groups_path
|
||||
find('.btn-success').click
|
||||
new_name = 'Samurai'
|
||||
new_description = 'Tokugawa Shogunate'
|
||||
|
||||
fill_in 'group_name', with: new_name
|
||||
fill_in 'group_description', with: new_description
|
||||
click_button 'Create group'
|
||||
|
||||
expect(current_path).to eq group_path(Group.find_by(name: new_name))
|
||||
expect(page).to have_content(new_name)
|
||||
expect(page).to have_content(new_description)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Group' do
|
||||
let(:user) { create(:user) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
|
@ -36,6 +36,15 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'with expected fields' do
|
||||
it 'renders from as expected', :aggregate_failures do
|
||||
expect(page).to have_field('name')
|
||||
expect(page).to have_field('group_path')
|
||||
expect(page).to have_field('group_visibility_level_0')
|
||||
expect(page).not_to have_field('description')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with space in group path' do
|
||||
it 'renders new group form with validation errors' do
|
||||
fill_in 'Group URL', with: 'space group'
|
||||
|
@ -135,7 +144,7 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
|
||||
describe 'create a nested group', :js do
|
||||
let(:group) { create(:group, path: 'foo') }
|
||||
let_it_be(:group) { create(:group, path: 'foo') }
|
||||
|
||||
context 'as admin' do
|
||||
let(:user) { create(:admin) }
|
||||
|
@ -185,8 +194,8 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
|
||||
describe 'group edit', :js do
|
||||
let(:group) { create(:group, :public) }
|
||||
let(:path) { edit_group_path(group) }
|
||||
let_it_be(:group) { create(:group, :public) }
|
||||
let(:path) { edit_group_path(group) }
|
||||
let(:new_name) { 'new-name' }
|
||||
|
||||
before do
|
||||
|
@ -230,8 +239,8 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
|
||||
describe 'group page with markdown description' do
|
||||
let(:group) { create(:group) }
|
||||
let(:path) { group_path(group) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let(:path) { group_path(group) }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
|
@ -271,9 +280,9 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
|
||||
describe 'group page with nested groups', :js do
|
||||
let!(:group) { create(:group) }
|
||||
let!(:nested_group) { create(:group, parent: group) }
|
||||
let!(:project) { create(:project, namespace: group) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:nested_group) { create(:group, parent: group) }
|
||||
let_it_be(:project) { create(:project, namespace: group) }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
|
@ -304,7 +313,11 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
|
||||
describe 'new subgroup / project button' do
|
||||
let(:group) { create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS, subgroup_creation_level: Gitlab::Access::OWNER_SUBGROUP_ACCESS) }
|
||||
let_it_be(:group, reload: true) do
|
||||
create(:group,
|
||||
project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS,
|
||||
subgroup_creation_level: Gitlab::Access::OWNER_SUBGROUP_ACCESS)
|
||||
end
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
|
@ -341,6 +354,7 @@ RSpec.describe 'Group' do
|
|||
context 'when user has project and subgroup creation permissions' do
|
||||
it 'displays "New subgroup" and "New project" buttons' do
|
||||
group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
|
||||
|
||||
visit group_path(group)
|
||||
|
||||
page.within '[data-testid="group-buttons"]' do
|
||||
|
|
|
@ -17,6 +17,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
|
|||
let!(:params) { {} }
|
||||
|
||||
before do
|
||||
stub_feature_flags(diffs_gradual_load: false)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
visit diffs_project_merge_request_path(project, merge_request, params)
|
||||
|
|
|
@ -160,10 +160,10 @@ describe('DiffsStoreActions', () => {
|
|||
.onGet(
|
||||
mergeUrlParams(
|
||||
{
|
||||
per_page: DIFFS_PER_PAGE,
|
||||
w: '1',
|
||||
view: 'inline',
|
||||
page: 1,
|
||||
per_page: DIFFS_PER_PAGE,
|
||||
},
|
||||
endpointBatch,
|
||||
),
|
||||
|
@ -172,10 +172,10 @@ describe('DiffsStoreActions', () => {
|
|||
.onGet(
|
||||
mergeUrlParams(
|
||||
{
|
||||
per_page: DIFFS_PER_PAGE,
|
||||
w: '1',
|
||||
view: 'inline',
|
||||
page: 2,
|
||||
per_page: DIFFS_PER_PAGE,
|
||||
},
|
||||
endpointBatch,
|
||||
),
|
||||
|
|
|
@ -7,7 +7,6 @@ RSpec.describe Gitlab::Checks::DiffCheck do
|
|||
|
||||
describe '#validate!' do
|
||||
let(:owner) { create(:user) }
|
||||
let!(:lock) { create(:lfs_file_lock, user: owner, project: project, path: 'README') }
|
||||
|
||||
before do
|
||||
allow(project.repository).to receive(:new_commits).and_return(
|
||||
|
@ -28,13 +27,27 @@ RSpec.describe Gitlab::Checks::DiffCheck do
|
|||
end
|
||||
|
||||
context 'with LFS enabled' do
|
||||
let!(:lock) { create(:lfs_file_lock, user: owner, project: project, path: 'README') }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:lfs_enabled?).and_return(true)
|
||||
end
|
||||
|
||||
context 'when change is sent by a different user' do
|
||||
it 'raises an error if the user is not allowed to update the file' do
|
||||
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
|
||||
context 'when diff check with paths rpc feature flag is true' do
|
||||
it 'raises an error if the user is not allowed to update the file' do
|
||||
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when diff check with paths rpc feature flag is false' do
|
||||
before do
|
||||
stub_feature_flags(diff_check_with_paths_changed_rpc: false)
|
||||
end
|
||||
|
||||
it 'raises an error if the user is not allowed to update the file' do
|
||||
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,6 +66,8 @@ RSpec.describe Gitlab::Checks::DiffCheck do
|
|||
|
||||
expect_any_instance_of(Commit).to receive(:raw_deltas).and_call_original
|
||||
|
||||
stub_feature_flags(diff_check_with_paths_changed_rpc: false)
|
||||
|
||||
subject.validate!
|
||||
end
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch do
|
|||
|
||||
let(:diff_files) { subject.diff_files }
|
||||
|
||||
before do
|
||||
stub_feature_flags(diffs_gradual_load: false)
|
||||
end
|
||||
|
||||
describe 'initialize' do
|
||||
it 'memoizes pagination_data' do
|
||||
expect(subject.pagination_data).to eq(current_page: 1, next_page: 2, total_pages: 2)
|
||||
|
@ -97,6 +101,18 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch do
|
|||
expect(collection.diff_files.map(&:new_path)).to eq(expected_batch_files)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with diffs gradual load feature flag enabled' do
|
||||
let(:batch_page) { 0 }
|
||||
|
||||
before do
|
||||
stub_feature_flags(diffs_gradual_load: true)
|
||||
end
|
||||
|
||||
it 'returns correct diff files' do
|
||||
expect(subject.diffs.map(&:new_path)).to eq(diff_files_relation.page(1).per(batch_size).map(&:new_path))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'unfoldable diff' do
|
||||
|
|
|
@ -1185,6 +1185,66 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#find_changed_paths' do
|
||||
let(:commit_1) { 'fa1b1e6c004a68b7d8763b86455da9e6b23e36d6' }
|
||||
let(:commit_2) { '4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6' }
|
||||
let(:commit_3) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
|
||||
let(:commit_1_files) do
|
||||
[
|
||||
OpenStruct.new(status: :ADDED, path: "files/executables/ls"),
|
||||
OpenStruct.new(status: :ADDED, path: "files/executables/touch"),
|
||||
OpenStruct.new(status: :ADDED, path: "files/links/regex.rb"),
|
||||
OpenStruct.new(status: :ADDED, path: "files/links/ruby-style-guide.md"),
|
||||
OpenStruct.new(status: :ADDED, path: "files/links/touch"),
|
||||
OpenStruct.new(status: :MODIFIED, path: ".gitmodules"),
|
||||
OpenStruct.new(status: :ADDED, path: "deeper/nested/six"),
|
||||
OpenStruct.new(status: :ADDED, path: "nested/six")
|
||||
]
|
||||
end
|
||||
|
||||
let(:commit_2_files) do
|
||||
[OpenStruct.new(status: :ADDED, path: "bin/executable")]
|
||||
end
|
||||
|
||||
let(:commit_3_files) do
|
||||
[
|
||||
OpenStruct.new(status: :MODIFIED, path: ".gitmodules"),
|
||||
OpenStruct.new(status: :ADDED, path: "gitlab-shell")
|
||||
]
|
||||
end
|
||||
|
||||
it 'returns a list of paths' do
|
||||
collection = repository.find_changed_paths([commit_1, commit_2, commit_3])
|
||||
|
||||
expect(collection).to be_a(Enumerable)
|
||||
expect(collection.to_a).to eq(commit_1_files + commit_2_files + commit_3_files)
|
||||
end
|
||||
|
||||
it 'returns no paths when SHAs are invalid' do
|
||||
collection = repository.find_changed_paths(['invalid', commit_1])
|
||||
|
||||
expect(collection).to be_a(Enumerable)
|
||||
expect(collection.to_a).to be_empty
|
||||
end
|
||||
|
||||
it 'returns a list of paths even when containing a blank ref' do
|
||||
collection = repository.find_changed_paths([nil, commit_1])
|
||||
|
||||
expect(collection).to be_a(Enumerable)
|
||||
expect(collection.to_a).to eq(commit_1_files)
|
||||
end
|
||||
|
||||
it 'returns no paths when the commits are nil' do
|
||||
expect_any_instance_of(Gitlab::GitalyClient::CommitService)
|
||||
.not_to receive(:find_changed_paths)
|
||||
|
||||
collection = repository.find_changed_paths([nil, nil])
|
||||
|
||||
expect(collection).to be_a(Enumerable)
|
||||
expect(collection.to_a).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe "#ls_files" do
|
||||
let(:master_file_paths) { repository.ls_files("master") }
|
||||
let(:utf8_file_paths) { repository.ls_files("ls-files-utf8") }
|
||||
|
|
|
@ -145,6 +145,31 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#find_changed_paths' do
|
||||
let(:commits) { %w[1a0b36b3cdad1d2ee32457c102a8c0b7056fa863 cfe32cf61b73a0d5e9f13e774abde7ff789b1660] }
|
||||
|
||||
it 'sends an RPC request and returns the stats' do
|
||||
request = Gitaly::FindChangedPathsRequest.new(repository: repository_message,
|
||||
commits: commits)
|
||||
|
||||
changed_paths_response = Gitaly::FindChangedPathsResponse.new(
|
||||
paths: [{
|
||||
path: "app/assets/javascripts/boards/components/project_select.vue",
|
||||
status: :MODIFIED
|
||||
}])
|
||||
|
||||
expect_any_instance_of(Gitaly::DiffService::Stub).to receive(:find_changed_paths)
|
||||
.with(request, kind_of(Hash)).and_return([changed_paths_response])
|
||||
|
||||
returned_value = described_class.new(repository).find_changed_paths(commits)
|
||||
|
||||
mapped_returned_value = returned_value.map(&:to_h)
|
||||
mapped_expected_value = changed_paths_response.paths.map(&:to_h)
|
||||
|
||||
expect(mapped_returned_value).to eq(mapped_expected_value)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#tree_entries' do
|
||||
let(:path) { '/' }
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ RSpec.describe Quality::TestLevel do
|
|||
context 'when level is unit' do
|
||||
it 'returns a pattern' do
|
||||
expect(subject.pattern(:unit))
|
||||
.to eq("spec/{bin,channels,config,db,dependencies,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,serializers,services,sidekiq,support_specs,tasks,uploaders,validators,views,workers,elastic_integration,tooling}{,/**/}*_spec.rb")
|
||||
.to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,serializers,services,sidekiq,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -103,7 +103,7 @@ RSpec.describe Quality::TestLevel do
|
|||
context 'when level is unit' do
|
||||
it 'returns a regexp' do
|
||||
expect(subject.regexp(:unit))
|
||||
.to eq(%r{spec/(bin|channels|config|db|dependencies|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|serializers|services|sidekiq|support_specs|tasks|uploaders|validators|views|workers|elastic_integration|tooling)})
|
||||
.to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|serializers|services|sidekiq|support_specs|tasks|uploaders|validators|views|workers|tooling)})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ RSpec.describe MergeRequestDiff do
|
|||
|
||||
let(:diff_with_commits) { create(:merge_request).merge_request_diff }
|
||||
|
||||
before do
|
||||
stub_feature_flags(diffs_gradual_load: false)
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
subject { diff_with_commits }
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ RSpec.describe PaginatedDiffEntity do
|
|||
|
||||
subject { entity.as_json }
|
||||
|
||||
before do
|
||||
stub_feature_flags(diffs_gradual_load: false)
|
||||
end
|
||||
|
||||
it 'exposes diff_files' do
|
||||
expect(subject[:diff_files]).to be_present
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue