Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-08-25 03:10:50 +00:00
parent 06528399ad
commit c9c77a8466
34 changed files with 458 additions and 356 deletions

View File

@ -98,6 +98,7 @@ export default {
:loading="loading"
:icon="buttonIcon"
:disabled="isDeleting || !hasSelectedDesigns"
/>
><slot></slot
></gl-button>
</div>
</template>

View File

@ -42,6 +42,7 @@ export default {
v-if="adminState !== null"
:inherit-from-id="adminState.id"
:override="override"
:learn-more-path="propsSource.learnMorePath"
@change="setOverride"
/>
<active-checkbox v-if="propsSource.showActive" :key="`${currentKey}-active-checkbox`" />

View File

@ -1,5 +1,5 @@
<script>
import { GlNewDropdown, GlNewDropdownItem } from '@gitlab/ui';
import { GlNewDropdown, GlNewDropdownItem, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
const dropdownOptions = [
@ -19,12 +19,18 @@ export default {
components: {
GlNewDropdown,
GlNewDropdownItem,
GlLink,
},
props: {
inheritFromId: {
type: Number,
required: true,
},
learnMorePath: {
type: String,
required: false,
default: null,
},
override: {
type: Boolean,
required: true,
@ -48,7 +54,12 @@ export default {
<div
class="gl-display-flex gl-justify-content-space-between gl-align-items-baseline gl-py-4 gl-mt-5 gl-mb-6 gl-border-t-1 gl-border-t-solid gl-border-b-1 gl-border-b-solid gl-border-gray-100"
>
<span>{{ s__('Integrations|Default settings are inherited from the instance level.') }}</span>
<span
>{{ s__('Integrations|Default settings are inherited from the instance level.') }}
<gl-link v-if="learnMorePath" :href="learnMorePath" target="_blank">{{
__('Learn more')
}}</gl-link>
</span>
<input name="service[inherit_from_id]" :value="override ? '' : inheritFromId" type="hidden" />
<gl-new-dropdown :text="selected.text">
<gl-new-dropdown-item

View File

@ -19,6 +19,7 @@ function parseDatasetToProps(data) {
projectKey,
upgradePlanPath,
editProjectPath,
learnMorePath,
triggerEvents,
fields,
inheritFromId,
@ -51,6 +52,7 @@ function parseDatasetToProps(data) {
upgradePlanPath,
editProjectPath,
},
learnMorePath,
triggerEvents: JSON.parse(triggerEvents),
fields: JSON.parse(fields),
inheritFromId: parseInt(inheritFromId, 10),

View File

@ -92,6 +92,7 @@ module ServicesHelper
commit_events: integration.commit_events.to_s,
enable_comments: integration.comment_on_event_enabled.to_s,
comment_detail: integration.comment_detail,
learn_more_path: integrations_help_page_path,
trigger_events: trigger_events_for_service(integration),
fields: fields_for_service(integration),
inherit_from_id: integration.inherit_from_id
@ -106,10 +107,18 @@ module ServicesHelper
ServiceFieldSerializer.new(service: integration).represent(integration.global_fields).to_json
end
def integrations_help_page_path
help_page_path('user/admin_area/settings/project_integration_management')
end
def project_jira_issues_integration?
false
end
def group_level_integrations?
@group.present? && Feature.enabled?(:group_level_integrations, @group)
end
extend self
end

View File

@ -8,8 +8,8 @@ module Packages
attr_reader :params
def initialize(recipe, user, project, params = {})
@recipe = recipe
def initialize(package, user, project, params = {})
@package = package
@user = user
@project = project
@params = params
@ -48,10 +48,10 @@ module Packages
def build_recipe_file_url(package_file)
expose_url(
api_v4_packages_conan_v1_files_export_path(
package_name: package.name,
package_version: package.version,
package_username: package.conan_metadatum.package_username,
package_channel: package.conan_metadatum.package_channel,
package_name: @package.name,
package_version: @package.version,
package_username: @package.conan_metadatum.package_username,
package_channel: @package.conan_metadatum.package_channel,
recipe_revision: package_file.conan_file_metadatum.recipe_revision,
file_name: package_file.file_name
)
@ -61,10 +61,10 @@ module Packages
def build_package_file_url(package_file)
expose_url(
api_v4_packages_conan_v1_files_package_path(
package_name: package.name,
package_version: package.version,
package_username: package.conan_metadatum.package_username,
package_channel: package.conan_metadatum.package_channel,
package_name: @package.name,
package_version: @package.version,
package_username: @package.conan_metadatum.package_username,
package_channel: @package.conan_metadatum.package_channel,
recipe_revision: package_file.conan_file_metadatum.recipe_revision,
conan_package_reference: package_file.conan_file_metadatum.conan_package_reference,
package_revision: package_file.conan_file_metadatum.package_revision,
@ -84,22 +84,9 @@ module Packages
end
def package_files
return unless package
return unless @package
@package_files ||= package.package_files.preload_conan_file_metadata
end
def package
strong_memoize(:package) do
name, version = @recipe.split('@')[0].split('/')
@project.packages
.conan
.with_name(name)
.with_version(version)
.order_created
.last
end
@package_files ||= @package.package_files.preload_conan_file_metadata
end
def matching_reference?(package_file)

View File

@ -16,5 +16,5 @@
%h4= s_('AdminSettings|Apply integration settings to all Projects')
%p
= s_('AdminSettings|Integrations configured here will automatically apply to all projects on this instance.')
= link_to _('Learn more'), '#'
= link_to _('Learn more'), integrations_help_page_path, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/integrations/index', integrations: @integrations

View File

@ -5,5 +5,5 @@
%h4= s_('GroupSettings|Apply integration settings to all Projects')
%p
= s_('GroupSettings|Integrations configured here will automatically apply to all projects in this group.')
= link_to _('Learn more'), '#'
= link_to _('Learn more'), integrations_help_page_path, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/integrations/index', integrations: @integrations

View File

@ -157,6 +157,12 @@
%span
= _('General')
- if group_level_integrations?
= nav_link(controller: :integrations) do
= link_to group_settings_integrations_path(@group), title: _('Integrations') do
%span
= _('Integrations')
= nav_link(path: 'groups#projects') do
= link_to projects_group_path(@group), title: _('Projects') do
%span
@ -171,11 +177,6 @@
= link_to group_settings_ci_cd_path(@group), title: _('CI / CD') do
%span
= _('CI / CD')
- if Feature.enabled?(:group_level_integrations, @group)
= nav_link(controller: :integrations) do
= link_to group_settings_integrations_path(@group), title: _('Integrations') do
%span
= _('Integrations')
= render_if_exists "groups/ee/settings_nav"

View File

@ -12,4 +12,4 @@
- if integration.editable?
.footer-block.row-content-block
= service_save_button
= link_to _('Cancel'), scoped_integration_path(integration), class: 'btn btn-cancel'
= link_to _('Cancel'), scoped_integrations_path, class: 'btn btn-cancel'

View File

@ -0,0 +1,6 @@
---
title: Fix bug where conan does not properly check package channel when returning
file download urls
merge_request: 40029
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix design management Archive Selected button label
merge_request: 40325
author:
type: fixed

View File

@ -0,0 +1,41 @@
---
- title: Assign Issues to Iterations
body: Prior to this release, there was no way to associate an issue with more than one timebox in GitLab. This has been particularly problematic for teams that follow Scrum or XP. Such teams often need to associate issues with iterations/sprints, while also rolling that issue up to longer-running milestones, such as program increments. Instead of having to decide whether to use milestones for sprints or program increments and track the other in a spreadsheet, you can now assign issues to iterations, milestones, or both.
stage: Plan
self-managed: true
gitlab-com: true
packages: starter, premium, ultimate
url: https://www.youtube.com/watch?v=31pNKjenlJY&feature=emb_title
image_url: http://i3.ytimg.com/vi/31pNKjenlJY/maxresdefault.jpg
published_at: 2020-07-22
release: 13.2
- title: Container Host Monitoring and Blocking
body: Were pleased to announce the first release of Container Host Security. This initial feature, container host monitoring and blocking, allows security administrators to secure their running containers at the host level by monitoring and optionally blocking unexpected activity. Such activity includes process starts, file changes, or opened network ports. This feature uses Falco to provide the monitoring functionality and AppArmor and Pod Security Policies for the blocking functionality.
stage: Defend
self-managed: true
gitlab-com: true
packages: All
url: https://www.youtube.com/watch?v=WxBzBz76FxU&feature=youtu.be
image_url: http://i3.ytimg.com/vi/WxBzBz76FxU/hqdefault.jpg
published_at: 2020-07-22
release: 13.2
- title: Official GitLab-Figma Plugin
body: Recently, the GitLab product design team and our open source Pajamas Design System switched over to Figma. We decided to build a new Figma plugin, which allows for easy uploads from Figma to issues on GitLab.com. This makes it quick and easy to collaborate on Designs. Connect your design environment with your source code management in a seamless workflow.
stage: Create
self-managed: false
gitlab-com: true
packages: All
url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#gitlab-figma-plugin
image_url: https://about.gitlab.com/images/13_2/figma-plugin.png
published_at: 2020-07-22
release: 13.2
- title: Cluster health monitoring now available in Core
body: To understand system performance, your development team must monitor the health and performance of the underlying infrastructure. We want our metrics solution to be available to all GitLab users, so as part of our 2020 gift, weve moved cluster health in the Monitor stage from GitLab Ultimate to GitLab Core. Beginning with GitLab 13.2, all users can connect a cluster and monitor its health in the GitLab user interface.
stage: Monitor
self-managed: true
gitlab-com: true
packages: All
url: https://docs.gitlab.com/ee/user/project/clusters/#visualizing-cluster-health
image_url: https://about.gitlab.com/images/13_2/k8s_cluster_monitoring.png
published_at: 2020-07-22
release: 13.2

View File

@ -113,7 +113,7 @@ module API
authorize!(:read_package, project)
presenter = ::Packages::Conan::PackagePresenter.new(
recipe,
package,
current_user,
project,
conan_package_reference: params[:conan_package_reference]
@ -131,7 +131,7 @@ module API
get do
authorize!(:read_package, project)
presenter = ::Packages::Conan::PackagePresenter.new(recipe, current_user, project)
presenter = ::Packages::Conan::PackagePresenter.new(package, current_user, project)
present presenter, with: ::API::Entities::ConanPackage::ConanRecipeSnapshot
end

View File

@ -9,7 +9,7 @@ module API
authorize!(:read_package, project)
presenter = ::Packages::Conan::PackagePresenter.new(
recipe,
package,
current_user,
project,
conan_package_reference: params[:conan_package_reference]
@ -94,6 +94,7 @@ module API
def package
strong_memoize(:package) do
project.packages
.conan
.with_name(params[:package_name])
.with_version(params[:package_version])
.with_conan_channel(params[:package_channel])

View File

@ -109,10 +109,6 @@ module QA
autoload :WikiPush, 'qa/resource/repository/wiki_push'
end
module Settings
autoload :HashedStorage, 'qa/resource/settings/hashed_storage'
end
module Wiki
autoload :ProjectPage, 'qa/resource/wiki/project_page'
end
@ -419,7 +415,6 @@ module QA
autoload :NewSession, 'qa/page/admin/new_session'
module Settings
autoload :Repository, 'qa/page/admin/settings/repository'
autoload :General, 'qa/page/admin/settings/general'
autoload :MetricsAndProfiling, 'qa/page/admin/settings/metrics_and_profiling'
autoload :Network, 'qa/page/admin/settings/network'
@ -427,7 +422,6 @@ module QA
module Component
autoload :IpLimits, 'qa/page/admin/settings/component/ip_limits'
autoload :OutboundRequests, 'qa/page/admin/settings/component/outbound_requests'
autoload :RepositoryStorage, 'qa/page/admin/settings/component/repository_storage'
autoload :AccountAndLimit, 'qa/page/admin/settings/component/account_and_limit'
autoload :PerformanceBar, 'qa/page/admin/settings/component/performance_bar'
end

View File

@ -1,26 +0,0 @@
# frozen_string_literal: true
module QA
module Page
module Admin
module Settings
module Component
class RepositoryStorage < Page::Base
view 'app/views/admin/application_settings/_repository_storage.html.haml' do
element :hashed_storage_checkbox
element :save_changes_button
end
def enable_hashed_storage
check_element :hashed_storage_checkbox
end
def save_settings
click_element :save_changes_button
end
end
end
end
end
end
end

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
module QA
module Page
module Admin
module Settings
class Repository < Page::Base
include QA::Page::Settings::Common
view 'app/views/admin/application_settings/repository.html.haml' do
element :repository_storage_settings_content
end
def expand_repository_storage(&block)
expand_content(:repository_storage_settings_content) do
Component::RepositoryStorage.perform(&block)
end
end
end
end
end
end
end

View File

@ -1,26 +0,0 @@
# frozen_string_literal: true
module QA
module Resource
module Settings
class HashedStorage < Base
def fabricate!(*traits)
raise ArgumentError unless traits.include?(:enabled)
Page::Main::Login.perform(&:sign_in_using_credentials)
Page::Main::Menu.perform(&:go_to_admin_area)
Page::Admin::Menu.perform(&:go_to_repository_settings)
Page::Admin::Settings::Repository.perform do |setting|
setting.expand_repository_storage do |page|
page.enable_hashed_storage
page.save_settings
end
end
QA::Page::Main::Menu.perform(&:sign_out)
end
end
end
end
end

View File

@ -59,7 +59,7 @@ module QA
end
context 'when deleted via API' do
it 'is not found' do
it 'is not found', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/931' do
delete(pipeline_data_request.url)
expect(JSON.parse(get(pipeline_data_request.url))['message'].downcase).to have_content('404 not found')
end

View File

@ -16,7 +16,7 @@ module QA
open_ci_cd_settings
end
it 'user adds a CI variable' do
it 'user adds a CI variable', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/395' do
Page::Project::Settings::CICD.perform do |settings|
settings.expand_ci_variables do |page|
expect(page).to have_text('VARIABLE_KEY')
@ -29,7 +29,7 @@ module QA
end
end
it 'user removes a CI variable' do
it 'user removes a CI variable', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/394' do
Page::Project::Settings::CICD.perform do |settings|
settings.expand_ci_variables do |page|
page.click_edit_ci_variable

View File

@ -24,7 +24,7 @@ module QA
runner.remove_via_api!
end
it 'users creates a pipeline which gets processed', :smoke do
it 'users creates a pipeline which gets processed', :smoke, status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/391' do
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|

View File

@ -15,7 +15,7 @@ module QA
runner.remove_via_api!
end
it 'user registers a new specific runner' do
it 'user registers a new specific runner', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/392' do
Flow::Login.sign_in
runner.project.visit!

View File

@ -33,7 +33,7 @@ module QA
runner.remove_via_api!
end
it 'creates an MR with code coverage statistics' do
it 'creates an MR with code coverage statistics', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/807' do
runner.project.visit!
configure_code_coverage(simplecov)
merge_request.visit!

View File

@ -1,202 +1,141 @@
# frozen_string_literal: true
require_relative 'cluster_with_prometheus.rb'
module QA
RSpec.describe 'Monitor' do
describe 'with Prometheus in a Gitlab-managed cluster', :orchestrated, :kubernetes, :requires_admin do
before :all do
@cluster = Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create!
@project = Resource::Project.fabricate_via_api! do |project|
project.name = 'monitoring-project'
project.auto_devops_enabled = true
project.template_name = 'express'
end
RSpec.describe 'Monitor', :orchestrated, :kubernetes, :requires_admin do
include_context "cluster with Prometheus installed"
deploy_project_with_prometheus
before do
Flow::Login.sign_in_unless_signed_in
@project.visit!
end
it 'configures custom metrics' do
verify_add_custom_metric
verify_edit_custom_metric
verify_delete_custom_metric
end
it 'duplicates to create dashboard to custom' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
on_dashboard.duplicate_dashboard
expect(on_dashboard).to have_metrics
expect(on_dashboard).to have_edit_dashboard_enabled
end
end
it 'verifies data on filtered deployed environment' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
on_dashboard.filter_environment
expect(on_dashboard).to have_metrics
end
end
it 'filters using the quick range' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
on_dashboard.show_last('30 minutes')
expect(on_dashboard).to have_metrics
on_dashboard.show_last('3 hours')
expect(on_dashboard).to have_metrics
on_dashboard.show_last('1 day')
expect(on_dashboard).to have_metrics
end
end
it 'observes cluster health graph' do
Page::Project::Menu.perform(&:go_to_operations_kubernetes)
Page::Project::Operations::Kubernetes::Index.perform do |cluster_list|
cluster_list.click_on_cluster(@cluster)
end
before do
Flow::Login.sign_in_unless_signed_in
@project.visit!
Page::Project::Operations::Kubernetes::Show.perform do |cluster_panel|
cluster_panel.open_health
cluster_panel.wait_for_cluster_health
end
end
it 'uses templating variables for metrics dashboards' do
templating_dashboard_yml = Pathname
.new(__dir__)
.join('../../../../fixtures/metrics_dashboards/templating.yml')
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = @project
push.file_name = '.gitlab/dashboards/templating.yml'
push.file_content = File.read(templating_dashboard_yml)
push.commit_message = 'Add templating in dashboard file'
push.new_branch = false
end
after :all do
@cluster.remove!
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |dashboard|
dashboard.select_dashboard('templating.yml')
expect(dashboard).to have_template_metric('CPU usage GitLab Runner')
expect(dashboard).to have_template_metric('Memory usage Postgresql')
expect(dashboard).to have_templating_variable('GitLab Runner')
expect(dashboard).to have_templating_variable('Postgresql')
end
end
private
def verify_add_custom_metric
Page::Project::Menu.perform(&:go_to_integrations_settings)
Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
metrics_panel.click_on_new_metric
metrics_panel.add_custom_metric
end
it 'configures custom metrics' do
verify_add_custom_metric
verify_edit_custom_metric
verify_delete_custom_metric
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).to have_custom_metric('HTTP Requests Total')
end
end
def verify_edit_custom_metric
Page::Project::Menu.perform(&:go_to_integrations_settings)
Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
metrics_panel.click_on_custom_metric('Business / HTTP Requests Total (req/sec)')
metrics_panel.edit_custom_metric
end
it 'duplicates to create dashboard to custom' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
on_dashboard.duplicate_dashboard
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).to have_custom_metric('Throughput')
end
end
expect(on_dashboard).to have_metrics
expect(on_dashboard).to have_edit_dashboard_enabled
end
def verify_delete_custom_metric
Page::Project::Menu.perform(&:go_to_integrations_settings)
Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
metrics_panel.click_on_custom_metric('Business / Throughput (req/sec)')
metrics_panel.delete_custom_metric
end
it 'verifies data on filtered deployed environment' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
on_dashboard.filter_environment
expect(on_dashboard).to have_metrics
end
end
it 'filters using the quick range' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
on_dashboard.show_last('30 minutes')
expect(on_dashboard).to have_metrics
on_dashboard.show_last('3 hours')
expect(on_dashboard).to have_metrics
on_dashboard.show_last('1 day')
expect(on_dashboard).to have_metrics
end
end
it 'observes cluster health graph' do
Page::Project::Menu.perform(&:go_to_operations_kubernetes)
Page::Project::Operations::Kubernetes::Index.perform do |cluster_list|
cluster_list.click_on_cluster(@cluster)
end
Page::Project::Operations::Kubernetes::Show.perform do |cluster_panel|
cluster_panel.open_health
cluster_panel.wait_for_cluster_health
end
end
it 'uses templating variables for metrics dashboards' do
templating_dashboard_yml = Pathname
.new(__dir__)
.join('../../../../fixtures/metrics_dashboards/templating.yml')
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = @project
push.file_name = '.gitlab/dashboards/templating.yml'
push.file_content = File.read(templating_dashboard_yml)
push.commit_message = 'Add templating in dashboard file'
push.new_branch = false
end
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |dashboard|
dashboard.select_dashboard('templating.yml')
expect(dashboard).to have_template_metric('CPU usage GitLab Runner')
expect(dashboard).to have_template_metric('Memory usage Postgresql')
expect(dashboard).to have_templating_variable('GitLab Runner')
expect(dashboard).to have_templating_variable('Postgresql')
end
end
private
def deploy_project_with_prometheus
%w[
CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED
SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
CONTAINER_SCANNING_DISABLED PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED
].each do |key|
Resource::CiVariable.fabricate_via_api! do |resource|
resource.project = @project
resource.key = key
resource.value = '1'
resource.masked = false
end
end
Flow::Login.sign_in
Resource::KubernetesCluster::ProjectCluster.fabricate! do |cluster_settings|
cluster_settings.project = @project
cluster_settings.cluster = @cluster
cluster_settings.install_runner = true
cluster_settings.install_ingress = true
cluster_settings.install_prometheus = true
end
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = @project
end.visit!
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('build')
end
Page::Project::Job::Show.perform do |job|
expect(job).to be_successful(timeout: 600)
job.click_element(:pipeline_path)
end
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('production')
end
Page::Project::Job::Show.perform do |job|
expect(job).to be_successful(timeout: 1200)
job.click_element(:pipeline_path)
end
end
def verify_add_custom_metric
Page::Project::Menu.perform(&:go_to_integrations_settings)
Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
metrics_panel.click_on_new_metric
metrics_panel.add_custom_metric
end
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).to have_custom_metric('HTTP Requests Total')
end
end
def verify_edit_custom_metric
Page::Project::Menu.perform(&:go_to_integrations_settings)
Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
metrics_panel.click_on_custom_metric('Business / HTTP Requests Total (req/sec)')
metrics_panel.edit_custom_metric
end
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).to have_custom_metric('Throughput')
end
end
def verify_delete_custom_metric
Page::Project::Menu.perform(&:go_to_integrations_settings)
Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
metrics_panel.click_on_custom_metric('Business / Throughput (req/sec)')
metrics_panel.delete_custom_metric
end
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).not_to have_custom_metric('Throughput')
end
Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).not_to have_custom_metric('Throughput')
end
end
end

View File

@ -0,0 +1,77 @@
# frozen_string_literal: true
module QA
RSpec.configure do |rspec|
# This config option will be enabled by default on RSpec 4,
# but for reasons of backwards compatibility, you have to
# set it on RSpec 3.
#
# It causes the host group and examples to inherit metadata
# from the shared context.
rspec.shared_context_metadata_behavior = :apply_to_host_groups
end
RSpec.shared_context "cluster with Prometheus installed", shared_context: :metadata do
before :all do
@cluster = Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create!
@project = Resource::Project.fabricate_via_api! do |project|
project.name = 'monitoring-project'
project.auto_devops_enabled = true
project.template_name = 'express'
end
deploy_project_with_prometheus
end
def deploy_project_with_prometheus
%w[
CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED
SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
CONTAINER_SCANNING_DISABLED PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED
].each do |key|
Resource::CiVariable.fabricate_via_api! do |resource|
resource.project = @project
resource.key = key
resource.value = '1'
resource.masked = false
end
end
Flow::Login.sign_in
Resource::KubernetesCluster::ProjectCluster.fabricate! do |cluster_settings|
cluster_settings.project = @project
cluster_settings.cluster = @cluster
cluster_settings.install_runner = true
cluster_settings.install_ingress = true
cluster_settings.install_prometheus = true
end
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = @project
end.visit!
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('build')
end
Page::Project::Job::Show.perform do |job|
expect(job).to be_successful(timeout: 600)
job.click_element(:pipeline_path)
end
Page::Project::Pipeline::Show.perform do |pipeline|
pipeline.click_job('production')
end
Page::Project::Job::Show.perform do |job|
expect(job).to be_successful(timeout: 1200)
job.click_element(:pipeline_path)
end
end
after :all do
@cluster.remove!
end
end
end

View File

@ -32,7 +32,7 @@ describe QA::Page::Validator do
let(:view) { spy('view') }
before do
allow(QA::Page::Admin::Settings::Repository)
allow(QA::Page::Admin::Settings::Network)
.to receive(:views).and_return([view])
end

View File

@ -8,7 +8,7 @@ describe('Batch delete button component', () => {
const findButton = () => wrapper.find(GlButton);
const findModal = () => wrapper.find(GlModal);
function createComponent(isDeleting = false) {
function createComponent({ isDeleting = false } = {}, { slots = {} } = {}) {
wrapper = shallowMount(BatchDeleteButton, {
propsData: {
isDeleting,
@ -16,6 +16,7 @@ describe('Batch delete button component', () => {
directives: {
GlModalDirective,
},
slots,
});
}
@ -31,7 +32,7 @@ describe('Batch delete button component', () => {
});
it('renders disabled button when design is deleting', () => {
createComponent(true);
createComponent({ isDeleting: true });
expect(findButton().attributes('disabled')).toBeTruthy();
});
@ -48,4 +49,18 @@ describe('Batch delete button component', () => {
expect(wrapper.emitted().deleteSelectedDesigns).toBeTruthy();
});
});
it('renders slot content', () => {
const testText = 'Archive selected';
createComponent(
{},
{
slots: {
default: testText,
},
},
);
expect(findButton().text()).toBe(testText);
});
});

View File

@ -0,0 +1,58 @@
import { shallowMount } from '@vue/test-utils';
import { GlNewDropdown, GlLink } from '@gitlab/ui';
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
describe('OverrideDropdown', () => {
let wrapper;
const defaultProps = {
inheritFromId: 1,
override: true,
};
const createComponent = (props = {}) => {
wrapper = shallowMount(OverrideDropdown, {
propsData: { ...defaultProps, ...props },
});
};
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
const findGlLink = () => wrapper.find(GlLink);
const findGlNewDropdown = () => wrapper.find(GlNewDropdown);
describe('template', () => {
describe('override prop is true', () => {
it('renders GlToggle as disabled', () => {
createComponent();
expect(findGlNewDropdown().props('text')).toBe('Use custom settings');
});
});
describe('override prop is false', () => {
it('renders GlToggle as disabled', () => {
createComponent({ override: false });
expect(findGlNewDropdown().props('text')).toBe('Use default settings');
});
});
describe('learnMorePath is present', () => {
it('renders GlLink with correct link', () => {
createComponent({
learnMorePath: '/docs',
});
expect(findGlLink().text()).toBe('Learn more');
expect(findGlLink().attributes('href')).toBe('/docs');
});
});
});
});

View File

@ -26,4 +26,36 @@ RSpec.describe ServicesHelper do
end
end
end
describe '#group_level_integrations?' do
subject { helper.group_level_integrations? }
context 'when no group is present' do
it { is_expected.to eq(false) }
end
context 'when group is present' do
let(:group) { build_stubbed(:group) }
before do
assign(:group, group)
end
context 'when `group_level_integrations` is not enabled' do
it 'returns false' do
stub_feature_flags(group_level_integrations: false)
is_expected.to eq(false)
end
end
context 'when `group_level_integrations` is enabled for the group' do
it 'returns true' do
stub_feature_flags(group_level_integrations: group)
is_expected.to eq(true)
end
end
end
end
end

View File

@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache do
let!(:project) { create(:project) }
let!(:milestone) { create(:milestone, project: project) }
let_it_be(:project) { create(:project) }
let_it_be(:milestone) { create(:milestone, project: project) }
let(:finder) { described_class.new(project) }
describe '#id_for' do

View File

@ -4,34 +4,20 @@ require 'spec_helper'
RSpec.describe ::Packages::Conan::PackagePresenter do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:package) { create(:conan_package) }
let_it_be(:project) { package.project }
let_it_be(:conan_package_reference) { '123456789'}
RSpec.shared_examples 'not selecting a package with the wrong type' do
context 'with a nuget package with same name and version' do
let_it_be(:wrong_package) { create(:nuget_package, name: 'wrong', version: '1.0.0', project: project) }
let(:recipe) { "#{wrong_package.name}/#{wrong_package.version}" }
it { is_expected.to be_empty }
end
end
describe '#recipe_urls' do
subject { described_class.new(recipe, user, project).recipe_urls }
subject { described_class.new(package, user, project).recipe_urls }
context 'no existing package' do
let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
let(:package) { nil }
it { is_expected.to be_empty }
end
it_behaves_like 'not selecting a package with the wrong type'
context 'existing package' do
let(:package) { create(:conan_package, project: project) }
let(:recipe) { package.conan_recipe }
let(:expected_result) do
{
"conanfile.py" => "#{Settings.build_base_gitlab_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
@ -40,24 +26,26 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
end
it { is_expected.to eq(expected_result) }
context 'when there are multiple channels for the same package' do
let(:conan_metadatum) { create(:conan_metadatum, package_channel: 'newest' ) }
let!(:newest_package) { create(:conan_package, name: package.name, version: package.version, project: project, conan_metadatum: conan_metadatum) }
it { is_expected.to eq(expected_result) }
end
end
end
describe '#recipe_snapshot' do
subject { described_class.new(recipe, user, project).recipe_snapshot }
subject { described_class.new(package, user, project).recipe_snapshot }
context 'no existing package' do
let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
let(:package) { nil }
it { is_expected.to be_empty }
end
it_behaves_like 'not selecting a package with the wrong type'
context 'existing package' do
let(:package) { create(:conan_package, project: project) }
let(:recipe) { package.conan_recipe }
let(:expected_result) do
{
"conanfile.py" => '12345abcde',
@ -74,22 +62,17 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
subject do
described_class.new(
recipe, user, project, conan_package_reference: reference
package, user, project, conan_package_reference: reference
).package_urls
end
context 'no existing package' do
let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
let(:package) { nil }
it { is_expected.to be_empty }
end
it_behaves_like 'not selecting a package with the wrong type'
context 'existing package' do
let(:package) { create(:conan_package, project: project) }
let(:recipe) { package.conan_recipe }
let(:expected_result) do
{
"conaninfo.txt" => "#{Settings.build_base_gitlab_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/#{conan_package_reference}/0/conaninfo.txt",
@ -131,7 +114,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
it 'returns empty if the reference does not exist' do
result = described_class.new(
recipe, user, project, conan_package_reference: 'doesnotexist'
package, user, project, conan_package_reference: 'doesnotexist'
).package_urls
expect(result).to eq({})
@ -145,22 +128,17 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
subject do
described_class.new(
recipe, user, project, conan_package_reference: reference
package, user, project, conan_package_reference: reference
).package_snapshot
end
context 'no existing package' do
let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
let(:package) { nil }
it { is_expected.to be_empty }
end
it_behaves_like 'not selecting a package with the wrong type'
context 'existing package' do
let(:package) { create(:conan_package, project: project) }
let(:recipe) { package.conan_recipe }
let(:expected_result) do
{
"conaninfo.txt" => '12345abcde',

View File

@ -268,7 +268,7 @@ RSpec.describe API::ConanPackages do
it 'returns not found' do
allow(::Packages::Conan::PackagePresenter).to receive(:new)
.with(
'aa/bb@%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) },
nil,
user,
project,
any_args
@ -284,6 +284,21 @@ RSpec.describe API::ConanPackages do
end
end
shared_examples 'not selecting a package with the wrong type' do
context 'with a nuget package with same name and version' do
let(:conan_username) { ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
let(:wrong_package) { create(:nuget_package, name: "wrong", version: '1.0.0', project: project) }
let(:recipe_path) { "#{wrong_package.name}/#{wrong_package.version}/#{conan_username}/foo" }
it 'calls the presenter with a nil package' do
expect(::Packages::Conan::PackagePresenter).to receive(:new)
.with(nil, user, project, any_args)
subject
end
end
end
shared_examples 'recipe download_urls' do
let(:recipe_path) { package.conan_recipe_path }
@ -299,6 +314,8 @@ RSpec.describe API::ConanPackages do
expect(json_response).to eq(expected_response)
end
it_behaves_like 'not selecting a package with the wrong type'
end
shared_examples 'package download_urls' do
@ -317,6 +334,8 @@ RSpec.describe API::ConanPackages do
expect(json_response).to eq(expected_response)
end
it_behaves_like 'not selecting a package with the wrong type'
end
context 'recipe endpoints' do
@ -327,7 +346,7 @@ RSpec.describe API::ConanPackages do
before do
allow(::Packages::Conan::PackagePresenter).to receive(:new)
.with(package.conan_recipe, user, package.project, any_args)
.with(package, user, package.project, any_args)
.and_return(presenter)
end

View File

@ -119,10 +119,10 @@ RSpec.shared_context 'group navbar structure' do
nav_item: _('Settings'),
nav_sub_items: [
_('General'),
_('Integrations'),
_('Projects'),
_('Repository'),
_('CI / CD'),
_('Integrations'),
_('Webhooks'),
_('Audit Events')
]