Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
fbc7e1f503
commit
2ccb5c91c8
|
@ -121,6 +121,11 @@ yarn-audit-dependency_scanning:
|
||||||
- cd .. && tar -I "gzip --best" -cf gitlab.tgz gitlab/
|
- cd .. && tar -I "gzip --best" -cf gitlab.tgz gitlab/
|
||||||
script:
|
script:
|
||||||
- DEBUG=* node /usr/src/app/cli.js analyze --format gitlab --manager ${PACKAGE_MANAGER} gitlab.tgz | tee ${CI_PROJECT_DIR}/gl-dependency-scanning-report.json
|
- DEBUG=* node /usr/src/app/cli.js analyze --format gitlab --manager ${PACKAGE_MANAGER} gitlab.tgz | tee ${CI_PROJECT_DIR}/gl-dependency-scanning-report.json
|
||||||
|
after_script:
|
||||||
|
- mkdir ~/.aws
|
||||||
|
- '[[ -z "${AWS_SIEM_REPORT_INGESTION_CREDENTIALS_FILE}" ]] || mv "${AWS_SIEM_REPORT_INGESTION_CREDENTIALS_FILE}" ~/.aws/credentials'
|
||||||
|
- npm install --no-save --ignore-scripts @aws-sdk/client-s3@3.49.0
|
||||||
|
- scripts/ingest-reports-to-siem
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- gl-dependency-scanning-report.json
|
- gl-dependency-scanning-report.json
|
||||||
|
|
|
@ -17,9 +17,6 @@ export default {
|
||||||
revokePath: {
|
revokePath: {
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
buttonClass: {
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
modalId() {
|
modalId() {
|
||||||
|
@ -38,10 +35,9 @@ export default {
|
||||||
<div>
|
<div>
|
||||||
<gl-button
|
<gl-button
|
||||||
v-gl-modal="modalId"
|
v-gl-modal="modalId"
|
||||||
:class="buttonClass"
|
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
class="float-right"
|
class="gl-float-right"
|
||||||
data-testid="revoke-button"
|
data-testid="revoke-button"
|
||||||
>{{ s__('DeployTokens|Revoke') }}</gl-button
|
>{{ s__('DeployTokens|Revoke') }}</gl-button
|
||||||
>
|
>
|
||||||
|
|
|
@ -9,14 +9,13 @@ export default () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return containers.forEach((el) => {
|
return containers.forEach((el) => {
|
||||||
const { token, revokePath, buttonClass } = el.dataset;
|
const { token, revokePath } = el.dataset;
|
||||||
|
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el,
|
el,
|
||||||
provide: {
|
provide: {
|
||||||
token: JSON.parse(token),
|
token: JSON.parse(token),
|
||||||
revokePath,
|
revokePath,
|
||||||
buttonClass,
|
|
||||||
},
|
},
|
||||||
render(h) {
|
render(h) {
|
||||||
return h(RevokeButton);
|
return h(RevokeButton);
|
||||||
|
|
|
@ -83,17 +83,17 @@ export default {
|
||||||
i18n: {
|
i18n: {
|
||||||
sectionTitle: s__('JiraService|View Jira issues in GitLab'),
|
sectionTitle: s__('JiraService|View Jira issues in GitLab'),
|
||||||
sectionDescription: s__(
|
sectionDescription: s__(
|
||||||
'JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only.',
|
'JiraService|Work on Jira issues without leaving GitLab. Add a Jira menu to access a read-only list of your Jira issues.',
|
||||||
),
|
),
|
||||||
enableCheckboxLabel: s__('JiraService|Enable Jira issues'),
|
enableCheckboxLabel: s__('JiraService|Enable Jira issues'),
|
||||||
enableCheckboxHelp: s__(
|
enableCheckboxHelp: s__(
|
||||||
'JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below.',
|
'JiraService|Warning: All GitLab users with access to this GitLab project can view all issues from the Jira project you select.',
|
||||||
),
|
),
|
||||||
projectKeyLabel: s__('JiraService|Jira project key'),
|
projectKeyLabel: s__('JiraService|Jira project key'),
|
||||||
projectKeyPlaceholder: s__('JiraService|For example, AB'),
|
projectKeyPlaceholder: s__('JiraService|For example, AB'),
|
||||||
requiredFieldFeedback: __('This field is required.'),
|
requiredFieldFeedback: __('This field is required.'),
|
||||||
issueTrackerConflictWarning: s__(
|
issueTrackerConflictWarning: s__(
|
||||||
'JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used.',
|
'JiraService|Displaying Jira issues while leaving GitLab issues also enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used.',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -138,7 +138,7 @@ export default {
|
||||||
label-for="service[trigger]"
|
label-for="service[trigger]"
|
||||||
:description="
|
:description="
|
||||||
s__(
|
s__(
|
||||||
'Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled).',
|
'JiraService|When a Jira issue is mentioned in a commit or merge request, a remote link and comment (if enabled) will be created.',
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|
|
@ -264,7 +264,7 @@ export default {
|
||||||
<gl-button
|
<gl-button
|
||||||
:disabled="submitDisabled"
|
:disabled="submitDisabled"
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
variant="success"
|
variant="confirm"
|
||||||
data-qa-selector="invite_button"
|
data-qa-selector="invite_button"
|
||||||
data-testid="invite-button"
|
data-testid="invite-button"
|
||||||
@click="submit"
|
@click="submit"
|
||||||
|
|
|
@ -135,6 +135,14 @@ export default {
|
||||||
const canReopen = this.isClosed && this.canReopenIssue;
|
const canReopen = this.isClosed && this.canReopenIssue;
|
||||||
return canClose || canReopen;
|
return canClose || canReopen;
|
||||||
},
|
},
|
||||||
|
hasDesktopDropdown() {
|
||||||
|
return (
|
||||||
|
this.canCreateIssue || this.canPromoteToEpic || !this.isIssueAuthor || this.canReportSpam
|
||||||
|
);
|
||||||
|
},
|
||||||
|
hasMobileDropdown() {
|
||||||
|
return this.hasDesktopDropdown || this.showToggleIssueStateButton;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
eventHub.$on('toggle.issuable.state', this.toggleIssueState);
|
eventHub.$on('toggle.issuable.state', this.toggleIssueState);
|
||||||
|
@ -223,10 +231,12 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div class="detail-page-header-actions gl-display-flex">
|
<div class="detail-page-header-actions gl-display-flex">
|
||||||
<gl-dropdown
|
<gl-dropdown
|
||||||
|
v-if="hasMobileDropdown"
|
||||||
class="gl-sm-display-none! w-100"
|
class="gl-sm-display-none! w-100"
|
||||||
block
|
block
|
||||||
:text="dropdownText"
|
:text="dropdownText"
|
||||||
data-qa-selector="issue_actions_dropdown"
|
data-qa-selector="issue_actions_dropdown"
|
||||||
|
data-testid="mobile-dropdown"
|
||||||
:loading="isToggleStateButtonLoading"
|
:loading="isToggleStateButtonLoading"
|
||||||
>
|
>
|
||||||
<gl-dropdown-item
|
<gl-dropdown-item
|
||||||
|
@ -276,11 +286,13 @@ export default {
|
||||||
</gl-button>
|
</gl-button>
|
||||||
|
|
||||||
<gl-dropdown
|
<gl-dropdown
|
||||||
|
v-if="hasDesktopDropdown"
|
||||||
class="gl-display-none gl-sm-display-inline-flex! gl-ml-3"
|
class="gl-display-none gl-sm-display-inline-flex! gl-ml-3"
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
:text="dropdownText"
|
:text="dropdownText"
|
||||||
:text-sr-only="true"
|
:text-sr-only="true"
|
||||||
|
data-testid="desktop-dropdown"
|
||||||
no-caret
|
no-caret
|
||||||
right
|
right
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlSprintf, GlButton, GlButtonGroup } from '@gitlab/ui';
|
import { GlSprintf, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
|
||||||
import { mapGetters, mapState, mapActions } from 'vuex';
|
import { mapGetters, mapState, mapActions } from 'vuex';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import FileIcon from '~/vue_shared/components/file_icon.vue';
|
import FileIcon from '~/vue_shared/components/file_icon.vue';
|
||||||
|
@ -23,6 +23,7 @@ export default {
|
||||||
GlButton,
|
GlButton,
|
||||||
GlButtonGroup,
|
GlButtonGroup,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
|
GlLoadingIcon,
|
||||||
FileIcon,
|
FileIcon,
|
||||||
DiffFileEditor,
|
DiffFileEditor,
|
||||||
InlineConflictLines,
|
InlineConflictLines,
|
||||||
|
@ -72,9 +73,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div id="conflicts">
|
<div id="conflicts">
|
||||||
<div v-if="isLoading" class="loading">
|
<gl-loading-icon v-if="isLoading" size="md" data-testid="loading-spinner" />
|
||||||
<div class="spinner spinner-md"></div>
|
|
||||||
</div>
|
|
||||||
<div v-if="hasError" class="nothing-here-block">
|
<div v-if="hasError" class="nothing-here-block">
|
||||||
{{ conflictsData.errorMessage }}
|
{{ conflictsData.errorMessage }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -69,9 +69,10 @@ export default {
|
||||||
// If it's a brand new file, we don't want to fetch the content.
|
// If it's a brand new file, we don't want to fetch the content.
|
||||||
// Then when the user commits the first time, the query would run
|
// Then when the user commits the first time, the query would run
|
||||||
// to get the initial file content, but we already have it in `lastCommitedContent`
|
// to get the initial file content, but we already have it in `lastCommitedContent`
|
||||||
// so we skip the loading altogether.
|
// so we skip the loading altogether. We also wait for the currentBranch
|
||||||
skip({ isNewCiConfigFile, lastCommittedContent }) {
|
// to have been fetched
|
||||||
return isNewCiConfigFile || lastCommittedContent;
|
skip() {
|
||||||
|
return this.shouldSkipBlobContentQuery;
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
|
@ -128,8 +129,8 @@ export default {
|
||||||
},
|
},
|
||||||
ciConfigData: {
|
ciConfigData: {
|
||||||
query: getCiConfigData,
|
query: getCiConfigData,
|
||||||
skip({ currentCiFileContent }) {
|
skip() {
|
||||||
return !currentCiFileContent;
|
return this.shouldSkipCiConfigQuery;
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
|
@ -174,6 +175,9 @@ export default {
|
||||||
},
|
},
|
||||||
commitSha: {
|
commitSha: {
|
||||||
query: getLatestCommitShaQuery,
|
query: getLatestCommitShaQuery,
|
||||||
|
skip({ currentBranch }) {
|
||||||
|
return !currentBranch;
|
||||||
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
projectPath: this.projectFullPath,
|
projectPath: this.projectFullPath,
|
||||||
|
@ -181,7 +185,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
update(data) {
|
update(data) {
|
||||||
const latestCommitSha = data.project?.repository?.tree?.lastCommit?.sha;
|
const latestCommitSha = data?.project?.repository?.tree?.lastCommit?.sha;
|
||||||
|
|
||||||
if (this.isFetchingCommitSha && latestCommitSha === this.commitSha) {
|
if (this.isFetchingCommitSha && latestCommitSha === this.commitSha) {
|
||||||
this.$apollo.queries.commitSha.startPolling(COMMIT_SHA_POLL_INTERVAL);
|
this.$apollo.queries.commitSha.startPolling(COMMIT_SHA_POLL_INTERVAL);
|
||||||
|
@ -192,6 +196,9 @@ export default {
|
||||||
this.$apollo.queries.commitSha.stopPolling();
|
this.$apollo.queries.commitSha.stopPolling();
|
||||||
return latestCommitSha;
|
return latestCommitSha;
|
||||||
},
|
},
|
||||||
|
error() {
|
||||||
|
this.reportFailure(LOAD_FAILURE_UNKNOWN);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
currentBranch: {
|
currentBranch: {
|
||||||
query: getCurrentBranch,
|
query: getCurrentBranch,
|
||||||
|
@ -234,6 +241,12 @@ export default {
|
||||||
isEmpty() {
|
isEmpty() {
|
||||||
return this.currentCiFileContent === '';
|
return this.currentCiFileContent === '';
|
||||||
},
|
},
|
||||||
|
shouldSkipBlobContentQuery() {
|
||||||
|
return this.isNewCiConfigFile || this.lastCommittedContent || !this.currentBranch;
|
||||||
|
},
|
||||||
|
shouldSkipCiConfigQuery() {
|
||||||
|
return !this.currentCiFileContent || !this.commitSha;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
resetModal: {
|
resetModal: {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||||
import RunnerHeader from '../components/runner_header.vue';
|
import RunnerHeader from '../components/runner_header.vue';
|
||||||
import RunnerUpdateForm from '../components/runner_update_form.vue';
|
import RunnerUpdateForm from '../components/runner_update_form.vue';
|
||||||
import { I18N_FETCH_ERROR } from '../constants';
|
import { I18N_FETCH_ERROR } from '../constants';
|
||||||
import getRunnerQuery from '../graphql/get_runner.query.graphql';
|
import runnerQuery from '../graphql/details/runner.query.graphql';
|
||||||
import { captureException } from '../sentry_utils';
|
import { captureException } from '../sentry_utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -27,7 +27,7 @@ export default {
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
runner: {
|
runner: {
|
||||||
query: getRunnerQuery,
|
query: runnerQuery,
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
id: convertToGraphQLId(TYPE_CI_RUNNER, this.runnerId),
|
id: convertToGraphQLId(TYPE_CI_RUNNER, this.runnerId),
|
||||||
|
|
|
@ -8,7 +8,7 @@ import RunnerPauseButton from '../components/runner_pause_button.vue';
|
||||||
import RunnerHeader from '../components/runner_header.vue';
|
import RunnerHeader from '../components/runner_header.vue';
|
||||||
import RunnerDetails from '../components/runner_details.vue';
|
import RunnerDetails from '../components/runner_details.vue';
|
||||||
import { I18N_FETCH_ERROR } from '../constants';
|
import { I18N_FETCH_ERROR } from '../constants';
|
||||||
import getRunnerQuery from '../graphql/get_runner.query.graphql';
|
import runnerQuery from '../graphql/details/runner.query.graphql';
|
||||||
import { captureException } from '../sentry_utils';
|
import { captureException } from '../sentry_utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -35,7 +35,7 @@ export default {
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
runner: {
|
runner: {
|
||||||
query: getRunnerQuery,
|
query: runnerQuery,
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
id: convertToGraphQLId(TYPE_CI_RUNNER, this.runnerId),
|
id: convertToGraphQLId(TYPE_CI_RUNNER, this.runnerId),
|
||||||
|
|
|
@ -26,8 +26,8 @@ import {
|
||||||
STATUS_STALE,
|
STATUS_STALE,
|
||||||
I18N_FETCH_ERROR,
|
I18N_FETCH_ERROR,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import getRunnersQuery from '../graphql/get_runners.query.graphql';
|
import runnersAdminQuery from '../graphql/list/admin_runners.query.graphql';
|
||||||
import getRunnersCountQuery from '../graphql/get_runners_count.query.graphql';
|
import runnersAdminCountQuery from '../graphql/list/admin_runners_count.query.graphql';
|
||||||
import {
|
import {
|
||||||
fromUrlQueryToSearch,
|
fromUrlQueryToSearch,
|
||||||
fromSearchToUrl,
|
fromSearchToUrl,
|
||||||
|
@ -36,7 +36,7 @@ import {
|
||||||
import { captureException } from '../sentry_utils';
|
import { captureException } from '../sentry_utils';
|
||||||
|
|
||||||
const runnersCountSmartQuery = {
|
const runnersCountSmartQuery = {
|
||||||
query: getRunnersCountQuery,
|
query: runnersAdminCountQuery,
|
||||||
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
|
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
|
||||||
update(data) {
|
update(data) {
|
||||||
return data?.runners?.count;
|
return data?.runners?.count;
|
||||||
|
@ -77,7 +77,7 @@ export default {
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
runners: {
|
runners: {
|
||||||
query: getRunnersQuery,
|
query: runnersAdminQuery,
|
||||||
// Runners can be updated by users directly in this list.
|
// Runners can be updated by users directly in this list.
|
||||||
// A "cache and network" policy prevents outdated filtered
|
// A "cache and network" policy prevents outdated filtered
|
||||||
// results.
|
// results.
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { createAlert } from '~/flash';
|
||||||
import { TYPE_GROUP, TYPE_PROJECT } from '~/graphql_shared/constants';
|
import { TYPE_GROUP, TYPE_PROJECT } from '~/graphql_shared/constants';
|
||||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { __, s__ } from '~/locale';
|
import { __, s__ } from '~/locale';
|
||||||
import runnersRegistrationTokenResetMutation from '~/runner/graphql/runners_registration_token_reset.mutation.graphql';
|
import runnersRegistrationTokenResetMutation from '~/runner/graphql/list/runners_registration_token_reset.mutation.graphql';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
|
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
|
import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
|
||||||
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
|
import runnerDeleteMutation from '~/runner/graphql/shared/runner_delete.mutation.graphql';
|
||||||
import { createAlert } from '~/flash';
|
import { createAlert } from '~/flash';
|
||||||
import { s__, sprintf } from '~/locale';
|
import { s__, sprintf } from '~/locale';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlSkeletonLoading } from '@gitlab/ui';
|
import { GlSkeletonLoading } from '@gitlab/ui';
|
||||||
import { createAlert } from '~/flash';
|
import { createAlert } from '~/flash';
|
||||||
import getRunnerJobsQuery from '../graphql/get_runner_jobs.query.graphql';
|
import runnerJobsQuery from '../graphql/details/runner_jobs.query.graphql';
|
||||||
import { I18N_FETCH_ERROR, I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '../constants';
|
import { I18N_FETCH_ERROR, I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '../constants';
|
||||||
import { captureException } from '../sentry_utils';
|
import { captureException } from '../sentry_utils';
|
||||||
import { getPaginationVariables } from '../utils';
|
import { getPaginationVariables } from '../utils';
|
||||||
|
@ -34,7 +34,7 @@ export default {
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
jobs: {
|
jobs: {
|
||||||
query: getRunnerJobsQuery,
|
query: runnerJobsQuery,
|
||||||
variables() {
|
variables() {
|
||||||
return this.variables;
|
return this.variables;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
|
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
|
||||||
import runnerToggleActiveMutation from '~/runner/graphql/runner_toggle_active.mutation.graphql';
|
import runnerToggleActiveMutation from '~/runner/graphql/shared/runner_toggle_active.mutation.graphql';
|
||||||
import { createAlert } from '~/flash';
|
import { createAlert } from '~/flash';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { I18N_PAUSE, I18N_RESUME } from '../constants';
|
import { I18N_PAUSE, I18N_RESUME } from '../constants';
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { GlSkeletonLoading } from '@gitlab/ui';
|
import { GlSkeletonLoading } from '@gitlab/ui';
|
||||||
import { sprintf, formatNumber } from '~/locale';
|
import { sprintf, formatNumber } from '~/locale';
|
||||||
import { createAlert } from '~/flash';
|
import { createAlert } from '~/flash';
|
||||||
import getRunnerProjectsQuery from '../graphql/get_runner_projects.query.graphql';
|
import runnerProjectsQuery from '../graphql/details/runner_projects.query.graphql';
|
||||||
import {
|
import {
|
||||||
I18N_ASSIGNED_PROJECTS,
|
I18N_ASSIGNED_PROJECTS,
|
||||||
I18N_NONE,
|
I18N_NONE,
|
||||||
|
@ -41,7 +41,7 @@ export default {
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
projects: {
|
projects: {
|
||||||
query: getRunnerProjectsQuery,
|
query: runnerProjectsQuery,
|
||||||
variables() {
|
variables() {
|
||||||
return this.variables;
|
return this.variables;
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { createAlert, VARIANT_SUCCESS } from '~/flash';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { ACCESS_LEVEL_NOT_PROTECTED, ACCESS_LEVEL_REF_PROTECTED, PROJECT_TYPE } from '../constants';
|
import { ACCESS_LEVEL_NOT_PROTECTED, ACCESS_LEVEL_REF_PROTECTED, PROJECT_TYPE } from '../constants';
|
||||||
import runnerUpdateMutation from '../graphql/runner_update.mutation.graphql';
|
import runnerUpdateMutation from '../graphql/details/runner_update.mutation.graphql';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RunnerUpdateForm',
|
name: 'RunnerUpdateForm',
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#import "ee_else_ce/runner/graphql/runner_details.fragment.graphql"
|
#import "ee_else_ce/runner/graphql/details/runner_details.fragment.graphql"
|
||||||
|
|
||||||
query getRunner($id: CiRunnerID!) {
|
query getRunner($id: CiRunnerID!) {
|
||||||
# We have an id in deeply nested fragment
|
# We have an id in deeply nested fragment
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||||
runner(id: $id) {
|
runner(id: $id) {
|
||||||
__typename
|
|
||||||
...RunnerDetails
|
...RunnerDetails
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
fragment RunnerDetailsShared on CiRunner {
|
fragment RunnerDetailsShared on CiRunner {
|
||||||
|
__typename
|
||||||
id
|
id
|
||||||
runnerType
|
runnerType
|
||||||
active
|
active
|
||||||
|
@ -22,7 +23,7 @@ fragment RunnerDetailsShared on CiRunner {
|
||||||
groups {
|
groups {
|
||||||
# Only a single group can be loaded here, while projects
|
# Only a single group can be loaded here, while projects
|
||||||
# are loaded separately using the query with pagination
|
# are loaded separately using the query with pagination
|
||||||
# parameters `get_runner_projects.query.graphql`.
|
# parameters `runner_projects.query.graphql`.
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
avatarUrl
|
avatarUrl
|
|
@ -1,4 +1,4 @@
|
||||||
#import "ee_else_ce/runner/graphql/runner_details.fragment.graphql"
|
#import "ee_else_ce/runner/graphql/details/runner_details.fragment.graphql"
|
||||||
|
|
||||||
# Mutation for updates from the runner form, loads
|
# Mutation for updates from the runner form, loads
|
||||||
# attributes shown in the runner details.
|
# attributes shown in the runner details.
|
|
@ -1,4 +1,4 @@
|
||||||
#import "~/runner/graphql/runner_node.fragment.graphql"
|
#import "~/runner/graphql/list/list_item.fragment.graphql"
|
||||||
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
|
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
|
||||||
|
|
||||||
query getRunners(
|
query getRunners(
|
||||||
|
@ -24,7 +24,7 @@ query getRunners(
|
||||||
sort: $sort
|
sort: $sort
|
||||||
) {
|
) {
|
||||||
nodes {
|
nodes {
|
||||||
...RunnerNode
|
...ListItem
|
||||||
adminUrl
|
adminUrl
|
||||||
editAdminUrl
|
editAdminUrl
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
#import "~/runner/graphql/runner_node.fragment.graphql"
|
#import "~/runner/graphql/list/list_item.fragment.graphql"
|
||||||
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
|
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
|
||||||
|
|
||||||
query getGroupRunners(
|
query getGroupRunners(
|
||||||
|
@ -29,8 +29,7 @@ query getGroupRunners(
|
||||||
webUrl
|
webUrl
|
||||||
editUrl
|
editUrl
|
||||||
node {
|
node {
|
||||||
__typename
|
...ListItem
|
||||||
...RunnerNode
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
|
@ -1,4 +1,4 @@
|
||||||
fragment RunnerNode on CiRunner {
|
fragment ListItem on CiRunner {
|
||||||
__typename
|
__typename
|
||||||
id
|
id
|
||||||
description
|
description
|
|
@ -24,8 +24,8 @@ import {
|
||||||
STATUS_OFFLINE,
|
STATUS_OFFLINE,
|
||||||
STATUS_STALE,
|
STATUS_STALE,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import getGroupRunnersQuery from '../graphql/get_group_runners.query.graphql';
|
import groupRunnersQuery from '../graphql/list/group_runners.query.graphql';
|
||||||
import getGroupRunnersCountQuery from '../graphql/get_group_runners_count.query.graphql';
|
import groupRunnersCountQuery from '../graphql/list/group_runners_count.query.graphql';
|
||||||
import {
|
import {
|
||||||
fromUrlQueryToSearch,
|
fromUrlQueryToSearch,
|
||||||
fromSearchToUrl,
|
fromSearchToUrl,
|
||||||
|
@ -34,7 +34,7 @@ import {
|
||||||
import { captureException } from '../sentry_utils';
|
import { captureException } from '../sentry_utils';
|
||||||
|
|
||||||
const runnersCountSmartQuery = {
|
const runnersCountSmartQuery = {
|
||||||
query: getGroupRunnersCountQuery,
|
query: groupRunnersCountQuery,
|
||||||
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
|
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
|
||||||
update(data) {
|
update(data) {
|
||||||
return data?.group?.runners?.count;
|
return data?.group?.runners?.count;
|
||||||
|
@ -84,7 +84,7 @@ export default {
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
runners: {
|
runners: {
|
||||||
query: getGroupRunnersQuery,
|
query: groupRunnersQuery,
|
||||||
// Runners can be updated by users directly in this list.
|
// Runners can be updated by users directly in this list.
|
||||||
// A "cache and network" policy prevents outdated filtered
|
// A "cache and network" policy prevents outdated filtered
|
||||||
// results.
|
// results.
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
class Projects::ClusterAgentsController < Projects::ApplicationController
|
class Projects::ClusterAgentsController < Projects::ApplicationController
|
||||||
before_action :authorize_can_read_cluster_agent!
|
before_action :authorize_can_read_cluster_agent!
|
||||||
|
|
||||||
before_action do
|
|
||||||
push_frontend_feature_flag(:cluster_vulnerabilities, project, default_enabled: :yaml)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature_category :kubernetes_management
|
feature_category :kubernetes_management
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -3,20 +3,6 @@
|
||||||
class ApplicationExperiment < Gitlab::Experiment
|
class ApplicationExperiment < Gitlab::Experiment
|
||||||
control { nil } # provide a default control for anonymous experiments
|
control { nil } # provide a default control for anonymous experiments
|
||||||
|
|
||||||
def publish(_result = nil)
|
|
||||||
super
|
|
||||||
|
|
||||||
publish_to_client
|
|
||||||
end
|
|
||||||
|
|
||||||
def publish_to_client
|
|
||||||
return unless should_track?
|
|
||||||
|
|
||||||
Gon.push({ experiment: { name => signature } }, true)
|
|
||||||
rescue NoMethodError
|
|
||||||
# means we're not in the request cycle, and can't add to Gon. Log a warning maybe?
|
|
||||||
end
|
|
||||||
|
|
||||||
def publish_to_database
|
def publish_to_database
|
||||||
ActiveSupport::Deprecation.warn('publish_to_database is deprecated and should not be used for reporting anymore')
|
ActiveSupport::Deprecation.warn('publish_to_database is deprecated and should not be used for reporting anymore')
|
||||||
|
|
||||||
|
|
|
@ -16,4 +16,11 @@ module DeployTokensHelper
|
||||||
Gitlab.config.packages.enabled &&
|
Gitlab.config.packages.enabled &&
|
||||||
can?(current_user, :read_package, group_or_project)
|
can?(current_user, :read_package, group_or_project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def deploy_token_revoke_button_data(token:, group_or_project:)
|
||||||
|
{
|
||||||
|
token: token.to_json(only: [:id, :name]),
|
||||||
|
revoke_path: revoke_deploy_token_path(group_or_project, token)
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -111,8 +111,8 @@ module Integrations
|
||||||
end
|
end
|
||||||
|
|
||||||
def help
|
def help
|
||||||
jira_doc_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_url('integration/jira/index.html') }
|
jira_doc_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('integration/jira/index.html') }
|
||||||
s_("JiraService|You must configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}.") % { jira_doc_link_start: jira_doc_link_start, link_end: '</a>'.html_safe }
|
s_("JiraService|You must configure Jira before enabling this integration. %{jira_doc_link_start}Learn more.%{link_end}") % { jira_doc_link_start: jira_doc_link_start, link_end: '</a>'.html_safe }
|
||||||
end
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
|
|
|
@ -40,12 +40,7 @@ class Namespace
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
Namespace.transaction do
|
Namespace.transaction do
|
||||||
if Feature.enabled?(:for_no_key_update_lock, default_enabled: :yaml)
|
@root.lock!("FOR NO KEY UPDATE")
|
||||||
@root.lock!("FOR NO KEY UPDATE")
|
|
||||||
else
|
|
||||||
@root.lock!
|
|
||||||
end
|
|
||||||
|
|
||||||
Namespace.connection.exec_query(sql)
|
Namespace.connection.exec_query(sql)
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::Deadlocked
|
rescue ActiveRecord::Deadlocked
|
||||||
|
|
|
@ -44,22 +44,15 @@ module Namespaces
|
||||||
included do
|
included do
|
||||||
before_update :lock_both_roots, if: -> { sync_traversal_ids? && parent_id_changed? }
|
before_update :lock_both_roots, if: -> { sync_traversal_ids? && parent_id_changed? }
|
||||||
after_update :sync_traversal_ids, if: -> { sync_traversal_ids? && saved_change_to_parent_id? }
|
after_update :sync_traversal_ids, if: -> { sync_traversal_ids? && saved_change_to_parent_id? }
|
||||||
# sync traversal_ids on namespace create, which can happen quite early within a transaction, thus keeping the lock on root namespace record
|
|
||||||
# for a relatively long time, e.g. creating the project namespace when a project is being created.
|
|
||||||
after_create :sync_traversal_ids, if: -> { sync_traversal_ids? && !sync_traversal_ids_before_commit? }
|
|
||||||
# This uses rails internal before_commit API to sync traversal_ids on namespace create, right before transaction is committed.
|
# This uses rails internal before_commit API to sync traversal_ids on namespace create, right before transaction is committed.
|
||||||
# This helps reduce the time during which the root namespace record is locked to ensure updated traversal_ids are valid
|
# This helps reduce the time during which the root namespace record is locked to ensure updated traversal_ids are valid
|
||||||
before_commit :sync_traversal_ids, on: [:create], if: -> { sync_traversal_ids? && sync_traversal_ids_before_commit? }
|
before_commit :sync_traversal_ids, on: [:create], if: -> { sync_traversal_ids? }
|
||||||
end
|
end
|
||||||
|
|
||||||
def sync_traversal_ids?
|
def sync_traversal_ids?
|
||||||
Feature.enabled?(:sync_traversal_ids, root_ancestor, default_enabled: :yaml)
|
Feature.enabled?(:sync_traversal_ids, root_ancestor, default_enabled: :yaml)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sync_traversal_ids_before_commit?
|
|
||||||
Feature.enabled?(:sync_traversal_ids_before_commit, root_ancestor, default_enabled: :yaml)
|
|
||||||
end
|
|
||||||
|
|
||||||
def use_traversal_ids?
|
def use_traversal_ids?
|
||||||
return false unless Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
|
return false unless Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,15 @@
|
||||||
= f.label :eks_account_id, _('Account ID'), class: 'label-bold'
|
= f.label :eks_account_id, _('Account ID'), class: 'label-bold'
|
||||||
= f.text_field :eks_account_id, class: 'form-control gl-form-input'
|
= f.text_field :eks_account_id, class: 'form-control gl-form-input'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :eks_access_key_id, _('Access key ID'), class: 'label-bold'
|
= f.label :eks_access_key_id, _('AWS access key ID (Optional)'), class: 'label-bold'
|
||||||
= f.text_field :eks_access_key_id, class: 'form-control gl-form-input'
|
= f.text_field :eks_access_key_id, class: 'form-control gl-form-input'
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= _('AWS Access Key. Only required if not using role instance credentials')
|
= _('Only required if not using role instance credentials.')
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :eks_secret_access_key, _('Secret access key'), class: 'label-bold'
|
= f.label :eks_secret_access_key, _('AWS secret access key (Optional)'), class: 'label-bold'
|
||||||
= f.password_field :eks_secret_access_key, autocomplete: 'off', class: 'form-control gl-form-input'
|
= f.password_field :eks_secret_access_key, autocomplete: 'off', class: 'form-control gl-form-input'
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= _('AWS Secret Access Key. Only required if not using role instance credentials')
|
= _('Only required if not using role instance credentials.')
|
||||||
|
|
||||||
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
|
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
- link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
|
- link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
|
||||||
= s_('SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance\'s code views and merge requests.').html_safe % { link_start: link_start, link_end: link_end }
|
= s_('SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance\'s code views and merge requests.').html_safe % { link_start: link_start, link_end: link_end }
|
||||||
%span
|
%span
|
||||||
= link_to s_('SourcegraphAdmin|More information'), help_page_path('integration/sourcegraph.md'), target: '_blank', rel: 'noopener noreferrer'
|
= link_to s_('SourcegraphAdmin|Learn more.'), help_page_path('integration/sourcegraph.md'), target: '_blank', rel: 'noopener noreferrer'
|
||||||
|
|
||||||
|
|
||||||
.settings-content
|
.settings-content
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
= f.check_box :sourcegraph_public_only, class: 'form-check-input'
|
= f.check_box :sourcegraph_public_only, class: 'form-check-input'
|
||||||
= f.label :sourcegraph_public_only, s_('SourcegraphAdmin|Block on private and internal projects'), class: 'form-check-label'
|
= f.label :sourcegraph_public_only, s_('SourcegraphAdmin|Block on private and internal projects'), class: 'form-check-label'
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= s_('SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph.')
|
= s_('SourcegraphAdmin|Only public projects have code intelligence enabled and communicate with Sourcegraph.')
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :sourcegraph_url, s_('SourcegraphAdmin|Sourcegraph URL'), class: 'label-bold'
|
= f.label :sourcegraph_url, s_('SourcegraphAdmin|Sourcegraph URL'), class: 'label-bold'
|
||||||
= f.text_field :sourcegraph_url, class: 'form-control gl-form-input', placeholder: s_('SourcegraphAdmin|e.g. https://sourcegraph.example.com')
|
= f.text_field :sourcegraph_url, class: 'form-control gl-form-input', placeholder: s_('SourcegraphAdmin|https://sourcegraph.example.com')
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= s_('SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects.')
|
= s_('SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects.')
|
||||||
= f.submit s_('SourcegraphAdmin|Save changes'), class: 'gl-button btn btn-confirm'
|
= f.submit s_('SourcegraphAdmin|Save changes'), class: 'gl-button btn btn-confirm'
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
.gl-w-half.gl-xs-w-full
|
.gl-w-half.gl-xs-w-full
|
||||||
.gl-display-flex.gl-flex-wrap.gl-justify-content-end.gl-mb-3
|
.gl-display-flex.gl-flex-wrap.gl-justify-content-end.gl-mb-3
|
||||||
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite a group') } }
|
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite a group') } }
|
||||||
.js-invite-members-trigger{ data: { variant: 'success',
|
.js-invite-members-trigger{ data: { variant: 'confirm',
|
||||||
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
|
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
|
||||||
trigger_source: 'group-members-page',
|
trigger_source: 'group-members-page',
|
||||||
display_text: _('Invite members') } }
|
display_text: _('Invite members') } }
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite a group') } }
|
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite a group') } }
|
||||||
= render 'projects/invite_groups_modal', project: @project
|
= render 'projects/invite_groups_modal', project: @project
|
||||||
- if can_admin_project_member?(@project)
|
- if can_admin_project_member?(@project)
|
||||||
.js-invite-members-trigger{ data: { variant: 'success',
|
.js-invite-members-trigger{ data: { variant: 'confirm',
|
||||||
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
|
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
|
||||||
trigger_source: 'project-members-page',
|
trigger_source: 'project-members-page',
|
||||||
display_text: _('Invite members') } }
|
display_text: _('Invite members') } }
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
%span.token-never-expires-label= _('Never')
|
%span.token-never-expires-label= _('Never')
|
||||||
%td= token.scopes.present? ? token.scopes.join(', ') : _('no scopes selected')
|
%td= token.scopes.present? ? token.scopes.join(', ') : _('no scopes selected')
|
||||||
%td
|
%td
|
||||||
.js-deploy-token-revoke-button{ data: { button_class: 'float-right', token: token.to_json, revoke_path: revoke_deploy_token_path(group_or_project, token) } }
|
.js-deploy-token-revoke-button{ data: deploy_token_revoke_button_data(token: token, group_or_project: group_or_project) }
|
||||||
|
|
||||||
- else
|
- else
|
||||||
.settings-message.text-center
|
.settings-message.text-center
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: cluster_vulnerabilities
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73321
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343917
|
|
||||||
milestone: '14.5'
|
|
||||||
type: development
|
|
||||||
group: group::container security
|
|
||||||
default_enabled: true
|
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: for_no_key_update_lock
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81239
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353619
|
|
||||||
milestone: '14.9'
|
|
||||||
type: development
|
|
||||||
group: group::workspaces
|
|
||||||
default_enabled: false
|
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: sync_traversal_ids_before_commit
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79964
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352499
|
|
||||||
group: group::workspace
|
|
||||||
type: development
|
|
||||||
default_enabled: false
|
|
||||||
milestone: '14.8'
|
|
|
@ -317,7 +317,7 @@ of tracking an event in Ruby would be:
|
||||||
experiment(:pill_color, actor: current_user).track(:clicked)
|
experiment(:pill_color, actor: current_user).track(:clicked)
|
||||||
```
|
```
|
||||||
|
|
||||||
When you run an experiment with any of the examples so far, an `:assigned` event
|
When you run an experiment with any of the examples so far, an `:assignment` event
|
||||||
is tracked automatically by default. All events that are tracked from an
|
is tracked automatically by default. All events that are tracked from an
|
||||||
experiment have a special
|
experiment have a special
|
||||||
[experiment context](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-3)
|
[experiment context](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-3)
|
||||||
|
|
|
@ -50,7 +50,7 @@ To configure your project:
|
||||||
If you enable Jira issues with this setting, all users with access to this GitLab project
|
If you enable Jira issues with this setting, all users with access to this GitLab project
|
||||||
can view all issues from the specified Jira project.
|
can view all issues from the specified Jira project.
|
||||||
|
|
||||||
1. To enable [issue creation for vulnerabilities](../../user/application_security/vulnerabilities/index.md#create-a-jira-issue-for-a-vulnerability), select **Enable Jira issues creation from vulnerabilities**.
|
1. To enable [issue creation for vulnerabilities](../../user/application_security/vulnerabilities/index.md#create-a-jira-issue-for-a-vulnerability), select **Enable Jira issue creation from vulnerabilities**.
|
||||||
1. Select the **Jira issue type**. If the dropdown is empty, select refresh (**{retry}**) and try again.
|
1. Select the **Jira issue type**. If the dropdown is empty, select refresh (**{retry}**) and try again.
|
||||||
1. To verify the Jira connection is working, select **Test settings**.
|
1. To verify the Jira connection is working, select **Test settings**.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
|
@ -80,7 +80,7 @@ The issue is then opened so you can take further action.
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
|
|
||||||
- [Enable Jira integration](../../../integration/jira/index.md).
|
- [Enable Jira integration](../../../integration/jira/index.md).
|
||||||
The **Enable Jira issues creation from vulnerabilities** option must be selected as part of the configuration.
|
The **Enable Jira issue creation from vulnerabilities** option must be selected as part of the configuration.
|
||||||
- Each user must have a personal Jira user account with permission to create issues in the target project.
|
- Each user must have a personal Jira user account with permission to create issues in the target project.
|
||||||
|
|
||||||
To create a Jira issue for a vulnerability:
|
To create a Jira issue for a vulnerability:
|
||||||
|
|
|
@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
# Container vulnerability scanning **(ULTIMATE)**
|
# Container vulnerability scanning **(ULTIMATE)**
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6346) in GitLab 14.8 [with a flag](../../../administration/feature_flags.md) named `cluster_vulnerabilities`. Enabled by default.
|
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6346) in GitLab 14.8.
|
||||||
|
|
||||||
To view cluster vulnerabilities, you can view the [vulnerability report](../../application_security/vulnerabilities/index.md).
|
To view cluster vulnerabilities, you can view the [vulnerability report](../../application_security/vulnerabilities/index.md).
|
||||||
You can also configure your agent so the vulnerabilities are displayed with other agent information in GitLab.
|
You can also configure your agent so the vulnerabilities are displayed with other agent information in GitLab.
|
||||||
|
|
|
@ -67,15 +67,15 @@ Features not found in standard Markdown:
|
||||||
|
|
||||||
Features [extended from standard Markdown](#features-extended-from-standard-markdown):
|
Features [extended from standard Markdown](#features-extended-from-standard-markdown):
|
||||||
|
|
||||||
| Standard Markdown | Extended Markdown in GitLab |
|
| Standard Markdown | Extended Markdown in GitLab |
|
||||||
| ------------------------------------- | ------------------------- |
|
|---------------------------------------|---------------------------------------------------------------------------------------|
|
||||||
| [blockquotes](#blockquotes) | [multi-line blockquotes](#multiline-blockquote) |
|
| [blockquotes](#blockquotes) | [multi-line blockquotes](#multiline-blockquote) |
|
||||||
| [code blocks](#code-spans-and-blocks) | [colored code and syntax highlighting](#colored-code-and-syntax-highlighting) |
|
| [code blocks](#code-spans-and-blocks) | [colored code and syntax highlighting](#colored-code-and-syntax-highlighting) |
|
||||||
| [emphasis](#emphasis) | [multiple underscores in words](#multiple-underscores-in-words-and-mid-word-emphasis)
|
| [emphasis](#emphasis) | [multiple underscores in words](#multiple-underscores-in-words-and-mid-word-emphasis) |
|
||||||
| [headers](#headers) | [linkable Header IDs](#header-ids-and-links) |
|
| [headers](#headers) | [linkable Header IDs](#header-ids-and-links) |
|
||||||
| [images](#images) | [embedded videos](#videos) and [audio](#audio) |
|
| [images](#images) | [embedded videos](#videos) and [audio](#audio) |
|
||||||
| [line breaks](#line-breaks) | [more line break control](#newlines) |
|
| [line breaks](#line-breaks) | [more line break control](#newlines) |
|
||||||
| [links](#links) | [automatically linking URLs](#url-auto-linking) |
|
| [links](#links) | [automatically linking URLs](#url-auto-linking) |
|
||||||
|
|
||||||
## Features not found in standard Markdown
|
## Features not found in standard Markdown
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ The following delimiters are supported:
|
||||||
---
|
---
|
||||||
title: About Front Matter
|
title: About Front Matter
|
||||||
example:
|
example:
|
||||||
language: yaml
|
language: yaml
|
||||||
---
|
---
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -515,31 +515,31 @@ version to reference other projects from the same namespace.
|
||||||
|
|
||||||
GitLab Flavored Markdown recognizes the following:
|
GitLab Flavored Markdown recognizes the following:
|
||||||
|
|
||||||
| references | input | cross-project reference | shortcut inside same namespace |
|
| references | input | cross-project reference | shortcut inside same namespace |
|
||||||
| :--------------------------------------------------- | :---------------------------- | :----------------------------------------- | :------------------------------- |
|
|:----------------------------------------------------------------------------|:------------------------------|:----------------------------------------|:-------------------------------|
|
||||||
| specific user | `@user_name` | | |
|
| specific user | `@user_name` | | |
|
||||||
| specific group | `@group_name` | | |
|
| specific group | `@group_name` | | |
|
||||||
| entire team | `@all` | | |
|
| entire team | `@all` | | |
|
||||||
| project | `namespace/project>` | | |
|
| project | `namespace/project>` | | |
|
||||||
| issue | ``#123`` | `namespace/project#123` | `project#123` |
|
| issue | ``#123`` | `namespace/project#123` | `project#123` |
|
||||||
| merge request | `!123` | `namespace/project!123` | `project!123` |
|
| merge request | `!123` | `namespace/project!123` | `project!123` |
|
||||||
| snippet | `$123` | `namespace/project$123` | `project$123` |
|
| snippet | `$123` | `namespace/project$123` | `project$123` |
|
||||||
| [epic](group/epics/index.md) | `&123` | `group1/subgroup&123` | |
|
| [epic](group/epics/index.md) | `&123` | `group1/subgroup&123` | |
|
||||||
| vulnerability **(ULTIMATE)** <sup>1</sup> | `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
|
| [vulnerability](application_security/vulnerabilities/index.md) <sup>1</sup> | `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
|
||||||
| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
|
| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
|
||||||
| label by ID | `~123` | `namespace/project~123` | `project~123` |
|
| label by ID | `~123` | `namespace/project~123` | `project~123` |
|
||||||
| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
|
| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
|
||||||
| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
|
| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
|
||||||
| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
|
| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
|
||||||
| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
|
| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
|
||||||
| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
|
| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
|
||||||
| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
|
| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
|
||||||
| specific commit | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` |
|
| specific commit | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` |
|
||||||
| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
|
| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
|
||||||
| repository file references | `[README](doc/README.md)` | | |
|
| repository file references | `[README](doc/README.md)` | | |
|
||||||
| repository file line references | `[README](doc/README.md#L13)` | | |
|
| repository file line references | `[README](doc/README.md#L13)` | | |
|
||||||
| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
|
| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
|
||||||
| contact | `[contact:test@example.com]` | | |
|
| contact | `[contact:test@example.com]` | | |
|
||||||
|
|
||||||
1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
|
1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
|
||||||
|
|
||||||
|
@ -1486,7 +1486,7 @@ but they do not render properly on `docs.gitlab.com`:
|
||||||
|
|
||||||
#### Copy from spreadsheet and paste in Markdown
|
#### Copy from spreadsheet and paste in Markdown
|
||||||
|
|
||||||
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27205) in GitLab 12.7.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27205) in GitLab 12.7.
|
||||||
|
|
||||||
If you're working in spreadsheet software (for example, Microsoft Excel, Google
|
If you're working in spreadsheet software (for example, Microsoft Excel, Google
|
||||||
Sheets, or Apple Numbers), GitLab creates a Markdown table when you copy-and-paste
|
Sheets, or Apple Numbers), GitLab creates a Markdown table when you copy-and-paste
|
||||||
|
|
|
@ -34,7 +34,8 @@ in the search field in the upper right corner:
|
||||||
|
|
||||||
> - Filtering by epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9.
|
> - Filtering by epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9.
|
||||||
> - Filtering by child epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab 13.0.
|
> - Filtering by child epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab 13.0.
|
||||||
> - Filtering by iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. Moved from GitLab Ultimate to Premium in 13.9.
|
> - Filtering by iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6.
|
||||||
|
> - Filtering by iterations was moved from GitLab Ultimate to GitLab Premium in 13.9.
|
||||||
> - Filtering by type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 13.10 [with a flag](../../administration/feature_flags.md) named `vue_issues_list`. Disabled by default.
|
> - Filtering by type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 13.10 [with a flag](../../administration/feature_flags.md) named `vue_issues_list`. Disabled by default.
|
||||||
|
|
||||||
Follow these steps to filter the **Issues** and **Merge requests** list pages in projects and
|
Follow these steps to filter the **Issues** and **Merge requests** list pages in projects and
|
||||||
|
@ -127,14 +128,14 @@ the dropdown list) **Approved-By** and select the user.
|
||||||
|
|
||||||
![Filter MRs by approved by](img/filter_approved_by_merge_requests_v14_6.png)
|
![Filter MRs by approved by](img/filter_approved_by_merge_requests_v14_6.png)
|
||||||
|
|
||||||
### Filtering merge requests by reviewer **(FREE)**
|
### Filtering merge requests by reviewer
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47605) in GitLab 13.7.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47605) in GitLab 13.7.
|
||||||
|
|
||||||
To filter review requested merge requests for a specific individual, you can type (or select from
|
To filter review requested merge requests for a specific individual, you can type (or select from
|
||||||
the dropdown list) **Reviewer** and select the user.
|
the dropdown list) **Reviewer** and select the user.
|
||||||
|
|
||||||
### Filtering merge requests by environment or deployment date **(FREE)**
|
### Filtering merge requests by environment or deployment date
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6.
|
||||||
|
|
||||||
|
@ -307,7 +308,7 @@ GitLab instance.
|
||||||
## Search settings
|
## Search settings
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8 [with a flag](../../administration/feature_flags.md) named `search_settings_in_page`. Disabled by default.
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8 [with a flag](../../administration/feature_flags.md) named `search_settings_in_page`. Disabled by default.
|
||||||
> - [Added to Group, Administrator, and User settings](https://gitlab.com/groups/gitlab-org/-/epics/4842) in GitLab 13.9.
|
> - [Added](https://gitlab.com/groups/gitlab-org/-/epics/4842) to Group, Administrator, and User settings in GitLab 13.9.
|
||||||
> - [Feature flag `search_settings_in_page` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
|
> - [Feature flag `search_settings_in_page` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
|
||||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
|
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,7 @@ You can create snippets in multiple ways, depending on whether you want to creat
|
||||||
**New snippet**, or:
|
**New snippet**, or:
|
||||||
- *If you're on a project's page,* select the plus icon (**{plus-square-o}**)
|
- *If you're on a project's page,* select the plus icon (**{plus-square-o}**)
|
||||||
in the top navigation bar, and then select **New snippet** from the
|
in the top navigation bar, and then select **New snippet** from the
|
||||||
**GitLab** (GitLab SaaS) or **Your Instance** (self-managed) section
|
**GitLab** section of the same dropdown list.
|
||||||
of the same dropdown list.
|
|
||||||
- *For all other pages,* select the plus icon (**{plus-square-o}**)
|
- *For all other pages,* select the plus icon (**{plus-square-o}**)
|
||||||
in the top navigation bar, then select **New snippet** from the dropdown list.
|
in the top navigation bar, then select **New snippet** from the dropdown list.
|
||||||
- If you installed the [GitLab Workflow VS Code extension](project/repository/vscode.md),
|
- If you installed the [GitLab Workflow VS Code extension](project/repository/vscode.md),
|
||||||
|
@ -153,8 +152,7 @@ To delete a file from your snippet through the GitLab UI:
|
||||||
|
|
||||||
1. Go to your snippet in the GitLab UI.
|
1. Go to your snippet in the GitLab UI.
|
||||||
1. Select **Edit** in the top right corner.
|
1. Select **Edit** in the top right corner.
|
||||||
1. Select **Delete file** alongside the filename of each file
|
1. Select **Delete file** alongside the filename of each file you wish to delete.
|
||||||
you wish to delete.
|
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
## Clone snippets
|
## Clone snippets
|
||||||
|
|
|
@ -1773,13 +1773,13 @@ msgstr ""
|
||||||
msgid "AWS Access Key"
|
msgid "AWS Access Key"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "AWS Access Key. Only required if not using role instance credentials"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "AWS Secret Access Key"
|
msgid "AWS Secret Access Key"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "AWS Secret Access Key. Only required if not using role instance credentials"
|
msgid "AWS access key ID (Optional)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AWS secret access key (Optional)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "AWS service error: %{error}"
|
msgid "AWS service error: %{error}"
|
||||||
|
@ -1839,9 +1839,6 @@ msgstr ""
|
||||||
msgid "Access granted"
|
msgid "Access granted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Access key ID"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Access requests"
|
msgid "Access requests"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -19864,9 +19861,6 @@ msgstr ""
|
||||||
msgid "Integrations|Use default settings"
|
msgid "Integrations|Use default settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
|
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -20830,15 +20824,15 @@ msgstr ""
|
||||||
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
|
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
|
msgid "JiraService|Displaying Jira issues while leaving GitLab issues also enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "JiraService|Enable Jira issue creation from vulnerabilities"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Enable Jira issues"
|
msgid "JiraService|Enable Jira issues"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "JiraService|Enable Jira transitions"
|
msgid "JiraService|Enable Jira transitions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -20953,16 +20947,19 @@ msgstr ""
|
||||||
msgid "JiraService|View Jira issues in GitLab"
|
msgid "JiraService|View Jira issues in GitLab"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below."
|
msgid "JiraService|Warning: All GitLab users with access to this GitLab project can view all issues from the Jira project you select."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Web URL"
|
msgid "JiraService|Web URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
|
msgid "JiraService|When a Jira issue is mentioned in a commit or merge request, a remote link and comment (if enabled) will be created."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|You must configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
|
msgid "JiraService|Work on Jira issues without leaving GitLab. Add a Jira menu to access a read-only list of your Jira issues."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "JiraService|You must configure Jira before enabling this integration. %{jira_doc_link_start}Learn more.%{link_end}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Job"
|
msgid "Job"
|
||||||
|
@ -25611,6 +25608,9 @@ msgstr ""
|
||||||
msgid "Only reCAPTCHA v2 is supported:"
|
msgid "Only reCAPTCHA v2 is supported:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Only required if not using role instance credentials."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Only use lowercase letters, numbers, and underscores."
|
msgid "Only use lowercase letters, numbers, and underscores."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -32290,9 +32290,6 @@ msgstr ""
|
||||||
msgid "Secret Detection"
|
msgid "Secret Detection"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Secret access key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Secret token"
|
msgid "Secret token"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -32491,9 +32488,6 @@ msgstr ""
|
||||||
msgid "SecurityOrchestration|.yaml preview"
|
msgid "SecurityOrchestration|.yaml preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Action"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Actions"
|
msgid "SecurityOrchestration|Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -32536,9 +32530,6 @@ msgstr ""
|
||||||
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
|
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Executes a %{scanType} scan"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
|
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -32554,6 +32545,9 @@ msgstr ""
|
||||||
msgid "SecurityOrchestration|New policy"
|
msgid "SecurityOrchestration|New policy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "SecurityOrchestration|No actions defined - policy will not run."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|No description"
|
msgid "SecurityOrchestration|No description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -32596,10 +32590,13 @@ msgstr ""
|
||||||
msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
|
msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Rule"
|
msgid "SecurityOrchestration|Rules"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Rules"
|
msgid "SecurityOrchestration|Runs %{actions} and %{lastAction} scans"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "SecurityOrchestration|Runs a %{action} scan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityOrchestration|Scan Execution"
|
msgid "SecurityOrchestration|Scan Execution"
|
||||||
|
@ -34688,10 +34685,10 @@ msgstr ""
|
||||||
msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
|
msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph."
|
msgid "SourcegraphAdmin|Learn more."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SourcegraphAdmin|More information"
|
msgid "SourcegraphAdmin|Only public projects have code intelligence enabled and communicate with Sourcegraph."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SourcegraphAdmin|Save changes"
|
msgid "SourcegraphAdmin|Save changes"
|
||||||
|
@ -34700,7 +34697,7 @@ msgstr ""
|
||||||
msgid "SourcegraphAdmin|Sourcegraph URL"
|
msgid "SourcegraphAdmin|Sourcegraph URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
|
msgid "SourcegraphAdmin|https://sourcegraph.example.com"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
|
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3')
|
||||||
|
const { fromIni } = require('@aws-sdk/credential-provider-ini')
|
||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const crypto = require('crypto')
|
||||||
|
|
||||||
|
function getMD5HashFromFile(data) {
|
||||||
|
const hash = crypto.createHash('md5').update(data).digest('base64')
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const s3Client = new S3Client({
|
||||||
|
region: 'us-east-2',
|
||||||
|
credentials: fromIni({ profile: 'gl-logs-for-panther' }),
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
const file = 'gl-dependency-scanning-report.json'
|
||||||
|
const data = fs.readFileSync(file)
|
||||||
|
const responseData = await s3Client.send(
|
||||||
|
new PutObjectCommand({
|
||||||
|
Bucket: 'gl-logs-for-panther-test',
|
||||||
|
Key: path.join('package_hunter_test', path.basename(file)),
|
||||||
|
Body: data,
|
||||||
|
ContentMD5: getMD5HashFromFile(data),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
console.log('Successfully uploaded %s', file)
|
||||||
|
} catch (err) {
|
||||||
|
if (err.name === 'CredentialsProviderError' || err.name === 'AuthorizationHeaderMalformed')
|
||||||
|
console.log('Could not upload the report. Are AWS credentials configured in ~/.aws/credentials?')
|
||||||
|
else
|
||||||
|
console.log('Unexpected error during upload.')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
})()
|
|
@ -28,63 +28,25 @@ RSpec.describe ApplicationExperiment, :experiment do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#publish" do
|
describe "#publish" do
|
||||||
let(:should_track) { true }
|
|
||||||
|
|
||||||
before do
|
|
||||||
allow(application_experiment).to receive(:should_track?).and_return(should_track)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "tracks the assignment", :snowplow do
|
it "tracks the assignment", :snowplow do
|
||||||
|
expect(application_experiment).to receive(:track).with(:assignment)
|
||||||
|
|
||||||
|
application_experiment.publish
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adds to the published experiments" do
|
||||||
|
# These are surfaced in the client layer by rendering them in the
|
||||||
|
# _published_experiments.html.haml partial.
|
||||||
application_experiment.publish
|
application_experiment.publish
|
||||||
|
|
||||||
expect_snowplow_event(
|
expect(ApplicationExperiment.published_experiments['namespaced/stub']).to include(
|
||||||
category: 'namespaced/stub',
|
experiment: 'namespaced/stub',
|
||||||
action: 'assignment',
|
excluded: false,
|
||||||
context: [{ schema: anything, data: anything }]
|
key: anything,
|
||||||
|
variant: 'control'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "publishes to the client" do
|
|
||||||
expect(application_experiment).to receive(:publish_to_client)
|
|
||||||
|
|
||||||
application_experiment.publish
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when we should not track' do
|
|
||||||
let(:should_track) { false }
|
|
||||||
|
|
||||||
it 'does not track an event to Snowplow', :snowplow do
|
|
||||||
application_experiment.publish
|
|
||||||
|
|
||||||
expect_no_snowplow_event
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#publish_to_client" do
|
|
||||||
it "adds the data into Gon" do
|
|
||||||
signature = { key: '86208ac54ca798e11f127e8b23ec396a', variant: 'control' }
|
|
||||||
expect(Gon).to receive(:push).with({ experiment: { 'namespaced/stub' => hash_including(signature) } }, true)
|
|
||||||
|
|
||||||
application_experiment.publish_to_client
|
|
||||||
end
|
|
||||||
|
|
||||||
it "handles when Gon raises exceptions (like when it can't be pushed into)" do
|
|
||||||
expect(Gon).to receive(:push).and_raise(NoMethodError)
|
|
||||||
|
|
||||||
expect { application_experiment.publish_to_client }.not_to raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when we should not track' do
|
|
||||||
let(:should_track) { false }
|
|
||||||
|
|
||||||
it 'returns early' do
|
|
||||||
expect(Gon).not_to receive(:push)
|
|
||||||
|
|
||||||
application_experiment.publish_to_client
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#publish_to_database' do
|
describe '#publish_to_database' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
using RSpec::Parameterized::TableSyntax
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,8 @@ RSpec.describe "User views incident" do
|
||||||
visit(project_issues_incident_path(project, incident))
|
visit(project_issues_incident_path(project, incident))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not show the incident action', :js, :aggregate_failures do
|
it 'does not show the incident actions', :js, :aggregate_failures do
|
||||||
click_button 'Incident actions'
|
expect(page).not_to have_button('Incident actions')
|
||||||
|
|
||||||
expect(page).not_to have_link('New incident')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,11 +70,6 @@ describe('RevokeButton', () => {
|
||||||
expect(findRevokeButton().exists()).toBe(true);
|
expect(findRevokeButton().exists()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the buttonClass to the button', () => {
|
|
||||||
wrapper = createComponent({ buttonClass: 'my-revoke-button' });
|
|
||||||
expect(findRevokeButton().classes()).toContain('my-revoke-button');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('opens the modal', () => {
|
it('opens the modal', () => {
|
||||||
findRevokeButton().trigger('click');
|
findRevokeButton().trigger('click');
|
||||||
expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.modalId);
|
expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.modalId);
|
||||||
|
|
|
@ -33,19 +33,19 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_runners_query_name = 'get_runners.query.graphql'
|
admin_runners_query = 'list/admin_runners.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_runners_query_name}")
|
get_graphql_query_as_string("#{query_path}#{admin_runners_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runners_query_name}.json" do
|
it "#{fixtures_path}#{admin_runners_query}.json" do
|
||||||
post_graphql(query, current_user: admin, variables: {})
|
post_graphql(query, current_user: admin, variables: {})
|
||||||
|
|
||||||
expect_graphql_errors_to_be_empty
|
expect_graphql_errors_to_be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runners_query_name}.paginated.json" do
|
it "#{fixtures_path}#{admin_runners_query}.paginated.json" do
|
||||||
post_graphql(query, current_user: admin, variables: { first: 2 })
|
post_graphql(query, current_user: admin, variables: { first: 2 })
|
||||||
|
|
||||||
expect_graphql_errors_to_be_empty
|
expect_graphql_errors_to_be_empty
|
||||||
|
@ -53,13 +53,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_runners_count_query_name = 'get_runners_count.query.graphql'
|
admin_runners_count_query = 'list/admin_runners_count.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_runners_count_query_name}")
|
get_graphql_query_as_string("#{query_path}#{admin_runners_count_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runners_count_query_name}.json" do
|
it "#{fixtures_path}#{admin_runners_count_query}.json" do
|
||||||
post_graphql(query, current_user: admin, variables: {})
|
post_graphql(query, current_user: admin, variables: {})
|
||||||
|
|
||||||
expect_graphql_errors_to_be_empty
|
expect_graphql_errors_to_be_empty
|
||||||
|
@ -67,13 +67,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_runner_query_name = 'get_runner.query.graphql'
|
runner_query = 'details/runner.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_runner_query_name}")
|
get_graphql_query_as_string("#{query_path}#{runner_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runner_query_name}.json" do
|
it "#{fixtures_path}#{runner_query}.json" do
|
||||||
post_graphql(query, current_user: admin, variables: {
|
post_graphql(query, current_user: admin, variables: {
|
||||||
id: instance_runner.to_global_id.to_s
|
id: instance_runner.to_global_id.to_s
|
||||||
})
|
})
|
||||||
|
@ -81,7 +81,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
expect_graphql_errors_to_be_empty
|
expect_graphql_errors_to_be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runner_query_name}.with_group.json" do
|
it "#{fixtures_path}#{runner_query}.with_group.json" do
|
||||||
post_graphql(query, current_user: admin, variables: {
|
post_graphql(query, current_user: admin, variables: {
|
||||||
id: group_runner.to_global_id.to_s
|
id: group_runner.to_global_id.to_s
|
||||||
})
|
})
|
||||||
|
@ -91,13 +91,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_runner_projects_query_name = 'get_runner_projects.query.graphql'
|
runner_projects_query = 'details/runner_projects.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_runner_projects_query_name}")
|
get_graphql_query_as_string("#{query_path}#{runner_projects_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runner_projects_query_name}.json" do
|
it "#{fixtures_path}#{runner_projects_query}.json" do
|
||||||
post_graphql(query, current_user: admin, variables: {
|
post_graphql(query, current_user: admin, variables: {
|
||||||
id: project_runner.to_global_id.to_s
|
id: project_runner.to_global_id.to_s
|
||||||
})
|
})
|
||||||
|
@ -107,13 +107,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_runner_jobs_query_name = 'get_runner_jobs.query.graphql'
|
runner_jobs_query = 'details/runner_jobs.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_runner_jobs_query_name}")
|
get_graphql_query_as_string("#{query_path}#{runner_jobs_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_runner_jobs_query_name}.json" do
|
it "#{fixtures_path}#{runner_jobs_query}.json" do
|
||||||
post_graphql(query, current_user: admin, variables: {
|
post_graphql(query, current_user: admin, variables: {
|
||||||
id: instance_runner.to_global_id.to_s
|
id: instance_runner.to_global_id.to_s
|
||||||
})
|
})
|
||||||
|
@ -131,13 +131,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_group_runners_query_name = 'get_group_runners.query.graphql'
|
group_runners_query = 'list/group_runners.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_group_runners_query_name}")
|
get_graphql_query_as_string("#{query_path}#{group_runners_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_group_runners_query_name}.json" do
|
it "#{fixtures_path}#{group_runners_query}.json" do
|
||||||
post_graphql(query, current_user: group_owner, variables: {
|
post_graphql(query, current_user: group_owner, variables: {
|
||||||
groupFullPath: group.full_path
|
groupFullPath: group.full_path
|
||||||
})
|
})
|
||||||
|
@ -145,7 +145,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
expect_graphql_errors_to_be_empty
|
expect_graphql_errors_to_be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_group_runners_query_name}.paginated.json" do
|
it "#{fixtures_path}#{group_runners_query}.paginated.json" do
|
||||||
post_graphql(query, current_user: group_owner, variables: {
|
post_graphql(query, current_user: group_owner, variables: {
|
||||||
groupFullPath: group.full_path,
|
groupFullPath: group.full_path,
|
||||||
first: 1
|
first: 1
|
||||||
|
@ -156,13 +156,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe GraphQL::Query, type: :request do
|
describe GraphQL::Query, type: :request do
|
||||||
get_group_runners_count_query_name = 'get_group_runners_count.query.graphql'
|
group_runners_count_query = 'list/group_runners_count.query.graphql'
|
||||||
|
|
||||||
let_it_be(:query) do
|
let_it_be(:query) do
|
||||||
get_graphql_query_as_string("#{query_path}#{get_group_runners_count_query_name}")
|
get_graphql_query_as_string("#{query_path}#{group_runners_count_query}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#{fixtures_path}#{get_group_runners_count_query_name}.json" do
|
it "#{fixtures_path}#{group_runners_count_query}.json" do
|
||||||
post_graphql(query, current_user: group_owner, variables: {
|
post_graphql(query, current_user: group_owner, variables: {
|
||||||
groupFullPath: group.full_path
|
groupFullPath: group.full_path
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
|
|
||||||
import Vue, { nextTick } from 'vue';
|
import Vue, { nextTick } from 'vue';
|
||||||
|
import { GlButton, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import { mockTracking } from 'helpers/tracking_helper';
|
import { mockTracking } from 'helpers/tracking_helper';
|
||||||
|
@ -65,12 +65,17 @@ describe('HeaderActions component', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const findToggleIssueStateButton = () => wrapper.findComponent(GlButton);
|
const findToggleIssueStateButton = () => wrapper.find(GlButton);
|
||||||
const findDropdownAt = (index) => wrapper.findAllComponents(GlDropdown).at(index);
|
|
||||||
const findMobileDropdownItems = () => findDropdownAt(0).findAllComponents(GlDropdownItem);
|
const findDropdownBy = (dataTestId) => wrapper.find(`[data-testid="${dataTestId}"]`);
|
||||||
const findDesktopDropdownItems = () => findDropdownAt(1).findAllComponents(GlDropdownItem);
|
const findMobileDropdown = () => findDropdownBy('mobile-dropdown');
|
||||||
const findModal = () => wrapper.findComponent(GlModal);
|
const findDesktopDropdown = () => findDropdownBy('desktop-dropdown');
|
||||||
const findModalLinkAt = (index) => findModal().findAllComponents(GlLink).at(index);
|
const findMobileDropdownItems = () => findMobileDropdown().findAll(GlDropdownItem);
|
||||||
|
const findDesktopDropdownItems = () => findDesktopDropdown().findAll(GlDropdownItem);
|
||||||
|
|
||||||
|
const findModal = () => wrapper.find(GlModal);
|
||||||
|
|
||||||
|
const findModalLinkAt = (index) => findModal().findAll(GlLink).at(index);
|
||||||
|
|
||||||
const mountComponent = ({
|
const mountComponent = ({
|
||||||
props = {},
|
props = {},
|
||||||
|
@ -161,10 +166,10 @@ describe('HeaderActions component', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.each`
|
describe.each`
|
||||||
description | isCloseIssueItemVisible | findDropdownItems
|
description | isCloseIssueItemVisible | findDropdownItems | findDropdown
|
||||||
${'mobile dropdown'} | ${true} | ${findMobileDropdownItems}
|
${'mobile dropdown'} | ${true} | ${findMobileDropdownItems} | ${findMobileDropdown}
|
||||||
${'desktop dropdown'} | ${false} | ${findDesktopDropdownItems}
|
${'desktop dropdown'} | ${false} | ${findDesktopDropdownItems} | ${findDesktopDropdown}
|
||||||
`('$description', ({ isCloseIssueItemVisible, findDropdownItems }) => {
|
`('$description', ({ isCloseIssueItemVisible, findDropdownItems, findDropdown }) => {
|
||||||
describe.each`
|
describe.each`
|
||||||
description | itemText | isItemVisible | canUpdateIssue | canCreateIssue | isIssueAuthor | canReportSpam | canPromoteToEpic | canDestroyIssue
|
description | itemText | isItemVisible | canUpdateIssue | canCreateIssue | isIssueAuthor | canReportSpam | canPromoteToEpic | canDestroyIssue
|
||||||
${`when user can update ${issueType}`} | ${`Close ${issueType}`} | ${isCloseIssueItemVisible} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
|
${`when user can update ${issueType}`} | ${`Close ${issueType}`} | ${isCloseIssueItemVisible} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
|
||||||
|
@ -214,6 +219,24 @@ describe('HeaderActions component', () => {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
describe(`when user can update but not create ${issueType}`, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mountComponent({
|
||||||
|
props: {
|
||||||
|
canUpdateIssue: true,
|
||||||
|
canCreateIssue: false,
|
||||||
|
isIssueAuthor: true,
|
||||||
|
issueType,
|
||||||
|
canReportSpam: false,
|
||||||
|
canPromoteToEpic: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it(`${isCloseIssueItemVisible ? 'shows' : 'hides'} the dropdown button`, () => {
|
||||||
|
expect(findDropdown().exists()).toBe(isCloseIssueItemVisible);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GlSprintf } from '@gitlab/ui';
|
import { GlSprintf } from '@gitlab/ui';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
|
||||||
import Vue, { nextTick } from 'vue';
|
import Vue, { nextTick } from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
|
import { shallowMountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import InlineConflictLines from '~/merge_conflicts/components/inline_conflict_lines.vue';
|
import InlineConflictLines from '~/merge_conflicts/components/inline_conflict_lines.vue';
|
||||||
import ParallelConflictLines from '~/merge_conflicts/components/parallel_conflict_lines.vue';
|
import ParallelConflictLines from '~/merge_conflicts/components/parallel_conflict_lines.vue';
|
||||||
import component from '~/merge_conflicts/merge_conflict_resolver_app.vue';
|
import component from '~/merge_conflicts/merge_conflict_resolver_app.vue';
|
||||||
|
@ -18,7 +18,7 @@ describe('Merge Conflict Resolver App', () => {
|
||||||
const decoratedMockFiles = decorateFiles(conflictsMock.files);
|
const decoratedMockFiles = decorateFiles(conflictsMock.files);
|
||||||
|
|
||||||
const mountComponent = () => {
|
const mountComponent = () => {
|
||||||
wrapper = shallowMount(component, {
|
wrapper = shallowMountExtended(component, {
|
||||||
store,
|
store,
|
||||||
stubs: { GlSprintf },
|
stubs: { GlSprintf },
|
||||||
provide() {
|
provide() {
|
||||||
|
@ -41,15 +41,17 @@ describe('Merge Conflict Resolver App', () => {
|
||||||
wrapper.destroy();
|
wrapper.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
const findConflictsCount = () => wrapper.find('[data-testid="conflicts-count"]');
|
const findLoadingSpinner = () => wrapper.findByTestId('loading-spinner');
|
||||||
const findFiles = () => wrapper.findAll('[data-testid="files"]');
|
const findConflictsCount = () => wrapper.findByTestId('conflicts-count');
|
||||||
const findFileHeader = (w = wrapper) => w.find('[data-testid="file-name"]');
|
const findFiles = () => wrapper.findAllByTestId('files');
|
||||||
const findFileInteractiveButton = (w = wrapper) => w.find('[data-testid="interactive-button"]');
|
const findFileHeader = (w = wrapper) => extendedWrapper(w).findByTestId('file-name');
|
||||||
const findFileInlineButton = (w = wrapper) => w.find('[data-testid="inline-button"]');
|
const findFileInteractiveButton = (w = wrapper) =>
|
||||||
const findSideBySideButton = () => wrapper.find('[data-testid="side-by-side"]');
|
extendedWrapper(w).findByTestId('interactive-button');
|
||||||
|
const findFileInlineButton = (w = wrapper) => extendedWrapper(w).findByTestId('inline-button');
|
||||||
|
const findSideBySideButton = () => wrapper.findByTestId('side-by-side');
|
||||||
const findInlineConflictLines = (w = wrapper) => w.find(InlineConflictLines);
|
const findInlineConflictLines = (w = wrapper) => w.find(InlineConflictLines);
|
||||||
const findParallelConflictLines = (w = wrapper) => w.find(ParallelConflictLines);
|
const findParallelConflictLines = (w = wrapper) => w.find(ParallelConflictLines);
|
||||||
const findCommitMessageTextarea = () => wrapper.find('[data-testid="commit-message"]');
|
const findCommitMessageTextarea = () => wrapper.findByTestId('commit-message');
|
||||||
|
|
||||||
it('shows the amount of conflicts', () => {
|
it('shows the amount of conflicts', () => {
|
||||||
mountComponent();
|
mountComponent();
|
||||||
|
@ -60,6 +62,19 @@ describe('Merge Conflict Resolver App', () => {
|
||||||
expect(title.text().trim()).toBe('Showing 3 conflicts between test-conflicts and main');
|
expect(title.text().trim()).toBe('Showing 3 conflicts between test-conflicts and main');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows a loading spinner while loading', () => {
|
||||||
|
store.commit('SET_LOADING_STATE', true);
|
||||||
|
mountComponent();
|
||||||
|
|
||||||
|
expect(findLoadingSpinner().exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not show a loading spinner once loaded', () => {
|
||||||
|
mountComponent();
|
||||||
|
|
||||||
|
expect(findLoadingSpinner().exists()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
describe('files', () => {
|
describe('files', () => {
|
||||||
it('shows one file area for each file', () => {
|
it('shows one file area for each file', () => {
|
||||||
mountComponent();
|
mountComponent();
|
||||||
|
|
|
@ -18,12 +18,15 @@ import {
|
||||||
COMMIT_SUCCESS,
|
COMMIT_SUCCESS,
|
||||||
COMMIT_SUCCESS_WITH_REDIRECT,
|
COMMIT_SUCCESS_WITH_REDIRECT,
|
||||||
COMMIT_FAILURE,
|
COMMIT_FAILURE,
|
||||||
|
EDITOR_APP_STATUS_LOADING,
|
||||||
} from '~/pipeline_editor/constants';
|
} from '~/pipeline_editor/constants';
|
||||||
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql';
|
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql';
|
||||||
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
|
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
|
||||||
import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql';
|
import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql';
|
||||||
import getLatestCommitShaQuery from '~/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql';
|
import getLatestCommitShaQuery from '~/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql';
|
||||||
import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql';
|
import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql';
|
||||||
|
import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.query.graphql';
|
||||||
|
import getAppStatus from '~/pipeline_editor/graphql/queries/client/app_status.query.graphql';
|
||||||
|
|
||||||
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
|
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
|
||||||
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
|
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
|
||||||
|
@ -84,9 +87,6 @@ describe('Pipeline editor app component', () => {
|
||||||
initialCiFileContent: {
|
initialCiFileContent: {
|
||||||
loading: blobLoading,
|
loading: blobLoading,
|
||||||
},
|
},
|
||||||
ciConfigData: {
|
|
||||||
loading: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -94,7 +94,11 @@ describe('Pipeline editor app component', () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const createComponentWithApollo = async ({ provide = {}, stubs = {} } = {}) => {
|
const createComponentWithApollo = async ({
|
||||||
|
provide = {},
|
||||||
|
stubs = {},
|
||||||
|
withUndefinedBranch = false,
|
||||||
|
} = {}) => {
|
||||||
const handlers = [
|
const handlers = [
|
||||||
[getBlobContent, mockBlobContentData],
|
[getBlobContent, mockBlobContentData],
|
||||||
[getCiConfigData, mockCiConfigData],
|
[getCiConfigData, mockCiConfigData],
|
||||||
|
@ -105,6 +109,31 @@ describe('Pipeline editor app component', () => {
|
||||||
|
|
||||||
mockApollo = createMockApollo(handlers, resolvers);
|
mockApollo = createMockApollo(handlers, resolvers);
|
||||||
|
|
||||||
|
if (!withUndefinedBranch) {
|
||||||
|
mockApollo.clients.defaultClient.cache.writeQuery({
|
||||||
|
query: getCurrentBranch,
|
||||||
|
data: {
|
||||||
|
workBranches: {
|
||||||
|
__typename: 'BranchList',
|
||||||
|
current: {
|
||||||
|
__typename: 'WorkBranch',
|
||||||
|
name: mockDefaultBranch,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mockApollo.clients.defaultClient.cache.writeQuery({
|
||||||
|
query: getAppStatus,
|
||||||
|
data: {
|
||||||
|
app: {
|
||||||
|
__typename: 'AppData',
|
||||||
|
status: EDITOR_APP_STATUS_LOADING,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
localVue,
|
localVue,
|
||||||
mocks: {},
|
mocks: {},
|
||||||
|
@ -145,6 +174,55 @@ describe('Pipeline editor app component', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('skipping queries', () => {
|
||||||
|
describe('when branchName is undefined', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await createComponentWithApollo({ withUndefinedBranch: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not calls getBlobContent', () => {
|
||||||
|
expect(mockBlobContentData).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when branchName is defined', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await createComponentWithApollo();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls getBlobContent', () => {
|
||||||
|
expect(mockBlobContentData).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when commit sha is undefined', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
mockLatestCommitShaQuery.mockResolvedValue(undefined);
|
||||||
|
await createComponentWithApollo();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls getBlobContent', () => {
|
||||||
|
expect(mockBlobContentData).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not call ciConfigData', () => {
|
||||||
|
expect(mockCiConfigData).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when commit sha is defined', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
|
||||||
|
mockLatestCommitShaQuery.mockResolvedValue(mockCommitShaResults);
|
||||||
|
await createComponentWithApollo();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls ciConfigData', () => {
|
||||||
|
expect(mockCiConfigData).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('when queries are called', () => {
|
describe('when queries are called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
|
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { createAlert } from '~/flash';
|
||||||
|
|
||||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import RunnerHeader from '~/runner/components/runner_header.vue';
|
import RunnerHeader from '~/runner/components/runner_header.vue';
|
||||||
import getRunnerQuery from '~/runner/graphql/get_runner.query.graphql';
|
import runnerQuery from '~/runner/graphql/details/runner.query.graphql';
|
||||||
import AdminRunnerEditApp from '~//runner/admin_runner_edit/admin_runner_edit_app.vue';
|
import AdminRunnerEditApp from '~//runner/admin_runner_edit/admin_runner_edit_app.vue';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ describe('AdminRunnerEditApp', () => {
|
||||||
|
|
||||||
const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
|
const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
|
||||||
wrapper = mountFn(AdminRunnerEditApp, {
|
wrapper = mountFn(AdminRunnerEditApp, {
|
||||||
apolloProvider: createMockApollo([[getRunnerQuery, mockRunnerQuery]]),
|
apolloProvider: createMockApollo([[runnerQuery, mockRunnerQuery]]),
|
||||||
propsData: {
|
propsData: {
|
||||||
runnerId: mockRunnerId,
|
runnerId: mockRunnerId,
|
||||||
...props,
|
...props,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import RunnerHeader from '~/runner/components/runner_header.vue';
|
import RunnerHeader from '~/runner/components/runner_header.vue';
|
||||||
import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
|
import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
|
||||||
import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
|
import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
|
||||||
import getRunnerQuery from '~/runner/graphql/get_runner.query.graphql';
|
import runnerQuery from '~/runner/graphql/details/runner.query.graphql';
|
||||||
import AdminRunnerShowApp from '~/runner/admin_runner_show/admin_runner_show_app.vue';
|
import AdminRunnerShowApp from '~/runner/admin_runner_show/admin_runner_show_app.vue';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ describe('AdminRunnerShowApp', () => {
|
||||||
|
|
||||||
const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
|
const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
|
||||||
wrapper = mountFn(AdminRunnerShowApp, {
|
wrapper = mountFn(AdminRunnerShowApp, {
|
||||||
apolloProvider: createMockApollo([[getRunnerQuery, mockRunnerQuery]]),
|
apolloProvider: createMockApollo([[runnerQuery, mockRunnerQuery]]),
|
||||||
propsData: {
|
propsData: {
|
||||||
runnerId: mockRunnerId,
|
runnerId: mockRunnerId,
|
||||||
...props,
|
...props,
|
||||||
|
|
|
@ -35,8 +35,8 @@ import {
|
||||||
STATUS_ACTIVE,
|
STATUS_ACTIVE,
|
||||||
RUNNER_PAGE_SIZE,
|
RUNNER_PAGE_SIZE,
|
||||||
} from '~/runner/constants';
|
} from '~/runner/constants';
|
||||||
import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
|
import adminRunnersQuery from '~/runner/graphql/list/admin_runners.query.graphql';
|
||||||
import getRunnersCountQuery from '~/runner/graphql/get_runners_count.query.graphql';
|
import adminRunnersCountQuery from '~/runner/graphql/list/admin_runners_count.query.graphql';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
|
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ describe('AdminRunnersApp', () => {
|
||||||
|
|
||||||
const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
|
const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
|
||||||
const handlers = [
|
const handlers = [
|
||||||
[getRunnersQuery, mockRunnersQuery],
|
[adminRunnersQuery, mockRunnersQuery],
|
||||||
[getRunnersCountQuery, mockRunnersCountQuery],
|
[adminRunnersCountQuery, mockRunnersCountQuery],
|
||||||
];
|
];
|
||||||
|
|
||||||
wrapper = mountFn(AdminRunnersApp, {
|
wrapper = mountFn(AdminRunnersApp, {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import { createAlert } from '~/flash';
|
import { createAlert } from '~/flash';
|
||||||
import RegistrationTokenResetDropdownItem from '~/runner/components/registration/registration_token_reset_dropdown_item.vue';
|
import RegistrationTokenResetDropdownItem from '~/runner/components/registration/registration_token_reset_dropdown_item.vue';
|
||||||
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
|
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
|
||||||
import runnersRegistrationTokenResetMutation from '~/runner/graphql/runners_registration_token_reset.mutation.graphql';
|
import runnersRegistrationTokenResetMutation from '~/runner/graphql/list/runners_registration_token_reset.mutation.graphql';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
|
||||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||||
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
|
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
|
import runnerDeleteMutation from '~/runner/graphql/shared/runner_delete.mutation.graphql';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
|
|
|
@ -11,7 +11,7 @@ import RunnerPagination from '~/runner/components/runner_pagination.vue';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '~/runner/constants';
|
import { I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '~/runner/constants';
|
||||||
|
|
||||||
import getRunnerJobsQuery from '~/runner/graphql/get_runner_jobs.query.graphql';
|
import runnerJobsQuery from '~/runner/graphql/details/runner_jobs.query.graphql';
|
||||||
|
|
||||||
import { runnerData, runnerJobsData } from '../mock_data';
|
import { runnerData, runnerJobsData } from '../mock_data';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ describe('RunnerJobs', () => {
|
||||||
|
|
||||||
const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
|
const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
|
||||||
wrapper = mountFn(RunnerJobs, {
|
wrapper = mountFn(RunnerJobs, {
|
||||||
apolloProvider: createMockApollo([[getRunnerJobsQuery, mockRunnerJobsQuery]]),
|
apolloProvider: createMockApollo([[runnerJobsQuery, mockRunnerJobsQuery]]),
|
||||||
propsData: {
|
propsData: {
|
||||||
runner: mockRunner,
|
runner: mockRunner,
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
|
||||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||||
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
|
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
import runnerToggleActiveMutation from '~/runner/graphql/runner_toggle_active.mutation.graphql';
|
import runnerToggleActiveMutation from '~/runner/graphql/shared/runner_toggle_active.mutation.graphql';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { createAlert } from '~/flash';
|
import { createAlert } from '~/flash';
|
||||||
|
|
|
@ -16,7 +16,7 @@ import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue';
|
||||||
import RunnerPagination from '~/runner/components/runner_pagination.vue';
|
import RunnerPagination from '~/runner/components/runner_pagination.vue';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
|
|
||||||
import getRunnerProjectsQuery from '~/runner/graphql/get_runner_projects.query.graphql';
|
import runnerProjectsQuery from '~/runner/graphql/details/runner_projects.query.graphql';
|
||||||
|
|
||||||
import { runnerData, runnerProjectsData } from '../mock_data';
|
import { runnerData, runnerProjectsData } from '../mock_data';
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ describe('RunnerProjects', () => {
|
||||||
|
|
||||||
const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
|
const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
|
||||||
wrapper = mountFn(RunnerProjects, {
|
wrapper = mountFn(RunnerProjects, {
|
||||||
apolloProvider: createMockApollo([[getRunnerProjectsQuery, mockRunnerProjectsQuery]]),
|
apolloProvider: createMockApollo([[runnerProjectsQuery, mockRunnerProjectsQuery]]),
|
||||||
propsData: {
|
propsData: {
|
||||||
runner: mockRunner,
|
runner: mockRunner,
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
ACCESS_LEVEL_REF_PROTECTED,
|
ACCESS_LEVEL_REF_PROTECTED,
|
||||||
ACCESS_LEVEL_NOT_PROTECTED,
|
ACCESS_LEVEL_NOT_PROTECTED,
|
||||||
} from '~/runner/constants';
|
} from '~/runner/constants';
|
||||||
import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
|
import runnerUpdateMutation from '~/runner/graphql/details/runner_update.mutation.graphql';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import { runnerData } from '../mock_data';
|
import { runnerData } from '../mock_data';
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ import {
|
||||||
RUNNER_PAGE_SIZE,
|
RUNNER_PAGE_SIZE,
|
||||||
I18N_EDIT,
|
I18N_EDIT,
|
||||||
} from '~/runner/constants';
|
} from '~/runner/constants';
|
||||||
import getGroupRunnersQuery from '~/runner/graphql/get_group_runners.query.graphql';
|
import getGroupRunnersQuery from '~/runner/graphql/list/group_runners.query.graphql';
|
||||||
import getGroupRunnersCountQuery from '~/runner/graphql/get_group_runners_count.query.graphql';
|
import getGroupRunnersCountQuery from '~/runner/graphql/list/group_runners_count.query.graphql';
|
||||||
import GroupRunnersApp from '~/runner/group_runners/group_runners_app.vue';
|
import GroupRunnersApp from '~/runner/group_runners/group_runners_app.vue';
|
||||||
import { captureException } from '~/runner/sentry_utils';
|
import { captureException } from '~/runner/sentry_utils';
|
||||||
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
|
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
// Fixtures generated by: spec/frontend/fixtures/runner.rb
|
// Fixtures generated by: spec/frontend/fixtures/runner.rb
|
||||||
|
|
||||||
// Admin queries
|
// List queries
|
||||||
import runnersData from 'test_fixtures/graphql/runner/get_runners.query.graphql.json';
|
import runnersData from 'test_fixtures/graphql/runner/list/admin_runners.query.graphql.json';
|
||||||
import runnersCountData from 'test_fixtures/graphql/runner/get_runners_count.query.graphql.json';
|
import runnersDataPaginated from 'test_fixtures/graphql/runner/list/admin_runners.query.graphql.paginated.json';
|
||||||
import runnersDataPaginated from 'test_fixtures/graphql/runner/get_runners.query.graphql.paginated.json';
|
import runnersCountData from 'test_fixtures/graphql/runner/list/admin_runners_count.query.graphql.json';
|
||||||
import runnerData from 'test_fixtures/graphql/runner/get_runner.query.graphql.json';
|
import groupRunnersData from 'test_fixtures/graphql/runner/list/group_runners.query.graphql.json';
|
||||||
import runnerWithGroupData from 'test_fixtures/graphql/runner/get_runner.query.graphql.with_group.json';
|
import groupRunnersDataPaginated from 'test_fixtures/graphql/runner/list/group_runners.query.graphql.paginated.json';
|
||||||
import runnerProjectsData from 'test_fixtures/graphql/runner/get_runner_projects.query.graphql.json';
|
import groupRunnersCountData from 'test_fixtures/graphql/runner/list/group_runners_count.query.graphql.json';
|
||||||
import runnerJobsData from 'test_fixtures/graphql/runner/get_runner_jobs.query.graphql.json';
|
|
||||||
|
|
||||||
// Group queries
|
// Details queries
|
||||||
import groupRunnersData from 'test_fixtures/graphql/runner/get_group_runners.query.graphql.json';
|
import runnerData from 'test_fixtures/graphql/runner/details/runner.query.graphql.json';
|
||||||
import groupRunnersCountData from 'test_fixtures/graphql/runner/get_group_runners_count.query.graphql.json';
|
import runnerWithGroupData from 'test_fixtures/graphql/runner/details/runner.query.graphql.with_group.json';
|
||||||
import groupRunnersDataPaginated from 'test_fixtures/graphql/runner/get_group_runners.query.graphql.paginated.json';
|
import runnerProjectsData from 'test_fixtures/graphql/runner/details/runner_projects.query.graphql.json';
|
||||||
|
import runnerJobsData from 'test_fixtures/graphql/runner/details/runner_jobs.query.graphql.json';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
runnersData,
|
runnersData,
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe DeployTokensHelper do
|
||||||
|
describe '#deploy_token_revoke_button_data' do
|
||||||
|
let_it_be(:token) { build(:deploy_token) }
|
||||||
|
let_it_be(:project) { build(:project) }
|
||||||
|
let_it_be(:revoke_deploy_token_path) { '/foobar/baz/-/deploy_tokens/1/revoke' }
|
||||||
|
|
||||||
|
it 'returns expected hash' do
|
||||||
|
expect(helper).to receive(:revoke_deploy_token_path).with(project, token).and_return(revoke_deploy_token_path)
|
||||||
|
|
||||||
|
expect(helper.deploy_token_revoke_button_data(token: token, group_or_project: project)).to match({
|
||||||
|
token: token.to_json(only: [:id, :name]),
|
||||||
|
revoke_path: revoke_deploy_token_path
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -49,7 +49,7 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProject
|
||||||
|
|
||||||
it 'invalidates the markdown cache of related projects' do
|
it 'invalidates the markdown cache of related projects' do
|
||||||
expect(subject).to receive(:remove_cached_html_for_projects)
|
expect(subject).to receive(:remove_cached_html_for_projects)
|
||||||
.with(projects.map(&:id))
|
.with(a_collection_containing_exactly(*projects.map(&:id)))
|
||||||
|
|
||||||
subject.rename_projects
|
subject.rename_projects
|
||||||
end
|
end
|
||||||
|
|
|
@ -390,26 +390,8 @@ RSpec.describe Group do
|
||||||
let!(:old_parent) { create(:group, parent: root) }
|
let!(:old_parent) { create(:group, parent: root) }
|
||||||
let!(:new_parent) { create(:group, parent: root) }
|
let!(:new_parent) { create(:group, parent: root) }
|
||||||
|
|
||||||
context 'with FOR UPDATE lock' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(for_no_key_update_lock: false)
|
|
||||||
subject
|
|
||||||
reload_models(old_parent, new_parent, group)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'updates traversal_ids' do
|
|
||||||
expect(group.traversal_ids).to eq [root.id, new_parent.id, group.id]
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'hierarchy with traversal_ids'
|
|
||||||
it_behaves_like 'locked row', 'FOR UPDATE' do
|
|
||||||
let(:row) { root }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with FOR NO KEY UPDATE lock' do
|
context 'with FOR NO KEY UPDATE lock' do
|
||||||
before do
|
before do
|
||||||
stub_feature_flags(for_no_key_update_lock: true)
|
|
||||||
subject
|
subject
|
||||||
reload_models(old_parent, new_parent, group)
|
reload_models(old_parent, new_parent, group)
|
||||||
end
|
end
|
||||||
|
@ -419,7 +401,7 @@ RSpec.describe Group do
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'hierarchy with traversal_ids'
|
it_behaves_like 'hierarchy with traversal_ids'
|
||||||
it_behaves_like 'locked row', 'FOR NO KEY UPDATE' do
|
it_behaves_like 'locked row' do
|
||||||
let(:row) { root }
|
let(:row) { root }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -68,24 +68,11 @@ RSpec.describe Namespace::TraversalHierarchy, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'locked row', 'FOR UPDATE' do
|
it_behaves_like 'locked row' do
|
||||||
let(:recorded_queries) { ActiveRecord::QueryRecorder.new }
|
let(:recorded_queries) { ActiveRecord::QueryRecorder.new }
|
||||||
let(:row) { root }
|
let(:row) { root }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_feature_flags(for_no_key_update_lock: false)
|
|
||||||
|
|
||||||
recorded_queries.record { subject }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'locked row', 'FOR NO KEY UPDATE' do
|
|
||||||
let(:recorded_queries) { ActiveRecord::QueryRecorder.new }
|
|
||||||
let(:row) { root }
|
|
||||||
|
|
||||||
before do
|
|
||||||
stub_feature_flags(for_no_key_update_lock: true)
|
|
||||||
|
|
||||||
recorded_queries.record { subject }
|
recorded_queries.record { subject }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -436,17 +436,7 @@ RSpec.describe Namespace do
|
||||||
it { expect(namespace.traversal_ids).to eq [namespace.id] }
|
it { expect(namespace.traversal_ids).to eq [namespace.id] }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with before_commit callback' do
|
it_behaves_like 'default traversal_ids'
|
||||||
it_behaves_like 'default traversal_ids'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with after_create callback' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(sync_traversal_ids_before_commit: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'default traversal_ids'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "after_commit :expire_child_caches" do
|
describe "after_commit :expire_child_caches" do
|
||||||
|
|
|
@ -262,17 +262,7 @@ RSpec.describe Project, factory_default: :keep do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'sync-ing traversal_ids in before_commit callback' do
|
it_behaves_like 'creates project namespace'
|
||||||
it_behaves_like 'creates project namespace'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'sync-ing traversal_ids in after_create callback' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(sync_traversal_ids_before_commit: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'creates project namespace'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -85,14 +85,6 @@ RSpec.describe Groups::CreateService, '#execute' do
|
||||||
context 'with before_commit callback' do
|
context 'with before_commit callback' do
|
||||||
it_behaves_like 'has sync-ed traversal_ids'
|
it_behaves_like 'has sync-ed traversal_ids'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with after_create callback' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(sync_traversal_ids_before_commit: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'has sync-ed traversal_ids'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user can not create a group' do
|
context 'when user can not create a group' do
|
||||||
|
@ -119,17 +111,7 @@ RSpec.describe Groups::CreateService, '#execute' do
|
||||||
expect { subject }.not_to change(OnboardingProgress, :count).from(0)
|
expect { subject }.not_to change(OnboardingProgress, :count).from(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with before_commit callback' do
|
it_behaves_like 'has sync-ed traversal_ids'
|
||||||
it_behaves_like 'has sync-ed traversal_ids'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with after_create callback' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(sync_traversal_ids_before_commit: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'has sync-ed traversal_ids'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'as guest' do
|
context 'as guest' do
|
||||||
|
|
|
@ -225,17 +225,7 @@ RSpec.describe Projects::CreateService, '#execute' do
|
||||||
expect(project.project_namespace).to be_in_sync_with_project(project)
|
expect(project.project_namespace).to be_in_sync_with_project(project)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with before_commit callback' do
|
it_behaves_like 'has sync-ed traversal_ids'
|
||||||
it_behaves_like 'has sync-ed traversal_ids'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with after_create callback' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(sync_traversal_ids_before_commit: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'has sync-ed traversal_ids'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'group sharing', :sidekiq_inline do
|
context 'group sharing', :sidekiq_inline do
|
||||||
|
|
|
@ -49,6 +49,7 @@ module SimpleCovEnv
|
||||||
|
|
||||||
def configure_profile
|
def configure_profile
|
||||||
SimpleCov.configure do
|
SimpleCov.configure do
|
||||||
|
enable_coverage :branch
|
||||||
load_profile 'test_frameworks'
|
load_profile 'test_frameworks'
|
||||||
track_files '{app,config/initializers,config/initializers_before_autoloader,db/post_migrate,haml_lint,lib,rubocop,tooling}/**/*.rb'
|
track_files '{app,config/initializers,config/initializers_before_autoloader,db/post_migrate,haml_lint,lib,rubocop,tooling}/**/*.rb'
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
# Ensure a transaction also occurred.
|
# Ensure a transaction also occurred.
|
||||||
# Be careful! This form of spec is not foolproof, but better than nothing.
|
# Be careful! This form of spec is not foolproof, but better than nothing.
|
||||||
|
|
||||||
RSpec.shared_examples 'locked row' do |lock_type|
|
RSpec.shared_examples 'locked row' do
|
||||||
it "has locked row" do
|
it "has locked row" do
|
||||||
table_name = row.class.table_name
|
table_name = row.class.table_name
|
||||||
ids_regex = /SELECT.*FROM.*#{table_name}.*"#{table_name}"."id" = #{row.id}.+#{lock_type}/m
|
ids_regex = /SELECT.*FROM.*#{table_name}.*"#{table_name}"."id" = #{row.id}.+FOR NO KEY UPDATE/m
|
||||||
|
|
||||||
expect(recorded_queries.log).to include a_string_matching 'SAVEPOINT'
|
expect(recorded_queries.log).to include a_string_matching 'SAVEPOINT'
|
||||||
expect(recorded_queries.log).to include a_string_matching ids_regex
|
expect(recorded_queries.log).to include a_string_matching ids_regex
|
||||||
|
|
|
@ -16,8 +16,8 @@ RSpec.describe 'admin/application_settings/_eks' do
|
||||||
shared_examples 'EKS secret access key input' do
|
shared_examples 'EKS secret access key input' do
|
||||||
it 'renders an empty password field' do
|
it 'renders an empty password field' do
|
||||||
render
|
render
|
||||||
expect(rendered).to have_field('Secret access key', type: 'password')
|
expect(rendered).to have_field('AWS secret access key (Optional)', type: 'password')
|
||||||
expect(page.find_field('Secret access key').value).to be_blank
|
expect(page.find_field('AWS secret access key (Optional)').value).to be_blank
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,20 @@ require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe 'layouts/_published_experiments', :experiment do
|
RSpec.describe 'layouts/_published_experiments', :experiment do
|
||||||
before do
|
before do
|
||||||
stub_const('TestControlExperiment', ApplicationExperiment)
|
# Stub each experiment to be enabled, otherwise tracking does not happen.
|
||||||
stub_const('TestCandidateExperiment', ApplicationExperiment)
|
stub_experiments(
|
||||||
stub_const('TestExcludedExperiment', ApplicationExperiment)
|
test_control: :control,
|
||||||
|
test_excluded: true,
|
||||||
|
test_published_only: :control,
|
||||||
|
test_candidate: :candidate,
|
||||||
|
test_variant: :variant_name
|
||||||
|
)
|
||||||
|
|
||||||
TestControlExperiment.new('test_control').tap do |e|
|
experiment(:test_control) { }
|
||||||
e.variant(:control)
|
experiment(:test_excluded) { |e| e.exclude! }
|
||||||
e.publish
|
experiment(:test_candidate) { |e| e.candidate { } }
|
||||||
end
|
experiment(:test_variant) { |e| e.variant(:variant_name) { } }
|
||||||
TestCandidateExperiment.new('test_candidate').tap do |e|
|
experiment(:test_published_only).publish
|
||||||
e.variant(:candidate)
|
|
||||||
e.publish
|
|
||||||
end
|
|
||||||
TestExcludedExperiment.new('test_excluded').tap do |e|
|
|
||||||
e.exclude!
|
|
||||||
e.publish
|
|
||||||
end
|
|
||||||
|
|
||||||
render
|
render
|
||||||
end
|
end
|
||||||
|
@ -29,7 +27,9 @@ RSpec.describe 'layouts/_published_experiments', :experiment do
|
||||||
|
|
||||||
expect(output).to include('gl.experiments = {')
|
expect(output).to include('gl.experiments = {')
|
||||||
expect(output).to match(/"test_control":\{[^}]*"variant":"control"/)
|
expect(output).to match(/"test_control":\{[^}]*"variant":"control"/)
|
||||||
expect(output).to match(/"test_candidate":\{[^}]*"variant":"candidate"/)
|
|
||||||
expect(output).not_to include('"test_excluded"')
|
expect(output).not_to include('"test_excluded"')
|
||||||
|
expect(output).to match(/"test_candidate":\{[^}]*"variant":"candidate"/)
|
||||||
|
expect(output).to match(/"test_variant":\{[^}]*"variant":"variant_name"/)
|
||||||
|
expect(output).to match(/"test_published_only":\{[^}]*"variant":"control"/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue