Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
59bd8a4403
commit
2bc1877c51
|
@ -315,13 +315,13 @@ async function fetchMetrics(metricsUrl, { filters = {}, limit } = {}) {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
if (Array.isArray(filters.search)) {
|
if (Array.isArray(filters.search)) {
|
||||||
const searchPrefix = filters.search
|
const search = filters.search
|
||||||
.map((f) => f.value)
|
.map((f) => f.value)
|
||||||
.join(' ')
|
.join(' ')
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
if (searchPrefix) {
|
if (search) {
|
||||||
params.append('starts_with', searchPrefix);
|
params.append('search', search);
|
||||||
if (limit) {
|
if (limit) {
|
||||||
params.append('limit', limit);
|
params.append('limit', limit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@ export default {
|
||||||
showHeader() {
|
showHeader() {
|
||||||
return this.loading || this.organizations.nodes?.length;
|
return this.loading || this.organizations.nodes?.length;
|
||||||
},
|
},
|
||||||
|
showNewOrganizationButton() {
|
||||||
|
return gon.features?.allowOrganizationCreation;
|
||||||
|
},
|
||||||
loading() {
|
loading() {
|
||||||
return this.$apollo.queries.organizations.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">
|
<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>
|
<h1 class="gl-my-4 gl-font-size-h-display">{{ $options.i18n.organizations }}</h1>
|
||||||
<div class="gl-ml-auto">
|
<div class="gl-ml-auto">
|
||||||
<gl-button :href="newOrganizationUrl" variant="confirm">{{
|
<gl-button v-if="showNewOrganizationButton" :href="newOrganizationUrl" variant="confirm">{{
|
||||||
$options.i18n.newOrganization
|
$options.i18n.newOrganization
|
||||||
}}</gl-button>
|
}}</gl-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -131,15 +131,10 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def actions
|
def actions
|
||||||
actions = {
|
{
|
||||||
createBranch: {
|
createBranch: {
|
||||||
templateUrl: "#{new_jira_connect_branch_url}?issue_key={issue.key}&issue_summary={issue.summary}"
|
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: {
|
searchConnectedWorkspaces: {
|
||||||
templateUrl: search_jira_connect_workspaces_url
|
templateUrl: search_jira_connect_workspaces_url
|
||||||
},
|
},
|
||||||
|
@ -149,6 +144,6 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
|
||||||
associateRepository: {
|
associateRepository: {
|
||||||
templateUrl: associate_jira_connect_repositories_url
|
templateUrl: associate_jira_connect_repositories_url
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
module JiraConnect
|
module JiraConnect
|
||||||
class RepositoriesController < JiraConnect::ApplicationController
|
class RepositoriesController < JiraConnect::ApplicationController
|
||||||
before_action do
|
|
||||||
render_404 if Feature.disabled?(:atlassian_new_app_based_auth_model)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature_category :integrations
|
feature_category :integrations
|
||||||
|
|
||||||
def search
|
def search
|
||||||
|
|
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
module JiraConnect
|
module JiraConnect
|
||||||
class WorkspacesController < JiraConnect::ApplicationController
|
class WorkspacesController < JiraConnect::ApplicationController
|
||||||
before_action do
|
|
||||||
render_404 if Feature.disabled?(:atlassian_new_app_based_auth_model)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature_category :integrations
|
feature_category :integrations
|
||||||
|
|
||||||
def search
|
def search
|
||||||
|
|
|
@ -11,6 +11,9 @@ module Organizations
|
||||||
|
|
||||||
before_action :event_filter, only: [:activity]
|
before_action :event_filter, only: [:activity]
|
||||||
before_action :authorize_read_organization!, only: [:activity, :show, :groups_and_projects]
|
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]
|
skip_before_action :authenticate_user!, only: [:activity, :show, :groups_and_projects]
|
||||||
|
|
||||||
|
|
|
@ -79,12 +79,7 @@ module EnvironmentsHelper
|
||||||
def static_metrics_data
|
def static_metrics_data
|
||||||
{
|
{
|
||||||
'documentation_path' => help_page_path('administration/monitoring/prometheus/index'),
|
'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'),
|
'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')
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -161,7 +161,7 @@ module SearchHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_service
|
def search_service
|
||||||
@search_service ||= ::SearchService.new(current_user, sanitized_search_params)
|
@search_service ||= ::SearchService.new(current_user, params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_sort_options
|
def search_sort_options
|
||||||
|
@ -588,20 +588,6 @@ module SearchHelper
|
||||||
issuable.target_branch unless issuable.target_branch == issuable.project.default_branch
|
issuable.target_branch unless issuable.target_branch == issuable.project.default_branch
|
||||||
end
|
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)
|
def wiki_blob_link(wiki_blob)
|
||||||
project_wiki_path(wiki_blob.project, wiki_blob.basename)
|
project_wiki_path(wiki_blob.project, wiki_blob.basename)
|
||||||
end
|
end
|
||||||
|
|
|
@ -815,6 +815,10 @@ class Project < ApplicationRecord
|
||||||
|
|
||||||
scope :in_organization, -> (organization) { where(organization: organization) }
|
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 }
|
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
|
||||||
|
|
||||||
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
|
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
|
||||||
|
|
|
@ -62,11 +62,6 @@ module Clusters
|
||||||
'dashboard-endpoint': clusterable.metrics_dashboard_path(cluster),
|
'dashboard-endpoint': clusterable.metrics_dashboard_path(cluster),
|
||||||
'documentation-path': help_page_path('user/infrastructure/clusters/manage/clusters_health'),
|
'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'),
|
'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': '',
|
'settings-path': '',
|
||||||
'project-path': '',
|
'project-path': '',
|
||||||
'tags-path': ''
|
'tags-path': ''
|
||||||
|
|
|
@ -4,6 +4,7 @@ module Organizations
|
||||||
class CreateService < ::Organizations::BaseService
|
class CreateService < ::Organizations::BaseService
|
||||||
def execute
|
def execute
|
||||||
return error_no_permissions unless can?(current_user, :create_organization)
|
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
|
add_organization_owner_attributes
|
||||||
organization = Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification
|
organization = Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification
|
||||||
|
@ -35,5 +36,10 @@ module Organizations
|
||||||
|
|
||||||
ServiceResponse.error(message: Array(message))
|
ServiceResponse.error(message: Array(message))
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: atlassian_new_app_based_auth_model
|
name: allow_organization_creation
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142316
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147930
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442334
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/452062
|
||||||
milestone: '16.10'
|
milestone: '16.11'
|
||||||
group: group::import and integrate
|
|
||||||
type: development
|
type: development
|
||||||
|
group: group::tenant scale
|
||||||
default_enabled: false
|
default_enabled: false
|
|
@ -7,4 +7,19 @@ feature_categories:
|
||||||
description: Represents a event type filter for audit event streaming
|
description: Represents a event type filter for audit event streaming
|
||||||
introduced_by_url:
|
introduced_by_url:
|
||||||
milestone: '15.6'
|
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
|
||||||
|
|
|
@ -7,4 +7,19 @@ feature_categories:
|
||||||
description: Represents a HTTP header sent with streaming audit events
|
description: Represents a HTTP header sent with streaming audit events
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88063
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88063
|
||||||
milestone: '15.1'
|
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
|
||||||
|
|
|
@ -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+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.
|
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
|
#### Emergency maintenance
|
||||||
|
|
||||||
|
|
|
@ -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:
|
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
|
- 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).
|
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
|
After their expiry, artifacts are deleted hourly by default (using a cron job), and are not
|
||||||
|
|
|
@ -1740,6 +1740,31 @@ For status, choose one:
|
||||||
|
|
||||||
Generally available features should not have a status.
|
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
|
##### Inline tier badges
|
||||||
|
|
||||||
Do not add tier badges inline with other text.
|
Do not add tier badges inline with other text.
|
||||||
|
|
|
@ -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 |
|
| 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/)) |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
||||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
# Free user limit
|
# Free user limit
|
||||||
|
|
||||||
DETAILS:
|
DETAILS:
|
||||||
**Tier:** Free, Premium, Ultimate
|
**Tier:** Free
|
||||||
**Offering:** GitLab.com
|
**Offering:** GitLab.com
|
||||||
|
|
||||||
A five-user limit applies to newly created top-level namespaces with
|
A five-user limit applies to newly created top-level namespaces with
|
||||||
|
|
|
@ -58,6 +58,10 @@ module ContainerRegistry
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def connected?
|
||||||
|
!registry_info.empty?
|
||||||
|
end
|
||||||
|
|
||||||
def repository_tags(name, page_size: DEFAULT_TAGS_PAGE_SIZE)
|
def repository_tags(name, page_size: DEFAULT_TAGS_PAGE_SIZE)
|
||||||
response = faraday.get("/v2/#{name}/tags/list") do |req|
|
response = faraday.get("/v2/#{name}/tags/list") do |req|
|
||||||
req.params['n'] = page_size
|
req.params['n'] = page_size
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Gitlab
|
||||||
alias_method :term, :query_string
|
alias_method :term, :query_string
|
||||||
|
|
||||||
def initialize(params, detect_abuse: true)
|
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])
|
@query_string = strip_surrounding_whitespace(@raw_params[:search] || @raw_params[:term])
|
||||||
@detect_abuse = detect_abuse
|
@detect_abuse = detect_abuse
|
||||||
@abuse_detection = AbuseDetection.new(self) if @detect_abuse
|
@abuse_detection = AbuseDetection.new(self) if @detect_abuse
|
||||||
|
@ -93,6 +93,24 @@ module Gitlab
|
||||||
def strip_surrounding_whitespace(obj)
|
def strip_surrounding_whitespace(obj)
|
||||||
obj.to_s.strip
|
obj.to_s.strip
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34635,7 +34635,7 @@ msgstr ""
|
||||||
msgid "ObservabilityMetrics|Search"
|
msgid "ObservabilityMetrics|Search"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "ObservabilityMetrics|Search metrics starting with..."
|
msgid "ObservabilityMetrics|Search metrics..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "ObservabilityMetrics|Select attributes"
|
msgid "ObservabilityMetrics|Select attributes"
|
||||||
|
@ -45826,6 +45826,9 @@ msgstr ""
|
||||||
msgid "SecurityOrchestration|Failed to load images."
|
msgid "SecurityOrchestration|Failed to load images."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "SecurityOrchestration|Fetching"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Fetching the scope information."
|
msgid "SecurityOrchestration|Fetching the scope information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -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
|
# 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
|
ARG GDK_BASE_TAG_PREFIX
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ module QA
|
||||||
|
|
||||||
view 'app/assets/javascripts/ci/pipeline_details/graph/components/stage_column_component.vue' do
|
view 'app/assets/javascripts/ci/pipeline_details/graph/components/stage_column_component.vue' do
|
||||||
element 'job-item-container', required: true
|
element 'job-item-container', required: true
|
||||||
|
element 'stage-column-title'
|
||||||
end
|
end
|
||||||
|
|
||||||
def running?(wait: 0)
|
def running?(wait: 0)
|
||||||
|
@ -134,6 +135,10 @@ module QA
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_stage?(name)
|
||||||
|
has_element?('stage-column-title', text: name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Manage', :github, :requires_admin, product_group: :import_and_integrate do
|
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'
|
include_context 'with github import'
|
||||||
|
|
||||||
context 'when imported via UI' do
|
context 'when imported via UI' do
|
||||||
|
|
|
@ -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
|
|
@ -30,6 +30,7 @@ module QA
|
||||||
security_configuration_history_link
|
security_configuration_history_link
|
||||||
skipped_job_in_group
|
skipped_job_in_group
|
||||||
snippet_description
|
snippet_description
|
||||||
|
stage
|
||||||
system_note
|
system_note
|
||||||
tag
|
tag
|
||||||
variable
|
variable
|
||||||
|
|
|
@ -100,23 +100,6 @@ RSpec.describe JiraConnect::AppDescriptorController, feature_category: :integrat
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -732,7 +732,7 @@ describe('buildClient', () => {
|
||||||
await client.fetchMetrics({
|
await client.fetchMetrics({
|
||||||
filters: { search: [{ value: 'foo' }, { value: 'bar' }, { value: ' ' }] },
|
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 () => {
|
it('ignores empty search', async () => {
|
||||||
|
@ -769,7 +769,7 @@ describe('buildClient', () => {
|
||||||
filters: { search: [{ value: 'foo' }] },
|
filters: { search: [{ value: 'foo' }] },
|
||||||
limit: 50,
|
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 () => {
|
it('does not add the search limit param if the search filter is missing', async () => {
|
||||||
|
|
|
@ -90,9 +90,14 @@ describe('OrganizationsIndexApp', () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
describe('`allowOrganizationCreation` is enabled', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
gon.features = { allowOrganizationCreation: true };
|
||||||
|
});
|
||||||
|
|
||||||
describe('when API call is loading', () => {
|
describe('when API call is loading', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent(jest.fn().mockReturnValue(new Promise(() => {})));
|
createComponent(jest.fn().mockResolvedValue({}));
|
||||||
});
|
});
|
||||||
|
|
||||||
itRendersHeaderText();
|
itRendersHeaderText();
|
||||||
|
@ -103,7 +108,6 @@ describe('OrganizationsIndexApp', () => {
|
||||||
expect(findOrganizationsView().props('loading')).toBe(true);
|
expect(findOrganizationsView().props('loading')).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when API call is successful', () => {
|
describe('when API call is successful', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
createComponent();
|
createComponent();
|
||||||
|
@ -121,6 +125,44 @@ describe('OrganizationsIndexApp', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('`allowOrganizationCreation` is disabled', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
gon.features = { allowOrganizationCreation: false };
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when API call is loading', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent(jest.fn().mockResolvedValue({}));
|
||||||
|
});
|
||||||
|
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('when API call is successful and returns no organizations', () => {
|
describe('when API call is successful and returns no organizations', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|
|
@ -28,10 +28,6 @@ RSpec.describe EnvironmentsHelper, feature_category: :environment_management do
|
||||||
'current_environment_name' => environment.name,
|
'current_environment_name' => environment.name,
|
||||||
'documentation_path' => help_page_path('administration/monitoring/prometheus/index'),
|
'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'),
|
'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),
|
'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
|
||||||
'default_branch' => 'master',
|
'default_branch' => 'master',
|
||||||
'project_path' => project_path(project),
|
'project_path' => project_path(project),
|
||||||
|
|
|
@ -789,53 +789,16 @@ RSpec.describe SearchHelper, feature_category: :global_search do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#search_service' do
|
describe '#search_service' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
let(:params) { { include_archived: true } }
|
||||||
|
|
||||||
subject { search_service }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(self).to receive(:current_user).and_return(:the_current_user)
|
allow(self).to receive(:current_user).and_return(:the_current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_context 'with inputs' do
|
it 'instantiates a new SearchService with current_user and params' do
|
||||||
where(:input, :expected) do
|
expect(::SearchService).to receive(:new).with(:the_current_user, { include_archived: true })
|
||||||
'0' | false
|
|
||||||
'1' | true
|
|
||||||
'yes' | true
|
|
||||||
'no' | false
|
|
||||||
'true' | true
|
|
||||||
'false' | false
|
|
||||||
true | true
|
|
||||||
false | false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'for confidential' do
|
search_service
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -468,6 +468,32 @@ RSpec.describe ContainerRegistry::Client, feature_category: :container_registry
|
||||||
it_behaves_like 'handling registry info'
|
it_behaves_like 'handling registry info'
|
||||||
end
|
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)
|
def stub_upload(path, content, digest, status = 200)
|
||||||
stub_request(:post, "#{registry_api_url}/v2/#{path}/blobs/uploads/")
|
stub_request(:post, "#{registry_api_url}/v2/#{path}/blobs/uploads/")
|
||||||
.with(headers: headers_with_accept_types)
|
.with(headers: headers_with_accept_types)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
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(:search) { 'search' }
|
||||||
let(:group_id) { 123 }
|
let(:group_id) { 123 }
|
||||||
|
@ -18,13 +18,14 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
|
|
||||||
it 'uses AbuseDetection by default' do
|
it 'uses AbuseDetection by default' do
|
||||||
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
|
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
|
||||||
described_class.new(params)
|
|
||||||
|
search_params
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#[]' do
|
describe '#[]' do
|
||||||
it 'feels like regular params' 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
|
end
|
||||||
|
|
||||||
it 'has indifferent access' do
|
it 'has indifferent access' do
|
||||||
|
@ -34,7 +35,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'also works on attr_reader attributes' do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'strips surrounding whitespace from query string' do
|
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)
|
expect(params.query_string).to eq(search)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -68,13 +69,13 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
|
|
||||||
it 'does NOT validate AbuseDetector' do
|
it 'does NOT validate AbuseDetector' do
|
||||||
expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
|
expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
|
||||||
subject.validate
|
search_params.validate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'validates AbuseDetector on validation' do
|
it 'validates AbuseDetector on validation' do
|
||||||
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
|
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
|
||||||
subject.validate
|
search_params.validate
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when query has too many terms' do
|
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
|
it 'does NOT validate AbuseDetector' do
|
||||||
expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
|
expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
|
||||||
subject.valid?
|
search_params.valid?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'validates AbuseDetector on validation' do
|
it 'validates AbuseDetector on validation' do
|
||||||
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
|
expect(Gitlab::Search::AbuseDetection).to receive(:new).at_least(:once).and_call_original
|
||||||
subject.valid?
|
search_params.valid?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
let(:abuse_detection) { instance_double(Gitlab::Search::AbuseDetection) }
|
let(:abuse_detection) { instance_double(Gitlab::Search::AbuseDetection) }
|
||||||
|
|
||||||
before do
|
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
|
allow(abuse_detection).to receive(:errors).and_return abuse_errors
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
let(:abuse_errors) { { foo: ['bar'] } }
|
let(:abuse_errors) { { foo: ['bar'] } }
|
||||||
|
|
||||||
it 'is considered abusive' do
|
it 'is considered abusive' do
|
||||||
expect(subject).to be_abusive
|
expect(search_params).to be_abusive
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -127,20 +128,20 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
||||||
|
|
||||||
context 'and there are other validation errors' do
|
context 'and there are other validation errors' do
|
||||||
it 'is NOT considered abusive' do
|
it 'is NOT considered abusive' do
|
||||||
allow(subject).to receive(:valid?) do
|
allow(search_params).to receive(:valid?) do
|
||||||
subject.errors.add :project_id, 'validation error unrelated to abuse'
|
search_params.errors.add :project_id, 'validation error unrelated to abuse'
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(subject).not_to be_abusive
|
expect(search_params).not_to be_abusive
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'and there are NO other validation errors' do
|
context 'and there are NO other validation errors' do
|
||||||
it 'is NOT considered abusive' 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
|
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
|
expect(described_class.new({ search: 'foo bar' })).not_to be_email_lookup
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -7038,6 +7038,18 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
||||||
end
|
end
|
||||||
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
|
describe '.deployments' do
|
||||||
subject { project.deployments }
|
subject { project.deployments }
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,6 @@ RSpec.describe Clusters::ClusterPresenter do
|
||||||
'dashboard-endpoint': clusterable_presenter.metrics_dashboard_path(cluster),
|
'dashboard-endpoint': clusterable_presenter.metrics_dashboard_path(cluster),
|
||||||
'documentation-path': help_page_path('user/infrastructure/clusters/manage/clusters_health'),
|
'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'),
|
'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': '',
|
'settings-path': '',
|
||||||
'project-path': '',
|
'project-path': '',
|
||||||
'tags-path': ''
|
'tags-path': ''
|
||||||
|
|
|
@ -65,17 +65,6 @@ RSpec.describe JiraConnect::RepositoriesController, feature_category: :integrati
|
||||||
expect(json_response).to include('containers' => [expected_response])
|
expect(json_response).to include('containers' => [expected_response])
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -115,17 +104,6 @@ RSpec.describe JiraConnect::RepositoriesController, feature_category: :integrati
|
||||||
expect(json_response).to include(expected_response)
|
expect(json_response).to include(expected_response)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,17 +60,6 @@ RSpec.describe JiraConnect::WorkspacesController, feature_category: :integration
|
||||||
expect(json_response).to include(expected_response)
|
expect(json_response).to include(expected_response)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -65,5 +65,18 @@ RSpec.describe Organizations::CreateService, feature_category: :cell do
|
||||||
end
|
end
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue