From 04a7fe4f4b1a693f14a676c5aa556bcdfac9d899 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 12 Oct 2021 18:12:42 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- CHANGELOG.md | 8 + .../ui/pipeline_editor_empty_state.vue | 14 +- .../profiles/passwords_controller.rb | 25 +- .../projects/ci/pipeline_editor_controller.rb | 1 - app/models/ci/build.rb | 55 +++- app/models/deployment.rb | 51 +++- app/views/profiles/passwords/edit.html.haml | 10 +- app/views/profiles/passwords/new.html.haml | 10 +- ...e_deployment_after_transaction_commit.yml} | 12 +- ...0210929025600_add_phone_to_user_details.rb | 15 + ...34_add_text_limit_to_user_details_phone.rb | 13 + ..._add_unique_index_phone_on_user_details.rb | 15 + ...0210929032555_create_verification_codes.rb | 36 +++ db/schema_migrations/20210929025600 | 1 + db/schema_migrations/20210929030834 | 1 + db/schema_migrations/20210929031049 | 1 + db/schema_migrations/20210929032555 | 1 + db/structure.sql | 28 ++ .../build_cloud/windows_build_cloud.md | 2 +- doc/development/documentation/testing.md | 1 - .../settings/external_authorization.md | 5 +- doc/user/analytics/ci_cd_analytics.md | 6 +- doc/user/analytics/issue_analytics.md | 2 +- doc/user/analytics/merge_request_analytics.md | 2 +- doc/user/analytics/productivity_analytics.md | 4 +- doc/user/analytics/repository_analytics.md | 2 +- .../coverage_fuzzing/index.md | 12 + .../group/settings/img/import_panel_v14_1.png | Bin 42789 -> 0 bytes .../img/new_group_navigation_v13_1.png | Bin 39500 -> 0 bytes doc/user/group/settings/import_export.md | 37 ++- .../notification_global_settings_v13_12.png | Bin 9268 -> 0 bytes doc/user/profile/notifications.md | 262 +++++++++--------- spec/features/profiles/password_spec.rb | 10 +- spec/features/users/login_spec.rb | 4 +- .../ui/pipeline_editor_empty_state_spec.js | 21 -- .../pipeline_editor_app_spec.js | 35 +-- spec/models/ci/build_spec.rb | 34 ++- spec/models/deployment_spec.rb | 135 ++++++++- spec/requests/api/deployments_spec.rb | 10 + .../deployments/update_service_spec.rb | 8 +- 40 files changed, 592 insertions(+), 297 deletions(-) rename config/feature_flags/development/{pipeline_editor_empty_state_action.yml => update_deployment_after_transaction_commit.yml} (52%) create mode 100644 db/migrate/20210929025600_add_phone_to_user_details.rb create mode 100644 db/migrate/20210929030834_add_text_limit_to_user_details_phone.rb create mode 100644 db/migrate/20210929031049_add_unique_index_phone_on_user_details.rb create mode 100644 db/migrate/20210929032555_create_verification_codes.rb create mode 100644 db/schema_migrations/20210929025600 create mode 100644 db/schema_migrations/20210929030834 create mode 100644 db/schema_migrations/20210929031049 create mode 100644 db/schema_migrations/20210929032555 delete mode 100644 doc/user/group/settings/img/import_panel_v14_1.png delete mode 100644 doc/user/group/settings/img/new_group_navigation_v13_1.png delete mode 100644 doc/user/profile/img/notification_global_settings_v13_12.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b6894e4e41..362ebae3c91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 14.3.3 (2021-10-12) + +### Fixed (3 changes) + +- [Disable caching of MergeToRefService call in mergeability check](gitlab-org/gitlab@ea9f38fb3ce1f9b345ca699b5f9ae7b36726a56f) ([merge request](gitlab-org/gitlab!72179)) +- [Fix 2FA setup for users with no password](gitlab-org/gitlab@c6d5cdfc3fa1a1dc0a6686a8f189972c03403f7a) ([merge request](gitlab-org/gitlab!72179)) +- [Fix dependency proxy image prefix](gitlab-org/gitlab@deb9719db05e99dec787bd76c5e96408f92eb802) ([merge request](gitlab-org/gitlab!72179)) + ## 14.3.2 (2021-10-01) ### Fixed (1 change) diff --git a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue index fbb66231f16..dcd08c9de8d 100644 --- a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue +++ b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue @@ -2,7 +2,6 @@ import { GlButton, GlSprintf } from '@gitlab/ui'; import { __ } from '~/locale'; import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { components: { @@ -17,17 +16,11 @@ export default { ), btnText: __('Create new CI/CD pipeline'), }, - mixins: [glFeatureFlagsMixin()], inject: { emptyStateIllustrationPath: { default: '', }, }, - computed: { - showCTAButton() { - return this.glFeatures.pipelineEditorEmptyStateAction; - }, - }, methods: { createEmptyConfigFile() { this.$emit('createEmptyConfigFile'); @@ -48,12 +41,7 @@ export default {

- + {{ $options.i18n.btnText }} diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index c8c2dd1c7d6..5eb0f80ddc9 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -15,17 +15,11 @@ class Profiles::PasswordsController < Profiles::ApplicationController end def create - unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password]) + unless @user.password_automatically_set || @user.valid_password?(user_params[:password]) redirect_to new_profile_password_path, alert: _('You must provide a valid current password') return end - password_attributes = { - password: user_params[:password], - password_confirmation: user_params[:password_confirmation], - password_automatically_set: false - } - result = Users::UpdateService.new(current_user, password_attributes.merge(user: @user)).execute if result[:status] == :success @@ -41,12 +35,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController end def update - password_attributes = user_params.select do |key, value| - %w(password password_confirmation).include?(key.to_s) - end - password_attributes[:password_automatically_set] = false - - unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password]) + unless @user.password_automatically_set || @user.valid_password?(user_params[:password]) handle_invalid_current_password_attempt! redirect_to edit_profile_password_path, alert: _('You must provide a valid current password') @@ -94,6 +83,14 @@ class Profiles::PasswordsController < Profiles::ApplicationController end def user_params - params.require(:user).permit(:current_password, :password, :password_confirmation) + params.require(:user).permit(:password, :new_password, :password_confirmation) + end + + def password_attributes + { + password: user_params[:new_password], + password_confirmation: user_params[:password_confirmation], + password_automatically_set: false + } end end diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index 550877548e1..953b9d83a66 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -3,7 +3,6 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController before_action :check_can_collaborate! before_action do - push_frontend_feature_flag(:pipeline_editor_empty_state_action, @project, default_enabled: :yaml) push_frontend_feature_flag(:pipeline_editor_drawer, @project, default_enabled: :yaml) push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml) end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 1e0ce5638bb..226289e4f62 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -309,8 +309,10 @@ module Ci end after_transition pending: :running do |build| - Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do - build.deployment&.run + unless build.update_deployment_after_transaction_commit? + Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do + build.deployment&.run + end end build.run_after_commit do @@ -333,8 +335,10 @@ module Ci end after_transition any => [:success] do |build| - Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do - build.deployment&.succeed + unless build.update_deployment_after_transaction_commit? + Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do + build.deployment&.succeed + end end build.run_after_commit do @@ -347,12 +351,14 @@ module Ci next unless build.project next unless build.deployment - begin - Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do - build.deployment.drop! + unless build.update_deployment_after_transaction_commit? + begin + Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do + build.deployment.drop! + end + rescue StandardError => e + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, build_id: build.id) end - rescue StandardError => e - Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, build_id: build.id) end true @@ -371,14 +377,29 @@ module Ci end after_transition any => [:skipped, :canceled] do |build, transition| - Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do - if transition.to_name == :skipped - build.deployment&.skip - else - build.deployment&.cancel + unless build.update_deployment_after_transaction_commit? + Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do + if transition.to_name == :skipped + build.deployment&.skip + else + build.deployment&.cancel + end end end end + + # Synchronize Deployment Status + # Please note that the data integirty is not assured because we can't use + # a database transaction due to DB decomposition. + after_transition do |build, transition| + next if transition.loopback? + next unless build.project + next unless build.update_deployment_after_transaction_commit? + + build.run_after_commit do + build.deployment&.sync_status_with(build) + end + end end def self.build_matchers(project) @@ -1095,6 +1116,12 @@ module Ci runner&.instance_type? end + def update_deployment_after_transaction_commit? + strong_memoize(:update_deployment_after_transaction_commit) do + Feature.enabled?(:update_deployment_after_transaction_commit, project, default_enabled: :yaml) + end + end + protected def run_status_commit_hooks! diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 2925fc7cdd7..f91700f764b 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -10,6 +10,9 @@ class Deployment < ApplicationRecord include FastDestroyAll include IgnorableColumns + StatusUpdateError = Class.new(StandardError) + StatusSyncError = Class.new(StandardError) + belongs_to :project, required: true belongs_to :environment, required: true belongs_to :cluster, class_name: 'Clusters::Cluster', optional: true @@ -312,20 +315,23 @@ class Deployment < ApplicationRecord # Changes the status of a deployment and triggers the corresponding state # machine events. def update_status(status) - case status - when 'running' - run - when 'success' - succeed - when 'failed' - drop - when 'canceled' - cancel - when 'skipped' - skip - else - raise ArgumentError, "The status #{status.inspect} is invalid" - end + update_status!(status) + rescue StandardError => e + Gitlab::ErrorTracking.track_exception( + StatusUpdateError.new(e.message), deployment_id: self.id) + + false + end + + def sync_status_with(build) + return false unless ::Deployment.statuses.include?(build.status) + + update_status!(build.status) + rescue StandardError => e + Gitlab::ErrorTracking.track_exception( + StatusSyncError.new(e.message), deployment_id: self.id, build_id: build.id) + + false end def valid_sha @@ -353,6 +359,23 @@ class Deployment < ApplicationRecord private + def update_status!(status) + case status + when 'running' + run! + when 'success' + succeed! + when 'failed' + drop! + when 'canceled' + cancel! + when 'skipped' + skip! + else + raise ArgumentError, "The status #{status.inspect} is invalid" + end + end + def legacy_finished_at self.created_at if success? && !read_attribute(:finished_at) end diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml index 2cc919fc70e..5d3e0720176 100644 --- a/app/views/profiles/passwords/edit.html.haml +++ b/app/views/profiles/passwords/edit.html.haml @@ -19,16 +19,16 @@ - unless @user.password_automatically_set? .form-group - = f.label :current_password, _('Current password'), class: 'label-bold' - = f.password_field :current_password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' } + = f.label :password, _('Current password'), class: 'label-bold' + = f.password_field :password, required: true, autocomplete: 'current-password', class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' } %p.form-text.text-muted = _('You must provide your current password in order to change it.') .form-group - = f.label :password, _('New password'), class: 'label-bold' - = f.password_field :password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' } + = f.label :new_password, _('New password'), class: 'label-bold' + = f.password_field :new_password, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' } .form-group = f.label :password_confirmation, _('Password confirmation'), class: 'label-bold' - = f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' } + = f.password_field :password_confirmation, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' } .gl-mt-3.gl-mb-3 = f.submit _('Save password'), class: "gl-button btn btn-confirm gl-mr-3", data: { qa_selector: 'save_password_button' } - unless @user.password_automatically_set? diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml index 7780ffe0cb4..9154c94abb6 100644 --- a/app/views/profiles/passwords/new.html.haml +++ b/app/views/profiles/passwords/new.html.haml @@ -14,18 +14,18 @@ - unless @user.password_automatically_set? .form-group.row .col-sm-2.col-form-label - = f.label :current_password, _('Current password') + = f.label :password, _('Current password') .col-sm-10 - = f.password_field :current_password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' } + = f.password_field :password, required: true, autocomplete: 'current-password', class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' } .form-group.row .col-sm-2.col-form-label - = f.label :password, _('New password') + = f.label :new_password, _('New password') .col-sm-10 - = f.password_field :password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' } + = f.password_field :new_password, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' } .form-group.row .col-sm-2.col-form-label = f.label :password_confirmation, _('Password confirmation') .col-sm-10 - = f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' } + = f.password_field :password_confirmation, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' } .form-actions = f.submit _('Set new password'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'set_new_password_button' } diff --git a/config/feature_flags/development/pipeline_editor_empty_state_action.yml b/config/feature_flags/development/update_deployment_after_transaction_commit.yml similarity index 52% rename from config/feature_flags/development/pipeline_editor_empty_state_action.yml rename to config/feature_flags/development/update_deployment_after_transaction_commit.yml index 870aeb14932..c07622fc9b4 100644 --- a/config/feature_flags/development/pipeline_editor_empty_state_action.yml +++ b/config/feature_flags/development/update_deployment_after_transaction_commit.yml @@ -1,8 +1,8 @@ --- -name: pipeline_editor_empty_state_action -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55414 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323229 -milestone: '13.10' +name: update_deployment_after_transaction_commit +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71450 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342021 +milestone: '14.4' type: development -group: group::pipeline authoring -default_enabled: true +group: group::release +default_enabled: false diff --git a/db/migrate/20210929025600_add_phone_to_user_details.rb b/db/migrate/20210929025600_add_phone_to_user_details.rb new file mode 100644 index 00000000000..9bcfd4ab7e3 --- /dev/null +++ b/db/migrate/20210929025600_add_phone_to_user_details.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddPhoneToUserDetails < Gitlab::Database::Migration[1.0] + enable_lock_retries! + + # rubocop:disable Migration/AddLimitToTextColumns + def up + add_column :user_details, :phone, :text, comment: 'JiHu-specific column' + end + # rubocop:enable Migration/AddLimitToTextColumns + + def down + remove_column :user_details, :phone + end +end diff --git a/db/migrate/20210929030834_add_text_limit_to_user_details_phone.rb b/db/migrate/20210929030834_add_text_limit_to_user_details_phone.rb new file mode 100644 index 00000000000..f250aad3253 --- /dev/null +++ b/db/migrate/20210929030834_add_text_limit_to_user_details_phone.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddTextLimitToUserDetailsPhone < Gitlab::Database::Migration[1.0] + disable_ddl_transaction! + + def up + add_text_limit :user_details, :phone, 32 + end + + def down + remove_text_limit :user_details, :phone + end +end diff --git a/db/migrate/20210929031049_add_unique_index_phone_on_user_details.rb b/db/migrate/20210929031049_add_unique_index_phone_on_user_details.rb new file mode 100644 index 00000000000..e0cf7aa8a44 --- /dev/null +++ b/db/migrate/20210929031049_add_unique_index_phone_on_user_details.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddUniqueIndexPhoneOnUserDetails < Gitlab::Database::Migration[1.0] + disable_ddl_transaction! + + INDEX_NAME = 'index_user_details_on_phone' + + def up + add_concurrent_index :user_details, :phone, unique: true, where: 'phone IS NOT NULL', name: INDEX_NAME, comment: 'JiHu-specific index' + end + + def down + remove_concurrent_index_by_name :user_details, INDEX_NAME + end +end diff --git a/db/migrate/20210929032555_create_verification_codes.rb b/db/migrate/20210929032555_create_verification_codes.rb new file mode 100644 index 00000000000..ad743641b9c --- /dev/null +++ b/db/migrate/20210929032555_create_verification_codes.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class CreateVerificationCodes < Gitlab::Database::Migration[1.0] + include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers + + def up + constraint_visitor_id_code = check_constraint_name('verification_codes', 'visitor_id_code', 'max_length') + constraint_code = check_constraint_name('verification_codes', 'code', 'max_length') + constraint_phone = check_constraint_name('verification_codes', 'phone', 'max_length') + + execute(<<~SQL) + CREATE TABLE verification_codes ( + created_at timestamp with time zone NOT NULL DEFAULT NOW(), + visitor_id_code text, + code text, + phone text, + PRIMARY KEY (created_at, visitor_id_code, code, phone), + CONSTRAINT #{constraint_visitor_id_code} CHECK ((char_length(visitor_id_code) <= 64)), + CONSTRAINT #{constraint_code} CHECK ((char_length(code) <= 8)), + CONSTRAINT #{constraint_phone} CHECK ((char_length(phone) <= 32)) + ) PARTITION BY RANGE (created_at); + COMMENT ON TABLE verification_codes IS 'JiHu-specific table'; + + CREATE UNIQUE INDEX index_verification_codes_on_phone_and_visitor_id_code ON verification_codes (visitor_id_code, phone, created_at); + COMMENT ON INDEX index_verification_codes_on_phone_and_visitor_id_code IS 'JiHu-specific index'; + SQL + + min_date = Date.today - 1.month + max_date = Date.today + 1.month + create_daterange_partitions('verification_codes', 'created_at', min_date, max_date) + end + + def down + drop_table :verification_codes + end +end diff --git a/db/schema_migrations/20210929025600 b/db/schema_migrations/20210929025600 new file mode 100644 index 00000000000..fb00216afac --- /dev/null +++ b/db/schema_migrations/20210929025600 @@ -0,0 +1 @@ +c757a7e17433b8ddf15ae6304286fe3da69f820966455e7fbed7282286f5eb67 \ No newline at end of file diff --git a/db/schema_migrations/20210929030834 b/db/schema_migrations/20210929030834 new file mode 100644 index 00000000000..a3dc19d0440 --- /dev/null +++ b/db/schema_migrations/20210929030834 @@ -0,0 +1 @@ +b5302b3a2384bd7d0e639f00941efb490c3121a9332f1e73be620ab0f6f3e771 \ No newline at end of file diff --git a/db/schema_migrations/20210929031049 b/db/schema_migrations/20210929031049 new file mode 100644 index 00000000000..19ba54b465a --- /dev/null +++ b/db/schema_migrations/20210929031049 @@ -0,0 +1 @@ +d3f588e4edded61f36acbf25fba39be17a2ac16f37e9114f2c5c257c47dc1308 \ No newline at end of file diff --git a/db/schema_migrations/20210929032555 b/db/schema_migrations/20210929032555 new file mode 100644 index 00000000000..779e6a63fe2 --- /dev/null +++ b/db/schema_migrations/20210929032555 @@ -0,0 +1 @@ +08593002910759482c58f9b31f251d589ab32b540d9614a2c677df11d32f7f26 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 43927bdf4e7..9ecb7857d50 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -19851,12 +19851,16 @@ CREATE TABLE user_details ( pronouns text, pronunciation text, registration_objective smallint, + phone text, CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)), + CONSTRAINT check_a73b398c60 CHECK ((char_length(phone) <= 32)), CONSTRAINT check_b132136b01 CHECK ((char_length(other_role) <= 100)), CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)), CONSTRAINT check_f932ed37db CHECK ((char_length(pronunciation) <= 255)) ); +COMMENT ON COLUMN user_details.phone IS 'JiHu-specific column'; + CREATE SEQUENCE user_details_user_id_seq START WITH 1 INCREMENT BY 1 @@ -20150,6 +20154,19 @@ CREATE SEQUENCE users_statistics_id_seq ALTER SEQUENCE users_statistics_id_seq OWNED BY users_statistics.id; +CREATE TABLE verification_codes ( + created_at timestamp with time zone DEFAULT now() NOT NULL, + visitor_id_code text NOT NULL, + code text NOT NULL, + phone text NOT NULL, + CONSTRAINT check_9b84e6aaff CHECK ((char_length(code) <= 8)), + CONSTRAINT check_ccc542256b CHECK ((char_length(visitor_id_code) <= 64)), + CONSTRAINT check_f5684c195b CHECK ((char_length(phone) <= 32)) +) +PARTITION BY RANGE (created_at); + +COMMENT ON TABLE verification_codes IS 'JiHu-specific table'; + CREATE TABLE vulnerabilities ( id bigint NOT NULL, milestone_id bigint, @@ -23810,6 +23827,9 @@ ALTER TABLE ONLY users_star_projects ALTER TABLE ONLY users_statistics ADD CONSTRAINT users_statistics_pkey PRIMARY KEY (id); +ALTER TABLE ONLY verification_codes + ADD CONSTRAINT verification_codes_pkey PRIMARY KEY (created_at, visitor_id_code, code, phone); + ALTER TABLE ONLY vulnerabilities ADD CONSTRAINT vulnerabilities_pkey PRIMARY KEY (id); @@ -26764,6 +26784,10 @@ CREATE INDEX index_user_custom_attributes_on_key_and_value ON user_custom_attrib CREATE UNIQUE INDEX index_user_custom_attributes_on_user_id_and_key ON user_custom_attributes USING btree (user_id, key); +CREATE UNIQUE INDEX index_user_details_on_phone ON user_details USING btree (phone) WHERE (phone IS NOT NULL); + +COMMENT ON INDEX index_user_details_on_phone IS 'JiHu-specific index'; + CREATE INDEX index_user_details_on_provisioned_by_group_id ON user_details USING btree (provisioned_by_group_id); CREATE UNIQUE INDEX index_user_details_on_user_id ON user_details USING btree (user_id); @@ -26846,6 +26870,10 @@ CREATE INDEX index_users_star_projects_on_project_id ON users_star_projects USIN CREATE UNIQUE INDEX index_users_star_projects_on_user_id_and_project_id ON users_star_projects USING btree (user_id, project_id); +CREATE UNIQUE INDEX index_verification_codes_on_phone_and_visitor_id_code ON ONLY verification_codes USING btree (visitor_id_code, phone, created_at); + +COMMENT ON INDEX index_verification_codes_on_phone_and_visitor_id_code IS 'JiHu-specific index'; + CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON vulnerability_historical_statistics USING btree (project_id, date); CREATE INDEX index_vulnerabilities_on_author_id ON vulnerabilities USING btree (author_id); diff --git a/doc/ci/runners/build_cloud/windows_build_cloud.md b/doc/ci/runners/build_cloud/windows_build_cloud.md index 5a1a3a4b58e..e01de723055 100644 --- a/doc/ci/runners/build_cloud/windows_build_cloud.md +++ b/doc/ci/runners/build_cloud/windows_build_cloud.md @@ -19,7 +19,7 @@ the Google Cloud Platform. This solution uses an developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html). Windows runners execute your CI/CD jobs on `n1-standard-2` instances with 2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in -the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md). +the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md). We want to keep iterating to get Windows runners in a stable state and [generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga). diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md index dfa2f3ed55a..13648a7c710 100644 --- a/doc/development/documentation/testing.md +++ b/doc/development/documentation/testing.md @@ -206,7 +206,6 @@ Vale returns three types of results: `suggestion`, `warning`, and `error`: (after the Technical Writing team completes its cleanup). Warnings don't break CI. See a list of [warning-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Warning%3A&group_id=9970&project_id=278964). - **Error**-level results are Style Guide violations, and should contain clear explanations - about how to resolve the error. Errors break CI and are displayed in CI job output. of how to resolve the error. Errors break CI and are displayed in CI job output. See a list of [error-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Error%3A&group_id=9970&project_id=278964). diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md index 985f3c133d5..0531f30f0af 100644 --- a/doc/user/admin_area/settings/external_authorization.md +++ b/doc/user/admin_area/settings/external_authorization.md @@ -1,8 +1,7 @@ --- -stage: none -group: unassigned +stage: Manage +group: Access info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: reference --- # External authorization control **(FREE SELF)** diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md index 3c80e1f5f2a..4a42133c308 100644 --- a/doc/user/analytics/ci_cd_analytics.md +++ b/doc/user/analytics/ci_cd_analytics.md @@ -24,7 +24,7 @@ View pipeline duration history: ## DevOps Research and Assessment (DORA) key metrics **(ULTIMATE)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.7. -> - Added support for [lead time for changes](https://gitlab.com/gitlab-org/gitlab/-/issues/291746) in GitLab 13.10. +> - [Added support](https://gitlab.com/gitlab-org/gitlab/-/issues/291746) for lead time for changes in GitLab 13.10. Customer experience is a key metric. Users want to measure platform stability and other post-deployment performance KPIs, and set targets for customer behavior, experience, and financial @@ -56,7 +56,7 @@ The following table shows the supported metrics, at which level they are support | `change_failure_rate` | Project/Group-level | To be supported | To be supported | | | `time_to_restore_service` | Project/Group-level | To be supported | To be supported | | -### Deployment frequency charts **(ULTIMATE)** +### Deployment frequency charts > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.8. @@ -69,7 +69,7 @@ for its deployment information to appear on the graphs. These charts are available for both groups and projects. -### Lead time charts **(ULTIMATE)** +### Lead time charts > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250329) in GitLab 13.11. diff --git a/doc/user/analytics/issue_analytics.md b/doc/user/analytics/issue_analytics.md index 44b8c87ee27..af7307eab39 100644 --- a/doc/user/analytics/issue_analytics.md +++ b/doc/user/analytics/issue_analytics.md @@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Issue Analytics **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196561) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.9. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196561) in GitLab 12.9. Issue Analytics is a bar graph which illustrates the number of issues created each month. The default time span is 13 months, which includes the current month, and the 12 months diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md index 44e4cd8b371..2ff15c00a3f 100644 --- a/doc/user/analytics/merge_request_analytics.md +++ b/doc/user/analytics/merge_request_analytics.md @@ -115,5 +115,5 @@ bookmark for those preferred settings in your browser. The **Merge Request Analytics** feature can be accessed only: -- On [Premium](https://about.gitlab.com/pricing/) and above. +- On [GitLab Premium](https://about.gitlab.com/pricing/) and above. - By users with [Reporter access](../permissions.md) and above. diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md index 391ec5c04d9..dbe71d5f743 100644 --- a/doc/user/analytics/productivity_analytics.md +++ b/doc/user/analytics/productivity_analytics.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Productivity Analytics **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12079) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12079) in GitLab 12.3. Track development velocity with Productivity Analytics. @@ -60,5 +60,5 @@ You can filter analytics based on a date range. To filter results: The **Productivity Analytics** dashboard can be accessed only: -- On the [Premium tier](https://about.gitlab.com/pricing/) and above. +- On [GitLab Premium](https://about.gitlab.com/pricing/) and above. - By users with [Reporter access](../permissions.md) and above. diff --git a/doc/user/analytics/repository_analytics.md b/doc/user/analytics/repository_analytics.md index 9016bf6393f..e8f8acf5661 100644 --- a/doc/user/analytics/repository_analytics.md +++ b/doc/user/analytics/repository_analytics.md @@ -4,7 +4,7 @@ group: Optimize info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Repository Analytics +# Repository Analytics **(FREE)** Get high-level overview of the project's Git repository. diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md index 303427d31e9..cdb2e7109bf 100644 --- a/doc/user/application_security/coverage_fuzzing/index.md +++ b/doc/user/application_security/coverage_fuzzing/index.md @@ -16,6 +16,18 @@ We recommend that you use fuzz testing in addition to the other security scanner and your own test processes. If you're using [GitLab CI/CD](../../../ci/index.md), you can run your coverage-guided fuzz tests as part your CI/CD workflow. +## Coverage-guided fuzz testing process + +The fuzz testing process: + +1. Compiles the target application. +1. Runs the instrumented application, using the `gitlab-cov-fuzz` tool. +1. Parses and analyzes the exception information output by the fuzzer. +1. Downloads the [corpus](../terminology/index.md#corpus) and crash events from previous pipelines. +1. Outputs the parsed crash events and data to the `gl-coverage-fuzzing-report.json` file. + +The results of the coverage-guided fuzz testing are available in the CI/CD pipeline. + ## Supported fuzzing engines and languages GitLab supports these languages through the fuzzing engine listed for each. We currently provide a diff --git a/doc/user/group/settings/img/import_panel_v14_1.png b/doc/user/group/settings/img/import_panel_v14_1.png deleted file mode 100644 index 28417383b6cb350c84fe7924671313702b8cd0f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42789 zcmeFZWmp_dw>ApF5;P=uu;4bhySuvt*8v8X;DiKscXtR7V344J;LhNKyMPU z)qVDlv#;~*^Xr}Kn(6MUweG5W)mq)FtGXv#RapiDl?W9M4h}<3R#F`f4gvi1t$mL0 zRB|@`h6N6ec+Xo?*G=8jlibP0(F$m9N$%$5WJzxM9%uyz_a0i62~=nLnh*@L!)-?# z{qDk+wAUx~8KmX(N~j zo|PjtGxD*gQ`gyY==GlHM8MdmF_z%tn9RMC^Q)07ocnrO#R1QA3z1(#ZPMEhO{ryB z=l8#;>E4R`WPNunn11uH+cal*>wh+yy@BP3d47`#^A)mgG7dezT;;3GaJ@8l6S6Ad z6hXP*mb@aEB~tWij&MeYVsm`TgjJ3^DD&B-3w zpXmleg-!@0&1|RVYIxP3tq~NlkCol}kSI**(FQH8Bd>b-c4}YcDoZ36oPK=SoOEB1 zDjX8`Lixg*XB@}#_+n6m`J)~pg_?Bm1b8AmIWYR3zBWNZC>TdWo-bKbLqRB%*ma06 zmFeV=I!RZ3usBIyf1hhwS7Wqc+SazR{RR)Nf7*qys&UqPw>UdRK*iHx&+i&rni#mH zCQSnRC3ic*J2g^2Vr!M@cY}+^TYJV(S>1T+k*NuFF3t8_aBo`1D);CPr_J^qDlg4` zB;~RuHGMd{xKeXepQiI!3Dvg>}KoM0y1&*aM9vB{9;l#t6cn;KM7K$q_hgC^XIH&|; zM_SghOs?U>nE-V|PJfw?frtjFfJ(^m?83JNx7O>4F?8BrKcvZ~elE19r=)tentxI@ zTTFzI(T`>yGBeV|$7h@12lANJm-ZU+JAdiT*1r=3L=q^JUyjb^ zP&j#kA9OQf$*k6uv5mIr@oxGc0~Z%0Sy`G49MZSPBv6N$E0>_f2(xf*PqcRq zIvg|aS~j_Aw@J+2R4R*eC!(EvUMz{Kdl!N-b*la1mY%C_%L)z`hf;f#3@1nVo}O?qM}DWYMQlXad06-5?Fn!#iIi)k;W=s zFkyBW=$n!64q|D<56iEXT8|>tY2f-XTOwegA(D;NZEN0L%XQfS|Ehx5!{JRa$3lIQ zUYYnD-O>^=61*9gjPfdPR3hWlm#~4b2E3QwVi9Edte)RkrLOwmn9tdC{P6Sr%<=jQ zaha1<2-rdNlZv8@6#0)ySJEo0iN1s}^zOwrcAn6c7V5BR>Vkz1Dw%I zX`}8zv0q2bH6(X?q@G7FMxGrp2RGbV*^uBIoWgz1K0_eRyPGMKHn3hD@yv9uLBM17 zL1wTzhJNQBPLZIQk)S$4*7}bA<{QxGVqz%_(f+6*F+}1Q_l-CnYC>M*OKTF21-~d1 z75N|LOfEKkLSiSH+}OdV_Au_zN7exR^Ef!5O@~CM`skr8SMH!-jYgi`&C+a$7A~a8?2Lv zuphyk>3**eZMy-e1!-}I&tH(fWszP9eTLrA%XglW5y7uUpL9e2v4_f)M{cLfy@pNJ7kKxVI_7h&@)9qPC?CCIPyv;Ma ze)iZ_n(#K&NP|Ad5qd2+8a*&~!uDoFf&WwR!u9oDYWU4k{FQ&23W=WA6+H7%%F>+) zg|507yNd$F_wTCHCv^gWbWW3UROdl=nXhWKjDS}wbyQA1H9l~xeltJ911y=YGd`%u zBE_pN>%Ymb>o3?If@y#?XC!Ck;=zR1YP&XUnCc|&OERppOqZ(BDc)Vc9y6YOc8dLJkpH--m0hNrnbJ_ZV&al5hKBs$EIa zg6_`S%E5xOX#=>Qr0$kSAXdWRnOmk32B0-5yrO|n&*2IYeWmz9eG&Ewlp}ln9fusk z^m>31PT7SsuB1r>5uMecsu@x$$ee$MG;8m`v12yjCOC+*mYST7T94(X_-nrQ`5WPw z{%7ZKx5@OR?7Yqt)M)3&I=?t17OJsnZER<{Ot>XE(TGYfP~)VXc(Jv6X(-?I)G85B zQ3S^ZI`*I;TM$6zhTegxO3RpPeZXUAJk{8kqH6l53>TmJm>CGk*=B6+-tkIDJ$v64 z4W_b*6?MY(kTw>pK=cYvpjS)_yB!k7clKWGkMXLDD;bK|Dnbf+ZdHQ;-L0ZV7Ds-d zv>&UZ&*o1s{6M6FL~RbVprOkk&0onItThwN4y1iyXD+jZM{d$)Yaxa`|7M85qK3Tpa-h@mX9JlX@Tl4g^Rx^30-uv{gsZ|+1u^{G*iC{ zDW63Ca&1HmT{^^7X#u|Db~Z zW-!Y-@-pWGAFrVQ77nT-CYEBrfC?Vr>z#*Gq%Xq!fzg7&gr!Z>x9Rk%qhN~xuYKJVR-EEpieyC6JKSGB8K1CR*XvMA)gSZIa5qQww_KeGC zgk|qo>|_LdrNpcQP|4S$9E`1&z7c4)!pGgJMljQ*j4QJsbZIG;*g4jS=fV_)FT*En zBd)&rmYDweMKb2LO*}*!c{kbj-mT-E0wcN4>|^>a2v^NK$d#u#y$)jD6VdxO?Y z9~N-tVMl)%7j?9K08)rL|H_rv>3h;3L~p4GVArW&DD<3jlRz6IoRwmM1l>ry=1rAt zE-QEyU#fpP;`70T3hw9jWEhmS^Nmi@G&6e^BTn4f$m_GWoz^K~rR?EsU%ZGLq_K>`s^w&7B2i$9&eZQJQU;j(Ov%7;ZrKY{278Yzd`rQzdV|eTiT5b-^H3 zK})$n=C@^Z9^$V~NdZJ>;-Td~_Eb1Iv!XnjyX~n>Am3SVWj#o5K*dWL=xJ%V-@-<0 zS5JtBUfdGD&Zfv%4R1rbKBdroesQvO@hPPW6jkGVGLL_?D)+T&~ zJ6<1oJ8uRMPYTB%y7P9qW=BK1&Hws-!1rolRq*;Y{zioqova0O5H)*M*oEeisUdm( z#a7TdHpYP1M?X8NdDYRF7bDxBg6;I$!oQ$tWHiLT(9lNj+Gl7XiO($kB2Lh}hX`)&Uj|QThMIykx_MO>2r|cf zOcv3X){ss8s93`z(HAnX5JxKp%nc@|H4^0BFzG(a^PmRMepEqlUS`?1bPgXG2J0j4 zQD^gEGfbf9V^Ds?lT0^Jcg83SjH>5(`TCV+?0Lu}Q~ifd>m07j?avV?V^a{@&H@yT z=x1-o3gy44`_*MGPLTbg6NJRn6jccNRF_U~rH&Yu?KxLfe;1WB#p0~7l{OHVPitkK z0cT3Z#;s$%ZF{|$A=8M`>QtfGHH;hl?%k*XDiq3yKu8Th`Yt($w|oZ2g)Q=)f&hn5 z0(-QTNIGjmx!pdCm;1}RW|0P@X~^<731HeWb7~Nm*vD=Ne3dyi>O^SDNT96Tq-c<` z<~a1(V07cN*e~++7KBWKQ6;ba2x`2(iRXL765wCZ8`MHd5|XHh*#0H#tZJFn zi=2xzBS_TT95vpx?EBqgGZ=!9K>p>_7G8hI+8nzH6-R~p*w5mlOjKV}=u$tH@Vl#0 zQ}CSj&%kR)i7Wa2z6$Wm;3V|ZI%+2={)PxX>??Ppy!bF}V5~OwT_Mu#?7&*IRFRi| zqHx8_$-`}*WX@ikC4ahH|Aju#H{bT_rtyHEK{sAx!p0mT$KQ9E({iuYUGYc8?@qp= z?Rff4pf=yf_Hh5oNJ7m2*7aaTb@0h-CH8V;mraU^$p1)1#qT`sW=4aI0d*+g4$O6Nx)hLFuI8OgpQHx%P4z_ncByu~Q+pSDkq#!PDnpb24gNz) zWxIwbm4*NGT%T^f5IM@kMr0)70n4q=h6 zOD-bb{;d343Rjd`zRqHmn1p9$5p(RRfg81G!*fR~uiuU;ka%Qw<;85PD)-10fAq39 zZ5`4@!cquxp|I(%LRMpX(=oi{!eu>!($w$+g(hJkBOK^qc=uvbE0t3*RP+ParpbmI ztg-K6y9EC=DZ$l}mU(jnLO-iu*VM+CERwM(YlBs2mC;uGz1lQCbTi>*2O7(qP9}2W zGI)QKc-?ZIlt0c^h@JZ0^gtC`u@Y2V`Ql(XO^>blQ+W2U+#}`vWSs7^YpT{4**fXB zal_jAUoYc~JOlf%iS2+REG6alU>$+?_gQi4@P;f5-Z1mE=qBZE+w@9135A#wnnp0qL}I5Qgq zehrm}xGGQs*l)(DGm4O(%NBsW9u}%Bz1T3m((bO@*VhL-DY#+D4d}Fa9Nt}J$yi;g z*p#sQsAGsUrZ{9mUSu`X65sf(tQ6{bh_Fi5PFXIEvo?K%+`?@3I5{J`21 z@OFISO#jNG)vPZbVIjKY$ifFbgm{7J!^NLnW)*O*k; zP2MsSU}R$g%(G4cc8s1rg$vFGB?;z&1O)Fi{ujMSCdePA+WUoZ6=UZv6IhY+BN(o@V$_F2hq0zh``!G4{;r+HI!O`5izHW?P zjPrRw&1<}CA~@FdZm7B(`{x9g*kO+-pGKUw!i+oXx9Rh^SgP4a`|+5c0j*9db7uMF z>38ic)HdggK&=IehZMXxK`2_}zyKV7F6T0RrDUE+8xFO4ISuWwTv?%O%&W>^JQ?B> z9VC;7iPN0?=;-1F4|a)*pSVXQ2+m2bzp45G@Rq9AggTOCQ@o|ImZ}XAkJ^qu5Ll^F z#f=eu4Sw65o~7!;>*Ql?q*zLTT}fBJ$7&)GUsw{fQr$ zQRqTa0d8=Z#-C42n<|wo5_sz6zipzjetTo2GID5Tqz2*#?xz=VgV*O;J!)hPe{ejy z^u5rsNf3^fgcG&Amq`E z&Y!yN=4rV;#|dc(XgAP!OFCg|8n!xTqDnwS1*Zu-5+`gTanO|0HKgce)!%Nu3SW)W z;E&%X%Tx)O=1amDWHjJ;))+Y?3d6+!G(zjf$m8DbtrN{G54d5`l*#k!w9-)^`dHH} zF z2W=huI1t&c#%OUU`pz~ym{dCI{TqMp*uv>`L`lS#bC(V28VVSB5tRcUs-(Qv@bZRZ z2dGQUWt16zXrAfy+XV>c9V(|SoP12}u)9cv#{!g%RK6b8>}(JXqog{H#Z+o5zp`#U zE9x@DxT$p}A@aA+zOQ@0s#*oDGUAQ$)Lb_n1{{37S*(VY@9y9mvKSuvV%c>*YQAN7 zejXVS2Bo>GwDt5Ve&=W(__vWXKHU95VFOq8cqD~!B#GO{dOgq&>C$9D9*GSKHJC`K6K3rA7l=ms zChzP3d#`aaFB_~XJ#~sw-(1e-X)&a4JliSH_KsZ00>Hj`D8hZros`(7f~K zT+QmqUeFyocuwcugWR~^)So*p)fp~*XXR~HJDO?d-ObyJw_q%^WBq5KJ}Z*?XF1L@ z)VCNXl;)~sq|!`!rO&_;hLdu-lG8cd-VihsGlOJLNT@5n$lu9LRps&cQzsDd6o&3^{5}hwk0+1$s%T#2xyo}cTB`#)pbC6SD&YGS zT9|%kD^`*RqK6r>!ro7P{?;-iS%yrYqCzN>%+%$w81;c-ECZNDcBl*quF$IF)ii-b zf4@ql7}{Hc_%6{f5=$M9^B45iWasXe+6u!OnlhA}pJ1XfZYNTVFuWjQex;0k3`)_E zAhkAK`Fn5DY!WRF(&fTv2ll$sMM`{B&47|i-A!`Y}~MYsKHCz{a8U-+{l@)#klTm6>+clXLf3-JkN1h#)-FA+=cB;C|)9I{uB+) zizK;uK~AYu1|X4nPA5f!K7+Z{B5K;8!O($5{o~j;@*)9TYvMl7Ih9J_En~}muKy)r za-y8J>Us!;0`)Zc3Q=yz954H>euZe}+j0})(FfO1YDD@x^m)|mcU$T-1yf=f7L>wB z`>UDBIYAK|$n|ekQ}c`Bw`Hfvs~!hp2yBlu6AzW`#usq+)MR}6Kh;?B=uEO%zWF7C zig2}CF^QS>c#q+u3Ld}?uedB$M}H)h*C}a@K|T6dHz21#y(^ef8S{xyBNUEXF~vFg_w*K zU%O^uB9J5_9B7nUu5EA42^*ofZ+`p4PL}k^O`+48B1!mG17#fNdQ9MSb>h9!7UDY6 zTeSEBqi+}DvJ**q{qHSb?7u1s@8L!npJ+y)7bX3qNg99=IHibIQ|_7!H=1TTz`v(k zu1sdvRJWPM^V24g*o#0=*fu2|h>eR@NkZwOgqC@(HYe+t{cD~af}G~looJz%o~6_C z>;UI;CUX8}0|H%ojZK0R7|S{vqdUJ|PF6vhD?5>yUop2~vLf+1DtG`j=u0PZ{}*u) ze)}??h~CE6^&1X&6cR<D??mWsGCv1Ew2lY)09Lg9GpUrP26>1{;c=1HkDAl}<7 z=iyigxz?mhHj2XGFd@v4f%f38jKthopSxuw$wqj7R%1-LQb7cNkMP?&3&KM#Bq%4D z=#>zk$BwdI%|x7WiNF+=u0zjE#%3wHhLCN-r6|hS@S_6o3WL;|_8q8#RslB03ss0( z-BKxm2Ur_zV}-yv+S{0>Rrg&;0dax2D}Ed*-}iI=f+V+!h!?ra0hN>x2f|vYdmJDd z^^1GADj6h3Hl8KzZFZ`yS;^;jSc2@f>RX%-9;?M}_dFKanhxd6o03KR{q}{Wyk(zO z1To_0ZH;Knn6gDg5s)UA(KGcg4=^4{&TM(1>j~*m!C@SZX%>Xosv8R6nmJ0 zw@8yGC5R@R;r0oa3_m<^cmh1?YrAW3K>2j}ZB-J%fh_0i7JxwJw9T|D!;C_SQHb%? zN>1l0TE$~^1vf~*AQ(25@_7&IN~1&2!vEJa4_11B_4iWrb4PRqtn^&WLwCnPLE!@4 zl5v$ZNH`x+m~TN?EA#IQW^KynhW z0{sCCrr1U+bBJ4}T!2=8lTX+UY4`{<3RPCV%H2jJw0eb72sx+X#_N-{CRIs$=-1)% zB$e4QE`2)Tk)B0!vRrTbo=h^q^CQX~ls_k@E{;`Uv&VzvFlx$n)*QvgHCvp zDKbpT_7NDu^pYZA6&=D32M7NNC?TOLCn53oHP5G&&Md!pA=&Su#J$EE#S|9^Kgc)Y z^7-{%;yO<=;N**!;p)4ye*J}(!AV8W91~>M)fL-Y@iDT#8nZfx{2G2^XQyb7g8Gq# z9vpVM)=YN%Q|RXkymSleuz2!U>7-)$@}J z=Dzy-@drNd>8#$sKv}_I^eLJZ@|+bg#@JmCwsw-%hU*4fBD3uMfP3#I&lplFQVt>8 zRJqs2^IBaS^Wtc|$?34tu)>NGjgGie-R-tsJw_e9^PKzO^{kG%5%-MmvL@IHapdA+ zxYS9el+u;T5y3b|{eJfn)y5R5;?=JR`0!LeATL~egmoP|RNZfVO2vsm$YzN-XM6U^ znbVon>&J-O)VVFEScYfoSxRG;ot;C-aDC^+gZAin^{@|9fT;3TRSPpffhm( zI$TPuN=_1%Hb7Z#7fTIqWleK$J99n@3K3yc!T0=603b^@Q}Xv9dk0tk_d*nZaQUD1 ze;2b*kpB^JvlF7wRZ=CFaCEUG=Vaz&W(7#S2YRqm2&0k#88t4m7%4dUrYh{DFr z&556d#naQ1*^`6W(Z!mDjgOCyg_WI!ogMHb0dVzla5H@maB!vk4e=L-q@}C53((08 z=;%QH8`IRx(cMjmg5s&3{O|n(IVmaq1Kz>)Z&rA+2g`d?Cl)qlRu&M5i-K0F8 zK>pUD|5n3Q^JyucMcvZX(cQ(|Qp&^9!Hx1?AuP=Qq3`7GV*iJZg*l6*y(Q>L)b*)V zwts6UNtbgm<@0ve!{i@v~H|f7~|0Db) zrKH3!>1gi$yL)nyLKMH-=eKZtnx*Ievunl2#%IRL#|hx&X5#{InwfC}c)2WipALCA zO)ae0p6Yo11xn7r)y>qw-10Zn6F4*Q35U~+m4}a&%@km6$;}DiM;K#Rd4}m8SOp+NuXAAr|_(+Xh4 z!Ny_6#%jiD!Oivu%EFvq+R+7M`ZSzCkg2sLi<5)(pNiiG=ND6z6QW>eX8mW0s=cY3 z)sun{g(A?w{rx{HG=U&X4L8%@)@0*m=Vs;O<78v!<>O`J{EPMjmgH! z%+C2o{r9l&KaqJdtm$t*eFFGX{=|h}!o||m&Cx~E(a~Or;x`2OZ_PjMO)mJ?pvVGU zpCr6~d;H&gUc=J)ucN<0z#jOgik$q9+wz;5|J8`AsfVS-pN5|F{;D#!F?F!Ee2VYC zIn>|Ff&a~5ne&))b6T0R0=Uh2*q+AQ+#F!WYiR}Gu;k=rXEn3nFg5=#=&p`dZl0zt zmSWaVOrO|1InWbN&oMC@wBo0Z6{WCHUKLRfQ?;~jhmmHlb?f?k(Gm=m6d|! zf1e_+IU5(RrG**5%HqijIeEBw0A}o*oB%dcOI}uPD>GgW^S?&w9|rvYN|A@3jgz01 z>;FfJY*t)PJa_?5R80Y#T$Zc=K3+>U05_kh87DiN1)CKQ`@fIN{{@QN{9Nq+PEnBM z_qqA+ek;iG|M2X;1peh@{xtf3l|5Y~o~}78|G4P<%`JWh!~f#vZxQvs*uoR^e;WB8 z+4n!@`j5H(M;7=W3IE5t{$sBHkp=!o!vFEE|7+$#{pW3~rNdJ$>-lt3`i)nQ;pyRP zI8{YWsoUGz&d$!^&6}4ton-FAAt52GtgJ8??BR5IadGh)24iL8J$pKaJ?$>=a&wjL zKkYviJUvz-#~~h|o3|>%{v>}7dl>iO=Uj!sc3`k>FM(z!9vJM9o0TOV3S(uLG^;p( zoz)iWa}n8hMW!L9(>+E@iJ@&kRJe_&R$~^modhq%1>32TfmRrU^jLV*zL+Zom z@WUfFu&(|L#^>C)Rb(in;jq2E9iz_9$I5ZhU>7-gA0)}0y$V~&*3KP1iBsWzJZt3^ zR1oy(t+8Tn*?#1e(pM7XdfYBF zb#Q(6csAtH`HIdjr;&1OFj&v+#)fHdxhl7Xx;L{wIPp5xs%MBJ&r+E35lK;rW1 z*J4|I$;xs{c!9g$_pfOYY$1@n!Muklh>}zOw;15=Y*SV4pn^?gK_jFL+}K!}Jb8F` zd9o509lPA{@niFpW!Bi&gQZ-pXBW$@Q6q~PQK4HcgQ^`@jCQ?kAzHaMGBTA1wd1?B zj^cf%E3lh^vE^mhbcFM_(`;8=y|k{v-2Ac1fxT_WQ2QjmVYIG^@kysY6w-X(KQvmM zF)=gzxZh6@GVbSXIkNWi4G5C=$^P^3bmz>1j$@!t>Zr}c{p`rHMHkf4FUd3Di(`QI zTCah!i6D` z$UYssaFW$?g@Z$T{rd|Kmyt#AREXmC^dKb4HVQiCOU~C4VRLYB8~J$9+33<2z{6L%{Bm4=o3qtSofn?xwRd{p;0|>zJYN`CYba>DO%nxV7>E zVoZ3rI6OEw;Gc~w8eHJhTNF>5A|yCbeYoEn$TK){09@WDh;}<`=%Zm>-Y;9noAc?= zYELNSbtzn6f9mBqnkVgjBjgh6*W?;8+{rcMacbRwBz4xVC%X0Mm%`4MOIX&oj>ks) zD#m8#Z*uc$P&qc}2 zuHHp}rB7&$6+C|1Xs84~Qb_1yF?3wS^M$EmXAh^yopF`T!&b|%ct8$Y+{}sH1}A8M zW$NB6V1*ms`b8j$yw6?kQ8O4NfPe%x{zAmR^6pfcar4px%y61}gdE+h0P*-C#mKW{ zUn+k$K6Cp~%0!SkkWmo5_6a)VjCpWeYnn!p>>w;UBVTv2 zH?D=Wcelz)B~ifCrESO=yyJ!v(XD?b>ke`>aFI~v{zSAgLK2#5y>$K6Nl^jPLAuk# z`zaPk8_5QcYt4!UT662)o>zl&Z_-jC%oNeSeJ`>kXNUbQ2U>C0w@V0oFYn1Eu;M{Iy?)6X{TMp8i z8U#vP=z~;qv3l9!=;bR{+@Nr0>*<*B<5~~*iG4HV0L@|PoWu`ywx%9GYuCDO%<+S2 zAq)&B*a+tKa@pTBD(L-t(EVHN{SLvu;`3?qxA=V8Jjr|`lZ2kZ1&T0V7F9(Zv%)=o z(G2-h@wfPW3f#ZN@Bf<^|1a%4sr+?55Y?BxvoDmJZ>s6``>~js*H!xgycS#bV*nM) zf(jfAUc-_R4-QQTq(lUEX>2onekuXF;>`;CKpK;aFay$r@wYO;N)khPW_}oQi+5_l z{^-#^4f_Oah~q)5t>wAT9QugBlb$-~n9OXWdu7ZuQ2jGIS6JT+^%3J$v^68nN24$B zkXJv)3^1vDQe09yx#be3i#3b2ZuOXet#S#lk2|0!9jxo0K4-_6_>R!;!YM2-G?9fj>Mxpq+1sjB`6E9LQfbi z{9Q7_Q%=MQ56#;f))8#jSZ-GBkM(Dy%;shaoyzdi8*+>_0qw<|_EBw9w}N}GoHA&5aSf?qT1zKe#7 z7?IoKm)HiJ8O3S}M+V!H_A{0No-|LTHDtV^URALb?$ye$fz}jw+jWN%#h{Z)3cLU# zCHC-*Dn=x^;QgysVETalc0$IC3V3zD%V2dM6Zizbj&3SCQ+{#Bj!ews)c^ zU%9<0N6()Lt8~|>@sNwK@6|O!yYVx}QiF(EEy&v8NN{!J$ED1cq5x7+?Dct+)PR8D z8H#K!sp1*+q4^ToN~v2~>oh)>_z-?(P*GWHeu$S=s)2L12{qstFPe;g#cDdfDTBal zzbYDRm1tY$@{(Pkg16 z4KwniAiM1OE6*!NtxIyXIJiyPGaX^p2N_q$5QGSd$uvYJ6VuDmu z>BlR*d^^Lr-6-W*ev7XPnweP}UAAeahGu(}egMk>r${>kBhXg*z9BwlA)l*wq^7qTQp!igfnIdA zQx)zo3#(nerDies_Z4+xKwiV26*Jwmnc-znoPDAh9(o|nh5UX@6}auv`xodtRO6E5 z@p!qgil*R~K;KGp{Ag_YjM1b#N7Zy^t(nDFBHQhup41D6dD*9QLPk#E`(-=kl|$O~ ztaj;^KM<&BP^*Px3~}34%|8KpH$8_4he9Ioo#7ehs)T?uXi$B9(=v8LTN&u-eXm{X z1g&qLA@B(7oeMr4N}JV&ny7Qg9({j+T-M7j&TOtj>aKm+az-%JuGlt<>dK?R1zN-S zX$)2NDStW;3yfxDAmbF0gc=Q{HLB{9&Xz)>!2);HJ3k+-<7HDkc|g$j*nQyfd~hF; ze9_EcdEK%sqp=fK1bF|F0>nWIBy_#MuqsPq@fIxtKy1~3`$Ti3%4@()zxc+VA1ROc zG}iM@up#UZ82})SFtL_f!7}tRx-A)0q{X4lkJor*`82@N`olk*A4266maj4k6R%d4 zi%5V%CGCD~CC7FLr7W>?Oi|#tORxBp(4otj_gfS%_#+~R8{!$Nd;%8PKoUypY1*G4 z&zguK+udGZVhHD@>_P zND*AC)H~Rhk@Gpp`Hq-xs2-LDuhHp+Wq=nB{)Lr0@hB+5KKK#*v-`N?kzYT3tr3c` zcn4-SdzDe^$_>c?6>pC*O1N()P52C_HR=Sp7a3j$Xbq7$YMIhvSgB~y9ZwxxVnsUT zUV0_Yj$h4j`oAEmjC?UcY)PsU1Lh>)us*_6vyL6r^X&tx>bHQwt(W$(>#1e|rvl{q z00jjp9%Dha?MHT|%j0xI~e9%!NN1d%C!}s|yX$ zHis^u(Hx<(DJ0eAz)oauKnZ7?frsEr#%;#c_pGx5{5%m@jZ8#zonafU-^UguiU&R) zMSzu>DmxW7I>Xq<_sZ)9uq{iq4j%`P&Q?V&t4e9OW+4onVF>|wR992_`i}_A9WC9I z{opZ;YnFmKhA_XdNvmqB4IWjW$e8J5W6AB9#vkw3jr5MBv4MKu@G6AQl+T2R+X9y& zlEE2KNBNqkgu;R~%s0y|CUrMbny3E0QMsfd<`CiMJ}|jKgwu`H?Rz|jN||JEt>mLh z-%`NGkLyOr)S!JW3xg{&o~H<;i zK>kMrMGu8~Xx4A546Pz-SFw7p*D;C!e%|XfY~uPS;18WX=>L5Z`_Ei;tvqQK8}7sh z{=cNT|CIP|ve|#g76t#66Cbl2#gvti@D{)c3PBvM)8uP$pU9T8T$QeI{*~|+;#*u+yOxZTK+8e zU40}DiR-KaBasF8ZVmL4;m@be#@$RhQdE)1Gar4g?oy8e-)97{1HH7>93hkHkzlfp zyA=eNAllT%0Z-ZJ5|2w1$YUQw+OO?#ZRdhaW}&m~=Z@kMOOett!E3Kn#AGTF=a&8= zLW+811G&ZWuIRMzm|++6^`=kY@Iwj8Zb$kz1Cb;G#f04~bP)e+P?)eJB*d6iig_hh zH#C8{So2=)wU(ho0@#%}VB{*si0O0cp{pXXKka2@R~wI>c+6=!kNJom(oM+Ta=}6% zb^cB(0CTt()5=GN_SjKjVNX)V@^#0fatuS2dihe(p3XOeLI#J2K*@!Zu2cEdW6z~8 zXU!^P`sXE`SW6?5TWtf_lw+u7@9JQKk=E!oip3VM-MXJ}uBjJ!XrqUpW5{tV zzWBjg{b$BSVhn#vT79*Bu3M5qWsMAH`Y z#?y-RZ7|iAox7}uv*p4Vw5F8~?uVpJ{Nx=iqe06fSD!C&9*0LPz*=<%ll4^x!#BmU z29rlWGK;>``bJiLT>X6gu+TN+^9Fd>Nk;*y9}yBzromu_U~j9^#cP9tjb;^LE6(fm z`q2K#3iSx^os^19cEQzZ&Ai?|WrKpP%FPB#Y^U`?{3e;7%R9_skk?c?88zmWLWhg` zmgYvFJ1W|0V(RztAs=mPQ;F!3l&Nwf1euZt%K#rOeSh4E2u1}OlHg)XD!_}@1vZ8u z=lbQZbS-VK4yiC`faC4*t6dK?qZ;+gfs8m{TSah!hu23w-$DOZM=y=twlWH@Q%W$V zdv~wHlcqKUiR9XXiXNDaF+8Zu_XBL{<2f6bxYJ7evx$gZ(3=^gE9Cvc?+;!kQi6J^ z2o33CC=}=Jrevl+mo+_rzZcA3*xgC}+FrGZ^ zg;eeZPv)!AZ#ykRv48`C9O4J~7|>s=x5|JZn}PeQkpN-A$DHf3wx$&BWSrs@sgjjr z6|w~nNgDCHtRhdhfXb&TaAxc>w`FjEU> zsuIL3sOn8?Gkd1DtCxjsh9Cr*Fy;*Ei~hTO+8n|p!WK?tN*YBVA;lmWl@ z8K%`6bbUR2%h&OJxG}&P<-XpL>;2D#ma_8ZP#(tH>ub&X%uU)y1N>Zf9Qtzp6s_V1 zyW;UA^?<5hYHC0p#jEwor`CNA7tF)Y6b{bLL_4O=cmHN2TjTfM@8X{w|GJVjKa~Ia zB>*>=!LL!h&Hw3^^r(E3w$Ntt__vv^S67&cPZG^G!e;7Io?bY|h3ID^F;^9P4sn?< z0zfm-HCM_(#g>$S++Y{CrFWui{VVTqQn~Xo52X_>sSSVv+gq4Bv=jUg((UsCyRa_b zNyy2fZIKp!Q%(XFin+n_QapagAMO zwNs5GYFNSSC0hCmtPvrff3cZtUkQXlH5rO7ykY}ZI_qL}KR>bE5AE+HQ#5Tvwim}=coYZD$ZNE&max#qJ49;!8qJRgx10%BAJZ>FYhS5sk@i@{Y{p+ouYU)N>VZE>Zj zcO)~+rT*t>%?QDC7$!uUTT72(!@r=TF-(8}%b z#{LbEgaoTkT9Wp7H!?^?S`zjvw(t!3%&cD-h&{=ZWFQQtd#C9Bj#Y}W$u~*;3_#XD z{q%PvF~fE3$vy(|ej891#debo9{C@#jH{6NVkJQ_KV^X*1Ww(oYRi&ew+rvz%O6?z zW{8!KpVmC(5Tn!_!uQ|$`$1otx2MwWm-dgRZVJ19HLKTks^oSB7k_rV8G!J2>>E2D z`kWE)iTVd9=cqNrb36N#dGuA?{dTu);VQ@w?UY|5jYj1e7ITt3;0nmYl;m?e_$wkA zQ}3tvlgmBbTX#OJ)KO9$g{YNYMmh^!1g@UZC#8_F9{y@RVH&ssCa=)X!C~}tdJ71z z3fzXg0+RG^o%@I-orq4?#m$D4tvUvL@+_7rwT->!Gw&1;+UrMB@zYL)7svqu(F*Ld z0N2YN))HdM^nQ%7xz3TaKCukkRy@^jPm)&7Zaz9OJN3yFYa}K({CzH27VW=g&VN>W z#PxqK_xv|`_TN^9zPSPbaBEly|5zFNFSEvfR*(Lgo&JrNlmmX6gq4dJAp+HeR8$$q z8<#2plt0cq909nr9m~{Kc@7Uu+Zluxms+WOwjjFJj;CiLT3+1}?yQ{kF9JsANeeNK z%WHo$PoX)?_GTS63zZ=sw%?QN{W5#gFn&qrveY%je1w**^Lbzx_ybsqTvJJstEgX! zZ_Ac4_Y)pJ)-@Z{^g7}zM?ndS?3*vH4wF*L87Y$aP}8s0UZZ2y-Mdw~BIQl9qUsmcv?ZF}~m6Ueww@39ffXTChjCjea|aeaN%R6 zOWDsW+c$l`mRsIeXs3um&D2sL!k?97@0jElMSg61A1|?9SPj=v7Oo%8 z7+Kv?=f``x%0h$ezejyIYiJef`vM|!eW8-M)YD8gt$4hUru)6xH-VdL^reuDMr)VK z0(L9SG>@D*{x}f^q1K^Na+7q!^aG3p5B zGG*Pp{9kEOYq&Eg@NIPa`qBp8seDCP`YNL3T%DL~HDKSr1vRdrkpoLRXd3ob8?&BP zO_QEyX*>KM_TD-!sl@edYph|x&rFGcNl1?; zdNw|YrWP*&xUzDGAI?1VGB2f|`%YqMuIXpYw`&_E=A|UJ*7c2sj=Qr>dl!KDGT?hjv1Y`)uv@U{4VG!1UV7riv$jBi88PRNFP(MgSnG$2;l%ZUD0G&&qduS2?D$&-cAosR&-$k~tBfuknvOlT_7NS) zn)2#Mdw2T|{L%We6VnVa=f3YOnv}b<`t_n0%}`~BvGyuvt21M(wMl(uHf$*!Mc|sM z#xsf^Us1FzA5t|Tlm7Uj0`=ajn&R#&?P_PPZkmo#7+P40*e0Mjir?QR;1xT6{^`!G z9AzRMn6jgk3wBXUM4Qx&e<^$FLW8_qU}9u(p_YH}iURIe;QNse=wYYz5%)w~VSRUz z1_>Pdo>Piq@jHAi$lv3ms3I0Ct1MAg@GMswsV}}D>A&+y$Zr147ehbnk;6s|MJ_KR z{JPBTLA|$!K@-bsJQ=IQOqjOjdMO?ENUBR6(vclxeRpfMatZy_9m^1F{Y>GQ%QAp@e(OdPR-)XaL#V2@KFw_>2gMq_=aR^z6x!qtrW7$g{;JW z4oBb{sTReKIdjc6Gj1ye6ci{mrRu$(1k&Z_cj=pq&I)N@US`u6;NQhk&jMg8vX!T< zzUm=iWlsFt!%g2<+3b59GlB=!j?tXG}?Vxf7auu@@f;go6kP)SXwW$CI> zL6>TQy#B_*s}4iHr4{#pi`YjSYEm3jy5=swv)C{+=vkDocI0q=`BOFDN$GW)fPKQ% z))6Bn)MQ#VU%7ZR0(oBLSgxuD|BOU$n#qmrPcg2VKQd%OVL727KD<)Hr!{0<_nZLj zZEG8g+zK((vAL&OP`eQK(TPsbolca%i_{uY@C)*$_2F}J?ey41-*95vR}U@LM-`)l zRd7ycc{MGyFDE>=^^jQSeqkzf`BsL2hT=>X`@8(#rVxHX1QP|6lT?U`%}^V5KUM75 z>cNoC)yLDB)clBBMbAt>C1$>oM`bzZ3l^7AYtC>pai;o}5~}$el0g*^8;d-BLzeUr z|E2|4*Vcm|b#u8~sa)C};WHuhB!((n^Jkrr z={W$;ZUlTi`mhyLu77hB)t+Xc4D(PeK82Nbp{44sA6^bdsQ1Sp;Fg0~6?;mtgIDQ)z*flnWsB=J&&r+cf z@XThM>tG3x&CRsYd%3MB=!wvWEoE{>QzRR#RB)jNRdGnN4+rH&t}STQ0#z<}!7XJq z8mGXb_X{s%V$hCS(|u|EDNUbK48~iXs)26!*9bd%^%CV0LjhsyXo)>-L|2kdJlbkU zzHG%Ko8BTQh_^*f-bpcXZrODS5S|+~5(D|56`s?^jJWC-!S8NFnhu(2#1`z3VN!fM zsPn|{s{Dz>@0+5d4`I-?-6E#|F*;l=KGAv~Gh&~V5a;*@CKz_C)Hmio42gJU$P z;C(%1mN`bbB%36gzUqw>4-g@2*-^#La~iKXt)9D9f)x4QUH-c!NVO-^s|Vj_ly6ceQFksWof$jyS7Ri021>fcM$>DHY0diQm?b;>56~6v0C8DBz?hroHrgnn^mguM0i65=9&AnVlDuY*fwf*k zbWQZLbrl-L64x^i2V!H$G|#x&Mo;Li2IS13kXzw`U5kQem!cWYKBYO~IFCaZmYAb0C)bm9~|MX%s@{=Y; zOz!Z{{HpOk$`GSoNFiz|cvyD7eE$<9klkLr)Kf7-#*7U5?%U*jeX#=%bxNZ84^7pX zOjQ8ID`>Qu6~ap6(&WUs0B#51j3WKsq&{SK^rbXWcLc6J} z1-AQ5xK)6iheHTzwB z|Bp27UxKRtRPa3H`R^ub31|>~Q@(f=g^b_HS=}JB-(3z1%bSxxs zLp6acT__5(=M-Tldu0m&1i}Hu_p0f1`%~y8V-cuBx-zWUUrcdz7KCuUU7;l!L%ct{ zv*J%4&xsn?0y@#HmVt0^+?u@b0Ma0Y<5^Qj#wyOxL5q5=T$P)?cO(WuFd)LAS#-Ph z1xajrUX-}FNPAuXSw<;xxRu-CqA3lcH`xfg8e~Lc;njlfZ|kf2>u4L^o4nnmYAQHl zF`z6v0^PX^M1e}2`g3(1_fi)6ZimuOO`vP7X>dn&V}T03BnM^v-uUw#-w2jjRL@UL zZ_QQ&FbDya7ZfIdz*Q~rcu${?EFSnEwHb6< zK;eh6m3mL=uH6^E%uSZN$($2eLBmWuoKt+c{D*^79Sm)c!l@nYVv(KMX;L>ox_6>k zjGDqu5v)RP<(SX$DJyrK+Lg^_%B;)2e~3^8!yLPq!e?=zc45>ZT69fi0#{B@UeOF) zysms#mQ#6cSgt{~t#gJCe)&0FN_o;)Qfjdr&9S{$!}uVHsbs|^sZJzR*BJLgH8xA+ zUAbp`#=Fmw+w${)`Fob@N<+Q$jf&aNoc zuqRL_?65+oA~aJJnRx9BsdCR9KpnT`OnS7=uhtj4m8$d+mpZr0Y>R-x_60UnBX2W& zOR_BUR`hw=?DevYy&-#%E}+dMCFKT3jsNV>y?EnOc^3#G+PpLo=~0}A!UCCwQg!$m zgm{`vaBW{H)=Vw zo0#Co6`bGmbYsOtSu|Z{&+NJJ;mmJ3 zl@WfuYWCETH1=+v=PJ{ga^uaY<)Q|t;l8b1;8^6fJ65CWH~6eXN>^NcC=L}K4GP?ma1H8a>WtGl=o zLkm-?&!Vpx_bTIeW>C<-Q`v7~AaH22He!xzh*4V$Z1U?eH^uRoIT2 zyW_>Jdw#n}OmEtMc=F;$(v^&;iiR#a#{D^6PmvZ^$ElS?z53OPEBG-cH2#xm?x-s}Ni&ZM-FpHa_-A%hi z?SAMT<&5Fv>|UQox6t-M0L*xsUdR09^|aR$+7qPUbgi<5n$$~e|!X&ZNTlynU< zJY=)koC&C&^XviGVwp*l-Fe}iV?N@C#6&68r%-c)Rwp{8%S z*v4Ma=__qqAg?pAXH;%)pGd#EHLd;y7z;Xexiwq&n6g!?n*E;qn40u3pMYgQ9YP^ zrN+*dTh>jgt@O?2&%igHG4V{eJQ8d7aqj+d#oTw(wwQh^`Wg(lI+6Cs<+c#Yj?Lg7oot|q`UbJc|&Em3lG|;=w z#~g=I-rg86RRCupNO|tvZs0DrQinY+Cu(5?`}7UV5uH4J>xX~xK&zBNGX-sc2hHJw zj=w?J7#u36ZqOG^>IOV1rZ53#C?otk67zN2LAB^ik`oUM1}%p_Qa(l=5FY`q{tdtc zy?_$^{PggnUMmAPpBr@B=)P9*-dF3V-KG%9;JZlJEXqSdtN6PfQs7N9zYP*1ZjEkI!4j!nVYy zs~?R>oV>anIUusdMdjB-%{r?aeao5vouWp=Alf2Aljt1QPvBBEcc@!xIbr`n2oD;` z4)1&g=PCGw+cGNJ{>Y*7L^FDqu!UH>#THAU<6b!2(WU^H6DFStxe%v|$n~Mf{v;yP z-w&N=b!2|{kH3`O^iYh5Nv`+xhese{QLCA`bXFJ)DDP>`i1xQlx9U#-Fyh=M+oimqt@Q~604N(V$#l9I8d4I^x1<_=%~g3 ziSGh=p*|^*!|$^MJod*b3a*-P)o}v0XTIEsfU(~CDKutml$cKZM!twE_3uM-y4?>h zYK=72dk3Q(49nx3uf9!!lOkKycU>M+kwUC;UUF=sM*6IiqQ3F|_21|cc>LmxiHQJENJ#5D6O_74ktizI#n(`eH z;T&RsXX4kY=M>O4*ZRDykm*vZU1@w>X#;-PkClt*q<})@%$bC5W7V=@(#Y)W zMn|RHagORv81Yi{;0EMnM!nLat^r4bpq6;>|==|gf>hYZI@*F zgTj#d=}T`J<-6GeP>XNfE2YE$y^4VR;yd@*jCKP2;=#Cz*C66~_o5dT;Mg7&azdSe z2uMffKgeC$>a9y>QOP>itzoK~H(CMo+D=5$ShI1-YJ;C2PCT}LSaR4;pz92o;09rH z-{5!bwTtl6)l8Nm7+Lw}i=1N7(eJ7PFRSM?_ny3+afc)RLQO-O?P+-T>L|iZ{>E09 zdu;FRKekY&S%RdB5p4DzGWk}-VDnBHZ?n~u zS-;FU^#W0UV4B(sD6T_05~4C6M(Bx`Ya{98VW&R;5!YiKVZQ~J99?<`DF<@ru;<_Q zM9#PkOy@sc?wIAE=t9v|N?AbNkW%q%TXVw<`NY+&mq0yc57ve}Z`^O!zwt>oYps^Q zyinRVL0HsrcAPlm;t{Xg^iR^2rwb4rbq&X?28VVQ`ingfCq-@-Z)0(EJQ?qdRA8m? z?!tUs(b%B<9}%Qw9%~Bfl9{qFpM5p9zS(4y*tj6e$50b7ZN^m3+L=#6>_8N$t9IxqGUx_q`rP#bI4-fp6i|v!4S{3v2oe3#XY+{S>_i2n~ zLY?+2&_PkQ2Yb4w&3=cQouSXT_2@lRQA$NtKW-J+C(7LIk~z|AlRj=SKzm+Qkyw87 ziGDq?8J$*^PMPCFm;I66DJ35*%^A+j zl09iz3349YIYBtzcMIAb5{WVV#Id$mG@Pf`D&leJgvp?%0q?<>8o+Bh944*P;Y{oN z_3j!all4taUY-(}6-mw5xgo22(*(u^lqG0dl6IsAw3L)tQ8kv}-S>uLygBu~>9Yzzp*$zYsfgh&Bn$_#I*}bzUpfqcDkmqZcSTp0nuC9XF0y)TBx2n^I zyFce#N`%ck=F}uF=2TA)X;bCpxwUOfwzsIopLsFb>|rCc;G4uXIU_k;Q1ISHeeD}8 zcVnNM`#7$=s^E0%E8Lr5Pg9zm;30};r~%=;zB(wq^y;c1wyyv6YF0W14IeTzVS?8n z^!qYJ7>*x9)90}0Z@U_N?)k6#NcEr(CO(VExOr?vx*b_%nL*8Lpy_|(l^qEN*73qe z9eHRyWxwB7fIwv+n_7kC_S1B~-KinUK5}~B=t|{=U*67UmIy2#t$36YL;**n5B)P* zDw-NUy&0}zbXCEq9^$-ZvYB*wZpO!w4sip?#skZ-US4(iP1n80(e<+LE6p$&(1{#a z_+G$YT(u=THWWppr(rE3#U|q*l9ue^ay5W}g?0F+W&&>)m=py_ah%la!_Cy(zh|R+ zlJ{y~1S{UtW=Ns$0XhlrE0x#CJ;bDx_tJMxKKkN2D)#?|lSB3-$!w&LfHHtvzkQpEnRUFDogqS)P0 zu1a*5-|hqUb2)zOe39zu$oB3`Y3WfB6Ut@b2gX8UlSa_*q$s{yUT;^sU>N+GXbW<1 zhCcPRqj?r$?m3Hzs{TyHw{oNc=cZb!__(x-P*01|+p`ZQ@Fe5Gd;qHM_gJq1KG%N# zjux3QxO9VPqhW^3+`!by3IoaroA_?}k@+MQN$M{CGdqgUgJkKfm$=sS>FGSY^bFgd znj2OB&6F1Org(1*?q z+ht$b5(T91#6Omyk3GaIuQp>iR9vjvQzSCy>_ijg8uFi9$P?kWk#>G@W`Umu?Kw8T z)G3)M?doSIDxdZ8W{7-h$WbPp529h*z$%fg(#!tAGfy*$qC@ML!;~(^Oc2rl=4Pl~ z#^V9fHhD&IitM0d=2%$! z%@p(Wftue(+88nptdSqyA7I7fOUPB^U0zP*yI_ISL45O1Z4<0^=dZfyPX#p)kJfMS zN}6#TTl@SQeOB;cQt93@azJA7r%8ykDMRLyA8B5XSko_ktma}Ob8FqEE9T?AjxvLf zK^dp(<_<=GTt^USA^OG=CM7q&I7Fhi*G34NSJzsjbQ26&qdpP&-C7=tvF7A#tQ{qr znP9$aajkySDG=+$+b|uF?G55PXE)=8_s=a^>^1cv=V94R?cz%n*A^BUzr-_B$xIk4C_aIf9GvV`x``Uz`?Mg_pGbQYodyW1#qyy18aJC=Vyx&RyH}O8(6&cJ*BE)cNuW*nM}Y!I4g=;iPAiT1 zERo?HbIEr`;tzZeedb1@HdJz!R*sI`(>HN0K5Osrp$}R#C2WELUA;Dn{N+qXPpC$=vhPhS=K7E{_WR|Cd2PZ8Sj081u4(8K(wWuaqHkF!U@tY!`Me@k@c|0wZa8+mh; z@5vu?5S+gYZ(LcMPRl9#3fcjyIv>Np}p}aIk2LUw_YVTp}mJ$zvS`e z2>-XKhku7l{6`Dpf2r;McWz`!&_juLQ9G7gO^f$4_RfEk)%Xh@`3vv>&3a#kvFK-ey==dSm;&FBK5^5Y9=irC}NuiWNzKM6e0%eiSRV3aSjfI1a_!*0N-}0tAkxFK^w4a_@V@EN)9Qd80&4<-WI$Xs03#L5?B5x#O?K_+GQg=8u-SKRPkOaW#oD1XM5HC&Q^`tC!2nZ$oE=bs-dj+gwXVov_itK&|0Eu} zArMK5>%j%;fAGS;URFth3!eXN-v8h658lRqHw*v99{+aw{~h1|n1|Vn;G_;RU01n_ z=Y8j20f&Db=l|R<;6LII|FjbS)l=aAGpsK$Xm1BTJk9ZENbWg_d%-e~{^>ma^Izah z2S5Jj1zZ5Yv;Pl{{9j)1mrY){iOTBMspsCeP%0E`D#4NXv((7P=*FR#Y2ieKwCE@v zKyl4$iRV^=lv-X+t7QU9-@5i|9+Co;*N{JC4#^K`buMFX|N96tZ&#mz1URveNXIWl z8ZcvlR}6y6H(u9odTTs4v8>SIDF;%v?HJ}pFfR@J;$lxHCPW!tN%Auvc{ z&S4!;S|jX_$FssyyXA7)O8My!?g)-h?cun7o_osM>R|sDM%dX8Y=v>?_)l6-rG7qcU{Sw}R2xQ2D z`A+W#%+l)`L6$Hznm|~eqBF_RSoHMfCk%@KUs0Az`P4_c5TN&x^_xdrGOoc-ID-s| zT=tVWlOy?!a~onwHz7|R+0%ILZZo1kk|>9IW@nqnBK!TX&gJ7Bt(S2epcNQJ3p zgg(HaI??m$x9EmOwGbQPhV9Sj-(~u!U1Tr;zD;OeAo{?h9>VM!qm zrjQa2R=91f3J2WTINy+rdt4_XXAj_v%RM*;c2cM*l2b;xgDf8(b3gn26%?flT`GDX zKLtiaIO`hiZv`(wAlo{zUs;ALpqN zypO8U=b&F#z#31o2B3z4HVXEFZck>Ewu;$?63*Q(zIq&#I8U82@f00tK?l;0IB0{H z%pt#ZP8|em@3BdVM=<8WnDrrt7uD9dcNt&#QMZxAa>Jr`fcgbVCEF9H2(;kudHj7n zKR|piE#=9^fQj1f1epcoo4S*?g%=BFE=wZ4QiL(B~y8i=|UL zJQTqAhYoh{yGZ2c(kYCc-@VvYJw0xN9zbU>n%K%=EfAV+b0GS?>IhgZia9oJi6O|6 zyuU;zISSl4EB!sh7R{S9QgX8;ldB8j1sWr*(Bg`9ntn#?A9R9v9P2b2g2$6bj-y<2 zs+qZ)(U0a3rZ9Jj4_;f7Dic2()HD5B5m}5@hMgxyZx$%EyU&3?{yZBNs3g@IT^3D; zjSf;jh`3|3Rn(a%nW?Ip8xWoXg{L`r6?~|j$U+9iss!bppoET^;@}~|>}yblw@>^` zB^wo=92>wu+nnRdx!+}KFt|>2?x`_Xb?oaM9{W(i|N2@DQvYKD!P zJ}o%c3RMN*$@*6x!8$rRkrh))#=Muh$?TGPx1I@fFu3>q400_i=&YR6;Hx#JbSs-X z_()xPxa0M4C=xy_J(2f-zH!S@ zdi^I*Y@$s$sEsXE>EUa4OLUM%G;fBa|FN;3yjzw`C?Mj16Azjr)U$ZA5J{H zBzOrjIR70*?biEokL}XIIBm={I?Y1z;+GYpmZf#QHDBFd6=}q}(sJAq+H6 zH#meId%oo|Elq^E9y{c5x`w>7af}M@-A|JEl69&}z9eo8eb?)$UUt6kKyumB=bE?5 zb>Wq9Y~T>Lbwkp@BK4#-O3KNvo~eQk_RG$GURfX)qpMoVQ#?@3<%zedzqS$Mts9SzJva>t;^9 z)MboO2AK}u?oG_E?*kzz4D{JU&VmXvei#B7W8nf8=^Twve~#ta68LL7MVtm-bulIX zw&T~>L<-%&vEqPh7ms46&%}>>f!S_$rhFYiarEq4?~lQO(8Wd}_C!gu-bllh*`w2Z z#v)77ftavuyKt17VRV{am8a1Wid&4pSoUs>>zS*$G}L96m8^exwn%2>2a=R;yQfd8 zVt?4R)OfK`jmC^!lxSeG@6z*0-v1NS{@)PPIw$O~Fw#R$wLDKXh%lbnq<@JT3D5T1 zEt2RX4;HF@Zn&cLcKvvRJ$y^uRrRpugogh6uGt!+OJJGTJpAT0{{s2aG*qYIDfhGk zDMoqYX4RdcxdThSwGuBaqUuf(=tAe7zYiA5!n2WM0~+TX-tZs;Hc7sgMY3~-HyM@5 zLrQdkD4AWy)2l*KDHH9?H91-1)|~ziQ}rIa0XUt+SPD&U5t!Z5Xq#$J8-do2ym+jv ztDv`-S7&bZ_5tlT%2Nz+-t&ZNn#<)4KHl+aGf91rs;?rrxxwAI7?n8awG{rTNFvqX z9zju<0;F3WgthgDsoQNdnvFWqNqA9*`HJ^ep03_ET%Kp6)&5I*T3pgObQq!By+B{m zrZX+200GUmK57DfWS}H9sZf=c*vDF%m9IqAB-KY@U%S~I68^-2c-uHRW&OBuzbEC5 znLK0=&*J;xKxLBxadS7-mS)VI;TIN$ zmQh1PMHRWB6Zz%UrhCQcr3ht--JnL|XgVkscWkSgr-0P=Emehq?nBNS1?Su;lYA(k zC_!~%>?A6w1&=0w0?%@AzWGKSG#tvc zCbGg;B7B(_krw7E#lx0cD*(?U60(>P;t+}&h&`$r{s4!0&F2^0+Wl<_mPN#{iS(*`5;e5JX1cp)8*E`AZ8uxos3p<~13=l85;DiUs-g<)IWqD) zq1m7S)M~pHS8c4ve2{jC1>0>r0;n6FOQUDIRYn#4yZ%7rMe~&6NL?$9HFaNRAJh65 zh*9uaBhEDM#}b933>J>ohM6kSjV6_;XB9!KtxhXm?tKrc6d(qgSz)>7x;0)7gL~^? zTGGTqpvNE$;+wiPl&XP1#zko!ynQf`hW_1S#e8IT zdn8-)I%kc4uNTNSH!B88BXlk|6)$U-2I37}nw+#b(b0k|^bh&ST z>=}nOa6aLNUr8OQWijySM~0zuue$UottifZ59`gj80^-0Q@ijCvIQpP#$RqE`b<3b zi#I??Nefqn1BI+^22RI?Qno48JiwE3&I;mqFYYipk?hCrDYwpcVO&|RpuL2FnAf?- zuqrs3ZK3Psp%Tuo0utDx#L1-A)4;ma<$qx+HP){;Z*GYoe}Co_^9Y5+cL`R(fftc; zKagEzD)L^lk0pXflJ%H4z5CPsL#RTgOIez1;0cmP_;<^;XUkpWh_Nwn3mCCD+}b!b ztdfE1ZEkPkBrBh9^{U)eeU2OVA)r6tejg|RZoidk+J7r%5dmpvm-zP#6nh_POh}G^ z!~>g^cHI5)wFKf{d ziE?Kj`NBZZm2pR{q(gJ@`XRTnAzmBum^Olj6u|3Df7LugDb zNOfR-Rp`uF6eDk8k`v^LGmnSt8~c^x$B9iLDiML@p=5Mi9@`vABmR5_Bt+IQ1~vsd zr6Y_nz38QR=|~?~?^p<{yzBX-bL;u5!UNaB5dypG!8!>e`z>cd0)E4h$`FsDj`>T4 z!AnFs0|6zz+pC}RY`&DdC=2e9f9PNgKA{7QUZru2N;}$;S|=SWthHp@?yE=N8Z@a+ z@|U(-U9Hetm2^`78Tar537)D7uAUd5OQ=S%$ULn>`M8YP49$LK$^LO5FxaER%TrgE zWY^29gOYkSCnZaAiqyU>q3Y0CLaiaHzK_&;n(`$l6d{yF z(Azzk!2(xhSN`-(YG=nN&Ev!}EKUafCfv z@a+;eP&q94XLjbxP!%^Nwjr}DJ$jUs*DzCLK75bQ;V`JNe+J_d7(@SUJS5Xb-m9~B zxhT)#4LPr4BucOGRJ7^U6TG871lCKyqW{1XBlD1_42>5&^BAE26y-hYa1&H~dUdbc2y%;-L#zI0!fQ|vCkLUm{3DLTt3^Bn`JF#=Px-W0Wv$UB>xjA2yt^bc zszNHKklWlaR_v&(!$Kz%{c#WJVc!K};pFkcpc8lw-`9%vm!IdW>5vdn_Be{9di1S? zV*%+Dl;4aZBzppA%$++}ctZ z^&2+DMs!Ql3W%`}3ikFgD&Gs21@GQ~wpy!5#KNdI{T9wG!^uoYLDq^HS$<0-Dv0(O zzWeHF+mq^b`kJ}(n3F$*&Y-u*{+C9ONf7sazHKJqt){wDOxJbu3Gz14F!RmZUVat9 z*3Bg(Pdb0o*UcF<$Uy@R3F=SeS42QctOC8!dE}d5tu)P`D9(TKg>p?roZc*27x$pR zl=dS{Vku1(kVtVz_Q|_VL{GL&Ej)HxkbY!0dV$FRcw&%jH!k^ZH|P-nh>HIV2b@7+ zqaBnpBSDr-t*(N3eqHqAsVpO}iSWnO4h!%Eks=ZZ1VZ%QGI`MYEGph#0`!~OTs`F5 zKd(bTEr}IyeT0O~ZY4WE0^<1cC`ysZus;Z7iYX)_n(TTVI($k-r^692pw;fTYkcx5G0X>yHGrW-t1$o7*}qRgib{LrktpFo%2mKezyM5^}fk9V@>OOXMse;Fn-Qqk9p+zi=wV?KmJywBJXEPx^AUhX^JT% z)i#JX;ABF#)c-!HRnzsCdW!~;-*01{dYg@lKAhmsnXPGIuhBm%kRCH1XqnVX6kGVo zh?LxI+B{OOGzeH94 ziNO9%f&2x*{(bcS6od7C@~3I5bBEE!7Z8IltQakMUiQ^Ut*9u!o<#+>l}!!m^I)?q zcv=*Is!BGJ8@{(-ESO0SDM&1=-@^E4z zSp``F@4QRjbmZ&LV@3!-YYY$2210+Y1|Pn;Xpm4VT5MW$BCe zg|5C1lo_xa&@(jjGTgUY9mTc{+dQ||ew=8K7k>6E=s6J#}9eVev z;Ks)a1pJiYzl*|OF0YcI!kJI8J-c)Z~BD_-%#Ayd za1l_Oh#A}4d=fTHD>dSOUk-%SquDopm{SuZdY-BAHMuiezdrB#F@T#vYqFT)q+?l8 zZC`lxaF*1Xa&6Xj?9Eq!t3Ql@gh23jKCM*+i9?)kxhAV?5<7)Lwzj-ou2<+H=zaoS zqqgtX67Ub&0$QlPA)-f4zRmSl|2A-1zgbI{m~z(E3^xQv&8)h%mHm!Dey~CN)T}6S-HW#B@6~g-i0Z?c$7HjGEwzY@6ySM}2^jpGisMYPg~gzfoY4 ziJwArDqe7Yq5AJP~-hYU=yl26n6AY_$u^@J?FoiO#jXjFWVDukWi@# zx%NXg>7|NR`5=<#dvRQbKo|jpOvm7UDf}fg+SoYZI`rwAr{x@aa?FQlR`NIsL3<06 z*W&gsp(bkJoBq&S|J)!!DLjvCERviEASD% zN!>g}9naWwqLw+s!o!!a<2xXP8s)tmFWgj7ynh@&p1<&!E(hN7SUP+0qu*cKws07l zoNht|_$f&?=zvGy zJ5D9SSU;b526MthuEKb+-{IsMmV)<%`REE;fFIfTBr|Q#5FS+fId!@TGK~T@OGp%yf`W$M|D>*8{-2x9|_s)B2GakaLlB*4W9@ZG1sxdT;mgQO*O*nq% zKGGWrlo45(h>aa8OI0i{zf9;uo_D?0M|ll$9FDx!XI)ad=?MAEWzR#NsX}AA-xgk2 zl23c?n(912%P%bpiK!s;YlSJ*4sC zC8`%d?s|H{jJB+&)P1o-6aH*wu-8#YVso-e-_84vTNJZazhJ(`GGVlf%` zTwUd36x9Kjx4qKV{J}0bEoo|DHKXQ!xTI`)y-boSH21Zwn4$e0Pd3(%^JH0%=o=L4|?x}=BI z8FIR8v5}`|Ynyh&6PktIZz1*Zcc5+85#`B`XiP9T*TO0hMwd!-exn0)K^_lk5`*pz z(~}wSUQvDOj6rYShO(?WtrB!}ef7!qS8Lo{I@(E5Gx9lV14Mwpj{6o-=X`=akPiW$OOaGg{sEaOF?xa5d`wjXY?Lt z1vSW#T+?RVksbb?@P?WB=G(IRfK~+_)HiKnnxpdrsjAcpChh}XJ7&YDe&=PX4g`do1I@)#V4f`ShQ0fni;-^V4~GKdox8$d5vuvDa(!bu!ZT6$NrX5#(tj3)cMxD*S_*%LZcFS*` zbb$WYaVxdOj8Uzp`Yj~;g+Zrs_s&4>g2dTuj}1?>Bp?^D;X;6q(;__345mH$3KEYQoH&Wn7P4JpYz5>fc-WmLO;X$x;>x@*Gw z`N@`!8re}CKOPQia`44cHI^A2g`mTXF_@5l|pF7BeKe7Y;@S|lb`e8IL58KbH1b5kf zI=Dmmv8?t#0x5LOghSA2dekp;R#I61Wn-BCc^jGFf~13pbBXDU6T%XHceR+SFy5D{cmq=JQS)jSU9XZ%ZG%Ca zWow<+x#=^Ei!FYfssyU!U(ZJ$ zupG;mNRZ)K?&X{bzfJkeg#kvRfFsCQE)~0-c*Xl2kl@3cJ={q&W%ev=BZ^3Tfi?=T z7YsLV4Jhq9MB75!grcg=v`6s-KcS`8?fgiy64}b@(OF>x$)0cWSKseu$a57}Yd}#W zjeCHaNa^37eCFq|BHww>ogjTI&@z~}8sdGH`f8N*tzvJvS5A|<;d``aMsxE^m~b(5 zaDGzCbZ7l^6cFY0Va%M=n5>jK43Jl=$oRtK_dFL~oBy*c01gcR!6V8bo>l5#wxkr% z%?KC#0GT)Hjx!49-?~`cqnRJLF^V3RMHU=P^#1(PivtpB)dQAKyR@-*f<@@7ftsgp zqn`0x`%(EfB=C^uLXhYWfB8S4G3{lc9vWwMT0(cP^+Mmp3@qB^(B5p`Hxb^Y9{?qcv2$u%mE4B$;vylB|_MuJ{UG|Vrt}ETmkrUppRR8#FAxcG$73&3}z+gS$S=5Da%Yo5)d+T1+V z&KTIxQnUuvU;sAJ@C&gJT1C=8XKtV=Y;su4FuR7UCWONIZt?PsV;+W#a`p^q0V9Ko z(Lb18nnAAl3zG3B(DaE(p-La+5+iLW<7(xyVNlLD3!IqjsLopX)t{gbUQpUa7E~*- zt5eJ8rH}oJVbXk~G9kzVd<2@A_-HgC`{X-T%6{Uy40YWQ!u0d-DG`ftrLr+9Qh%0A z?}h1TSF<_$?pe%S*?IW^b+kXH(<4_)H+TMnuH{(&h3}*6R3j%Vv5w5b0?YbhmR-w+ zeiu`k7D7{G$`_D!RRdvqSp|O4Pn&$q<&`6okEcg})700wesNjg zjZefpYJg!~%tiU)&8hR5_4-x3m^!)Qyqu(`gfgm|l7|uxKhjc7*$U0r7DI_>ys@3E z5`g&sD(%ewq3+*3u2q{9p%RL0jhRulEQ3TEGsw=^cOMM0Wf#g=(%iPOQ_L9Kq!@Br zQb}U6G!rsH#n6ylBl{Wm-T9t#zK{Dn&JX7g_-xnv{l4Cx_v^Zz*To1$QoGy@!e{+k zY#`4Fsq(|9kN(3?-VDJ~KOJy`9Q(xrg|lX|Crwll>l?P)z z25Ap>)s;0zMd5|y{Gyn4t-%t2two)BHT2guYg(3Mu~7bNE6S%-#_rW}>x21$Rw3ve zTCCYMFUiGTjUv0{*8HIn6T30!owc7Zbge#>RnhgUKH8o^oA0-aA-hCBTkI=DynDks zjHFv1{T>xJa?D^X13fQNs_=$IIuDa5kWucH6#3AyeIvm<2v5CRzal5zFpc3g@~x;z zH1>9%5H4UKlT|*pR#(I65NFT;CX~m>06Tx}T=plo_b(L)atv7DshGValS18_mHB_pKDaN*u0hBhW;sWg z%^8o>uam(C*_wHdtH1D`nbr={mjyC;EfihAqSN|SjqTj3FW3C}M(hHo^LiPPcYb}g zN^9Miu4;pqaEIV^)IM#chgdh1g;>8mLou+zq&Ks9mI2WMbooUAh@PIbe%1y>4jva< zk5}d|EdtvF;?6Bx6|}EO;44s?dHd(jiCmpg%D`IkKrKpka()gUse`Nc8)NsC4z9L1 zo-nX8Jmnsqyq?!Jtya-U?h?OgeS<9N)w~rII{kTN@3+kNgdp2x#w#JT_HYe~Y;LEa zK|P)~lD9Pl#tY3O`oof|SI)w%z1#eBQ`@~dJOX6RKcNuk%FtDF0H%EAT^Rj?e0-p@ z@kCBI{Y3q-6EO5%-=nV1aVGLd{jCaALs7h#)z5*0avrNX*yQ*Q6~)P=_LuulZk9bX zJ&py+>*o?Hyo*l>NBB6M^u)sBkW^|z=Ku_KF5c1WUR$_@)fYa8BiK+wkjP_Z{*8lw z{E?z_zOYt7;)HdBt+(Jc}BWy($Ib5=z7$3aty7K+XT z`$YUkT6;KcvLYY}`Fl*PT>XyFc=D>Xe!W9!C|?nM+xAhr?M3a|AR75%(3l~ohkJ!} zs8KW6M%%XH(U#HnoT7{xKhxVp{7=7=k#|VheC`gQrQQ#7SD8`Il$8B^<*jKkv$1o! z6uF$&<0AzLqO)gm2hT}Fo9azh1k~*sJs^=KPkuO6_o%B|{ipud%dp`@SXM&4Yn{}t z!I$!M*Kjci1QZ?Cv&8q(=Pa{breCDqj4^+Z z`_3sr?vM^uMI>S--`!p3&W3e{-OfWLRhhgq=3y;%>5`vs36(Po2b9%Nnfe*8Go7p~ z11bn+KABv>k2Qo-hS;GwAwPrU zwwHM6Rpu*?6^cN(iY+*|o8EsuAptN?E(AE7(I-k_IyT?5$2aR_gz*Ly%Tv_^8Vl^U z^Tp!9?m6D>T-GvbYHBh)S3U%Sh>6c_P$PA++}Lm%RB8_vWiV+~mbMm&9F z_L{I&6mDy^(EYyI+}oB&o(ahTCKoKL?JX;ND&ZjeShAgVcv{1Isg`67BgPX6aMRsk zNwx`n+h?YbbPyKD(&GZEktk2nvF?v)1Glcz2fg$_io*2e+CiQKJ=ED=A<4E=fPM1u z;x`uQEIl;PJtPb!9kSL?F)wWDo=PEjBWBj|;*Hk>oZmuuVWg`qjRYZkz2v<1d4MS$ zfvTymCwJvk62!}`cli0x=n94kUZJQMg>t<*W(ZU9aK{feBN>axD0-nTZ&FDdu8nIXpLYi_~$=_e*oO7JGsqSiD zf{jtXa#4gC&K!`xeYoQFIB3P`%DoL5`nSr<4DZFU!;d$r5-r}9)oDC0VqlCDzr zdh&mPT(ueP7%Yt*gSxL90UDNkWW>YNh%nM)aYpK^RLQvDlm)l@%RFY(q=4K(2L80~ z`0e|r6L_dKX#L@;C&l5-UDX|*?n@$k>^+9_`lTr)fw+OLoZ+7D{{9=T!2*cD;Fzo@ zMMbk_~)PTwpQ zB`rfVD#eBmttryPS0T|8yv}9{1;@rWc)FeGAyR^I4na?>XQtMdJ(YMYgl%M>KLRBt zcXFK z<6R-IYe_a&K}O=FtCDT>)1W{7MrlbjIXI9;`TA7OqIinKN%&^XrvT>m@x!_cq1l4ldfoU-ktS?(KnY^_$1OaD|1(6 z#l-j~>8d9(-4kywi(>KnNq?A!Qc{p3{yqLcm}FW}RCP*P&%O|4D==v>m#FJ1IP%rW zw`M3UilgcqHsS$yhAz7t=XhfP&GRN=X*JZcQTY<*o5|3PpIIk@3Itrjk`PG>xefb= zZpC}_@o&_%FN1SDiGYUP4p6j6z!gVKr!!IaF?lnu-Qjwmvv~AS+|)vElVdf?5vwXMstwn2)mkxiVy@v2e4ZyrC4yU-J*v z5WG^==v01_sdW(<`-XKM>rj}st`~X*m{BF-l6*#d&VER9JC82eAO3&#=R&2CT@y2L zDF|1mGpK!c52n{wEg46!C4^0ap5;-^ICx%2`QhUXW6|7wcjMFQYow#1#9r`p@6o&t z_Zqs`;gmS}cji1hzPcM({R_jmtKF5FOVkh+u;`g|Q`GOTLe|Ta-Z8&IPa#tHQ1VJ4mkHnr4b|$V z%Vn}#(`PC2myU2{fvQn?xVM}iaNfp#ZH_w^mE3SX1cEE|Q4p5bxKg&Cn)j=?G zYjaF=KG+C9UPG>6Vu>u2Ntn|so@LYSB^OH9N{?tsw%X~t0><=+Xmx1+RZrjBddwHe z?4P0bac*jFE^ckx!kvUT(nmrhOX*L^;q+!otpr^Gv+|#CuNFra#Y}S~s+fM|2o)276zL zc)2!v_wtWnge@nB6^-Ei2|$k5&C1;Eh7#gHpdrOA(oDkIyz~zLnRaaiNAo)vNpv#-)Jq7bV=8A0>VIe&3o33suMab<)FauWhW)l)b6f@oZ~OQ+jvR7<&(^IrgEZzggFOa?u>qG0FZE z@w`T8mEs9Pnt9H)WhHx`!ty6aG>Ya6$KpkPzf<(a@BAd`s=^|w*Zd)g!4|MbdG zP4=i&XW31!@1F(*^pD$V0`NX*#A1rn04;5E1J@-c@` z00$U}LIxeyM5O;yKh6K5Y}oSKzc`k^R^$JNrqN7hdyc+{aud{Hjy@Z93A^8{%>N*4 z{&(l1>3p;4W7{|B1;(AHF?XID2`lnI?-f+N^RSxz@?e4=e3wYMWG&* z?)D%2M=UNkl?x%*HEdT`SuagX=;OUYc?vp53GI^+_&UqK&o z9-x#84v7_gJHbfhPFDo0@?j%5JS3w-L@}gIN+dwv@WJkNS_`r} g0(Dp7>&~9l!>0?8#hZ88on<-TItJQLv>amp19^eZx&QzG diff --git a/doc/user/group/settings/img/new_group_navigation_v13_1.png b/doc/user/group/settings/img/new_group_navigation_v13_1.png deleted file mode 100644 index 307175727c7f961f72c31d7618741e3c1394378a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39500 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 [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2888) in GitLab 13.0 as an experimental feature. May change in future releases. @@ -23,9 +24,9 @@ Users with the [Owner role](../../permissions.md) for a group can enable import and export for that group: 1. On the top bar, select **Menu > Admin**. -1. On the left sidebar, select **Settings > General > Visibility and access controls**. -1. Scroll to **Import sources**. -1. Enable the desired **Import sources**. +1. On the left sidebar, select **Settings > General**. +1. Expand **Visibility and access controls**. +1. In the **Import sources** section, select the checkboxes for the sources you want. ## Important Notes @@ -72,16 +73,16 @@ in GitLab 14.6 and replaced by [GitLab Migration](../import/). Users with the [Owner role](../../permissions.md) for a group can export the contents of that group: -1. On the top bar, select **Menu >** **Groups** and find your group. -1. On the left sidebar, select **Settings**. -1. Scroll to the **Advanced** section, and select **Export Group**. +1. On the top bar, select **Menu > Groups** and find your group. +1. On the left sidebar, select **Settings > General**. +1. In the **Advanced** section, select **Export Group**. 1. After the export is generated, you should receive an email with a link to the [exported contents](#exported-contents) in a compressed tar archive, with contents in NDJSON format. 1. Alternatively, you can download the export from the UI: 1. Return to your group's **Settings > General** page. - 1. Scroll to the **Advanced** section, and select **Download export**. - You can also generate a new file by clicking **Regenerate export**. + 1. In the **Advanced** section, select **Download export**. + You can also generate a new file by selecting **Regenerate export**. NOTE: The maximum import file size can be set by the Administrator, default is `0` (unlimited). @@ -95,24 +96,18 @@ The Enterprise Edition retains some group data that isn't part of the Community ## Importing the group -1. Navigate to the New Group page, either via the `+` button in the top navigation bar, or the **New subgroup** button -on an existing group's page. - - ![Navigation paths to create a new group](img/new_group_navigation_v13_1.png) - -1. On the New Group page, select the **Import group**. - - ![Fill in group details](img/import_panel_v14_1.png) +1. Create a new group: + - On the top bar, select **New** (**{plus}**) and then **New group**. + - On an existing group's page, select the **New subgroup** button. +1. Select **Import group**. 1. Enter your group name. - 1. Accept or modify the associated group URL. - -1. Click **Choose file** - +1. Select **Choose file**. 1. Select the file that you exported in the [Export a group](#export-a-group) section. +1. To begin importing, select **Import group**. -1. Click **Import group** to begin importing. Your newly imported group page appears after the operation completes. +Your newly imported group page appears after the operation completes. ## Version history diff --git a/doc/user/profile/img/notification_global_settings_v13_12.png b/doc/user/profile/img/notification_global_settings_v13_12.png deleted file mode 100644 index 0998bb89778ec5306824653c908175d4157644ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9268 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 Introduced in GitLab 12.0 +> Introduced in GitLab 12.0. -You can select an email address to receive notifications for each group you belong to. This could be useful, for example, if you work freelance, and want to keep email about clients' projects separate. +You can select an email address to receive notifications for each group you belong to. +You can use group notifications, for example, if you work freelance, and want to keep email about clients' projects separate. 1. In the top-right corner, select your avatar. 1. Select **Preferences**. @@ -112,9 +117,9 @@ You can select an email address to receive notifications for each group you belo 1. Locate the project in the **Groups** section. 1. Select the desired email address. -### Project notifications +### Change level of project notifications -You can select a notification level for each project to help you closely monitor activity in select projects. +To help you stay up to date, you can select a notification level for each project. To select a notification level for a project, use either of these methods: @@ -131,28 +136,20 @@ Or: 1. Select the desired [notification level](#notification-levels). -To learn how to be notified when a new release is available, see [Notification for releases](https://www.youtube.com/watch?v=qyeNkGgqmH4). +To learn how to be notified when a new release is available, watch [Notification for releases](https://www.youtube.com/watch?v=qyeNkGgqmH4). -### Notification levels - -For each project and group you can select one of the following levels: - -| Level | Description | -| ----------- | ----------------------------------------------------------- | -| Global | Your global settings apply. | -| Watch | Receive notifications for any activity. | -| On mention | Receive notifications when [mentioned](../project/issues/issue_data_and_actions.md#mentions) in a comment. | -| Participate | Receive notifications for threads you have participated in. | -| Disabled | Turns off notifications. | -| Custom | Receive notifications for custom selected events. | - -### Product marketing emails +### Opt out of product marketing emails You can receive emails that teach you about various GitLab features. -This is enabled by default. +These emails are enabled by default. -To opt out, [edit your notification settings](#edit-notification-settings) and clear the -**Receive product marketing emails** checkbox. +To opt out: + +1. In the top-right corner, select your avatar. +1. Select **Preferences**. +1. On the left sidebar, select **Notifications**. +1. Clear the **Receive product marketing emails** checkbox. + Edited settings are automatically saved and enabled. Disabling these emails does not disable all emails. Learn how to [opt out of all emails from GitLab](#opt-out-of-all-gitlab-emails). @@ -175,108 +172,115 @@ Users are notified of the following events: | Event | Sent to | Settings level | |------------------------------|---------------------|------------------------------| -| New release | Project members | Custom notification | -| Project moved | Project members (1) | (1) not disabled | +| New release | Project members | Custom notification. | +| Project moved | Project members | Any other than disabled. | | Email changed | User | Security email, always sent. | -| Group access level changed | User | Sent when user group access level is changed | +| Group access level changed | User | Sent when user group access level is changed. | | New email added | User | Security email, always sent. | | New SAML/SCIM user provisioned | User | Sent when a user is provisioned through SAML/SCIM. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276018) in GitLab 13.8 | | New SSH key added | User | Security email, always sent. | -| New user created | User | Sent on user creation, except for OmniAuth (LDAP)| -| Password changed | User | Security email, always sent when user changes their own password | -| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user | -| Personal access tokens expiring soon | User | Security email, always sent. | +| New user created | User | Sent on user creation, except for OmniAuth (LDAP). | +| Password changed | User | Security email, always sent when user changes their own password. | +| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user. | +| Personal access tokens expiring soon | User | Security email, always sent. | | Personal access tokens have expired | User | Security email, always sent. | -| Project access level changed | User | Sent when user project access level is changed | -| SSH key has expired | User | Security email, always sent. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322637) in GitLab 13.12 | +| Project access level changed | User | Sent when user project access level is changed. | +| SSH key has expired | User | Security email, always sent. _[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322637) in GitLab 13.12._ | | Two-factor authentication disabled | User | Security email, always sent. | -| User added to group | User | Sent when user is added to group | -| User added to project | User | Sent when user is added to project | +| User added to group | User | Sent when user is added to group. | +| User added to project | User | Sent when user is added to project. | ## Notifications on issues, merge requests, and epics +You also receive notifications for events happening on +issues, merge requests, and epics. + +### Who receives notifications on issues, merge requests, and epics + +In issues, merge requests, and epics, for most events, the notification is sent to: + +- Participants: + - The author and assignee. + - Authors of comments. + - Anyone [mentioned](../project/issues/issue_data_and_actions.md#mentions) by username in the title + or description. + - Anyone mentioned by username in a comment if their notification level is "Participating" or higher. +- Watchers: users with notification level "Watch". +- Subscribers: anyone who manually subscribed to notifications. +- Custom: users with notification level "Custom" who turned on notifications for a fitting type of events. + +NOTE: +To minimize the number of notifications that do not require any action, in +[GitLab 12.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/616), eligible +approvers are no longer notified for all the activities in their projects. To turn on such notifications, they have +to change their user notification settings to **Watch** instead. + +### Edit notification settings for issues, merge requests, and epics + To enable notifications on a specific issue, merge request, or epic, you must turn on the **Notifications** toggle in the right sidebar. - To subscribe, **turn on** if you are not a participant in the discussion, but want to receive notifications on each update. + + When you turn notifications on in an epic, you aren't automatically subscribed to the issues linked + to the epic. + - To unsubscribe, **turn off** if you are receiving notifications for updates but no longer want to - receive them, unsubscribe from it. + receive them. -Turning this toggle off only unsubscribes you from updates related to this issue, merge request, or epic. -Learn how to [opt out of all emails from GitLab](#opt-out-of-all-gitlab-emails). + Turning this toggle off only unsubscribes you from updates related to this issue, merge request, or epic. + Learn how to [opt out of all emails from GitLab](#opt-out-of-all-gitlab-emails). -Turning notifications on in an epic doesn't automatically subscribe you to the issues linked -to the epic. - -For most events, the notification is sent to: - -- Participants: - - The author and assignee of the issue/merge request. - - Authors of comments. - - Anyone [mentioned](../project/issues/issue_data_and_actions.md#mentions) by username in the title - or description of the issue, merge request or epic. - - Anyone with notification level "Participating" or higher that is mentioned by their username in - any of the comments on the issue, merge request, or epic. -- Watchers: users with notification level "Watch". -- Subscribers: anyone who manually subscribed to the issue, merge request, or epic. -- Custom: Users with notification level "custom" who turned on notifications for any of the events in the following table. - -NOTE: -To minimize the number of notifications that do not require any action, in -[GitLab versions 12.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/616), eligible -approvers are no longer notified for all the activities in their projects. To receive them they have -to change their user notification settings to **Watch** instead. +### Notification events on issues, merge requests, and epics The following table presents the events that generate notifications for issues, merge requests, and epics: | Event | Sent to | |------------------------|---------| -| Change milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected | -| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected | +| Change milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected. | +| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected. | | Close epic | | | Close issue | | | Close merge request | | -| Due issue | Participants and Custom notification level with this event selected | -| Failed pipeline | The author of the pipeline | -| Fixed pipeline | The author of the pipeline. Enabled by default. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24309) in GitLab 13.1 | +| Due issue | Participants and Custom notification level with this event selected. | +| Failed pipeline | The author of the pipeline. | +| Fixed pipeline | The author of the pipeline. Enabled by default. _[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24309) in GitLab 13.1._ | | Merge merge request | | -| Merge when pipeline succeeds | Author, Participants, Watchers, Subscribers, and Custom notification level with this event selected. Custom notification level is ignored for Author, Watchers and Subscribers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211961) in GitLab 13.4 | -| Merge request [marked as ready](../project/merge_requests/drafts.md) | Watchers and participants. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15332) in GitLab 13.10 | -| New comment | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher | +| Merge when pipeline succeeds | Author, Participants, Watchers, Subscribers, and Custom notification level with this event selected. Custom notification level is ignored for Author, Watchers and Subscribers. _[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211961) in GitLab 13.4._ | +| Merge request [marked as ready](../project/merge_requests/drafts.md) | Watchers and participants. _[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15332) in GitLab 13.10._ | +| New comment | Participants, Watchers, Subscribers, and Custom notification level with this event selected. Also anyone mentioned by username in the comment, with notification level "Mention" or higher. | | New epic | | | New issue | | | New merge request | | -| Push to merge request | Participants and Custom notification level with this event selected | -| Reassign issue | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus the old assignee | -| Reassign merge request | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus the old assignee | -| Remove milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected | -| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected | +| Push to merge request | Participants and Custom notification level with this event selected. | +| Reassign issue | Participants, Watchers, Subscribers, Custom notification level with this event selected, and the old assignee. | +| Reassign merge request | Participants, Watchers, Subscribers, Custom notification level with this event selected, and the old assignee. | +| Remove milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected. | +| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected. | | Reopen epic | | | Reopen issue | | | Reopen merge request | | -| Successful pipeline | The author of the pipeline, if they have the custom notification setting for successful pipelines set. If the pipeline failed previously, a `Fixed pipeline` message is sent for the first successful pipeline after the failure, then a `Successful pipeline` message for any further successful pipelines. | +| Successful pipeline | The author of the pipeline, with Custom notification level for successful pipelines. If the pipeline failed previously, a "Fixed pipeline" message is sent for the first successful pipeline after the failure, and then a "Successful pipeline" message for any further successful pipelines. | If the title or description of an issue or merge request is -changed, notifications are sent to any **new** mentions by `@username` as +changed, notifications are sent to any **new** mentions by username as if they had been mentioned in the original text. -By default, you don't receive notifications for issues, merge requests, or epics created -by yourself. You only receive notifications when somebody else comments or adds changes to the ones -that you've created or mentions you, or when an issue is due soon. -To always receive notifications on your own issues and so on, you must turn on -[notifications about your own activity](#global-notification-settings). - If an open merge request becomes unmergeable due to conflict, its author is notified about the cause. If a user has also set the merge request to automatically merge when pipeline succeeds, then that user is also notified. +By default, you don't receive notifications for issues, merge requests, or epics created by yourself. +To always receive notifications on your own issues, merge requests, and so on, turn on +[notifications about your own activity](#global-notification-settings). + ## Notifications on designs > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217095) in GitLab 13.6. -Email notifications are sent to the participants when comments are made on a design. +Email notifications are sent to the participants when someone comments on a design. The participants are: @@ -288,7 +292,9 @@ The participants are: If you no longer wish to receive any email notifications: -1. [Go to the Notifications settings page.](#edit-notification-settings) +1. In the top-right corner, select your avatar. +1. Select **Preferences**. +1. On the left sidebar, select **Notifications**. 1. Clear the **Receive product marketing emails** checkbox. 1. Set your **Global notification level** to **Disabled**. 1. Clear the **Receive notifications about your own activity** checkbox. @@ -299,40 +305,43 @@ On self-managed installations, even after doing this, your instance administrato [can still email you](../../tools/email.md). To unsubscribe, select the unsubscribe link in one of these emails. -## Filter email +## Email headers you can use to filter email -Notification email messages include GitLab-specific headers. You can filter the notification emails based on the content of these headers to better manage your notifications. For example, you could filter all emails for a specific project where you are being assigned either a merge request or issue. +Notification email messages include GitLab-specific headers. To better manage your notifications, +you can filter the notification emails based on the content of these headers. + +For example, you could filter all emails from a specific project where you are being assigned a +a merge request or an issue. The following table lists all GitLab-specific email headers: | Header | Description | |------------------------------------|-------------------------------------------------------------------------| -| `X-GitLab-Group-Id` **(PREMIUM)** | The group's ID. Only present on notification emails for epics. | -| `X-GitLab-Group-Path` **(PREMIUM)** | The group's path. Only present on notification emails for epics. | -| `X-GitLab-Project` | The name of the project the notification belongs to. | -| `X-GitLab-Project-Id` | The project's ID. | -| `X-GitLab-Project-Path` | The project's path. | +| `List-Id` | The path of the project in an RFC 2919 mailing list identifier. You can use it for email organization with filters. | | `X-GitLab-(Resource)-ID` | The ID of the resource the notification is for. The resource, for example, can be `Issue`, `MergeRequest`, `Commit`, or another such resource. | | `X-GitLab-Discussion-ID` | The ID of the thread the comment belongs to, in notification emails for comments. | +| `X-GitLab-Group-Id` **(PREMIUM)** | The group's ID. Only present on notification emails for epics. | +| `X-GitLab-Group-Path` **(PREMIUM)** | The group's path. Only present on notification emails for epics. | +| [`X-GitLab-NotificationReason`](#x-gitlab-notificationreason) | The reason for the notification. This can be `mentioned`, `assigned`, or `own_activity`. | | `X-GitLab-Pipeline-Id` | The ID of the pipeline the notification is for, in notification emails for pipelines. | +| `X-GitLab-Project-Id` | The project's ID. | +| `X-GitLab-Project-Path` | The project's path. | +| `X-GitLab-Project` | The name of the project the notification belongs to. | | `X-GitLab-Reply-Key` | A unique token to support reply by email. | -| `X-GitLab-NotificationReason` | The reason for the notification. This can be `mentioned`, `assigned`, or `own_activity`. | -| `List-Id` | The path of the project in an RFC 2919 mailing list identifier. This is useful for email organization with filters, for example. | ### X-GitLab-NotificationReason -The `X-GitLab-NotificationReason` header contains the reason for the notification. The value is one of the following, in order of priority: +The `X-GitLab-NotificationReason` header contains the reason for the notification. +The value is one of the following, in order of priority: - `own_activity` - `assigned` - `mentioned` -The reason for the notification is also included in the footer of the notification email. For example an email with the -reason `assigned` has this sentence in the footer: +The reason for the notification is also included in the footer of the notification email. +For example, an email with the reason `assigned` has this sentence in the footer: -- `You are receiving this email because you have been assigned an item on .` - -Notification of other events is being considered for inclusion in the `X-GitLab-NotificationReason` header. For details, see this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/20689). +> You are receiving this email because you have been assigned an item on \. For example, an alert notification email can have one of [the alert's](../../operations/incident_management/alerts.md) statuses: @@ -341,3 +350,6 @@ For example, an alert notification email can have one of - `alert_acknowledged` - `alert_resolved` - `alert_ignored` + +Expanding the list of events included in the `X-GitLab-NotificationReason` header is tracked in +[issue 20689](https://gitlab.com/gitlab-org/gitlab/-/issues/20689). diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index 893dd2c76e0..7059697354d 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -89,7 +89,7 @@ RSpec.describe 'Profile > Password' do shared_examples 'user enters an incorrect current password' do subject do page.within '.update-password' do - fill_in 'user_current_password', with: user_current_password + fill_in 'user_password', with: user_current_password fill_passwords(new_password, new_password) end end @@ -131,7 +131,7 @@ RSpec.describe 'Profile > Password' do end context 'when current password is incorrect' do - let(:user_current_password) {'invalid' } + let(:user_current_password) { 'invalid' } it_behaves_like 'user enters an incorrect current password' end @@ -139,7 +139,7 @@ RSpec.describe 'Profile > Password' do context 'when the password reset is successful' do subject do page.within '.update-password' do - fill_in "user_current_password", with: user.password + fill_in "user_password", with: user.password fill_passwords(new_password, new_password) end end @@ -169,8 +169,8 @@ RSpec.describe 'Profile > Password' do expect(current_path).to eq new_profile_password_path - fill_in :user_current_password, with: user.password - fill_in :user_password, with: '12345678' + fill_in :user_password, with: user.password + fill_in :user_new_password, with: '12345678' fill_in :user_password_confirmation, with: '12345678' click_button 'Set new password' diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index d9c919dae3d..b4c041199bb 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -866,8 +866,8 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do expect(current_path).to eq(new_profile_password_path) - fill_in 'user_current_password', with: '12345678' - fill_in 'user_password', with: 'new password' + fill_in 'user_password', with: '12345678' + fill_in 'user_new_password', with: 'new password' fill_in 'user_password_confirmation', with: 'new password' click_button 'Set new password' diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js index b019bae886c..8e0a73b6e7c 100644 --- a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js +++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js @@ -6,9 +6,6 @@ import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_e describe('Pipeline editor empty state', () => { let wrapper; const defaultProvide = { - glFeatures: { - pipelineEditorEmptyStateAction: false, - }, emptyStateIllustrationPath: 'my/svg/path', }; @@ -51,24 +48,6 @@ describe('Pipeline editor empty state', () => { expect(findFileNav().exists()).toBe(true); }); - describe('with feature flag off', () => { - it('does not renders a CTA button', () => { - expect(findConfirmButton().exists()).toBe(false); - }); - }); - }); - - describe('with feature flag on', () => { - beforeEach(() => { - createComponent({ - provide: { - glFeatures: { - pipelineEditorEmptyStateAction: true, - }, - }, - }); - }); - it('renders a CTA button', () => { expect(findConfirmButton().exists()).toBe(true); expect(findConfirmButton().text()).toBe(wrapper.vm.$options.i18n.btnText); diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js index 393cad0546b..b6713319e69 100644 --- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js +++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js @@ -22,7 +22,6 @@ import { mockCiConfigPath, mockCiConfigQueryResponse, mockBlobContentQueryResponse, - mockBlobContentQueryResponseEmptyCiFile, mockBlobContentQueryResponseNoCiFile, mockCiYml, mockCommitSha, @@ -43,9 +42,6 @@ const MockSourceEditor = { const mockProvide = { ciConfigPath: mockCiConfigPath, defaultBranch: mockDefaultBranch, - glFeatures: { - pipelineEditorEmptyStateAction: false, - }, projectFullPath: mockProjectFullPath, }; @@ -221,37 +217,12 @@ describe('Pipeline editor app component', () => { }); }); - describe('with an empty CI config file', () => { - describe('with empty state feature flag on', () => { - it('does not show the empty screen state', async () => { - mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseEmptyCiFile); - - await createComponentWithApollo({ - provide: { - glFeatures: { - pipelineEditorEmptyStateAction: true, - }, - }, - }); - - expect(findEmptyState().exists()).toBe(false); - expect(findTextEditor().exists()).toBe(true); - }); - }); - }); - - describe('when landing on the empty state with feature flag on', () => { - it('user can click on CTA button and see an empty editor', async () => { + describe('with no CI config setup', () => { + it('user can click on CTA button to get started', async () => { mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseNoCiFile); mockLatestCommitShaQuery.mockResolvedValue(mockEmptyCommitShaResults); - await createComponentWithApollo({ - provide: { - glFeatures: { - pipelineEditorEmptyStateAction: true, - }, - }, - }); + await createComponentWithApollo(); expect(findEmptyState().exists()).toBe(true); expect(findTextEditor().exists()).toBe(false); diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 9ba7d0ab359..2ebf75a1d8a 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1290,7 +1290,7 @@ RSpec.describe Ci::Build do end end - describe 'state transition as a deployable' do + shared_examples_for 'state transition as a deployable' do subject { build.send(event) } let!(:build) { create(:ci_build, :with_deployment, :start_review_app, project: project, pipeline: pipeline) } @@ -1399,6 +1399,36 @@ RSpec.describe Ci::Build do end end + it_behaves_like 'state transition as a deployable' do + context 'when transits to running' do + let(:event) { :run! } + + context 'when deployment is already running state' do + before do + build.deployment.success! + end + + it 'does not change deployment status and tracks an error' do + expect(Gitlab::ErrorTracking) + .to receive(:track_exception).with( + instance_of(Deployment::StatusSyncError), deployment_id: deployment.id, build_id: build.id) + + with_cross_database_modification_prevented do + expect { subject }.not_to change { deployment.reload.status } + end + end + end + end + end + + context 'when update_deployment_after_transaction_commit feature flag is disabled' do + before do + stub_feature_flags(update_deployment_after_transaction_commit: false) + end + + it_behaves_like 'state transition as a deployable' + end + describe '#on_stop' do subject { build.on_stop } @@ -3948,7 +3978,7 @@ RSpec.describe Ci::Build do end it 'can drop the build' do - expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception) + expect(Gitlab::ErrorTracking).to receive(:track_exception) expect { build.drop! }.not_to raise_error diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index acccf2c39c4..f9a05fbb06f 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -765,7 +765,7 @@ RSpec.describe Deployment do expect(Deployments::LinkMergeRequestWorker).to receive(:perform_async) expect(Deployments::HooksWorker).to receive(:perform_async) - deploy.update_status('success') + expect(deploy.update_status('success')).to eq(true) end it 'updates finished_at when transitioning to a finished status' do @@ -775,6 +775,139 @@ RSpec.describe Deployment do expect(deploy.read_attribute(:finished_at)).to eq(Time.current) end end + + it 'tracks an exception if an invalid status transition is detected' do + expect(Gitlab::ErrorTracking) + .to receive(:track_exception) + .with(instance_of(described_class::StatusUpdateError), deployment_id: deploy.id) + + expect(deploy.update_status('running')).to eq(false) + end + + it 'tracks an exception if an invalid argument' do + expect(Gitlab::ErrorTracking) + .to receive(:track_exception) + .with(instance_of(described_class::StatusUpdateError), deployment_id: deploy.id) + + expect(deploy.update_status('created')).to eq(false) + end + end + + describe '#sync_status_with' do + subject { deployment.sync_status_with(ci_build) } + + let_it_be(:project) { create(:project, :repository) } + + let(:deployment) { create(:deployment, project: project, status: deployment_status) } + let(:ci_build) { create(:ci_build, project: project, status: build_status) } + + shared_examples_for 'synchronizing deployment' do + it 'changes deployment status' do + expect(Gitlab::ErrorTracking).not_to receive(:track_exception) + + is_expected.to eq(true) + + expect(deployment.status).to eq(build_status.to_s) + expect(deployment.errors).to be_empty + end + end + + shared_examples_for 'gracefully handling error' do + it 'tracks an exception' do + expect(Gitlab::ErrorTracking).to receive(:track_exception).with( + instance_of(described_class::StatusSyncError), + deployment_id: deployment.id, + build_id: ci_build.id) + + is_expected.to eq(false) + + expect(deployment.status).to eq(deployment_status.to_s) + expect(deployment.errors.full_messages).to include(error_message) + end + end + + shared_examples_for 'ignoring build' do + it 'does not change deployment status' do + expect(Gitlab::ErrorTracking).not_to receive(:track_exception) + + is_expected.to eq(false) + + expect(deployment.status).to eq(deployment_status.to_s) + expect(deployment.errors).to be_empty + end + end + + context 'with created deployment' do + let(:deployment_status) { :created } + + context 'with running build' do + let(:build_status) { :running } + + it_behaves_like 'synchronizing deployment' + end + + context 'with finished build' do + let(:build_status) { :success } + + it_behaves_like 'synchronizing deployment' + end + + context 'with unrelated build' do + let(:build_status) { :waiting_for_resource } + + it_behaves_like 'ignoring build' + end + end + + context 'with running deployment' do + let(:deployment_status) { :running } + + context 'with running build' do + let(:build_status) { :running } + + it_behaves_like 'gracefully handling error' do + let(:error_message) { %Q{Status cannot transition via \"run\"} } + end + end + + context 'with finished build' do + let(:build_status) { :success } + + it_behaves_like 'synchronizing deployment' + end + + context 'with unrelated build' do + let(:build_status) { :waiting_for_resource } + + it_behaves_like 'ignoring build' + end + end + + context 'with finished deployment' do + let(:deployment_status) { :success } + + context 'with running build' do + let(:build_status) { :running } + + it_behaves_like 'gracefully handling error' do + let(:error_message) { %Q{Status cannot transition via \"run\"} } + end + end + + context 'with finished build' do + let(:build_status) { :success } + + it_behaves_like 'gracefully handling error' do + let(:error_message) { %Q{Status cannot transition via \"succeed\"} } + end + end + + context 'with unrelated build' do + let(:build_status) { :waiting_for_resource } + + it_behaves_like 'ignoring build' + end + end end describe '#valid_sha' do diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb index 38c96cd37af..69f7b54c277 100644 --- a/spec/requests/api/deployments_spec.rb +++ b/spec/requests/api/deployments_spec.rb @@ -376,6 +376,16 @@ RSpec.describe API::Deployments do expect(json_response['status']).to eq('success') end + it 'returns an error when an invalid status transition is detected' do + put( + api("/projects/#{project.id}/deployments/#{deploy.id}", user), + params: { status: 'running' } + ) + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['message']['status']).to include(%Q{cannot transition via \"run\"}) + end + it 'links merge requests when the deployment status changes to success', :sidekiq_inline do mr = create( :merge_request, diff --git a/spec/services/deployments/update_service_spec.rb b/spec/services/deployments/update_service_spec.rb index 16b24d0dee8..d3840189ba4 100644 --- a/spec/services/deployments/update_service_spec.rb +++ b/spec/services/deployments/update_service_spec.rb @@ -34,9 +34,11 @@ RSpec.describe Deployments::UpdateService do expect(deploy).to be_canceled end - it 'raises ArgumentError if the status is invalid' do - expect { described_class.new(deploy, status: 'kittens').execute } - .to raise_error(ArgumentError) + it 'does not change the state if the status is invalid' do + expect(described_class.new(deploy, status: 'kittens').execute) + .to be_falsy + + expect(deploy).to be_created end it 'links merge requests when changing the status to success', :sidekiq_inline do