Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ef615776bf
commit
edfc0f680f
|
@ -1,12 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlTabs, GlTab } from '@gitlab/ui';
|
import { GlTabs, GlTab } from '@gitlab/ui';
|
||||||
import { CLUSTERS_TABS, MAX_CLUSTERS_LIST, MAX_LIST_COUNT, AGENT } from '../constants';
|
import Tracking from '~/tracking';
|
||||||
|
import {
|
||||||
|
CLUSTERS_TABS,
|
||||||
|
MAX_CLUSTERS_LIST,
|
||||||
|
MAX_LIST_COUNT,
|
||||||
|
AGENT,
|
||||||
|
EVENT_LABEL_TABS,
|
||||||
|
EVENT_ACTIONS_CHANGE,
|
||||||
|
} from '../constants';
|
||||||
import Agents from './agents.vue';
|
import Agents from './agents.vue';
|
||||||
import InstallAgentModal from './install_agent_modal.vue';
|
import InstallAgentModal from './install_agent_modal.vue';
|
||||||
import ClustersActions from './clusters_actions.vue';
|
import ClustersActions from './clusters_actions.vue';
|
||||||
import Clusters from './clusters.vue';
|
import Clusters from './clusters.vue';
|
||||||
import ClustersViewAll from './clusters_view_all.vue';
|
import ClustersViewAll from './clusters_view_all.vue';
|
||||||
|
|
||||||
|
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_TABS });
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GlTabs,
|
GlTabs,
|
||||||
|
@ -18,6 +28,7 @@ export default {
|
||||||
InstallAgentModal,
|
InstallAgentModal,
|
||||||
},
|
},
|
||||||
CLUSTERS_TABS,
|
CLUSTERS_TABS,
|
||||||
|
mixins: [trackingMixin],
|
||||||
props: {
|
props: {
|
||||||
defaultBranchName: {
|
defaultBranchName: {
|
||||||
default: '.noBranch',
|
default: '.noBranch',
|
||||||
|
@ -34,9 +45,12 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
onTabChange(tabName) {
|
onTabChange(tabName) {
|
||||||
this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName);
|
this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName);
|
||||||
|
|
||||||
this.maxAgents = tabName === AGENT ? MAX_LIST_COUNT : MAX_CLUSTERS_LIST;
|
this.maxAgents = tabName === AGENT ? MAX_LIST_COUNT : MAX_CLUSTERS_LIST;
|
||||||
},
|
},
|
||||||
|
trackTabChange(tab) {
|
||||||
|
const tabName = CLUSTERS_TABS[tab].queryParamValue;
|
||||||
|
this.track(EVENT_ACTIONS_CHANGE, { property: tabName });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -47,6 +61,7 @@ export default {
|
||||||
sync-active-tab-with-query-params
|
sync-active-tab-with-query-params
|
||||||
nav-class="gl-flex-grow-1 gl-align-items-center"
|
nav-class="gl-flex-grow-1 gl-align-items-center"
|
||||||
lazy
|
lazy
|
||||||
|
@input="trackTabChange"
|
||||||
>
|
>
|
||||||
<gl-tab
|
<gl-tab
|
||||||
v-for="(tab, idx) in $options.CLUSTERS_TABS"
|
v-for="(tab, idx) in $options.CLUSTERS_TABS"
|
||||||
|
|
|
@ -11,8 +11,19 @@ import {
|
||||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||||
import CodeBlock from '~/vue_shared/components/code_block.vue';
|
import CodeBlock from '~/vue_shared/components/code_block.vue';
|
||||||
|
import Tracking from '~/tracking';
|
||||||
import { generateAgentRegistrationCommand } from '../clusters_util';
|
import { generateAgentRegistrationCommand } from '../clusters_util';
|
||||||
import { INSTALL_AGENT_MODAL_ID, I18N_AGENT_MODAL, KAS_DISABLED_ERROR } from '../constants';
|
import {
|
||||||
|
INSTALL_AGENT_MODAL_ID,
|
||||||
|
I18N_AGENT_MODAL,
|
||||||
|
KAS_DISABLED_ERROR,
|
||||||
|
EVENT_LABEL_MODAL,
|
||||||
|
EVENT_ACTIONS_OPEN,
|
||||||
|
EVENT_ACTIONS_SELECT,
|
||||||
|
EVENT_ACTIONS_CLICK,
|
||||||
|
MODAL_TYPE_EMPTY,
|
||||||
|
MODAL_TYPE_REGISTER,
|
||||||
|
} from '../constants';
|
||||||
import { addAgentToStore, addAgentConfigToStore } from '../graphql/cache_update';
|
import { addAgentToStore, addAgentConfigToStore } from '../graphql/cache_update';
|
||||||
import createAgent from '../graphql/mutations/create_agent.mutation.graphql';
|
import createAgent from '../graphql/mutations/create_agent.mutation.graphql';
|
||||||
import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql';
|
import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql';
|
||||||
|
@ -20,8 +31,13 @@ import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
|
||||||
import agentConfigurations from '../graphql/queries/agent_configurations.query.graphql';
|
import agentConfigurations from '../graphql/queries/agent_configurations.query.graphql';
|
||||||
import AvailableAgentsDropdown from './available_agents_dropdown.vue';
|
import AvailableAgentsDropdown from './available_agents_dropdown.vue';
|
||||||
|
|
||||||
|
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_MODAL });
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
modalId: INSTALL_AGENT_MODAL_ID,
|
modalId: INSTALL_AGENT_MODAL_ID,
|
||||||
|
EVENT_ACTIONS_OPEN,
|
||||||
|
EVENT_ACTIONS_CLICK,
|
||||||
|
EVENT_LABEL_MODAL,
|
||||||
components: {
|
components: {
|
||||||
AvailableAgentsDropdown,
|
AvailableAgentsDropdown,
|
||||||
ClipboardButton,
|
ClipboardButton,
|
||||||
|
@ -34,6 +50,7 @@ export default {
|
||||||
GlModal,
|
GlModal,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
},
|
},
|
||||||
|
mixins: [trackingMixin],
|
||||||
inject: ['projectPath', 'kasAddress', 'emptyStateImage'],
|
inject: ['projectPath', 'kasAddress', 'emptyStateImage'],
|
||||||
props: {
|
props: {
|
||||||
defaultBranchName: {
|
defaultBranchName: {
|
||||||
|
@ -81,7 +98,7 @@ export default {
|
||||||
return !this.registering && this.agentName !== null;
|
return !this.registering && this.agentName !== null;
|
||||||
},
|
},
|
||||||
canCancel() {
|
canCancel() {
|
||||||
return !this.registered && !this.registering && this.isRegisterModal;
|
return !this.registered && !this.registering && this.isAgentRegistrationModal;
|
||||||
},
|
},
|
||||||
agentRegistrationCommand() {
|
agentRegistrationCommand() {
|
||||||
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
|
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
|
||||||
|
@ -117,21 +134,24 @@ export default {
|
||||||
return `/${this.projectPath}`;
|
return `/${this.projectPath}`;
|
||||||
},
|
},
|
||||||
modalType() {
|
modalType() {
|
||||||
return !this.availableAgents?.length && !this.registered ? 'install' : 'register';
|
return !this.availableAgents?.length && !this.registered
|
||||||
|
? MODAL_TYPE_EMPTY
|
||||||
|
: MODAL_TYPE_REGISTER;
|
||||||
},
|
},
|
||||||
modalSize() {
|
modalSize() {
|
||||||
return this.isInstallModal ? 'sm' : 'md';
|
return this.isEmptyStateModal ? 'sm' : 'md';
|
||||||
},
|
},
|
||||||
isInstallModal() {
|
isEmptyStateModal() {
|
||||||
return this.modalType === 'install';
|
return this.modalType === MODAL_TYPE_EMPTY;
|
||||||
},
|
},
|
||||||
isRegisterModal() {
|
isAgentRegistrationModal() {
|
||||||
return this.modalType === 'register';
|
return this.modalType === MODAL_TYPE_REGISTER;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setAgentName(name) {
|
setAgentName(name) {
|
||||||
this.agentName = name;
|
this.agentName = name;
|
||||||
|
this.track(EVENT_ACTIONS_SELECT);
|
||||||
},
|
},
|
||||||
closeModal() {
|
closeModal() {
|
||||||
this.$refs.modal.hide();
|
this.$refs.modal.hide();
|
||||||
|
@ -242,8 +262,9 @@ export default {
|
||||||
static
|
static
|
||||||
lazy
|
lazy
|
||||||
@hidden="resetModal"
|
@hidden="resetModal"
|
||||||
|
@show="track($options.EVENT_ACTIONS_OPEN, { property: modalType })"
|
||||||
>
|
>
|
||||||
<template v-if="isRegisterModal">
|
<template v-if="isAgentRegistrationModal">
|
||||||
<template v-if="!registered">
|
<template v-if="!registered">
|
||||||
<p>
|
<p>
|
||||||
<strong>{{ i18n.selectAgentTitle }}</strong>
|
<strong>{{ i18n.selectAgentTitle }}</strong>
|
||||||
|
@ -347,23 +368,40 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #modal-footer>
|
<template #modal-footer>
|
||||||
<gl-button v-if="canCancel" @click="closeModal">{{ i18n.cancel }} </gl-button>
|
<gl-button
|
||||||
|
v-if="canCancel"
|
||||||
|
:data-track-action="$options.EVENT_ACTIONS_CLICK"
|
||||||
|
:data-track-label="$options.EVENT_LABEL_MODAL"
|
||||||
|
data-track-property="cancel"
|
||||||
|
@click="closeModal"
|
||||||
|
>{{ i18n.cancel }}
|
||||||
|
</gl-button>
|
||||||
|
|
||||||
<gl-button v-if="registered" variant="confirm" category="primary" @click="closeModal"
|
<gl-button
|
||||||
|
v-if="registered"
|
||||||
|
variant="confirm"
|
||||||
|
category="primary"
|
||||||
|
:data-track-action="$options.EVENT_ACTIONS_CLICK"
|
||||||
|
:data-track-label="$options.EVENT_LABEL_MODAL"
|
||||||
|
data-track-property="close"
|
||||||
|
@click="closeModal"
|
||||||
>{{ i18n.close }}
|
>{{ i18n.close }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
|
|
||||||
<gl-button
|
<gl-button
|
||||||
v-else-if="isRegisterModal"
|
v-else-if="isAgentRegistrationModal"
|
||||||
:disabled="!nextButtonDisabled"
|
:disabled="!nextButtonDisabled"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
category="primary"
|
category="primary"
|
||||||
|
:data-track-action="$options.EVENT_ACTIONS_CLICK"
|
||||||
|
:data-track-label="$options.EVENT_LABEL_MODAL"
|
||||||
|
data-track-property="register"
|
||||||
@click="registerAgent"
|
@click="registerAgent"
|
||||||
>{{ i18n.registerAgentButton }}
|
>{{ i18n.registerAgentButton }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
|
|
||||||
<gl-button
|
<gl-button
|
||||||
v-if="isInstallModal"
|
v-if="isEmptyStateModal"
|
||||||
:href="repositoryPath"
|
:href="repositoryPath"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
category="secondary"
|
category="secondary"
|
||||||
|
@ -371,7 +409,14 @@ export default {
|
||||||
>{{ i18n.secondaryButton }}
|
>{{ i18n.secondaryButton }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
|
|
||||||
<gl-button v-if="isInstallModal" variant="confirm" category="primary" @click="closeModal"
|
<gl-button
|
||||||
|
v-if="isEmptyStateModal"
|
||||||
|
variant="confirm"
|
||||||
|
category="primary"
|
||||||
|
:data-track-action="$options.EVENT_ACTIONS_CLICK"
|
||||||
|
:data-track-label="$options.EVENT_LABEL_MODAL"
|
||||||
|
data-track-property="done"
|
||||||
|
@click="closeModal"
|
||||||
>{{ i18n.done }}
|
>{{ i18n.done }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -65,7 +65,7 @@ export const STATUSES = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const I18N_AGENT_MODAL = {
|
export const I18N_AGENT_MODAL = {
|
||||||
register: {
|
agent_registration: {
|
||||||
registerAgentButton: s__('ClusterAgents|Register Agent'),
|
registerAgentButton: s__('ClusterAgents|Register Agent'),
|
||||||
close: __('Close'),
|
close: __('Close'),
|
||||||
cancel: __('Cancel'),
|
cancel: __('Cancel'),
|
||||||
|
@ -104,7 +104,7 @@ export const I18N_AGENT_MODAL = {
|
||||||
registrationErrorTitle: __('Failed to register Agent'),
|
registrationErrorTitle: __('Failed to register Agent'),
|
||||||
unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
|
unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
|
||||||
},
|
},
|
||||||
install: {
|
empty_state: {
|
||||||
modalTitle: s__('ClusterAgents|Install new Agent'),
|
modalTitle: s__('ClusterAgents|Install new Agent'),
|
||||||
modalBody: s__(
|
modalBody: s__(
|
||||||
'ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process.',
|
'ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process.',
|
||||||
|
@ -236,3 +236,13 @@ export const CLUSTERS_ACTIONS = {
|
||||||
|
|
||||||
export const AGENT = 'agent';
|
export const AGENT = 'agent';
|
||||||
export const CERTIFICATE_BASED = 'certificate_based';
|
export const CERTIFICATE_BASED = 'certificate_based';
|
||||||
|
|
||||||
|
export const EVENT_LABEL_MODAL = 'agent_registration_modal';
|
||||||
|
export const EVENT_LABEL_TABS = 'kubernetes_section_tabs';
|
||||||
|
export const EVENT_ACTIONS_OPEN = 'open_modal';
|
||||||
|
export const EVENT_ACTIONS_SELECT = 'select_agent';
|
||||||
|
export const EVENT_ACTIONS_CLICK = 'click_button';
|
||||||
|
export const EVENT_ACTIONS_CHANGE = 'change_tab';
|
||||||
|
|
||||||
|
export const MODAL_TYPE_EMPTY = 'empty_state';
|
||||||
|
export const MODAL_TYPE_REGISTER = 'agent_registration';
|
||||||
|
|
|
@ -67,7 +67,7 @@ export default {
|
||||||
data-qa-selector="dropdown_button"
|
data-qa-selector="dropdown_button"
|
||||||
@click.stop="openDropdown()"
|
@click.stop="openDropdown()"
|
||||||
>
|
>
|
||||||
<gl-icon name="ellipsis_v" /> <gl-icon name="chevron-down" />
|
<gl-icon name="ellipsis_v" />
|
||||||
</button>
|
</button>
|
||||||
<ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
|
<ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
|
||||||
<template v-if="type === 'tree'">
|
<template v-if="type === 'tree'">
|
||||||
|
|
|
@ -2099,6 +2099,10 @@ This endpoint:
|
||||||
|
|
||||||
- Deletes a project including all associated resources (including issues and
|
- Deletes a project including all associated resources (including issues and
|
||||||
merge requests).
|
merge requests).
|
||||||
|
- In [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) and later, on
|
||||||
|
[Premium or higher](https://about.gitlab.com/pricing/) tiers,
|
||||||
|
[delayed project deletion](../user/project/settings/index.md#delayed-project-deletion)
|
||||||
|
is applied if enabled.
|
||||||
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on
|
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on
|
||||||
[Premium or higher](https://about.gitlab.com/pricing/) tiers, group
|
[Premium or higher](https://about.gitlab.com/pricing/) tiers, group
|
||||||
administrators can [configure](../user/group/index.md#enable-delayed-project-deletion)
|
administrators can [configure](../user/group/index.md#enable-delayed-project-deletion)
|
||||||
|
|
|
@ -22,8 +22,7 @@ This tutorial assumes you are familiar with GitLab CI/CD and Vault.
|
||||||
To follow along, you must have:
|
To follow along, you must have:
|
||||||
|
|
||||||
- An account on GitLab.
|
- An account on GitLab.
|
||||||
- A running Vault server and access to it is required to configure authentication and create roles
|
- Access to a running Vault server (at least v1.2.0) to configure authentication and to create roles and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
|
||||||
and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
|
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
You must replace the `vault.example.com` URL below with the URL of your Vault server, and `gitlab.example.com` with the URL of your GitLab instance.
|
You must replace the `vault.example.com` URL below with the URL of your Vault server, and `gitlab.example.com` with the URL of your GitLab instance.
|
||||||
|
|
|
@ -53,6 +53,7 @@ and supports multiple secrets engines.
|
||||||
|
|
||||||
To configure your Vault server:
|
To configure your Vault server:
|
||||||
|
|
||||||
|
1. Ensure your Vault server is running on version 1.2.0 or higher.
|
||||||
1. Enable the authentication method by running these commands. They provide your Vault
|
1. Enable the authentication method by running these commands. They provide your Vault
|
||||||
server the [JSON Web Key Set](https://tools.ietf.org/html/rfc7517) (JWKS) endpoint for your GitLab instance, so Vault
|
server the [JSON Web Key Set](https://tools.ietf.org/html/rfc7517) (JWKS) endpoint for your GitLab instance, so Vault
|
||||||
can fetch the public signing key and verify the JSON Web Token (JWT) when authenticating:
|
can fetch the public signing key and verify the JSON Web Token (JWT) when authenticating:
|
||||||
|
|
|
@ -97,8 +97,8 @@ delete a project. To allow only users with the Administrator role to delete proj
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2 for groups created after August 12, 2021.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2 for groups created after August 12, 2021.
|
||||||
|
|
||||||
Projects in a group (but not a personal namespace) can be deleted after a delayed period.
|
[Delayed project deletion](../../project/settings/index.md#delayed-project-deletion) allows projects in a group (not a personal namespace)
|
||||||
You can [configure it in group settings](../../group/index.md#enable-delayed-project-deletion).
|
to be deleted after a period of delay.
|
||||||
|
|
||||||
To enable delayed project deletion by default in new groups:
|
To enable delayed project deletion by default in new groups:
|
||||||
|
|
||||||
|
@ -110,14 +110,13 @@ To enable delayed project deletion by default in new groups:
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6.
|
||||||
|
|
||||||
By default, a project marked for deletion is permanently removed with immediate effect.
|
By default, a project marked for deletion is permanently removed with immediate effect.
|
||||||
|
See [delayed project deletion](../../project/settings/index.md#delayed-project-deletion) to learn more.
|
||||||
By default, a group marked for deletion is permanently removed after seven days.
|
By default, a group marked for deletion is permanently removed after seven days.
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
|
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
|
||||||
[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
|
[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
|
||||||
|
|
||||||
Projects in a group (but not a personal namespace) can be deleted after a delayed period, by
|
|
||||||
[configuring in Group Settings](../../group/index.md#enable-delayed-project-deletion).
|
|
||||||
The default period is seven days, and can be changed. Setting this period to `0` enables immediate removal
|
The default period is seven days, and can be changed. Setting this period to `0` enables immediate removal
|
||||||
of projects or groups.
|
of projects or groups.
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
INFO:
|
INFO:
|
||||||
Want to try out container scanning?
|
Want to try out container scanning?
|
||||||
[Get a free 30-day trial GitLab Ultimate](https://about.gitlab.com/free-trial?glm_source=docs.gitlab.com&glm_content=u-container-scanning-docs).
|
[Get a free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial?glm_source=docs.gitlab.com&glm_content=u-container-scanning-docs).
|
||||||
|
|
||||||
Your application's Docker image may itself be based on Docker images that contain known
|
Your application's Docker image may itself be based on Docker images that contain known
|
||||||
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
|
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
|
||||||
|
@ -135,6 +135,7 @@ You can [configure](#customizing-the-container-scanning-settings) analyzers by u
|
||||||
| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. | All |
|
| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. | All |
|
||||||
| `CS_ANALYZER_IMAGE` | `registry.gitlab.com/security-products/container-scanning:4` | Docker image of the analyzer. | All |
|
| `CS_ANALYZER_IMAGE` | `registry.gitlab.com/security-products/container-scanning:4` | Docker image of the analyzer. | All |
|
||||||
| `CS_DEFAULT_BRANCH_IMAGE` | `""` | The name of the `DOCKER_IMAGE` on the default branch. See [Setting the default branch image](#setting-the-default-branch-image) for more details. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338877) in GitLab 14.5. | All |
|
| `CS_DEFAULT_BRANCH_IMAGE` | `""` | The name of the `DOCKER_IMAGE` on the default branch. See [Setting the default branch image](#setting-the-default-branch-image) for more details. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338877) in GitLab 14.5. | All |
|
||||||
|
| `CS_DISABLE_DEPENDENCY_SCAN` | `"true"` | Disable Dependency Scanning for packages installed in the scanned image. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345434) in GitLab 14.6. | All |
|
||||||
| `CS_DOCKER_INSECURE` | `"false"` | Allow access to secure Docker registries using HTTPS without validating the certificates. | All |
|
| `CS_DOCKER_INSECURE` | `"false"` | Allow access to secure Docker registries using HTTPS without validating the certificates. | All |
|
||||||
| `CS_REGISTRY_INSECURE` | `"false"` | Allow access to insecure registries (HTTP only). Should only be set to `true` when testing the image locally. Works with all scanners, but the registry must listen on port `80/tcp` for Trivy to work. | All |
|
| `CS_REGISTRY_INSECURE` | `"false"` | Allow access to insecure registries (HTTP only). Should only be set to `true` when testing the image locally. Works with all scanners, but the registry must listen on port `80/tcp` for Trivy to work. | All |
|
||||||
| `CS_SEVERITY_THRESHOLD` | `UNKNOWN` | Severity level threshold. The scanner outputs vulnerabilities with severity level higher than or equal to this threshold. Supported levels are Unknown, Low, Medium, High, and Critical. | Trivy |
|
| `CS_SEVERITY_THRESHOLD` | `UNKNOWN` | Severity level threshold. The scanner outputs vulnerabilities with severity level higher than or equal to this threshold. Supported levels are Unknown, Low, Medium, High, and Critical. | Trivy |
|
||||||
|
|
|
@ -672,12 +672,9 @@ To disable group mentions:
|
||||||
> - [Inheritance and enforcement added](https://gitlab.com/gitlab-org/gitlab/-/issues/321724) in GitLab 13.11.
|
> - [Inheritance and enforcement added](https://gitlab.com/gitlab-org/gitlab/-/issues/321724) in GitLab 13.11.
|
||||||
> - [Instance setting to enable by default added](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2.
|
> - [Instance setting to enable by default added](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2.
|
||||||
|
|
||||||
Projects can be configured to be deleted either:
|
[Delayed project deletion](../project/settings/index.md#delayed-project-deletion) can be enabled for groups. When enabled, projects in
|
||||||
|
the group are deleted after a period of delay. During this period, projects are in a read-only state and can be restored. The default
|
||||||
- Immediately.
|
period is seven days but [is configurable at the instance level](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
|
||||||
- After a delayed interval. During this interval period, the projects are in a read-only state
|
|
||||||
and can be restored. The default interval period is seven days but
|
|
||||||
[is configurable](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
|
|
||||||
|
|
||||||
On self-managed GitLab, projects are deleted immediately by default.
|
On self-managed GitLab, projects are deleted immediately by default.
|
||||||
In GitLab 14.2 and later, an administrator can
|
In GitLab 14.2 and later, an administrator can
|
||||||
|
|
|
@ -248,7 +248,7 @@ To delete a project, first navigate to the home page for that project.
|
||||||
1. Click **Delete project**
|
1. Click **Delete project**
|
||||||
1. Confirm this action by typing in the expected text.
|
1. Confirm this action by typing in the expected text.
|
||||||
|
|
||||||
Projects in personal namespaces are deleted immediately on request. For information on delayed deletion of projects in a group, please see [Enable delayed project deletion](../group/index.md#enable-delayed-project-deletion).
|
Projects in personal namespaces are deleted immediately on request. For information on delayed deletion of projects in a group, please see [delayed project deletion](settings/index.md#delayed-project-deletion).
|
||||||
|
|
||||||
## Project settings
|
## Project settings
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ container_scanning:
|
||||||
artifacts:
|
artifacts:
|
||||||
reports:
|
reports:
|
||||||
container_scanning: gl-container-scanning-report.json
|
container_scanning: gl-container-scanning-report.json
|
||||||
paths: [gl-container-scanning-report.json]
|
dependency_scanning: gl-dependency-scanning-report.json
|
||||||
|
paths: [gl-container-scanning-report.json, gl-dependency-scanning-report.json]
|
||||||
dependencies: []
|
dependencies: []
|
||||||
script:
|
script:
|
||||||
- gtcs scan
|
- gtcs scan
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { GlTabs, GlTab } from '@gitlab/ui';
|
import { GlTabs, GlTab } from '@gitlab/ui';
|
||||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
|
import { mockTracking } from 'helpers/tracking_helper';
|
||||||
import ClustersMainView from '~/clusters_list/components/clusters_main_view.vue';
|
import ClustersMainView from '~/clusters_list/components/clusters_main_view.vue';
|
||||||
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
|
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
|
||||||
import {
|
import {
|
||||||
|
@ -8,12 +9,15 @@ import {
|
||||||
CLUSTERS_TABS,
|
CLUSTERS_TABS,
|
||||||
MAX_CLUSTERS_LIST,
|
MAX_CLUSTERS_LIST,
|
||||||
MAX_LIST_COUNT,
|
MAX_LIST_COUNT,
|
||||||
|
EVENT_LABEL_TABS,
|
||||||
|
EVENT_ACTIONS_CHANGE,
|
||||||
} from '~/clusters_list/constants';
|
} from '~/clusters_list/constants';
|
||||||
|
|
||||||
const defaultBranchName = 'default-branch';
|
const defaultBranchName = 'default-branch';
|
||||||
|
|
||||||
describe('ClustersMainViewComponent', () => {
|
describe('ClustersMainViewComponent', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
let trackingSpy;
|
||||||
|
|
||||||
const propsData = {
|
const propsData = {
|
||||||
defaultBranchName,
|
defaultBranchName,
|
||||||
|
@ -23,6 +27,7 @@ describe('ClustersMainViewComponent', () => {
|
||||||
wrapper = shallowMountExtended(ClustersMainView, {
|
wrapper = shallowMountExtended(ClustersMainView, {
|
||||||
propsData,
|
propsData,
|
||||||
});
|
});
|
||||||
|
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -71,6 +76,7 @@ describe('ClustersMainViewComponent', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
findComponent().vm.$emit('changeTab', AGENT);
|
findComponent().vm.$emit('changeTab', AGENT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('changes the tab', () => {
|
it('changes the tab', () => {
|
||||||
expect(findTabs().attributes('value')).toBe('1');
|
expect(findTabs().attributes('value')).toBe('1');
|
||||||
});
|
});
|
||||||
|
@ -78,5 +84,13 @@ describe('ClustersMainViewComponent', () => {
|
||||||
it('passes correct max-agents param to the modal', () => {
|
it('passes correct max-agents param to the modal', () => {
|
||||||
expect(findModal().props('maxAgents')).toBe(MAX_LIST_COUNT);
|
expect(findModal().props('maxAgents')).toBe(MAX_LIST_COUNT);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends the correct tracking event', () => {
|
||||||
|
findTabs().vm.$emit('input', 1);
|
||||||
|
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_CHANGE, {
|
||||||
|
label: EVENT_LABEL_TABS,
|
||||||
|
property: AGENT,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,9 +2,18 @@ import { GlAlert, GlButton, GlFormInputGroup } from '@gitlab/ui';
|
||||||
import { createLocalVue } from '@vue/test-utils';
|
import { createLocalVue } from '@vue/test-utils';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
|
import { mockTracking } from 'helpers/tracking_helper';
|
||||||
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
|
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
|
||||||
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
|
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
|
||||||
import { I18N_AGENT_MODAL, MAX_LIST_COUNT } from '~/clusters_list/constants';
|
import {
|
||||||
|
I18N_AGENT_MODAL,
|
||||||
|
MAX_LIST_COUNT,
|
||||||
|
EVENT_LABEL_MODAL,
|
||||||
|
EVENT_ACTIONS_OPEN,
|
||||||
|
EVENT_ACTIONS_SELECT,
|
||||||
|
MODAL_TYPE_EMPTY,
|
||||||
|
MODAL_TYPE_REGISTER,
|
||||||
|
} from '~/clusters_list/constants';
|
||||||
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
|
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
|
||||||
import getAgentConfigurations from '~/clusters_list/graphql/queries/agent_configurations.query.graphql';
|
import getAgentConfigurations from '~/clusters_list/graphql/queries/agent_configurations.query.graphql';
|
||||||
import createAgentMutation from '~/clusters_list/graphql/mutations/create_agent.mutation.graphql';
|
import createAgentMutation from '~/clusters_list/graphql/mutations/create_agent.mutation.graphql';
|
||||||
|
@ -34,6 +43,7 @@ const maxAgents = MAX_LIST_COUNT;
|
||||||
describe('InstallAgentModal', () => {
|
describe('InstallAgentModal', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
let apolloProvider;
|
let apolloProvider;
|
||||||
|
let trackingSpy;
|
||||||
|
|
||||||
const configurations = [{ agentName: 'agent-name' }];
|
const configurations = [{ agentName: 'agent-name' }];
|
||||||
const apolloQueryResponse = {
|
const apolloQueryResponse = {
|
||||||
|
@ -56,7 +66,7 @@ describe('InstallAgentModal', () => {
|
||||||
const findActionButton = () => findButtonByVariant('confirm');
|
const findActionButton = () => findButtonByVariant('confirm');
|
||||||
const findCancelButton = () => findButtonByVariant('default');
|
const findCancelButton = () => findButtonByVariant('default');
|
||||||
const findSecondaryButton = () => wrapper.findByTestId('agent-secondary-button');
|
const findSecondaryButton = () => wrapper.findByTestId('agent-secondary-button');
|
||||||
const findImage = () => wrapper.findByRole('img', { alt: I18N_AGENT_MODAL.install.altText });
|
const findImage = () => wrapper.findByRole('img', { alt: I18N_AGENT_MODAL.empty_state.altText });
|
||||||
|
|
||||||
const expectDisabledAttribute = (element, disabled) => {
|
const expectDisabledAttribute = (element, disabled) => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
@ -121,6 +131,7 @@ describe('InstallAgentModal', () => {
|
||||||
[getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
|
[getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
|
||||||
]);
|
]);
|
||||||
createWrapper();
|
createWrapper();
|
||||||
|
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -129,7 +140,7 @@ describe('InstallAgentModal', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when agent configurations are present', () => {
|
describe('when agent configurations are present', () => {
|
||||||
const i18n = I18N_AGENT_MODAL.register;
|
const i18n = I18N_AGENT_MODAL.agent_registration;
|
||||||
|
|
||||||
describe('initial state', () => {
|
describe('initial state', () => {
|
||||||
it('renders the dropdown for available agents', () => {
|
it('renders the dropdown for available agents', () => {
|
||||||
|
@ -150,6 +161,14 @@ describe('InstallAgentModal', () => {
|
||||||
expect(findActionButton().text()).toBe(i18n.registerAgentButton);
|
expect(findActionButton().text()).toBe(i18n.registerAgentButton);
|
||||||
expectDisabledAttribute(findActionButton(), true);
|
expectDisabledAttribute(findActionButton(), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends the event with the modalType', () => {
|
||||||
|
findModal().vm.$emit('show');
|
||||||
|
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_OPEN, {
|
||||||
|
label: EVENT_LABEL_MODAL,
|
||||||
|
property: MODAL_TYPE_REGISTER,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('an agent is selected', () => {
|
describe('an agent is selected', () => {
|
||||||
|
@ -161,6 +180,12 @@ describe('InstallAgentModal', () => {
|
||||||
expect(findActionButton().isVisible()).toBe(true);
|
expect(findActionButton().isVisible()).toBe(true);
|
||||||
expectDisabledAttribute(findActionButton(), false);
|
expectDisabledAttribute(findActionButton(), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends the correct tracking event', () => {
|
||||||
|
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_SELECT, {
|
||||||
|
label: EVENT_LABEL_MODAL,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('registering an agent', () => {
|
describe('registering an agent', () => {
|
||||||
|
@ -247,7 +272,7 @@ describe('InstallAgentModal', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when there are no agent configurations present', () => {
|
describe('when there are no agent configurations present', () => {
|
||||||
const i18n = I18N_AGENT_MODAL.install;
|
const i18n = I18N_AGENT_MODAL.empty_state;
|
||||||
const apolloQueryEmptyResponse = {
|
const apolloQueryEmptyResponse = {
|
||||||
data: {
|
data: {
|
||||||
project: {
|
project: {
|
||||||
|
@ -272,5 +297,13 @@ describe('InstallAgentModal', () => {
|
||||||
expect(findSecondaryButton().isVisible()).toBe(true);
|
expect(findSecondaryButton().isVisible()).toBe(true);
|
||||||
expect(findSecondaryButton().text()).toBe(i18n.secondaryButton);
|
expect(findSecondaryButton().text()).toBe(i18n.secondaryButton);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends the event with the modalType', () => {
|
||||||
|
findModal().vm.$emit('show');
|
||||||
|
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_OPEN, {
|
||||||
|
label: EVENT_LABEL_MODAL,
|
||||||
|
property: MODAL_TYPE_EMPTY,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,9 +31,13 @@ module Database
|
||||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/339396
|
# See https://gitlab.com/gitlab-org/gitlab/-/issues/339396
|
||||||
return if sql.include?("DISABLE TRIGGER") || sql.include?("ENABLE TRIGGER")
|
return if sql.include?("DISABLE TRIGGER") || sql.include?("ENABLE TRIGGER")
|
||||||
|
|
||||||
# PgQuery might fail in some cases due to limited nesting:
|
tables = begin
|
||||||
# https://github.com/pganalyze/pg_query/issues/209
|
PgQuery.parse(sql).tables
|
||||||
tables = PgQuery.parse(sql).tables
|
rescue PgQuery::ParseError
|
||||||
|
# PgQuery might fail in some cases due to limited nesting:
|
||||||
|
# https://github.com/pganalyze/pg_query/issues/209
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
schemas = ::Gitlab::Database::GitlabSchema.table_schemas(tables)
|
schemas = ::Gitlab::Database::GitlabSchema.table_schemas(tables)
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,15 @@ RSpec.describe Database::PreventCrossJoins do
|
||||||
expect { main_and_ci_query_allowlist_nested }.not_to raise_error
|
expect { main_and_ci_query_allowlist_nested }.not_to raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when there is a parser error' do
|
||||||
|
it 'does not raise parse PGQuery::ParseError' do
|
||||||
|
# Since this is in an invalid query it still raises from ActiveRecord
|
||||||
|
# but this tests that we rescue the PGQuery::ParseError which would
|
||||||
|
# have otherwise raised first
|
||||||
|
expect { ApplicationRecord.connection.execute('SELECT SELECT FROM SELECT') }.to raise_error(ActiveRecord::StatementInvalid)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue