diff --git a/app/assets/javascripts/vue_shared/components/deprecated_project_avatar/default.vue b/app/assets/javascripts/vue_shared/components/deprecated_project_avatar/default.vue
deleted file mode 100644
index 733accdff44..00000000000
--- a/app/assets/javascripts/vue_shared/components/deprecated_project_avatar/default.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/assets/javascripts/vue_shared/components/deprecated_project_avatar/image.vue b/app/assets/javascripts/vue_shared/components/deprecated_project_avatar/image.vue
deleted file mode 100644
index 269736c799c..00000000000
--- a/app/assets/javascripts/vue_shared/components/deprecated_project_avatar/image.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
diff --git a/app/assets/javascripts/vue_shared/components/identicon.vue b/app/assets/javascripts/vue_shared/components/identicon.vue
deleted file mode 100644
index 87a995464fa..00000000000
--- a/app/assets/javascripts/vue_shared/components/identicon.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- {{ identiconTitle }}
-
-
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index 0bd57c84018..19ffbe37ce7 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
@@ -3,7 +3,7 @@ import { GlButton, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { isString } from 'lodash';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
-import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
+import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
export default {
name: 'ProjectListItem',
@@ -22,6 +22,9 @@ export default {
matcher: { type: String, required: false, default: '' },
},
computed: {
+ projectAvatarUrl() {
+ return this.project.avatar_url || this.project.avatarUrl;
+ },
projectNameWithNamespace() {
return this.project.nameWithNamespace || this.project.name_with_namespace;
},
@@ -49,7 +52,11 @@ export default {
class="gl-display-flex gl-align-items-center gl-flex-wrap project-namespace-name-container"
>
-
+
" \
# --or--
-# Deprecated: removal planned in 15.0
+# Deprecated: removal planned in 16.0
curl --request PUT --header "PRIVATE-TOKEN:
" \
--form "active=false" "https://gitlab.example.com/api/v4/runners/6"
```
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 21d1ee84722..733a0344d51 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1121,7 +1121,7 @@ host localhost # Give your setup a name (here: override localhost)
hostname 127.0.0.1; # Your server name or IP
```
-You also need to change the corresponding options (for example, `ssh_user`, `ssh_host`, `admin_uri`) in the `config\gitlab.yml` file.
+You also need to change the corresponding options (for example, `ssh_user`, `ssh_host`, `admin_uri`) in the `config/gitlab.yml` file.
### Additional Markup Styles
diff --git a/doc/integration/index.md b/doc/integration/index.md
index 61d8547aaf7..e7f6e01eea1 100644
--- a/doc/integration/index.md
+++ b/doc/integration/index.md
@@ -24,8 +24,8 @@ GitLab can be configured to authenticate access requests with the following auth
- Integrate with [Kerberos](kerberos.md).
- Enable sign in via [LDAP](../administration/auth/ldap/index.md).
- Enable [OAuth2 provider](oauth_provider.md) application creation.
-- Use [OmniAuth](omniauth.md) to enable sign in via Twitter, GitHub, GitLab.com, Google,
- Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure, or Authentiq ID.
+- Use [OmniAuth](omniauth.md) to enable sign in through Twitter, GitHub, GitLab.com, Google,
+ Bitbucket, Facebook, SAML, Crowd, Azure, or Authentiq ID.
- Use GitLab as an [OpenID Connect](openid_connect_provider.md) identity provider.
- Authenticate to [Vault](vault.md) through GitLab OpenID Connect.
- Configure GitLab as a [SAML](saml.md) 2.0 Service Provider.
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index cba07e505de..41722778410 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -41,7 +41,6 @@ GitLab supports the following OmniAuth providers.
| [OpenID Connect](../administration/auth/oidc.md) | `openid_connect` |
| [Salesforce](salesforce.md) | `salesforce` |
| [SAML](saml.md) | `saml` |
-| [Shibboleth](saml.md) | `shibboleth` |
| [Twitter](twitter.md) | `twitter` |
## Configure initial settings
@@ -53,7 +52,7 @@ Setting | Description | Default value
---------------------------|-------------|--------------
`allow_single_sign_on` | Enables you to list the providers that automatically create a GitLab account. The provider names are available in the **OmniAuth provider name** column in the [supported providers table](#supported-providers). | The default is `false`. If `false`, users must be created manually, or they can't sign in using OmniAuth.
`auto_link_ldap_user` | If enabled, creates an LDAP identity in GitLab for users that are created through an OmniAuth provider. You can enable this setting if you have the [LDAP (ActiveDirectory)](../administration/auth/ldap/index.md) integration enabled. Requires the `uid` of the user to be the same in both LDAP and the OmniAuth provider. | The default is `false`.
-`block_auto_created_users` | If enabled, blocks users that are automatically created from signing in until they are approved by an administrator. | The default is `true`. If you set the value to `false`, make sure you only define providers for `allow_single_sign_on` that you can control, like SAML, Shibboleth, Crowd, or Google. Otherwise, any user on the internet can sign in to GitLab without an administrator's approval.
+`block_auto_created_users` | If enabled, blocks users that are automatically created from signing in until they are approved by an administrator. | The default is `true`. If you set the value to `false`, make sure you only define providers for `allow_single_sign_on` that you can control, like SAML, Crowd, or Google. Otherwise, any user on the internet can sign in to GitLab without an administrator's approval.
To change these settings:
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 6f204792e59..a3b9fb52f0d 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -91,7 +91,8 @@ To view a list of merge requests that need your attention:
1. On the top bar, select **Merge requests** (**{merge-request}**).
1. Select **Attention requests**.
-To request attention from another user:
+To request attention from another user, use the `/attention @user`
+[quick action](../quick_actions.md) or:
1. Go to the merge request.
1. On the right sidebar, identify the user you want to request attention from.
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index ae42d90af06..b73b381ffcd 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -55,6 +55,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/assign me` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself. |
| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` or `/request_review @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users as reviewers. |
| `/assign_reviewer me` or `/reviewer me` or `/request_review me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself as a reviewer. |
+| `/attention @user1` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | [Request attention](merge_requests/index.md#request-attention-to-a-merge-request) to a merge request from a user. |
| `/award :emoji:` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Toggle emoji award. |
| `/child_epic ` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Add child epic to ``. The `` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7330) in GitLab 12.0). |
| `/clear_health_status` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Clear [health status](issues/managing_issues.md#health-status) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213814) in GitLab 14.7). |
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index a498e329c3f..1389939f28b 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -124,9 +124,9 @@ module Gitlab
config[:storage] = storages
- runtime_dir = options[:runtime_dir] || File.join(gitaly_dir, 'run')
- FileUtils.mkdir(runtime_dir) unless File.exist?(runtime_dir)
- config[:runtime_dir] = runtime_dir
+ internal_socket_dir = options[:internal_socket_dir] || File.join(gitaly_dir, 'internal_sockets')
+ FileUtils.mkdir(internal_socket_dir) unless File.exist?(internal_socket_dir)
+ config[:internal_socket_dir] = internal_socket_dir
config[:'gitaly-ruby'] = { dir: File.join(gitaly_dir, 'ruby') } if gitaly_ruby
config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 4055d53af07..39fa905bdda 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -45052,9 +45052,6 @@ msgstr ""
msgid "project access tokens"
msgstr ""
-msgid "project avatar"
-msgstr ""
-
msgid "project bots cannot be added to other groups / projects"
msgstr ""
diff --git a/qa/qa/tools/test_resources_handler.rb b/qa/qa/tools/test_resources_handler.rb
index 476f87fff6b..d90e11a1681 100644
--- a/qa/qa/tools/test_resources_handler.rb
+++ b/qa/qa/tools/test_resources_handler.rb
@@ -81,6 +81,7 @@ module QA
return puts "\nNothing to download!" if files_list.empty?
+ FileUtils.mkdir_p('tmp/')
files_list.each do |file_name|
local_path = "tmp/#{file_name.split('/').last}"
Runtime::Logger.info("Downloading #{file_name} to #{local_path}")
diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb
index 26161b5fb5c..e1f25589eeb 100644
--- a/spec/controllers/projects/static_site_editor_controller_spec.rb
+++ b/spec/controllers/projects/static_site_editor_controller_spec.rb
@@ -76,12 +76,11 @@ RSpec.describe Projects::StaticSiteEditorController do
get :show, params: default_params
end
- it 'increases the views counter' do
- expect(Gitlab::UsageDataCounters::StaticSiteEditorCounter).to have_received(:increment_views_count)
- end
+ it 'redirects to the Web IDE' do
+ get :show, params: default_params
- it 'renders the edit page' do
- expect(response).to render_template(:show)
+ expected_path_regex = %r[-/ide/project/#{project.full_path}/edit/master/-/README.md]
+ expect(response).to redirect_to(expected_path_regex)
end
it 'assigns ref and path variables' do
@@ -96,62 +95,6 @@ RSpec.describe Projects::StaticSiteEditorController do
expect(response).to have_gitlab_http_status(:not_found)
end
end
-
- context 'when invalid config file' do
- let(:service_response) { ServiceResponse.error(message: 'invalid') }
-
- it 'redirects to project page and flashes error message' do
- expect(response).to redirect_to(project_path(project))
- expect(controller).to set_flash[:alert].to('invalid')
- end
- end
-
- context 'with a service response payload containing multiple data types' do
- let(:data) do
- {
- a_string: 'string',
- an_array: [
- {
- foo: 'bar'
- }
- ],
- an_integer: 123,
- a_hash: {
- a_deeper_hash: {
- foo: 'bar'
- }
- },
- a_boolean: true,
- a_nil: nil
- }
- end
-
- let(:assigns_data) { assigns(:data) }
-
- it 'leaves data values which are strings as strings' do
- expect(assigns_data[:a_string]).to eq('string')
- end
-
- it 'leaves data values which are integers as integers' do
- expect(assigns_data[:an_integer]).to eq(123)
- end
-
- it 'serializes data values which are booleans to JSON' do
- expect(assigns_data[:a_boolean]).to eq('true')
- end
-
- it 'serializes data values which are arrays to JSON' do
- expect(assigns_data[:an_array]).to eq('[{"foo":"bar"}]')
- end
-
- it 'serializes data values which are hashes to JSON' do
- expect(assigns_data[:a_hash]).to eq('{"a_deeper_hash":{"foo":"bar"}}')
- end
-
- it 'serializes data values which are nil to an empty string' do
- expect(assigns_data[:a_nil]).to eq('')
- end
- end
end
end
end
diff --git a/spec/features/static_site_editor_spec.rb b/spec/features/static_site_editor_spec.rb
deleted file mode 100644
index 98313905a33..00000000000
--- a/spec/features/static_site_editor_spec.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Static Site Editor' do
- include ContentSecurityPolicyHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :public, :repository) }
-
- let(:sse_path) { project_show_sse_path(project, 'master/README.md') }
-
- before_all do
- project.add_developer(user)
- end
-
- before do
- sign_in(user)
- end
-
- context "when no config file is present" do
- before do
- visit sse_path
- end
-
- it 'renders SSE page with all generated config values and default config file values' do
- node = page.find('#static-site-editor')
-
- # assert generated config values are present
- expect(node['data-base-url']).to eq("/#{project.full_path}/-/sse/master%2FREADME.md")
- expect(node['data-branch']).to eq('master')
- expect(node['data-commit-id']).to match(/\A[0-9a-f]{40}\z/)
- expect(node['data-is-supported-content']).to eq('true')
- expect(node['data-merge-requests-illustration-path'])
- .to match(%r{/assets/illustrations/merge_requests-.*\.svg})
- expect(node['data-namespace']).to eq(project.namespace.full_path)
- expect(node['data-project']).to eq(project.path)
- expect(node['data-project-id']).to eq(project.id.to_s)
-
- # assert default config file values are present
- expect(node['data-image-upload-path']).to eq('source/images')
- expect(node['data-mounts']).to eq('[{"source":"source","target":""}]')
- expect(node['data-static-site-generator']).to eq('middleman')
- end
- end
-
- context "when a config file is present" do
- let(:config_file_yml) do
- <<~YAML
- image_upload_path: custom-image-upload-path
- mounts:
- - source: source1
- target: ""
- - source: source2
- target: target2
- static_site_generator: middleman
- YAML
- end
-
- before do
- allow_next_instance_of(Repository) do |repository|
- allow(repository).to receive(:blob_data_at).and_return(config_file_yml)
- end
-
- visit sse_path
- end
-
- it 'renders Static Site Editor page values read from config file' do
- node = page.find('#static-site-editor')
-
- # assert user-specified config file values are present
- expected_mounts = '[{"source":"source1","target":""},{"source":"source2","target":"target2"}]'
- expect(node['data-image-upload-path']).to eq('custom-image-upload-path')
- expect(node['data-mounts']).to eq(expected_mounts)
- expect(node['data-static-site-generator']).to eq('middleman')
- end
- end
-
- describe 'Static Site Editor Content Security Policy' do
- subject { response_headers['Content-Security-Policy'] }
-
- context 'when no global CSP config exists' do
- before do
- setup_csp_for_controller(Projects::StaticSiteEditorController)
- end
-
- it 'does not add CSP directives' do
- visit sse_path
-
- is_expected.to be_blank
- end
- end
-
- context 'when a global CSP config exists' do
- let_it_be(:cdn_url) { 'https://some-cdn.test' }
- let_it_be(:youtube_url) { 'https://www.youtube.com' }
-
- before do
- csp = ActionDispatch::ContentSecurityPolicy.new do |p|
- p.frame_src :self, cdn_url
- end
-
- setup_existing_csp_for_controller(Projects::StaticSiteEditorController, csp)
- end
-
- it 'appends youtube to the CSP frame-src policy' do
- visit sse_path
-
- is_expected.to eql("frame-src 'self' #{cdn_url} #{youtube_url}")
- end
- end
- end
-end
diff --git a/spec/frontend/vue_shared/components/__snapshots__/identicon_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/identicon_spec.js.snap
deleted file mode 100644
index 1d8e04b83a3..00000000000
--- a/spec/frontend/vue_shared/components/__snapshots__/identicon_spec.js.snap
+++ /dev/null
@@ -1,21 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Identicon entity id is a GraphQL id matches snapshot 1`] = `
-
-
- E
-
-
-`;
-
-exports[`Identicon entity id is a number matches snapshot 1`] = `
-
-
- E
-
-
-`;
diff --git a/spec/frontend/vue_shared/components/identicon_spec.js b/spec/frontend/vue_shared/components/identicon_spec.js
deleted file mode 100644
index 24fc3713e2b..00000000000
--- a/spec/frontend/vue_shared/components/identicon_spec.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import IdenticonComponent from '~/vue_shared/components/identicon.vue';
-
-describe('Identicon', () => {
- let wrapper;
-
- const defaultProps = {
- entityId: 1,
- entityName: 'entity-name',
- sizeClass: 's40',
- };
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(IdenticonComponent, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('entity id is a number', () => {
- beforeEach(() => createComponent());
-
- it('matches snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('adds a correct class to identicon', () => {
- expect(wrapper.find({ ref: 'identicon' }).classes()).toContain('bg2');
- });
- });
-
- describe('entity id is a GraphQL id', () => {
- beforeEach(() => createComponent({ entityId: 'gid://gitlab/Project/8' }));
-
- it('matches snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('adds a correct class to identicon', () => {
- expect(wrapper.find({ ref: 'identicon' }).classes()).toContain('bg2');
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/project_avatar/default_spec.js b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
deleted file mode 100644
index d042db6051c..00000000000
--- a/spec/frontend/vue_shared/components/project_avatar/default_spec.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import { projectData } from 'jest/ide/mock_data';
-import { TEST_HOST } from 'spec/test_constants';
-import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
-import ProjectAvatarDefault from '~/vue_shared/components/deprecated_project_avatar/default.vue';
-
-describe('ProjectAvatarDefault component', () => {
- const Component = Vue.extend(ProjectAvatarDefault);
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- project: projectData,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders identicon if project has no avatar_url', async () => {
- const expectedText = getFirstCharacterCapitalized(projectData.name);
-
- vm.project = {
- ...vm.project,
- avatar_url: null,
- };
-
- await nextTick();
- const identiconEl = vm.$el.querySelector('.identicon');
-
- expect(identiconEl).not.toBe(null);
- expect(identiconEl.textContent.trim()).toEqual(expectedText);
- });
-
- it('renders avatar image if project has avatar_url', async () => {
- const avatarUrl = `${TEST_HOST}/images/home/nasa.svg`;
-
- vm.project = {
- ...vm.project,
- avatar_url: avatarUrl,
- };
-
- await nextTick();
- expect(vm.$el.querySelector('.avatar')).not.toBeNull();
- expect(vm.$el.querySelector('.identicon')).toBeNull();
- expect(vm.$el.querySelector('img')).toHaveAttr('src', avatarUrl);
- });
-});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 5afa017aa76..397ab2254b9 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
-import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
+import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
describe('ProjectListItem component', () => {
@@ -52,8 +52,13 @@ describe('ProjectListItem component', () => {
it(`renders the project avatar`, () => {
wrapper = shallowMount(Component, options);
+ const avatar = wrapper.findComponent(ProjectAvatar);
- expect(wrapper.findComponent(ProjectAvatar).exists()).toBe(true);
+ expect(avatar.exists()).toBe(true);
+ expect(avatar.props()).toMatchObject({
+ projectAvatarUrl: '',
+ projectName: project.name_with_namespace,
+ });
});
it(`renders a simple namespace name with a trailing slash`, () => {
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 0ad83bdeeb2..a4ee618457d 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -267,7 +267,7 @@ module GitalySetup
{ 'default' => repos_path },
force: true,
options: {
- runtime_dir: File.join(gitaly_dir, "run2"),
+ internal_socket_dir: File.join(gitaly_dir, "internal_gitaly2"),
gitaly_socket: "gitaly2.socket",
config_filename: "gitaly2.config.toml"
}