diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-16 00:11:12 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-16 00:11:12 +0300 |
commit | a7aff3e0e4deb15c0902e0f948eb300ba77f3e47 (patch) | |
tree | c294fb9c39d5619fb3cac6f4a8d520deb8403dca | |
parent | 27d1ed4ddff6c2649544a968c2842140272d9c9d (diff) |
Add latest changes from gitlab-org/gitlab@master
38 files changed, 368 insertions, 81 deletions
diff --git a/app/assets/javascripts/error_tracking_settings/components/app.vue b/app/assets/javascripts/error_tracking_settings/components/app.vue index d188574e721..e12d9cc2b07 100644 --- a/app/assets/javascripts/error_tracking_settings/components/app.vue +++ b/app/assets/javascripts/error_tracking_settings/components/app.vue @@ -1,5 +1,5 @@ <script> -import { GlButton, GlFormGroup, GlFormCheckbox } from '@gitlab/ui'; +import { GlButton, GlFormGroup, GlFormCheckbox, GlFormRadioGroup, GlFormRadio } from '@gitlab/ui'; import { mapActions, mapGetters, mapState } from 'vuex'; import ErrorTrackingForm from './error_tracking_form.vue'; import ProjectDropdown from './project_dropdown.vue'; @@ -10,6 +10,8 @@ export default { GlButton, GlFormCheckbox, GlFormGroup, + GlFormRadioGroup, + GlFormRadio, ProjectDropdown, }, props: { @@ -22,6 +24,10 @@ export default { type: String, required: true, }, + initialIntegrated: { + type: String, + required: true, + }, initialProject: { type: String, required: false, @@ -49,12 +55,20 @@ export default { 'isProjectInvalid', 'projectSelectionLabel', ]), - ...mapState(['enabled', 'projects', 'selectedProject', 'settingsLoading', 'token']), + ...mapState([ + 'enabled', + 'integrated', + 'projects', + 'selectedProject', + 'settingsLoading', + 'token', + ]), }, created() { this.setInitialState({ apiHost: this.initialApiHost, enabled: this.initialEnabled, + integrated: this.initialIntegrated, project: this.initialProject, token: this.initialToken, listProjectsEndpoint: this.listProjectsEndpoint, @@ -62,7 +76,13 @@ export default { }); }, methods: { - ...mapActions(['setInitialState', 'updateEnabled', 'updateSelectedProject', 'updateSettings']), + ...mapActions([ + 'setInitialState', + 'updateEnabled', + 'updateIntegrated', + 'updateSelectedProject', + 'updateSettings', + ]), handleSubmit() { this.updateSettings(); }, @@ -76,27 +96,44 @@ export default { :label="s__('ErrorTracking|Enable error tracking')" label-for="error-tracking-enabled" > - <gl-form-checkbox - id="error-tracking-enabled" - :checked="enabled" - @change="updateEnabled($event)" - > + <gl-form-checkbox id="error-tracking-enabled" :checked="enabled" @change="updateEnabled"> {{ s__('ErrorTracking|Active') }} </gl-form-checkbox> </gl-form-group> - <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" - /> + <gl-form-group + :label="s__('ErrorTracking|Error tracking backend')" + data-testid="tracking-backend-settings" + > + <gl-form-radio-group name="explicit" :checked="integrated" @change="updateIntegrated"> + <gl-form-radio name="error-tracking-integrated" :value="false"> + {{ __('Sentry') }} + <template #help> + {{ __('Requires you to deploy or set up cloud-hosted Sentry.') }} + </template> + </gl-form-radio> + <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> <gl-button :disabled="settingsLoading" diff --git a/app/assets/javascripts/error_tracking_settings/index.js b/app/assets/javascripts/error_tracking_settings/index.js index ce315963723..324b3292834 100644 --- a/app/assets/javascripts/error_tracking_settings/index.js +++ b/app/assets/javascripts/error_tracking_settings/index.js @@ -5,7 +5,15 @@ import createStore from './store'; export default () => { const formContainerEl = document.querySelector('.js-error-tracking-form'); const { - dataset: { apiHost, enabled, project, token, listProjectsEndpoint, operationsSettingsEndpoint }, + dataset: { + apiHost, + enabled, + integrated, + project, + token, + listProjectsEndpoint, + operationsSettingsEndpoint, + }, } = formContainerEl; return new Vue({ @@ -16,6 +24,7 @@ export default () => { props: { initialApiHost: apiHost, initialEnabled: enabled, + initialIntegrated: integrated, initialProject: project, initialToken: token, listProjectsEndpoint, diff --git a/app/assets/javascripts/error_tracking_settings/store/actions.js b/app/assets/javascripts/error_tracking_settings/store/actions.js index d402d0336d9..972ad58c617 100644 --- a/app/assets/javascripts/error_tracking_settings/store/actions.js +++ b/app/assets/javascripts/error_tracking_settings/store/actions.js @@ -79,6 +79,10 @@ export const updateEnabled = ({ commit }, enabled) => { commit(types.UPDATE_ENABLED, enabled); }; +export const updateIntegrated = ({ commit }, integrated) => { + commit(types.UPDATE_INTEGRATED, integrated); +}; + export const updateToken = ({ commit }, token) => { commit(types.UPDATE_TOKEN, token); commit(types.RESET_CONNECT); diff --git a/app/assets/javascripts/error_tracking_settings/store/mutation_types.js b/app/assets/javascripts/error_tracking_settings/store/mutation_types.js index bf3df383ddc..2cfa14c9b64 100644 --- a/app/assets/javascripts/error_tracking_settings/store/mutation_types.js +++ b/app/assets/javascripts/error_tracking_settings/store/mutation_types.js @@ -6,6 +6,7 @@ export const UPDATE_API_HOST = 'UPDATE_API_HOST'; export const UPDATE_CONNECT_ERROR = 'UPDATE_CONNECT_ERROR'; export const UPDATE_CONNECT_SUCCESS = 'UPDATE_CONNECT_SUCCESS'; export const UPDATE_ENABLED = 'UPDATE_ENABLED'; +export const UPDATE_INTEGRATED = 'UPDATE_INTEGRATED'; export const UPDATE_SELECTED_PROJECT = 'UPDATE_SELECTED_PROJECT'; export const UPDATE_SETTINGS_LOADING = 'UPDATE_SETTINGS_LOADING'; export const UPDATE_TOKEN = 'UPDATE_TOKEN'; diff --git a/app/assets/javascripts/error_tracking_settings/store/mutations.js b/app/assets/javascripts/error_tracking_settings/store/mutations.js index 2242169aa1e..a1b43ccaaee 100644 --- a/app/assets/javascripts/error_tracking_settings/store/mutations.js +++ b/app/assets/javascripts/error_tracking_settings/store/mutations.js @@ -20,9 +20,18 @@ export default { }, [types.SET_INITIAL_STATE]( state, - { apiHost, enabled, project, token, listProjectsEndpoint, operationsSettingsEndpoint }, + { + apiHost, + enabled, + integrated, + project, + token, + listProjectsEndpoint, + operationsSettingsEndpoint, + }, ) { state.enabled = parseBoolean(enabled); + state.integrated = parseBoolean(integrated); state.apiHost = apiHost; state.token = token; state.listProjectsEndpoint = listProjectsEndpoint; @@ -38,6 +47,9 @@ export default { [types.UPDATE_ENABLED](state, enabled) { state.enabled = enabled; }, + [types.UPDATE_INTEGRATED](state, integrated) { + state.integrated = integrated; + }, [types.UPDATE_TOKEN](state, token) { state.token = token; }, diff --git a/app/assets/javascripts/error_tracking_settings/store/state.js b/app/assets/javascripts/error_tracking_settings/store/state.js index ab616f11e83..ee5597abeb3 100644 --- a/app/assets/javascripts/error_tracking_settings/store/state.js +++ b/app/assets/javascripts/error_tracking_settings/store/state.js @@ -1,6 +1,7 @@ export default () => ({ apiHost: '', enabled: false, + integrated: false, token: '', projects: [], isLoadingProjects: false, diff --git a/app/assets/javascripts/error_tracking_settings/utils.js b/app/assets/javascripts/error_tracking_settings/utils.js index 5d18ac8e802..7ef5f7bbd34 100644 --- a/app/assets/javascripts/error_tracking_settings/utils.js +++ b/app/assets/javascripts/error_tracking_settings/utils.js @@ -1,6 +1,12 @@ 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 ? { slug: selectedProject.slug, @@ -10,7 +16,7 @@ export const transformFrontendSettings = ({ apiHost, enabled, token, selectedPro } : 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}`; diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index e32815b6239..56e201c592f 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -136,6 +136,7 @@ module Projects error_tracking_setting_attributes: [ :enabled, + :integrated, :api_host, :token, project: [:slug, :name, :organization_slug, :organization_name] diff --git a/app/experiments/security_reports_mr_widget_prompt_experiment.rb b/app/experiments/security_reports_mr_widget_prompt_experiment.rb new file mode 100644 index 00000000000..fa0ba8e24d4 --- /dev/null +++ b/app/experiments/security_reports_mr_widget_prompt_experiment.rb @@ -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 diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb index 51b8e3c6c54..ef74f3e6e7a 100644 --- a/app/services/projects/operations/update_service.rb +++ b/app/services/projects/operations/update_service.rb @@ -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][:integrated] = settings[:integrated] unless settings[:integrated].nil? params end diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml index 4ef9e1bd6fb..6b2a1468eec 100644 --- a/app/views/projects/settings/operations/_error_tracking.html.haml +++ b/app/views/projects/settings/operations/_error_tracking.html.haml @@ -17,4 +17,5 @@ project: error_tracking_setting_project_json, api_host: setting.api_host, enabled: setting.enabled.to_json, + integrated: setting.integrated.to_json, token: setting.token.present? ? '*' * 12 : nil } } diff --git a/config/feature_flags/development/ci_pipeline_add_job_with_lock.yml b/config/feature_flags/development/ci_pipeline_add_job_with_lock.yml index 48aa64ba7f4..6a708013ca5 100644 --- a/config/feature_flags/development/ci_pipeline_add_job_with_lock.yml +++ b/config/feature_flags/development/ci_pipeline_add_job_with_lock.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337628 milestone: '14.2' type: development group: group::pipeline authoring -default_enabled: false +default_enabled: true diff --git a/config/feature_flags/experiment/security_reports_mr_widget_prompt.yml b/config/feature_flags/experiment/security_reports_mr_widget_prompt.yml new file mode 100644 index 00000000000..ca6d17b1720 --- /dev/null +++ b/config/feature_flags/experiment/security_reports_mr_widget_prompt.yml @@ -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 diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml index dea3cb13db0..66b8e714723 100644 --- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml +++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml @@ -7,7 +7,8 @@ product_stage: configure product_group: group::configure product_category: infrastructure_as_code value_type: number -status: broken +status: removed +milestone_removed: '14.3' repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466 time_frame: 28d data_source: redis_hll diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml index 96d25513545..cf0e69c6da2 100644 --- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml +++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml @@ -7,7 +7,8 @@ product_stage: configure product_group: group::configure product_category: infrastructure_as_code value_type: number -status: broken +status: removed +milestone_removed: '14.3' repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466 time_frame: 7d data_source: redis_hll diff --git a/config/pseudonymizer.yml b/config/pseudonymizer.yml index 532fbe3b70f..cd8db9d8dc5 100644 --- a/config/pseudonymizer.yml +++ b/config/pseudonymizer.yml @@ -385,7 +385,6 @@ tables: - public_builds - last_repository_check_failed - last_repository_check_at - - container_registry_enabled - only_allow_merge_if_pipeline_succeeds - has_external_issue_tracker - repository_storage diff --git a/db/post_migrate/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs.rb b/db/post_migrate/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs.rb new file mode 100644 index 00000000000..f04c5cd6561 --- /dev/null +++ b/db/post_migrate/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs.rb @@ -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 diff --git a/db/post_migrate/20210909152027_remove_container_registry_enabled.rb b/db/post_migrate/20210909152027_remove_container_registry_enabled.rb new file mode 100644 index 00000000000..d97faaf58d2 --- /dev/null +++ b/db/post_migrate/20210909152027_remove_container_registry_enabled.rb @@ -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 diff --git a/db/schema_migrations/20210902144144 b/db/schema_migrations/20210902144144 new file mode 100644 index 00000000000..330569f1beb --- /dev/null +++ b/db/schema_migrations/20210902144144 @@ -0,0 +1 @@ +c99df310082dd6f5faff3cfd90dfca88af26d840889910ebac0e73ba483a09b2
\ No newline at end of file diff --git a/db/schema_migrations/20210909152027 b/db/schema_migrations/20210909152027 new file mode 100644 index 00000000000..39db0c43aa6 --- /dev/null +++ b/db/schema_migrations/20210909152027 @@ -0,0 +1 @@ +abed3f9a6c188890d3dcd21f73a09347f8ccec0f6cc448220fadba5cbda17281
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 3453df441cd..6ccb49396d0 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -64,15 +64,6 @@ RETURN NULL; 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 LANGUAGE plpgsql AS $$ @@ -11227,7 +11218,6 @@ ALTER SEQUENCE chat_teams_id_seq OWNED BY chat_teams.id; CREATE TABLE ci_build_needs ( id integer NOT NULL, - build_id_convert_to_bigint integer DEFAULT 0 NOT NULL, name text NOT NULL, artifacts boolean DEFAULT true NOT NULL, optional boolean DEFAULT false NOT NULL, @@ -18184,7 +18174,6 @@ CREATE TABLE projects ( public_builds boolean DEFAULT true NOT NULL, last_repository_check_failed boolean, last_repository_check_at timestamp without time zone, - container_registry_enabled boolean, only_allow_merge_if_pipeline_succeeds boolean DEFAULT false NOT NULL, has_external_issue_tracker boolean, 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; -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_542d6c2ad72e BEFORE INSERT OR UPDATE ON ci_builds_metadata FOR EACH ROW EXECUTE FUNCTION trigger_542d6c2ad72e(); diff --git a/doc/administration/merge_request_diffs.md b/doc/administration/merge_request_diffs.md index 1133bff204c..d6b9fa2b8d3 100644 --- a/doc/administration/merge_request_diffs.md +++ b/doc/administration/merge_request_diffs.md @@ -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 against concurrent access to the table. The `ANSI` parameter should be set to 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 +``` diff --git a/doc/user/packages/debian_repository/index.md b/doc/user/packages/debian_repository/index.md index 28489bb89b2..29641380753 100644 --- a/doc/user/packages/debian_repository/index.md +++ b/doc/user/packages/debian_repository/index.md @@ -78,7 +78,7 @@ packages on the group level, create a distribution with the same `codename`. To create a project-level distribution: ```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: diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb index 96562a44391..8fc8bb5d344 100644 --- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb +++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb @@ -18,6 +18,24 @@ module Gitlab KNOWN_EVENTS_PATH = File.expand_path('known_events/*.yml', __dir__) 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 # 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])) 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_monthly"] = unique_events(**monthly_time_range.merge(event_names: events_names)) end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 9fe1eb7a262..2ce4bc6f2e8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -13366,6 +13366,9 @@ msgstr "" msgid "ErrorTracking|Enable error tracking" 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" msgstr "" @@ -28637,6 +28640,9 @@ msgstr[1] "" msgid "Requires values to meet regular expression requirements." msgstr "" +msgid "Requires you to deploy or set up cloud-hosted Sentry." +msgstr "" + msgid "Requires your primary GitLab email address." msgstr "" @@ -30517,6 +30523,9 @@ msgstr "" msgid "Send service data" msgstr "" +msgid "Sentry" +msgstr "" + msgid "Sentry API URL" msgstr "" @@ -37013,6 +37022,9 @@ msgstr "" msgid "UsersSelect|Unassigned" 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}" msgstr "" diff --git a/spec/experiments/security_reports_mr_widget_prompt_experiment_spec.rb b/spec/experiments/security_reports_mr_widget_prompt_experiment_spec.rb new file mode 100644 index 00000000000..4328ff12d42 --- /dev/null +++ b/spec/experiments/security_reports_mr_widget_prompt_experiment_spec.rb @@ -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 diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb index 1efcc329e32..60963d95ae5 100644 --- a/spec/features/issues/filtered_search/search_bar_spec.rb +++ b/spec/features/issues/filtered_search/search_bar_spec.rb @@ -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) 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 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 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) end end diff --git a/spec/features/projects/settings/monitor_settings_spec.rb b/spec/features/projects/settings/monitor_settings_spec.rb index 2d8c418b7d0..e3d75c30e5e 100644 --- a/spec/features/projects/settings/monitor_settings_spec.rb +++ b/spec/features/projects/settings/monitor_settings_spec.rb @@ -150,6 +150,33 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do assert_text('Connection failed. Check Auth Token and try again.') 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 context 'grafana integration settings form' do diff --git a/spec/frontend/error_tracking_settings/components/app_spec.js b/spec/frontend/error_tracking_settings/components/app_spec.js index e0be81b3899..30541ba68a5 100644 --- a/spec/frontend/error_tracking_settings/components/app_spec.js +++ b/spec/frontend/error_tracking_settings/components/app_spec.js @@ -1,6 +1,9 @@ +import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui'; import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Vuex from 'vuex'; 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 ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue'; import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue'; @@ -14,20 +17,31 @@ describe('error tracking settings app', () => { let wrapper; function mountComponent() { - wrapper = shallowMount(ErrorTrackingSettings, { - localVue, - store, // Override the imported store - propsData: { - initialEnabled: 'true', - initialApiHost: TEST_HOST, - initialToken: 'someToken', - initialProject: null, - listProjectsEndpoint: TEST_HOST, - operationsSettingsEndpoint: TEST_HOST, - }, - }); + wrapper = extendedWrapper( + shallowMount(ErrorTrackingSettings, { + localVue, + store, // Override the imported store + propsData: { + initialEnabled: 'true', + initialIntegrated: 'false', + initialApiHost: TEST_HOST, + initialToken: 'someToken', + 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(() => { 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); + }, + ); + }); }); diff --git a/spec/frontend/error_tracking_settings/mock.js b/spec/frontend/error_tracking_settings/mock.js index e64a6d1fe14..b2d7a912518 100644 --- a/spec/frontend/error_tracking_settings/mock.js +++ b/spec/frontend/error_tracking_settings/mock.js @@ -42,6 +42,7 @@ export const sampleBackendProject = { export const sampleFrontendSettings = { apiHost: 'apiHost', enabled: false, + integrated: false, token: 'token', selectedProject: { slug: normalizedProject.slug, @@ -54,6 +55,7 @@ export const sampleFrontendSettings = { export const transformedSettings = { api_host: 'apiHost', enabled: false, + integrated: false, token: 'token', project: { slug: normalizedProject.slug, @@ -71,6 +73,7 @@ export const defaultProps = { export const initialEmptyState = { apiHost: '', enabled: false, + integrated: false, project: null, token: '', listProjectsEndpoint: TEST_HOST, @@ -80,6 +83,7 @@ export const initialEmptyState = { export const initialPopulatedState = { apiHost: 'apiHost', enabled: true, + integrated: true, project: JSON.stringify(projectList[0]), token: 'token', listProjectsEndpoint: TEST_HOST, diff --git a/spec/frontend/error_tracking_settings/store/actions_spec.js b/spec/frontend/error_tracking_settings/store/actions_spec.js index 281db7d9686..1b9be042dd4 100644 --- a/spec/frontend/error_tracking_settings/store/actions_spec.js +++ b/spec/frontend/error_tracking_settings/store/actions_spec.js @@ -202,5 +202,11 @@ describe('error tracking settings actions', () => { 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 }, + ]); + }); }); }); diff --git a/spec/frontend/error_tracking_settings/store/mutation_spec.js b/spec/frontend/error_tracking_settings/store/mutation_spec.js index 78fd56904b3..ecf1c91c08a 100644 --- a/spec/frontend/error_tracking_settings/store/mutation_spec.js +++ b/spec/frontend/error_tracking_settings/store/mutation_spec.js @@ -25,6 +25,7 @@ describe('error tracking settings mutations', () => { expect(state.apiHost).toEqual(''); expect(state.enabled).toEqual(false); + expect(state.integrated).toEqual(false); expect(state.selectedProject).toEqual(null); expect(state.token).toEqual(''); expect(state.listProjectsEndpoint).toEqual(TEST_HOST); @@ -38,6 +39,7 @@ describe('error tracking settings mutations', () => { expect(state.apiHost).toEqual('apiHost'); expect(state.enabled).toEqual(true); + expect(state.integrated).toEqual(true); expect(state.selectedProject).toEqual(projectList[0]); expect(state.token).toEqual('token'); expect(state.listProjectsEndpoint).toEqual(TEST_HOST); @@ -78,5 +80,11 @@ describe('error tracking settings mutations', () => { expect(state.connectSuccessful).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); + }); }); }); diff --git a/spec/frontend/error_tracking_settings/utils_spec.js b/spec/frontend/error_tracking_settings/utils_spec.js index 4b144f7daf1..61e75cdc45e 100644 --- a/spec/frontend/error_tracking_settings/utils_spec.js +++ b/spec/frontend/error_tracking_settings/utils_spec.js @@ -11,12 +11,14 @@ describe('error tracking settings utils', () => { const emptyFrontendSettingsObject = { apiHost: '', enabled: false, + integrated: false, token: '', selectedProject: null, }; const transformedEmptySettingsObject = { api_host: null, enabled: false, + integrated: false, token: null, project: null, }; diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb index 887759014f5..427dd4a205e 100644 --- a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb @@ -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(: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('event2_slot', values: entity2, time: 2.days.ago) described_class.track_event('event2_slot', values: entity3, time: 2.weeks.ago) diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 5d85ad5ad01..d96cd8a2db4 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -1279,9 +1279,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do subject { described_class.redis_hll_counters } 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 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" } - 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") end diff --git a/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb b/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb new file mode 100644 index 00000000000..1b35982c41d --- /dev/null +++ b/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb @@ -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 diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb index 1d9d5f6e938..a71fafb2121 100644 --- a/spec/services/projects/operations/update_service_spec.rb +++ b/spec/services/projects/operations/update_service_spec.rb @@ -153,6 +153,7 @@ RSpec.describe Projects::Operations::UpdateService do { error_tracking_setting_attributes: { enabled: false, + integrated: true, api_host: 'http://gitlab.com/', token: 'token', project: { @@ -174,6 +175,7 @@ RSpec.describe Projects::Operations::UpdateService do project.reload 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( 'http://gitlab.com/api/0/projects/org/project/' ) @@ -206,6 +208,7 @@ RSpec.describe Projects::Operations::UpdateService do { error_tracking_setting_attributes: { enabled: true, + integrated: true, api_host: 'http://gitlab.com/', token: 'token', project: { @@ -222,6 +225,7 @@ RSpec.describe Projects::Operations::UpdateService do expect(result[:status]).to eq(:success) 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( 'http://gitlab.com/api/0/projects/org/project/' ) diff --git a/spec/support/helpers/bare_repo_operations.rb b/spec/support/helpers/bare_repo_operations.rb index cd2dcecd1b6..e29e12a15f6 100644 --- a/spec/support/helpers/bare_repo_operations.rb +++ b/spec/support/helpers/bare_repo_operations.rb @@ -17,25 +17,6 @@ class BareRepoOperations commit_id[0] 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 def execute(args, allow_failure: false) |