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(); 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);
} }

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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': ''

View File

@ -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

View File

@ -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

View File

@ -1,10 +1,25 @@
--- ---
table_name: audit_events_streaming_event_type_filters table_name: audit_events_streaming_event_type_filters
classes: classes:
- AuditEvents::Streaming::EventTypeFilter - AuditEvents::Streaming::EventTypeFilter
feature_categories: feature_categories:
- audit_events - audit_events
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

View File

@ -1,10 +1,25 @@
--- ---
table_name: audit_events_streaming_headers table_name: audit_events_streaming_headers
classes: classes:
- AuditEvents::Streaming::Header - AuditEvents::Streaming::Header
feature_categories: feature_categories:
- audit_events - audit_events
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

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+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

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: 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

View File

@ -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.

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 | | 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 |

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ""

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 # 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

View File

@ -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

View File

@ -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

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 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

View File

@ -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

View File

@ -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 () => {

View File

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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 }

View File

@ -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': ''

View File

@ -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

View File

@ -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

View File

@ -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