From 21b8ed2e35ee50538ddb2e48ad2b04de2eba43d6 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Sat, 29 Oct 2022 00:08:52 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../settings/repository_controller.rb | 1 + app/models/issue.rb | 22 ++++-- app/models/project.rb | 1 + app/models/project_setting.rb | 1 + .../_branch_names_fields.html.haml | 14 ++++ .../projects/branch_defaults/_show.html.haml | 1 + .../merge_requests/_code_dropdown.html.haml | 2 +- .../merge_requests/_mr_title.html.haml | 4 +- .../approval_rules_eligible_filter.yml | 8 -- ...sue_branch_template_to_project_settings.rb | 17 +++++ db/schema_migrations/20220721065723 | 1 + db/structure.sql | 2 + .../gitlab_rails_cheat_sheet.md | 42 ----------- doc/user/project/merge_requests/index.md | 73 +++++++++++++++++++ lib/api/entities/project.rb | 1 + lib/api/helpers/projects_helpers.rb | 2 + locale/gitlab.pot | 9 +++ package.json | 2 +- .../settings/repository_controller_spec.rb | 32 ++++++++ .../settings/branch_names_settings_spec.rb | 48 ++++++++++++ .../import_export/safe_model_attributes.yml | 1 + spec/models/issue_spec.rb | 11 ++- spec/models/project_setting_spec.rb | 1 + storybook/config/webpack.config.js | 22 ++++++ 24 files changed, 257 insertions(+), 61 deletions(-) create mode 100644 app/views/projects/branch_defaults/_branch_names_fields.html.haml delete mode 100644 config/feature_flags/development/approval_rules_eligible_filter.yml create mode 100644 db/migrate/20220721065723_add_issue_branch_template_to_project_settings.rb create mode 100644 db/schema_migrations/20220721065723 create mode 100644 spec/features/projects/settings/branch_names_settings_spec.rb diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index e3bd89def99..0bf9b05b3b5 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -116,6 +116,7 @@ module Projects def project_params_attributes [ + :issue_branch_template, :default_branch, :autoclose_referenced_issues ] diff --git a/app/models/issue.rb b/app/models/issue.rb index 639bb3140f8..7c2270c7558 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -39,6 +39,7 @@ class Issue < ApplicationRecord DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze SORTING_PREFERENCE_FIELD = :issues_sort + MAX_BRANCH_TEMPLATE = 255 # Types of issues that should be displayed on issue lists across the app # for example, project issues list, group issues list, and issues dashboard. @@ -394,10 +395,21 @@ class Issue < ApplicationRecord ) end - def self.to_branch_name(*args) - branch_name = args.map(&:to_s).each_with_index.map do |arg, i| - arg.parameterize(preserve_case: i == 0).presence - end.compact.join('-') + def self.to_branch_name(id, title, project: nil) + params = { + 'id' => id.to_s.parameterize(preserve_case: true), + '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 truncated_string = branch_name[0, 100] @@ -475,7 +487,7 @@ class Issue < ApplicationRecord if self.confidential? "#{iid}-confidential-issue" else - self.class.to_branch_name(iid, title) + self.class.to_branch_name(iid, title, project: project) end end diff --git a/app/models/project.rb b/app/models/project.rb index db30a74112d..8ecfdeb98f5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -491,6 +491,7 @@ class Project < ApplicationRecord to: :project_setting 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 :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 diff --git a/app/models/project_setting.rb b/app/models/project_setting.rb index 6d40544fad4..4c3be49fddd 100644 --- a/app/models/project_setting.rb +++ b/app/models/project_setting.rb @@ -20,6 +20,7 @@ class ProjectSetting < ApplicationRecord validates :merge_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 :suggested_reviewers_enabled, inclusion: { in: [true, false] } diff --git a/app/views/projects/branch_defaults/_branch_names_fields.html.haml b/app/views/projects/branch_defaults/_branch_names_fields.html.haml new file mode 100644 index 00000000000..65f975fbd9e --- /dev/null +++ b/app/views/projects/branch_defaults/_branch_names_fields.html.haml @@ -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" diff --git a/app/views/projects/branch_defaults/_show.html.haml b/app/views/projects/branch_defaults/_show.html.haml index 6790a658dce..4ecbc3b7fc8 100644 --- a/app/views/projects/branch_defaults/_show.html.haml +++ b/app/views/projects/branch_defaults/_show.html.haml @@ -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| %input{ name: 'update_section', type: 'hidden', value: 'js-issue-settings' } = 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' } diff --git a/app/views/projects/merge_requests/_code_dropdown.html.haml b/app/views/projects/merge_requests/_code_dropdown.html.haml index bb42c3067d9..eecea5ae855 100644 --- a/app/views/projects/merge_requests/_code_dropdown.html.haml +++ b/app/views/projects/merge_requests/_code_dropdown.html.haml @@ -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) } = 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') diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml index 893f03157db..a73d2aa5cc4 100644 --- a/app/views/projects/merge_requests/_mr_title.html.haml +++ b/app/views/projects/merge_requests/_mr_title.html.haml @@ -25,9 +25,9 @@ - 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}" }) - .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 - = 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 = render 'projects/merge_requests/code_dropdown' diff --git a/config/feature_flags/development/approval_rules_eligible_filter.yml b/config/feature_flags/development/approval_rules_eligible_filter.yml deleted file mode 100644 index e8d925d08a7..00000000000 --- a/config/feature_flags/development/approval_rules_eligible_filter.yml +++ /dev/null @@ -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 diff --git a/db/migrate/20220721065723_add_issue_branch_template_to_project_settings.rb b/db/migrate/20220721065723_add_issue_branch_template_to_project_settings.rb new file mode 100644 index 00000000000..d65bd2c21e7 --- /dev/null +++ b/db/migrate/20220721065723_add_issue_branch_template_to_project_settings.rb @@ -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 diff --git a/db/schema_migrations/20220721065723 b/db/schema_migrations/20220721065723 new file mode 100644 index 00000000000..78b1fedaff1 --- /dev/null +++ b/db/schema_migrations/20220721065723 @@ -0,0 +1 @@ +5e3fbb2c033f8512e5fd14b8ce8c6088866c596a2b769e115dcc1feb9ce9d041 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index bfb0c9b0a24..e23b88fe4fd 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -20190,12 +20190,14 @@ CREATE TABLE project_settings ( target_platforms character varying[] DEFAULT '{}'::character varying[] NOT NULL, enforce_auth_checks_on_uploads boolean DEFAULT true 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, jitsu_key text, suggested_reviewers_enabled 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_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_bde223416c CHECK ((show_default_award_emojis IS NOT NULL)), CONSTRAINT check_eaf7cfb6a7 CHECK ((char_length(merge_commit_template) <= 500)) diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 507940806ea..193f58fa5d3 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -233,48 +233,6 @@ user.max_member_access_for_group group.id ## Merge requests -### Close a merge request - -```ruby -u = User.find_by_username('') -p = Project.find_by_full_path('') -m = p.merge_requests.find_by(iid: ) -MergeRequests::CloseService.new(project: p, current_user: u).execute(m) -``` - -### Delete a merge request - -```ruby -u = User.find_by_username('') -p = Project.find_by_full_path('') -m = p.merge_requests.find_by(iid: ) -Issuable::DestroyService.new(project: m.project, current_user: u).execute(m) -``` - -### Rebase manually - -```ruby -u = User.find_by_username('') -p = Project.find_by_full_path('') -m = p.merge_requests.find_by(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 `. - -```ruby -u = User.find_by_username('') -p = Project.find_by_full_path('') -m = p.merge_requests.find_by(iid: ) -MergeRequests::PostMergeService.new(project: p, current_user: u).execute(m) -``` - ## CI This content has been moved to [Troubleshooting CI/CD](../../ci/troubleshooting.md). diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index e73c339e000..872f7524cb7 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -289,3 +289,76 @@ For a web developer writing a webpage for your company's website: - [Commits](commits.md) - [CI/CD pipelines](../../../ci/index.md) - [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 ``, +``, and `` 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('') +p = Project.find_by_full_path('') +m = p.merge_requests.find_by(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 ``, ``, +and `` 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('') +p = Project.find_by_full_path('') +m = p.merge_requests.find_by(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 `. + +### 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('') +p = Project.find_by_full_path('') +m = p.merge_requests.find_by(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('') +p = Project.find_by_full_path('') +m = p.merge_requests.find_by(iid: ) +Issuable::DestroyService.new(project: m.project, current_user: u).execute(m) +``` diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb index f158695f605..9b0a472400d 100644 --- a/lib/api/entities/project.rb +++ b/lib/api/entities/project.rb @@ -133,6 +133,7 @@ module API expose :suggestion_commit_message expose :merge_commit_template expose :squash_commit_template + expose :issue_branch_template expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) { options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project) } diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index 07b19742c2e..c95bf0f0c21 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -65,6 +65,7 @@ module API 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 :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 :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' @@ -174,6 +175,7 @@ module API :suggestion_commit_message, :merge_commit_template, :squash_commit_template, + :issue_branch_template, :repository_storage, :packages_enabled, :service_desk_enabled, diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e0106db1181..132e6b1080d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6831,6 +6831,9 @@ msgstr "" msgid "Branch name" msgstr "" +msgid "Branch name template" +msgstr "" + msgid "Branch not loaded - %{branchId}" msgstr "" @@ -31796,6 +31799,9 @@ msgstr "" msgid "ProjectSettings|Badges" msgstr "" +msgid "ProjectSettings|Branches created from issues follow this pattern." +msgstr "" + msgid "ProjectSettings|Build, test, and deploy your changes." msgstr "" @@ -45619,6 +45625,9 @@ msgstr "" msgid "What templates can I create?" msgstr "" +msgid "What variables can I use?" +msgstr "" + msgid "What will you use this group for?" msgstr "" diff --git a/package.json b/package.json index 363c5bd3763..826c7ca9676 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "markdownlint:no-trailing-spaces:fix": "yarn run markdownlint:no-trailing-spaces --fix", "postinstall": "node ./scripts/frontend/postinstall.js", "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", "swagger:validate": "swagger-cli validate", "webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js", diff --git a/spec/controllers/projects/settings/repository_controller_spec.rb b/spec/controllers/projects/settings/repository_controller_spec.rb index 31fefee3daa..6e04e3991ab 100644 --- a/spec/controllers/projects/settings/repository_controller_spec.rb +++ b/spec/controllers/projects/settings/repository_controller_spec.rb @@ -168,5 +168,37 @@ RSpec.describe Projects::Settings::RepositoryController do 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 diff --git a/spec/features/projects/settings/branch_names_settings_spec.rb b/spec/features/projects/settings/branch_names_settings_spec.rb new file mode 100644 index 00000000000..fdd883bc2b6 --- /dev/null +++ b/spec/features/projects/settings/branch_names_settings_spec.rb @@ -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 diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 64fed73303f..75d980cd5f4 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -568,6 +568,7 @@ Project: - suggestion_commit_message - merge_commit_template - squash_commit_template +- issue_branch_template Author: - name ProjectFeature: diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index f8c731b0d10..9dfe89b8814 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -864,7 +864,7 @@ RSpec.describe Issue do describe '.to_branch_name' 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 it 'preserves the case in the first argument' do @@ -872,7 +872,7 @@ RSpec.describe Issue do end 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 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". expect(branch_name).to eq('999-lorem-ipsum-dolor-sit-amet-consectetur-adipiscing-elit-mauris-sit-amet-ipsum-id-lacus-custom') 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 describe '#to_branch_name' do diff --git a/spec/models/project_setting_spec.rb b/spec/models/project_setting_spec.rb index eb0292c7005..b33cf0219d3 100644 --- a/spec/models/project_setting_spec.rb +++ b/spec/models/project_setting_spec.rb @@ -20,6 +20,7 @@ RSpec.describe ProjectSetting, type: :model do describe 'validations' do it { is_expected.not_to allow_value(nil).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.to allow_value(true).for(:suggested_reviewers_enabled) } diff --git a/storybook/config/webpack.config.js b/storybook/config/webpack.config.js index 51aaa1e18a6..a10ae0887ff 100644 --- a/storybook/config/webpack.config.js +++ b/storybook/config/webpack.config.js @@ -9,6 +9,12 @@ const IS_EE = require('../../config/helpers/is_ee_env'); const IS_JH = require('../../config/helpers/is_jh_env'); 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 includePaths = []; if (path.isAbsolute(previouslyResolvedPath)) { @@ -144,6 +150,22 @@ module.exports = function storybookWebpackConfig({ config }) { // Silence webpack warnings about moment/pikaday not being able to resolve. 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'; // Add any missing aliases from the main GitLab webpack config