Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
27d1ed4ddf
commit
a7aff3e0e4
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlButton, GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
|
import { GlButton, GlFormGroup, GlFormCheckbox, GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
|
||||||
import { mapActions, mapGetters, mapState } from 'vuex';
|
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||||
import ErrorTrackingForm from './error_tracking_form.vue';
|
import ErrorTrackingForm from './error_tracking_form.vue';
|
||||||
import ProjectDropdown from './project_dropdown.vue';
|
import ProjectDropdown from './project_dropdown.vue';
|
||||||
|
@ -10,6 +10,8 @@ export default {
|
||||||
GlButton,
|
GlButton,
|
||||||
GlFormCheckbox,
|
GlFormCheckbox,
|
||||||
GlFormGroup,
|
GlFormGroup,
|
||||||
|
GlFormRadioGroup,
|
||||||
|
GlFormRadio,
|
||||||
ProjectDropdown,
|
ProjectDropdown,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -22,6 +24,10 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
initialIntegrated: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
initialProject: {
|
initialProject: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -49,12 +55,20 @@ export default {
|
||||||
'isProjectInvalid',
|
'isProjectInvalid',
|
||||||
'projectSelectionLabel',
|
'projectSelectionLabel',
|
||||||
]),
|
]),
|
||||||
...mapState(['enabled', 'projects', 'selectedProject', 'settingsLoading', 'token']),
|
...mapState([
|
||||||
|
'enabled',
|
||||||
|
'integrated',
|
||||||
|
'projects',
|
||||||
|
'selectedProject',
|
||||||
|
'settingsLoading',
|
||||||
|
'token',
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.setInitialState({
|
this.setInitialState({
|
||||||
apiHost: this.initialApiHost,
|
apiHost: this.initialApiHost,
|
||||||
enabled: this.initialEnabled,
|
enabled: this.initialEnabled,
|
||||||
|
integrated: this.initialIntegrated,
|
||||||
project: this.initialProject,
|
project: this.initialProject,
|
||||||
token: this.initialToken,
|
token: this.initialToken,
|
||||||
listProjectsEndpoint: this.listProjectsEndpoint,
|
listProjectsEndpoint: this.listProjectsEndpoint,
|
||||||
|
@ -62,7 +76,13 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['setInitialState', 'updateEnabled', 'updateSelectedProject', 'updateSettings']),
|
...mapActions([
|
||||||
|
'setInitialState',
|
||||||
|
'updateEnabled',
|
||||||
|
'updateIntegrated',
|
||||||
|
'updateSelectedProject',
|
||||||
|
'updateSettings',
|
||||||
|
]),
|
||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
this.updateSettings();
|
this.updateSettings();
|
||||||
},
|
},
|
||||||
|
@ -76,27 +96,44 @@ export default {
|
||||||
:label="s__('ErrorTracking|Enable error tracking')"
|
:label="s__('ErrorTracking|Enable error tracking')"
|
||||||
label-for="error-tracking-enabled"
|
label-for="error-tracking-enabled"
|
||||||
>
|
>
|
||||||
<gl-form-checkbox
|
<gl-form-checkbox id="error-tracking-enabled" :checked="enabled" @change="updateEnabled">
|
||||||
id="error-tracking-enabled"
|
|
||||||
:checked="enabled"
|
|
||||||
@change="updateEnabled($event)"
|
|
||||||
>
|
|
||||||
{{ s__('ErrorTracking|Active') }}
|
{{ s__('ErrorTracking|Active') }}
|
||||||
</gl-form-checkbox>
|
</gl-form-checkbox>
|
||||||
</gl-form-group>
|
</gl-form-group>
|
||||||
<error-tracking-form />
|
<gl-form-group
|
||||||
<div class="form-group">
|
:label="s__('ErrorTracking|Error tracking backend')"
|
||||||
<project-dropdown
|
data-testid="tracking-backend-settings"
|
||||||
:has-projects="hasProjects"
|
>
|
||||||
:invalid-project-label="invalidProjectLabel"
|
<gl-form-radio-group name="explicit" :checked="integrated" @change="updateIntegrated">
|
||||||
:is-project-invalid="isProjectInvalid"
|
<gl-form-radio name="error-tracking-integrated" :value="false">
|
||||||
:dropdown-label="dropdownLabel"
|
{{ __('Sentry') }}
|
||||||
:project-selection-label="projectSelectionLabel"
|
<template #help>
|
||||||
:projects="projects"
|
{{ __('Requires you to deploy or set up cloud-hosted Sentry.') }}
|
||||||
:selected-project="selectedProject"
|
</template>
|
||||||
:token="token"
|
</gl-form-radio>
|
||||||
@select-project="updateSelectedProject"
|
<gl-form-radio name="error-tracking-integrated" :value="true">
|
||||||
/>
|
{{ __('GitLab') }}
|
||||||
|
<template #help>
|
||||||
|
{{ __('Uses GitLab as a lightweight alternative to Sentry.') }}
|
||||||
|
</template>
|
||||||
|
</gl-form-radio>
|
||||||
|
</gl-form-radio-group>
|
||||||
|
</gl-form-group>
|
||||||
|
<div v-if="!integrated" class="js-sentry-setting-form" data-testid="sentry-setting-form">
|
||||||
|
<error-tracking-form />
|
||||||
|
<div class="form-group">
|
||||||
|
<project-dropdown
|
||||||
|
:has-projects="hasProjects"
|
||||||
|
:invalid-project-label="invalidProjectLabel"
|
||||||
|
:is-project-invalid="isProjectInvalid"
|
||||||
|
:dropdown-label="dropdownLabel"
|
||||||
|
:project-selection-label="projectSelectionLabel"
|
||||||
|
:projects="projects"
|
||||||
|
:selected-project="selectedProject"
|
||||||
|
:token="token"
|
||||||
|
@select-project="updateSelectedProject"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<gl-button
|
<gl-button
|
||||||
:disabled="settingsLoading"
|
:disabled="settingsLoading"
|
||||||
|
|
|
@ -5,7 +5,15 @@ import createStore from './store';
|
||||||
export default () => {
|
export default () => {
|
||||||
const formContainerEl = document.querySelector('.js-error-tracking-form');
|
const formContainerEl = document.querySelector('.js-error-tracking-form');
|
||||||
const {
|
const {
|
||||||
dataset: { apiHost, enabled, project, token, listProjectsEndpoint, operationsSettingsEndpoint },
|
dataset: {
|
||||||
|
apiHost,
|
||||||
|
enabled,
|
||||||
|
integrated,
|
||||||
|
project,
|
||||||
|
token,
|
||||||
|
listProjectsEndpoint,
|
||||||
|
operationsSettingsEndpoint,
|
||||||
|
},
|
||||||
} = formContainerEl;
|
} = formContainerEl;
|
||||||
|
|
||||||
return new Vue({
|
return new Vue({
|
||||||
|
@ -16,6 +24,7 @@ export default () => {
|
||||||
props: {
|
props: {
|
||||||
initialApiHost: apiHost,
|
initialApiHost: apiHost,
|
||||||
initialEnabled: enabled,
|
initialEnabled: enabled,
|
||||||
|
initialIntegrated: integrated,
|
||||||
initialProject: project,
|
initialProject: project,
|
||||||
initialToken: token,
|
initialToken: token,
|
||||||
listProjectsEndpoint,
|
listProjectsEndpoint,
|
||||||
|
|
|
@ -79,6 +79,10 @@ export const updateEnabled = ({ commit }, enabled) => {
|
||||||
commit(types.UPDATE_ENABLED, enabled);
|
commit(types.UPDATE_ENABLED, enabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateIntegrated = ({ commit }, integrated) => {
|
||||||
|
commit(types.UPDATE_INTEGRATED, integrated);
|
||||||
|
};
|
||||||
|
|
||||||
export const updateToken = ({ commit }, token) => {
|
export const updateToken = ({ commit }, token) => {
|
||||||
commit(types.UPDATE_TOKEN, token);
|
commit(types.UPDATE_TOKEN, token);
|
||||||
commit(types.RESET_CONNECT);
|
commit(types.RESET_CONNECT);
|
||||||
|
|
|
@ -6,6 +6,7 @@ export const UPDATE_API_HOST = 'UPDATE_API_HOST';
|
||||||
export const UPDATE_CONNECT_ERROR = 'UPDATE_CONNECT_ERROR';
|
export const UPDATE_CONNECT_ERROR = 'UPDATE_CONNECT_ERROR';
|
||||||
export const UPDATE_CONNECT_SUCCESS = 'UPDATE_CONNECT_SUCCESS';
|
export const UPDATE_CONNECT_SUCCESS = 'UPDATE_CONNECT_SUCCESS';
|
||||||
export const UPDATE_ENABLED = 'UPDATE_ENABLED';
|
export const UPDATE_ENABLED = 'UPDATE_ENABLED';
|
||||||
|
export const UPDATE_INTEGRATED = 'UPDATE_INTEGRATED';
|
||||||
export const UPDATE_SELECTED_PROJECT = 'UPDATE_SELECTED_PROJECT';
|
export const UPDATE_SELECTED_PROJECT = 'UPDATE_SELECTED_PROJECT';
|
||||||
export const UPDATE_SETTINGS_LOADING = 'UPDATE_SETTINGS_LOADING';
|
export const UPDATE_SETTINGS_LOADING = 'UPDATE_SETTINGS_LOADING';
|
||||||
export const UPDATE_TOKEN = 'UPDATE_TOKEN';
|
export const UPDATE_TOKEN = 'UPDATE_TOKEN';
|
||||||
|
|
|
@ -20,9 +20,18 @@ export default {
|
||||||
},
|
},
|
||||||
[types.SET_INITIAL_STATE](
|
[types.SET_INITIAL_STATE](
|
||||||
state,
|
state,
|
||||||
{ apiHost, enabled, project, token, listProjectsEndpoint, operationsSettingsEndpoint },
|
{
|
||||||
|
apiHost,
|
||||||
|
enabled,
|
||||||
|
integrated,
|
||||||
|
project,
|
||||||
|
token,
|
||||||
|
listProjectsEndpoint,
|
||||||
|
operationsSettingsEndpoint,
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
state.enabled = parseBoolean(enabled);
|
state.enabled = parseBoolean(enabled);
|
||||||
|
state.integrated = parseBoolean(integrated);
|
||||||
state.apiHost = apiHost;
|
state.apiHost = apiHost;
|
||||||
state.token = token;
|
state.token = token;
|
||||||
state.listProjectsEndpoint = listProjectsEndpoint;
|
state.listProjectsEndpoint = listProjectsEndpoint;
|
||||||
|
@ -38,6 +47,9 @@ export default {
|
||||||
[types.UPDATE_ENABLED](state, enabled) {
|
[types.UPDATE_ENABLED](state, enabled) {
|
||||||
state.enabled = enabled;
|
state.enabled = enabled;
|
||||||
},
|
},
|
||||||
|
[types.UPDATE_INTEGRATED](state, integrated) {
|
||||||
|
state.integrated = integrated;
|
||||||
|
},
|
||||||
[types.UPDATE_TOKEN](state, token) {
|
[types.UPDATE_TOKEN](state, token) {
|
||||||
state.token = token;
|
state.token = token;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export default () => ({
|
export default () => ({
|
||||||
apiHost: '',
|
apiHost: '',
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: false,
|
||||||
token: '',
|
token: '',
|
||||||
projects: [],
|
projects: [],
|
||||||
isLoadingProjects: false,
|
isLoadingProjects: false,
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
export const projectKeys = ['name', 'organizationName', 'organizationSlug', 'slug'];
|
export const projectKeys = ['name', 'organizationName', 'organizationSlug', 'slug'];
|
||||||
|
|
||||||
export const transformFrontendSettings = ({ apiHost, enabled, token, selectedProject }) => {
|
export const transformFrontendSettings = ({
|
||||||
|
apiHost,
|
||||||
|
enabled,
|
||||||
|
integrated,
|
||||||
|
token,
|
||||||
|
selectedProject,
|
||||||
|
}) => {
|
||||||
const project = selectedProject
|
const project = selectedProject
|
||||||
? {
|
? {
|
||||||
slug: selectedProject.slug,
|
slug: selectedProject.slug,
|
||||||
|
@ -10,7 +16,7 @@ export const transformFrontendSettings = ({ apiHost, enabled, token, selectedPro
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return { api_host: apiHost || null, enabled, token: token || null, project };
|
return { api_host: apiHost || null, enabled, integrated, token: token || null, project };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDisplayName = (project) => `${project.organizationName} | ${project.slug}`;
|
export const getDisplayName = (project) => `${project.organizationName} | ${project.slug}`;
|
||||||
|
|
|
@ -136,6 +136,7 @@ module Projects
|
||||||
|
|
||||||
error_tracking_setting_attributes: [
|
error_tracking_setting_attributes: [
|
||||||
:enabled,
|
:enabled,
|
||||||
|
:integrated,
|
||||||
:api_host,
|
:api_host,
|
||||||
:token,
|
:token,
|
||||||
project: [:slug, :name, :organization_slug, :organization_name]
|
project: [:slug, :name, :organization_slug, :organization_name]
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SecurityReportsMrWidgetPromptExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
|
||||||
|
def publish(_result = nil)
|
||||||
|
super
|
||||||
|
|
||||||
|
publish_to_database
|
||||||
|
end
|
||||||
|
|
||||||
|
# This is a purely client side experiment, and since we don't have a nicer
|
||||||
|
# way to define variants yet, we define them here.
|
||||||
|
def candidate_behavior
|
||||||
|
end
|
||||||
|
end
|
|
@ -94,6 +94,7 @@ module Projects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
params[:error_tracking_setting_attributes][:token] = settings[:token] unless /\A\*+\z/.match?(settings[:token]) # Don't update token if we receive masked value
|
params[:error_tracking_setting_attributes][:token] = settings[:token] unless /\A\*+\z/.match?(settings[:token]) # Don't update token if we receive masked value
|
||||||
|
params[:error_tracking_setting_attributes][:integrated] = settings[:integrated] unless settings[:integrated].nil?
|
||||||
|
|
||||||
params
|
params
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,4 +17,5 @@
|
||||||
project: error_tracking_setting_project_json,
|
project: error_tracking_setting_project_json,
|
||||||
api_host: setting.api_host,
|
api_host: setting.api_host,
|
||||||
enabled: setting.enabled.to_json,
|
enabled: setting.enabled.to_json,
|
||||||
|
integrated: setting.integrated.to_json,
|
||||||
token: setting.token.present? ? '*' * 12 : nil } }
|
token: setting.token.present? ? '*' * 12 : nil } }
|
||||||
|
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337628
|
||||||
milestone: '14.2'
|
milestone: '14.2'
|
||||||
type: development
|
type: development
|
||||||
group: group::pipeline authoring
|
group: group::pipeline authoring
|
||||||
default_enabled: false
|
default_enabled: true
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: security_reports_mr_widget_prompt
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70086
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340436
|
||||||
|
milestone: '14.3'
|
||||||
|
type: experiment
|
||||||
|
group: group::adoption
|
||||||
|
default_enabled: false
|
|
@ -7,7 +7,8 @@ product_stage: configure
|
||||||
product_group: group::configure
|
product_group: group::configure
|
||||||
product_category: infrastructure_as_code
|
product_category: infrastructure_as_code
|
||||||
value_type: number
|
value_type: number
|
||||||
status: broken
|
status: removed
|
||||||
|
milestone_removed: '14.3'
|
||||||
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466
|
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466
|
||||||
time_frame: 28d
|
time_frame: 28d
|
||||||
data_source: redis_hll
|
data_source: redis_hll
|
||||||
|
|
|
@ -7,7 +7,8 @@ product_stage: configure
|
||||||
product_group: group::configure
|
product_group: group::configure
|
||||||
product_category: infrastructure_as_code
|
product_category: infrastructure_as_code
|
||||||
value_type: number
|
value_type: number
|
||||||
status: broken
|
status: removed
|
||||||
|
milestone_removed: '14.3'
|
||||||
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466
|
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466
|
||||||
time_frame: 7d
|
time_frame: 7d
|
||||||
data_source: redis_hll
|
data_source: redis_hll
|
||||||
|
|
|
@ -385,7 +385,6 @@ tables:
|
||||||
- public_builds
|
- public_builds
|
||||||
- last_repository_check_failed
|
- last_repository_check_failed
|
||||||
- last_repository_check_at
|
- last_repository_check_at
|
||||||
- container_registry_enabled
|
|
||||||
- only_allow_merge_if_pipeline_succeeds
|
- only_allow_merge_if_pipeline_succeeds
|
||||||
- has_external_issue_tracker
|
- has_external_issue_tracker
|
||||||
- repository_storage
|
- repository_storage
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropTemporaryColumnsAndTriggersForCiBuildNeeds < Gitlab::Database::Migration[1.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
TABLE = 'ci_build_needs'
|
||||||
|
TEMPORARY_COLUMN = 'build_id_convert_to_bigint'
|
||||||
|
MAIN_COLUMN = 'build_id'
|
||||||
|
|
||||||
|
# rubocop:disable Migration/WithLockRetriesDisallowedMethod
|
||||||
|
def up
|
||||||
|
with_lock_retries do
|
||||||
|
cleanup_conversion_of_integer_to_bigint(TABLE, MAIN_COLUMN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
check_trigger_permissions!(TABLE)
|
||||||
|
|
||||||
|
with_lock_retries do
|
||||||
|
add_column(TABLE, TEMPORARY_COLUMN, :int, default: 0, null: false)
|
||||||
|
install_rename_triggers(TABLE, MAIN_COLUMN, TEMPORARY_COLUMN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# rubocop:enable Migration/WithLockRetriesDisallowedMethod
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RemoveContainerRegistryEnabled < Gitlab::Database::Migration[1.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
with_lock_retries do
|
||||||
|
remove_column :projects, :container_registry_enabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
with_lock_retries do
|
||||||
|
add_column :projects, :container_registry_enabled, :boolean # rubocop:disable Migration/AddColumnsToWideTables
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
c99df310082dd6f5faff3cfd90dfca88af26d840889910ebac0e73ba483a09b2
|
|
@ -0,0 +1 @@
|
||||||
|
abed3f9a6c188890d3dcd21f73a09347f8ccec0f6cc448220fadba5cbda17281
|
|
@ -64,15 +64,6 @@ RETURN NULL;
|
||||||
END
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
CREATE FUNCTION trigger_21e7a2602957() RETURNS trigger
|
|
||||||
LANGUAGE plpgsql
|
|
||||||
AS $$
|
|
||||||
BEGIN
|
|
||||||
NEW."build_id_convert_to_bigint" := NEW."build_id";
|
|
||||||
RETURN NEW;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
CREATE FUNCTION trigger_3f6129be01d2() RETURNS trigger
|
CREATE FUNCTION trigger_3f6129be01d2() RETURNS trigger
|
||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$
|
AS $$
|
||||||
|
@ -11227,7 +11218,6 @@ ALTER SEQUENCE chat_teams_id_seq OWNED BY chat_teams.id;
|
||||||
|
|
||||||
CREATE TABLE ci_build_needs (
|
CREATE TABLE ci_build_needs (
|
||||||
id integer NOT NULL,
|
id integer NOT NULL,
|
||||||
build_id_convert_to_bigint integer DEFAULT 0 NOT NULL,
|
|
||||||
name text NOT NULL,
|
name text NOT NULL,
|
||||||
artifacts boolean DEFAULT true NOT NULL,
|
artifacts boolean DEFAULT true NOT NULL,
|
||||||
optional boolean DEFAULT false NOT NULL,
|
optional boolean DEFAULT false NOT NULL,
|
||||||
|
@ -18184,7 +18174,6 @@ CREATE TABLE projects (
|
||||||
public_builds boolean DEFAULT true NOT NULL,
|
public_builds boolean DEFAULT true NOT NULL,
|
||||||
last_repository_check_failed boolean,
|
last_repository_check_failed boolean,
|
||||||
last_repository_check_at timestamp without time zone,
|
last_repository_check_at timestamp without time zone,
|
||||||
container_registry_enabled boolean,
|
|
||||||
only_allow_merge_if_pipeline_succeeds boolean DEFAULT false NOT NULL,
|
only_allow_merge_if_pipeline_succeeds boolean DEFAULT false NOT NULL,
|
||||||
has_external_issue_tracker boolean,
|
has_external_issue_tracker boolean,
|
||||||
repository_storage character varying DEFAULT 'default'::character varying NOT NULL,
|
repository_storage character varying DEFAULT 'default'::character varying NOT NULL,
|
||||||
|
@ -27322,8 +27311,6 @@ ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_p
|
||||||
|
|
||||||
ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
|
ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
|
||||||
|
|
||||||
CREATE TRIGGER trigger_21e7a2602957 BEFORE INSERT OR UPDATE ON ci_build_needs FOR EACH ROW EXECUTE FUNCTION trigger_21e7a2602957();
|
|
||||||
|
|
||||||
CREATE TRIGGER trigger_3f6129be01d2 BEFORE INSERT OR UPDATE ON ci_builds FOR EACH ROW EXECUTE FUNCTION trigger_3f6129be01d2();
|
CREATE TRIGGER trigger_3f6129be01d2 BEFORE INSERT OR UPDATE ON ci_builds FOR EACH ROW EXECUTE FUNCTION trigger_3f6129be01d2();
|
||||||
|
|
||||||
CREATE TRIGGER trigger_542d6c2ad72e BEFORE INSERT OR UPDATE ON ci_builds_metadata FOR EACH ROW EXECUTE FUNCTION trigger_542d6c2ad72e();
|
CREATE TRIGGER trigger_542d6c2ad72e BEFORE INSERT OR UPDATE ON ci_builds_metadata FOR EACH ROW EXECUTE FUNCTION trigger_542d6c2ad72e();
|
||||||
|
|
|
@ -265,3 +265,9 @@ by assigning different processes to different parts of the table. The `BATCH`
|
||||||
and `UPDATE_DELAY` parameters allow the speed of the migration to be traded off
|
and `UPDATE_DELAY` parameters allow the speed of the migration to be traded off
|
||||||
against concurrent access to the table. The `ANSI` parameter should be set to
|
against concurrent access to the table. The `ANSI` parameter should be set to
|
||||||
false if your terminal does not support ANSI escape codes.
|
false if your terminal does not support ANSI escape codes.
|
||||||
|
|
||||||
|
By default, `sudo` does not preserve existing environment variables. You should append them, rather than prefix them.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo gitlab-rake gitlab:external_diffs:force_object_storage START_ID=59946109 END_ID=59946109 UPDATE_DELAY=5
|
||||||
|
```
|
||||||
|
|
|
@ -78,7 +78,7 @@ packages on the group level, create a distribution with the same `codename`.
|
||||||
To create a project-level distribution:
|
To create a project-level distribution:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/debian_distributions?codename=unstable
|
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/debian_distributions?codename=unstable"
|
||||||
```
|
```
|
||||||
|
|
||||||
Example response:
|
Example response:
|
||||||
|
|
|
@ -18,6 +18,24 @@ module Gitlab
|
||||||
KNOWN_EVENTS_PATH = File.expand_path('known_events/*.yml', __dir__)
|
KNOWN_EVENTS_PATH = File.expand_path('known_events/*.yml', __dir__)
|
||||||
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
|
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
|
||||||
|
|
||||||
|
CATEGORIES_FOR_TOTALS = %w[
|
||||||
|
analytics
|
||||||
|
code_review
|
||||||
|
compliance
|
||||||
|
deploy_token_packages
|
||||||
|
ecosystem
|
||||||
|
epic_boards_usage
|
||||||
|
epics_usage
|
||||||
|
ide_edit
|
||||||
|
incident_management
|
||||||
|
issues_edit
|
||||||
|
pipeline_authoring
|
||||||
|
quickactions
|
||||||
|
search
|
||||||
|
testing
|
||||||
|
user_packages
|
||||||
|
].freeze
|
||||||
|
|
||||||
# Track event on entity_id
|
# Track event on entity_id
|
||||||
# Increment a Redis HLL counter for unique event_name and entity_id
|
# Increment a Redis HLL counter for unique event_name and entity_id
|
||||||
#
|
#
|
||||||
|
@ -90,7 +108,7 @@ module Gitlab
|
||||||
hash["#{event}_monthly"] = unique_events(**monthly_time_range.merge(event_names: [event]))
|
hash["#{event}_monthly"] = unique_events(**monthly_time_range.merge(event_names: [event]))
|
||||||
end
|
end
|
||||||
|
|
||||||
if eligible_for_totals?(events_names)
|
if eligible_for_totals?(events_names) && CATEGORIES_FOR_TOTALS.include?(category)
|
||||||
event_results["#{category}_total_unique_counts_weekly"] = unique_events(**weekly_time_range.merge(event_names: events_names))
|
event_results["#{category}_total_unique_counts_weekly"] = unique_events(**weekly_time_range.merge(event_names: events_names))
|
||||||
event_results["#{category}_total_unique_counts_monthly"] = unique_events(**monthly_time_range.merge(event_names: events_names))
|
event_results["#{category}_total_unique_counts_monthly"] = unique_events(**monthly_time_range.merge(event_names: events_names))
|
||||||
end
|
end
|
||||||
|
|
|
@ -13366,6 +13366,9 @@ msgstr ""
|
||||||
msgid "ErrorTracking|Enable error tracking"
|
msgid "ErrorTracking|Enable error tracking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ErrorTracking|Error tracking backend"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
|
msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -28637,6 +28640,9 @@ msgstr[1] ""
|
||||||
msgid "Requires values to meet regular expression requirements."
|
msgid "Requires values to meet regular expression requirements."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Requires you to deploy or set up cloud-hosted Sentry."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Requires your primary GitLab email address."
|
msgid "Requires your primary GitLab email address."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -30517,6 +30523,9 @@ msgstr ""
|
||||||
msgid "Send service data"
|
msgid "Send service data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Sentry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Sentry API URL"
|
msgid "Sentry API URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -37013,6 +37022,9 @@ msgstr ""
|
||||||
msgid "UsersSelect|Unassigned"
|
msgid "UsersSelect|Unassigned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Uses GitLab as a lightweight alternative to Sentry."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
|
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe SecurityReportsMrWidgetPromptExperiment do
|
||||||
|
it "defines a control and candidate" do
|
||||||
|
expect(subject.behaviors.keys).to match_array(%w[control candidate])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "publishes to the database" do
|
||||||
|
expect(subject).to receive(:publish_to_database)
|
||||||
|
|
||||||
|
subject.publish
|
||||||
|
end
|
||||||
|
end
|
|
@ -89,7 +89,7 @@ RSpec.describe 'Search bar', :js do
|
||||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: original_size)
|
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: original_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'resets the dropdown filters', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/9985' do
|
it 'resets the dropdown filters' do
|
||||||
filtered_search.click
|
filtered_search.click
|
||||||
|
|
||||||
hint_offset = get_left_style(find('#js-dropdown-hint')['style'])
|
hint_offset = get_left_style(find('#js-dropdown-hint')['style'])
|
||||||
|
@ -103,7 +103,7 @@ RSpec.describe 'Search bar', :js do
|
||||||
find('.filtered-search-box .clear-search').click
|
find('.filtered-search-box .clear-search').click
|
||||||
filtered_search.click
|
filtered_search.click
|
||||||
|
|
||||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6)
|
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', minimum: 6)
|
||||||
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
|
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -150,6 +150,33 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
|
||||||
assert_text('Connection failed. Check Auth Token and try again.')
|
assert_text('Connection failed. Check Auth Token and try again.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'integrated error tracking backend' do
|
||||||
|
it 'successfully fills and submits the form' do
|
||||||
|
visit project_settings_operations_path(project)
|
||||||
|
|
||||||
|
wait_for_requests
|
||||||
|
|
||||||
|
within '.js-error-tracking-settings' do
|
||||||
|
click_button('Expand')
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_content('Error tracking backend')
|
||||||
|
|
||||||
|
within '.js-error-tracking-settings' do
|
||||||
|
check('Active')
|
||||||
|
choose('GitLab')
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).not_to have_content('Sentry API URL')
|
||||||
|
|
||||||
|
click_button('Save changes')
|
||||||
|
|
||||||
|
wait_for_requests
|
||||||
|
|
||||||
|
assert_text('Your changes have been saved')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'grafana integration settings form' do
|
context 'grafana integration settings form' do
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
|
||||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||||
|
import { nextTick } from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import ErrorTrackingSettings from '~/error_tracking_settings/components/app.vue';
|
import ErrorTrackingSettings from '~/error_tracking_settings/components/app.vue';
|
||||||
import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
|
import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
|
||||||
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
|
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
|
||||||
|
@ -14,20 +17,31 @@ describe('error tracking settings app', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
|
||||||
function mountComponent() {
|
function mountComponent() {
|
||||||
wrapper = shallowMount(ErrorTrackingSettings, {
|
wrapper = extendedWrapper(
|
||||||
localVue,
|
shallowMount(ErrorTrackingSettings, {
|
||||||
store, // Override the imported store
|
localVue,
|
||||||
propsData: {
|
store, // Override the imported store
|
||||||
initialEnabled: 'true',
|
propsData: {
|
||||||
initialApiHost: TEST_HOST,
|
initialEnabled: 'true',
|
||||||
initialToken: 'someToken',
|
initialIntegrated: 'false',
|
||||||
initialProject: null,
|
initialApiHost: TEST_HOST,
|
||||||
listProjectsEndpoint: TEST_HOST,
|
initialToken: 'someToken',
|
||||||
operationsSettingsEndpoint: TEST_HOST,
|
initialProject: null,
|
||||||
},
|
listProjectsEndpoint: TEST_HOST,
|
||||||
});
|
operationsSettingsEndpoint: TEST_HOST,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findBackendSettingsSection = () => wrapper.findByTestId('tracking-backend-settings');
|
||||||
|
const findBackendSettingsRadioGroup = () =>
|
||||||
|
findBackendSettingsSection().findComponent(GlFormRadioGroup);
|
||||||
|
const findBackendSettingsRadioButtons = () =>
|
||||||
|
findBackendSettingsRadioGroup().findAllComponents(GlFormRadio);
|
||||||
|
const findElementWithText = (wrappers, text) => wrappers.filter((item) => item.text() === text);
|
||||||
|
const findSentrySettings = () => wrapper.findByTestId('sentry-setting-form');
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
store = createStore();
|
store = createStore();
|
||||||
|
|
||||||
|
@ -62,4 +76,46 @@ describe('error tracking settings app', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('tracking-backend settings', () => {
|
||||||
|
it('contains a form-group with the correct label', () => {
|
||||||
|
expect(findBackendSettingsSection().attributes('label')).toBe('Error tracking backend');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains a radio group', () => {
|
||||||
|
expect(findBackendSettingsRadioGroup().exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains the correct radio buttons', () => {
|
||||||
|
expect(findBackendSettingsRadioButtons()).toHaveLength(2);
|
||||||
|
|
||||||
|
expect(findElementWithText(findBackendSettingsRadioButtons(), 'Sentry')).toHaveLength(1);
|
||||||
|
expect(findElementWithText(findBackendSettingsRadioButtons(), 'GitLab')).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toggles the sentry-settings section when sentry is selected as a tracking-backend', async () => {
|
||||||
|
expect(findSentrySettings().exists()).toBe(true);
|
||||||
|
|
||||||
|
// set the "integrated" setting to "true"
|
||||||
|
findBackendSettingsRadioGroup().vm.$emit('change', true);
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
expect(findSentrySettings().exists()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([true, false])(
|
||||||
|
'calls the `updateIntegrated` action when the setting changes to `%s`',
|
||||||
|
(integrated) => {
|
||||||
|
jest.spyOn(store, 'dispatch').mockImplementation();
|
||||||
|
|
||||||
|
expect(store.dispatch).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
|
findBackendSettingsRadioGroup().vm.$emit('change', integrated);
|
||||||
|
|
||||||
|
expect(store.dispatch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(store.dispatch).toHaveBeenCalledWith('updateIntegrated', integrated);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -42,6 +42,7 @@ export const sampleBackendProject = {
|
||||||
export const sampleFrontendSettings = {
|
export const sampleFrontendSettings = {
|
||||||
apiHost: 'apiHost',
|
apiHost: 'apiHost',
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: false,
|
||||||
token: 'token',
|
token: 'token',
|
||||||
selectedProject: {
|
selectedProject: {
|
||||||
slug: normalizedProject.slug,
|
slug: normalizedProject.slug,
|
||||||
|
@ -54,6 +55,7 @@ export const sampleFrontendSettings = {
|
||||||
export const transformedSettings = {
|
export const transformedSettings = {
|
||||||
api_host: 'apiHost',
|
api_host: 'apiHost',
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: false,
|
||||||
token: 'token',
|
token: 'token',
|
||||||
project: {
|
project: {
|
||||||
slug: normalizedProject.slug,
|
slug: normalizedProject.slug,
|
||||||
|
@ -71,6 +73,7 @@ export const defaultProps = {
|
||||||
export const initialEmptyState = {
|
export const initialEmptyState = {
|
||||||
apiHost: '',
|
apiHost: '',
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: false,
|
||||||
project: null,
|
project: null,
|
||||||
token: '',
|
token: '',
|
||||||
listProjectsEndpoint: TEST_HOST,
|
listProjectsEndpoint: TEST_HOST,
|
||||||
|
@ -80,6 +83,7 @@ export const initialEmptyState = {
|
||||||
export const initialPopulatedState = {
|
export const initialPopulatedState = {
|
||||||
apiHost: 'apiHost',
|
apiHost: 'apiHost',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
integrated: true,
|
||||||
project: JSON.stringify(projectList[0]),
|
project: JSON.stringify(projectList[0]),
|
||||||
token: 'token',
|
token: 'token',
|
||||||
listProjectsEndpoint: TEST_HOST,
|
listProjectsEndpoint: TEST_HOST,
|
||||||
|
|
|
@ -202,5 +202,11 @@ describe('error tracking settings actions', () => {
|
||||||
done,
|
done,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([true, false])('should set the `integrated` flag to `%s`', async (payload) => {
|
||||||
|
await testAction(actions.updateIntegrated, payload, state, [
|
||||||
|
{ type: types.UPDATE_INTEGRATED, payload },
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,6 +25,7 @@ describe('error tracking settings mutations', () => {
|
||||||
|
|
||||||
expect(state.apiHost).toEqual('');
|
expect(state.apiHost).toEqual('');
|
||||||
expect(state.enabled).toEqual(false);
|
expect(state.enabled).toEqual(false);
|
||||||
|
expect(state.integrated).toEqual(false);
|
||||||
expect(state.selectedProject).toEqual(null);
|
expect(state.selectedProject).toEqual(null);
|
||||||
expect(state.token).toEqual('');
|
expect(state.token).toEqual('');
|
||||||
expect(state.listProjectsEndpoint).toEqual(TEST_HOST);
|
expect(state.listProjectsEndpoint).toEqual(TEST_HOST);
|
||||||
|
@ -38,6 +39,7 @@ describe('error tracking settings mutations', () => {
|
||||||
|
|
||||||
expect(state.apiHost).toEqual('apiHost');
|
expect(state.apiHost).toEqual('apiHost');
|
||||||
expect(state.enabled).toEqual(true);
|
expect(state.enabled).toEqual(true);
|
||||||
|
expect(state.integrated).toEqual(true);
|
||||||
expect(state.selectedProject).toEqual(projectList[0]);
|
expect(state.selectedProject).toEqual(projectList[0]);
|
||||||
expect(state.token).toEqual('token');
|
expect(state.token).toEqual('token');
|
||||||
expect(state.listProjectsEndpoint).toEqual(TEST_HOST);
|
expect(state.listProjectsEndpoint).toEqual(TEST_HOST);
|
||||||
|
@ -78,5 +80,11 @@ describe('error tracking settings mutations', () => {
|
||||||
expect(state.connectSuccessful).toBe(false);
|
expect(state.connectSuccessful).toBe(false);
|
||||||
expect(state.connectError).toBe(false);
|
expect(state.connectError).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([true, false])('should update `integrated` to `%s`', (integrated) => {
|
||||||
|
mutations[types.UPDATE_INTEGRATED](state, integrated);
|
||||||
|
|
||||||
|
expect(state.integrated).toBe(integrated);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,12 +11,14 @@ describe('error tracking settings utils', () => {
|
||||||
const emptyFrontendSettingsObject = {
|
const emptyFrontendSettingsObject = {
|
||||||
apiHost: '',
|
apiHost: '',
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: false,
|
||||||
token: '',
|
token: '',
|
||||||
selectedProject: null,
|
selectedProject: null,
|
||||||
};
|
};
|
||||||
const transformedEmptySettingsObject = {
|
const transformedEmptySettingsObject = {
|
||||||
api_host: null,
|
api_host: null,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: false,
|
||||||
token: null,
|
token: null,
|
||||||
project: null,
|
project: null,
|
||||||
};
|
};
|
||||||
|
|
|
@ -462,6 +462,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
||||||
allow(described_class).to receive(:known_events).and_return(known_events)
|
allow(described_class).to receive(:known_events).and_return(known_events)
|
||||||
allow(described_class).to receive(:categories).and_return(%w(category1 category2))
|
allow(described_class).to receive(:categories).and_return(%w(category1 category2))
|
||||||
|
|
||||||
|
stub_const('Gitlab::UsageDataCounters::HLLRedisCounter::CATEGORIES_FOR_TOTALS', %w(category1 category2))
|
||||||
|
|
||||||
described_class.track_event('event1_slot', values: entity1, time: 2.days.ago)
|
described_class.track_event('event1_slot', values: entity1, time: 2.days.ago)
|
||||||
described_class.track_event('event2_slot', values: entity2, time: 2.days.ago)
|
described_class.track_event('event2_slot', values: entity2, time: 2.days.ago)
|
||||||
described_class.track_event('event2_slot', values: entity3, time: 2.weeks.ago)
|
described_class.track_event('event2_slot', values: entity3, time: 2.weeks.ago)
|
||||||
|
|
|
@ -1279,9 +1279,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
|
||||||
subject { described_class.redis_hll_counters }
|
subject { described_class.redis_hll_counters }
|
||||||
|
|
||||||
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
|
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
|
||||||
let(:ineligible_total_categories) do
|
|
||||||
%w[source_code ci_secrets_management incident_management_alerts snippets terraform incident_management_oncall secure network_policies]
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with redis_hll_tracking feature enabled' do
|
context 'with redis_hll_tracking feature enabled' do
|
||||||
it 'has all known_events' do
|
it 'has all known_events' do
|
||||||
|
@ -1296,7 +1293,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
|
||||||
|
|
||||||
metrics = keys.map { |key| "#{key}_weekly" } + keys.map { |key| "#{key}_monthly" }
|
metrics = keys.map { |key| "#{key}_weekly" } + keys.map { |key| "#{key}_monthly" }
|
||||||
|
|
||||||
if ineligible_total_categories.exclude?(category)
|
if ::Gitlab::UsageDataCounters::HLLRedisCounter::CATEGORIES_FOR_TOTALS.include?(category)
|
||||||
metrics.append("#{category}_total_unique_counts_weekly", "#{category}_total_unique_counts_monthly")
|
metrics.append("#{category}_total_unique_counts_weekly", "#{category}_total_unique_counts_monthly")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_migration!('drop_temporary_columns_and_triggers_for_ci_build_needs')
|
||||||
|
|
||||||
|
RSpec.describe DropTemporaryColumnsAndTriggersForCiBuildNeeds do
|
||||||
|
let(:ci_build_needs_table) { table(:ci_build_needs) }
|
||||||
|
|
||||||
|
it 'correctly migrates up and down' do
|
||||||
|
reversible_migration do |migration|
|
||||||
|
migration.before -> {
|
||||||
|
expect(ci_build_needs_table.column_names).to include('build_id_convert_to_bigint')
|
||||||
|
}
|
||||||
|
|
||||||
|
migration.after -> {
|
||||||
|
ci_build_needs_table.reset_column_information
|
||||||
|
expect(ci_build_needs_table.column_names).not_to include('build_id_convert_to_bigint')
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -153,6 +153,7 @@ RSpec.describe Projects::Operations::UpdateService do
|
||||||
{
|
{
|
||||||
error_tracking_setting_attributes: {
|
error_tracking_setting_attributes: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
integrated: true,
|
||||||
api_host: 'http://gitlab.com/',
|
api_host: 'http://gitlab.com/',
|
||||||
token: 'token',
|
token: 'token',
|
||||||
project: {
|
project: {
|
||||||
|
@ -174,6 +175,7 @@ RSpec.describe Projects::Operations::UpdateService do
|
||||||
|
|
||||||
project.reload
|
project.reload
|
||||||
expect(project.error_tracking_setting).not_to be_enabled
|
expect(project.error_tracking_setting).not_to be_enabled
|
||||||
|
expect(project.error_tracking_setting.integrated).to be_truthy
|
||||||
expect(project.error_tracking_setting.api_url).to eq(
|
expect(project.error_tracking_setting.api_url).to eq(
|
||||||
'http://gitlab.com/api/0/projects/org/project/'
|
'http://gitlab.com/api/0/projects/org/project/'
|
||||||
)
|
)
|
||||||
|
@ -206,6 +208,7 @@ RSpec.describe Projects::Operations::UpdateService do
|
||||||
{
|
{
|
||||||
error_tracking_setting_attributes: {
|
error_tracking_setting_attributes: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
integrated: true,
|
||||||
api_host: 'http://gitlab.com/',
|
api_host: 'http://gitlab.com/',
|
||||||
token: 'token',
|
token: 'token',
|
||||||
project: {
|
project: {
|
||||||
|
@ -222,6 +225,7 @@ RSpec.describe Projects::Operations::UpdateService do
|
||||||
expect(result[:status]).to eq(:success)
|
expect(result[:status]).to eq(:success)
|
||||||
|
|
||||||
expect(project.error_tracking_setting).to be_enabled
|
expect(project.error_tracking_setting).to be_enabled
|
||||||
|
expect(project.error_tracking_setting.integrated).to be_truthy
|
||||||
expect(project.error_tracking_setting.api_url).to eq(
|
expect(project.error_tracking_setting.api_url).to eq(
|
||||||
'http://gitlab.com/api/0/projects/org/project/'
|
'http://gitlab.com/api/0/projects/org/project/'
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,25 +17,6 @@ class BareRepoOperations
|
||||||
commit_id[0]
|
commit_id[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit_file(file, dst_path, branch = 'master')
|
|
||||||
head_id = execute(['show', '--format=format:%H', '--no-patch', branch], allow_failure: true)[0] || Gitlab::Git::EMPTY_TREE_ID
|
|
||||||
|
|
||||||
execute(['read-tree', '--empty'])
|
|
||||||
execute(['read-tree', head_id])
|
|
||||||
|
|
||||||
blob_id = execute(['hash-object', '--stdin', '-w']) do |stdin|
|
|
||||||
stdin.write(file.read)
|
|
||||||
end
|
|
||||||
|
|
||||||
execute(['update-index', '--add', '--cacheinfo', '100644', blob_id[0], dst_path])
|
|
||||||
|
|
||||||
tree_id = execute(['write-tree'])
|
|
||||||
|
|
||||||
commit_id = commit_tree(tree_id[0], "Add #{dst_path}", parent: head_id)
|
|
||||||
|
|
||||||
execute(['update-ref', "refs/heads/#{branch}", commit_id])
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def execute(args, allow_failure: false)
|
def execute(args, allow_failure: false)
|
||||||
|
|
Loading…
Reference in New Issue