Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-03-29 21:10:06 +00:00
parent 59bd8a4403
commit 2bc1877c51
39 changed files with 436 additions and 201 deletions

View File

@ -315,13 +315,13 @@ async function fetchMetrics(metricsUrl, { filters = {}, limit } = {}) {
const params = new URLSearchParams();
if (Array.isArray(filters.search)) {
const searchPrefix = filters.search
const search = filters.search
.map((f) => f.value)
.join(' ')
.trim();
if (searchPrefix) {
params.append('starts_with', searchPrefix);
if (search) {
params.append('search', search);
if (limit) {
params.append('limit', limit);
}

View File

@ -49,6 +49,9 @@ export default {
showHeader() {
return this.loading || this.organizations.nodes?.length;
},
showNewOrganizationButton() {
return gon.features?.allowOrganizationCreation;
},
loading() {
return this.$apollo.queries.organizations.loading;
},
@ -79,7 +82,7 @@ export default {
<div v-if="showHeader" class="gl-display-flex gl-align-items-center">
<h1 class="gl-my-4 gl-font-size-h-display">{{ $options.i18n.organizations }}</h1>
<div class="gl-ml-auto">
<gl-button :href="newOrganizationUrl" variant="confirm">{{
<gl-button v-if="showNewOrganizationButton" :href="newOrganizationUrl" variant="confirm">{{
$options.i18n.newOrganization
}}</gl-button>
</div>

View File

@ -131,15 +131,10 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
end
def actions
actions = {
{
createBranch: {
templateUrl: "#{new_jira_connect_branch_url}?issue_key={issue.key}&issue_summary={issue.summary}"
}
}
return actions unless Feature.enabled?(:atlassian_new_app_based_auth_model)
actions.merge(
},
searchConnectedWorkspaces: {
templateUrl: search_jira_connect_workspaces_url
},
@ -149,6 +144,6 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
associateRepository: {
templateUrl: associate_jira_connect_repositories_url
}
)
}
end
end

View File

@ -2,10 +2,6 @@
module JiraConnect
class RepositoriesController < JiraConnect::ApplicationController
before_action do
render_404 if Feature.disabled?(:atlassian_new_app_based_auth_model)
end
feature_category :integrations
def search

View File

@ -2,10 +2,6 @@
module JiraConnect
class WorkspacesController < JiraConnect::ApplicationController
before_action do
render_404 if Feature.disabled?(:atlassian_new_app_based_auth_model)
end
feature_category :integrations
def search

View File

@ -11,6 +11,9 @@ module Organizations
before_action :event_filter, only: [:activity]
before_action :authorize_read_organization!, only: [:activity, :show, :groups_and_projects]
before_action only: [:index] do
push_frontend_feature_flag(:allow_organization_creation, current_user)
end
skip_before_action :authenticate_user!, only: [:activity, :show, :groups_and_projects]

View File

@ -79,12 +79,7 @@ module EnvironmentsHelper
def static_metrics_data
{
'documentation_path' => help_page_path('administration/monitoring/prometheus/index'),
'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index', anchor: 'add-a-new-dashboard-to-your-project'),
'empty_getting_started_svg_path' => image_path('illustrations/monitoring/getting_started.svg'),
'empty_loading_svg_path' => image_path('illustrations/monitoring/loading.svg'),
'empty_no_data_svg_path' => image_path('illustrations/monitoring/no_data.svg'),
'empty_no_data_small_svg_path' => image_path('illustrations/chart-empty-state-small.svg'),
'empty_unable_to_connect_svg_path' => image_path('illustrations/monitoring/unable_to_connect.svg')
'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index', anchor: 'add-a-new-dashboard-to-your-project')
}
end
end

View File

@ -161,7 +161,7 @@ module SearchHelper
end
def search_service
@search_service ||= ::SearchService.new(current_user, sanitized_search_params)
@search_service ||= ::SearchService.new(current_user, params)
end
def search_sort_options
@ -588,20 +588,6 @@ module SearchHelper
issuable.target_branch unless issuable.target_branch == issuable.project.default_branch
end
def sanitized_search_params
sanitized_params = params.dup
if sanitized_params.key?(:confidential)
sanitized_params[:confidential] = Gitlab::Utils.to_boolean(sanitized_params[:confidential])
end
if sanitized_params.key?(:include_archived)
sanitized_params[:include_archived] = Gitlab::Utils.to_boolean(sanitized_params[:include_archived])
end
sanitized_params
end
def wiki_blob_link(wiki_blob)
project_wiki_path(wiki_blob.project, wiki_blob.basename)
end

View File

@ -815,6 +815,10 @@ class Project < ApplicationRecord
scope :in_organization, -> (organization) { where(organization: organization) }
scope :not_a_fork, -> {
left_outer_joins(:fork_network_member).where(fork_network_member: { forked_from_project_id: nil })
}
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,

View File

@ -62,11 +62,6 @@ module Clusters
'dashboard-endpoint': clusterable.metrics_dashboard_path(cluster),
'documentation-path': help_page_path('user/infrastructure/clusters/manage/clusters_health'),
'add-dashboard-documentation-path': help_page_path('operations/metrics/dashboards/index', anchor: 'add-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': image_path('illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': image_path('illustrations/monitoring/loading.svg'),
'empty-no-data-svg-path': image_path('illustrations/monitoring/no_data.svg'),
'empty-no-data-small-svg-path': image_path('illustrations/chart-empty-state-small.svg'),
'empty-unable-to-connect-svg-path': image_path('illustrations/monitoring/unable_to_connect.svg'),
'settings-path': '',
'project-path': '',
'tags-path': ''

View File

@ -4,6 +4,7 @@ module Organizations
class CreateService < ::Organizations::BaseService
def execute
return error_no_permissions unless can?(current_user, :create_organization)
return error_feature_flag unless Feature.enabled?(:allow_organization_creation, current_user)
add_organization_owner_attributes
organization = Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification
@ -35,5 +36,10 @@ module Organizations
ServiceResponse.error(message: Array(message))
end
def error_feature_flag
# Don't translate feature flag error because it's temporary.
ServiceResponse.error(message: ['Feature flag `allow_organization_creation` is not enabled for this user.'])
end
end
end

View File

@ -1,8 +1,8 @@
---
name: atlassian_new_app_based_auth_model
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142316
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442334
milestone: '16.10'
group: group::import and integrate
name: allow_organization_creation
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147930
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/452062
milestone: '16.11'
type: development
group: group::tenant scale
default_enabled: false

View File

@ -1,10 +1,25 @@
---
table_name: audit_events_streaming_event_type_filters
classes:
- AuditEvents::Streaming::EventTypeFilter
- AuditEvents::Streaming::EventTypeFilter
feature_categories:
- audit_events
- audit_events
description: Represents a event type filter for audit event streaming
introduced_by_url:
milestone: '15.6'
gitlab_schema: gitlab_main
gitlab_schema: gitlab_main_cell
allow_cross_joins:
- gitlab_main_clusterwide
allow_cross_transactions:
- gitlab_main_clusterwide
allow_cross_foreign_keys:
- gitlab_main_clusterwide
desired_sharding_key:
group_id:
references: namespaces
backfill_via:
parent:
foreign_key: external_audit_event_destination_id
table: audit_events_external_audit_event_destinations
sharding_key: namespace_id
belongs_to: external_audit_event_destination

View File

@ -1,10 +1,25 @@
---
table_name: audit_events_streaming_headers
classes:
- AuditEvents::Streaming::Header
- AuditEvents::Streaming::Header
feature_categories:
- audit_events
- audit_events
description: Represents a HTTP header sent with streaming audit events
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88063
milestone: '15.1'
gitlab_schema: gitlab_main
gitlab_schema: gitlab_main_cell
allow_cross_joins:
- gitlab_main_clusterwide
allow_cross_transactions:
- gitlab_main_clusterwide
allow_cross_foreign_keys:
- gitlab_main_clusterwide
desired_sharding_key:
group_id:
references: namespaces
backfill_via:
parent:
foreign_key: external_audit_event_destination_id
table: audit_events_external_audit_event_destinations
sharding_key: namespace_id
belongs_to: external_audit_event_destination

View File

@ -237,7 +237,7 @@ Where **T** is the date of a [minor GitLab release](../../policy/maintenance.md)
1. At T+6 calendar days: Tenant instances in the `APAC` maintenance window are upgraded.
1. At T+10 calendar days: Tenant instances in the `AMER Option 2` maintenance window are upgraded.
For example, GitLab 16.9 released on 2024-02-15. Therefore, tenant instances in the `EMEA` and `AMER Option 1` maintenance window are upgraded on 2024-04-20.
For example, GitLab 16.9 released on 2024-02-15. Therefore, tenant instances in the `EMEA` and `AMER Option 1` maintenance window are upgraded to 16.8 on 2024-02-20.
#### Emergency maintenance

View File

@ -1295,7 +1295,7 @@ Use `expire_in` to specify how long [job artifacts](../jobs/job_artifacts.md) ar
they expire and are deleted. The `expire_in` setting does not affect:
- Artifacts from the latest job, unless keeping the latest job artifacts is disabled
[at the project level](../jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
[at the project level](../jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs)
or [instance-wide](../../administration/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
After their expiry, artifacts are deleted hourly by default (using a cron job), and are not

View File

@ -1740,6 +1740,31 @@ For status, choose one:
Generally available features should not have a status.
##### Duplicating tier, offering, or status on subheadings
If a subheading has the same tier, offering, or status as its parent
topic, you don't need to repeat the information in the subheading's
badge.
For example, if the heading 1 is:
```markdown
# My title
DETAILS:
**Offering:** GitLab.com
**Tier:** Premium, Ultimate
```
Any lower-level heading that applies to a different tier but same offering would be:
```markdown
## My title
DETAILS:
**Tier:** Ultimate
```
##### Inline tier badges
Do not add tier badges inline with other text.

View File

@ -21,7 +21,7 @@ Some features are still in development. View details about [support for each sta
| Helps you write code more efficiently by showing code suggestions as you type. <br><br><i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Watch overview](https://www.youtube.com/watch?v=hCAyCTacdAQ) | [Code Suggestions](project/repository/code_suggestions/index.md) | **Tier:** Premium or Ultimate with [GitLab Duo Pro](../subscriptions/subscription-add-ons.md) <br>**Offering:** GitLab.com, Self-managed, GitLab Dedicated |
| Processes and generates text and code in a conversational manner. Helps you quickly identify useful information in large volumes of text in issues, epics, code, and GitLab documentation. | [Chat](gitlab_duo_chat.md) | **Tier:** Premium, Ultimate <br>**Offering:** GitLab.com, Self-managed, GitLab Dedicated <br>**Status:** Beta (Subject to the [Testing Agreement](https://handbook.gitlab.com/handbook/legal/testing-agreement/)) |
| Helps you discover or recall Git commands when and where you need them. | [Git suggestions](../editor_extensions/gitlab_cli/index.md#gitlab-duo-commands) | **Tier:** Ultimate <br>**Offering:** GitLab.com <br>**Status:** Experiment |
| Assists with quickly getting everyone up to speed on lengthy conversations to help ensure you are all on the same page. | [Discussion summary](#summarize-issue-discussions-with-discussion-summary) | **Tier:** Ultimate <br>**Offering:** GitLab.com <br>**Status:** Experiment |
| Assists with quickly getting everyone up to speed on lengthy conversations to help ensure you are all on the same page. <br><br><i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Watch overview](https://www.youtube.com/watch?v=IcdxLfTIUgc) | [Discussion summary](#summarize-issue-discussions-with-discussion-summary) | **Tier:** Ultimate <br>**Offering:** GitLab.com <br>**Status:** Experiment |
| Generates issue descriptions. | [Issue description generation](#summarize-an-issue-with-issue-description-generation) | **Tier:** Ultimate<br>**Offering:** GitLab.com <br>**Status:** Experiment |
| Automates repetitive tasks and helps catch bugs early. | [Test generation](gitlab_duo_chat.md#write-tests-in-the-ide) | **Tier:** Ultimate <br>**Offering:** GitLab.com, Self-managed, GitLab Dedicated <br>**Status:** Beta |
| Generates a description for the merge request based on the contents of the template. | [Merge request template population](project/merge_requests/ai_in_merge_requests.md#fill-in-merge-request-templates) | **Tier:** Ultimate<br>**Offering:** GitLab.com <br>**Status:** Experiment |

View File

@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Free user limit
DETAILS:
**Tier:** Free, Premium, Ultimate
**Tier:** Free
**Offering:** GitLab.com
A five-user limit applies to newly created top-level namespaces with

View File

@ -58,6 +58,10 @@ module ContainerRegistry
}
end
def connected?
!registry_info.empty?
end
def repository_tags(name, page_size: DEFAULT_TAGS_PAGE_SIZE)
response = faraday.get("/v2/#{name}/tags/list") do |req|
req.params['n'] = page_size

View File

@ -18,7 +18,7 @@ module Gitlab
alias_method :term, :query_string
def initialize(params, detect_abuse: true)
@raw_params = params.is_a?(Hash) ? params.with_indifferent_access : params.dup
@raw_params = convert_all_boolean_params(params)
@query_string = strip_surrounding_whitespace(@raw_params[:search] || @raw_params[:term])
@detect_abuse = detect_abuse
@abuse_detection = AbuseDetection.new(self) if @detect_abuse
@ -93,6 +93,24 @@ module Gitlab
def strip_surrounding_whitespace(obj)
obj.to_s.strip
end
def convert_all_boolean_params(params)
converted_params = params.is_a?(Hash) ? params.with_indifferent_access : params.dup
if converted_params.key?(:confidential)
converted_params[:confidential] = Gitlab::Utils.to_boolean(converted_params[:confidential])
end
if converted_params.key?(:include_archived)
converted_params[:include_archived] = Gitlab::Utils.to_boolean(converted_params[:include_archived])
end
if converted_params.key?(:include_forked)
converted_params[:include_forked] = Gitlab::Utils.to_boolean(converted_params[:include_forked])
end
converted_params
end
end
end
end

View File

@ -34635,7 +34635,7 @@ msgstr ""
msgid "ObservabilityMetrics|Search"
msgstr ""
msgid "ObservabilityMetrics|Search metrics starting with..."
msgid "ObservabilityMetrics|Search metrics..."
msgstr ""
msgid "ObservabilityMetrics|Select attributes"
@ -45826,6 +45826,9 @@ msgstr ""
msgid "SecurityOrchestration|Failed to load images."
msgstr ""
msgid "SecurityOrchestration|Fetching"
msgstr ""
msgid "SecurityOrchestration|Fetching the scope information."
msgstr ""

View File

@ -1,4 +1,4 @@
ARG GDK_SHA=5c935ca5fabd2f0de85aee3e8799aee95b371123
ARG GDK_SHA=a2f71be9f31d963372199010b9682bdfbab11b10
# Use tag prefix when running on 'stable' branch to make sure 'protected' image is used which is not deleted by registry cleanup
ARG GDK_BASE_TAG_PREFIX

View File

@ -32,6 +32,7 @@ module QA
view 'app/assets/javascripts/ci/pipeline_details/graph/components/stage_column_component.vue' do
element 'job-item-container', required: true
element 'stage-column-title'
end
def running?(wait: 0)
@ -134,6 +135,10 @@ module QA
end
end
end
def has_stage?(name)
has_element?('stage-column-title', text: name)
end
end
end
end

View File

@ -2,7 +2,11 @@
module QA
RSpec.describe 'Manage', :github, :requires_admin, product_group: :import_and_integrate do
describe 'GitHub import' do
describe 'GitHub import',
quarantine: {
type: :investigating,
issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/452419"
} do
include_context 'with github import'
context 'when imported via UI' do

View File

@ -0,0 +1,115 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Verify', :runner, :skip_live_env, product_group: :pipeline_authoring do
describe 'CI component' do
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
let(:tag) { '1.0.0' }
let(:domain_name) { Runtime::Scenario.gitlab_address.split("/").last }
let(:test_stage) { 'test' }
let(:test_phrase) { 'this is NOT secret!!!!!!!' }
let(:component_project) do
create(:project, :with_readme, name: 'component-project', description: 'This is a project with CI component.')
end
let(:test_project) do
create(:project, :with_readme, name: 'project-to-test-component')
end
let!(:runner) do
Resource::ProjectRunner.fabricate! do |runner|
runner.project = test_project
runner.name = executor
runner.tags = [executor]
end
end
let(:component_content) do
<<~YAML
spec:
inputs:
secret-phrase:
default: 'this is secret'
stage:
default: "#{test_stage}"
---
my-component:
script: echo $[[ inputs.secret-phrase ]]
YAML
end
let(:ci_yml_content) do
<<~YAML
default:
tags: ["#{executor}"]
include:
- component: "#{domain_name}/#{component_project.full_path}/new-component@#{tag}"
inputs:
secret-phrase: #{test_phrase}
cat:
stage: deploy
script: echo 'Meow'
YAML
end
let(:pipeline) do
create(:pipeline, project: test_project, id: test_project.latest_pipeline[:id])
end
before do
Flow::Login.sign_in
enable_catalog_resource_feature
add_ci_file(component_project, 'templates/new-component.yml', component_content)
component_project.create_release(tag)
test_project.visit!
add_ci_file(test_project, '.gitlab-ci.yml', ci_yml_content)
end
after do
runner.remove_via_api!
end
it 'runs in project pipeline with correct inputs', :aggregate_failures,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/451582' do
Flow::Pipeline.visit_latest_pipeline(status: 'Passed')
Page::Project::Pipeline::Show.perform do |show|
expect(show).to have_stage(test_stage), "Expected pipeline to have stage #{test_stage} but not found."
end
Flow::Pipeline.visit_pipeline_job_page(job_name: 'my-component', pipeline: pipeline)
Page::Project::Job::Show.perform do |show|
expect(show.output).to have_content(test_phrase),
"Component job failed to use custom phrase #{test_phrase}."
end
end
private
def enable_catalog_resource_feature
component_project.visit!
Page::Project::Menu.perform(&:go_to_general_settings)
Page::Project::Settings::Main.perform do |settings|
settings.expand_visibility_project_features_permissions(&:enable_ci_cd_catalog_resource)
end
end
def add_ci_file(project, file_path, content)
create(:commit, project: project, commit_message: 'Add CI yml file', actions: [
{
action: 'create',
file_path: file_path,
content: content
}
])
end
end
end
end

View File

@ -30,6 +30,7 @@ module QA
security_configuration_history_link
skipped_job_in_group
snippet_description
stage
system_note
tag
variable

View File

@ -100,23 +100,6 @@ RSpec.describe JiraConnect::AppDescriptorController, feature_category: :integrat
)
)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(atlassian_new_app_based_auth_model: false)
end
it 'returns JSON app descriptior with createBranch action' do
get :show
expect(response).to have_gitlab_http_status(:ok)
expect(descriptor[:modules][:jiraDevelopmentTool][:actions]).to include(
createBranch: {
templateUrl: 'http://test.host/-/jira_connect/branches/new?issue_key={issue.key}&issue_summary={issue.summary}'
}
)
end
end
end
end
end

View File

@ -732,7 +732,7 @@ describe('buildClient', () => {
await client.fetchMetrics({
filters: { search: [{ value: 'foo' }, { value: 'bar' }, { value: ' ' }] },
});
expect(getQueryParam()).toBe('starts_with=foo+bar');
expect(getQueryParam()).toBe('search=foo+bar');
});
it('ignores empty search', async () => {
@ -769,7 +769,7 @@ describe('buildClient', () => {
filters: { search: [{ value: 'foo' }] },
limit: 50,
});
expect(getQueryParam()).toBe('starts_with=foo&limit=50');
expect(getQueryParam()).toBe('search=foo&limit=50');
});
it('does not add the search limit param if the search filter is missing', async () => {

View File

@ -90,34 +90,76 @@ describe('OrganizationsIndexApp', () => {
});
};
describe('when API call is loading', () => {
describe('`allowOrganizationCreation` is enabled', () => {
beforeEach(() => {
createComponent(jest.fn().mockReturnValue(new Promise(() => {})));
gon.features = { allowOrganizationCreation: true };
});
itRendersHeaderText();
itRendersNewOrganizationButton();
itDoesNotRenderErrorMessage();
describe('when API call is loading', () => {
beforeEach(() => {
createComponent(jest.fn().mockResolvedValue({}));
});
it('renders the organizations view with loading prop set to true', () => {
expect(findOrganizationsView().props('loading')).toBe(true);
itRendersHeaderText();
itRendersNewOrganizationButton();
itDoesNotRenderErrorMessage();
it('renders the organizations view with loading prop set to true', () => {
expect(findOrganizationsView().props('loading')).toBe(true);
});
});
describe('when API call is successful', () => {
beforeEach(async () => {
createComponent();
await waitForPromises();
});
itRendersHeaderText();
itRendersNewOrganizationButton();
itDoesNotRenderErrorMessage();
it('passes organizations to view component', () => {
expect(findOrganizationsView().props()).toMatchObject({
loading: false,
organizations,
});
});
});
});
describe('when API call is successful', () => {
beforeEach(async () => {
createComponent();
await waitForPromises();
describe('`allowOrganizationCreation` is disabled', () => {
beforeEach(() => {
gon.features = { allowOrganizationCreation: false };
});
itRendersHeaderText();
itRendersNewOrganizationButton();
itDoesNotRenderErrorMessage();
describe('when API call is loading', () => {
beforeEach(() => {
createComponent(jest.fn().mockResolvedValue({}));
});
it('passes organizations to view component', () => {
expect(findOrganizationsView().props()).toMatchObject({
loading: false,
organizations,
itRendersHeaderText();
itDoesNotRenderNewOrganizationButton();
itDoesNotRenderErrorMessage();
it('renders the organizations view with loading prop set to true', () => {
expect(findOrganizationsView().props('loading')).toBe(true);
});
});
describe('when API call is successful', () => {
beforeEach(() => {
createComponent();
return waitForPromises();
});
itRendersHeaderText();
itDoesNotRenderNewOrganizationButton();
itDoesNotRenderErrorMessage();
it('passes organizations to view component', () => {
expect(findOrganizationsView().props()).toMatchObject({
loading: false,
organizations,
});
});
});
});

View File

@ -28,10 +28,6 @@ RSpec.describe EnvironmentsHelper, feature_category: :environment_management do
'current_environment_name' => environment.name,
'documentation_path' => help_page_path('administration/monitoring/prometheus/index'),
'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index', anchor: 'add-a-new-dashboard-to-your-project'),
'empty_getting_started_svg_path' => match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
'empty_loading_svg_path' => match_asset_path('/assets/illustrations/monitoring/loading.svg'),
'empty_no_data_svg_path' => match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
'empty_unable_to_connect_svg_path' => match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
'default_branch' => 'master',
'project_path' => project_path(project),

View File

@ -789,53 +789,16 @@ RSpec.describe SearchHelper, feature_category: :global_search do
end
describe '#search_service' do
using RSpec::Parameterized::TableSyntax
subject { search_service }
let(:params) { { include_archived: true } }
before do
allow(self).to receive(:current_user).and_return(:the_current_user)
end
shared_context 'with inputs' do
where(:input, :expected) do
'0' | false
'1' | true
'yes' | true
'no' | false
'true' | true
'false' | false
true | true
false | false
end
end
it 'instantiates a new SearchService with current_user and params' do
expect(::SearchService).to receive(:new).with(:the_current_user, { include_archived: true })
describe 'for confidential' do
let(:params) { { confidential: input } }
include_context 'with inputs'
with_them do
it 'transforms param' do
expect(::SearchService).to receive(:new).with(:the_current_user, { confidential: expected })
subject
end
end
end
describe 'for include_archived' do
let(:params) { { include_archived: input } }
include_context 'with inputs'
with_them do
it 'transforms param' do
expect(::SearchService).to receive(:new).with(:the_current_user, { include_archived: expected })
subject
end
end
search_service
end
end

View File

@ -468,6 +468,32 @@ RSpec.describe ContainerRegistry::Client, feature_category: :container_registry
it_behaves_like 'handling registry info'
end
describe '#connected?' do
subject { client.connected? }
context 'with a valid connection' do
before do
stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
stub_registry_info
end
it 'returns true' do
expect(subject).to be true
end
end
context 'with an invalid connection' do
before do
stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
stub_registry_info(status: 500)
end
it 'returns false' do
expect(subject).to be false
end
end
end
def stub_upload(path, content, digest, status = 200)
stub_request(:post, "#{registry_api_url}/v2/#{path}/blobs/uploads/")
.with(headers: headers_with_accept_types)

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
subject { described_class.new(params, detect_abuse: detect_abuse) }
subject(:search_params) { described_class.new(params, detect_abuse: detect_abuse) }
let(:search) { 'search' }
let(:group_id) { 123 }
@ -18,13 +18,14 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
it 'uses AbuseDetection by default' do
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
described_class.new(params)
search_params
end
end
describe '#[]' do
it 'feels like regular params' do
expect(subject[:group_id]).to eq(params[:group_id])
expect(search_params[:group_id]).to eq(params[:group_id])
end
it 'has indifferent access' do
@ -34,7 +35,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
end
it 'also works on attr_reader attributes' do
expect(subject[:query_string]).to eq(subject.query_string)
expect(search_params[:query_string]).to eq(search_params.query_string)
end
end
@ -57,7 +58,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
end
it 'strips surrounding whitespace from query string' do
params = described_class.new({ search: ' ' + search + ' ' })
params = described_class.new({ search: " #{search} " })
expect(params.query_string).to eq(search)
end
end
@ -68,13 +69,13 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
it 'does NOT validate AbuseDetector' do
expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
subject.validate
search_params.validate
end
end
it 'validates AbuseDetector on validation' do
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
subject.validate
search_params.validate
end
context 'when query has too many terms' do
@ -96,13 +97,13 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
it 'does NOT validate AbuseDetector' do
expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
subject.valid?
search_params.valid?
end
end
it 'validates AbuseDetector on validation' do
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
subject.valid?
search_params.valid?
end
end
@ -110,7 +111,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
let(:abuse_detection) { instance_double(Gitlab::Search::AbuseDetection) }
before do
allow(subject).to receive(:abuse_detection).and_return abuse_detection
allow(search_params).to receive(:abuse_detection).and_return abuse_detection
allow(abuse_detection).to receive(:errors).and_return abuse_errors
end
@ -118,7 +119,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
let(:abuse_errors) { { foo: ['bar'] } }
it 'is considered abusive' do
expect(subject).to be_abusive
expect(search_params).to be_abusive
end
end
@ -127,20 +128,20 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
context 'and there are other validation errors' do
it 'is NOT considered abusive' do
allow(subject).to receive(:valid?) do
subject.errors.add :project_id, 'validation error unrelated to abuse'
allow(search_params).to receive(:valid?) do
search_params.errors.add :project_id, 'validation error unrelated to abuse'
false
end
expect(subject).not_to be_abusive
expect(search_params).not_to be_abusive
end
end
context 'and there are NO other validation errors' do
it 'is NOT considered abusive' do
allow(subject).to receive(:valid?).and_return(true)
allow(search_params).to receive(:valid?).and_return(true)
expect(subject).not_to be_abusive
expect(search_params).not_to be_abusive
end
end
end
@ -153,4 +154,57 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
expect(described_class.new({ search: 'foo bar' })).not_to be_email_lookup
end
end
describe 'converts boolean params' do
using RSpec::Parameterized::TableSyntax
shared_context 'with inputs' do
where(:input, :expected) do
'0' | false
'1' | true
'yes' | true
'no' | false
'true' | true
'false' | false
true | true
false | false
end
end
describe 'for confidential' do
let(:params) { { group_id: 123, search: search, confidential: input } }
include_context 'with inputs'
with_them do
it 'transforms param' do
expect(search_params[:confidential]).to eq(expected)
end
end
end
describe 'for include_archived' do
let(:params) { { group_id: 123, search: search, include_archived: input } }
include_context 'with inputs'
with_them do
it 'transforms param' do
expect(search_params[:include_archived]).to eq(expected)
end
end
end
describe 'for include_forked' do
let(:params) { { group_id: 123, search: search, include_forked: input } }
include_context 'with inputs'
with_them do
it 'transforms param' do
expect(search_params[:include_forked]).to eq(expected)
end
end
end
end
end

View File

@ -7038,6 +7038,18 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
describe '.not_a_fork' do
let_it_be(:project) { create(:project, :public) }
subject(:not_a_fork) { described_class.not_a_fork }
it 'returns projects which are not forks' do
fork_project(project)
expect(not_a_fork).to contain_exactly(project)
end
end
describe '.deployments' do
subject { project.deployments }

View File

@ -124,11 +124,6 @@ RSpec.describe Clusters::ClusterPresenter do
'dashboard-endpoint': clusterable_presenter.metrics_dashboard_path(cluster),
'documentation-path': help_page_path('user/infrastructure/clusters/manage/clusters_health'),
'add-dashboard-documentation-path': help_page_path('operations/metrics/dashboards/index', anchor: 'add-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': match_asset_path('/assets/illustrations/monitoring/loading.svg'),
'empty-no-data-svg-path': match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
'empty-no-data-small-svg-path': match_asset_path('illustrations/chart-empty-state-small.svg'),
'empty-unable-to-connect-svg-path': match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
'settings-path': '',
'project-path': '',
'tags-path': ''

View File

@ -65,17 +65,6 @@ RSpec.describe JiraConnect::RepositoriesController, feature_category: :integrati
expect(json_response).to include('containers' => [expected_response])
end
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(atlassian_new_app_based_auth_model: false)
get '/-/jira_connect/repositories/search', params: { jwt: jwt, searchQuery: search_query }
end
it 'returns 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
@ -115,17 +104,6 @@ RSpec.describe JiraConnect::RepositoriesController, feature_category: :integrati
expect(json_response).to include(expected_response)
end
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(atlassian_new_app_based_auth_model: false)
post '/-/jira_connect/repositories/associate', params: { jwt: jwt, id: id }
end
it 'returns 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
end

View File

@ -60,17 +60,6 @@ RSpec.describe JiraConnect::WorkspacesController, feature_category: :integration
expect(json_response).to include(expected_response)
end
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(atlassian_new_app_based_auth_model: false)
get '/-/jira_connect/workspaces/search', params: { jwt: jwt, searchQuery: search_query }
end
it 'returns 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
end

View File

@ -65,5 +65,18 @@ RSpec.describe Organizations::CreateService, feature_category: :cell do
end
end
end
context 'when `allow_organization_creation` FF is disabled' do
before do
stub_feature_flags(allow_organization_creation: false)
end
it 'returns an error' do
expect(response).to be_error
expect(response.message)
.to match_array(['Feature flag `allow_organization_creation` is not enabled for this user.'])
end
end
end
end