Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-11-12 12:10:27 +00:00
parent 7717a594e8
commit ce07dcdcf5
42 changed files with 296 additions and 225 deletions

View File

@ -32,6 +32,20 @@
expire_in: 7 days
when: always
.parallel-qa-base:
parallel: 5
script:
- export KNAPSACK_REPORT_PATH=knapsack/master_report.json
- export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
- |
bin/test "${QA_SCENARIO}" "${CI_ENVIRONMENT_URL}" \
-- \
--color --format documentation \
--format RspecJunitFormatter --out tmp/rspec.xml
artifacts:
reports:
junit: qa/tmp/rspec.xml
.allure-report-base:
image:
name: ${GITLAB_DEPENDENCY_PROXY}andrcuns/allure-report-publisher:0.4.1
@ -65,24 +79,23 @@ review-qa-smoke:
script:
- bin/test Test::Instance::Smoke "${CI_ENVIRONMENT_URL}"
review-qa-reliable:
extends:
- .review-qa-base
- .review:rules:review-qa-reliable
- .parallel-qa-base
variables:
QA_RUN_TYPE: review-qa-reliable
QA_SCENARIO: Test::Instance::Reliable
review-qa-all:
extends:
- .review-qa-base
- .review:rules:review-qa-all
- .parallel-qa-base
variables:
QA_RUN_TYPE: review-qa-all
parallel: 5
script:
- export KNAPSACK_REPORT_PATH=knapsack/master_report.json
- export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
- |
bin/test Test::Instance::All "${CI_ENVIRONMENT_URL}" \
-- \
--color --format documentation \
--format RspecJunitFormatter --out tmp/rspec.xml
artifacts:
reports:
junit: qa/tmp/rspec.xml
QA_SCENARIO: Test::Instance::All
review-performance:
extends:

View File

@ -1666,6 +1666,11 @@
- <<: *if-dot-com-ee-schedule-child-pipeline
when: on_failure
.review:rules:review-qa-reliable:
rules:
- when: on_success
allow_failure: true
.review:rules:review-qa-all:
rules:
- <<: *if-not-ee

View File

@ -2629,6 +2629,5 @@ Style/OpenStructUse:
- 'spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb'
- 'spec/support_specs/helpers/stub_feature_flags_spec.rb'
- 'spec/tooling/rspec_flaky/flaky_example_spec.rb'
- 'tooling/rspec_flaky/flaky_example.rb'

View File

@ -1 +1 @@
1c25541fb9d55a330b83c5b01ed996eb6021459c
a4079265eb1b35c794ca45a056984cb13a7c2c82

View File

@ -16,6 +16,7 @@ import {
import * as Sentry from '@sentry/browser';
import { isEqual, isEmpty, omit } from 'lodash';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
import {
integrationTypes,
integrationSteps,
@ -129,6 +130,7 @@ export default {
name: true,
apiUrl: true,
},
pricingLink: `${PROMO_URL}/pricing`,
};
},
computed: {
@ -436,7 +438,7 @@ export default {
disabled="true"
class="gl-display-inline-block gl-my-4"
:message="$options.i18n.integrationFormSteps.selectType.enterprise"
link="https://about.gitlab.com/pricing"
:link="pricingLink"
data-testid="multi-integrations-not-supported"
/>
</gl-form-group>

View File

@ -5,6 +5,12 @@ const PATH_SEPARATOR_LEADING_REGEX = new RegExp(`^${PATH_SEPARATOR}+`);
const PATH_SEPARATOR_ENDING_REGEX = new RegExp(`${PATH_SEPARATOR}+$`);
const SHA_REGEX = /[\da-f]{40}/gi;
// About GitLab default host (overwrite in jh)
export const PROMO_HOST = 'about.gitlab.com';
// About Gitlab default url (overwrite in jh)
export const PROMO_URL = `https://${PROMO_HOST}`;
// Reset the cursor in a Regex so that multiple uses before a recompile don't fail
function resetRegExp(regex) {
regex.lastIndex = 0; /* eslint-disable-line no-param-reassign */

View File

@ -1,5 +1,5 @@
<script>
import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { GlLoadingIcon, GlTableLite } from '@gitlab/ui';
import createFlash from '~/flash';
import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
@ -12,7 +12,7 @@ const TIME_DATE_FORMAT = 'mmmm d, yyyy, HH:MM ("UTC:" o)';
export default {
components: {
GlLoadingIcon,
GlTable,
GlTableLite,
},
inject: ['issuableType'],
props: {
@ -89,7 +89,7 @@ export default {
<template>
<div>
<div v-if="isLoading"><gl-loading-icon size="md" /></div>
<gl-table v-else :items="report" :fields="$options.fields" foot-clone>
<gl-table-lite v-else :items="report" :fields="$options.fields" foot-clone>
<template #cell(spentAt)="{ item: { spentAt } }">
<div>{{ formatDate(spentAt) }}</div>
</template>
@ -111,6 +111,6 @@ export default {
<div>{{ getSummary(summary, note) }}</div>
</template>
<template #foot(note)>&nbsp;</template>
</gl-table>
</gl-table-lite>
</div>
</template>

View File

@ -4,7 +4,7 @@ module Projects
module Security
module ConfigurationHelper
def security_upgrade_path
'https://about.gitlab.com/pricing/'
"https://#{ApplicationHelper.promo_host}/pricing/"
end
end
end

View File

@ -7,11 +7,15 @@ module BlobViewer
self.file_types = %i(package_json)
def manager_name
'npm'
yarn? ? 'yarn' : 'npm'
end
def yarn?
json_data['engines'].present? && json_data['engines']['yarn'].present?
end
def manager_url
'https://www.npmjs.com/'
yarn? ? 'https://yarnpkg.com/' : 'https://www.npmjs.com/'
end
def package_name
@ -38,7 +42,11 @@ module BlobViewer
end
def npm_url
"https://www.npmjs.com/package/#{package_name}"
if yarn?
"https://yarnpkg.com/package/#{package_name}"
else
"https://www.npmjs.com/package/#{package_name}"
end
end
end
end

View File

@ -24,8 +24,9 @@ class ProjectAuthorization < ApplicationRecord
end
connection.execute <<-EOF.strip_heredoc
INSERT INTO project_authorizations (user_id, project_id, access_level)
VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
INSERT INTO project_authorizations (user_id, project_id, access_level)
VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
ON CONFLICT DO NOTHING
EOF
end
end

View File

@ -1020,8 +1020,10 @@ class User < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
def remove_project_authorizations(project_ids)
project_authorizations.where(project_id: project_ids).delete_all
def remove_project_authorizations(project_ids, per_batch = 1000)
project_ids.each_slice(per_batch) do |project_ids_batch|
project_authorizations.where(project_id: project_ids_batch).delete_all
end
end
def authorized_projects(min_access_level = nil)

View File

@ -67,10 +67,8 @@ module Users
def update_authorizations(remove = [], add = [])
log_refresh_details(remove, add)
User.transaction do
user.remove_project_authorizations(remove) unless remove.empty?
ProjectAuthorization.insert_authorizations(add) unless add.empty?
end
user.remove_project_authorizations(remove) unless remove.empty?
ProjectAuthorization.insert_authorizations(add) unless add.empty?
# Since we batch insert authorization rows, Rails' associations may get
# out of sync. As such we force a reload of the User object.

View File

@ -2,7 +2,7 @@
.top-area.adjust
.gl-display-block.gl-text-right.gl-my-4.gl-w-full
- if clusterable.can_add_cluster?
= link_to s_('ClusterIntegration|Connect cluster with certificate'), clusterable.new_path, class: 'btn gl-button btn-confirm js-add-cluster gl-py-2', qa_selector: :integrate_kubernetes_cluster_button
= link_to s_('ClusterIntegration|Connect cluster with certificate'), clusterable.new_path, class: 'btn gl-button btn-confirm js-add-cluster gl-py-2', data: { qa_selector: 'integrate_kubernetes_cluster_button' }
- else
%span.btn.gl-button.btn-confirm.js-add-cluster.disabled.gl-py-2
= s_("ClusterIntegration|Connect cluster with certificate")

View File

@ -1,18 +1,13 @@
- feature_project_list_filter_bar = Feature.enabled?(:project_list_filter_bar)
- is_your_projects_path = current_page?(dashboard_projects_path) || current_page?(root_path)
- is_explore_projects_path = current_page?(explore_root_path) || current_page?(trending_explore_projects_path) || current_page?(starred_explore_projects_path) || current_page?(explore_projects_path)
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs{ class: ('gl-border-0!' if feature_project_list_filter_bar) }
= nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do
= _("Your projects")
%span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(@total_user_projects_count)
= nav_link(page: starred_dashboard_projects_path) do
= link_to starred_dashboard_projects_path, data: {placement: 'right'} do
= _("Starred projects")
%span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(@total_starred_projects_count)
= nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do
= link_to explore_root_path, data: {placement: 'right'} do
= _("Explore projects")
= nav_link(page: topics_explore_projects_path) do
= link_to topics_explore_projects_path, data: {placement: 'right'} do
= _("Explore topics")
= gl_tabs_nav({ class: 'scrolling-tabs nav-links gl-display-flex gl-flex-grow-1 gl-flex-nowrap gl-border-0' }) do
= gl_tab_link_to dashboard_projects_path, { item_active: is_your_projects_path, class: 'shortcuts-activity', data: { placement: 'right' } } do
= _("Your projects")
= gl_tab_counter_badge(limited_counter_with_delimiter(@total_user_projects_count))
= gl_tab_link_to starred_dashboard_projects_path, { data: { placement: 'right' } } do
= _("Starred projects")
= gl_tab_counter_badge(limited_counter_with_delimiter(@total_starred_projects_count))
= gl_tab_link_to _("Explore projects"), explore_root_path, { item_active: is_explore_projects_path, data: { placement: 'right' } }
= gl_tab_link_to _("Explore topics"), topics_explore_projects_path, { data: { placement: 'right' } }
= render_if_exists "dashboard/removed_projects_tab", removed_projects_count: @removed_projects_count

View File

@ -46,5 +46,5 @@
%button.btn-blank.btn-link.js-trigger-shortcut{ type: 'button' }
= _('Use shortcuts')
- unless Gitlab::CurrentSettings.help_page_hide_commercial_content?
%li= link_to _('Get a support subscription'), 'https://about.gitlab.com/pricing/'
%li= link_to _('Compare GitLab editions'), 'https://about.gitlab.com/features/#compare'
%li= link_to _('Get a support subscription'), "https://#{ApplicationHelper.promo_host}/pricing/"
%li= link_to _('Compare GitLab editions'), "https://#{ApplicationHelper.promo_host}/features/#compare"

View File

@ -1,7 +1,7 @@
---
name: invite_team_email
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72470
rollout_issue_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345553
milestone: '14.5'
type: experiment
group: group::activation

View File

@ -1100,17 +1100,15 @@ To test the logic of Apollo cache updates, we might want to mock an Apollo Clien
To separate tests with mocked client from 'usual' unit tests, create an additional factory and pass the created `mockApollo` as an option to the `createComponent`-factory. This way we only create Apollo Client instance when it's necessary.
We need to inject `VueApollo` to the Vue local instance and, likewise, it is recommended to call `localVue.use()` in `createMockApolloProvider()` to only load it when it is necessary.
We need to inject `VueApollo` into the Vue instance by calling `Vue.use(VueApollo)`. This will install `VueApollo` globally for all the tests in the file. It is recommended to call `Vue.use(VueApollo)` just after the imports.
```javascript
import VueApollo from 'vue-apollo';
import { createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
const localVue = createLocalVue();
Vue.use(VueApollo);
function createMockApolloProvider() {
localVue.use(VueApollo);
return createMockApollo(requestHandlers);
}
@ -1118,7 +1116,6 @@ function createComponent(options = {}) {
const { mockApollo } = options;
...
return shallowMount(..., {
localVue,
apolloProvider: mockApollo,
...
});
@ -1188,7 +1185,6 @@ describe('Some component', () => {
const { mockApollo } = options;
return shallowMount(Index, {
localVue,
apolloProvider: mockApollo,
});
}
@ -1275,7 +1271,6 @@ function createComponent(options = {}) {
const { mockApollo } = options;
return shallowMount(Index, {
localVue,
apolloProvider: mockApollo,
});
}
@ -1408,7 +1403,6 @@ const createComponentWithApollo = ({ props = {} } = {}) => {
mockApollo = createMockApollo([], mockResolvers); // resolvers are the second parameter
wrapper = shallowMount(MyComponent, {
localVue,
propsData: {},
apolloProvider: mockApollo,
// ...
@ -1476,7 +1470,6 @@ function createComponent(options = {}) {
const { mockApollo } = options;
return shallowMount(Index, {
localVue,
apolloProvider: mockApollo,
});
}

View File

@ -199,8 +199,9 @@ security issues:
### Vulnerability-Check rule
To prevent a merge request introducing a security vulnerability in a project, enable the
Vulnerability-Check rule. While this rule is enabled, an additional merge request approval is
required when the latest security report in a merge request:
Vulnerability-Check rule. While this rule is enabled, additional merge request approval by
[eligible approvers](../project/merge_requests/approvals/rules.md#eligible-approvers)
is required when the latest security report in a merge request:
- Contains vulnerabilities with states (for example, `previously detected`, `dismissed`) matching the rule's vulnerability states. Only `newly detected` will be considered if the target branch differs from the project default branch.
- Contains vulnerabilities with severity levels (for example, `high`, `critical`, or `unknown`)
@ -215,13 +216,12 @@ An approval is optional when the security report:
the rule's severity levels.
- Contains a vulnerability count equal to or less than what the rule allows.
Project members assigned [at least the Maintainer role](../permissions.md#project-members-permissions) can enable or edit
the Vulnerability-Check rule.
#### Enable the Vulnerability-Check rule
Prerequisites:
- Maintainer or Owner [role](../permissions.md#project-members-permissions).
To enable the `Vulnerability-Check` rule:
To enable or edit the Vulnerability-Check rule:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > General**.

View File

@ -3,6 +3,13 @@ const baseConfig = require('./jest.config.base');
checkEnvironment();
console.log(`
PSA: Running into unexpected and/or strange frontend integration test errors?
Please help improve our error logging by following the instructions on this issue:
https://gitlab.com/gitlab-org/gitlab/-/issues/345513
`);
module.exports = {
...baseConfig('spec/frontend_integration', {
moduleNameMapper: {

View File

@ -24,8 +24,7 @@ spec:
args:
- --token-file=/config/token
- --kas-address
- "<%= kas_wss_address %>" # Use this for GitLab chart deployments
# - "<%= kas_grpc_address %>" # Use this for GDK
- "<%= kas_wss_address %>"
volumeMounts:
- name: token-volume
mountPath: /config

View File

@ -11,7 +11,7 @@ module QA
end
def add_existing_cluster
click_element(:add_existing_cluster_tab)
page.find('.gl-tab-nav-item', text: 'Connect existing cluster').click
end
end
end

View File

@ -6,12 +6,12 @@ module QA
module Infrastructure
module Kubernetes
class Index < Page::Base
view 'app/assets/javascripts/clusters_list/components/clusters_empty_state.vue' do
element :add_kubernetes_cluster_link
view 'app/views/clusters/clusters/_cluster_list.html.haml' do
element :integrate_kubernetes_cluster_button
end
def add_kubernetes_cluster
click_element :add_kubernetes_cluster_link
def connect_cluster_with_certificate
find('.js-add-cluster').click
end
def has_cluster?(cluster)

View File

@ -7,26 +7,9 @@ module QA
module Kubernetes
class Show < Page::Base
view 'app/assets/javascripts/clusters/forms/components/integration_form.vue' do
element :integration_status_toggle, required: true
element :base_domain_field, required: true
element :save_changes_button, required: true
end
view 'app/views/clusters/clusters/_details_tab.html.haml' do
element :details, required: true
end
view 'app/views/clusters/clusters/_health.html.haml' do
element :cluster_health_section
end
view 'app/views/clusters/clusters/_health_tab.html.haml' do
element :health, required: true
end
def open_details
has_element?(:details, wait: 30)
click_element :details
element :integration_status_toggle
element :base_domain_field
element :save_changes_button
end
def set_domain(domain)
@ -36,29 +19,6 @@ module QA
def save_domain
click_element :save_changes_button, Page::Project::Infrastructure::Kubernetes::Show
end
def wait_for_cluster_health
wait_until(max_duration: 120, sleep_interval: 3, reload: true) do
has_cluster_health_graphs?
end
end
def open_health
has_element?(:health, wait: 30)
click_element :health
end
def has_cluster_health_graphs?
within_cluster_health_section do
has_text?('CPU Usage')
end
end
def within_cluster_health_section
within_element :cluster_health_section do
yield
end
end
end
end
end

View File

@ -19,13 +19,12 @@ module QA
def fabricate!
puts 'TODO: FABRICATE VIA UI'
end
# TODO
#
# The UI for this model is not yet implemented. So far it can only be
# created through the GraphQL API
# def fabricate
#
# end
def resource_web_url(resource)
super
rescue ResourceURLMissingError
# this particular resource does not expose a web_url property
end
def api_get_path
"gid://gitlab/Clusters::Agent/#{id}"

View File

@ -13,13 +13,12 @@ module QA
def fabricate!
puts 'TODO: FABRICATE VIA UI'
end
# TODO
#
# The UI for this model is not yet implemented. So far it can only be
# created through the GraphQL API
# def fabricate
#
# end
def resource_web_url(resource)
super
rescue ResourceURLMissingError
# this particular resource does not expose a web_url property
end
def api_get_path
"gid://gitlab/Clusters::AgentToken/#{id}"

View File

@ -13,8 +13,8 @@ module QA
Resource::Project.fabricate!
end
def ingress_ip
@ingress_ip ||= @cluster.fetch_external_ip_for_ingress
attribute :ingress_ip do
@cluster.fetch_external_ip_for_ingress
end
def fabricate!
@ -24,7 +24,7 @@ module QA
&:go_to_infrastructure_kubernetes)
Page::Project::Infrastructure::Kubernetes::Index.perform(
&:add_kubernetes_cluster)
&:connect_cluster_with_certificate)
Page::Project::Infrastructure::Kubernetes::Add.perform(
&:add_existing_cluster)
@ -39,14 +39,10 @@ module QA
end
Page::Project::Infrastructure::Kubernetes::Show.perform do |show|
# We must wait a few seconds for permissions to be set up correctly for new cluster
sleep 25
if @install_ingress
populate(:ingress_ip)
ingress_ip
show.open_details
show.set_domain("#{ingress_ip}.nip.io")
show.set_domain("#{@ingress_ip}.nip.io")
show.save_domain
end
end

View File

@ -403,7 +403,7 @@ module QA
end
def gitlab_agentk_version
ENV.fetch('GITLAB_AGENTK_VERSION', 'v13.7.0')
ENV.fetch('GITLAB_AGENTK_VERSION', 'v14.4.0')
end
def transient_trials

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
module QA
module Scenario
module Test
module Instance
class Reliable < Template
include Bootable
include SharedAttributes
tags :reliable
end
end
end
end
end

View File

@ -24,16 +24,6 @@ module QA
)
end
def set_credentials(admin_user)
master_auth = JSON.parse(`gcloud container clusters describe #{cluster_name} --region #{@region} --format 'json(masterAuth.username, masterAuth.password)'`)
shell <<~CMD.tr("\n", ' ')
kubectl config set-credentials #{admin_user}
--username #{master_auth['masterAuth']['username']}
--password #{master_auth['masterAuth']['password']}
CMD
end
def setup
login_if_not_already_logged_in
create_cluster
@ -43,6 +33,12 @@ module QA
delete_cluster
end
def install_ingress
QA::Runtime::Logger.info "Attempting to install Ingress on cluster #{cluster_name}"
shell 'kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.31.0/deploy/static/provider/cloud/deploy.yaml'
wait_for_ingress
end
private
def login_if_not_already_logged_in
@ -59,7 +55,7 @@ module QA
end
def attempt_login_with_env_vars
puts "No gcloud account. Attempting to login from env vars GCLOUD_ACCOUNT_EMAIL and GCLOUD_ACCOUNT_KEY."
QA::Runtime::Logger.debug("Logging in with GCLOUD_ACCOUNT_EMAIL and GCLOUD_ACCOUNT_KEY.")
gcloud_account_key = Tempfile.new('gcloud-account-key')
gcloud_account_key.write(Runtime::Env.gcloud_account_key)
gcloud_account_key.close
@ -80,7 +76,6 @@ module QA
gcloud container clusters
create #{cluster_name}
#{auth_options}
--enable-basic-auth
--region #{@region}
--disk-size 10GB
--num-nodes #{Runtime::Env.gcloud_num_nodes}
@ -109,6 +104,18 @@ module QA
def get_region
Runtime::Env.gcloud_region || @available_regions.delete(@available_regions.sample)
end
def wait_for_ingress
QA::Runtime::Logger.info 'Waiting for Ingress controller pod to be initialized'
Support::Retrier.retry_until(max_attempts: 60, sleep_interval: 1) do
service_available?('kubectl get pods --all-namespaces -l app.kubernetes.io/component=controller | grep -o "ingress-nginx-controller.*1/1"')
end
end
def service_available?(command)
system("#{command} > /dev/null 2>&1")
end
end
end
end

View File

@ -41,6 +41,10 @@ module QA
cluster_name
end
def install_ingress
@provider.install_ingress
end
def create_secret(secret, secret_name)
shell("kubectl create secret generic #{secret_name} --from-literal=token='#{secret}'")
end
@ -70,7 +74,13 @@ module QA
end
def fetch_external_ip_for_ingress
`kubectl get svc --all-namespaces --no-headers=true -l app.kubernetes.io/name=ingress-nginx -o custom-columns=:'status.loadBalancer.ingress[0].ip' | grep -v 'none'`
install_ingress
# need to wait since the ingress-nginx service has an initial delay set of 10 seconds
sleep 10
ingress_ip = `kubectl get svc --all-namespaces --no-headers=true -l app.kubernetes.io/name=ingress-nginx -o custom-columns=:'status.loadBalancer.ingress[0].ip' | grep -v 'none'`
QA::Runtime::Logger.debug "Has ingress address set to: #{ingress_ip}"
ingress_ip
end
private
@ -82,7 +92,6 @@ module QA
def fetch_credentials
return global_credentials unless rbac
@provider.set_credentials(admin_user)
create_service_account(admin_user)
account_credentials
end

View File

@ -1,10 +1,10 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Configure' do
RSpec.describe 'Configure', only: { subdomain: :staging } do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = Runtime::Env.auto_devops_project_name || 'autodevops-project'
project.name = 'autodevops-project'
project.auto_devops_enabled = true
end
end
@ -13,35 +13,24 @@ module QA
disable_optional_jobs(project)
end
describe 'Auto DevOps support', :orchestrated, :kubernetes, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/251090', type: :stale } do
describe 'Auto DevOps support' do
context 'when rbac is enabled' do
let(:cluster) { Service::KubernetesCluster.new.create! }
after do
cluster&.remove!
project.remove_via_api!
end
it 'runs auto devops', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1422' do
Flow::Login.sign_in
# Set an application secret CI variable (prefixed with K8S_SECRET_)
Resource::CiVariable.fabricate! do |resource|
resource.project = project
resource.key = 'K8S_SECRET_OPTIONAL_MESSAGE'
resource.value = 'you_can_see_this_variable'
resource.masked = false
end
# Connect K8s cluster
Resource::KubernetesCluster::ProjectCluster.fabricate! do |k8s_cluster|
k8s_cluster.project = project
k8s_cluster.cluster = cluster
k8s_cluster.install_ingress = true
k8s_cluster.install_prometheus = true
k8s_cluster.install_runner = true
end
# Create Auto DevOps compatible repo
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.directory = Pathname
@ -78,46 +67,6 @@ module QA
job.click_element(:pipeline_path)
end
Page::Project::Menu.perform(&:go_to_deployments_environments)
Page::Project::Deployments::Environments::Index.perform do |index|
index.click_environment_link('production')
end
Page::Project::Deployments::Environments::Show.perform do |show|
show.view_deployment do
expect(page).to have_content('Hello World!')
expect(page).to have_content('you_can_see_this_variable')
end
end
end
end
end
describe 'Auto DevOps', :smoke do
before do
Flow::Login.sign_in
project.visit!
Page::Project::Menu.perform(&:go_to_ci_cd_settings)
Page::Project::Settings::CiCd.perform(&:expand_auto_devops)
Page::Project::Settings::AutoDevops.perform(&:enable_autodevops)
# Create AutoDevOps repo
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.directory = Pathname
.new(__dir__)
.join('../../../../../fixtures/auto_devops_rack')
push.commit_message = 'Create AutoDevOps compatible Project'
end
end
it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1564' do
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to have_tag('Auto DevOps')
end
end
end
@ -128,7 +77,8 @@ module QA
%w[
CODE_QUALITY_DISABLED LICENSE_MANAGEMENT_DISABLED
SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
CONTAINER_SCANNING_DISABLED
CONTAINER_SCANNING_DISABLED BROWSER_PERFORMANCE_DISABLED
SECRET_DETECTION_DISABLED
].each do |key|
Resource::CiVariable.fabricate_via_api! do |resource|
resource.project = project

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
RSpec.describe QA::Scenario::Test::Instance::Reliable do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:reliable] }
end
end

View File

@ -80,7 +80,7 @@ RSpec.describe 'Dashboard Projects' do
visit dashboard_projects_path
expect(page).to have_content(project.name)
expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
expect(find('.gl-tabs-nav li:nth-child(1) .badge-pill')).to have_content(1)
end
it 'shows personal projects on personal projects tab', :js do
@ -128,8 +128,8 @@ RSpec.describe 'Dashboard Projects' do
expect(page).not_to have_content(project.name)
expect(page).to have_content(project2.name)
expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
expect(find('.nav-links li:nth-child(2) .badge-pill')).to have_content(1)
expect(find('.gl-tabs-nav li:nth-child(1) .badge-pill')).to have_content(1)
expect(find('.gl-tabs-nav li:nth-child(2) .badge-pill')).to have_content(1)
end
it 'does not show tabs to filter by all projects or personal' do

View File

@ -1,4 +1,12 @@
import { GlForm, GlFormSelect, GlFormInput, GlToggle, GlFormTextarea, GlTab } from '@gitlab/ui';
import {
GlForm,
GlFormSelect,
GlFormInput,
GlToggle,
GlFormTextarea,
GlTab,
GlLink,
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@ -101,6 +109,12 @@ describe('AlertsSettingsForm', () => {
expect(findFormFields().at(0).attributes('id')).not.toBe('name-integration');
});
it('verify pricing link url', () => {
createComponent({ props: { canAddIntegration: false } });
const link = findMultiSupportText().findComponent(GlLink);
expect(link.attributes('href')).toMatch(/https:\/\/about.gitlab.(com|cn)\/pricing/);
});
describe('form tabs', () => {
it('renders 3 tabs', () => {
expect(findTabs()).toHaveLength(3);

View File

@ -1060,4 +1060,12 @@ describe('URL utility', () => {
},
);
});
describe('defaultPromoUrl', () => {
it('Gitlab about page url', () => {
const url = 'https://about.gitlab.com';
expect(urlUtils.PROMO_URL).toBe(url);
});
});
});

View File

@ -8,6 +8,6 @@ RSpec.describe Projects::Security::ConfigurationHelper do
describe 'security_upgrade_path' do
subject { security_upgrade_path }
it { is_expected.to eq('https://about.gitlab.com/pricing/') }
it { is_expected.to eq("https://#{ApplicationHelper.promo_host}/pricing/") }
end
end

View File

@ -27,11 +27,55 @@ RSpec.describe BlobViewer::PackageJson do
end
end
describe '#package_url' do
it 'returns the package URL' do
expect(subject).to receive(:prepare!)
context 'yarn' do
let(:data) do
<<-SPEC.strip_heredoc
{
"name": "module-name",
"version": "10.3.1",
"engines": {
"yarn": "^2.4.0"
}
}
SPEC
end
expect(subject.package_url).to eq("https://www.npmjs.com/package/#{subject.package_name}")
let(:blob) { fake_blob(path: 'package.json', data: data) }
subject { described_class.new(blob) }
describe '#package_url' do
it 'returns the package URL', :aggregate_failures do
expect(subject).to receive(:prepare!)
expect(subject.package_url).to eq("https://yarnpkg.com/package/#{subject.package_name}")
end
end
describe '#manager_url' do
it 'returns the manager URL', :aggregate_failures do
expect(subject).to receive(:prepare!)
expect(subject.manager_url).to eq("https://yarnpkg.com/")
end
end
end
context 'npm' do
describe '#package_url' do
it 'returns the package URL', :aggregate_failures do
expect(subject).to receive(:prepare!)
expect(subject.package_url).to eq("https://www.npmjs.com/package/#{subject.package_name}")
end
end
describe '#manager_url' do
it 'returns the manager URL', :aggregate_failures do
expect(subject).to receive(:prepare!)
expect(subject.manager_url).to eq("https://www.npmjs.com/")
end
end
end

View File

@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe ProjectAuthorization do
let(:user) { create(:user) }
let(:project1) { create(:project) }
let(:project2) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:project1) { create(:project) }
let_it_be(:project2) { create(:project) }
let_it_be(:project3) { create(:project) }
describe '.insert_authorizations' do
it 'inserts the authorizations' do
@ -23,5 +24,19 @@ RSpec.describe ProjectAuthorization do
expect(user.project_authorizations.count).to eq(2)
end
it 'skips duplicates and inserts the remaining rows without error' do
create(:project_authorization, user: user, project: project1, access_level: Gitlab::Access::MAINTAINER)
rows = [
[user.id, project1.id, Gitlab::Access::MAINTAINER],
[user.id, project2.id, Gitlab::Access::MAINTAINER],
[user.id, project3.id, Gitlab::Access::MAINTAINER]
]
described_class.insert_authorizations(rows)
expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(rows)
end
end
end

View File

@ -4147,6 +4147,23 @@ RSpec.describe User do
end
end
describe '#remove_project_authorizations' do
let_it_be(:project1) { create(:project) }
let_it_be(:project2) { create(:project) }
let_it_be(:project3) { create(:project) }
let_it_be(:user) { create(:user) }
it 'removes the project authorizations of the user, in specified projects' do
create(:project_authorization, user: user, project: project1)
create(:project_authorization, user: user, project: project2)
create(:project_authorization, user: user, project: project3)
user.remove_project_authorizations([project1.id, project2.id])
expect(user.project_authorizations.pluck(:project_id)).to match_array([project3.id])
end
end
describe '#access_level=' do
let(:user) { build(:user) }

View File

@ -97,7 +97,7 @@ RSpec.describe StubFeatureFlags do
context 'type handling' do
context 'raises error' do
where(:feature_actors) do
['string', 1, 1.0, OpenStruct.new]
['string', 1, 1.0, Object.new]
end
with_them do

View File

@ -84,6 +84,7 @@ module Tooling
%r{\A((ee|jh)/)?app/finders/} => [:database, :backend],
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
%r{\A(\.ruby-version\z|\.nvmrc\z|\.tool-versions\z)} => :tooling,
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :tooling,
%r{\A\.codeclimate\.yml\z} => :tooling,
%r{\Alefthook.yml\z} => :tooling,

1
workhorse/.tool-versions Normal file
View File

@ -0,0 +1 @@
golang 1.16.9