Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
bd06d7cd6c
commit
e40061efd4
|
|
@ -8,3 +8,9 @@ glfm-verify:
|
||||||
script:
|
script:
|
||||||
- !reference [.base-script, script]
|
- !reference [.base-script, script]
|
||||||
- bundle exec scripts/glfm/verify-all-generated-files-are-up-to-date.rb
|
- bundle exec scripts/glfm/verify-all-generated-files-are-up-to-date.rb
|
||||||
|
artifacts:
|
||||||
|
name: changed-files
|
||||||
|
when: on_failure
|
||||||
|
expire_in: 31d
|
||||||
|
paths:
|
||||||
|
- glfm_specification/
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
038b442dc21c71a69ad170a61ce79a12a74fb725
|
d4bc56074d6151875943c1b128b89b4f554af68a
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@ export const I18N = {
|
||||||
'BranchRules|Approvals to ensure separation of duties for new merge requests. %{linkStart}Lean more.%{linkEnd}',
|
'BranchRules|Approvals to ensure separation of duties for new merge requests. %{linkStart}Lean more.%{linkEnd}',
|
||||||
),
|
),
|
||||||
statusChecksTitle: s__('BranchRules|Status checks'),
|
statusChecksTitle: s__('BranchRules|Status checks'),
|
||||||
|
statusChecksDescription: s__(
|
||||||
|
'BranchRules|Check for a status response in merge requests. Failures do not block merges. %{linkStart}Lean more.%{linkEnd}',
|
||||||
|
),
|
||||||
|
statusChecksLinkTitle: s__('BranchRules|Manage in Status checks'),
|
||||||
|
statusChecksHeader: s__('BranchRules|Status checks (%{total})'),
|
||||||
allowedToPushHeader: s__('BranchRules|Allowed to push (%{total})'),
|
allowedToPushHeader: s__('BranchRules|Allowed to push (%{total})'),
|
||||||
allowedToMergeHeader: s__('BranchRules|Allowed to merge (%{total})'),
|
allowedToMergeHeader: s__('BranchRules|Allowed to merge (%{total})'),
|
||||||
approvalsHeader: s__('BranchRules|Required approvals (%{total})'),
|
approvalsHeader: s__('BranchRules|Required approvals (%{total})'),
|
||||||
|
|
@ -40,3 +45,5 @@ export const WILDCARDS_HELP_PATH =
|
||||||
export const PROTECTED_BRANCHES_HELP_PATH = 'user/project/protected_branches';
|
export const PROTECTED_BRANCHES_HELP_PATH = 'user/project/protected_branches';
|
||||||
|
|
||||||
export const APPROVALS_HELP_PATH = 'user/project/merge_requests/approvals/index.md';
|
export const APPROVALS_HELP_PATH = 'user/project/merge_requests/approvals/index.md';
|
||||||
|
|
||||||
|
export const STATUS_CHECKS_HELP_PATH = 'user/project/merge_requests/status_checks.md';
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@ import {
|
||||||
WILDCARDS_HELP_PATH,
|
WILDCARDS_HELP_PATH,
|
||||||
PROTECTED_BRANCHES_HELP_PATH,
|
PROTECTED_BRANCHES_HELP_PATH,
|
||||||
APPROVALS_HELP_PATH,
|
APPROVALS_HELP_PATH,
|
||||||
|
STATUS_CHECKS_HELP_PATH,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
const wildcardsHelpDocLink = helpPagePath(WILDCARDS_HELP_PATH);
|
const wildcardsHelpDocLink = helpPagePath(WILDCARDS_HELP_PATH);
|
||||||
const protectedBranchesHelpDocLink = helpPagePath(PROTECTED_BRANCHES_HELP_PATH);
|
const protectedBranchesHelpDocLink = helpPagePath(PROTECTED_BRANCHES_HELP_PATH);
|
||||||
const approvalsHelpDocLink = helpPagePath(APPROVALS_HELP_PATH);
|
const approvalsHelpDocLink = helpPagePath(APPROVALS_HELP_PATH);
|
||||||
|
const statusChecksHelpDocLink = helpPagePath(STATUS_CHECKS_HELP_PATH);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RuleView',
|
name: 'RuleView',
|
||||||
|
|
@ -24,6 +26,7 @@ export default {
|
||||||
wildcardsHelpDocLink,
|
wildcardsHelpDocLink,
|
||||||
protectedBranchesHelpDocLink,
|
protectedBranchesHelpDocLink,
|
||||||
approvalsHelpDocLink,
|
approvalsHelpDocLink,
|
||||||
|
statusChecksHelpDocLink,
|
||||||
components: { Protection, GlSprintf, GlLink, GlLoadingIcon },
|
components: { Protection, GlSprintf, GlLink, GlLoadingIcon },
|
||||||
inject: {
|
inject: {
|
||||||
projectPath: {
|
projectPath: {
|
||||||
|
|
@ -35,6 +38,9 @@ export default {
|
||||||
approvalRulesPath: {
|
approvalRulesPath: {
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
statusChecksPath: {
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
project: {
|
project: {
|
||||||
|
|
@ -48,6 +54,7 @@ export default {
|
||||||
const branchRule = branchRules.nodes.find((rule) => rule.name === this.branch);
|
const branchRule = branchRules.nodes.find((rule) => rule.name === this.branch);
|
||||||
this.branchProtection = branchRule?.branchProtection;
|
this.branchProtection = branchRule?.branchProtection;
|
||||||
this.approvalRules = branchRule?.approvalRules;
|
this.approvalRules = branchRule?.approvalRules;
|
||||||
|
this.statusChecks = branchRule?.externalStatusChecks || [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -56,6 +63,7 @@ export default {
|
||||||
branch: getParameterByName(BRANCH_PARAM_NAME),
|
branch: getParameterByName(BRANCH_PARAM_NAME),
|
||||||
branchProtection: {},
|
branchProtection: {},
|
||||||
approvalRules: {},
|
approvalRules: {},
|
||||||
|
statusChecks: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -91,6 +99,11 @@ export default {
|
||||||
total,
|
total,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
statusChecksHeader() {
|
||||||
|
return sprintf(this.$options.i18n.statusChecksHeader, {
|
||||||
|
total: this.statusChecks.length,
|
||||||
|
});
|
||||||
|
},
|
||||||
allBranches() {
|
allBranches() {
|
||||||
return this.branch === ALL_BRANCHES_WILDCARD;
|
return this.branch === ALL_BRANCHES_WILDCARD;
|
||||||
},
|
},
|
||||||
|
|
@ -201,6 +214,21 @@ export default {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Status checks -->
|
<!-- Status checks -->
|
||||||
<!-- Follow-up: add status checks section (https://gitlab.com/gitlab-org/gitlab/-/issues/372362) -->
|
<h4 class="gl-mb-1 gl-mt-5">{{ $options.i18n.statusChecksTitle }}</h4>
|
||||||
|
<gl-sprintf :message="$options.i18n.statusChecksDescription">
|
||||||
|
<template #link="{ content }">
|
||||||
|
<gl-link :href="$options.statusChecksHelpDocLink">
|
||||||
|
{{ content }}
|
||||||
|
</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
|
||||||
|
<protection
|
||||||
|
class="gl-mt-3"
|
||||||
|
:header="statusChecksHeader"
|
||||||
|
:header-link-title="$options.i18n.statusChecksLinkTitle"
|
||||||
|
:header-link-href="statusChecksPath"
|
||||||
|
:status-checks="statusChecks"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
statusChecks: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showUsersDivider() {
|
showUsersDivider() {
|
||||||
|
|
@ -95,5 +100,14 @@ export default {
|
||||||
:users="approval.eligibleApprovers.nodes"
|
:users="approval.eligibleApprovers.nodes"
|
||||||
:approvals-required="approval.approvalsRequired"
|
:approvals-required="approval.approvalsRequired"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- Status checks -->
|
||||||
|
<protection-row
|
||||||
|
v-for="(statusCheck, index) in statusChecks"
|
||||||
|
:key="statusCheck.id"
|
||||||
|
:show-divider="index !== 0"
|
||||||
|
:title="statusCheck.name"
|
||||||
|
:status-check-url="statusCheck.externalUrl"
|
||||||
|
/>
|
||||||
</gl-card>
|
</gl-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
|
statusCheckUrl: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
avatarBadgeSrOnlyText() {
|
avatarBadgeSrOnlyText() {
|
||||||
|
|
@ -67,7 +72,7 @@ export default {
|
||||||
class="gl-display-flex gl-align-items-center gl-border-gray-100 gl-mb-4 gl-pt-4 gl-border-t-1"
|
class="gl-display-flex gl-align-items-center gl-border-gray-100 gl-mb-4 gl-pt-4 gl-border-t-1"
|
||||||
:class="{ 'gl-border-t-solid': showDivider }"
|
:class="{ 'gl-border-t-solid': showDivider }"
|
||||||
>
|
>
|
||||||
<div class="gl-display-flex gl-w-half gl-justify-content-space-between gl-align-items-center">
|
<div class="gl-display-flex gl-w-full gl-justify-content-space-between gl-align-items-center">
|
||||||
<div class="gl-mr-7 gl-w-quarter">{{ title }}</div>
|
<div class="gl-mr-7 gl-w-quarter">{{ title }}</div>
|
||||||
|
|
||||||
<gl-avatars-inline
|
<gl-avatars-inline
|
||||||
|
|
@ -94,6 +99,8 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
</gl-avatars-inline>
|
</gl-avatars-inline>
|
||||||
|
|
||||||
|
<div v-if="statusCheckUrl" class="gl-ml-7 gl-flex-grow-1">{{ statusCheckUrl }}</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in accessLevels"
|
v-for="(item, index) in accessLevels"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|
@ -104,7 +111,7 @@ export default {
|
||||||
{{ item.accessLevelDescription }}
|
{{ item.accessLevelDescription }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gl-ml-7 gl-w-quarter">{{ approvalsRequiredTitle }}</div>
|
<div class="gl-ml-7 gl-flex-grow-1">{{ approvalsRequiredTitle }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export default function mountBranchRules(el) {
|
||||||
defaultClient: createDefaultClient(),
|
defaultClient: createDefaultClient(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { projectPath, protectedBranchesPath, approvalRulesPath } = el.dataset;
|
const { projectPath, protectedBranchesPath, approvalRulesPath, statusChecksPath } = el.dataset;
|
||||||
|
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el,
|
el,
|
||||||
|
|
@ -23,6 +23,7 @@ export default function mountBranchRules(el) {
|
||||||
projectPath,
|
projectPath,
|
||||||
protectedBranchesPath,
|
protectedBranchesPath,
|
||||||
approvalRulesPath,
|
approvalRulesPath,
|
||||||
|
statusChecksPath,
|
||||||
},
|
},
|
||||||
render(h) {
|
render(h) {
|
||||||
return h(View);
|
return h(View);
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ class SystemHook < WebHook
|
||||||
:merge_request_hooks
|
:merge_request_hooks
|
||||||
]
|
]
|
||||||
|
|
||||||
default_value_for :push_events, false
|
attribute :push_events, default: false
|
||||||
default_value_for :repository_update_events, true
|
attribute :repository_update_events, default: true
|
||||||
default_value_for :merge_requests_events, false
|
attribute :merge_requests_events, default: false
|
||||||
|
|
||||||
validates :url, system_hook_url: true
|
validates :url, system_hook_url: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ class Label < ApplicationRecord
|
||||||
|
|
||||||
DEFAULT_COLOR = ::Gitlab::Color.of('#6699cc')
|
DEFAULT_COLOR = ::Gitlab::Color.of('#6699cc')
|
||||||
|
|
||||||
attribute :color, ::Gitlab::Database::Type::Color.new
|
attribute :color, ::Gitlab::Database::Type::Color.new, default: DEFAULT_COLOR
|
||||||
default_value_for :color, DEFAULT_COLOR
|
|
||||||
|
|
||||||
has_many :lists, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
has_many :lists, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
||||||
has_many :priorities, class_name: 'LabelPriority'
|
has_many :priorities, class_name: 'LabelPriority'
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ class ProjectMember < Member
|
||||||
delegate :namespace_id, to: :project
|
delegate :namespace_id, to: :project
|
||||||
|
|
||||||
# Make sure project member points only to project as it source
|
# Make sure project member points only to project as it source
|
||||||
default_value_for :source_type, SOURCE_TYPE
|
attribute :source_type, default: SOURCE_TYPE
|
||||||
validates :source_type, format: { with: SOURCE_TYPE_FORMAT }
|
validates :source_type, format: { with: SOURCE_TYPE_FORMAT }
|
||||||
default_scope { where(source_type: SOURCE_TYPE) } # rubocop:disable Cop/DefaultScope
|
default_scope { where(source_type: SOURCE_TYPE) } # rubocop:disable Cop/DefaultScope
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ module Ml
|
||||||
has_many :params, class_name: 'Ml::CandidateParam'
|
has_many :params, class_name: 'Ml::CandidateParam'
|
||||||
has_many :latest_metrics, -> { latest }, class_name: 'Ml::CandidateMetric', inverse_of: :candidate
|
has_many :latest_metrics, -> { latest }, class_name: 'Ml::CandidateMetric', inverse_of: :candidate
|
||||||
|
|
||||||
default_value_for(:iid) { SecureRandom.uuid }
|
attribute :iid, default: -> { SecureRandom.uuid }
|
||||||
|
|
||||||
scope :including_metrics_and_params, -> { includes(:latest_metrics, :params) }
|
scope :including_metrics_and_params, -> { includes(:latest_metrics, :params) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class Note < ApplicationRecord
|
||||||
# Attribute used to determine whether keep_around_commits will be skipped for diff notes.
|
# Attribute used to determine whether keep_around_commits will be skipped for diff notes.
|
||||||
attr_accessor :skip_keep_around_commits
|
attr_accessor :skip_keep_around_commits
|
||||||
|
|
||||||
default_value_for :system, false
|
attribute :system, default: false
|
||||||
|
|
||||||
attr_mentionable :note, pipeline: :note
|
attr_mentionable :note, pipeline: :note
|
||||||
participant :author
|
participant :author
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ module Operations
|
||||||
|
|
||||||
has_internal_id :iid, scope: :project
|
has_internal_id :iid, scope: :project
|
||||||
|
|
||||||
default_value_for :active, true
|
attribute :active, default: true
|
||||||
default_value_for :version, :new_version_flag
|
attribute :version, default: :new_version_flag
|
||||||
|
|
||||||
# strategies exists only for the second version
|
# strategies exists only for the second version
|
||||||
has_many :strategies, class_name: 'Operations::FeatureFlags::Strategy'
|
has_many :strategies, class_name: 'Operations::FeatureFlags::Strategy'
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ class ProjectStatistics < ApplicationRecord
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
belongs_to :namespace
|
belongs_to :namespace
|
||||||
|
|
||||||
default_value_for :wiki_size, 0
|
attribute :wiki_size, default: 0
|
||||||
default_value_for :snippets_size, 0
|
attribute :snippets_size, default: 0
|
||||||
|
|
||||||
counter_attribute :build_artifacts_size
|
counter_attribute :build_artifacts_size
|
||||||
|
|
||||||
|
|
@ -95,8 +95,7 @@ class ProjectStatistics < ApplicationRecord
|
||||||
# and the column can be nil.
|
# and the column can be nil.
|
||||||
# This means that, when the columns were added, all rows had nil
|
# This means that, when the columns were added, all rows had nil
|
||||||
# values on them.
|
# values on them.
|
||||||
# Therefore, any call to any of those methods will return nil instead
|
# Therefore, any call to any of those methods will return nil instead of 0.
|
||||||
# of 0, because `default_value_for` works with new records, not existing ones.
|
|
||||||
#
|
#
|
||||||
# These two methods provide consistency and avoid returning nil.
|
# These two methods provide consistency and avoid returning nil.
|
||||||
def wiki_size
|
def wiki_size
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@ module TimeTracking
|
||||||
|
|
||||||
DEFAULT_COLOR = ::Gitlab::Color.of('#6699cc')
|
DEFAULT_COLOR = ::Gitlab::Color.of('#6699cc')
|
||||||
|
|
||||||
attribute :color, ::Gitlab::Database::Type::Color.new
|
attribute :color, ::Gitlab::Database::Type::Color.new, default: DEFAULT_COLOR
|
||||||
default_value_for :color, DEFAULT_COLOR
|
|
||||||
|
|
||||||
def self.find_by_name(namespace_id, name)
|
def self.find_by_name(namespace_id, name)
|
||||||
where(namespace: namespace_id)
|
where(namespace: namespace_id)
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,15 @@ module MergeRequests
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_create(issuable)
|
def after_create(issuable)
|
||||||
issuable.mark_as_preparing
|
current_user_id = current_user.id
|
||||||
|
|
||||||
# Add new items to MergeRequests::AfterCreateService if they can
|
issuable.run_after_commit do
|
||||||
# be performed in Sidekiq
|
# Add new items to MergeRequests::AfterCreateService if they can
|
||||||
NewMergeRequestWorker.perform_async(issuable.id, current_user.id)
|
# be performed in Sidekiq
|
||||||
|
NewMergeRequestWorker.perform_async(issuable.id, current_user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
issuable.mark_as_preparing
|
||||||
|
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
@ -64,4 +68,4 @@ module MergeRequests
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
MergeRequests::CreateService.include_mod_with('MergeRequests::CreateService')
|
MergeRequests::CreateService.prepend_mod_with('MergeRequests::CreateService')
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
%h3.gl-mb-5= s_('BranchRules|Branch rules details')
|
%h3.gl-mb-5= s_('BranchRules|Branch rules details')
|
||||||
|
|
||||||
#js-branch-rules{ data: { project_path: @project.full_path, protected_branches_path: project_settings_repository_path(@project, anchor: 'js-protected-branches-settings'), approval_rules_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-approval-settings') } }
|
#js-branch-rules{ data: { project_path: @project.full_path, protected_branches_path: project_settings_repository_path(@project, anchor: 'js-protected-branches-settings'), approval_rules_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-approval-settings'), status_checks_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-settings') } }
|
||||||
|
|
|
||||||
|
|
@ -6921,6 +6921,9 @@ msgstr ""
|
||||||
msgid "BranchRules|Branch rules details"
|
msgid "BranchRules|Branch rules details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "BranchRules|Check for a status response in merge requests. Failures do not block merges. %{linkStart}Lean more.%{linkEnd}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BranchRules|Create wildcard: %{searchTerm}"
|
msgid "BranchRules|Create wildcard: %{searchTerm}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -6945,6 +6948,9 @@ msgstr ""
|
||||||
msgid "BranchRules|Manage in Protected Branches"
|
msgid "BranchRules|Manage in Protected Branches"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "BranchRules|Manage in Status checks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BranchRules|No data to display"
|
msgid "BranchRules|No data to display"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -6975,6 +6981,9 @@ msgstr ""
|
||||||
msgid "BranchRules|Status checks"
|
msgid "BranchRules|Status checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "BranchRules|Status checks (%{total})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BranchRules|Target Branch"
|
msgid "BranchRules|Target Branch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -36915,6 +36924,9 @@ msgstr ""
|
||||||
msgid "See our website for help"
|
msgid "See our website for help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "See the Geo troubleshooting documentation to learn more: %{docs_url}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "See the affected projects in the GitLab admin panel"
|
msgid "See the affected projects in the GitLab admin panel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,20 @@ module Glfm
|
||||||
|
|
||||||
return if verify_cmd_output.empty?
|
return if verify_cmd_output.empty?
|
||||||
|
|
||||||
raise "The following files were modified by running GLFM scripts. Please review, verify, and commit " \
|
warn(
|
||||||
"the changes:\n#{verify_cmd_output}"
|
"ERROR: The following files were modified by running GLFM scripts. Please review, verify, and commit " \
|
||||||
|
"the changes:\n#{verify_cmd_output}\n"
|
||||||
|
)
|
||||||
|
warn("See the CI artifacts for the modified version of the files.\n")
|
||||||
|
|
||||||
|
warn("This is the output of `git diff`:\n")
|
||||||
|
diff_output = run_external_cmd('git diff')
|
||||||
|
warn(diff_output)
|
||||||
|
|
||||||
|
# Ensure that the diff output is flushed and output before we raise and exit.
|
||||||
|
$stderr.flush
|
||||||
|
|
||||||
|
raise('ERROR: The generated files are not up to date.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ describe('View branch rules', () => {
|
||||||
const projectPath = 'test/testing';
|
const projectPath = 'test/testing';
|
||||||
const protectedBranchesPath = 'protected/branches';
|
const protectedBranchesPath = 'protected/branches';
|
||||||
const approvalRulesPath = 'approval/rules';
|
const approvalRulesPath = 'approval/rules';
|
||||||
|
const statusChecksPath = 'status/checks';
|
||||||
const branchProtectionsMockRequestHandler = jest
|
const branchProtectionsMockRequestHandler = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockResolvedValue(branchProtectionsMockResponse);
|
.mockResolvedValue(branchProtectionsMockResponse);
|
||||||
|
|
@ -43,7 +44,7 @@ describe('View branch rules', () => {
|
||||||
|
|
||||||
wrapper = shallowMountExtended(RuleView, {
|
wrapper = shallowMountExtended(RuleView, {
|
||||||
apolloProvider: fakeApollo,
|
apolloProvider: fakeApollo,
|
||||||
provide: { projectPath, protectedBranchesPath, approvalRulesPath },
|
provide: { projectPath, protectedBranchesPath, approvalRulesPath, statusChecksPath },
|
||||||
});
|
});
|
||||||
|
|
||||||
await waitForPromises();
|
await waitForPromises();
|
||||||
|
|
@ -59,6 +60,7 @@ describe('View branch rules', () => {
|
||||||
const findBranchProtections = () => wrapper.findAllComponents(Protection);
|
const findBranchProtections = () => wrapper.findAllComponents(Protection);
|
||||||
const findForcePushTitle = () => wrapper.findByText(I18N.allowForcePushDescription);
|
const findForcePushTitle = () => wrapper.findByText(I18N.allowForcePushDescription);
|
||||||
const findApprovalsTitle = () => wrapper.findByText(I18N.approvalsTitle);
|
const findApprovalsTitle = () => wrapper.findByText(I18N.approvalsTitle);
|
||||||
|
const findStatusChecksTitle = () => wrapper.findByText(I18N.statusChecksTitle);
|
||||||
|
|
||||||
it('gets the branch param from url and renders it in the view', () => {
|
it('gets the branch param from url and renders it in the view', () => {
|
||||||
expect(util.getParameterByName).toHaveBeenCalledWith('branch');
|
expect(util.getParameterByName).toHaveBeenCalledWith('branch');
|
||||||
|
|
@ -111,4 +113,16 @@ describe('View branch rules', () => {
|
||||||
approvals: approvalRulesMock,
|
approvals: approvalRulesMock,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders a branch protection component for status checks', () => {
|
||||||
|
expect(findStatusChecksTitle().exists()).toBe(true);
|
||||||
|
|
||||||
|
expect(findBranchProtections().at(3).props()).toMatchObject({
|
||||||
|
// status checks BE/FE integration will happen on a follow-up, so we expect data to be empty
|
||||||
|
header: sprintf(I18N.statusChecksHeader, { total: 0 }),
|
||||||
|
headerLinkHref: statusChecksPath,
|
||||||
|
headerLinkTitle: I18N.statusChecksLinkTitle,
|
||||||
|
statusChecks: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ export const approvalRulesMock = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const statusChecksRulesMock = [
|
||||||
|
{ __typename: 'StatusCheckRule', id: '123', name: 'test', externalUrl: 'https://test.test' },
|
||||||
|
{ __typename: 'StatusCheckRule', id: '456', name: 'test 2', externalUrl: 'https://test2.test2' },
|
||||||
|
];
|
||||||
|
|
||||||
export const protectionPropsMock = {
|
export const protectionPropsMock = {
|
||||||
header: 'Test protection',
|
header: 'Test protection',
|
||||||
headerLinkTitle: 'Test link title',
|
headerLinkTitle: 'Test link title',
|
||||||
|
|
@ -64,6 +69,7 @@ export const protectionPropsMock = {
|
||||||
users: usersMock,
|
users: usersMock,
|
||||||
groups: groupsMock,
|
groups: groupsMock,
|
||||||
approvals: approvalRulesMock,
|
approvals: approvalRulesMock,
|
||||||
|
statusChecks: statusChecksRulesMock,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const protectionRowPropsMock = {
|
export const protectionRowPropsMock = {
|
||||||
|
|
@ -71,6 +77,7 @@ export const protectionRowPropsMock = {
|
||||||
users: usersMock,
|
users: usersMock,
|
||||||
accessLevels: accessLevelsMock,
|
accessLevels: accessLevelsMock,
|
||||||
approvalsRequired,
|
approvalsRequired,
|
||||||
|
statusCheckUrl: statusChecksRulesMock[0].externalUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const accessLevelsMockResponse = [
|
export const accessLevelsMockResponse = [
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ describe('Branch rule protection row', () => {
|
||||||
const findAccessLevels = () => wrapper.findAllByTestId('access-level');
|
const findAccessLevels = () => wrapper.findAllByTestId('access-level');
|
||||||
const findApprovalsRequired = () =>
|
const findApprovalsRequired = () =>
|
||||||
wrapper.findByText(`${protectionRowPropsMock.approvalsRequired} approvals required`);
|
wrapper.findByText(`${protectionRowPropsMock.approvalsRequired} approvals required`);
|
||||||
|
const findStatusChecksUrl = () => wrapper.findByText(protectionRowPropsMock.statusCheckUrl);
|
||||||
|
|
||||||
it('renders a title', () => {
|
it('renders a title', () => {
|
||||||
expect(findTitle().exists()).toBe(true);
|
expect(findTitle().exists()).toBe(true);
|
||||||
|
|
@ -68,4 +69,8 @@ describe('Branch rule protection row', () => {
|
||||||
it('renders the number of approvals required', () => {
|
it('renders the number of approvals required', () => {
|
||||||
expect(findApprovalsRequired().exists()).toBe(true);
|
expect(findApprovalsRequired().exists()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders status checks URL', () => {
|
||||||
|
expect(findStatusChecksUrl().exists()).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -65,4 +65,15 @@ describe('Branch rule protection', () => {
|
||||||
approvalsRequired: approval.approvalsRequired,
|
approvalsRequired: approval.approvalsRequired,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders a protection row for status checks', () => {
|
||||||
|
const statusCheck = protectionPropsMock.statusChecks[0];
|
||||||
|
expect(findProtectionRows().at(4).props()).toMatchObject({
|
||||||
|
title: statusCheck.name,
|
||||||
|
showDivider: false,
|
||||||
|
statusCheckUrl: statusCheck.externalUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(findProtectionRows().at(5).props('showDivider')).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ require "spec_helper"
|
||||||
|
|
||||||
RSpec.describe SystemHook do
|
RSpec.describe SystemHook do
|
||||||
context 'default attributes' do
|
context 'default attributes' do
|
||||||
let(:system_hook) { build(:system_hook) }
|
let(:system_hook) { described_class.new }
|
||||||
|
|
||||||
it 'sets defined default parameters' do
|
it 'sets defined default parameters' do
|
||||||
attrs = {
|
attrs = {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ RSpec.describe ProjectMember do
|
||||||
it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.values) }
|
it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.values) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'default values' do
|
||||||
|
it { expect(described_class.new.source_type).to eq('Project') }
|
||||||
|
end
|
||||||
|
|
||||||
describe 'delegations' do
|
describe 'delegations' do
|
||||||
it { is_expected.to delegate_method(:namespace_id).to(:project) }
|
it { is_expected.to delegate_method(:namespace_id).to(:project) }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,8 @@ RSpec.describe Ml::Candidate, factory_default: :keep do
|
||||||
it { is_expected.to eq("/ml_candidate_#{candidate.iid}/-/") }
|
it { is_expected.to eq("/ml_candidate_#{candidate.iid}/-/") }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#new' do
|
describe 'default values' do
|
||||||
it 'iid is not null' do
|
it { expect(described_class.new.iid).to be_present }
|
||||||
expect(candidate.iid).not_to be_nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#by_project_id_and_iid' do
|
describe '#by_project_id_and_iid' do
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@ RSpec.describe Note do
|
||||||
it { is_expected.to include_module(Sortable) }
|
it { is_expected.to include_module(Sortable) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'default values' do
|
||||||
|
it { expect(described_class.new).not_to be_system }
|
||||||
|
end
|
||||||
|
|
||||||
describe 'validation' do
|
describe 'validation' do
|
||||||
it { is_expected.to validate_length_of(:note).is_at_most(1_000_000) }
|
it { is_expected.to validate_length_of(:note).is_at_most(1_000_000) }
|
||||||
it { is_expected.to validate_presence_of(:note) }
|
it { is_expected.to validate_presence_of(:note) }
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ RSpec.describe Operations::FeatureFlag do
|
||||||
it { is_expected.to have_many(:strategies) }
|
it { is_expected.to have_many(:strategies) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'default values' do
|
||||||
|
it { expect(described_class.new).to be_active }
|
||||||
|
it { expect(described_class.new.version).to eq('new_version_flag') }
|
||||||
|
end
|
||||||
|
|
||||||
describe '.reference_pattern' do
|
describe '.reference_pattern' do
|
||||||
subject { described_class.reference_pattern }
|
subject { described_class.reference_pattern }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ RSpec.describe TimeTracking::TimelogCategory, type: :model do
|
||||||
it { is_expected.to belong_to(:namespace).with_foreign_key('namespace_id') }
|
it { is_expected.to belong_to(:namespace).with_foreign_key('namespace_id') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'default values' do
|
||||||
|
it { expect(described_class.new.color).to eq(described_class::DEFAULT_COLOR) }
|
||||||
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
subject { create(:timelog_category) }
|
subject { create(:timelog_category) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,13 @@ RSpec.describe Glfm::VerifyAllGeneratedFilesAreUpToDate, '#process' do
|
||||||
before do
|
before do
|
||||||
# Simulate a clean repo, then simulate changes to generated files
|
# Simulate a clean repo, then simulate changes to generated files
|
||||||
allow(subject).to receive(:run_external_cmd).twice.with(verify_cmd).and_return('', "M #{snapshots_path}")
|
allow(subject).to receive(:run_external_cmd).twice.with(verify_cmd).and_return('', "M #{snapshots_path}")
|
||||||
|
allow(subject).to receive(:run_external_cmd).with('git diff')
|
||||||
|
allow(subject).to receive(:warn).and_call_original
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error', :unlimited_max_formatted_output_length do
|
it 'raises an error', :unlimited_max_formatted_output_length do
|
||||||
expect { subject.process }.to raise_error(/following files were modified.*#{snapshots_path}/m)
|
expect(subject).to receive(:warn).with(/following files were modified.*#{snapshots_path}/m)
|
||||||
|
expect { subject.process }.to raise_error(/The generated files are not up to date/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,12 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
|
||||||
it_behaves_like 'reviewer_ids filter' do
|
it_behaves_like 'reviewer_ids filter' do
|
||||||
let(:execute) { service.execute }
|
let(:execute) { service.execute }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when called in a transaction' do
|
||||||
|
it 'does not raise an error' do
|
||||||
|
expect { MergeRequest.transaction { described_class.new(project: project, current_user: user, params: opts).execute } }.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'issuable record that supports quick actions' do
|
it_behaves_like 'issuable record that supports quick actions' do
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue