Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot
2023-04-07 21:08:31 +00:00
parent 6d36b38d4d
commit d66cbbc11b
23 changed files with 2736 additions and 2690 deletions

View File

@ -1 +1 @@
0997bd28e31dc8f6b3a6528439cc277b7d64215b
c27112befe2cf3c936b03afdf679d0cd03db3f50

View File

@ -1 +1 @@
affdc645175554504efdf19daad28900b5b43e87
2f33d556988d697070d7b2ef1b5b2fad57257e09

View File

@ -0,0 +1,82 @@
<script>
import { GlFormInput, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { sprintf } from '~/locale';
import { SHOW_PASSWORD, HIDE_PASSWORD, PASSWORD_TITLE } from '../constants';
export default {
name: 'PasswordInput',
i18n: {
showPassword: SHOW_PASSWORD,
hidePassword: HIDE_PASSWORD,
},
components: {
GlFormInput,
GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
resourceName: {
type: String,
required: true,
},
minimumPasswordLength: {
type: String,
required: true,
},
qaSelector: {
type: String,
required: true,
},
},
data() {
return {
isMasked: true,
};
},
computed: {
passwordTitle() {
return sprintf(PASSWORD_TITLE, { minimum_password_length: this.minimumPasswordLength });
},
type() {
return this.isMasked ? 'password' : 'text';
},
toggleVisibilityLabel() {
return this.isMasked ? this.$options.i18n.showPassword : this.$options.i18n.hidePassword;
},
toggleVisibilityIcon() {
return this.isMasked ? 'eye' : 'eye-slash';
},
},
methods: {
handleToggleVisibilityButtonClick() {
this.isMasked = !this.isMasked;
},
},
};
</script>
<template>
<div class="gl-field-error-anchor input-icon-wrapper">
<gl-form-input
:id="`${resourceName}_password`"
class="js-password-complexity-validation gl-pr-8!"
required
autocomplete="new-password"
:name="`${resourceName}[password]`"
:minlength="minimumPasswordLength"
:data-qa-selector="qaSelector"
:title="passwordTitle"
:type="type"
/>
<gl-button
v-gl-tooltip="toggleVisibilityLabel"
class="input-icon-right gl-right-0!"
category="tertiary"
:aria-label="toggleVisibilityLabel"
:icon="toggleVisibilityIcon"
@click="handleToggleVisibilityButtonClick"
/>
</div>
</template>

View File

@ -0,0 +1,8 @@
import { __, s__ } from '~/locale';
export const SHOW_PASSWORD = __('Show password');
export const HIDE_PASSWORD = __('Hide password');
export const PASSWORD_TITLE = s__(
'SignUp|Minimum length is %{minimum_password_length} characters.',
);

View File

@ -0,0 +1,32 @@
import Vue from 'vue';
import GlFieldErrors from '~/gl_field_errors';
import PasswordInput from './components/password_input.vue';
export const initTogglePasswordVisibility = () => {
const el = document.querySelector('.js-password');
if (!el) {
return null;
}
const { form } = el;
const { resourceName, minimumPasswordLength, qaSelector } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
el,
name: 'PasswordInputRoot',
render(createElement) {
return createElement(PasswordInput, {
props: {
resourceName,
minimumPasswordLength,
qaSelector,
},
});
},
});
// Since we replaced password input, we need to re-initialize the field errors handler
return new GlFieldErrors(form);
};

View File

@ -54,6 +54,7 @@ import { __ } from '~/locale';
const errorMessageClass = 'gl-field-error';
const inputErrorClass = 'gl-field-error-outline';
const validInputHintClass = '.gl-field-hint-valid';
const errorAnchorSelector = '.gl-field-error-anchor';
const ignoreInputSelector = '.gl-field-error-ignore';
@ -151,6 +152,7 @@ export default class GlFieldError {
renderInvalid() {
this.inputElement.addClass(inputErrorClass);
this.scopedSiblings.addClass('hidden');
this.inputElement.parents('.form-group').find(validInputHintClass).addClass('hidden');
return this.fieldErrorElement.removeClass('hidden');
}

View File

@ -5,6 +5,7 @@ import LengthValidator from '~/validators/length_validator';
import UsernameValidator from '~/pages/sessions/new/username_validator';
import EmailFormatValidator from '~/pages/sessions/new/email_format_validator';
import { initLanguageSwitcher } from '~/language_switcher';
import { initTogglePasswordVisibility } from '~/authentication/password';
import Tracking from '~/tracking';
new UsernameValidator(); // eslint-disable-line no-new
@ -19,3 +20,4 @@ Tracking.enableFormTracking({
});
initLanguageSwitcher();
initTogglePasswordVisibility();

View File

@ -1,12 +1,13 @@
- max_first_name_length = max_last_name_length = 127
- omniauth_providers_placement ||= :bottom
- borderless ||= false
- form_resource_name = "new_#{resource_name}"
.gl-mb-3.gl-p-4{ class: (borderless ? '' : 'gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-base') }
- if show_omniauth_providers && omniauth_providers_placement == :top
= render 'devise/shared/signup_omniauth_providers_top'
= gitlab_ui_form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors js-arkose-labs-form', 'aria-live' => 'assertive' }, data: { testid: 'signup-form' }) do |f|
= gitlab_ui_form_for(resource, as: form_resource_name, url: url, html: { class: 'new_user gl-show-field-errors js-arkose-labs-form', 'aria-live' => 'assertive' }, data: { testid: 'signup-form' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Gitlab::CurrentSettings.invisible_captcha_enabled
@ -52,16 +53,12 @@
%p.validation-warning.gl-field-error-ignore.text-secondary.hide= _('This email address does not look right, are you sure you typed it correctly?')
-# This is used for providing entry to Jihu on email verification
= render_if_exists 'devise/shared/signup_email_additional_info'
.form-group.gl-mb-5#password-strength
.form-group.gl-mb-5
= f.label :password, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.password_field :password,
class: 'form-control gl-form-input bottom js-password-complexity-validation',
data: { qa_selector: 'new_user_password_field' },
autocomplete: 'new-password',
required: true,
pattern: ".{#{@minimum_password_length},}",
title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%input.form-control.gl-form-input.js-password{ data: { resource_name: form_resource_name,
minimum_password_length: @minimum_password_length,
qa_selector: 'new_user_password_field' } }
%p.gl-field-hint-valid.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
= render_if_exists 'shared/password_requirements_list'
= render_if_exists 'devise/shared/phone_verification', form: f
%div

View File

@ -2,6 +2,7 @@
stage: none
group: none
info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
toc: false
---
# Deprecations by version
@ -30,7 +31,7 @@ For deprecation reviewers (Technical Writers only):
{::options parse_block_html="true" /}
In each release, GitLab announces features that are deprecated and no longer recommended for use.
These GitLab features are deprecated and no longer recommended for use.
Each deprecated feature will be removed in a future release.
Some features cause breaking changes when they are removed.
@ -39,39 +40,33 @@ add this URL to your RSS feed reader: `https://about.gitlab.com/breaking-changes
You can also view [REST API](https://docs.gitlab.com/ee/api/rest/deprecations.html)
and [GraphQL](https://docs.gitlab.com/ee/api/graphql/removed_items.html) deprecations/removals.
<div class="js-deprecation-filters"></div>
<% if milestones.any? -%>
<%- milestones.each do |milestone| %>
<div class="announcement-milestone">
## Announced in <%= milestone %>
<%- entries.select{|d| d["announcement_milestone"] == milestone}.each do |deprecation| %>
<div class="deprecation removal-<%= deprecation["removal_milestone"].gsub('.', '') %><% if deprecation["breaking_change"] -%> breaking-change<% end %>">
<% if milestones.any? -%><div class="js-deprecation-filters"></div><%- end -%>
<%- milestones.each do |milestone| %>
<div class="milestone-wrapper" data-milestone="<%= milestone %>">
## GitLab <%= milestone %>
<%- entries.select{|d| d["removal_milestone"] == milestone}.each do |deprecation| %>
<div class="deprecation <% if deprecation["breaking_change"] -%>breaking-change<% end %>" data-milestone="<%= milestone %>">
### <%= deprecation["title"] %>
<div class="deprecation-notes">
- Announced in: GitLab <span class="milestone"><%= deprecation["announcement_milestone"]%></span>
<% if deprecation["end_of_support_milestone"] -%>
End of Support: GitLab <span class="removal-milestone"><%= deprecation["end_of_support_milestone"]%></span> <span class="support-end-date"></span><br />
- End of Support: GitLab <span class="milestone"><%= deprecation["end_of_support_milestone"]%></span>
<% end -%>
Planned removal: GitLab <span class="removal-milestone"><%= deprecation["removal_milestone"]%></span> <span class="removal-date"></span>
<% if deprecation["breaking_change"] -%>
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
<%= deprecation["body"] -%><% else %>
<%= deprecation["body"] -%><% end %><%- if deprecation["removal_milestone"] -%>
- [Breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/)
<%- end -%>
</div>
<%- end -%>
<%- end -%>
<%= deprecation["body"] -%>
</div>
<%- end -%>
<%- else -%>
Deprecated features scheduled for removal will be listed here, sorted by GitLab milestone.
<% end -%>
</div>
<%- end -%>
DISCLAIMER:
This page contains information related to upcoming products, features, and functionality.

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddCodeSuggestionsToNamespaceSettings < Gitlab::Database::Migration[2.1]
enable_lock_retries!
def change
add_column :namespace_settings, :code_suggestions, :boolean, default: false, null: false
end
end

View File

@ -0,0 +1 @@
ffc795945693f4856bd10224788ceb8305227ec296223c450af75a26a11f4811

View File

@ -18662,6 +18662,7 @@ CREATE TABLE namespace_settings (
allow_runner_registration_token boolean DEFAULT true NOT NULL,
unique_project_download_limit_alertlist integer[] DEFAULT '{}'::integer[] NOT NULL,
emails_enabled boolean DEFAULT true NOT NULL,
code_suggestions boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT namespace_settings_unique_project_download_limit_alertlist_size CHECK ((cardinality(unique_project_download_limit_alertlist) <= 100)),
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))

View File

@ -819,10 +819,10 @@ often using fixtures to validate correct integration with the backend code.
### Use fixtures
To import a JSON fixture, `import` it using the `test_fixtures` alias.
To import a JSON or HTML fixture, `import` it using the `test_fixtures` alias.
```javascript
import responseBody from 'test_fixtures/some/fixture.json' // loads spec/frontend/fixtures/some/fixture.json
import responseBody from 'test_fixtures/some/fixture.json' // loads tmp/tests/frontend/fixtures-ee/some/fixture.json
it('makes a request', () => {
axiosMock.onGet(endpoint).reply(200, responseBody);
@ -833,23 +833,6 @@ it('makes a request', () => {
});
```
For other fixtures, Jest uses `spec/frontend/__helpers__/fixtures.js` to import them in tests.
The following are examples of tests that work for Jest:
```javascript
it('uses some HTML element', () => {
loadHTMLFixture('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM
const element = document.getElementById('#my-id');
// ...
// Jest does not clean up the DOM automatically
resetHTMLFixture();
});
```
### Generate fixtures
You can find code to generate test fixtures in:

View File

@ -20,6 +20,10 @@ or use one of the following methods.
| [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit#documentation) | A set of automation tools. | Use to deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers. Has some [limitations](https://gitlab.com/gitlab-org/gitlab-environment-toolkit#missing-features-to-be-aware-of) and manual setup for production environments. |
| [GitLab Operator](https://docs.gitlab.com/operator/) | An installation and management method that follows the [Kubernetes Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/). | Use to run GitLab in an [OpenShift](openshift_and_gitlab/index.md) environment. |
## Cloud providers
See [Cloud providers](cloud_providers.md).
## Unsupported Linux distributions and Unix-like operating systems
- Arch Linux

File diff suppressed because it is too large Load Diff

View File

@ -134,7 +134,7 @@ To enable global group memberships lock:
After a group sync, users who are not members of a mapped SAML group are removed from the group.
On GitLab.com, users in the top-level group are assigned the
[default membership role](index.md#role) instead of being removed.
default membership role instead of being removed.
For example, in the following diagram:

View File

@ -222,7 +222,10 @@ After you set up your identity provider to work with GitLab, you must configure
- In the **Identity provider single sign-on URL** field, enter the SSO URL from your identity provider.
- In the **Certificate fingerprint** field, enter the fingerprint for the SAML token signing certificate.
1. In the **Default membership role** field, select the role to assign to new users.
The default role is **Guest**.
The default role is **Guest**. In [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/214523)
and later, group owners can set a default membership role other than **Guest**.
To do so, [configure the SAML SSO for the group](#configure-gitlab). That role
becomes the starting role of all users added to the group.
1. Select the **Enable SAML authentication for this group** checkbox.
1. Optional. Select:
- **Enforce SSO-only authentication for web activity for this group**.
@ -267,15 +270,24 @@ For more information, see the [attributes available for self-managed GitLab inst
To link SAML to your existing GitLab.com account:
1. Sign in to your GitLab.com account. [Reset your password](https://gitlab.com/users/password/new) if necessary.
1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group owner can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the identity provider.
1. Optional. Select the **Remember me** checkbox to stay signed in to GitLab for 2 weeks. You may still be asked to re-authenticate with your SAML provider
more frequently.
1. Sign in to your GitLab.com account. [Reset your password](https://gitlab.com/users/password/new)
if necessary.
1. Locate and visit the **GitLab single sign-on URL** for the group you're signing
in to. A group owner can find this on the group's **Settings > SAML SSO** page.
If the sign-in URL is configured, users can connect to the GitLab app from the identity provider.
1. Optional. Select the **Remember me** checkbox to stay signed in to GitLab for 2 weeks.
You may still be asked to re-authenticate with your SAML provider more frequently.
1. Select **Authorize**.
1. Enter your credentials on the identity provider if prompted.
1. You are then redirected back to GitLab.com and should now have access to the group. In the future, you can use SAML to sign in to GitLab.com.
1. You are then redirected back to GitLab.com and should now have access to the group.
In the future, you can use SAML to sign in to GitLab.com.
On subsequent visits, you should be able to go [sign in to GitLab.com with SAML](#sign-in-to-gitlabcom-with-saml) or by visiting links directly. If the **enforce SSO** option is turned on, you are then redirected to sign in through the identity provider.
If a user is already a member of the group, linking the SAML identity does not
change their role.
On subsequent visits, you should be able to [sign in to GitLab.com with SAML](#sign-in-to-gitlabcom-with-saml)
or by visiting links directly. If the **enforce SSO** option is turned on, you
are then redirected to sign in through the identity provider.
### Sign in to GitLab.com with SAML
@ -357,18 +369,6 @@ bypassed for users:
- That are provisioned with SAML or SCIM.
- That have an email address that belongs to the verified domain.
### Role
Starting from [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/214523), group owners can set a
"Default membership role" other than Guest. To do so, [configure the SAML SSO for the group](#configure-gitlab).
That role becomes the starting access level of all users added to the group.
Existing members with appropriate privileges can promote or demote users, as needed.
If a user is already a member of the group, linking the SAML identity does not change their role.
Users given a "minimal access" role have [specific restrictions](../../permissions.md#users-with-minimal-access).
### Block user access
To rescind a user's access to the group when only SAML SSO is configured, either:
@ -376,7 +376,9 @@ To rescind a user's access to the group when only SAML SSO is configured, either
- Remove (in order) the user from:
1. The user data store on the identity provider or the list of users on the specific app.
1. The GitLab.com group.
- Use [Group Sync](group_sync.md#automatic-member-removal) at the top-level of your group with the [default role](#role) set to [minimal access](../../permissions.md#users-with-minimal-access) to automatically block access to all resources in the group.
- Use [Group Sync](group_sync.md#automatic-member-removal) at the top-level of
your group with the default role set to [minimal access](../../permissions.md#users-with-minimal-access)
to automatically block access to all resources in the group.
To rescind a user's access to the group when also using SCIM, refer to [Remove access](scim_setup.md#remove-access).

View File

@ -21378,6 +21378,9 @@ msgstr ""
msgid "Hide marketing-related entries from the Help page"
msgstr ""
msgid "Hide password"
msgstr ""
msgid "Hide payload"
msgstr ""
@ -40906,6 +40909,9 @@ msgstr ""
msgid "Show open epics"
msgstr ""
msgid "Show password"
msgstr ""
msgid "Show project milestones"
msgstr ""

View File

@ -151,7 +151,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures, feature_cate
end
end
context 'when inviting an unregistered user' do
context 'when inviting an unregistered user', :js do
let(:new_user) { build_stubbed(:user) }
let(:invite_email) { new_user.email }
let(:group_invite) { create(:group_member, :invited, group: group, invite_email: invite_email, created_by: owner) }
@ -208,7 +208,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures, feature_cate
context 'email confirmation enabled' do
context 'when user is not valid in sign up form' do
let(:new_user) { build_stubbed(:user, first_name: '', last_name: '') }
let(:new_user) { build_stubbed(:user, password: '11111111') }
it 'fails sign up and redirects back to sign up', :aggregate_failures do
expect { fill_in_sign_up_form(new_user) }.not_to change { User.count }

View File

@ -10,7 +10,7 @@ RSpec.shared_examples 'Signup name validation' do |field, max_length, label|
visit new_user_registration_path
end
describe "#{field} validation", :js do
describe "#{field} validation" do
it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
fill_in field, with: 'u' * max_length
@ -44,7 +44,7 @@ RSpec.shared_examples 'Signup name validation' do |field, max_length, label|
end
end
RSpec.describe 'Signup', feature_category: :user_profile do
RSpec.describe 'Signup', :js, feature_category: :user_profile do
include TermsHelper
let(:new_user) { build_stubbed(:user) }
@ -71,7 +71,7 @@ RSpec.describe 'Signup', feature_category: :user_profile do
stub_application_setting(require_admin_approval_after_user_signup: false)
end
describe 'username validation', :js do
describe 'username validation' do
before do
visit new_user_registration_path
end
@ -356,6 +356,8 @@ RSpec.describe 'Signup', feature_category: :user_profile do
visit new_user_registration_path
fill_in_signup_form
wait_for_all_requests
click_button 'Register'
visit new_project_path
@ -383,7 +385,7 @@ RSpec.describe 'Signup', feature_category: :user_profile do
expect(page.body).not_to match(/#{new_user.password}/)
end
context 'with invalid email', :js do
context 'with invalid email' do
it_behaves_like 'user email validation' do
let(:path) { new_user_registration_path }
end

View File

@ -0,0 +1,49 @@
import { GlFormInput, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import PasswordInput from '~/authentication/password/components/password_input.vue';
import { SHOW_PASSWORD, HIDE_PASSWORD } from '~/authentication/password/constants';
describe('PasswordInput', () => {
let wrapper;
const findPasswordInput = () => wrapper.findComponent(GlFormInput);
const findToggleButton = () => wrapper.findComponent(GlButton);
const createComponent = () => {
return shallowMount(PasswordInput, {
propsData: {
resourceName: 'new_user',
minimumPasswordLength: '8',
qaSelector: 'new_user_password_field',
},
});
};
beforeEach(() => {
wrapper = createComponent();
});
describe('when the show password button is clicked', () => {
beforeEach(() => {
findToggleButton().vm.$emit('click');
});
it('displays hide password button', () => {
expect(findPasswordInput().attributes('type')).toBe('text');
expect(findToggleButton().attributes('icon')).toBe('eye-slash');
expect(findToggleButton().attributes('aria-label')).toBe(HIDE_PASSWORD);
});
describe('when the hide password button is clicked', () => {
beforeEach(() => {
findToggleButton().vm.$emit('click');
});
it('displays show password button', () => {
expect(findPasswordInput().attributes('type')).toBe('password');
expect(findToggleButton().attributes('icon')).toBe('eye');
expect(findToggleButton().attributes('aria-label')).toBe(SHOW_PASSWORD);
});
});
});
});

View File

@ -17,7 +17,7 @@ RSpec.describe Docs::DeprecationHandling do
allow(YAML).to receive(:load_file) do |file_name|
{
'title' => file_name[/[a-z]*\.yml/],
'announcement_milestone' => file_name[/\d+-\d+/].tr('-', '.')
'removal_milestone' => file_name[/\d+-\d+/].tr('-', '.')
}
end
end

View File

@ -1,4 +1,5 @@
# frozen_string_literal: true
require 'erb'
module Docs
@ -7,11 +8,7 @@ module Docs
@type = type
@yaml_glob_path = Rails.root.join("data/#{type.pluralize}/**/*.yml")
@template_path = Rails.root.join("data/#{type.pluralize}/templates/_#{type}_template.md.erb")
@milestone_key_name = if type == "deprecation"
"announcement_milestone"
else
"removal_milestone"
end
@milestone_key_name = "removal_milestone"
end
def render