Commit 78e34e45 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents e189d788 02fcb882
......@@ -132,9 +132,6 @@ export default {
noteable: this.noteableDisplayName,
});
},
buttonVariant() {
return this.isOpen ? 'warning' : 'default';
},
actionButtonClassNames() {
return {
'btn-reopen': !this.isOpen,
......@@ -422,8 +419,6 @@ export default {
<gl-button
v-if="canToggleIssueState"
:loading="isToggleStateButtonLoading"
category="secondary"
:variant="buttonVariant"
:class="[actionButtonClassNames, 'btn-comment btn-comment-and-close']"
:disabled="isSubmitting"
data-testid="close-reopen-button"
......
......@@ -3,8 +3,6 @@
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants';
import initInviteMembersBanner from '~/groups/init_invite_members_banner';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { getPagePath, getDashPath } from '~/lib/utils/common_utils';
import initNotificationsDropdown from '~/notifications';
import ProjectsList from '~/projects_list';
......@@ -26,6 +24,4 @@ export default function initGroupDetails(actionName = 'show') {
new ProjectsList();
initInviteMembersBanner();
initInviteMembersModal();
initInviteMembersTrigger();
}
......@@ -3,8 +3,6 @@ import Activities from '~/activities';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import BlobViewer from '~/blob/viewer/index';
import { initUploadForm } from '~/blob_edit/blob_bundle';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import leaveByUrl from '~/namespaces/leave_by_url';
import initVueNotificationsDropdown from '~/notifications';
import initReadMore from '~/read_more';
......@@ -43,6 +41,3 @@ leaveByUrl('project');
initVueNotificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new
initInviteMembersTrigger();
initInviteMembersModal();
<script>
import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { BRANCH_REF_TYPE, TAG_REF_TYPE, DEBOUNCE_REFS_SEARCH_MS } from '../constants';
import formatRefs from '../utils/format_refs';
export default {
components: {
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
GlSearchBoxByType,
},
inject: ['projectRefsEndpoint'],
props: {
value: {
type: Object,
required: false,
default: () => ({}),
},
},
data() {
return {
isLoading: false,
searchTerm: '',
branches: [],
tags: [],
};
},
computed: {
lowerCasedSearchTerm() {
return this.searchTerm.toLowerCase();
},
refShortName() {
return this.value.shortName;
},
hasTags() {
return this.tags.length > 0;
},
},
watch: {
searchTerm() {
this.debouncedLoadRefs();
},
},
methods: {
loadRefs() {
this.isLoading = true;
axios
.get(this.projectRefsEndpoint, {
params: {
search: this.lowerCasedSearchTerm,
},
})
.then(({ data }) => {
// Note: These keys are uppercase in API
const { Branches = [], Tags = [] } = data;
this.branches = formatRefs(Branches, BRANCH_REF_TYPE);
this.tags = formatRefs(Tags, TAG_REF_TYPE);
})
.catch((e) => {
this.$emit('loadingError', e);
})
.finally(() => {
this.isLoading = false;
});
},
debouncedLoadRefs: debounce(function debouncedLoadRefs() {
this.loadRefs();
}, DEBOUNCE_REFS_SEARCH_MS),
setRefSelected(ref) {
this.$emit('input', ref);
},
isSelected(ref) {
return ref.fullName === this.value.fullName;
},
},
};
</script>
<template>
<gl-dropdown :text="refShortName" block @show.once="loadRefs">
<gl-search-box-by-type
v-model.trim="searchTerm"
:is-loading="isLoading"
:placeholder="__('Search refs')"
/>
<gl-dropdown-section-header>{{ __('Branches') }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="branch in branches"
:key="branch.fullName"
class="gl-font-monospace"
is-check-item
:is-checked="isSelected(branch)"
@click="setRefSelected(branch)"
>
{{ branch.shortName }}
</gl-dropdown-item>
<gl-dropdown-section-header v-if="hasTags">{{ __('Tags') }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="tag in tags"
:key="tag.fullName"
class="gl-font-monospace"
is-check-item
:is-checked="isSelected(tag)"
@click="setRefSelected(tag)"
>
{{ tag.shortName }}
</gl-dropdown-item>
</gl-dropdown>
</template>
export const VARIABLE_TYPE = 'env_var';
export const FILE_TYPE = 'file';
export const DEBOUNCE_REFS_SEARCH_MS = 250;
export const CONFIG_VARIABLES_TIMEOUT = 5000;
export const BRANCH_REF_TYPE = 'branch';
export const TAG_REF_TYPE = 'tag';
import Vue from 'vue';
import PipelineNewForm from './components/pipeline_new_form.vue';
import formatRefs from './utils/format_refs';
export default () => {
const el = document.getElementById('js-new-pipeline');
const {
// provide/inject
projectRefsEndpoint,
// props
projectId,
pipelinesPath,
configVariablesPath,
......@@ -12,19 +15,18 @@ export default () => {
refParam,
varParam,
fileParam,
branchRefs,
tagRefs,
settingsLink,
maxWarnings,
} = el?.dataset;
const variableParams = JSON.parse(varParam);
const fileParams = JSON.parse(fileParam);
const branches = formatRefs(JSON.parse(branchRefs), 'branch');
const tags = formatRefs(JSON.parse(tagRefs), 'tag');
return new Vue({
el,
provide: {
projectRefsEndpoint,
},
render(createElement) {
return createElement(PipelineNewForm, {
props: {
......@@ -35,8 +37,6 @@ export default () => {
refParam,
variableParams,
fileParams,
branches,
tags,
settingsLink,
maxWarnings: Number(maxWarnings),
},
......
......@@ -196,10 +196,6 @@
@include btn-orange;
}
&.btn-close {
@include btn-outline($white, $orange-500, $orange-500, $orange-50, $orange-600, $orange-600, $orange-100, $orange-700, $orange-700);
}
&.btn-danger {
@include btn-red;
}
......
......@@ -16,11 +16,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
= content_for :invite_members_sidebar do
- if can_invite_members_for_group?(@group)
%li
.js-invite-members-trigger{ data: { icon: 'plus', classes: 'gl-text-decoration-none! gl-shadow-none!', display_text: _('Invite team members') } }
= render partial: 'flash_messages'
= render_if_exists 'trials/banner', namespace: @group
......
......@@ -137,8 +137,6 @@
%strong.fly-out-top-item-name
= _('Members')
= content_for :invite_members_sidebar
- if group_sidebar_link?(:settings)
= nav_link(path: group_settings_nav_link_paths) do
= link_to edit_group_path(@group) do
......
......@@ -378,8 +378,6 @@
%strong.fly-out-top-item-name
= _('Members')
= content_for :invite_members_sidebar
- if project_nav_tab? :settings
= nav_link(path: sidebar_settings_paths) do
= link_to edit_project_path(@project) do
......
......@@ -3,8 +3,6 @@
- max_project_topic_length = 15
- emails_disabled = @project.emails_disabled?
= render 'projects/invite_members_modal', project: @project
.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
.row.gl-mb-3
.home-panel-title-row.col-md-12.col-lg-6.d-flex
......
- return unless can_invite_members_for_project?(@project)
%li
.js-invite-members-trigger{ data: { icon: 'plus', classes: 'gl-text-decoration-none! gl-shadow-none!', display_text: _('Invite team members') } }
......@@ -2,9 +2,6 @@
- default_branch_name = @project.default_branch_or_master
- @skip_current_level_breadcrumb = true
= content_for :invite_members_sidebar do
= render partial: 'projects/invite_members_link'
= render partial: 'flash_messages', locals: { project: @project }
= render "home_panel"
......
......@@ -12,8 +12,6 @@
#{ _('This means you can not push code until you create an empty repository or import existing one.') }
%hr
= render 'projects/invite_members_modal', project: @project
.no-repo-actions
= link_to project_repository_path(@project), method: :post, class: 'btn gl-button btn-confirm' do
#{ _('Create empty repository') }
......
......@@ -14,8 +14,7 @@
ref_param: params[:ref] || @project.default_branch,
var_param: params[:var].to_json,
file_param: params[:file_var].to_json,
branch_refs: @project.repository.branch_names.to_json.html_safe,
tag_refs: @project.repository.tag_names.to_json.html_safe,
project_refs_endpoint: refs_project_path(@project, sort: 'updated_desc'),
settings_link: project_settings_ci_cd_path(@project),
max_warnings: ::Gitlab::Ci::Warnings::MAX_LIMIT } }
......
......@@ -6,9 +6,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
= content_for :invite_members_sidebar do
= render partial: 'projects/invite_members_link'
= render partial: 'flash_messages', locals: { project: @project }
= render "projects/last_push"
......
---
title: Deemphasize comment and close button
merge_request: 55075
author:
type: other
---
title: Improve performance of manual pipeline form by limiting the refs loaded on page load.
merge_request: 55394
author:
type: performance
---
title: Fix N+1 queries in api/v3/repos/:namespace/:project/events endpoint
merge_request: 55442
author:
type: performance
---
name: api_v3_repos_events_optimization
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54618
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322059
name: new_route_ci_minutes_purchase
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54934
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322582
milestone: '13.10'
type: development
group: group::ecosystem
group: group::purchase
default_enabled: false
......@@ -17,21 +17,21 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|-------------|----------|
| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | `m5.2xlarge` | D8s v3 |
| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
| Gitaly Cluster | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | `m5.4xlarge` | D16s v3 |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | `c5.9xlarge` | F32s v2 |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
| Gitaly | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | m5.4xlarge | D16s v3 |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
......@@ -206,7 +206,7 @@ The following list includes descriptions of each server and its assigned IP:
- `10.6.0.111`: GitLab application 1
- `10.6.0.112`: GitLab application 2
- `10.6.0.113`: GitLab application 3
- `10.6.0.121`: Prometheus
- `10.6.0.151`: Prometheus
## Configure the external load balancer
......@@ -1927,7 +1927,7 @@ To configure the Sidekiq nodes, on each one:
node_exporter['listen_address'] = '0.0.0.0:9100'
# Rails Status for prometheus
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
gitlab_rails['monitoring_whitelist'] = ['10.6.0.151/32', '127.0.0.0/8']
#############################
### Object storage ###
......@@ -2055,8 +2055,8 @@ On each node perform the following:
# Add the monitoring node's IP address to the monitoring whitelist and allow it to
# scrape the NGINX metrics
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8']
gitlab_rails['monitoring_whitelist'] = ['10.6.0.151/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['10.6.0.151/32', '127.0.0.0/8']
#############################
### Object storage ###
......@@ -2192,7 +2192,7 @@ running [Prometheus](../monitoring/prometheus/index.md) and
The following IP will be used as an example:
- `10.6.0.121`: Prometheus
- `10.6.0.151`: Prometheus
To configure the Monitoring node:
......
......@@ -137,10 +137,10 @@ To execute a pipeline manually:
1. Navigate to your project's **CI/CD > Pipelines**.
1. Select the **Run Pipeline** button.
1. On the **Run Pipeline** page:
1. Select the branch to run the pipeline for in the **Create for** field.
1. Select the branch or tag to run the pipeline for in the **Run for branch name or tag** field.
1. Enter any [environment variables](../variables/README.md) required for the pipeline run.
You can set specific variables to have their [values prefilled in the form](#prefill-variables-in-manual-pipelines).
1. Click the **Create pipeline** button.
1. Click the **Run pipeline** button.
The pipeline now executes the jobs as configured.
......
This diff is collapsed.
import mountSubscriptionsApplication from 'ee/subscriptions/buy_minutes';
mountSubscriptionsApplication();
......@@ -20,7 +20,7 @@ import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue'
import { VULNERABILITY_STATES } from 'ee/vulnerabilities/constants';
import { formatDate } from '~/lib/utils/datetime_utility';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { s__, __, sprintf } from '~/locale';
import { s__, __ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { VULNERABILITIES_PER_PAGE } from '../store/constants';
import IssuesBadge from './issues_badge.vue';
......@@ -230,7 +230,7 @@ export default {
}
if (file && startLine) {
return `${file} ${sprintf(__('(line: %{startLine})'), { startLine })}`;
return `${file}:${startLine}`;
}
if (path) {
......@@ -248,6 +248,16 @@ export default {
extraIdentifierCount(identifiers) {
return identifiers?.length - 1;
},
fileUrl(vulnerability) {
const { startLine: start, endLine: end, blobPath } = vulnerability.location;
const lineNumber = end > start ? `${start}-${end}` : start;
if (!blobPath) {
return '';
}
return `${blobPath}${lineNumber ? `#L${lineNumber}` : ''}`;
},
primaryIdentifier(identifiers) {
return getPrimaryIdentifier(identifiers, 'externalType');
},
......@@ -421,8 +431,11 @@ export default {
<div v-if="shouldShowProjectNamespace">
{{ item.project.nameWithNamespace }}
</div>
<div v-if="shouldShowVulnerabilityPath(item)" class="monospace">
<gl-truncate :text="createLocationString(item.location)" position="middle" />
<div v-if="shouldShowVulnerabilityPath(item)">
<gl-link v-if="item.location.blobPath" :href="fileUrl(item)">
<gl-truncate :text="createLocationString(item.location)" position="middle" />
</gl-link>
<gl-truncate v-else :text="createLocationString(item.location)" position="middle" />
</div>
</div>
</template>
......
......@@ -27,13 +27,16 @@ fragment Vulnerability on Vulnerability {
image
}
... on VulnerabilityLocationDependencyScanning {
blobPath
file
}
... on VulnerabilityLocationSast {
blobPath
file
startLine
}
... on VulnerabilityLocationSecretDetection {
blobPath
file
startLine
}
......
<script>
import StepOrderApp from 'ee/vue_shared/components/step_order_app.vue';
export default {
components: {
StepOrderApp,
},
};
</script>
<template>
<step-order-app>
<template #checkout></template>
<template #order-summary></template>
</step-order-app>
</template>
import Vue from 'vue';
import App from './components/app.vue';
export default () => {
const el = document.getElementById('js-buy-minutes');
return new Vue({
el,
components: {
App,
},
render(createElement) {
return createElement(App);
},
});
};
<script>
import StepOrderApp from 'ee/vue_shared/components/step_order_app.vue';
import Checkout from './checkout.vue';
import OrderSummary from './order_summary.vue';
export default {
components: {
StepOrderApp,
Checkout,
OrderSummary,
},
};
</script>
<template>
<step-order-app>
<template #checkout>
<checkout />
</template>
<template #order-summary>
<order-summary />
</template>
</step-order-app>
</template>
import Vue from 'vue';
import Checkout from './components/checkout.vue';
import OrderSummary from './components/order_summary.vue';
import App from './components/app.vue';
import createStore from './store';
export default () => {
const checkoutEl = document.getElementById('checkout');
const summaryEl = document.getElementById('summary');
const store = createStore(checkoutEl.dataset);
// eslint-disable-next-line no-new
new Vue({
el: checkoutEl,
store,
render(createElement) {
return createElement(Checkout);
},
});
const el = document.getElementById('js-new-subscription');
const store = createStore(el.dataset);
return new Vue({
el: summaryEl,
el,
store,
components: {
App,
},
render(createElement) {
return createElement(OrderSummary);
return createElement(App);
},
});
};
<template>
<div
class="row gl-flex-grow-1 gl-flex-direction-column flex-nowrap gl-lg-flex-direction-row flex-xl-row flex-lg-wrap flex-xl-wrap"
>
<div
class="checkout-pane gl-px-3 gl-align-items-center gl-bg-gray-10 col-lg-7 gl-display-flex gl-flex-direction-column gl-flex-grow-1"
>
<slot name="checkout"></slot>
</div>
<div
class="gl-pb-3 gl-px-3 px-lg-7 col-lg-5 gl-display-flex gl-flex-direction-row gl-justify-content-center"
>
<slot name="order-summary"></slot>
</div>
</div>
</template>
......@@ -2,7 +2,7 @@
class SubscriptionsController < ApplicationController
layout 'checkout'
skip_before_action :authenticate_user!, only: :new
skip_before_action :authenticate_user!, only: [:new, :buy_minutes]
feature_category :purchase
......@@ -24,10 +24,12 @@ class SubscriptionsController < ApplicationController
end
def new
return if current_user
redirect_unauthenticated_user('checkout')
end
store_location_for :user, request.fullpath
redirect_to new_user_registration_path(redirect_from: 'checkout')
def buy_minutes
render_404 unless Feature.enabled?(:new_route_ci_minutes_purchase, default_enabled: :yaml)
redirect_unauthenticated_user
end
def payment_form
......@@ -90,4 +92,11 @@ class SubscriptionsController < ApplicationController
def customer_portal_new_subscription_url
"#{EE::SUBSCRIPTIONS_URL}/subscriptions/new?plan_id=#{params[:plan_id]}&transaction=create_subscription"
end
def redirect_unauthenticated_user(from = action_name)
return if current_user
store_location_for :user, request.fullpath
redirect_to new_user_registration_path(redirect_from: from)
end
end
......@@ -107,7 +107,7 @@ module Security
return by_find_params if by_find_params
Gitlab::ErrorTracking.track_and_raise_exception(e, find_params: find_params, uuid: finding.uuid)
rescue ActiveRecord::RecordInvalid => e
rescue ActiveRecord::ActiveRecordError => e
Gitlab::ErrorTracking.track_and_raise_exception(e, create_params: create_params&.dig(:raw_metadata))
end
end
......
- page_title _('Buy CI Minutes')
#js-buy-minutes{ data: subscription_data }
- page_title _('Checkout')
.row.flex-grow-1.flex-column.flex-nowrap.flex-lg-row.flex-xl-row.flex-lg-wrap.flex-xl-wrap
.checkout-pane.px-3.align-items-center.bg-gray-light.col-lg-7.d-flex.flex-column.flex-grow-1
#checkout{ data: subscription_data }
.pb-3.px-3.px-lg-7.col-lg-5.d-flex.flex-row.justify-content-center
#summary
#js-new-subscription{ data: subscription_data }
---
title: Make vulnerability file path linkable in the vulnerability list
merge_request: 55356
author:
type: changed
# frozen_string_literal: true
resource :subscriptions, only: [:new, :create] do
get :buy_minutes
get :payment_form
get :payment_method
......
......@@ -84,7 +84,7 @@ module Gitlab
# Returns true if load balancing is to be enabled.
def self.enable?
return false if program_name == 'rake' || Gitlab::Runtime.sidekiq?
return false if Gitlab::Runtime.rake? || Gitlab::Runtime.sidekiq?
return false unless self.configured?
true
......
......@@ -5,21 +5,39 @@ require 'spec_helper'
RSpec.describe SubscriptionsController do
let_it_be(:user) { create(:user) }
describe 'GET #new' do
subject { get :new, params: { plan_id: 'bronze_id' } }
shared_examples 'unauthenticated subscription request' do |redirect_from|
it { is_expected.to have_gitlab_http_status(:redirect) }
it { is_expected.to redirect_to new_user_registration_path(redirect_from: redirect_from) }
context 'with unauthenticated user' do
it { is_expected.to have_gitlab_http_status(:redirect) }
it { is_expected.to redirect_to new_user_registration_path(redirect_from: 'checkout') }
it 'stores subscription URL for later' do
subject
it 'stores subscription URL for later' do
subject
expected_subscription_path = new_subscriptions_path(plan_id: 'bronze_id') if redirect_from == 'checkout'
expected_subscription_path = buy_minutes_subscriptions_path(plan_id: 'bronze_id') if redirect_from == 'buy_minutes'
expected_subscription_path = new_subscriptions_path(plan_id: 'bronze_id')
expect(controller.stored_location_for(:user)).to eq(expected_subscription_path)
end
end
expect(controller.stored_location_for(:user)).to eq(expected_subscription_path)
describe 'GET #new' do
subject { get :new, params: { plan_id: 'bronze_id' } }
it_behaves_like 'unauthenticated subscription request', 'checkout'
context 'with authenticated user' do
before do
sign_in(user)
end
it { is_expected.to render_template 'layouts/checkout' }
it { is_expected.to render_template :new }
end
end
describe 'GET #buy_minutes' do
subject { get :buy_minutes, params: { plan_id: 'bronze_id' } }
it_behaves_like 'unauthenticated subscription request', 'buy_minutes'
context 'with authenticated user' do
before do
......@@ -27,7 +45,16 @@ RSpec.describe SubscriptionsController do
end
it { is_expected.to render_template 'layouts/checkout' }
it { is_expected.to render_template :new }
it { is_expected.to render_template :buy_minutes }
end
context 'with :new_route_ci_minutes_purchase disabled' do
before do
sign_in(user)
stub_feature_flags(new_route_ci_minutes_purchase: false)
end
it { is_expected.to have_gitlab_http_status(:not_found) }
end
end
......
......@@ -58,6 +58,8 @@ export const generateVulnerabilities = () => [
location: {
file: 'src/main/java/com/gitlab/security_products/tests/App.java',
startLine: '1337',
blobPath:
'/gitlab-org/security-reports2/-/blob/e5c61e4d5d0b8418011171def04ca0aa36532621/src/main/java/com/gitlab/security_products/tests/App.java',
},
project: {
nameWithNamespace: 'Administrator / Vulnerability reports',
......
......@@ -146,7 +146,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
end
it 'returns false when running inside a Rake task' do
expect(described_class).to receive(:program_name).and_return('rake')
allow(Gitlab::Runtime).to receive(:rake?).and_return(true)
expect(described_class.enable?).to eq(false)
end
......
# frozen_string_literal: true
RSpec.shared_examples_for 'subscription form data' do |js_selector|
before do
allow(view).to receive(:subscription_data).and_return(
setup_for_company: 'true',
full_name: 'First Last',
plan_data: '[{"id":"bronze_id","code":"bronze","price_per_year":48.0}]',
plan_id: 'bronze_id'
)
end
subject { render }
it { is_expected.to have_selector("#{js_selector}[data-setup-for-company='true']") }
it { is_expected.to have_selector("#{js_selector}[data-full-name='First Last']") }
it { is_expected.to have_selector("#{js_selector}[data-plan-data='[{\"id\":\"bronze_id\",\"code\":\"bronze\",\"price_per_year\":48.0}]']") }
it { is_expected.to have_selector("#{js_selector}[data-plan-id='bronze_id']") }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'subscriptions/buy_minutes' do
it_behaves_like 'subscription form data', '#js-buy-minutes'
end
......@@ -3,19 +3,5 @@
require 'spec_helper'
RSpec.describe 'subscriptions/new' do
before do
allow(view).to receive(:subscription_data).and_return(
setup_for_company: 'true',
full_name: 'First Last',
plan_data: '[{"id":"bronze_id","code":"bronze","price_per_year":48.0}]',
plan_id: 'bronze_id'
)
end
subject { render }
it { is_expected.to have_selector("#checkout[data-setup-for-company='true']") }
it { is_expected.to have_selector("#checkout[data-full-name='First Last']") }
it { is_expected.to have_selector("#checkout[data-plan-data='[{\"id\":\"bronze_id\",\"code\":\"bronze\",\"price_per_year\":48.0}]']") }
it { is_expected.to have_selector("#checkout[data-plan-id='bronze_id']") }
it_behaves_like 'subscription form data', '#js-new-subscription'
end
......@@ -199,10 +199,7 @@ module API
user_project = find_project_with_access(params)
merge_requests = authorized_merge_requests_for_project(user_project)
if Feature.enabled?(:api_v3_repos_events_optimization, user_project)
merge_requests = merge_requests.preload(:author, :assignees, :metrics, source_project: :namespace, target_project: :namespace)
end
merge_requests = merge_requests.preload(:author, :assignees, :metrics, source_project: :namespace, target_project: :namespace)
present paginate(merge_requests), with: ::API::Github::Entities::PullRequestEvent
end
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment