Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
13f15365a3
commit
04a7fe4f4b
40 changed files with 592 additions and 297 deletions
|
@ -2,6 +2,14 @@
|
||||||
documentation](doc/development/changelog.md) for instructions on adding your own
|
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||||
entry.
|
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)
|
## 14.3.2 (2021-10-01)
|
||||||
|
|
||||||
### Fixed (1 change)
|
### Fixed (1 change)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { GlButton, GlSprintf } from '@gitlab/ui';
|
import { GlButton, GlSprintf } from '@gitlab/ui';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue';
|
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 {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
@ -17,17 +16,11 @@ export default {
|
||||||
),
|
),
|
||||||
btnText: __('Create new CI/CD pipeline'),
|
btnText: __('Create new CI/CD pipeline'),
|
||||||
},
|
},
|
||||||
mixins: [glFeatureFlagsMixin()],
|
|
||||||
inject: {
|
inject: {
|
||||||
emptyStateIllustrationPath: {
|
emptyStateIllustrationPath: {
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
showCTAButton() {
|
|
||||||
return this.glFeatures.pipelineEditorEmptyStateAction;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
createEmptyConfigFile() {
|
createEmptyConfigFile() {
|
||||||
this.$emit('createEmptyConfigFile');
|
this.$emit('createEmptyConfigFile');
|
||||||
|
@ -48,12 +41,7 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
</gl-sprintf>
|
</gl-sprintf>
|
||||||
</p>
|
</p>
|
||||||
<gl-button
|
<gl-button variant="confirm" class="gl-mt-3" @click="createEmptyConfigFile">
|
||||||
v-if="showCTAButton"
|
|
||||||
variant="confirm"
|
|
||||||
class="gl-mt-3"
|
|
||||||
@click="createEmptyConfigFile"
|
|
||||||
>
|
|
||||||
{{ $options.i18n.btnText }}
|
{{ $options.i18n.btnText }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,17 +15,11 @@ class Profiles::PasswordsController < Profiles::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
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')
|
redirect_to new_profile_password_path, alert: _('You must provide a valid current password')
|
||||||
return
|
return
|
||||||
end
|
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
|
result = Users::UpdateService.new(current_user, password_attributes.merge(user: @user)).execute
|
||||||
|
|
||||||
if result[:status] == :success
|
if result[:status] == :success
|
||||||
|
@ -41,12 +35,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
password_attributes = user_params.select do |key, value|
|
unless @user.password_automatically_set || @user.valid_password?(user_params[:password])
|
||||||
%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])
|
|
||||||
handle_invalid_current_password_attempt!
|
handle_invalid_current_password_attempt!
|
||||||
|
|
||||||
redirect_to edit_profile_password_path, alert: _('You must provide a valid current password')
|
redirect_to edit_profile_password_path, alert: _('You must provide a valid current password')
|
||||||
|
@ -94,6 +83,14 @@ class Profiles::PasswordsController < Profiles::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_params
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
class Projects::Ci::PipelineEditorController < Projects::ApplicationController
|
class Projects::Ci::PipelineEditorController < Projects::ApplicationController
|
||||||
before_action :check_can_collaborate!
|
before_action :check_can_collaborate!
|
||||||
before_action do
|
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(:pipeline_editor_drawer, @project, default_enabled: :yaml)
|
||||||
push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml)
|
push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml)
|
||||||
end
|
end
|
||||||
|
|
|
@ -309,8 +309,10 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
after_transition pending: :running do |build|
|
after_transition pending: :running do |build|
|
||||||
Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
|
unless build.update_deployment_after_transaction_commit?
|
||||||
build.deployment&.run
|
Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
|
||||||
|
build.deployment&.run
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
build.run_after_commit do
|
build.run_after_commit do
|
||||||
|
@ -333,8 +335,10 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
after_transition any => [:success] do |build|
|
after_transition any => [:success] do |build|
|
||||||
Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
|
unless build.update_deployment_after_transaction_commit?
|
||||||
build.deployment&.succeed
|
Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
|
||||||
|
build.deployment&.succeed
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
build.run_after_commit do
|
build.run_after_commit do
|
||||||
|
@ -347,12 +351,14 @@ module Ci
|
||||||
next unless build.project
|
next unless build.project
|
||||||
next unless build.deployment
|
next unless build.deployment
|
||||||
|
|
||||||
begin
|
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
|
begin
|
||||||
build.deployment.drop!
|
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
|
end
|
||||||
rescue StandardError => e
|
|
||||||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, build_id: build.id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -371,14 +377,29 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
after_transition any => [:skipped, :canceled] do |build, transition|
|
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
|
unless build.update_deployment_after_transaction_commit?
|
||||||
if transition.to_name == :skipped
|
Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
|
||||||
build.deployment&.skip
|
if transition.to_name == :skipped
|
||||||
else
|
build.deployment&.skip
|
||||||
build.deployment&.cancel
|
else
|
||||||
|
build.deployment&.cancel
|
||||||
|
end
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
def self.build_matchers(project)
|
def self.build_matchers(project)
|
||||||
|
@ -1095,6 +1116,12 @@ module Ci
|
||||||
runner&.instance_type?
|
runner&.instance_type?
|
||||||
end
|
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
|
protected
|
||||||
|
|
||||||
def run_status_commit_hooks!
|
def run_status_commit_hooks!
|
||||||
|
|
|
@ -10,6 +10,9 @@ class Deployment < ApplicationRecord
|
||||||
include FastDestroyAll
|
include FastDestroyAll
|
||||||
include IgnorableColumns
|
include IgnorableColumns
|
||||||
|
|
||||||
|
StatusUpdateError = Class.new(StandardError)
|
||||||
|
StatusSyncError = Class.new(StandardError)
|
||||||
|
|
||||||
belongs_to :project, required: true
|
belongs_to :project, required: true
|
||||||
belongs_to :environment, required: true
|
belongs_to :environment, required: true
|
||||||
belongs_to :cluster, class_name: 'Clusters::Cluster', optional: 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
|
# Changes the status of a deployment and triggers the corresponding state
|
||||||
# machine events.
|
# machine events.
|
||||||
def update_status(status)
|
def update_status(status)
|
||||||
case status
|
update_status!(status)
|
||||||
when 'running'
|
rescue StandardError => e
|
||||||
run
|
Gitlab::ErrorTracking.track_exception(
|
||||||
when 'success'
|
StatusUpdateError.new(e.message), deployment_id: self.id)
|
||||||
succeed
|
|
||||||
when 'failed'
|
false
|
||||||
drop
|
end
|
||||||
when 'canceled'
|
|
||||||
cancel
|
def sync_status_with(build)
|
||||||
when 'skipped'
|
return false unless ::Deployment.statuses.include?(build.status)
|
||||||
skip
|
|
||||||
else
|
update_status!(build.status)
|
||||||
raise ArgumentError, "The status #{status.inspect} is invalid"
|
rescue StandardError => e
|
||||||
end
|
Gitlab::ErrorTracking.track_exception(
|
||||||
|
StatusSyncError.new(e.message), deployment_id: self.id, build_id: build.id)
|
||||||
|
|
||||||
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_sha
|
def valid_sha
|
||||||
|
@ -353,6 +359,23 @@ class Deployment < ApplicationRecord
|
||||||
|
|
||||||
private
|
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
|
def legacy_finished_at
|
||||||
self.created_at if success? && !read_attribute(:finished_at)
|
self.created_at if success? && !read_attribute(:finished_at)
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,16 +19,16 @@
|
||||||
|
|
||||||
- unless @user.password_automatically_set?
|
- unless @user.password_automatically_set?
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :current_password, _('Current password'), class: 'label-bold'
|
= f.label :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.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
|
%p.form-text.text-muted
|
||||||
= _('You must provide your current password in order to change it.')
|
= _('You must provide your current password in order to change it.')
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :password, _('New password'), class: 'label-bold'
|
= f.label :new_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.password_field :new_password, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' }
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
|
= 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
|
.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' }
|
= f.submit _('Save password'), class: "gl-button btn btn-confirm gl-mr-3", data: { qa_selector: 'save_password_button' }
|
||||||
- unless @user.password_automatically_set?
|
- unless @user.password_automatically_set?
|
||||||
|
|
|
@ -14,18 +14,18 @@
|
||||||
- unless @user.password_automatically_set?
|
- unless @user.password_automatically_set?
|
||||||
.form-group.row
|
.form-group.row
|
||||||
.col-sm-2.col-form-label
|
.col-sm-2.col-form-label
|
||||||
= f.label :current_password, _('Current password')
|
= f.label :password, _('Current password')
|
||||||
.col-sm-10
|
.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
|
.form-group.row
|
||||||
.col-sm-2.col-form-label
|
.col-sm-2.col-form-label
|
||||||
= f.label :password, _('New password')
|
= f.label :new_password, _('New password')
|
||||||
.col-sm-10
|
.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
|
.form-group.row
|
||||||
.col-sm-2.col-form-label
|
.col-sm-2.col-form-label
|
||||||
= f.label :password_confirmation, _('Password confirmation')
|
= f.label :password_confirmation, _('Password confirmation')
|
||||||
.col-sm-10
|
.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
|
.form-actions
|
||||||
= f.submit _('Set new password'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'set_new_password_button' }
|
= f.submit _('Set new password'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'set_new_password_button' }
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: pipeline_editor_empty_state_action
|
name: update_deployment_after_transaction_commit
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55414
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71450
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323229
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342021
|
||||||
milestone: '13.10'
|
milestone: '14.4'
|
||||||
type: development
|
type: development
|
||||||
group: group::pipeline authoring
|
group: group::release
|
||||||
default_enabled: true
|
default_enabled: false
|
15
db/migrate/20210929025600_add_phone_to_user_details.rb
Normal file
15
db/migrate/20210929025600_add_phone_to_user_details.rb
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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
|
36
db/migrate/20210929032555_create_verification_codes.rb
Normal file
36
db/migrate/20210929032555_create_verification_codes.rb
Normal file
|
@ -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
|
1
db/schema_migrations/20210929025600
Normal file
1
db/schema_migrations/20210929025600
Normal file
|
@ -0,0 +1 @@
|
||||||
|
c757a7e17433b8ddf15ae6304286fe3da69f820966455e7fbed7282286f5eb67
|
1
db/schema_migrations/20210929030834
Normal file
1
db/schema_migrations/20210929030834
Normal file
|
@ -0,0 +1 @@
|
||||||
|
b5302b3a2384bd7d0e639f00941efb490c3121a9332f1e73be620ab0f6f3e771
|
1
db/schema_migrations/20210929031049
Normal file
1
db/schema_migrations/20210929031049
Normal file
|
@ -0,0 +1 @@
|
||||||
|
d3f588e4edded61f36acbf25fba39be17a2ac16f37e9114f2c5c257c47dc1308
|
1
db/schema_migrations/20210929032555
Normal file
1
db/schema_migrations/20210929032555
Normal file
|
@ -0,0 +1 @@
|
||||||
|
08593002910759482c58f9b31f251d589ab32b540d9614a2c677df11d32f7f26
|
|
@ -19851,12 +19851,16 @@ CREATE TABLE user_details (
|
||||||
pronouns text,
|
pronouns text,
|
||||||
pronunciation text,
|
pronunciation text,
|
||||||
registration_objective smallint,
|
registration_objective smallint,
|
||||||
|
phone text,
|
||||||
CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)),
|
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_b132136b01 CHECK ((char_length(other_role) <= 100)),
|
||||||
CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)),
|
CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)),
|
||||||
CONSTRAINT check_f932ed37db CHECK ((char_length(pronunciation) <= 255))
|
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
|
CREATE SEQUENCE user_details_user_id_seq
|
||||||
START WITH 1
|
START WITH 1
|
||||||
INCREMENT BY 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;
|
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 (
|
CREATE TABLE vulnerabilities (
|
||||||
id bigint NOT NULL,
|
id bigint NOT NULL,
|
||||||
milestone_id bigint,
|
milestone_id bigint,
|
||||||
|
@ -23810,6 +23827,9 @@ ALTER TABLE ONLY users_star_projects
|
||||||
ALTER TABLE ONLY users_statistics
|
ALTER TABLE ONLY users_statistics
|
||||||
ADD CONSTRAINT users_statistics_pkey PRIMARY KEY (id);
|
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
|
ALTER TABLE ONLY vulnerabilities
|
||||||
ADD CONSTRAINT vulnerabilities_pkey PRIMARY KEY (id);
|
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_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 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);
|
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_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 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);
|
CREATE INDEX index_vulnerabilities_on_author_id ON vulnerabilities USING btree (author_id);
|
||||||
|
|
|
@ -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).
|
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
|
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
|
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
|
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).
|
[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
|
||||||
|
|
|
@ -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
|
(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).
|
[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
|
- **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
|
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).
|
[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).
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
---
|
---
|
||||||
stage: none
|
stage: Manage
|
||||||
group: unassigned
|
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
|
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)**
|
# External authorization control **(FREE SELF)**
|
||||||
|
|
|
@ -24,7 +24,7 @@ View pipeline duration history:
|
||||||
## DevOps Research and Assessment (DORA) key metrics **(ULTIMATE)**
|
## DevOps Research and Assessment (DORA) key metrics **(ULTIMATE)**
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.7.
|
> - [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
|
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
|
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 | |
|
| `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 | |
|
| `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.
|
> [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.
|
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.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250329) in GitLab 13.11.
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
# Issue Analytics **(PREMIUM)**
|
# 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.
|
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
|
The default time span is 13 months, which includes the current month, and the 12 months
|
||||||
|
|
|
@ -115,5 +115,5 @@ bookmark for those preferred settings in your browser.
|
||||||
|
|
||||||
The **Merge Request Analytics** feature can be accessed only:
|
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.
|
- By users with [Reporter access](../permissions.md) and above.
|
||||||
|
|
|
@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
# Productivity Analytics **(PREMIUM)**
|
# 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.
|
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:
|
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.
|
- By users with [Reporter access](../permissions.md) and above.
|
||||||
|
|
|
@ -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
|
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.
|
Get high-level overview of the project's Git repository.
|
||||||
|
|
||||||
|
|
|
@ -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),
|
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.
|
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
|
## Supported fuzzing engines and languages
|
||||||
|
|
||||||
GitLab supports these languages through the fuzzing engine listed for each. We currently provide a
|
GitLab supports these languages through the fuzzing engine listed for each. We currently provide a
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
Before Width: | Height: | Size: 39 KiB |
|
@ -4,6 +4,7 @@ stage: Manage
|
||||||
group: Import
|
group: Import
|
||||||
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
|
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
|
||||||
---
|
---
|
||||||
|
|
||||||
# Group import/export **(FREE)**
|
# Group import/export **(FREE)**
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2888) in GitLab 13.0 as an experimental feature. May change in future releases.
|
> [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:
|
import and export for that group:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Admin**.
|
1. On the top bar, select **Menu > Admin**.
|
||||||
1. On the left sidebar, select **Settings > General > Visibility and access controls**.
|
1. On the left sidebar, select **Settings > General**.
|
||||||
1. Scroll to **Import sources**.
|
1. Expand **Visibility and access controls**.
|
||||||
1. Enable the desired **Import sources**.
|
1. In the **Import sources** section, select the checkboxes for the sources you want.
|
||||||
|
|
||||||
## Important Notes
|
## 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
|
Users with the [Owner role](../../permissions.md) for a group can export the
|
||||||
contents of that group:
|
contents of that group:
|
||||||
|
|
||||||
1. On the top bar, select **Menu >** **Groups** and find your group.
|
1. On the top bar, select **Menu > Groups** and find your group.
|
||||||
1. On the left sidebar, select **Settings**.
|
1. On the left sidebar, select **Settings > General**.
|
||||||
1. Scroll to the **Advanced** section, and select **Export Group**.
|
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)
|
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.
|
in a compressed tar archive, with contents in NDJSON format.
|
||||||
1. Alternatively, you can download the export from the UI:
|
1. Alternatively, you can download the export from the UI:
|
||||||
|
|
||||||
1. Return to your group's **Settings > General** page.
|
1. Return to your group's **Settings > General** page.
|
||||||
1. Scroll to the **Advanced** section, and select **Download export**.
|
1. In the **Advanced** section, select **Download export**.
|
||||||
You can also generate a new file by clicking **Regenerate export**.
|
You can also generate a new file by selecting **Regenerate export**.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
The maximum import file size can be set by the Administrator, default is `0` (unlimited).
|
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
|
## Importing the group
|
||||||
|
|
||||||
1. Navigate to the New Group page, either via the `+` button in the top navigation bar, or the **New subgroup** button
|
1. Create a new group:
|
||||||
on an existing group's page.
|
- On the top bar, select **New** (**{plus}**) and then **New group**.
|
||||||
|
- On an existing group's page, select the **New subgroup** button.
|
||||||
![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. Select **Import group**.
|
||||||
1. Enter your group name.
|
1. Enter your group name.
|
||||||
|
|
||||||
1. Accept or modify the associated group URL.
|
1. Accept or modify the associated group URL.
|
||||||
|
1. Select **Choose file**.
|
||||||
1. Click **Choose file**
|
|
||||||
|
|
||||||
1. Select the file that you exported in the [Export a group](#export-a-group) section.
|
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
|
## Version history
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.1 KiB |
|
@ -13,56 +13,62 @@ You can receive updates about activity in issues, merge requests, epics, and des
|
||||||
For the tool that GitLab administrators can use to send messages to users, read
|
For the tool that GitLab administrators can use to send messages to users, read
|
||||||
[Email from GitLab](../../tools/email.md).
|
[Email from GitLab](../../tools/email.md).
|
||||||
|
|
||||||
## Receive notifications
|
## Who receives notifications
|
||||||
|
|
||||||
You receive notifications for one of the following reasons:
|
When notifications are enabled for an issue, merge request, or epic, GitLab notifies you of actions
|
||||||
|
that happen there.
|
||||||
|
|
||||||
- You participate in an issue, merge request, epic, or design. In this context, _participate_ means
|
You might receive notifications for one of the following reasons:
|
||||||
comment or edit.
|
|
||||||
|
- You participate in an issue, merge request, epic, or design. You become a participant when you comment
|
||||||
|
or edit, or someone mentions you.
|
||||||
- You've [enabled notifications in an issue, merge request, or epic](#notifications-on-issues-merge-requests-and-epics).
|
- You've [enabled notifications in an issue, merge request, or epic](#notifications-on-issues-merge-requests-and-epics).
|
||||||
- You configured notifications at the [project](#project-notifications) and/or [group](#group-notifications) level.
|
- You've configured notifications for the [project](#change-level-of-project-notifications) or [group](#group-notifications).
|
||||||
|
|
||||||
While notifications are enabled, you receive notification of actions occurring in that issue, merge request, or epic.
|
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
Administrators can block notifications, preventing them from being sent.
|
Administrators can block notifications, preventing them from being sent.
|
||||||
|
|
||||||
## Tune your notifications
|
## Edit notification settings
|
||||||
|
|
||||||
Getting many notifications can be overwhelming. You can tune the notifications you receive.
|
Getting many notifications can be overwhelming. You can tune the notifications you receive.
|
||||||
For example, you might want to be notified about all activity in a specific project.
|
For example, you might want to be notified about all activity in a specific project.
|
||||||
For other projects, you only want to be notified when you are mentioned by name.
|
For other projects, you only want to be notified when you are mentioned by name.
|
||||||
|
|
||||||
You can tune the notifications you receive by changing your notification settings:
|
|
||||||
|
|
||||||
- [Global notification settings](#global-notification-settings)
|
|
||||||
- [Notification scope](#notification-scope)
|
|
||||||
- [Notification levels](#notification-levels)
|
|
||||||
|
|
||||||
## Edit notification settings
|
|
||||||
|
|
||||||
These notification settings apply only to you. They do not affect the notifications received by
|
These notification settings apply only to you. They do not affect the notifications received by
|
||||||
anyone else in the same project or group.
|
anyone else.
|
||||||
|
|
||||||
To edit your notification settings:
|
To edit your notification settings:
|
||||||
|
|
||||||
1. In the top-right corner, select your avatar.
|
1. In the top-right corner, select your avatar.
|
||||||
1. Select **Preferences**.
|
1. Select **Preferences**.
|
||||||
1. On the left sidebar, select **Notifications**.
|
1. On the left sidebar, select **Notifications**.
|
||||||
1. Edit the desired notification settings. Edited settings are automatically saved and enabled.
|
1. Edit the desired global, group, or project notification settings.
|
||||||
|
Edited settings are automatically saved.
|
||||||
|
|
||||||
## Notification scope
|
### Notification scope
|
||||||
|
|
||||||
You can tune the scope of your notifications by selecting different notification levels for each project and group.
|
You can tune the scope of your notifications by selecting different notification levels for each
|
||||||
|
project and group.
|
||||||
|
|
||||||
Notification scope is applied from the broadest to most specific levels:
|
Notification scope is applied from the broadest to most specific levels:
|
||||||
|
|
||||||
- **Global (default)**: Your global, or _default_, notification level applies if you
|
- Your **global**, or _default_, notification level applies if you
|
||||||
have not selected a notification level for the project or group in which the activity occurred.
|
have not selected a notification level for the project or group in which the activity occurred.
|
||||||
- **Group**: For each group, you can select a notification level. Your group setting
|
- Your **group** setting overrides your default setting.
|
||||||
overrides your default setting.
|
- Your **project** setting overrides the group setting.
|
||||||
- **Project**: For each project, you can select a notification level. Your project
|
|
||||||
setting overrides the group setting.
|
### 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. |
|
||||||
|
| Participate | Receive notifications for threads you have participated in. |
|
||||||
|
| On mention | Receive notifications when you are [mentioned](../project/issues/issue_data_and_actions.md#mentions) in a comment. |
|
||||||
|
| Disabled | Receive no notifications. |
|
||||||
|
| Custom | Receive notifications for selected events. |
|
||||||
|
|
||||||
### Global notification settings
|
### Global notification settings
|
||||||
|
|
||||||
|
@ -72,19 +78,17 @@ different values for a project or a group.
|
||||||
- **Notification email**: the email address your notifications are sent to.
|
- **Notification email**: the email address your notifications are sent to.
|
||||||
Defaults to your primary email address.
|
Defaults to your primary email address.
|
||||||
- **Receive product marketing emails**: select this checkbox to receive
|
- **Receive product marketing emails**: select this checkbox to receive
|
||||||
[periodic emails](#product-marketing-emails) about GitLab features.
|
[periodic emails](#opt-out-of-product-marketing-emails) about GitLab features.
|
||||||
- **Global notification level**: the default [notification level](#notification-levels)
|
- **Global notification level**: the default [notification level](#notification-levels)
|
||||||
which applies to all your notifications.
|
which applies to all your notifications.
|
||||||
- **Receive notifications about your own activity**: select this checkbox to receive
|
- **Receive notifications about your own activity**: select this checkbox to receive
|
||||||
notifications about your own activity. Not selected by default.
|
notifications about your own activity. Not selected by default.
|
||||||
|
|
||||||
![notification settings](img/notification_global_settings_v13_12.png)
|
|
||||||
|
|
||||||
### Group notifications
|
### Group notifications
|
||||||
|
|
||||||
You can select a notification level and email address for each group.
|
You can select a notification level and email address for each group.
|
||||||
|
|
||||||
#### Group notification level
|
#### Change level of group notifications
|
||||||
|
|
||||||
To select a notification level for a group, use either of these methods:
|
To select a notification level for a group, use either of these methods:
|
||||||
|
|
||||||
|
@ -100,11 +104,12 @@ Or:
|
||||||
1. Select the notification dropdown, next to the bell icon (**{notifications}**).
|
1. Select the notification dropdown, next to the bell icon (**{notifications}**).
|
||||||
1. Select the desired [notification level](#notification-levels).
|
1. Select the desired [notification level](#notification-levels).
|
||||||
|
|
||||||
#### Group notification email address
|
#### Change email address used for group notifications
|
||||||
|
|
||||||
> 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. In the top-right corner, select your avatar.
|
||||||
1. Select **Preferences**.
|
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. Locate the project in the **Groups** section.
|
||||||
1. Select the desired email address.
|
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:
|
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).
|
1. Select the desired [notification level](#notification-levels).
|
||||||
|
|
||||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||||
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
|
### Opt out of product marketing emails
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
You can receive emails that teach you about various GitLab features.
|
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
|
To opt out:
|
||||||
**Receive product marketing emails** checkbox.
|
|
||||||
|
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.
|
Disabling these emails does not disable all emails.
|
||||||
Learn how to [opt out of all emails from GitLab](#opt-out-of-all-gitlab-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 |
|
| Event | Sent to | Settings level |
|
||||||
|------------------------------|---------------------|------------------------------|
|
|------------------------------|---------------------|------------------------------|
|
||||||
| New release | Project members | Custom notification |
|
| New release | Project members | Custom notification. |
|
||||||
| Project moved | Project members (1) | (1) not disabled |
|
| Project moved | Project members | Any other than disabled. |
|
||||||
| Email changed | User | Security email, always sent. |
|
| 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 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 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 SSH key added | User | Security email, always sent. |
|
||||||
| New user created | User | Sent on user creation, except for OmniAuth (LDAP)|
|
| 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 | 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 |
|
| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user. |
|
||||||
| Personal access tokens expiring soon <!-- Do not delete or lint this instance of future tense --> | User | Security email, always sent. |
|
| Personal access tokens expiring soon | User | Security email, always sent. |
|
||||||
| Personal access tokens have expired | 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 |
|
| 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 |
|
| 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. |
|
| Two-factor authentication disabled | User | Security email, always sent. |
|
||||||
| User added to group | User | Sent when user is added to group |
|
| 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 project | User | Sent when user is added to project. |
|
||||||
|
|
||||||
## Notifications on issues, merge requests, and epics
|
## 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
|
To enable notifications on a specific issue, merge request, or epic, you must turn on the
|
||||||
**Notifications** toggle in the right sidebar.
|
**Notifications** toggle in the right sidebar.
|
||||||
|
|
||||||
- To subscribe, **turn on** if you are not a participant in the discussion, but want to receive
|
- To subscribe, **turn on** if you are not a participant in the discussion, but want to receive
|
||||||
notifications on each update.
|
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
|
- 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.
|
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).
|
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
|
### Notification events on issues, merge requests, and epics
|
||||||
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.
|
|
||||||
|
|
||||||
The following table presents the events that generate notifications for issues, merge requests, and
|
The following table presents the events that generate notifications for issues, merge requests, and
|
||||||
epics:
|
epics:
|
||||||
|
|
||||||
| Event | Sent to |
|
| Event | Sent to |
|
||||||
|------------------------|---------|
|
|------------------------|---------|
|
||||||
| Change milestone issue | 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 |
|
| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected. |
|
||||||
| Close epic | |
|
| Close epic | |
|
||||||
| Close issue | |
|
| Close issue | |
|
||||||
| Close merge request | |
|
| Close merge request | |
|
||||||
| Due issue | Participants and Custom notification level with this event selected |
|
| Due issue | Participants and Custom notification level with this event selected. |
|
||||||
| Failed pipeline | The author of the pipeline |
|
| 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 |
|
| 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 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 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 |
|
| 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 |
|
| 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 epic | |
|
||||||
| New issue | |
|
| New issue | |
|
||||||
| New merge request | |
|
| New merge request | |
|
||||||
| Push to merge request | Participants 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, and Custom notification level with this event selected, plus the old assignee |
|
| Reassign issue | Participants, Watchers, Subscribers, Custom notification level with this event selected, and the old assignee. |
|
||||||
| Reassign merge request | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus 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 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 |
|
| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected. |
|
||||||
| Reopen epic | |
|
| Reopen epic | |
|
||||||
| Reopen issue | |
|
| Reopen issue | |
|
||||||
| Reopen merge request | |
|
| 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
|
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.
|
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 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,
|
If a user has also set the merge request to automatically merge when pipeline succeeds,
|
||||||
then that user is also notified.
|
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
|
## Notifications on designs
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217095) in GitLab 13.6.
|
> [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:
|
The participants are:
|
||||||
|
|
||||||
|
@ -288,7 +292,9 @@ The participants are:
|
||||||
|
|
||||||
If you no longer wish to receive any email notifications:
|
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. Clear the **Receive product marketing emails** checkbox.
|
||||||
1. Set your **Global notification level** to **Disabled**.
|
1. Set your **Global notification level** to **Disabled**.
|
||||||
1. Clear the **Receive notifications about your own activity** checkbox.
|
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).
|
[can still email you](../../tools/email.md).
|
||||||
To unsubscribe, select the unsubscribe link in one of these emails.
|
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:
|
The following table lists all GitLab-specific email headers:
|
||||||
|
|
||||||
| Header | Description |
|
| Header | Description |
|
||||||
|------------------------------------|-------------------------------------------------------------------------|
|
|------------------------------------|-------------------------------------------------------------------------|
|
||||||
| `X-GitLab-Group-Id` **(PREMIUM)** | The group's ID. Only present on notification emails for epics. |
|
| `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-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. |
|
|
||||||
| `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-(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-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-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-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
|
### 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`
|
- `own_activity`
|
||||||
- `assigned`
|
- `assigned`
|
||||||
- `mentioned`
|
- `mentioned`
|
||||||
|
|
||||||
The reason for the notification is also included in the footer of the notification email. For example an email with the
|
The reason for the notification is also included in the footer of the notification email.
|
||||||
reason `assigned` has this sentence in the footer:
|
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 <configured GitLab hostname>.`
|
> You are receiving this email because you have been assigned an item on \<configured GitLab hostname>.
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
For example, an alert notification email can have one of
|
For example, an alert notification email can have one of
|
||||||
[the alert's](../../operations/incident_management/alerts.md) statuses:
|
[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_acknowledged`
|
||||||
- `alert_resolved`
|
- `alert_resolved`
|
||||||
- `alert_ignored`
|
- `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).
|
||||||
|
|
|
@ -89,7 +89,7 @@ RSpec.describe 'Profile > Password' do
|
||||||
shared_examples 'user enters an incorrect current password' do
|
shared_examples 'user enters an incorrect current password' do
|
||||||
subject do
|
subject do
|
||||||
page.within '.update-password' 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)
|
fill_passwords(new_password, new_password)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -131,7 +131,7 @@ RSpec.describe 'Profile > Password' do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when current password is incorrect' do
|
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'
|
it_behaves_like 'user enters an incorrect current password'
|
||||||
end
|
end
|
||||||
|
@ -139,7 +139,7 @@ RSpec.describe 'Profile > Password' do
|
||||||
context 'when the password reset is successful' do
|
context 'when the password reset is successful' do
|
||||||
subject do
|
subject do
|
||||||
page.within '.update-password' 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)
|
fill_passwords(new_password, new_password)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -169,8 +169,8 @@ RSpec.describe 'Profile > Password' do
|
||||||
|
|
||||||
expect(current_path).to eq new_profile_password_path
|
expect(current_path).to eq new_profile_password_path
|
||||||
|
|
||||||
fill_in :user_current_password, with: user.password
|
fill_in :user_password, with: user.password
|
||||||
fill_in :user_password, with: '12345678'
|
fill_in :user_new_password, with: '12345678'
|
||||||
fill_in :user_password_confirmation, with: '12345678'
|
fill_in :user_password_confirmation, with: '12345678'
|
||||||
click_button 'Set new password'
|
click_button 'Set new password'
|
||||||
|
|
||||||
|
|
|
@ -866,8 +866,8 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
|
||||||
|
|
||||||
expect(current_path).to eq(new_profile_password_path)
|
expect(current_path).to eq(new_profile_password_path)
|
||||||
|
|
||||||
fill_in 'user_current_password', with: '12345678'
|
fill_in 'user_password', with: '12345678'
|
||||||
fill_in 'user_password', with: 'new password'
|
fill_in 'user_new_password', with: 'new password'
|
||||||
fill_in 'user_password_confirmation', with: 'new password'
|
fill_in 'user_password_confirmation', with: 'new password'
|
||||||
click_button 'Set new password'
|
click_button 'Set new password'
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,6 @@ import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_e
|
||||||
describe('Pipeline editor empty state', () => {
|
describe('Pipeline editor empty state', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
const defaultProvide = {
|
const defaultProvide = {
|
||||||
glFeatures: {
|
|
||||||
pipelineEditorEmptyStateAction: false,
|
|
||||||
},
|
|
||||||
emptyStateIllustrationPath: 'my/svg/path',
|
emptyStateIllustrationPath: 'my/svg/path',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,24 +48,6 @@ describe('Pipeline editor empty state', () => {
|
||||||
expect(findFileNav().exists()).toBe(true);
|
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', () => {
|
it('renders a CTA button', () => {
|
||||||
expect(findConfirmButton().exists()).toBe(true);
|
expect(findConfirmButton().exists()).toBe(true);
|
||||||
expect(findConfirmButton().text()).toBe(wrapper.vm.$options.i18n.btnText);
|
expect(findConfirmButton().text()).toBe(wrapper.vm.$options.i18n.btnText);
|
||||||
|
|
|
@ -22,7 +22,6 @@ import {
|
||||||
mockCiConfigPath,
|
mockCiConfigPath,
|
||||||
mockCiConfigQueryResponse,
|
mockCiConfigQueryResponse,
|
||||||
mockBlobContentQueryResponse,
|
mockBlobContentQueryResponse,
|
||||||
mockBlobContentQueryResponseEmptyCiFile,
|
|
||||||
mockBlobContentQueryResponseNoCiFile,
|
mockBlobContentQueryResponseNoCiFile,
|
||||||
mockCiYml,
|
mockCiYml,
|
||||||
mockCommitSha,
|
mockCommitSha,
|
||||||
|
@ -43,9 +42,6 @@ const MockSourceEditor = {
|
||||||
const mockProvide = {
|
const mockProvide = {
|
||||||
ciConfigPath: mockCiConfigPath,
|
ciConfigPath: mockCiConfigPath,
|
||||||
defaultBranch: mockDefaultBranch,
|
defaultBranch: mockDefaultBranch,
|
||||||
glFeatures: {
|
|
||||||
pipelineEditorEmptyStateAction: false,
|
|
||||||
},
|
|
||||||
projectFullPath: mockProjectFullPath,
|
projectFullPath: mockProjectFullPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -221,37 +217,12 @@ describe('Pipeline editor app component', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with an empty CI config file', () => {
|
describe('with no CI config setup', () => {
|
||||||
describe('with empty state feature flag on', () => {
|
it('user can click on CTA button to get started', async () => {
|
||||||
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 () => {
|
|
||||||
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseNoCiFile);
|
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseNoCiFile);
|
||||||
mockLatestCommitShaQuery.mockResolvedValue(mockEmptyCommitShaResults);
|
mockLatestCommitShaQuery.mockResolvedValue(mockEmptyCommitShaResults);
|
||||||
|
|
||||||
await createComponentWithApollo({
|
await createComponentWithApollo();
|
||||||
provide: {
|
|
||||||
glFeatures: {
|
|
||||||
pipelineEditorEmptyStateAction: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(findEmptyState().exists()).toBe(true);
|
expect(findEmptyState().exists()).toBe(true);
|
||||||
expect(findTextEditor().exists()).toBe(false);
|
expect(findTextEditor().exists()).toBe(false);
|
||||||
|
|
|
@ -1290,7 +1290,7 @@ RSpec.describe Ci::Build do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'state transition as a deployable' do
|
shared_examples_for 'state transition as a deployable' do
|
||||||
subject { build.send(event) }
|
subject { build.send(event) }
|
||||||
|
|
||||||
let!(:build) { create(:ci_build, :with_deployment, :start_review_app, project: project, pipeline: pipeline) }
|
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
|
||||||
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
|
describe '#on_stop' do
|
||||||
subject { build.on_stop }
|
subject { build.on_stop }
|
||||||
|
|
||||||
|
@ -3948,7 +3978,7 @@ RSpec.describe Ci::Build do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can drop the build' do
|
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
|
expect { build.drop! }.not_to raise_error
|
||||||
|
|
||||||
|
|
|
@ -765,7 +765,7 @@ RSpec.describe Deployment do
|
||||||
expect(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
|
expect(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
|
||||||
expect(Deployments::HooksWorker).to receive(:perform_async)
|
expect(Deployments::HooksWorker).to receive(:perform_async)
|
||||||
|
|
||||||
deploy.update_status('success')
|
expect(deploy.update_status('success')).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates finished_at when transitioning to a finished status' do
|
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)
|
expect(deploy.read_attribute(:finished_at)).to eq(Time.current)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
describe '#valid_sha' do
|
describe '#valid_sha' do
|
||||||
|
|
|
@ -376,6 +376,16 @@ RSpec.describe API::Deployments do
|
||||||
expect(json_response['status']).to eq('success')
|
expect(json_response['status']).to eq('success')
|
||||||
end
|
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
|
it 'links merge requests when the deployment status changes to success', :sidekiq_inline do
|
||||||
mr = create(
|
mr = create(
|
||||||
:merge_request,
|
:merge_request,
|
||||||
|
|
|
@ -34,9 +34,11 @@ RSpec.describe Deployments::UpdateService do
|
||||||
expect(deploy).to be_canceled
|
expect(deploy).to be_canceled
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises ArgumentError if the status is invalid' do
|
it 'does not change the state if the status is invalid' do
|
||||||
expect { described_class.new(deploy, status: 'kittens').execute }
|
expect(described_class.new(deploy, status: 'kittens').execute)
|
||||||
.to raise_error(ArgumentError)
|
.to be_falsy
|
||||||
|
|
||||||
|
expect(deploy).to be_created
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'links merge requests when changing the status to success', :sidekiq_inline do
|
it 'links merge requests when changing the status to success', :sidekiq_inline do
|
||||||
|
|
Loading…
Reference in a new issue