Commit 50ae4065 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent be37a0ee
......@@ -88,3 +88,4 @@ jsdoc/
/qa/.rakeTasks
webpack-dev-server.json
/.nvimrc
.solargraph.yml
......@@ -532,44 +532,41 @@ export default {
:show-panels="showPanels"
:collapse-group="collapseGroup(groupData.key)"
>
<div v-if="!groupSingleEmptyState(groupData.key)">
<vue-draggable
:value="groupData.panels"
group="metrics-dashboard"
:component-data="{ attrs: { class: 'row mx-0 w-100' } }"
:disabled="!isRearrangingPanels"
@input="updatePanels(groupData.key, $event)"
<vue-draggable
v-if="!groupSingleEmptyState(groupData.key)"
:value="groupData.panels"
group="metrics-dashboard"
:component-data="{ attrs: { class: 'row mx-0 w-100' } }"
:disabled="!isRearrangingPanels"
@input="updatePanels(groupData.key, $event)"
>
<div
v-for="(graphData, graphIndex) in groupData.panels"
:key="`panel-type-${graphIndex}`"
class="col-12 col-lg-6 px-2 mb-2 draggable"
:class="{ 'draggable-enabled': isRearrangingPanels }"
>
<div
v-for="(graphData, graphIndex) in groupData.panels"
:key="`panel-type-${graphIndex}`"
class="col-12 col-lg-6 px-2 mb-2 draggable"
:class="{ 'draggable-enabled': isRearrangingPanels }"
>
<div class="position-relative draggable-panel js-draggable-panel">
<div
v-if="isRearrangingPanels"
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removePanel(groupData.key, groupData.panels, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')">
<icon name="close" />
</a>
</div>
<panel-type
:clipboard-text="
generateLink(groupData.group, graphData.title, graphData.y_label)
"
:graph-data="graphData"
:alerts-endpoint="alertsEndpoint"
:prometheus-alerts-available="prometheusAlertsAvailable"
:index="`${index}-${graphIndex}`"
/>
<div class="position-relative draggable-panel js-draggable-panel">
<div
v-if="isRearrangingPanels"
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removePanel(groupData.key, groupData.panels, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')">
<icon name="close" />
</a>
</div>
<panel-type
:clipboard-text="generateLink(groupData.group, graphData.title, graphData.y_label)"
:graph-data="graphData"
:alerts-endpoint="alertsEndpoint"
:prometheus-alerts-available="prometheusAlertsAvailable"
:index="`${index}-${graphIndex}`"
/>
</div>
</vue-draggable>
</div>
</div>
</vue-draggable>
<div v-else class="py-5 col col-sm-10 col-md-8 col-lg-7 col-xl-6">
<group-empty-state
ref="empty-group"
......
......@@ -40,7 +40,7 @@ export default class Wikis {
// Replace hyphens with spaces
if (title) title = title.replace(/-+/g, ' ');
const newCommitMessage = sprintf(this.commitMessageI18n, { pageTitle: title });
const newCommitMessage = sprintf(this.commitMessageI18n, { pageTitle: title }, false);
this.commitMessageInput.value = newCommitMessage;
}
......
......@@ -8,20 +8,20 @@
= f.label :gravatar_enabled, class: 'form-check-label' do
= _('Gravatar enabled')
.form-group
= f.label :default_projects_limit, class: 'label-bold'
= f.number_field :default_projects_limit, class: 'form-control'
= f.label :default_projects_limit, _('Default projects limit'), class: 'label-bold'
= f.number_field :default_projects_limit, class: 'form-control', title: _('Maximum number of projects.'), data: { toggle: 'tooltip', container: 'body' }
.form-group
= f.label :max_attachment_size, _('Maximum attachment size (MB)'), class: 'label-bold'
= f.number_field :max_attachment_size, class: 'form-control'
= f.number_field :max_attachment_size, class: 'form-control', title: _('Maximum size of individual attachments in comments.'), data: { toggle: 'tooltip', container: 'body' }
= render_if_exists 'admin/application_settings/repository_size_limit_setting', form: f
.form-group
= f.label :receive_max_input_size, _('Maximum push size (MB)'), class: 'label-light'
= f.number_field :receive_max_input_size, class: 'form-control qa-receive-max-input-size-field'
= f.number_field :receive_max_input_size, class: 'form-control qa-receive-max-input-size-field', title: _('Maximum size limit for a single commit.'), data: { toggle: 'tooltip', container: 'body' }
.form-group
= f.label :session_expire_delay, _('Session duration (minutes)'), class: 'label-light'
= f.number_field :session_expire_delay, class: 'form-control'
= f.number_field :session_expire_delay, class: 'form-control', title: _('Maximum duration of a session.'), data: { toggle: 'tooltip', container: 'body' }
%span.form-text.text-muted#session_expire_delay_help_block= _('GitLab restart is required to apply changes.')
= render_if_exists 'admin/application_settings/personal_access_token_expiration_policy', form: f
......
......@@ -20,7 +20,7 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Session expiration, projects limit and attachment size.')
= _('Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan.')
.settings-content
= render 'account_and_limit'
......
......@@ -5,15 +5,14 @@
= render_broadcast_message(@broadcast_message)
- else
Your message here
- if Feature.enabled?(:broadcast_notification_type)
.d-flex.justify-content-center
.broadcast-notification-message.preview.js-broadcast-notification-message-preview.mt-2{ class: ('hidden' unless @broadcast_message.notification? ) }
= sprite_icon('bullhorn', size: 16, css_class:'vertical-align-text-top')
.js-broadcast-message-preview
- if @broadcast_message.message.present?
= render_broadcast_message(@broadcast_message)
- else
Your message here
.d-flex.justify-content-center
.broadcast-notification-message.preview.js-broadcast-notification-message-preview.mt-2{ class: ('hidden' unless @broadcast_message.notification? ) }
= sprite_icon('bullhorn', size: 16, css_class:'vertical-align-text-top')
.js-broadcast-message-preview
- if @broadcast_message.message.present?
= render_broadcast_message(@broadcast_message)
- else
Your message here
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form js-quick-submit js-requires-input'} do |f|
= form_errors(@broadcast_message)
......@@ -26,12 +25,11 @@
required: true,
dir: 'auto',
data: { preview_path: preview_admin_broadcast_messages_path }
- if Feature.enabled?(:broadcast_notification_type)
.form-group.row
.col-sm-2.col-form-label
= f.label :broadcast_type, _('Type')
.col-sm-10
= f.select :broadcast_type, broadcast_type_options, {}, class: 'form-control js-broadcast-message-type'
.form-group.row
.col-sm-2.col-form-label
= f.label :broadcast_type, _('Type')
.col-sm-10
= f.select :broadcast_type, broadcast_type_options, {}, class: 'form-control js-broadcast-message-type'
.form-group.row.js-broadcast-message-background-color-form-group{ class: ('hidden' unless @broadcast_message.banner? ) }
.col-sm-2.col-form-label
= f.label :color, _("Background color")
......
......@@ -10,7 +10,7 @@
.input-group-prepend.flex-shrink-0.has-tooltip{ title: root_url }
.input-group-text
= root_url
= select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace', tabindex: 1
= select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace block-truncated', tabindex: 1
- else
.input-group-prepend.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
.input-group-text.border-0
......
- current_broadcast_banner_messages.each do |message|
= broadcast_message(message)
- if Feature.enabled?(:broadcast_notification_type)
= broadcast_message(current_broadcast_notification_message)
= broadcast_message(current_broadcast_notification_message)
---
title: Displays package tags next to the name on the new package list page
merge_request: 23675
author:
type: added
---
title: Add can_create_merge_request_in to /project/:id API response
merge_request: 23577
author:
type: added
---
title: Auto generated wiki commit message containing HTML encoded entities
merge_request: 21371
author: 2knal
type: other
---
title: Add clarifying content to account fields
merge_request:
author:
type: other
---
title: Fix custom charts in monitoring dashboard shrinking
merge_request: 23649
author:
type: fixed
---
title: Update links related to MR approvals in UI
merge_request: 23948
author:
type: other
---
title: Add broadcast types to broadcast messages
merge_request:
author:
type: added
---
title: Upgrade Pages to 1.15.0
merge_request: 24043
author:
type: added
---
title: Prevent project path namespace overflow during import
merge_request: 24042
author: George Tsiolis
type: fixed
---
# `extends` indicates the Vale extension point being used.
# Full list of styles: https://errata-ai.github.io/vale/styles/
extends: substitution
# Substitution rules can display the matched and suggested strings in the
# message shown to the user. The first use of %s prints the suggested option,
# and the second use of %s displays what was found in the text.
message: Use "%s" instead of "%s" in most cases.
# Should a result be flagged as a suggestion, warning, or error?
# Results that fall below the MinAlertLevel set in
# https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini won't be shown.
level: suggestion
# Should a match be case-insensitive or case-sensitive?
# Acceptable values are 'true' or 'false'
ignorecase: true
# Should this rule be limited to a specific scope? If yes, uncomment the line.
# Possible scopes: https://errata-ai.github.io/vale/formats/#available-scopes
# scope: heading
# Should this rule ignore normal word boundaries, such as \b ?
# Acceptable values are 'true' or 'false'
nonword: false
# What is the source for this rule?
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language
# The 'swap' section provides a list of values, one per line, in the form of
# $bad: $good
swap:
# Common contractions are ok
it is: it's
can not: can't
cannot: can't
do not: don't
have not: haven't
that is: that's
we are: we're
will not: won't
would not: wouldn't
you are: you're
you have: you've
# Uncommon contractions are not ok
aren't: are not
couldn't: could not
didn't: did not
doesn't: does not
hasn't: has not
how'll: how will
how's: how is
isn't: is not
it'll: it will
shouldn't: should not
that'll: that will
they'll: they will
they're: they are
wasn't: was not
weren't: were not
we'll: we will
we've: we have
what's: what is
what'll: what will
when's: when is
when'll: when will
where's: where is
where'll: where will
who's: who is
who'll: who will
why's: why is
why'll: why will
......@@ -129,6 +129,7 @@ When the user is authenticated and `simple` is not set this returns something li
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -205,6 +206,7 @@ When the user is authenticated and `simple` is not set this returns something li
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -371,6 +373,7 @@ This endpoint supports [keyset pagination](README.md#keyset-based-pagination) fo
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -447,6 +450,7 @@ This endpoint supports [keyset pagination](README.md#keyset-based-pagination) fo
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -584,6 +588,7 @@ Example response:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -657,6 +662,7 @@ Example response:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -774,6 +780,7 @@ GET /projects/:id
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"container_expiration_policy": {
......@@ -1260,6 +1267,7 @@ Example responses:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -1342,6 +1350,7 @@ Example response:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -1431,6 +1440,7 @@ Example response:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -1594,6 +1604,7 @@ Example response:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......@@ -1702,6 +1713,7 @@ Example response:
"jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"can_create_merge_request_in": true,
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
......
......@@ -15,8 +15,7 @@ to be marked as `Accepting Merge Requests`. Please include screenshots or
wireframes of the proposed feature if it will also change the UI.
Merge requests should be submitted to the appropriate project at GitLab.com, for example
[GitLab CE](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests),
[GitLab EE](https://gitlab.com/gitlab-org/gitlab/merge_requests),
[GitLab](https://gitlab.com/gitlab-org/gitlab/merge_requests),
[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/merge_requests),
[GitLab Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests), etc.
......@@ -227,6 +226,7 @@ requirements.
1. [Changelog entry added](../changelog.md), if necessary.
1. Reviewed by relevant (UX/FE/BE/tech writing) reviewers and all concerns are addressed.
1. Merged by a project maintainer.
1. Create an issue in the [infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues) to inform the Infrastructure department when your contribution is changing default settings or introduces a new setting, if relevant.
1. Confirmed to be working in the [Canary stage](https://about.gitlab.com/handbook/engineering/#canary-testing) or on GitLab.com once the contribution is deployed.
1. Added to the [release post](https://about.gitlab.com/handbook/marketing/blog/release-posts/),
if relevant.
......
......@@ -771,6 +771,9 @@ nicely on different mobile devices.
To make things easier for the user, always add a full code block for things that can be
useful to copy and paste, as they can easily do it with the button on code blocks.
- Add a blank line above and below code blocks.
- When providing a shell command and its output, prefix the shell command with `$` and
leave a blank line between the command and the output.
- When providing a command without output, don't prefix the shell command with `$`.
- For regular code blocks, always use a highlighting class corresponding to the
language for better readability. Examples:
......@@ -795,7 +798,8 @@ nicely on different mobile devices.
- To display raw Markdown instead of rendered Markdown, you can use triple backticks
with `md`, like the `Markdown code` example above, unless you want to include triple
backticks in the code block as well. In that case, use triple tildes (`~~~`) instead.
- [Syntax highlighting for code blocks](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) is available for many languages.
- [Syntax highlighting for code blocks](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
is available for many languages. Use `shell` instead of `bash` or `sh` for shell output.
- For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks).
## GitLab SVG icons
......
......@@ -54,6 +54,17 @@ By default, this seeds an average of 10 issues per week for the last 52 weeks
per project. All issues will also be randomly labeled with team, type, severity,
and priority.
#### Seeding groups with sub-groups
You can seed groups with sub-groups that contain milestones/projects/issues
with the `gitlab:seed:group_seed` task:
```shell
bin/rake "gitlab:seed:group_seed[subgroup_depth, username]"
```
Group are additionally seeded with epics if GitLab instance has epics feature available.
### Automation
If you're very sure that you want to **wipe the current database** and refill
......
......@@ -132,6 +132,10 @@ module API
expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) }
expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) }
expose(:can_create_merge_request_in) do |project, options|
Ability.allowed?(options[:current_user], :create_merge_request_in, project)
end
expose(:issues_access_level) { |project, options| project.project_feature.string_access_level(:issues) }
expose(:repository_access_level) { |project, options| project.project_feature.string_access_level(:repository) }
expose(:merge_requests_access_level) { |project, options| project.project_feature.string_access_level(:merge_requests) }
......
# frozen_string_literal: true
# Seed test groups with:
# 1. 2 Subgroups per level
# 1. 2 Users & group members per group
# 1. 2 Epics, 2 Milestones & 2 Projects per group
# 1. Project issues
#
# It also assigns each project's issue with one of group's or ascendants
# groups milestone & epic.
#
# @param subgroups_depth - number of subgroup levels
# @param username - user creating subgroups (i.e. GitLab admin)
#
# @example
# bundle exec rake "gitlab:seed:group_seed[5, root]"
#
namespace :gitlab do
namespace :seed do
desc 'Seed groups with sub-groups/projects/epics/milestones for Group Import testing'
task :group_seed, [:subgroups_depth, :username] => :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
......@@ -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 ""
......
......@@ -83,15 +83,15 @@ describe 'User updates wiki page' do
end
it 'updates the commit message as the title is changed', :js do
fill_in(:wiki_title, with: 'Wiki title')
fill_in(:wiki_title, with: '& < > \ \ { } &')
expect(page).to have_field('wiki[message]', with: 'Update Wiki title')
expect(page).to have_field('wiki[message]', with: 'Update & < > \ \ { } &')
end
it 'does not allow XSS', :js do
fill_in(:wiki_title, with: '<script>')
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 &lt;script&gt;')
expect(page).to have_field('wiki[message]', with: 'Update Wiki title')
end
it 'shows a validation error message' do
......
......@@ -129,6 +129,18 @@ describe 'User views a wiki page' do
end
end
context 'when a page has XSS in its message' do
before do
wiki_page.update(message: '<script>alert(true)<script>', content: 'XSS update')
end
it 'safely displays the message' do
visit(project_wiki_history_path(project, wiki_page))
expect(page).to have_content('<script>alert(true)<script>')
end
end
context 'when page has invalid content encoding' do
let(:content) { (+'whatever').force_encoding('ISO-8859-1') }
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Dashboard template matches the default snapshot 1`] = `
<div
class="prometheus-graphs"
data-qa-selector="prometheus_graphs"
>
<div
class="prometheus-graphs-header gl-p-3 pb-0 border-bottom bg-gray-light"
>
<div
class="row"
>
<gl-form-group-stub
class="col-sm-12 col-md-6 col-lg-2"
label="Dashboard"
label-for="monitor-dashboards-dropdown"
label-size="sm"
>
<dashboards-dropdown-stub
class="mb-0 d-flex"
defaultbranch="master"
id="monitor-dashboards-dropdown"
selecteddashboard="[object Object]"
toggle-class="dropdown-menu-toggle"
/>
</gl-form-group-stub>
<gl-form-group-stub
class="col-sm-6 col-md-6 col-lg-2"
label="Environment"
label-for="monitor-environments-dropdown"
label-size="sm"
>
<gl-dropdown-stub
class="mb-0 d-flex"
data-qa-selector="environments_dropdown"
id="monitor-environments-dropdown"
menu-class="monitor-environment-dropdown-menu"
text="production"
toggle-class="dropdown-menu-toggle"
>
<div
class="d-flex flex-column overflow-hidden"
>
<gl-dropdown-header-stub
class="text-center"
>
Environment
</gl-dropdown-header-stub>
<gl-dropdown-divider-stub />
<!---->
<div
class="flex-fill overflow-auto"
/>
<!---->
</div>
</gl-dropdown-stub>
</gl-form-group-stub>
<gl-form-group-stub
class="col-sm-6 col-md-6 col-lg-4"
label="Show last"
label-for="monitor-time-window-dropdown"
label-size="sm"
>
<date-time-picker-stub
end="2020-01-01T18:57:47.000Z"
start="2020-01-01T18:27:47.000Z"
timewindows="[object Object]"
/>
</gl-form-group-stub>
<!---->
</div>
</div>
<empty-state-stub
clusterspath="/path/to/clusters"
documentationpath="/path/to/docs"
emptygettingstartedsvgpath="/path/to/getting-started.svg"
emptyloadingsvgpath="/path/to/loading.svg"
emptynodatasmallsvgpath="/path/to/no-data-small.svg"
emptynodatasvgpath="/path/to/no-data.svg"
emptyunabletoconnectsvgpath="/path/to/unable-to-connect.svg"
selectedstate="gettingStarted"
settingspath="/path/to/settings"
/>
</div>
`;
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Dashboard from '~/monitoring/components/dashboard.vue';
import { createStore } from '~/monitoring/stores';
import { propsData } from '../init_utils';
jest.mock('~/lib/utils/url_utility', () => ({
getParameterValues: jest.fn().mockImplementation(param => {
if (param === 'start') return ['2020-01-01T18:27:47.000Z'];
if (param === 'end') return ['2020-01-01T18:57:47.000Z'];
return [];
}),
}));
describe('Dashboard template', () => {
let wrapper;
let store;
let mock;
beforeEach(() => {
store = createStore();
mock = new MockAdapter(axios);
});
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
mock.restore();
});
it('matches the default snapshot', () => {
wrapper = shallowMount(Dashboard, {
propsData: { ...propsData },
methods: {
fetchData: jest.fn(),
},
store,
});
expect(wrapper.element).toMatchSnapshot();
});
});
......@@ -1340,6 +1340,7 @@ describe API::Projects do
expect(json_response['path']).to be_present
expect(json_response['issues_enabled']).to be_present
expect(json_response['merge_requests_enabled']).to be_present
expect(json_response['can_create_merge_request_in']).to be_present
expect(json_response['wiki_enabled']).to be_present
expect(json_response['jobs_enabled']).to be_present
expect(json_response['snippets_enabled']).to be_present
......@@ -1390,6 +1391,7 @@ describe API::Projects do
expect(json_response['path']).to be_present
expect(json_response['issues_enabled']).to be_present
expect(json_response['merge_requests_enabled']).to be_present
expect(json_response['can_create_merge_request_in']).to be_present
expect(json_response['wiki_enabled']).to be_present
expect(json_response['jobs_enabled']).to be_present
expect(json_response['snippets_enabled']).to be_present
......
# frozen_string_literal: true
require 'rake_helper'
describe 'gitlab:seed:group_seed rake task', :sidekiq do
let(:username) { 'group_seed' }
let!(:user) { create(:user, username: username) }
let(:task_params) { [2, username] }
before do
Rake.application.rake_require('tasks/gitlab/seed/group_seed')
end
subject { run_rake_task('gitlab:seed:group_seed', task_params) }
it 'performs group seed successfully' do
expect { subject }.not_to raise_error
group = user.groups.first
expect(user.groups.count).to be 3
expect(group.projects.count).to be 2
expect(group.members.count).to be 3
expect(group.milestones.count).to be 2
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment