Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a0fdcfcdd5
commit
24d67ec554
2
Gemfile
2
Gemfile
|
@ -466,7 +466,7 @@ gem 'benchmark-memory', '~> 0.1', require: false
|
|||
gem 'activerecord-explain-analyze', '~> 0.1', require: false
|
||||
|
||||
# OAuth
|
||||
gem 'oauth2', '~> 1.4'
|
||||
gem 'oauth2', '~> 2.0'
|
||||
|
||||
# Health check
|
||||
gem 'health_check', '~> 3.0'
|
||||
|
|
12
Gemfile.lock
12
Gemfile.lock
|
@ -826,12 +826,13 @@ GEM
|
|||
shellany (~> 0.0)
|
||||
numerizer (0.2.0)
|
||||
oauth (0.5.6)
|
||||
oauth2 (1.4.7)
|
||||
faraday (>= 0.8, < 2.0)
|
||||
oauth2 (2.0.3)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
jwt (>= 1.0, < 3.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
rash_alt (>= 0.4, < 1)
|
||||
version_gem (~> 1.0)
|
||||
octokit (4.20.0)
|
||||
faraday (>= 0.9)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
|
@ -1050,6 +1051,8 @@ GEM
|
|||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
randexp (0.1.7)
|
||||
rash_alt (0.4.12)
|
||||
hashie (>= 3.4)
|
||||
rb-fsevent (0.10.4)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
|
@ -1408,6 +1411,7 @@ GEM
|
|||
validates_hostname (1.0.11)
|
||||
activerecord (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
version_gem (1.0.0)
|
||||
version_sorter (2.2.4)
|
||||
view_component (2.50.0)
|
||||
activesupport (>= 5.0.0, < 8.0)
|
||||
|
@ -1612,7 +1616,7 @@ DEPENDENCIES
|
|||
net-ldap (~> 0.16.3)
|
||||
net-ntp
|
||||
nokogiri (~> 1.13.6)
|
||||
oauth2 (~> 1.4)
|
||||
oauth2 (~> 2.0)
|
||||
octokit (~> 4.15)
|
||||
ohai (~> 16.10)
|
||||
oj (~> 3.10.6)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<script>
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
name: 'IncludedInTrialIndicator',
|
||||
i18n: {
|
||||
trialOnly: s__('LearnGitlab|- Included in trial'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only">
|
||||
{{ $options.i18n.trialOnly }}
|
||||
</span>
|
||||
</template>
|
|
@ -38,14 +38,16 @@ export default {
|
|||
actionsData: this.actions,
|
||||
};
|
||||
},
|
||||
maxValue: Object.keys(ACTION_LABELS).length,
|
||||
actionSections: Object.keys(ACTION_SECTIONS),
|
||||
computed: {
|
||||
maxValue() {
|
||||
return Object.keys(this.actionsData).length;
|
||||
},
|
||||
progressValue() {
|
||||
return Object.values(this.actionsData).filter((a) => a.completed).length;
|
||||
},
|
||||
progressPercentage() {
|
||||
return Math.round((this.progressValue / this.$options.maxValue) * 100);
|
||||
return Math.round((this.progressValue / this.maxValue) * 100);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
@ -125,7 +127,7 @@ export default {
|
|||
<template #percentSymbol>%</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<gl-progress-bar :value="progressValue" :max="$options.maxValue" />
|
||||
<gl-progress-bar :value="progressValue" :max="maxValue" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
<script>
|
||||
import { GlLink, GlCard, GlIcon } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
name: 'LearnGitlabInfoCard',
|
||||
components: { GlLink, GlCard, GlIcon },
|
||||
i18n: {
|
||||
trial: s__('Learn GitLab|Trial only'),
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
description: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
actionLabel: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
url: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
completed: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
},
|
||||
svg: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
trialRequired: {
|
||||
default: false,
|
||||
required: false,
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-card class="gl-pt-0">
|
||||
<div class="gl-text-right gl-h-5">
|
||||
<gl-icon
|
||||
v-if="completed"
|
||||
name="check-circle-filled"
|
||||
class="gl-text-green-500"
|
||||
:size="16"
|
||||
data-testid="completed-icon"
|
||||
/>
|
||||
<span
|
||||
v-else-if="trialRequired"
|
||||
class="gl-text-gray-500 gl-font-sm gl-font-style-italic"
|
||||
data-testid="trial-only"
|
||||
>{{ $options.i18n.trial }}</span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
|
||||
>
|
||||
<img :src="svg" :alt="actionLabel" />
|
||||
<h6>{{ title }}</h6>
|
||||
<p class="gl-font-sm gl-text-gray-700">{{ description }}</p>
|
||||
<gl-link :href="url" target="_blank" rel="noopener noreferrer" />
|
||||
</div>
|
||||
</gl-card>
|
||||
</template>
|
|
@ -6,6 +6,7 @@ import { isExperimentVariant } from '~/experimentation/utils';
|
|||
import eventHub from '~/invite_members/event_hub';
|
||||
import { s__, __ } from '~/locale';
|
||||
import { ACTION_LABELS } from '../constants';
|
||||
import IncludedInTrialIndicator from './included_in_trial_indicator.vue';
|
||||
|
||||
export default {
|
||||
name: 'LearnGitlabSectionLink',
|
||||
|
@ -15,12 +16,12 @@ export default {
|
|||
GlButton,
|
||||
GlPopover,
|
||||
GitlabExperiment,
|
||||
IncludedInTrialIndicator,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip,
|
||||
},
|
||||
i18n: {
|
||||
trialOnly: s__('LearnGitlab|Trial only'),
|
||||
contactAdmin: s__('LearnGitlab|Contact your administrator to start a free Ultimate trial.'),
|
||||
viewAdminList: s__('LearnGitlab|View administrator list'),
|
||||
watchHow: __('Watch how'),
|
||||
|
@ -41,12 +42,6 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
linkTitle() {
|
||||
return ACTION_LABELS[this.action].title;
|
||||
},
|
||||
trialOnly() {
|
||||
return ACTION_LABELS[this.action].trialRequired;
|
||||
},
|
||||
showInviteModalLink() {
|
||||
return (
|
||||
this.action === 'userAdded' && isExperimentVariant('invite_for_help_continuous_onboarding')
|
||||
|
@ -55,49 +50,51 @@ export default {
|
|||
openInNewTab() {
|
||||
return ACTION_LABELS[this.action]?.openInNewTab === true || this.value.openInNewTab === true;
|
||||
},
|
||||
linkToVideoTutorial() {
|
||||
return ACTION_LABELS[this.action].videoTutorial;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openModal() {
|
||||
eventHub.$emit('openModal', { source: 'learn_gitlab' });
|
||||
},
|
||||
actionLabelValue(value) {
|
||||
return ACTION_LABELS[this.action][value];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="gl-mb-4">
|
||||
<div v-if="trialOnly" class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only">
|
||||
{{ $options.i18n.trialOnly }}
|
||||
</div>
|
||||
<div class="flex align-items-center">
|
||||
<span v-if="value.completed" class="gl-text-green-500">
|
||||
<gl-icon name="check-circle-filled" :size="16" data-testid="completed-icon" />
|
||||
{{ linkTitle }}
|
||||
{{ actionLabelValue('title') }}
|
||||
<included-in-trial-indicator v-if="actionLabelValue('trialRequired')" />
|
||||
</span>
|
||||
<gl-link
|
||||
v-else-if="showInviteModalLink"
|
||||
data-track-action="click_link"
|
||||
:data-track-label="linkTitle"
|
||||
data-track-property="Growth::Activation::Experiment::InviteForHelpContinuousOnboarding"
|
||||
data-testid="invite-for-help-continuous-onboarding-experiment-link"
|
||||
@click="openModal"
|
||||
>
|
||||
{{ linkTitle }}
|
||||
</gl-link>
|
||||
<gl-link
|
||||
v-else-if="value.enabled"
|
||||
:target="openInNewTab ? '_blank' : '_self'"
|
||||
:href="value.url"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
:data-track-label="linkTitle"
|
||||
>
|
||||
{{ linkTitle }}
|
||||
</gl-link>
|
||||
<div v-else-if="showInviteModalLink">
|
||||
<gl-link
|
||||
data-track-action="click_link"
|
||||
:data-track-label="actionLabelValue('trackLabel')"
|
||||
data-track-property="Growth::Activation::Experiment::InviteForHelpContinuousOnboarding"
|
||||
data-testid="invite-for-help-continuous-onboarding-experiment-link"
|
||||
@click="openModal"
|
||||
>{{ actionLabelValue('title') }}</gl-link
|
||||
>
|
||||
|
||||
<included-in-trial-indicator v-if="actionLabelValue('trialRequired')" />
|
||||
</div>
|
||||
<div v-else-if="value.enabled">
|
||||
<gl-link
|
||||
:target="openInNewTab ? '_blank' : '_self'"
|
||||
:href="value.url"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
:data-track-label="actionLabelValue('trackLabel')"
|
||||
>{{ actionLabelValue('title') }}</gl-link
|
||||
>
|
||||
|
||||
<included-in-trial-indicator v-if="actionLabelValue('trialRequired')" />
|
||||
</div>
|
||||
<template v-else>
|
||||
<div data-testid="disabled-learn-gitlab-link">{{ linkTitle }}</div>
|
||||
<div data-testid="disabled-learn-gitlab-link">{{ actionLabelValue('title') }}</div>
|
||||
<gl-button
|
||||
:id="popoverId"
|
||||
category="tertiary"
|
||||
|
@ -127,19 +124,19 @@ export default {
|
|||
<template #control></template>
|
||||
<template #candidate>
|
||||
<gl-button
|
||||
v-if="linkToVideoTutorial"
|
||||
v-if="actionLabelValue('videoTutorial')"
|
||||
v-gl-tooltip
|
||||
category="tertiary"
|
||||
icon="live-preview"
|
||||
:title="$options.i18n.watchHow"
|
||||
:aria-label="$options.i18n.watchHow"
|
||||
:href="linkToVideoTutorial"
|
||||
:href="actionLabelValue('videoTutorial')"
|
||||
target="_blank"
|
||||
class="ml-auto"
|
||||
size="small"
|
||||
data-testid="video-tutorial-link"
|
||||
data-track-action="click_video_link"
|
||||
:data-track-label="linkTitle"
|
||||
:data-track-label="actionLabelValue('trackLabel')"
|
||||
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
|
||||
data-track-experiment="video_tutorials_continuous_onboarding"
|
||||
/>
|
||||
|
|
|
@ -2,9 +2,10 @@ import { s__ } from '~/locale';
|
|||
|
||||
export const ACTION_LABELS = {
|
||||
gitWrite: {
|
||||
title: s__('LearnGitLab|Create or import a repository'),
|
||||
actionLabel: s__('LearnGitLab|Create or import a repository'),
|
||||
title: s__('LearnGitLab|Create a repository'),
|
||||
actionLabel: s__('LearnGitLab|Create a repository'),
|
||||
description: s__('LearnGitLab|Create or import your first repository into your new project.'),
|
||||
trackLabel: 'create_a_repository',
|
||||
section: 'workspace',
|
||||
position: 1,
|
||||
},
|
||||
|
@ -14,20 +15,23 @@ export const ACTION_LABELS = {
|
|||
description: s__(
|
||||
'LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features.',
|
||||
),
|
||||
trackLabel: 'invite_your_colleagues',
|
||||
section: 'workspace',
|
||||
position: 0,
|
||||
},
|
||||
pipelineCreated: {
|
||||
title: s__('LearnGitLab|Set up CI/CD'),
|
||||
actionLabel: s__('LearnGitLab|Set-up CI/CD'),
|
||||
title: s__("LearnGitLab|Set up your first project's CI/CD"),
|
||||
actionLabel: s__('LearnGitLab|Set up CI/CD'),
|
||||
description: s__('LearnGitLab|Save time by automating your integration and deployment tasks.'),
|
||||
trackLabel: 'set_up_your_first_project_s_ci_cd',
|
||||
section: 'workspace',
|
||||
position: 2,
|
||||
},
|
||||
trialStarted: {
|
||||
title: s__('LearnGitLab|Start a free Ultimate trial'),
|
||||
title: s__('LearnGitLab|Start a free trial of GitLab Ultimate'),
|
||||
actionLabel: s__('LearnGitLab|Try GitLab Ultimate for free'),
|
||||
description: s__('LearnGitLab|Try all GitLab features for 30 days, no credit card required.'),
|
||||
trackLabel: 'start_a_free_trial_of_gitlab_ultimate',
|
||||
section: 'workspace',
|
||||
position: 3,
|
||||
openInNewTab: true,
|
||||
|
@ -38,6 +42,7 @@ export const ACTION_LABELS = {
|
|||
description: s__(
|
||||
'LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths.',
|
||||
),
|
||||
trackLabel: 'add_code_owners',
|
||||
trialRequired: true,
|
||||
section: 'workspace',
|
||||
position: 4,
|
||||
|
@ -45,9 +50,10 @@ export const ACTION_LABELS = {
|
|||
videoTutorial: 'https://vimeo.com/670896787',
|
||||
},
|
||||
requiredMrApprovalsEnabled: {
|
||||
title: s__('LearnGitLab|Add merge request approval'),
|
||||
title: s__('LearnGitLab|Enable require merge approvals'),
|
||||
actionLabel: s__('LearnGitLab|Enable require merge approvals'),
|
||||
description: s__('LearnGitLab|Route code reviews to the right reviewers, every time.'),
|
||||
trackLabel: 'enable_require_merge_approvals',
|
||||
trialRequired: true,
|
||||
section: 'workspace',
|
||||
position: 5,
|
||||
|
@ -55,28 +61,52 @@ export const ACTION_LABELS = {
|
|||
videoTutorial: 'https://vimeo.com/670904904',
|
||||
},
|
||||
mergeRequestCreated: {
|
||||
title: s__('LearnGitLab|Submit a merge request'),
|
||||
title: s__('LearnGitLab|Submit a merge request (MR)'),
|
||||
actionLabel: s__('LearnGitLab|Submit a merge request (MR)'),
|
||||
description: s__('LearnGitLab|Review and edit proposed changes to source code.'),
|
||||
trackLabel: 'submit_a_merge_request_mr',
|
||||
section: 'plan',
|
||||
position: 1,
|
||||
},
|
||||
securityScanEnabled: {
|
||||
title: s__('LearnGitLab|Run a Security scan using CI/CD'),
|
||||
actionLabel: s__('LearnGitLab|Run a Security scan using CI/CD'),
|
||||
description: s__('LearnGitLab|Scan your code to uncover vulnerabilities before deploying.'),
|
||||
section: 'deploy',
|
||||
position: 1,
|
||||
},
|
||||
issueCreated: {
|
||||
title: s__('LearnGitLab|Create an issue'),
|
||||
actionLabel: s__('LearnGitLab|Create an issue'),
|
||||
description: s__(
|
||||
'LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work.',
|
||||
),
|
||||
trackLabel: 'create_an_issue',
|
||||
section: 'plan',
|
||||
position: 0,
|
||||
},
|
||||
securityScanEnabled: {
|
||||
title: s__('LearnGitLab|Run a Security scan using CI/CD'),
|
||||
actionLabel: s__('LearnGitLab|Run a Security scan using CI/CD'),
|
||||
description: s__('LearnGitLab|Scan your code to uncover vulnerabilities before deploying.'),
|
||||
trackLabel: 'run_a_security_scan_using_ci_cd',
|
||||
section: 'deploy',
|
||||
position: 1,
|
||||
},
|
||||
licenseScanningRun: {
|
||||
title: s__('LearnGitLab|Scan dependencies for licenses'),
|
||||
trackLabel: 'scan_dependencies_for_licenses',
|
||||
trialRequired: true,
|
||||
section: 'deploy',
|
||||
position: 2,
|
||||
},
|
||||
secureDependencyScanningRun: {
|
||||
title: s__('LearnGitLab|Scan dependencies for vulnerabilities'),
|
||||
trackLabel: 'scan_dependencies_for_vulnerabilities',
|
||||
trialRequired: true,
|
||||
section: 'deploy',
|
||||
position: 3,
|
||||
},
|
||||
secureDastRun: {
|
||||
title: s__('LearnGitLab|Analyze your application for vulnerabilities with DAST'),
|
||||
trackLabel: 'analyze_your_application_for_vulnerabilities_with_dast',
|
||||
trialRequired: true,
|
||||
section: 'deploy',
|
||||
position: 4,
|
||||
},
|
||||
};
|
||||
|
||||
export const ACTION_SECTIONS = {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||
import createTestReportsStore from '../../stores/test_reports';
|
||||
import EmptyState from './empty_state.vue';
|
||||
import TestSuiteTable from './test_suite_table.vue';
|
||||
import TestSummary from './test_summary.vue';
|
||||
|
@ -15,9 +16,10 @@ export default {
|
|||
TestSummary,
|
||||
TestSummaryTable,
|
||||
},
|
||||
inject: ['blobPath', 'summaryEndpoint', 'suiteEndpoint'],
|
||||
computed: {
|
||||
...mapState(['isLoading', 'selectedSuiteIndex', 'testReports']),
|
||||
...mapGetters(['getSelectedSuite']),
|
||||
...mapState('testReports', ['isLoading', 'selectedSuiteIndex', 'testReports']),
|
||||
...mapGetters('testReports', ['getSelectedSuite']),
|
||||
showSuite() {
|
||||
return this.selectedSuiteIndex !== null;
|
||||
},
|
||||
|
@ -27,10 +29,19 @@ export default {
|
|||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.registerModule(
|
||||
'testReports',
|
||||
createTestReportsStore({
|
||||
blobPath: this.blobPath,
|
||||
summaryEndpoint: this.summaryEndpoint,
|
||||
suiteEndpoint: this.suiteEndpoint,
|
||||
}),
|
||||
);
|
||||
|
||||
this.fetchSummary();
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
...mapActions('testReports', [
|
||||
'fetchTestSuite',
|
||||
'fetchSummary',
|
||||
'setSelectedSuiteIndex',
|
||||
|
|
|
@ -51,14 +51,18 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState(['pageInfo']),
|
||||
...mapGetters(['getSuiteTests', 'getSuiteTestCount', 'getSuiteArtifactsExpired']),
|
||||
...mapState('testReports', ['pageInfo']),
|
||||
...mapGetters('testReports', [
|
||||
'getSuiteTests',
|
||||
'getSuiteTestCount',
|
||||
'getSuiteArtifactsExpired',
|
||||
]),
|
||||
hasSuites() {
|
||||
return this.getSuiteTests.length > 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setPage']),
|
||||
...mapActions('testReports', ['setPage']),
|
||||
},
|
||||
wrapSymbols: ['::', '#', '.', '_', '-', '/', '\\'],
|
||||
i18n,
|
||||
|
|
|
@ -19,7 +19,7 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['getTestSuites']),
|
||||
...mapGetters('testReports', ['getTestSuites']),
|
||||
hasSuites() {
|
||||
return this.getTestSuites.length > 0;
|
||||
},
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import Translate from '~/vue_shared/translate';
|
||||
import TestReports from './components/test_reports/test_reports.vue';
|
||||
import createTestReportsStore from './stores/test_reports';
|
||||
|
||||
Vue.use(Vuex);
|
||||
Vue.use(Translate);
|
||||
|
||||
export const createTestDetails = (selector) => {
|
||||
|
@ -16,11 +17,6 @@ export const createTestDetails = (selector) => {
|
|||
suiteEndpoint,
|
||||
artifactsExpiredImagePath,
|
||||
} = el?.dataset || {};
|
||||
const testReportsStore = createTestReportsStore({
|
||||
blobPath,
|
||||
summaryEndpoint,
|
||||
suiteEndpoint,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
|
@ -32,8 +28,11 @@ export const createTestDetails = (selector) => {
|
|||
emptyStateImagePath,
|
||||
artifactsExpiredImagePath,
|
||||
hasTestReport: parseBoolean(hasTestReport),
|
||||
blobPath,
|
||||
summaryEndpoint,
|
||||
suiteEndpoint,
|
||||
},
|
||||
store: testReportsStore,
|
||||
store: new Vuex.Store(),
|
||||
render(createElement) {
|
||||
return createElement('test-reports');
|
||||
},
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import * as actions from './actions';
|
||||
import * as getters from './getters';
|
||||
import mutations from './mutations';
|
||||
import state from './state';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export default (initialState) =>
|
||||
new Vuex.Store({
|
||||
export default (initialState) => {
|
||||
return {
|
||||
namespaced: true,
|
||||
actions,
|
||||
getters,
|
||||
mutations,
|
||||
state: state(initialState),
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -206,6 +206,7 @@ export default {
|
|||
<template #features>
|
||||
<feature-card
|
||||
v-for="feature in augmentedSecurityFeatures"
|
||||
:id="feature.anchor"
|
||||
:key="feature.type"
|
||||
data-testid="security-testing-card"
|
||||
:feature="feature"
|
||||
|
|
|
@ -194,6 +194,7 @@ export const securityFeatures = [
|
|||
helpPath: DAST_HELP_PATH,
|
||||
configurationHelpPath: DAST_CONFIG_HELP_PATH,
|
||||
type: REPORT_TYPE_DAST,
|
||||
anchor: 'dast',
|
||||
},
|
||||
{
|
||||
name: DEPENDENCY_SCANNING_NAME,
|
||||
|
@ -201,6 +202,7 @@ export const securityFeatures = [
|
|||
helpPath: DEPENDENCY_SCANNING_HELP_PATH,
|
||||
configurationHelpPath: DEPENDENCY_SCANNING_CONFIG_HELP_PATH,
|
||||
type: REPORT_TYPE_DEPENDENCY_SCANNING,
|
||||
anchor: 'dependency-scanning',
|
||||
},
|
||||
{
|
||||
name: CONTAINER_SCANNING_NAME,
|
||||
|
|
|
@ -53,7 +53,9 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
|||
|
||||
def set_index_vars
|
||||
@applications = current_user.oauth_applications.load
|
||||
@authorized_tokens = current_user.oauth_authorized_tokens.preload(:application).order(created_at: :desc).load # rubocop: disable CodeReuse/ActiveRecord
|
||||
@authorized_tokens = current_user.oauth_authorized_tokens
|
||||
.latest_per_application
|
||||
.preload_application
|
||||
|
||||
# Don't overwrite a value possibly set by `create`
|
||||
@application ||= Doorkeeper::Application.new
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SecurityActionsContinuousOnboardingExperiment < ApplicationExperiment
|
||||
def control_behavior
|
||||
end
|
||||
|
||||
def candidate_behavior
|
||||
end
|
||||
end
|
|
@ -216,7 +216,7 @@ module IntegrationsHelper
|
|||
end
|
||||
|
||||
def fields_for_integration(integration)
|
||||
Integrations::FieldSerializer.new(integration: integration).represent(integration.global_fields).to_json
|
||||
Integrations::FieldSerializer.new(integration: integration).represent(integration.form_fields).to_json
|
||||
end
|
||||
|
||||
def integration_level(integration)
|
||||
|
|
|
@ -4,6 +4,7 @@ module LearnGitlabHelper
|
|||
IMAGE_PATH_PLAN = "learn_gitlab/section_plan.svg"
|
||||
IMAGE_PATH_DEPLOY = "learn_gitlab/section_deploy.svg"
|
||||
IMAGE_PATH_WORKSPACE = "learn_gitlab/section_workspace.svg"
|
||||
LICENSE_SCANNING_RUN_URL = 'https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html'
|
||||
|
||||
def learn_gitlab_enabled?(project)
|
||||
return false unless current_user
|
||||
|
@ -64,7 +65,7 @@ module LearnGitlabHelper
|
|||
git_write: project_path(project),
|
||||
merge_request_created: project_merge_requests_path(project),
|
||||
user_added: project_members_url(project),
|
||||
security_scan_enabled: project_security_configuration_path(project)
|
||||
**deploy_section_action_urls(project)
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -72,6 +73,23 @@ module LearnGitlabHelper
|
|||
LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }
|
||||
end
|
||||
|
||||
def deploy_section_action_urls(project)
|
||||
experiment(:security_actions_continuous_onboarding,
|
||||
namespace: project.namespace,
|
||||
user: current_user,
|
||||
sticky_to: current_user
|
||||
) do |e|
|
||||
e.control { { security_scan_enabled: project_security_configuration_path(project) } }
|
||||
e.candidate do
|
||||
{
|
||||
license_scanning_run: LICENSE_SCANNING_RUN_URL,
|
||||
secure_dependency_scanning_run: project_security_configuration_path(project, anchor: 'dependency-scanning'),
|
||||
secure_dast_run: project_security_configuration_path(project, anchor: 'dast')
|
||||
}
|
||||
end
|
||||
end.run
|
||||
end
|
||||
|
||||
def learn_gitlab_project
|
||||
@learn_gitlab_project ||= LearnGitlab::Project.new(current_user).project
|
||||
end
|
||||
|
|
|
@ -29,10 +29,6 @@ module Ci
|
|||
return_exit_code: -> (build) { build.exit_codes_defined? }
|
||||
}.freeze
|
||||
|
||||
DEFAULT_RETRIES = {
|
||||
scheduler_failure: 2
|
||||
}.freeze
|
||||
|
||||
DEGRADATION_THRESHOLD_VARIABLE_NAME = 'DEGRADATION_THRESHOLD'
|
||||
RUNNERS_STATUS_CACHE_EXPIRATION = 1.minute
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@ module Ci
|
|||
DEFAULT_CONFIG_PATH = CONFIG_EXTENSION
|
||||
CANCELABLE_STATUSES = (Ci::HasStatus::CANCELABLE_STATUSES + ['manual']).freeze
|
||||
|
||||
BridgeStatusError = Class.new(StandardError)
|
||||
|
||||
paginates_per 15
|
||||
|
||||
sha_attribute :source_sha
|
||||
|
|
|
@ -505,8 +505,8 @@ class Integration < ApplicationRecord
|
|||
fields.reject { _1[:type] == 'password' }.pluck(:name)
|
||||
end
|
||||
|
||||
def global_fields
|
||||
fields
|
||||
def form_fields
|
||||
fields.reject { _1[:api_only] == true }
|
||||
end
|
||||
|
||||
def configurable_events
|
||||
|
|
|
@ -139,8 +139,8 @@ module Integrations
|
|||
supported_events.map { |event| event_channel_name(event) }
|
||||
end
|
||||
|
||||
def global_fields
|
||||
fields.reject { |field| field[:name].end_with?('channel') }
|
||||
def form_fields
|
||||
super.reject { |field| field[:name].end_with?('channel') }
|
||||
end
|
||||
|
||||
def default_channel_placeholder
|
||||
|
|
|
@ -71,11 +71,12 @@ module Integrations
|
|||
non_empty_password_help: -> { s_('JiraService|Leave blank to use your current password or API token.') },
|
||||
help: -> { s_('JiraService|Use a password for server version and an API token for cloud version.') }
|
||||
|
||||
field :jira_issue_transition_id, api_only: true
|
||||
|
||||
# TODO: we can probably just delegate as part of
|
||||
# https://gitlab.com/gitlab-org/gitlab/issues/29404
|
||||
# These fields are API only, so no field definition is required.
|
||||
data_field :jira_issue_transition_automatic
|
||||
data_field :jira_issue_transition_id
|
||||
data_field :project_key
|
||||
data_field :issues_enabled
|
||||
data_field :vulnerabilities_enabled
|
||||
|
|
|
@ -7,6 +7,8 @@ class OauthAccessToken < Doorkeeper::AccessToken
|
|||
alias_attribute :user, :resource_owner
|
||||
|
||||
scope :distinct_resource_owner_counts, ->(applications) { where(application: applications).distinct.group(:application_id).count(:resource_owner_id) }
|
||||
scope :latest_per_application, -> { select('distinct on(application_id) *').order(application_id: :desc, created_at: :desc) }
|
||||
scope :preload_application, -> { preload(:application) }
|
||||
|
||||
def scopes=(value)
|
||||
if value.is_a?(Array)
|
||||
|
|
|
@ -1626,7 +1626,7 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
def oauth_authorized_tokens
|
||||
Doorkeeper::AccessToken.where(resource_owner_id: id, revoked_at: nil)
|
||||
OauthAccessToken.where(resource_owner_id: id, revoked_at: nil)
|
||||
end
|
||||
|
||||
# Returns the projects a user contributed to in the last year.
|
||||
|
|
|
@ -10,24 +10,12 @@ module Ci
|
|||
return pull_request_not_open_error unless pull_request.open?
|
||||
return pull_request_branch_error unless pull_request.actual_branch_head?
|
||||
|
||||
create_pipeline_for(pull_request)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_pipeline_for(pull_request)
|
||||
Ci::ExternalPullRequests::CreatePipelineWorker.perform_async(
|
||||
project.id, current_user.id, pull_request.id
|
||||
)
|
||||
end
|
||||
|
||||
def create_params(pull_request)
|
||||
{
|
||||
ref: pull_request.source_ref,
|
||||
source_sha: pull_request.source_sha,
|
||||
target_sha: pull_request.target_sha
|
||||
}
|
||||
end
|
||||
private
|
||||
|
||||
def pull_request_not_open_error
|
||||
ServiceResponse.error(message: 'The pull request is not opened', payload: nil)
|
||||
|
|
|
@ -5,8 +5,6 @@ module Ci
|
|||
class CreateService < ::BaseService
|
||||
include Gitlab::Utils::UsageData
|
||||
|
||||
ArtifactsExistError = Class.new(StandardError)
|
||||
|
||||
LSIF_ARTIFACT_TYPE = 'lsif'
|
||||
METRICS_REPORT_UPLOAD_EVENT_NAME = 'i_testing_metrics_report_artifact_uploaders'
|
||||
|
||||
|
@ -74,10 +72,6 @@ module Ci
|
|||
Ci::JobArtifact.max_artifact_size(type: type, project: project)
|
||||
end
|
||||
|
||||
def forbidden_type_error(type)
|
||||
error("#{type} artifacts are forbidden", :forbidden)
|
||||
end
|
||||
|
||||
def too_large_error
|
||||
error('file size has reached maximum size limit', :payload_too_large)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: security_actions_continuous_onboarding
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82274
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345176
|
||||
milestone: '15.2'
|
||||
type: experiment
|
||||
group: group::acquisition
|
||||
default_enabled: false
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPartialIndexOnOauthAccessTokensRevokedAtWithOrder < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'partial_index_user_id_app_id_created_at_token_not_revoked'
|
||||
EXISTING_INDEX_NAME = 'partial_index_resource_owner_id_created_at_token_not_revoked'
|
||||
|
||||
def up
|
||||
add_concurrent_index :oauth_access_tokens, [:resource_owner_id, :application_id, :created_at],
|
||||
name: INDEX_NAME, where: 'revoked_at IS NULL'
|
||||
remove_concurrent_index :oauth_access_tokens, [:resource_owner_id, :created_at], name: EXISTING_INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :oauth_access_tokens, [:resource_owner_id, :created_at],
|
||||
name: EXISTING_INDEX_NAME, where: 'revoked_at IS NULL'
|
||||
remove_concurrent_index :oauth_access_tokens, [:resource_owner_id, :application_id, :created_at], name: INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
5b12e0fbebef2979cfc31aab16ce78988a2f94662dbe1048791413347edb3c99
|
|
@ -30172,14 +30172,14 @@ CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON depl
|
|||
|
||||
CREATE INDEX partial_index_deployments_for_project_id_and_tag ON deployments USING btree (project_id) WHERE (tag IS TRUE);
|
||||
|
||||
CREATE INDEX partial_index_resource_owner_id_created_at_token_not_revoked ON oauth_access_tokens USING btree (resource_owner_id, created_at) WHERE (revoked_at IS NULL);
|
||||
|
||||
CREATE INDEX partial_index_slack_integrations_with_bot_user_id ON slack_integrations USING btree (id) WHERE (bot_user_id IS NOT NULL);
|
||||
|
||||
CREATE UNIQUE INDEX partial_index_sop_configs_on_namespace_id ON security_orchestration_policy_configurations USING btree (namespace_id) WHERE (namespace_id IS NOT NULL);
|
||||
|
||||
CREATE UNIQUE INDEX partial_index_sop_configs_on_project_id ON security_orchestration_policy_configurations USING btree (project_id) WHERE (project_id IS NOT NULL);
|
||||
|
||||
CREATE INDEX partial_index_user_id_app_id_created_at_token_not_revoked ON oauth_access_tokens USING btree (resource_owner_id, application_id, created_at) WHERE (revoked_at IS NULL);
|
||||
|
||||
CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_and_note_id_index ON snippet_user_mentions USING btree (snippet_id, note_id);
|
||||
|
||||
CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON snippet_user_mentions USING btree (snippet_id) WHERE (note_id IS NULL);
|
||||
|
|
|
@ -148,6 +148,7 @@ This method should return an array of hashes for each field, where the keys can
|
|||
| `title:` | string | false | Capitalized value of `name:` | The label for the form field.
|
||||
| `placeholder:` | string | false | | A placeholder for the form field.
|
||||
| `help:` | string | false | | A help text that displays below the form field.
|
||||
| `api_only:` | boolean | false | `false` | Specify if the field should only be available through the API, and excluded from the frontend form.
|
||||
|
||||
#### Additional keys for `type: 'checkbox'`
|
||||
|
||||
|
|
|
@ -61,3 +61,13 @@ before_action do
|
|||
push_licensed_feature(:feature_symbol, project)
|
||||
end
|
||||
```
|
||||
|
||||
## Allow use of licensed EE features
|
||||
|
||||
To enable plans per namespace turn on the `Allow use of licensed EE features` option from the settings page.
|
||||
This will make licensed EE features available to projects only if the project namespace's plan includes the feature
|
||||
or if the project is public. To enable it:
|
||||
|
||||
1. If you are developing locally, follow the steps in [simulate SaaS](ee_features.md#act-as-saas) to make the option available.
|
||||
1. Visit Admin > Settings > General > "Account and limit" and
|
||||
enabling "Allow use of licensed EE features".
|
||||
|
|
|
@ -86,7 +86,7 @@ To create an application for your GitLab instance:
|
|||
When creating application in the **Admin Area** , you can mark it as _trusted_.
|
||||
The user authorization step is automatically skipped for this application.
|
||||
|
||||
## Expiring access tokens
|
||||
## Access token expiration
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21745) in GitLab 14.3, with the ability to opt out.
|
||||
> - Ability to opt-out of expiring access token [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/340848) in GitLab 15.0.
|
||||
|
@ -97,12 +97,7 @@ in GitLab 14.3 and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/34084
|
|||
existing integrations must be updated to support access token refresh.
|
||||
|
||||
Access tokens expire in two hours which means that integrations that use them must support generating new access
|
||||
tokens at least every two hours. Existing:
|
||||
|
||||
- Applications can have expiring access tokens:
|
||||
1. Edit the application.
|
||||
1. Select **Expire access tokens**.
|
||||
- Tokens must be [revoked](../api/oauth2.md#revoke-a-token) or they don't expire.
|
||||
tokens at least every two hours.
|
||||
|
||||
When applications are deleted, all grants and tokens associated with the application are also deleted.
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ You can [check the status of existing migrations](../../../update/index.md#batch
|
|||
|
||||
## Enable or disable batched background migrations
|
||||
|
||||
WARNING:
|
||||
If you disable this feature flag, GitLab upgrades may fail.
|
||||
|
||||
Batched background migrations are under development but ready for production use.
|
||||
It is deployed behind a feature flag that is **enabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
|
||||
|
|
|
@ -34,7 +34,7 @@ To view value stream analytics for your project:
|
|||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Value stream**.
|
||||
1. To view metrics for each stage, above the **Filter results** text box, select a stage.
|
||||
1. To view metrics for a particular stage, select a stage below the **Filter results** text box.
|
||||
1. Optional. Filter the results:
|
||||
1. Select the **Filter results** text box.
|
||||
1. Select a parameter.
|
||||
|
|
|
@ -37,7 +37,7 @@ To view value stream analytics for your group:
|
|||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Analytics > Value stream**.
|
||||
1. To view metrics for each stage, above the **Filter results** text box, select a stage.
|
||||
1. To view metrics for a particular stage, select a stage below the **Filter results** text box.
|
||||
1. Optional. Filter the results:
|
||||
1. Select the **Filter results** text box.
|
||||
1. Select a parameter.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
module LearnGitlab
|
||||
class Onboarding
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include Gitlab::Experiment::Dsl
|
||||
|
||||
ACTION_ISSUE_IDS = {
|
||||
pipeline_created: 7,
|
||||
|
@ -15,12 +16,12 @@ module LearnGitlab
|
|||
:issue_created,
|
||||
:git_write,
|
||||
:merge_request_created,
|
||||
:user_added,
|
||||
:security_scan_enabled
|
||||
:user_added
|
||||
].freeze
|
||||
|
||||
def initialize(namespace)
|
||||
def initialize(namespace, current_user = nil)
|
||||
@namespace = namespace
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def completed_percentage
|
||||
|
@ -49,9 +50,20 @@ module LearnGitlab
|
|||
end
|
||||
|
||||
def tracked_actions
|
||||
ACTION_ISSUE_IDS.keys + ACTION_PATHS
|
||||
ACTION_ISSUE_IDS.keys + ACTION_PATHS + deploy_section_tracked_actions
|
||||
end
|
||||
|
||||
attr_reader :namespace
|
||||
def deploy_section_tracked_actions
|
||||
experiment(:security_actions_continuous_onboarding,
|
||||
namespace: namespace,
|
||||
user: current_user,
|
||||
sticky_to: current_user
|
||||
) do |e|
|
||||
e.control { [:security_scan_enabled] }
|
||||
e.candidate { [:license_scanning_run, :secure_dependency_scanning_run, :secure_dast_run] }
|
||||
end.run
|
||||
end
|
||||
|
||||
attr_reader :namespace, :current_user
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,10 @@ module Sidebars
|
|||
override :pill_count
|
||||
def pill_count
|
||||
strong_memoize(:pill_count) do
|
||||
percentage = LearnGitlab::Onboarding.new(context.project.namespace).completed_percentage
|
||||
percentage = LearnGitlab::Onboarding.new(
|
||||
context.project.namespace,
|
||||
context.current_user
|
||||
).completed_percentage
|
||||
|
||||
"#{percentage}%"
|
||||
end
|
||||
|
|
|
@ -22824,9 +22824,6 @@ msgstr ""
|
|||
msgid "Learn GitLab - Ultimate trial"
|
||||
msgstr ""
|
||||
|
||||
msgid "Learn GitLab|Trial only"
|
||||
msgstr ""
|
||||
|
||||
msgid "Learn More"
|
||||
msgstr ""
|
||||
|
||||
|
@ -22902,21 +22899,21 @@ msgstr ""
|
|||
msgid "LearnGitLab|Add code owners"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Add merge request approval"
|
||||
msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Create a repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Create an issue"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Create or import a repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Create or import your first repository into your new project."
|
||||
msgstr ""
|
||||
|
||||
|
@ -22959,22 +22956,25 @@ msgstr ""
|
|||
msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Scan dependencies for licenses"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Scan dependencies for vulnerabilities"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Set up CI/CD"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Set up your first project's CI/CD"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Set up your workspace"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Set-up CI/CD"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Start a free Ultimate trial"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Submit a merge request"
|
||||
msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitLab|Submit a merge request (MR)"
|
||||
|
@ -22992,6 +22992,9 @@ msgstr ""
|
|||
msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|- Included in trial"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|Contact your administrator to start a free Ultimate trial."
|
||||
msgstr ""
|
||||
|
||||
|
@ -23001,9 +23004,6 @@ msgstr ""
|
|||
msgid "LearnGitlab|Ok, let's go"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|Trial only"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|View administrator list"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -382,10 +382,17 @@ module QA
|
|||
#
|
||||
# @return [Regex]
|
||||
def created_by_pattern
|
||||
@created_by_pattern ||= /\n\n \*By gitlab-migration on \S+ \(imported from GitLab\)\*/
|
||||
@created_by_pattern ||= /\n\n \*By #{importer_username_pattern} on \S+ \(imported from GitLab\)\*/
|
||||
end
|
||||
|
||||
# Remove added prefixes and legacy diff format from comments
|
||||
# Username of importer user for removal from comments and descriptions
|
||||
#
|
||||
# @return [String]
|
||||
def importer_username_pattern
|
||||
@importer_username_pattern ||= ENV['QA_LARGE_IMPORT_USER_PATTERN'] || "(gitlab-migration|GitLab QA Bot)"
|
||||
end
|
||||
|
||||
# Remove added prefixes from comments
|
||||
#
|
||||
# @param [String] body
|
||||
# @return [String]
|
||||
|
|
|
@ -65,7 +65,7 @@ RSpec.describe Import::BitbucketController do
|
|||
.with(hash_including(
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => code,
|
||||
redirect_uri: users_import_bitbucket_callback_url),
|
||||
'redirect_uri' => users_import_bitbucket_callback_url),
|
||||
{})
|
||||
.and_return(access_token)
|
||||
stub_omniauth_provider('bitbucket')
|
||||
|
|
|
@ -45,10 +45,12 @@ RSpec.describe 'Profile > Applications' do
|
|||
let(:anonymous_token) { create(:oauth_access_token, resource_owner: user) }
|
||||
|
||||
context 'with multiple access token types and multiple owners' do
|
||||
let!(:token2) { create(:oauth_access_token, application: application, resource_owner: user) }
|
||||
let!(:other_user_token) { create(:oauth_access_token, application: application, resource_owner: other_user) }
|
||||
|
||||
before do
|
||||
token.update_column(:created_at, created_at)
|
||||
token2.update_column(:created_at, created_at - 1.day)
|
||||
anonymous_token.update_columns(application_id: nil, created_at: 1.day.ago)
|
||||
end
|
||||
|
||||
|
|
|
@ -85,8 +85,6 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
|
@ -105,7 +103,8 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
</svg>
|
||||
|
||||
Invite your colleagues
|
||||
|
||||
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
<!---->
|
||||
|
@ -114,8 +113,6 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
|
@ -133,8 +130,9 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
|
||||
Create or import a repository
|
||||
|
||||
Create a repository
|
||||
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
<!---->
|
||||
|
@ -143,48 +141,23 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Set up CI/CD"
|
||||
href="http://example.com/"
|
||||
target="_self"
|
||||
>
|
||||
|
||||
Set up CI/CD
|
||||
|
||||
</a>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Start a free Ultimate trial"
|
||||
href="http://example.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
Start a free Ultimate trial
|
||||
|
||||
</a>
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="set_up_your_first_project_s_ci_cd"
|
||||
href="http://example.com/"
|
||||
target="_self"
|
||||
>
|
||||
Set up your first project's CI/CD
|
||||
</a>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -192,31 +165,24 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<div
|
||||
class="gl-font-style-italic gl-text-gray-500"
|
||||
data-testid="trial-only"
|
||||
>
|
||||
|
||||
Trial only
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Add code owners"
|
||||
href="http://example.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
Add code owners
|
||||
|
||||
</a>
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="start_a_free_trial_of_gitlab_ultimate"
|
||||
href="http://example.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Start a free trial of GitLab Ultimate
|
||||
</a>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -225,30 +191,62 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
class="gl-mb-4"
|
||||
>
|
||||
<div
|
||||
class="gl-font-style-italic gl-text-gray-500"
|
||||
data-testid="trial-only"
|
||||
class="flex align-items-center"
|
||||
>
|
||||
|
||||
Trial only
|
||||
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="add_code_owners"
|
||||
href="http://example.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Add code owners
|
||||
</a>
|
||||
|
||||
<span
|
||||
class="gl-font-style-italic gl-text-gray-500"
|
||||
data-testid="trial-only"
|
||||
>
|
||||
|
||||
- Included in trial
|
||||
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Add merge request approval"
|
||||
href="http://example.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
Add merge request approval
|
||||
|
||||
</a>
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="enable_require_merge_approvals"
|
||||
href="http://example.com/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Enable require merge approvals
|
||||
</a>
|
||||
|
||||
<span
|
||||
class="gl-font-style-italic gl-text-gray-500"
|
||||
data-testid="trial-only"
|
||||
>
|
||||
|
||||
- Included in trial
|
||||
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -290,23 +288,23 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Create an issue"
|
||||
href="http://example.com/"
|
||||
target="_self"
|
||||
>
|
||||
|
||||
Create an issue
|
||||
|
||||
</a>
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="create_an_issue"
|
||||
href="http://example.com/"
|
||||
target="_self"
|
||||
>
|
||||
Create an issue
|
||||
</a>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -314,23 +312,23 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Submit a merge request"
|
||||
href="http://example.com/"
|
||||
target="_self"
|
||||
>
|
||||
|
||||
Submit a merge request
|
||||
|
||||
</a>
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="submit_a_merge_request_mr"
|
||||
href="http://example.com/"
|
||||
target="_self"
|
||||
>
|
||||
Submit a merge request (MR)
|
||||
</a>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -372,24 +370,24 @@ exports[`Learn GitLab renders correctly 1`] = `
|
|||
<div
|
||||
class="gl-mb-4"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="flex align-items-center"
|
||||
>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="Run a Security scan using CI/CD"
|
||||
href="https://docs.gitlab.com/ee/foobar/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
Run a Security scan using CI/CD
|
||||
|
||||
</a>
|
||||
<div>
|
||||
<a
|
||||
class="gl-link"
|
||||
data-testid="uncompleted-learn-gitlab-link"
|
||||
data-track-action="click_link"
|
||||
data-track-label="run_a_security_scan_using_ci_cd"
|
||||
href="https://docs.gitlab.com/ee/foobar/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Run a Security scan using CI/CD
|
||||
</a>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import LearnGitlabInfoCard from '~/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue';
|
||||
|
||||
const defaultProps = {
|
||||
title: 'Create Repository',
|
||||
description: 'Some description',
|
||||
actionLabel: 'Create Repository now',
|
||||
url: 'https://example.com',
|
||||
completed: false,
|
||||
svg: 'https://example.com/illustration.svg',
|
||||
};
|
||||
|
||||
describe('Learn GitLab Info Card', () => {
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
const createWrapper = (props = {}) => {
|
||||
wrapper = shallowMount(LearnGitlabInfoCard, {
|
||||
propsData: { ...defaultProps, ...props },
|
||||
});
|
||||
};
|
||||
|
||||
it('renders no icon when not completed', () => {
|
||||
createWrapper({ completed: false });
|
||||
|
||||
expect(wrapper.find('[data-testid="completed-icon"]').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders the completion icon when completed', () => {
|
||||
createWrapper({ completed: true });
|
||||
|
||||
expect(wrapper.find('[data-testid="completed-icon"]').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders no trial only when it is not required', () => {
|
||||
createWrapper();
|
||||
|
||||
expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders trial only when trial is required', () => {
|
||||
createWrapper({ trialRequired: true });
|
||||
|
||||
expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders completion icon when completed a trial-only feature', () => {
|
||||
createWrapper({ trialRequired: true, completed: true });
|
||||
|
||||
expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(false);
|
||||
expect(wrapper.find('[data-testid="completed-icon"]').exists()).toBe(true);
|
||||
});
|
||||
});
|
|
@ -119,7 +119,7 @@ describe('Learn GitLab Section Link', () => {
|
|||
findUncompletedLink().trigger('click');
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_link', {
|
||||
label: 'Run a Security scan using CI/CD',
|
||||
label: 'run_a_security_scan_using_ci_cd',
|
||||
});
|
||||
|
||||
unmockTracking();
|
||||
|
@ -164,7 +164,7 @@ describe('Learn GitLab Section Link', () => {
|
|||
triggerEvent(openInviteMembesrModalLink().element);
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_link', {
|
||||
label: 'Invite your colleagues',
|
||||
label: 'invite_your_colleagues',
|
||||
property: 'Growth::Activation::Experiment::InviteForHelpContinuousOnboarding',
|
||||
});
|
||||
|
||||
|
@ -203,7 +203,7 @@ describe('Learn GitLab Section Link', () => {
|
|||
videoTutorialLink().trigger('click');
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_video_link', {
|
||||
label: 'Add code owners',
|
||||
label: 'add_code_owners',
|
||||
property: 'Growth::Conversion::Experiment::LearnGitLab',
|
||||
context: {
|
||||
data: {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import IncludedInTrialIndicator from '~/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue';
|
||||
|
||||
describe('Learn GitLab Trial Card', () => {
|
||||
it('renders correctly', () => {
|
||||
const wrapper = shallowMount(IncludedInTrialIndicator);
|
||||
|
||||
expect(wrapper.text()).toEqual('- Included in trial');
|
||||
|
||||
wrapper.destroy();
|
||||
});
|
||||
});
|
|
@ -31,18 +31,30 @@ describe('Test reports app', () => {
|
|||
|
||||
const createComponent = ({ state = {} } = {}) => {
|
||||
store = new Vuex.Store({
|
||||
state: {
|
||||
isLoading: false,
|
||||
selectedSuiteIndex: null,
|
||||
testReports,
|
||||
...state,
|
||||
modules: {
|
||||
testReports: {
|
||||
namespaced: true,
|
||||
state: {
|
||||
isLoading: false,
|
||||
selectedSuiteIndex: null,
|
||||
testReports,
|
||||
...state,
|
||||
},
|
||||
actions: actionSpies,
|
||||
getters,
|
||||
},
|
||||
},
|
||||
actions: actionSpies,
|
||||
getters,
|
||||
});
|
||||
|
||||
jest.spyOn(store, 'registerModule').mockReturnValue(null);
|
||||
|
||||
wrapper = extendedWrapper(
|
||||
shallowMount(TestReports, {
|
||||
provide: {
|
||||
blobPath: '/blob/path',
|
||||
summaryEndpoint: '/summary.json',
|
||||
suiteEndpoint: '/suite.json',
|
||||
},
|
||||
store,
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -34,22 +34,32 @@ describe('Test reports suite table', () => {
|
|||
|
||||
const createComponent = ({ suite = testSuite, perPage = 20, errorMessage } = {}) => {
|
||||
store = new Vuex.Store({
|
||||
state: {
|
||||
blobPath,
|
||||
modules: {
|
||||
testReports: {
|
||||
test_suites: [suite],
|
||||
namespaced: true,
|
||||
state: {
|
||||
blobPath,
|
||||
testReports: {
|
||||
test_suites: [suite],
|
||||
},
|
||||
selectedSuiteIndex: 0,
|
||||
pageInfo: {
|
||||
page: 1,
|
||||
perPage,
|
||||
},
|
||||
errorMessage,
|
||||
},
|
||||
getters,
|
||||
},
|
||||
selectedSuiteIndex: 0,
|
||||
pageInfo: {
|
||||
page: 1,
|
||||
perPage,
|
||||
},
|
||||
errorMessage,
|
||||
},
|
||||
getters,
|
||||
});
|
||||
|
||||
wrapper = shallowMountExtended(SuiteTable, {
|
||||
provide: {
|
||||
blobPath: '/blob/path',
|
||||
summaryEndpoint: '/summary.json',
|
||||
suiteEndpoint: '/suite.json',
|
||||
},
|
||||
store,
|
||||
stubs: { GlFriendlyWrap },
|
||||
});
|
||||
|
|
|
@ -20,13 +20,23 @@ describe('Test reports summary table', () => {
|
|||
|
||||
const createComponent = (reports = null) => {
|
||||
store = new Vuex.Store({
|
||||
state: {
|
||||
testReports: reports || testReports,
|
||||
modules: {
|
||||
testReports: {
|
||||
namespaced: true,
|
||||
state: {
|
||||
testReports: reports || testReports,
|
||||
},
|
||||
getters,
|
||||
},
|
||||
},
|
||||
getters,
|
||||
});
|
||||
|
||||
wrapper = mount(SummaryTable, {
|
||||
provide: {
|
||||
blobPath: '/blob/path',
|
||||
summaryEndpoint: '/summary.json',
|
||||
suiteEndpoint: '/suite.json',
|
||||
},
|
||||
propsData: defaultProps,
|
||||
store,
|
||||
});
|
||||
|
|
|
@ -92,38 +92,6 @@ RSpec.describe LearnGitlabHelper do
|
|||
|
||||
it_behaves_like 'has all data'
|
||||
|
||||
it 'sets correct paths' do
|
||||
expect(onboarding_actions_data).to match({
|
||||
trial_started: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/issues/2\z})
|
||||
),
|
||||
pipeline_created: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/issues/7\z})
|
||||
),
|
||||
code_owners_enabled: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/issues/10\z})
|
||||
),
|
||||
required_mr_approvals_enabled: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/issues/11\z})
|
||||
),
|
||||
issue_created: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/issues\z})
|
||||
),
|
||||
git_write: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab\z})
|
||||
),
|
||||
user_added: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/project_members\z})
|
||||
),
|
||||
merge_request_created: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/merge_requests\z})
|
||||
),
|
||||
security_scan_enabled: a_hash_including(
|
||||
url: a_string_matching(%r{/learn_gitlab/-/security/configuration\z})
|
||||
)
|
||||
})
|
||||
end
|
||||
|
||||
it 'sets correct completion statuses' do
|
||||
expect(onboarding_actions_data).to match({
|
||||
issue_created: a_hash_including(completed: false),
|
||||
|
@ -137,5 +105,58 @@ RSpec.describe LearnGitlabHelper do
|
|||
security_scan_enabled: a_hash_including(completed: false)
|
||||
})
|
||||
end
|
||||
|
||||
describe 'security_actions_continuous_onboarding experiment' do
|
||||
let(:base_paths) do
|
||||
{
|
||||
trial_started: a_hash_including(url: %r{/learn_gitlab/-/issues/2\z}),
|
||||
pipeline_created: a_hash_including(url: %r{/learn_gitlab/-/issues/7\z}),
|
||||
code_owners_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/10\z}),
|
||||
required_mr_approvals_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/11\z}),
|
||||
issue_created: a_hash_including(url: %r{/learn_gitlab/-/issues\z}),
|
||||
git_write: a_hash_including(url: %r{/learn_gitlab\z}),
|
||||
user_added: a_hash_including(url: %r{/learn_gitlab/-/project_members\z}),
|
||||
merge_request_created: a_hash_including(url: %r{/learn_gitlab/-/merge_requests\z})
|
||||
}
|
||||
end
|
||||
|
||||
context 'when control' do
|
||||
before do
|
||||
stub_experiments(security_actions_continuous_onboarding: :control)
|
||||
end
|
||||
|
||||
it 'sets correct paths' do
|
||||
expect(onboarding_actions_data).to match(
|
||||
base_paths.merge(
|
||||
security_scan_enabled: a_hash_including(
|
||||
url: %r{/learn_gitlab/-/security/configuration\z}
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when candidate' do
|
||||
before do
|
||||
stub_experiments(security_actions_continuous_onboarding: :candidate)
|
||||
end
|
||||
|
||||
it 'sets correct paths' do
|
||||
expect(onboarding_actions_data).to match(
|
||||
base_paths.merge(
|
||||
license_scanning_run: a_hash_including(
|
||||
url: described_class::LICENSE_SCANNING_RUN_URL
|
||||
),
|
||||
secure_dependency_scanning_run: a_hash_including(
|
||||
url: project_security_configuration_path(project, anchor: 'dependency-scanning')
|
||||
),
|
||||
secure_dast_run: a_hash_including(
|
||||
url: project_security_configuration_path(project, anchor: 'dast')
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,8 +21,8 @@ RSpec.describe Gitlab::GitlabImport::Importer do
|
|||
'name' => 'John Doe'
|
||||
}
|
||||
}
|
||||
])
|
||||
stub_request('issues/3/notes', [])
|
||||
].to_json)
|
||||
stub_request('issues/3/notes', [].to_json)
|
||||
end
|
||||
|
||||
it 'persists issues' do
|
||||
|
|
|
@ -6,11 +6,14 @@ RSpec.describe LearnGitlab::Onboarding do
|
|||
describe '#completed_percentage' do
|
||||
let(:completed_actions) { {} }
|
||||
let(:onboarding_progress) { build(:onboarding_progress, namespace: namespace, **completed_actions) }
|
||||
let(:namespace) { build(:namespace) }
|
||||
let(:namespace) { create(:namespace) }
|
||||
|
||||
let_it_be(:tracked_action_columns) do
|
||||
tracked_actions = described_class::ACTION_ISSUE_IDS.keys + described_class::ACTION_PATHS
|
||||
tracked_actions.map { |key| OnboardingProgress.column_name(key) }
|
||||
[
|
||||
*described_class::ACTION_ISSUE_IDS.keys,
|
||||
*described_class::ACTION_PATHS,
|
||||
:security_scan_enabled
|
||||
].map { |key| OnboardingProgress.column_name(key) }
|
||||
end
|
||||
|
||||
before do
|
||||
|
@ -29,12 +32,6 @@ RSpec.describe LearnGitlab::Onboarding do
|
|||
it { is_expected.to eq(0) }
|
||||
end
|
||||
|
||||
context 'when one action has been completed' do
|
||||
let(:completed_actions) { Hash[tracked_action_columns.first, Time.current] }
|
||||
|
||||
it { is_expected.to eq(11) }
|
||||
end
|
||||
|
||||
context 'when all tracked actions have been completed' do
|
||||
let(:completed_actions) do
|
||||
tracked_action_columns.to_h { |action| [action, Time.current] }
|
||||
|
@ -42,5 +39,25 @@ RSpec.describe LearnGitlab::Onboarding do
|
|||
|
||||
it { is_expected.to eq(100) }
|
||||
end
|
||||
|
||||
describe 'security_actions_continuous_onboarding experiment' do
|
||||
let(:completed_actions) { Hash[tracked_action_columns.first, Time.current] }
|
||||
|
||||
context 'when control' do
|
||||
before do
|
||||
stub_experiments(security_actions_continuous_onboarding: :control)
|
||||
end
|
||||
|
||||
it { is_expected.to eq(11) }
|
||||
end
|
||||
|
||||
context 'when candidate' do
|
||||
before do
|
||||
stub_experiments(security_actions_continuous_onboarding: :candidate)
|
||||
end
|
||||
|
||||
it { is_expected.to eq(9) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -799,7 +799,7 @@ RSpec.describe Integration do
|
|||
|
||||
shared_examples '#api_field_names' do
|
||||
it 'filters out secret fields' do
|
||||
safe_fields = %w[some_safe_field safe_field url trojan_gift]
|
||||
safe_fields = %w[some_safe_field safe_field url trojan_gift api_only_field]
|
||||
|
||||
expect(fake_integration.new).to have_attributes(
|
||||
api_field_names: match_array(safe_fields)
|
||||
|
@ -807,6 +807,12 @@ RSpec.describe Integration do
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples '#form_fields' do
|
||||
it 'filters out API only fields' do
|
||||
expect(fake_integration.new.form_fields.pluck(:name)).not_to include('api_only_field')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the class overrides #fields' do
|
||||
let(:fake_integration) do
|
||||
Class.new(Integration) do
|
||||
|
@ -824,7 +830,8 @@ RSpec.describe Integration do
|
|||
{ name: 'safe_field' },
|
||||
{ name: 'url' },
|
||||
{ name: 'trojan_horse', type: 'password' },
|
||||
{ name: 'trojan_gift', type: 'text' }
|
||||
{ name: 'trojan_gift', type: 'text' },
|
||||
{ name: 'api_only_field', api_only: true }
|
||||
].shuffle
|
||||
end
|
||||
end
|
||||
|
@ -832,6 +839,7 @@ RSpec.describe Integration do
|
|||
|
||||
it_behaves_like '#fields'
|
||||
it_behaves_like '#api_field_names'
|
||||
it_behaves_like '#form_fields'
|
||||
end
|
||||
|
||||
context 'when the class uses the field DSL' do
|
||||
|
@ -850,11 +858,13 @@ RSpec.describe Integration do
|
|||
field :url
|
||||
field :trojan_horse, type: 'password'
|
||||
field :trojan_gift, type: 'text'
|
||||
field :api_only_field, api_only: true
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like '#fields'
|
||||
it_behaves_like '#api_field_names'
|
||||
it_behaves_like '#form_fields'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ RSpec.describe Integrations::Jira do
|
|||
subject(:fields) { integration.fields }
|
||||
|
||||
it 'returns custom fields' do
|
||||
expect(fields.pluck(:name)).to eq(%w[url api_url username password])
|
||||
expect(fields.pluck(:name)).to eq(%w[url api_url username password jira_issue_transition_id])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,22 +7,40 @@ RSpec.describe OauthAccessToken do
|
|||
let(:app_one) { create(:oauth_application) }
|
||||
let(:app_two) { create(:oauth_application) }
|
||||
let(:app_three) { create(:oauth_application) }
|
||||
let(:tokens) { described_class.all }
|
||||
let(:token) { create(:oauth_access_token, application_id: app_one.id) }
|
||||
|
||||
before do
|
||||
create(:oauth_access_token, application_id: app_one.id)
|
||||
create_list(:oauth_access_token, 2, resource_owner: user, application_id: app_two.id)
|
||||
end
|
||||
describe 'scopes' do
|
||||
describe '.distinct_resource_owner_counts' do
|
||||
let(:tokens) { described_class.all }
|
||||
|
||||
it 'returns unique owners' do
|
||||
expect(tokens.count).to eq(3)
|
||||
expect(tokens.distinct_resource_owner_counts([app_one])).to eq({ app_one.id => 1 })
|
||||
expect(tokens.distinct_resource_owner_counts([app_two])).to eq({ app_two.id => 1 })
|
||||
expect(tokens.distinct_resource_owner_counts([app_three])).to eq({})
|
||||
expect(tokens.distinct_resource_owner_counts([app_one, app_two]))
|
||||
.to eq({
|
||||
app_one.id => 1,
|
||||
app_two.id => 1
|
||||
})
|
||||
before do
|
||||
token
|
||||
create_list(:oauth_access_token, 2, resource_owner: user, application_id: app_two.id)
|
||||
end
|
||||
|
||||
it 'returns unique owners' do
|
||||
expect(tokens.count).to eq(3)
|
||||
expect(tokens.distinct_resource_owner_counts([app_one])).to eq({ app_one.id => 1 })
|
||||
expect(tokens.distinct_resource_owner_counts([app_two])).to eq({ app_two.id => 1 })
|
||||
expect(tokens.distinct_resource_owner_counts([app_three])).to eq({})
|
||||
expect(tokens.distinct_resource_owner_counts([app_one, app_two]))
|
||||
.to eq({
|
||||
app_one.id => 1,
|
||||
app_two.id => 1
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
describe '.latest_per_application' do
|
||||
let!(:app_two_token1) { create(:oauth_access_token, application: app_two) }
|
||||
let!(:app_two_token2) { create(:oauth_access_token, application: app_two) }
|
||||
let!(:app_three_token1) { create(:oauth_access_token, application: app_three) }
|
||||
let!(:app_three_token2) { create(:oauth_access_token, application: app_three) }
|
||||
|
||||
it 'returns only the latest token for each application' do
|
||||
expect(described_class.latest_per_application.map(&:id))
|
||||
.to match_array([app_two_token2.id, app_three_token2.id])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -363,6 +363,31 @@ RSpec.describe API::Integrations do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Jira integration' do
|
||||
let(:integration_name) { 'jira' }
|
||||
let(:params) do
|
||||
{ url: 'https://jira.example.com', username: 'username', password: 'password' }
|
||||
end
|
||||
|
||||
before do
|
||||
project.create_jira_integration(active: true, properties: params)
|
||||
end
|
||||
|
||||
it 'returns the jira_issue_transition_id for get request' do
|
||||
get api("/projects/#{project.id}/#{endpoint}/#{integration_name}", user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['properties']).to include('jira_issue_transition_id' => nil)
|
||||
end
|
||||
|
||||
it 'returns the jira_issue_transition_id for put request' do
|
||||
put api("/projects/#{project.id}/#{endpoint}/#{integration_name}", user), params: params.merge(jira_issue_transition_id: '1')
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['properties']['jira_issue_transition_id']).to eq('1')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Pipelines Email Integration' do
|
||||
let(:integration_name) { 'pipelines-email' }
|
||||
|
||||
|
|
|
@ -114,6 +114,6 @@ RSpec.describe Integrations::FieldEntity do
|
|||
end
|
||||
|
||||
def integration_field(name)
|
||||
integration.global_fields.find { |f| f[:name] == name }
|
||||
integration.form_fields.find { |f| f[:name] == name }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,6 +20,11 @@ RSpec.shared_examples 'integration settings form' do
|
|||
"#{integration.title} field #{field_name} not present"
|
||||
end
|
||||
|
||||
api_only_fields = integration.fields.select { _1[:api_only] }
|
||||
api_only_fields.each do |field|
|
||||
expect(page).not_to have_field("service[#{field.name}]", wait: 0)
|
||||
end
|
||||
|
||||
sections = integration.sections
|
||||
events = parse_json(trigger_events_for_integration(integration))
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/getsentry/raven-go v0.2.0
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gomodule/redigo v2.0.0+incompatible
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
|
@ -33,7 +33,7 @@ require (
|
|||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93
|
||||
golang.org/x/tools v0.1.5
|
||||
golang.org/x/tools v0.1.11
|
||||
google.golang.org/grpc v1.45.0
|
||||
google.golang.org/protobuf v1.28.0
|
||||
honnef.co/go/tools v0.1.3
|
||||
|
@ -102,7 +102,7 @@ require (
|
|||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/mod v0.5.0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg=
|
||||
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
|
@ -261,6 +262,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
@ -368,9 +370,11 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
|
|||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
github.com/getsentry/raven-go v0.1.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/getsentry/raven-go v0.1.2/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
|
@ -429,6 +433,7 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn
|
|||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
|
||||
|
@ -457,8 +462,8 @@ github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
|
|||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw=
|
||||
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg=
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -466,6 +471,7 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er
|
|||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
|
@ -495,6 +501,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
|
@ -502,6 +509,7 @@ github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNu
|
|||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
|
@ -564,6 +572,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
|||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
|
||||
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
|
@ -581,6 +591,7 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY
|
|||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.3-0.20210213123510-be4c235f9d1c/go.mod h1:RXwzibsL7UhPcEmGyGvXKJ8kyJsOCOEaLgGce4igMFs=
|
||||
|
@ -611,6 +622,7 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
|
|||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
|
@ -627,6 +639,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
|
|||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
|
||||
|
@ -747,6 +760,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
|
|||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
|
@ -780,8 +794,10 @@ github.com/lightstep/lightstep-tracer-go v0.24.0/go.mod h1:RnONwHKg89zYPmF+Uig5P
|
|||
github.com/lightstep/lightstep-tracer-go v0.25.0 h1:sGVnz8h3jTQuHKMbUe2949nXm3Sg09N1UcR3VoQNN5E=
|
||||
github.com/lightstep/lightstep-tracer-go v0.25.0/go.mod h1:G1ZAEaqTHFPWpWunnbUn1ADEY/Jvzz7jIOaXwAfD6A8=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
|
@ -791,6 +807,7 @@ github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/
|
|||
github.com/mattn/go-ieproxy v0.0.3/go.mod h1:6ZpRmhBaYuBX1U2za+9rC9iCGLsSp2tftelZne7CPko=
|
||||
github.com/mattn/go-ieproxy v0.0.6 h1:tVDlituRyeHMMkHpGpUu8CJG+hxPMwbYCkIUK2PUCbo=
|
||||
github.com/mattn/go-ieproxy v0.0.6/go.mod h1:6ZpRmhBaYuBX1U2za+9rC9iCGLsSp2tftelZne7CPko=
|
||||
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
|
@ -824,6 +841,7 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
|
|||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
|
@ -890,6 +908,7 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
|
|||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
|
@ -998,15 +1017,20 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
|
|||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/ssgelm/cookiejarparser v1.0.1/go.mod h1:DUfC0mpjIzlDN7DzKjXpHj0qMI5m9VrZuz3wSlI+OEI=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
|
@ -1071,6 +1095,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
gitlab.com/gitlab-org/gitaly v1.68.0 h1:VlcJs1+PrhW7lqJUU7Fh1q8FMJujmbbivdfde/cwB98=
|
||||
|
@ -1206,8 +1231,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -1266,6 +1292,7 @@ golang.org/x/net v0.0.0-20210505214959-0714010a04ed/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
@ -1275,6 +1302,7 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
|||
golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -1298,6 +1326,7 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a h1:qfl7ob3DIEs3Ml9oLuPwY2N04gymzAW04WsUQHIClgM=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -1402,6 +1431,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -1430,6 +1460,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -1513,8 +1544,9 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -1527,6 +1559,7 @@ gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM=
|
|||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||
google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
|
@ -1585,6 +1618,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
|
|||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
|
@ -1678,6 +1712,7 @@ google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2
|
|||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de h1:9Ti5SG2U4cAcluryUo/sFay3TQKoxiFMfaT0pbizU7k=
|
||||
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
|
Loading…
Reference in New Issue