Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
71d6b9014b
commit
21b8ed2e35
|
@ -116,6 +116,7 @@ module Projects
|
||||||
|
|
||||||
def project_params_attributes
|
def project_params_attributes
|
||||||
[
|
[
|
||||||
|
:issue_branch_template,
|
||||||
:default_branch,
|
:default_branch,
|
||||||
:autoclose_referenced_issues
|
:autoclose_referenced_issues
|
||||||
]
|
]
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Issue < ApplicationRecord
|
||||||
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
|
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
|
||||||
|
|
||||||
SORTING_PREFERENCE_FIELD = :issues_sort
|
SORTING_PREFERENCE_FIELD = :issues_sort
|
||||||
|
MAX_BRANCH_TEMPLATE = 255
|
||||||
|
|
||||||
# Types of issues that should be displayed on issue lists across the app
|
# Types of issues that should be displayed on issue lists across the app
|
||||||
# for example, project issues list, group issues list, and issues dashboard.
|
# for example, project issues list, group issues list, and issues dashboard.
|
||||||
|
@ -394,10 +395,21 @@ class Issue < ApplicationRecord
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_branch_name(*args)
|
def self.to_branch_name(id, title, project: nil)
|
||||||
branch_name = args.map(&:to_s).each_with_index.map do |arg, i|
|
params = {
|
||||||
arg.parameterize(preserve_case: i == 0).presence
|
'id' => id.to_s.parameterize(preserve_case: true),
|
||||||
end.compact.join('-')
|
'title' => title.to_s.parameterize
|
||||||
|
}
|
||||||
|
template = project&.issue_branch_template
|
||||||
|
|
||||||
|
branch_name =
|
||||||
|
if template.present?
|
||||||
|
Gitlab::StringPlaceholderReplacer.replace_string_placeholders(template, /(#{params.keys.join('|')})/) do |arg|
|
||||||
|
params[arg]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
params.values.select(&:present?).join('-')
|
||||||
|
end
|
||||||
|
|
||||||
if branch_name.length > 100
|
if branch_name.length > 100
|
||||||
truncated_string = branch_name[0, 100]
|
truncated_string = branch_name[0, 100]
|
||||||
|
@ -475,7 +487,7 @@ class Issue < ApplicationRecord
|
||||||
if self.confidential?
|
if self.confidential?
|
||||||
"#{iid}-confidential-issue"
|
"#{iid}-confidential-issue"
|
||||||
else
|
else
|
||||||
self.class.to_branch_name(iid, title)
|
self.class.to_branch_name(iid, title, project: project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -491,6 +491,7 @@ class Project < ApplicationRecord
|
||||||
to: :project_setting
|
to: :project_setting
|
||||||
delegate :merge_commit_template, :merge_commit_template=, to: :project_setting, allow_nil: true
|
delegate :merge_commit_template, :merge_commit_template=, to: :project_setting, allow_nil: true
|
||||||
delegate :squash_commit_template, :squash_commit_template=, to: :project_setting, allow_nil: true
|
delegate :squash_commit_template, :squash_commit_template=, to: :project_setting, allow_nil: true
|
||||||
|
delegate :issue_branch_template, :issue_branch_template=, to: :project_setting, allow_nil: true
|
||||||
|
|
||||||
delegate :log_jira_dvcs_integration_usage, :jira_dvcs_server_last_sync_at, :jira_dvcs_cloud_last_sync_at, to: :feature_usage
|
delegate :log_jira_dvcs_integration_usage, :jira_dvcs_server_last_sync_at, :jira_dvcs_cloud_last_sync_at, to: :feature_usage
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ class ProjectSetting < ApplicationRecord
|
||||||
|
|
||||||
validates :merge_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
|
validates :merge_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
|
||||||
validates :squash_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
|
validates :squash_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
|
||||||
|
validates :issue_branch_template, length: { maximum: Issue::MAX_BRANCH_TEMPLATE }
|
||||||
validates :target_platforms, inclusion: { in: ALLOWED_TARGET_PLATFORMS }
|
validates :target_platforms, inclusion: { in: ALLOWED_TARGET_PLATFORMS }
|
||||||
validates :suggested_reviewers_enabled, inclusion: { in: [true, false] }
|
validates :suggested_reviewers_enabled, inclusion: { in: [true, false] }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
- if @project.project_feature.issues_access_level > 0
|
||||||
|
%fieldset#branch-names-settings
|
||||||
|
.form-group
|
||||||
|
= f.label :issue_branch_template, _('Branch name template'), class: 'label-bold'
|
||||||
|
%p= s_('ProjectSettings|Branches created from issues follow this pattern.')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
.gl-mb-2
|
||||||
|
= f.text_field :issue_branch_template, class: 'form-control gl-mb-2', placeholder: "%{id}-%{title}"
|
||||||
|
%p.form-text.text-muted
|
||||||
|
= s_('ProjectSettings|Leave empty to use default template.')
|
||||||
|
= sprintf(s_('ProjectSettings|Maximum %{maxLength} characters.'), { maxLength: Issue::MAX_BRANCH_TEMPLATE })
|
||||||
|
- branch_name_help_link = help_page_path('user/project/repository/web_editor.md', anchor: 'create-a-new-branch-from-an-issue')
|
||||||
|
= link_to _('What variables can I use?'), branch_name_help_link, target: "_blank"
|
|
@ -13,4 +13,5 @@
|
||||||
= gitlab_ui_form_for @project, url: url, method: :put, html: { multipart: true, class: "issue-settings-form js-issue-settings-form" }, authenticity_token: true do |f|
|
= gitlab_ui_form_for @project, url: url, method: :put, html: { multipart: true, class: "issue-settings-form js-issue-settings-form" }, authenticity_token: true do |f|
|
||||||
%input{ name: 'update_section', type: 'hidden', value: 'js-issue-settings' }
|
%input{ name: 'update_section', type: 'hidden', value: 'js-issue-settings' }
|
||||||
= render 'projects/branch_defaults/default_branch_fields', f: f
|
= render 'projects/branch_defaults/default_branch_fields', f: f
|
||||||
|
= render 'projects/branch_defaults/branch_names_fields', f: f
|
||||||
= f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
|
= f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.float-left.gl-md-ml-3.dropdown.gl-new-dropdown{ class: "gl-display-none! gl-md-display-flex!" }
|
.gl-md-ml-3.dropdown.gl-new-dropdown{ class: "gl-display-none! gl-md-display-flex!" }
|
||||||
#js-check-out-modal{ data: how_merge_modal_data(@merge_request) }
|
#js-check-out-modal{ data: how_merge_modal_data(@merge_request) }
|
||||||
= button_tag type: 'button', class: "btn dropdown-toggle btn-confirm gl-button gl-dropdown-toggle", data: { toggle: 'dropdown', qa_selector: 'mr_code_dropdown' } do
|
= button_tag type: 'button', class: "btn dropdown-toggle btn-confirm gl-button gl-dropdown-toggle", data: { toggle: 'dropdown', qa_selector: 'mr_code_dropdown' } do
|
||||||
%span.gl-new-dropdown-button-text= _('Code')
|
%span.gl-new-dropdown-button-text= _('Code')
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
- display_class = moved_mr_sidebar_enabled? ? 'gl-md-display-none!' : 'gl-sm-display-none!'
|
- display_class = moved_mr_sidebar_enabled? ? 'gl-md-display-none!' : 'gl-sm-display-none!'
|
||||||
= render Pajamas::ButtonComponent.new(icon: "chevron-double-lg-left", button_options: { class: "btn-icon float-right gl-display-block gutter-toggle issuable-gutter-toggle js-sidebar-toggle #{display_class}" })
|
= render Pajamas::ButtonComponent.new(icon: "chevron-double-lg-left", button_options: { class: "btn-icon float-right gl-display-block gutter-toggle issuable-gutter-toggle js-sidebar-toggle #{display_class}" })
|
||||||
|
|
||||||
.detail-page-header-actions.gl-align-self-start.is-merge-request.js-issuable-actions
|
.detail-page-header-actions.gl-align-self-start.is-merge-request.js-issuable-actions.gl-display-flex
|
||||||
- if can_update_merge_request
|
- if can_update_merge_request
|
||||||
= link_to _('Edit'), edit_project_merge_request_path(@project, @merge_request), class: "gl-display-none gl-md-display-block btn gl-button btn-default btn-grouped js-issuable-edit", data: { qa_selector: "edit_button" }
|
= link_to _('Edit'), edit_project_merge_request_path(@project, @merge_request), class: "gl-display-none gl-md-display-block btn gl-button btn-default js-issuable-edit", data: { qa_selector: "edit_button" }
|
||||||
|
|
||||||
- if @merge_request.source_project
|
- if @merge_request.source_project
|
||||||
= render 'projects/merge_requests/code_dropdown'
|
= render 'projects/merge_requests/code_dropdown'
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: approval_rules_eligible_filter
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100192
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/376331
|
|
||||||
milestone: '15.5'
|
|
||||||
type: development
|
|
||||||
group: group::source code
|
|
||||||
default_enabled: false
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddIssueBranchTemplateToProjectSettings < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
with_lock_retries do
|
||||||
|
add_column :project_settings, :issue_branch_template, :text, if_not_exists: true
|
||||||
|
end
|
||||||
|
|
||||||
|
add_text_limit :project_settings, :issue_branch_template, 255
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :project_settings, :issue_branch_template, if_exists: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
5e3fbb2c033f8512e5fd14b8ce8c6088866c596a2b769e115dcc1feb9ce9d041
|
|
@ -20190,12 +20190,14 @@ CREATE TABLE project_settings (
|
||||||
target_platforms character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
target_platforms character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
enforce_auth_checks_on_uploads boolean DEFAULT true NOT NULL,
|
enforce_auth_checks_on_uploads boolean DEFAULT true NOT NULL,
|
||||||
selective_code_owner_removals boolean DEFAULT false NOT NULL,
|
selective_code_owner_removals boolean DEFAULT false NOT NULL,
|
||||||
|
issue_branch_template text,
|
||||||
show_diff_preview_in_email boolean DEFAULT true NOT NULL,
|
show_diff_preview_in_email boolean DEFAULT true NOT NULL,
|
||||||
jitsu_key text,
|
jitsu_key text,
|
||||||
suggested_reviewers_enabled boolean DEFAULT false NOT NULL,
|
suggested_reviewers_enabled boolean DEFAULT false NOT NULL,
|
||||||
only_allow_merge_if_all_status_checks_passed boolean DEFAULT false NOT NULL,
|
only_allow_merge_if_all_status_checks_passed boolean DEFAULT false NOT NULL,
|
||||||
CONSTRAINT check_2981f15877 CHECK ((char_length(jitsu_key) <= 100)),
|
CONSTRAINT check_2981f15877 CHECK ((char_length(jitsu_key) <= 100)),
|
||||||
CONSTRAINT check_3a03e7557a CHECK ((char_length(previous_default_branch) <= 4096)),
|
CONSTRAINT check_3a03e7557a CHECK ((char_length(previous_default_branch) <= 4096)),
|
||||||
|
CONSTRAINT check_3ca5cbffe6 CHECK ((char_length(issue_branch_template) <= 255)),
|
||||||
CONSTRAINT check_b09644994b CHECK ((char_length(squash_commit_template) <= 500)),
|
CONSTRAINT check_b09644994b CHECK ((char_length(squash_commit_template) <= 500)),
|
||||||
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL)),
|
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL)),
|
||||||
CONSTRAINT check_eaf7cfb6a7 CHECK ((char_length(merge_commit_template) <= 500))
|
CONSTRAINT check_eaf7cfb6a7 CHECK ((char_length(merge_commit_template) <= 500))
|
||||||
|
|
|
@ -233,48 +233,6 @@ user.max_member_access_for_group group.id
|
||||||
|
|
||||||
## Merge requests
|
## Merge requests
|
||||||
|
|
||||||
### Close a merge request
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
u = User.find_by_username('<username>')
|
|
||||||
p = Project.find_by_full_path('<namespace/project>')
|
|
||||||
m = p.merge_requests.find_by(iid: <iid>)
|
|
||||||
MergeRequests::CloseService.new(project: p, current_user: u).execute(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Delete a merge request
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
u = User.find_by_username('<username>')
|
|
||||||
p = Project.find_by_full_path('<namespace/project>')
|
|
||||||
m = p.merge_requests.find_by(iid: <iid>)
|
|
||||||
Issuable::DestroyService.new(project: m.project, current_user: u).execute(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rebase manually
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
u = User.find_by_username('<username>')
|
|
||||||
p = Project.find_by_full_path('<namespace/project>')
|
|
||||||
m = p.merge_requests.find_by(iid: <iid>)
|
|
||||||
MergeRequests::RebaseService.new(project: m.target_project, current_user: u).execute(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set a merge request as merged
|
|
||||||
|
|
||||||
Use when a merge request was accepted and the changes merged into the Git repository,
|
|
||||||
but the merge request still shows as open.
|
|
||||||
|
|
||||||
If the changes are not merged yet, this action causes the merge request to
|
|
||||||
incorrectly show `merged into <branch-name>`.
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
u = User.find_by_username('<username>')
|
|
||||||
p = Project.find_by_full_path('<namespace/project>')
|
|
||||||
m = p.merge_requests.find_by(iid: <iid>)
|
|
||||||
MergeRequests::PostMergeService.new(project: p, current_user: u).execute(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
## CI
|
## CI
|
||||||
|
|
||||||
This content has been moved to [Troubleshooting CI/CD](../../ci/troubleshooting.md).
|
This content has been moved to [Troubleshooting CI/CD](../../ci/troubleshooting.md).
|
||||||
|
|
|
@ -289,3 +289,76 @@ For a web developer writing a webpage for your company's website:
|
||||||
- [Commits](commits.md)
|
- [Commits](commits.md)
|
||||||
- [CI/CD pipelines](../../../ci/index.md)
|
- [CI/CD pipelines](../../../ci/index.md)
|
||||||
- [Push options](../push_options.md) for merge requests
|
- [Push options](../push_options.md) for merge requests
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Rebase a merge request from the Rails console **(FREE SELF)**
|
||||||
|
|
||||||
|
In addition to the `/rebase` [quick action](../quick_actions.md#issues-merge-requests-and-epics),
|
||||||
|
users with access to the [Rails console](../../../administration/operations/rails_console.md)
|
||||||
|
can rebase a merge request from the Rails console. Replace `<username>`,
|
||||||
|
`<namespace/project>`, and `<iid>` with appropriate values:
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
Any command that changes data directly could be damaging if not run correctly,
|
||||||
|
or under the right conditions. We highly recommend running them in a test environment
|
||||||
|
with a backup of the instance ready to be restored, just in case.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
u = User.find_by_username('<username>')
|
||||||
|
p = Project.find_by_full_path('<namespace/project>')
|
||||||
|
m = p.merge_requests.find_by(iid: <iid>)
|
||||||
|
MergeRequests::RebaseService.new(project: m.target_project, current_user: u).execute(m)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fix incorrect merge request status **(FREE SELF)**
|
||||||
|
|
||||||
|
If a merge request remains **Open** after its changes are merged,
|
||||||
|
users with access to the [Rails console](../../../administration/operations/rails_console.md)
|
||||||
|
can correct the merge request's status. Replace `<username>`, `<namespace/project>`,
|
||||||
|
and `<iid>` with appropriate values:
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
Any command that changes data directly could be damaging if not run correctly,
|
||||||
|
or under the right conditions. We highly recommend running them in a test environment
|
||||||
|
with a backup of the instance ready to be restored, just in case.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
u = User.find_by_username('<username>')
|
||||||
|
p = Project.find_by_full_path('<namespace/project>')
|
||||||
|
m = p.merge_requests.find_by(iid: <iid>)
|
||||||
|
MergeRequests::PostMergeService.new(project: p, current_user: u).execute(m)
|
||||||
|
```
|
||||||
|
|
||||||
|
Running this command against a merge request with unmerged changes causes the
|
||||||
|
merge request to display an incorrect message: `merged into <branch-name>`.
|
||||||
|
|
||||||
|
### Close a merge request from the Rails console **(FREE SELF)**
|
||||||
|
|
||||||
|
If closing a merge request doesn't work through the UI or API, you may want to attempt to close it in a [Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
u = User.find_by_username('<username>')
|
||||||
|
p = Project.find_by_full_path('<namespace/project>')
|
||||||
|
m = p.merge_requests.find_by(iid: <iid>)
|
||||||
|
MergeRequests::CloseService.new(project: p, current_user: u).execute(m)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete a merge request from the Rails console **(FREE SELF)**
|
||||||
|
|
||||||
|
If deleting a merge request doesn't work through the UI or API, you may want to attempt to delete it in a [Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
Any command that changes data directly could be damaging if not run correctly,
|
||||||
|
or under the right conditions. We highly recommend running them in a test environment
|
||||||
|
with a backup of the instance ready to be restored, just in case.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
u = User.find_by_username('<username>')
|
||||||
|
p = Project.find_by_full_path('<namespace/project>')
|
||||||
|
m = p.merge_requests.find_by(iid: <iid>)
|
||||||
|
Issuable::DestroyService.new(project: m.project, current_user: u).execute(m)
|
||||||
|
```
|
||||||
|
|
|
@ -133,6 +133,7 @@ module API
|
||||||
expose :suggestion_commit_message
|
expose :suggestion_commit_message
|
||||||
expose :merge_commit_template
|
expose :merge_commit_template
|
||||||
expose :squash_commit_template
|
expose :squash_commit_template
|
||||||
|
expose :issue_branch_template
|
||||||
expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) {
|
expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) {
|
||||||
options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project)
|
options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project)
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ module API
|
||||||
optional :suggestion_commit_message, type: String, desc: 'The commit message used to apply merge request suggestions'
|
optional :suggestion_commit_message, type: String, desc: 'The commit message used to apply merge request suggestions'
|
||||||
optional :merge_commit_template, type: String, desc: 'Template used to create merge commit message'
|
optional :merge_commit_template, type: String, desc: 'Template used to create merge commit message'
|
||||||
optional :squash_commit_template, type: String, desc: 'Template used to create squash commit message'
|
optional :squash_commit_template, type: String, desc: 'Template used to create squash commit message'
|
||||||
|
optional :issue_branch_template, type: String, desc: 'Template used to create a branch from an issue'
|
||||||
optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
|
optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
|
||||||
optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning'
|
optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning'
|
||||||
optional :auto_devops_enabled, type: Boolean, desc: 'Flag indication if Auto DevOps is enabled'
|
optional :auto_devops_enabled, type: Boolean, desc: 'Flag indication if Auto DevOps is enabled'
|
||||||
|
@ -174,6 +175,7 @@ module API
|
||||||
:suggestion_commit_message,
|
:suggestion_commit_message,
|
||||||
:merge_commit_template,
|
:merge_commit_template,
|
||||||
:squash_commit_template,
|
:squash_commit_template,
|
||||||
|
:issue_branch_template,
|
||||||
:repository_storage,
|
:repository_storage,
|
||||||
:packages_enabled,
|
:packages_enabled,
|
||||||
:service_desk_enabled,
|
:service_desk_enabled,
|
||||||
|
|
|
@ -6831,6 +6831,9 @@ msgstr ""
|
||||||
msgid "Branch name"
|
msgid "Branch name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Branch name template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Branch not loaded - %{branchId}"
|
msgid "Branch not loaded - %{branchId}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -31796,6 +31799,9 @@ msgstr ""
|
||||||
msgid "ProjectSettings|Badges"
|
msgid "ProjectSettings|Badges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ProjectSettings|Branches created from issues follow this pattern."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ProjectSettings|Build, test, and deploy your changes."
|
msgid "ProjectSettings|Build, test, and deploy your changes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -45619,6 +45625,9 @@ msgstr ""
|
||||||
msgid "What templates can I create?"
|
msgid "What templates can I create?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "What variables can I use?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "What will you use this group for?"
|
msgid "What will you use this group for?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
"markdownlint:no-trailing-spaces:fix": "yarn run markdownlint:no-trailing-spaces --fix",
|
"markdownlint:no-trailing-spaces:fix": "yarn run markdownlint:no-trailing-spaces --fix",
|
||||||
"postinstall": "node ./scripts/frontend/postinstall.js",
|
"postinstall": "node ./scripts/frontend/postinstall.js",
|
||||||
"storybook:install": "yarn --cwd ./storybook install",
|
"storybook:install": "yarn --cwd ./storybook install",
|
||||||
"storybook:build": "yarn --cwd ./storybook build",
|
"storybook:build": "yarn --cwd ./storybook build --quiet",
|
||||||
"storybook:start": "./scripts/frontend/start_storybook.sh",
|
"storybook:start": "./scripts/frontend/start_storybook.sh",
|
||||||
"swagger:validate": "swagger-cli validate",
|
"swagger:validate": "swagger-cli validate",
|
||||||
"webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
|
"webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
|
||||||
|
|
|
@ -168,5 +168,37 @@ RSpec.describe Projects::Settings::RepositoryController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when updating branch names template from issues' do
|
||||||
|
let(:branch_name_template) { 'feat/GL-%{id}-%{title}' }
|
||||||
|
|
||||||
|
let(:request_params) { base_params.merge({ project: project_params_attributes }) }
|
||||||
|
|
||||||
|
subject { put :update, params: request_params }
|
||||||
|
|
||||||
|
context('with a good request') do
|
||||||
|
let(:project_params_attributes) { { issue_branch_template: branch_name_template } }
|
||||||
|
|
||||||
|
it "updates issue_branch_template and redirect to project_settings_repository_path" do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to redirect_to project_settings_repository_path(project)
|
||||||
|
expect(controller).to set_flash[:notice].to("Project settings were successfully updated.")
|
||||||
|
expect(project.reload.issue_branch_template).to eq(branch_name_template)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context('with a bad input') do
|
||||||
|
let(:project_params_attributes) { { issue_branch_template: 'a' * 260 } }
|
||||||
|
|
||||||
|
it "updates issue_branch_template and redirect to project_settings_repository_path" do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to redirect_to project_settings_repository_path(project)
|
||||||
|
expect(controller).to set_flash[:alert].to("Project setting issue branch template is too long (maximum is 255 characters)")
|
||||||
|
expect(project.reload.issue_branch_template).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Project settings > repositories > Branch names', :js do
|
||||||
|
let_it_be(:project) { create(:project, :public) }
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
project.add_maintainer(user)
|
||||||
|
|
||||||
|
sign_in(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when Issues are initially disabled' do
|
||||||
|
let(:project_feature) { project.project_feature }
|
||||||
|
|
||||||
|
before do
|
||||||
|
project_feature.update!(issues_access_level: ProjectFeature::DISABLED)
|
||||||
|
visit project_settings_repository_path(project)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'do not render the Branch names settings' do
|
||||||
|
expect(page).not_to have_content('Branch name template')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when Issues are initially enabled' do
|
||||||
|
before do
|
||||||
|
visit project_settings_repository_path(project)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'shows the Branch names settings' do
|
||||||
|
expect(page).to have_content('Branch name template')
|
||||||
|
|
||||||
|
value = "feature-%{id}"
|
||||||
|
|
||||||
|
within('section#branch-defaults-settings') do
|
||||||
|
fill_in 'project[issue_branch_template]', with: value
|
||||||
|
|
||||||
|
click_on('Save changes')
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(project.reload.issue_branch_template).to eq(value)
|
||||||
|
expect(page).to have_content('Branch name template')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -568,6 +568,7 @@ Project:
|
||||||
- suggestion_commit_message
|
- suggestion_commit_message
|
||||||
- merge_commit_template
|
- merge_commit_template
|
||||||
- squash_commit_template
|
- squash_commit_template
|
||||||
|
- issue_branch_template
|
||||||
Author:
|
Author:
|
||||||
- name
|
- name
|
||||||
ProjectFeature:
|
ProjectFeature:
|
||||||
|
|
|
@ -864,7 +864,7 @@ RSpec.describe Issue do
|
||||||
|
|
||||||
describe '.to_branch_name' do
|
describe '.to_branch_name' do
|
||||||
it 'parameterizes arguments and joins with dashes' do
|
it 'parameterizes arguments and joins with dashes' do
|
||||||
expect(described_class.to_branch_name(123, 'foo bar', '!@#$%', 'f!o@o#b$a%r^')).to eq('123-foo-bar-f-o-o-b-a-r')
|
expect(described_class.to_branch_name(123, 'foo bar!@#$%f!o@o#b$a%r^')).to eq('123-foo-bar-f-o-o-b-a-r')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'preserves the case in the first argument' do
|
it 'preserves the case in the first argument' do
|
||||||
|
@ -872,7 +872,7 @@ RSpec.describe Issue do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'truncates branch name to at most 100 characters' do
|
it 'truncates branch name to at most 100 characters' do
|
||||||
expect(described_class.to_branch_name('a' * 101)).to eq('a' * 100)
|
expect(described_class.to_branch_name('a' * 101, 'a')).to eq('a' * 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'truncates dangling parts of the branch name' do
|
it 'truncates dangling parts of the branch name' do
|
||||||
|
@ -884,6 +884,13 @@ RSpec.describe Issue do
|
||||||
# 100 characters would've got us "999-lorem...lacus-custom-fri".
|
# 100 characters would've got us "999-lorem...lacus-custom-fri".
|
||||||
expect(branch_name).to eq('999-lorem-ipsum-dolor-sit-amet-consectetur-adipiscing-elit-mauris-sit-amet-ipsum-id-lacus-custom')
|
expect(branch_name).to eq('999-lorem-ipsum-dolor-sit-amet-consectetur-adipiscing-elit-mauris-sit-amet-ipsum-id-lacus-custom')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'takes issue branch template into account' do
|
||||||
|
project = create(:project)
|
||||||
|
project.project_setting.update!(issue_branch_template: 'feature-%{id}-%{title}')
|
||||||
|
|
||||||
|
expect(described_class.to_branch_name(123, 'issue title', project: project)).to eq('feature-123-issue-title')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#to_branch_name' do
|
describe '#to_branch_name' do
|
||||||
|
|
|
@ -20,6 +20,7 @@ RSpec.describe ProjectSetting, type: :model do
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
it { is_expected.not_to allow_value(nil).for(:target_platforms) }
|
it { is_expected.not_to allow_value(nil).for(:target_platforms) }
|
||||||
it { is_expected.to allow_value([]).for(:target_platforms) }
|
it { is_expected.to allow_value([]).for(:target_platforms) }
|
||||||
|
it { is_expected.to validate_length_of(:issue_branch_template).is_at_most(255) }
|
||||||
|
|
||||||
it { is_expected.not_to allow_value(nil).for(:suggested_reviewers_enabled) }
|
it { is_expected.not_to allow_value(nil).for(:suggested_reviewers_enabled) }
|
||||||
it { is_expected.to allow_value(true).for(:suggested_reviewers_enabled) }
|
it { is_expected.to allow_value(true).for(:suggested_reviewers_enabled) }
|
||||||
|
|
|
@ -9,6 +9,12 @@ const IS_EE = require('../../config/helpers/is_ee_env');
|
||||||
const IS_JH = require('../../config/helpers/is_jh_env');
|
const IS_JH = require('../../config/helpers/is_jh_env');
|
||||||
const gitlabWebpackConfig = require('../../config/webpack.config');
|
const gitlabWebpackConfig = require('../../config/webpack.config');
|
||||||
|
|
||||||
|
const ROOT_PATH = path.resolve(__dirname, '..', '..');
|
||||||
|
const EMPTY_VUE_COMPONENT_PATH = path.join(
|
||||||
|
ROOT_PATH,
|
||||||
|
'app/assets/javascripts/vue_shared/components/empty_component.js',
|
||||||
|
);
|
||||||
|
|
||||||
const buildIncludePaths = (nodeSassIncludePaths, previouslyResolvedPath) => {
|
const buildIncludePaths = (nodeSassIncludePaths, previouslyResolvedPath) => {
|
||||||
const includePaths = [];
|
const includePaths = [];
|
||||||
if (path.isAbsolute(previouslyResolvedPath)) {
|
if (path.isAbsolute(previouslyResolvedPath)) {
|
||||||
|
@ -144,6 +150,22 @@ module.exports = function storybookWebpackConfig({ config }) {
|
||||||
// Silence webpack warnings about moment/pikaday not being able to resolve.
|
// Silence webpack warnings about moment/pikaday not being able to resolve.
|
||||||
config.plugins.push(new webpack.IgnorePlugin(/moment/, /pikaday/));
|
config.plugins.push(new webpack.IgnorePlugin(/moment/, /pikaday/));
|
||||||
|
|
||||||
|
if (!IS_EE) {
|
||||||
|
config.plugins.push(
|
||||||
|
new webpack.NormalModuleReplacementPlugin(/^ee_component\/(.*)\.vue/, (resource) => {
|
||||||
|
resource.request = EMPTY_VUE_COMPONENT_PATH;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_JH) {
|
||||||
|
config.plugins.push(
|
||||||
|
new webpack.NormalModuleReplacementPlugin(/^jh_component\/(.*)\.vue/, (resource) => {
|
||||||
|
resource.request = EMPTY_VUE_COMPONENT_PATH;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const baseIntegrationTestHelpersPath = 'spec/frontend_integration/test_helpers';
|
const baseIntegrationTestHelpersPath = 'spec/frontend_integration/test_helpers';
|
||||||
|
|
||||||
// Add any missing aliases from the main GitLab webpack config
|
// Add any missing aliases from the main GitLab webpack config
|
||||||
|
|
Loading…
Reference in New Issue