Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-12-02 03:13:01 +00:00
parent ef615776bf
commit edfc0f680f
16 changed files with 173 additions and 41 deletions

View File

@ -1,12 +1,22 @@
<script>
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 InstallAgentModal from './install_agent_modal.vue';
import ClustersActions from './clusters_actions.vue';
import Clusters from './clusters.vue';
import ClustersViewAll from './clusters_view_all.vue';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_TABS });
export default {
components: {
GlTabs,
@ -18,6 +28,7 @@ export default {
InstallAgentModal,
},
CLUSTERS_TABS,
mixins: [trackingMixin],
props: {
defaultBranchName: {
default: '.noBranch',
@ -34,9 +45,12 @@ export default {
methods: {
onTabChange(tabName) {
this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName);
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>
@ -47,6 +61,7 @@ export default {
sync-active-tab-with-query-params
nav-class="gl-flex-grow-1 gl-align-items-center"
lazy
@input="trackTabChange"
>
<gl-tab
v-for="(tab, idx) in $options.CLUSTERS_TABS"

View File

@ -11,8 +11,19 @@ import {
import { helpPagePath } from '~/helpers/help_page_helper';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import Tracking from '~/tracking';
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 createAgent from '../graphql/mutations/create_agent.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 AvailableAgentsDropdown from './available_agents_dropdown.vue';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_MODAL });
export default {
modalId: INSTALL_AGENT_MODAL_ID,
EVENT_ACTIONS_OPEN,
EVENT_ACTIONS_CLICK,
EVENT_LABEL_MODAL,
components: {
AvailableAgentsDropdown,
ClipboardButton,
@ -34,6 +50,7 @@ export default {
GlModal,
GlSprintf,
},
mixins: [trackingMixin],
inject: ['projectPath', 'kasAddress', 'emptyStateImage'],
props: {
defaultBranchName: {
@ -81,7 +98,7 @@ export default {
return !this.registering && this.agentName !== null;
},
canCancel() {
return !this.registered && !this.registering && this.isRegisterModal;
return !this.registered && !this.registering && this.isAgentRegistrationModal;
},
agentRegistrationCommand() {
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
@ -117,21 +134,24 @@ export default {
return `/${this.projectPath}`;
},
modalType() {
return !this.availableAgents?.length && !this.registered ? 'install' : 'register';
return !this.availableAgents?.length && !this.registered
? MODAL_TYPE_EMPTY
: MODAL_TYPE_REGISTER;
},
modalSize() {
return this.isInstallModal ? 'sm' : 'md';
return this.isEmptyStateModal ? 'sm' : 'md';
},
isInstallModal() {
return this.modalType === 'install';
isEmptyStateModal() {
return this.modalType === MODAL_TYPE_EMPTY;
},
isRegisterModal() {
return this.modalType === 'register';
isAgentRegistrationModal() {
return this.modalType === MODAL_TYPE_REGISTER;
},
},
methods: {
setAgentName(name) {
this.agentName = name;
this.track(EVENT_ACTIONS_SELECT);
},
closeModal() {
this.$refs.modal.hide();
@ -242,8 +262,9 @@ export default {
static
lazy
@hidden="resetModal"
@show="track($options.EVENT_ACTIONS_OPEN, { property: modalType })"
>
<template v-if="isRegisterModal">
<template v-if="isAgentRegistrationModal">
<template v-if="!registered">
<p>
<strong>{{ i18n.selectAgentTitle }}</strong>
@ -347,23 +368,40 @@ export default {
</template>
<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 }}
</gl-button>
<gl-button
v-else-if="isRegisterModal"
v-else-if="isAgentRegistrationModal"
:disabled="!nextButtonDisabled"
variant="confirm"
category="primary"
:data-track-action="$options.EVENT_ACTIONS_CLICK"
:data-track-label="$options.EVENT_LABEL_MODAL"
data-track-property="register"
@click="registerAgent"
>{{ i18n.registerAgentButton }}
</gl-button>
<gl-button
v-if="isInstallModal"
v-if="isEmptyStateModal"
:href="repositoryPath"
variant="confirm"
category="secondary"
@ -371,7 +409,14 @@ export default {
>{{ i18n.secondaryButton }}
</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 }}
</gl-button>
</template>

View File

@ -65,7 +65,7 @@ export const STATUSES = {
};
export const I18N_AGENT_MODAL = {
register: {
agent_registration: {
registerAgentButton: s__('ClusterAgents|Register Agent'),
close: __('Close'),
cancel: __('Cancel'),
@ -104,7 +104,7 @@ export const I18N_AGENT_MODAL = {
registrationErrorTitle: __('Failed to register Agent'),
unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
},
install: {
empty_state: {
modalTitle: s__('ClusterAgents|Install new Agent'),
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.',
@ -236,3 +236,13 @@ export const CLUSTERS_ACTIONS = {
export const AGENT = 'agent';
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';

View File

@ -67,7 +67,7 @@ export default {
data-qa-selector="dropdown_button"
@click.stop="openDropdown()"
>
<gl-icon name="ellipsis_v" /> <gl-icon name="chevron-down" />
<gl-icon name="ellipsis_v" />
</button>
<ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
<template v-if="type === 'tree'">

View File

@ -2099,6 +2099,10 @@ This endpoint:
- Deletes a project including all associated resources (including issues and
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
[Premium or higher](https://about.gitlab.com/pricing/) tiers, group
administrators can [configure](../user/group/index.md#enable-delayed-project-deletion)

View File

@ -22,8 +22,7 @@ This tutorial assumes you are familiar with GitLab CI/CD and Vault.
To follow along, you must have:
- An account on GitLab.
- A running Vault server and access to it is required to configure authentication and create roles
and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
- 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.
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.

View File

@ -53,6 +53,7 @@ and supports multiple secrets engines.
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
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:

View File

@ -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.
Projects in a group (but not a personal namespace) can be deleted after a delayed period.
You can [configure it in group settings](../../group/index.md#enable-delayed-project-deletion).
[Delayed project deletion](../../project/settings/index.md#delayed-project-deletion) allows projects in a group (not a personal namespace)
to be deleted after a period of delay.
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.
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.
WARNING:
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.
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
of projects or groups.

View File

@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
INFO:
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
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 |
| `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_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_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 |

View File

@ -672,12 +672,9 @@ To disable group mentions:
> - [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.
Projects can be configured to be deleted either:
- Immediately.
- 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).
[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
period is seven days but [is configurable at the instance level](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
On self-managed GitLab, projects are deleted immediately by default.
In GitLab 14.2 and later, an administrator can

View File

@ -248,7 +248,7 @@ To delete a project, first navigate to the home page for that project.
1. Click **Delete project**
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

View File

@ -38,7 +38,8 @@ container_scanning:
artifacts:
reports:
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: []
script:
- gtcs scan

View File

@ -1,5 +1,6 @@
import { GlTabs, GlTab } from '@gitlab/ui';
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 InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
import {
@ -8,12 +9,15 @@ import {
CLUSTERS_TABS,
MAX_CLUSTERS_LIST,
MAX_LIST_COUNT,
EVENT_LABEL_TABS,
EVENT_ACTIONS_CHANGE,
} from '~/clusters_list/constants';
const defaultBranchName = 'default-branch';
describe('ClustersMainViewComponent', () => {
let wrapper;
let trackingSpy;
const propsData = {
defaultBranchName,
@ -23,6 +27,7 @@ describe('ClustersMainViewComponent', () => {
wrapper = shallowMountExtended(ClustersMainView, {
propsData,
});
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
@ -71,6 +76,7 @@ describe('ClustersMainViewComponent', () => {
beforeEach(() => {
findComponent().vm.$emit('changeTab', AGENT);
});
it('changes the tab', () => {
expect(findTabs().attributes('value')).toBe('1');
});
@ -78,5 +84,13 @@ describe('ClustersMainViewComponent', () => {
it('passes correct max-agents param to the modal', () => {
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,
});
});
});
});

View File

@ -2,9 +2,18 @@ import { GlAlert, GlButton, GlFormInputGroup } from '@gitlab/ui';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
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 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 getAgentConfigurations from '~/clusters_list/graphql/queries/agent_configurations.query.graphql';
import createAgentMutation from '~/clusters_list/graphql/mutations/create_agent.mutation.graphql';
@ -34,6 +43,7 @@ const maxAgents = MAX_LIST_COUNT;
describe('InstallAgentModal', () => {
let wrapper;
let apolloProvider;
let trackingSpy;
const configurations = [{ agentName: 'agent-name' }];
const apolloQueryResponse = {
@ -56,7 +66,7 @@ describe('InstallAgentModal', () => {
const findActionButton = () => findButtonByVariant('confirm');
const findCancelButton = () => findButtonByVariant('default');
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) => {
if (disabled) {
@ -121,6 +131,7 @@ describe('InstallAgentModal', () => {
[getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
]);
createWrapper();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
@ -129,7 +140,7 @@ describe('InstallAgentModal', () => {
});
describe('when agent configurations are present', () => {
const i18n = I18N_AGENT_MODAL.register;
const i18n = I18N_AGENT_MODAL.agent_registration;
describe('initial state', () => {
it('renders the dropdown for available agents', () => {
@ -150,6 +161,14 @@ describe('InstallAgentModal', () => {
expect(findActionButton().text()).toBe(i18n.registerAgentButton);
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', () => {
@ -161,6 +180,12 @@ describe('InstallAgentModal', () => {
expect(findActionButton().isVisible()).toBe(true);
expectDisabledAttribute(findActionButton(), false);
});
it('sends the correct tracking event', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_SELECT, {
label: EVENT_LABEL_MODAL,
});
});
});
describe('registering an agent', () => {
@ -247,7 +272,7 @@ describe('InstallAgentModal', () => {
});
describe('when there are no agent configurations present', () => {
const i18n = I18N_AGENT_MODAL.install;
const i18n = I18N_AGENT_MODAL.empty_state;
const apolloQueryEmptyResponse = {
data: {
project: {
@ -272,5 +297,13 @@ describe('InstallAgentModal', () => {
expect(findSecondaryButton().isVisible()).toBe(true);
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,
});
});
});
});

View File

@ -31,9 +31,13 @@ module Database
# See https://gitlab.com/gitlab-org/gitlab/-/issues/339396
return if sql.include?("DISABLE TRIGGER") || sql.include?("ENABLE TRIGGER")
# PgQuery might fail in some cases due to limited nesting:
# https://github.com/pganalyze/pg_query/issues/209
tables = PgQuery.parse(sql).tables
tables = begin
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)

View File

@ -39,6 +39,15 @@ RSpec.describe Database::PreventCrossJoins do
expect { main_and_ci_query_allowlist_nested }.not_to raise_error
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