Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/admin/users/components/user_actions.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue1
-rw-r--r--app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/remove_member_button.vue16
-rw-r--r--app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue18
-rw-r--r--app/assets/javascripts/members/components/table/member_action_buttons.vue5
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue5
-rw-r--r--app/models/namespace.rb8
-rw-r--r--app/models/user.rb4
-rw-r--r--app/services/import/github_service.rb11
-rw-r--r--app/views/admin/users/projects.html.haml4
-rw-r--r--doc/development/documentation/styleguide/word_list.md13
-rw-r--r--doc/user/application_security/api_fuzzing/index.md19
-rw-r--r--doc/user/application_security/dast_api/index.md19
-rw-r--r--lib/api/entities/ci/pipeline.rb4
-rw-r--r--locale/gitlab.pot9
-rw-r--r--spec/frontend/members/components/action_buttons/remove_member_button_spec.js19
-rw-r--r--spec/frontend/members/components/action_buttons/user_action_buttons_spec.js31
-rw-r--r--spec/frontend/members/components/table/member_action_buttons_spec.js1
-rw-r--r--spec/lib/api/entities/ci/pipeline_spec.rb16
-rw-r--r--spec/models/user_spec.rb26
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb2
-rw-r--r--spec/services/import/github_service_spec.rb33
-rw-r--r--spec/support/database/cross-database-modification-allowlist.yml1
24 files changed, 226 insertions, 43 deletions
diff --git a/app/assets/javascripts/admin/users/components/user_actions.vue b/app/assets/javascripts/admin/users/components/user_actions.vue
index 4f4e2947341..567d7151847 100644
--- a/app/assets/javascripts/admin/users/components/user_actions.vue
+++ b/app/assets/javascripts/admin/users/components/user_actions.vue
@@ -112,7 +112,7 @@ export default {
right
:text="$options.i18n.userAdministration"
:text-sr-only="!showButtonLabels"
- icon="settings"
+ icon="ellipsis_h"
data-qa-selector="user_actions_dropdown_toggle"
:data-qa-username="user.username"
>
diff --git a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
index 35966be7363..d092283338c 100644
--- a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
@@ -53,6 +53,7 @@ export default {
:title="s__('Member|Deny access')"
:is-access-request="true"
icon="close"
+ button-category="primary"
/>
</div>
</action-button-group>
diff --git a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
index 91062c222f4..ab9abfd38c6 100644
--- a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
@@ -41,6 +41,8 @@ export default {
<remove-member-button
:member-id="member.id"
:message="message"
+ icon="remove"
+ button-category="primary"
:title="s__('Member|Revoke invite')"
is-invite
/>
diff --git a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
index 69137ce615b..01606d07554 100644
--- a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
@@ -30,7 +30,17 @@ export default {
icon: {
type: String,
required: false,
- default: 'remove',
+ default: undefined,
+ },
+ buttonText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ buttonCategory: {
+ type: String,
+ required: false,
+ default: 'secondary',
},
isAccessRequest: {
type: Boolean,
@@ -79,10 +89,12 @@ export default {
<gl-button
v-gl-tooltip
variant="danger"
+ :category="buttonCategory"
:title="title"
:aria-label="title"
:icon="icon"
data-qa-selector="delete_member_button"
@click="showRemoveMemberModal(modalData)"
- />
+ ><template v-if="buttonText">{{ buttonText }}</template></gl-button
+ >
</template>
diff --git a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
index 44d658c90a0..594da7f68cc 100644
--- a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
@@ -1,5 +1,5 @@
<script>
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import { parseUserDeletionObstacles } from '~/vue_shared/components/user_deletion_obstacles/utils';
import ActionButtonGroup from './action_button_group.vue';
import LeaveButton from './leave_button.vue';
@@ -23,6 +23,10 @@ export default {
type: Boolean,
required: true,
},
+ isInvitedUser: {
+ type: Boolean,
+ required: true,
+ },
permissions: {
type: Object,
required: true,
@@ -56,6 +60,15 @@ export default {
obstacles: parseUserDeletionObstacles(this.member.user),
};
},
+ removeMemberButtonText() {
+ return this.isInvitedUser ? null : __('Remove user');
+ },
+ removeMemberButtonIcon() {
+ return this.isInvitedUser ? 'remove' : '';
+ },
+ removeMemberButtonCategory() {
+ return this.isInvitedUser ? 'primary' : 'secondary';
+ },
},
};
</script>
@@ -70,6 +83,9 @@ export default {
:member-type="member.type"
:user-deletion-obstacles="userDeletionObstaclesUserData"
:message="message"
+ :icon="removeMemberButtonIcon"
+ :button-text="removeMemberButtonText"
+ :button-category="removeMemberButtonCategory"
:title="s__('Member|Remove member')"
/>
</div>
diff --git a/app/assets/javascripts/members/components/table/member_action_buttons.vue b/app/assets/javascripts/members/components/table/member_action_buttons.vue
index 6f15f079d2d..971b1a8435e 100644
--- a/app/assets/javascripts/members/components/table/member_action_buttons.vue
+++ b/app/assets/javascripts/members/components/table/member_action_buttons.vue
@@ -30,6 +30,10 @@ export default {
type: Boolean,
required: true,
},
+ isInvitedUser: {
+ type: Boolean,
+ required: true,
+ },
},
computed: {
actionButtonComponent() {
@@ -53,5 +57,6 @@ export default {
:member="member"
:permissions="permissions"
:is-current-user="isCurrentUser"
+ :is-invited-user="isInvitedUser"
/>
</template>
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index 202f3aa89e1..de733ae75df 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -8,6 +8,7 @@ import initUserPopovers from '~/user_popovers';
import {
FIELDS,
ACTIVE_TAB_QUERY_PARAM_NAME,
+ TAB_QUERY_PARAM_VALUES,
MEMBER_STATE_AWAITING,
USER_STATE_BLOCKED_PENDING_APPROVAL,
BADGE_LABELS_PENDING_OWNER_APPROVAL,
@@ -82,6 +83,9 @@ export default {
return paramName && currentPage && perPage && totalItems;
},
+ isInvitedUser() {
+ return this.tabQueryParamValue === TAB_QUERY_PARAM_VALUES.invite;
+ },
},
mounted() {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
@@ -275,6 +279,7 @@ export default {
<member-action-buttons
:member-type="memberType"
:is-current-user="isCurrentUser"
+ :is-invited-user="isInvitedUser"
:permissions="permissions"
:member="member"
/>
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 75e06ac2b86..db306221318 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -120,12 +120,8 @@ class Namespace < ApplicationRecord
saved_change_to_name? || saved_change_to_path? || saved_change_to_parent_id?
}
- # TODO: change to `type: Namespaces::UserNamespace.sti_name` when
- # working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- scope :user_namespaces, -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) }
- # TODO: this can be simplified with `type != 'Project'` when working on issue
- # https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- scope :without_project_namespaces, -> { where(Namespace.arel_table[:type].is_distinct_from(Namespaces::ProjectNamespace.sti_name)) }
+ scope :user_namespaces, -> { where(type: Namespaces::UserNamespace.sti_name) }
+ scope :without_project_namespaces, -> { where(Namespace.arel_table[:type].not_eq(Namespaces::ProjectNamespace.sti_name)) }
scope :sort_by_type, -> { order(Gitlab::Database.nulls_first_order(:type)) }
scope :include_route, -> { includes(:route) }
scope :by_parent, -> (parent) { where(parent_id: parent) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 691a07bd6bc..f8579add392 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -112,10 +112,8 @@ class User < ApplicationRecord
#
# Namespace for personal projects
- # TODO: change to `:namespace, -> { where(type: Namespaces::UserNamespace.sti_name}, class_name: 'Namespaces::UserNamespace'...`
- # when working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
has_one :namespace,
- -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) },
+ -> { where(type: Namespaces::UserNamespace.sti_name) },
dependent: :destroy, # rubocop:disable Cop/ActiveRecordDependent
foreign_key: :owner_id,
inverse_of: :owner,
diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb
index 2aaab88e778..061543b5885 100644
--- a/app/services/import/github_service.rb
+++ b/app/services/import/github_service.rb
@@ -10,7 +10,7 @@ module Import
def execute(access_params, provider)
if blocked_url?
- return log_and_return_error("Invalid URL: #{url}", :bad_request)
+ return log_and_return_error("Invalid URL: #{url}", _("Invalid URL: %{url}") % { url: url }, :bad_request)
end
unless authorized?
@@ -119,6 +119,15 @@ module Import
error(_('Import failed due to a GitHub error: %{original}') % { original: exception.response_body }, :unprocessable_entity)
end
+
+ def log_and_return_error(message, translated_message, http_status)
+ Gitlab::GithubImport::Logger.error(
+ message: 'Error while attempting to import from GitHub',
+ error: message
+ )
+
+ error(translated_message, http_status)
+ end
end
end
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
index 8c56e888dcc..b47ed38f65f 100644
--- a/app/views/admin/users/projects.html.haml
+++ b/app/views/admin/users/projects.html.haml
@@ -17,7 +17,7 @@
%span.light.vertical-align-middle= group_member.human_access
- unless group_member.owner?
= link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), testid: 'remove-user' }, method: :delete, remote: true, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from group') do
- = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ = sprite_icon('remove', size: 16, css_class: 'gl-icon')
.row
.col-md-6
@@ -47,6 +47,6 @@
- if member.respond_to? :project
= link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from project') do
- = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ = sprite_icon('remove', size: 16, css_class: 'gl-icon')
= render partial: 'admin/users/modals'
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index a044e7a3177..b55c7a5dd30 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -376,6 +376,19 @@ Do not use **build** to be synonymous with **job**. A job is defined in the `.gi
If you want to use **CI** with the word **job**, use **CI/CD job** rather than **CI job**.
+## Kubernetes executor
+
+GitLab Runner can run jobs on a Kubernetes cluster. To do this, GitLab Runner uses the Kubernetes executor.
+
+When referring to this feature, use:
+
+- Kubernetes executor for GitLab Runner
+- Kubernetes executor
+
+Do not use:
+
+- GitLab Runner Kubernetes executor, because this can infringe on the Kubernetes trademark.
+
## later
Use **later** when talking about version numbers.
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index e5f3437a121..2d8fa78f793 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -1293,6 +1293,25 @@ The API Fuzzing template supports launching a docker container containing an API
TODO
-->
+## Get support or request an improvement
+
+To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/get-help/).
+
+The [GitLab issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues) is the right place for bugs and feature proposals about API Security and API Fuzzing.
+Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding API fuzzing to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](../../../development/code_review.md#review-response-slo) to understand when you should receive a response.
+
+[Search the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) for similar entries before submitting your own, there's a good chance somebody else had the same issue or feature proposal. Show your support with an award emoji and or join the discussion.
+
+When experiencing a behavior not working as expected, consider providing contextual information:
+
+- GitLab version if using a self-managed instance.
+- `.gitlab-ci.yml` job definition.
+- Full job console output.
+- Scanner log file available as a job artifact named `gl-api-security-scanner.log`.
+
+WARNING:
+**Sanitize data attached to a support issue**. Please remove sensitive information, including: credentials, passwords, tokens, keys, and secrets.
+
## Glossary
- Assert: Assertions are detection modules used by checks to trigger a fault. Many assertions have
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index e6cb207cf5a..da6cb817518 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -1209,6 +1209,25 @@ deploy-test-target:
- environment_url.txt
```
+## Get support or request an improvement
+
+To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/get-help/).
+
+The [GitLab issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues) is the right place for bugs and feature proposals about API Security and DAST API.
+Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding DAST API to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](../../../development/code_review.md#review-response-slo) to understand when you should receive a response.
+
+[Search the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) for similar entries before submitting your own, there's a good chance somebody else had the same issue or feature proposal. Show your support with an award emoji and or join the discussion.
+
+When experiencing a behavior not working as expected, consider providing contextual information:
+
+- GitLab version if using a self-managed instance.
+- `.gitlab-ci.yml` job definition.
+- Full job console output.
+- Scanner log file available as a job artifact named `gl-api-security-scanner.log`.
+
+WARNING:
+**Sanitize data attached to a support issue**. Please remove sensitive information, including: credentials, passwords, tokens, keys, and secrets.
+
## Glossary
- Assert: Assertions are detection modules used by checks to trigger a vulnerability. Many assertions have
diff --git a/lib/api/entities/ci/pipeline.rb b/lib/api/entities/ci/pipeline.rb
index 11336ae070d..a8033a21044 100644
--- a/lib/api/entities/ci/pipeline.rb
+++ b/lib/api/entities/ci/pipeline.rb
@@ -10,7 +10,9 @@ module API
expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
expose :duration
expose :queued_duration
- expose :coverage
+ expose :coverage do |pipeline|
+ pipeline.present.coverage
+ end
expose :detailed_status, using: DetailedStatusEntity do |pipeline, options|
pipeline.detailed_status(options[:current_user])
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8e455321a43..e50022f9dd0 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -12381,15 +12381,15 @@ msgstr ""
msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
msgstr ""
-msgid "Discover|Give feedback for this page"
-msgstr ""
-
msgid "Discover|Security capabilities, integrated into your development lifecycle"
msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
+msgid "Discover|Send feedback"
+msgstr ""
+
msgid "Discover|Start a free trial"
msgstr ""
@@ -19071,6 +19071,9 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
+msgid "Invalid URL: %{url}"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
diff --git a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
index 7eb0ea37fe6..1a031cc56d6 100644
--- a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
@@ -54,6 +54,8 @@ describe('RemoveMemberButton', () => {
});
};
+ const findButton = () => wrapper.findComponent(GlButton);
+
beforeEach(() => {
createComponent();
});
@@ -66,7 +68,6 @@ describe('RemoveMemberButton', () => {
expect(wrapper.attributes()).toMatchObject({
'aria-label': 'Remove member',
title: 'Remove member',
- icon: 'remove',
});
});
@@ -75,8 +76,22 @@ describe('RemoveMemberButton', () => {
});
it('calls Vuex action to show `remove member` modal when clicked', () => {
- wrapper.findComponent(GlButton).vm.$emit('click');
+ findButton().vm.$emit('click');
expect(actions.showRemoveMemberModal).toHaveBeenCalledWith(expect.any(Object), modalData);
});
+
+ describe('button optional properties', () => {
+ it('has default value for category and text', () => {
+ createComponent();
+ expect(findButton().props('category')).toBe('secondary');
+ expect(findButton().text()).toBe('');
+ });
+
+ it('allow changing value of button category and text', () => {
+ createComponent({ buttonCategory: 'primary', buttonText: 'Decline request' });
+ expect(findButton().props('category')).toBe('primary');
+ expect(findButton().text()).toBe('Decline request');
+ });
+ });
});
diff --git a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
index 10e451376c8..356df7e7b11 100644
--- a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
@@ -13,6 +13,7 @@ describe('UserActionButtons', () => {
propsData: {
member,
isCurrentUser: false,
+ isInvitedUser: false,
...propsData,
},
});
@@ -45,7 +46,9 @@ describe('UserActionButtons', () => {
title: 'Remove member',
isAccessRequest: false,
isInvite: false,
- icon: 'remove',
+ icon: '',
+ buttonCategory: 'secondary',
+ buttonText: 'Remove user',
userDeletionObstacles: {
name: member.user.name,
obstacles: parseUserDeletionObstacles(member.user),
@@ -129,4 +132,30 @@ describe('UserActionButtons', () => {
expect(findRemoveMemberButton().props().memberType).toBe('ProjectMember');
});
});
+
+ describe('isInvitedUser', () => {
+ it.each`
+ isInvitedUser | icon | buttonText | buttonCategory
+ ${true} | ${'remove'} | ${null} | ${'primary'}
+ ${false} | ${''} | ${'Remove user'} | ${'secondary'}
+ `(
+ 'passes the correct props to remove-member-button when isInvitedUser is $isInvitedUser',
+ ({ isInvitedUser, icon, buttonText, buttonCategory }) => {
+ createComponent({
+ isInvitedUser,
+ permissions: {
+ canRemove: true,
+ },
+ });
+
+ expect(findRemoveMemberButton().props()).toEqual(
+ expect.objectContaining({
+ icon,
+ buttonText,
+ buttonCategory,
+ }),
+ );
+ },
+ );
+ });
});
diff --git a/spec/frontend/members/components/table/member_action_buttons_spec.js b/spec/frontend/members/components/table/member_action_buttons_spec.js
index 546d09732d6..1379b2d26ce 100644
--- a/spec/frontend/members/components/table/member_action_buttons_spec.js
+++ b/spec/frontend/members/components/table/member_action_buttons_spec.js
@@ -14,6 +14,7 @@ describe('MemberActionButtons', () => {
wrapper = shallowMount(MemberActionButtons, {
propsData: {
isCurrentUser: false,
+ isInvitedUser: false,
permissions: {
canRemove: true,
},
diff --git a/spec/lib/api/entities/ci/pipeline_spec.rb b/spec/lib/api/entities/ci/pipeline_spec.rb
new file mode 100644
index 00000000000..6a658cc3e18
--- /dev/null
+++ b/spec/lib/api/entities/ci/pipeline_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::Ci::Pipeline do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+ let_it_be(:job) { create(:ci_build, name: "rspec", coverage: 30.212, pipeline: pipeline) }
+
+ let(:entity) { described_class.new(pipeline) }
+
+ subject { entity.as_json }
+
+ it 'returns the coverage as a string' do
+ expect(subject[:coverage]).to eq '30.21'
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 3813fcd18b1..acc3d598269 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2602,26 +2602,18 @@ RSpec.describe User do
end
describe '.find_by_full_path' do
- using RSpec::Parameterized::TableSyntax
+ let!(:user) { create(:user, namespace: create(:user_namespace)) }
- # TODO: this `where/when` can be removed in issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- # At that point we only need to check `user_namespace`
- where(namespace_type: [:namespace, :user_namespace])
+ context 'with a route matching the given path' do
+ let!(:route) { user.namespace.route }
- with_them do
- let!(:user) { create(:user, namespace: create(namespace_type)) }
-
- context 'with a route matching the given path' do
- let!(:route) { user.namespace.route }
-
- it 'returns the user' do
- expect(described_class.find_by_full_path(route.path)).to eq(user)
- end
+ it 'returns the user' do
+ expect(described_class.find_by_full_path(route.path)).to eq(user)
+ end
- it 'is case-insensitive' do
- expect(described_class.find_by_full_path(route.path.upcase)).to eq(user)
- expect(described_class.find_by_full_path(route.path.downcase)).to eq(user)
- end
+ it 'is case-insensitive' do
+ expect(described_class.find_by_full_path(route.path.upcase)).to eq(user)
+ expect(described_class.find_by_full_path(route.path.downcase)).to eq(user)
end
context 'with a redirect route matching the given path' do
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 7ae350885f4..ab977f8326d 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -840,7 +840,7 @@ RSpec.describe API::Ci::Pipelines do
it 'exposes the coverage' do
get api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
- expect(json_response["coverage"].to_i).to eq(30)
+ expect(json_response["coverage"]).to eq('30.00')
end
end
end
diff --git a/spec/services/import/github_service_spec.rb b/spec/services/import/github_service_spec.rb
index 776df01d399..04a94d96f67 100644
--- a/spec/services/import/github_service_spec.rb
+++ b/spec/services/import/github_service_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Import::GithubService do
let_it_be(:access_params) { { github_access_token: 'github-complex-token' } }
let_it_be(:params) { { repo_id: 123, new_name: 'new_repo', target_namespace: 'root' } }
- let(:subject) { described_class.new(client, user, params) }
+ subject(:github_importer) { described_class.new(client, user, params) }
before do
allow(subject).to receive(:authorized?).and_return(true)
@@ -110,6 +110,29 @@ RSpec.describe Import::GithubService do
end
end
end
+
+ context 'when a blocked/local URL is used as github_hostname' do
+ let(:message) { 'Error while attempting to import from GitHub' }
+ let(:error) { "Invalid URL: #{url}" }
+
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
+ end
+
+ where(url: %w[https://localhost https://10.0.0.1])
+
+ with_them do
+ it 'returns and logs an error' do
+ allow(github_importer).to receive(:url).and_return(url)
+
+ expect(Gitlab::Import::Logger).to receive(:error).with({
+ message: message,
+ error: error
+ }).and_call_original
+ expect(github_importer.execute(access_params, :github)).to include(blocked_url_error(url))
+ end
+ end
+ end
end
context 'when remove_legacy_github_client feature flag is enabled' do
@@ -135,4 +158,12 @@ RSpec.describe Import::GithubService do
message: '"repository" size (101 Bytes) is larger than the limit of 100 Bytes.'
}
end
+
+ def blocked_url_error(url)
+ {
+ status: :error,
+ http_status: :bad_request,
+ message: "Invalid URL: #{url}"
+ }
+ end
end
diff --git a/spec/support/database/cross-database-modification-allowlist.yml b/spec/support/database/cross-database-modification-allowlist.yml
index 1bc77577f56..9b4233c64f4 100644
--- a/spec/support/database/cross-database-modification-allowlist.yml
+++ b/spec/support/database/cross-database-modification-allowlist.yml
@@ -3,7 +3,6 @@
- "./ee/spec/mailers/notify_spec.rb"
- "./ee/spec/models/ci/bridge_spec.rb"
- "./ee/spec/models/ci/build_spec.rb"
-- "./ee/spec/models/ci/minutes/additional_pack_spec.rb"
- "./ee/spec/models/ee/ci/job_artifact_spec.rb"
- "./ee/spec/models/group_member_spec.rb"
- "./ee/spec/replicators/geo/pipeline_artifact_replicator_spec.rb"