diff --git a/.gitignore b/.gitignore index 5cdab272055..b3e6cbae96b 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,4 @@ jsdoc/ /qa/.rakeTasks webpack-dev-server.json /.nvimrc +.solargraph.yml diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION index 850e742404b..141f2e805be 100644 --- a/GITLAB_PAGES_VERSION +++ b/GITLAB_PAGES_VERSION @@ -1 +1 @@ -1.14.0 +1.15.0 diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 0cdda48f1e5..5c643a864d6 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -532,44 +532,41 @@ export default { :show-panels="showPanels" :collapse-group="collapseGroup(groupData.key)" > -
- +
-
-
-
- - - -
- - +
+ + +
- -
+
+
:gitlab_environment do |_t, args| + require 'sidekiq/testing' + + GroupSeeder.new( + subgroups_depth: args.subgroups_depth, + username: args.username + ).seed + end + end +end + +class GroupSeeder + PROJECT_URL = 'https://gitlab.com/gitlab-org/gitlab-test.git' + + attr_reader :all_group_ids + + def initialize(subgroups_depth:, username:) + @subgroups_depth = subgroups_depth.to_i + @user = User.find_by_username(username) + @group_names = Set.new + @resource_count = 2 + @all_groups = {} + @all_group_ids = [] + end + + def seed + create_groups + + puts 'Done!' + end + + def create_groups + create_root_group + create_sub_groups + create_users_and_members + create_epics if Gitlab.ee? + create_labels + create_milestones + + Sidekiq::Testing.inline! do + create_projects + end + end + + def create_users_and_members + all_group_ids.each do |group_id| + @resource_count.times do |_| + user = create_user + create_member(user.id, group_id) + end + end + end + + def create_root_group + root_group = ::Groups::CreateService.new(@user, group_params).execute + + track_group_id(1, root_group.id) + end + + def create_sub_groups + (2..@subgroups_depth).each do |level| + parent_level = level - 1 + current_level = level + parent_groups = @all_groups[parent_level] + + parent_groups.each do |parent_id| + @resource_count.times do |_| + sub_group = ::Groups::CreateService.new(@user, group_params(parent_id: parent_id)).execute + + track_group_id(current_level, sub_group.id) + end + end + end + end + + def track_group_id(depth_level, group_id) + @all_groups[depth_level] ||= [] + @all_groups[depth_level] << group_id + @all_group_ids << group_id + end + + def group_params(parent_id: nil) + name = unique_name + + { + name: name, + path: name, + parent_id: parent_id + } + end + + def unique_name + name = ffaker_name + name = ffaker_name until @group_names.add?(name) + name + end + + def ffaker_name + FFaker::Lorem.characters(5) + end + + def create_user + User.create!( + username: FFaker::Internet.user_name, + name: FFaker::Name.name, + email: FFaker::Internet.email, + confirmed_at: DateTime.now, + password: Devise.friendly_token + ) + end + + def create_member(user_id, group_id) + roles = Gitlab::Access.values + + GroupMember.create(user_id: user_id, access_level: roles.sample, source_id: group_id) + end + + def create_epics + all_group_ids.each do |group_id| + @resource_count.times do |_| + group = Group.find(group_id) + + epic_params = { + title: FFaker::Lorem.sentence(6), + description: FFaker::Lorem.paragraphs(3).join("\n\n"), + author: group.users.sample, + group: group + } + + Epic.create!(epic_params) + end + end + end + + def create_labels + all_group_ids.each do |group_id| + @resource_count.times do |_| + group = Group.find(group_id) + label_title = FFaker::Product.brand + + Labels::CreateService.new(title: label_title, color: "##{Digest::MD5.hexdigest(label_title)[0..5]}").execute(group: group) + end + end + end + + def create_milestones + all_group_ids.each do |group_id| + @resource_count.times do |i| + group = Group.find(group_id) + + milestone_params = { + title: "v#{i}.0", + description: FFaker::Lorem.sentence, + state: [:active, :closed].sample + } + + Milestones::CreateService.new(group, group.members.sample, milestone_params).execute + end + end + end + + def create_projects + all_group_ids.each do |group_id| + group = Group.find(group_id) + + @resource_count.times do |i| + _, project_path = PROJECT_URL.split('/')[-2..-1] + + project_path.gsub!('.git', '') + + params = { + import_url: PROJECT_URL, + namespace_id: group.id, + name: project_path.titleize + FFaker::Lorem.characters(10), + description: FFaker::Lorem.sentence, + visibility_level: 0, + skip_disk_validation: true + } + + project = nil + + Sidekiq::Worker.skipping_transaction_check do + project = ::Projects::CreateService.new(@user, params).execute + project.send(:_run_after_commit_queue) + project.import_state.send(:_run_after_commit_queue) + project.repository.expire_all_method_caches + end + + create_project_issues(project) + assign_issues_to_epics_and_milestones(project) + end + end + end + + def create_project_issues(project) + seeder = Quality::Seeders::Issues.new(project: project) + seeder.seed(backfill_weeks: 2, average_issues_per_week: 2) + end + + def assign_issues_to_epics_and_milestones(project) + group_ids = project.group.self_and_ancestors.map(&:id) + + project.issues.each do |issue| + issue_params = { + milestone: Milestone.where(group: group_ids).sample + } + + issue_params[:epic] = Epic.where(group: group_ids).sample if Gitlab.ee? + + issue.update(issue_params) + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 81442d3fc7d..adc979efd1d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6035,6 +6035,9 @@ msgstr "" msgid "Default project deletion protection" msgstr "" +msgid "Default projects limit" +msgstr "" + msgid "Default: Directly import the Google Code email address or username" msgstr "" @@ -10470,6 +10473,9 @@ msgstr "" msgid "Is blocked by" msgstr "" +msgid "Is this GitLab trial for your company?" +msgstr "" + msgid "Is using license seat:" msgstr "" @@ -11628,6 +11634,9 @@ msgstr "" msgid "Maximum delay (Minutes)" msgstr "" +msgid "Maximum duration of a session." +msgstr "" + msgid "Maximum job timeout" msgstr "" @@ -11646,12 +11655,24 @@ msgstr "" msgid "Maximum number of mirrors that can be synchronizing at the same time." msgstr "" +msgid "Maximum number of projects." +msgstr "" + msgid "Maximum page reached" msgstr "" msgid "Maximum push size (MB)" msgstr "" +msgid "Maximum size limit for a single commit." +msgstr "" + +msgid "Maximum size limit for each repository." +msgstr "" + +msgid "Maximum size of individual attachments in comments." +msgstr "" + msgid "Maximum time between updates that a mirror can have when scheduled to synchronize." msgstr "" @@ -17024,9 +17045,6 @@ msgstr "" msgid "Session duration (minutes)" msgstr "" -msgid "Session expiration, projects limit and attachment size." -msgstr "" - msgid "Set %{epic_ref} as the parent epic." msgstr "" @@ -17066,6 +17084,9 @@ msgstr "" msgid "Set parent epic to an epic" msgstr "" +msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan." +msgstr "" + msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication." msgstr "" diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb index 3f3711f9eb8..d3a0c9b790b 100644 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb @@ -83,17 +83,17 @@ describe 'User updates wiki page' do end it 'updates the commit message as the title is changed', :js do + fill_in(:wiki_title, with: '& < > \ \ { } &') + + expect(page).to have_field('wiki[message]', with: 'Update & < > \ \ { } &') + end + + it 'correctly escapes the commit message entities', :js do fill_in(:wiki_title, with: 'Wiki title') expect(page).to have_field('wiki[message]', with: 'Update Wiki title') end - it 'does not allow XSS', :js do - fill_in(:wiki_title, with: '