From 5956978e1d2aa2b5b35c2d79f67f6b9706b8ec4e Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 22 Jun 2020 09:08:42 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../components/notes/noteable_warning.vue | 15 +-- .../layouts/nav/sidebar/_project.html.haml | 6 +- .../_create_protected_tag.html.haml | 2 +- .../shared/_create_protected_tag.html.haml | 2 +- .../protected_tags/shared/_dropdown.html.haml | 2 +- .../protected_tags/shared/_index.html.haml | 2 +- app/views/projects/tags/index.html.haml | 2 +- app/views/projects/tags/new.html.haml | 8 +- app/views/projects/tags/show.html.haml | 6 +- app/views/shared/_zen.html.haml | 2 +- ...-enclose-release-cli-steps-in-an-array.yml | 5 + ...-warning-doesnt-show-the-issuable-type.yml | 5 + doc/update/restore_after_failure.md | 4 +- doc/user/project/requirements/index.md | 31 ++++- lib/gitlab/ci/build/releaser.rb | 2 +- qa/qa.rb | 7 ++ qa/qa/page/component/dropdown_filter.rb | 2 +- qa/qa/page/project/settings/protected_tags.rb | 41 +++++++ qa/qa/page/project/settings/repository.rb | 10 ++ qa/qa/page/project/sub_menus/repository.rb | 15 ++- qa/qa/page/project/tag/index.rb | 19 +++ qa/qa/page/project/tag/new.rb | 41 +++++++ qa/qa/page/project/tag/show.rb | 29 +++++ qa/qa/resource/project.rb | 6 +- .../1_manage/project/protected_tags_spec.rb | 109 ++++++++++++++++++ .../ide/components/repo_editor_spec.js | 10 +- .../components/notes/noteable_warning_spec.js | 17 +-- spec/lib/gitlab/ci/build/releaser_spec.rb | 4 +- spec/lib/gitlab/ci/build/step_spec.rb | 2 +- spec/requests/api/runner_spec.rb | 2 +- .../spam/spam_verdict_service_spec.rb | 11 -- 31 files changed, 356 insertions(+), 63 deletions(-) create mode 100644 changelogs/unreleased/223162-enclose-release-cli-steps-in-an-array.yml create mode 100644 changelogs/unreleased/223279-confidential-warning-doesnt-show-the-issuable-type.yml create mode 100644 qa/qa/page/project/settings/protected_tags.rb create mode 100644 qa/qa/page/project/tag/index.rb create mode 100644 qa/qa/page/project/tag/new.rb create mode 100644 qa/qa/page/project/tag/show.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb diff --git a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue index e3986af695d..f986b105f20 100644 --- a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue +++ b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue @@ -8,16 +8,10 @@ function buildDocsLinkStart(path) { return ``; } -const NoteableType = { - Issue: 'issue', - Epic: 'epic', - MergeRequest: 'merge_request', -}; - const NoteableTypeText = { - [NoteableType.Issue]: __('issue'), - [NoteableType.Epic]: __('epic'), - [NoteableType.MergeRequest]: __('merge request'), + Issue: __('issue'), + Epic: __('epic'), + MergeRequest: __('merge request'), }; export default { @@ -39,7 +33,8 @@ export default { noteableType: { type: String, required: false, - default: NoteableType.Issue, + // eslint-disable-next-line @gitlab/require-i18n-strings + default: 'Issue', }, lockedNoteableDocsPath: { type: String, diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index 16902ebe1d4..0c3a69cf569 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -37,7 +37,7 @@ - if project_nav_tab? :files = nav_link(controller: sidebar_repository_paths, unless: -> { current_path?('projects/graphs#charts') }) do - = link_to project_tree_path(@project), class: 'shortcuts-tree qa-project-menu-repo' do + = link_to project_tree_path(@project), class: 'shortcuts-tree', data: { qa_selector: "repository_link" } do .nav-icon-container = sprite_icon('doc-text') %span.nav-item-name#js-onboarding-repo-link @@ -58,11 +58,11 @@ = _('Commits') = nav_link(html_options: {class: branches_tab_class}) do - = link_to project_branches_path(@project), class: 'qa-branches-link', id: 'js-onboarding-branches-link' do + = link_to project_branches_path(@project), data: { qa_selector: "branches_link" }, id: 'js-onboarding-branches-link' do = _('Branches') = nav_link(controller: [:tags]) do - = link_to project_tags_path(@project) do + = link_to project_tags_path(@project), data: { qa_selector: "tags_link" } do = _('Tags') = nav_link(path: 'graphs#show') do diff --git a/app/views/projects/protected_tags/_create_protected_tag.html.haml b/app/views/projects/protected_tags/_create_protected_tag.html.haml index f53b81cada6..b58df9de380 100644 --- a/app/views/projects/protected_tags/_create_protected_tag.html.haml +++ b/app/views/projects/protected_tags/_create_protected_tag.html.haml @@ -3,6 +3,6 @@ = dropdown_tag('Select', options: { toggle_class: 'js-allowed-to-create wide', dropdown_class: 'dropdown-menu-selectable capitalize-header', - data: { field_name: 'protected_tag[create_access_levels_attributes][0][access_level]', input_id: 'create_access_levels_attributes' }}) + data: { field_name: 'protected_tag[create_access_levels_attributes][0][access_level]', input_id: 'create_access_levels_attributes', qa_selector: 'access_levels_dropdown' }}) = render 'projects/protected_tags/shared/create_protected_tag' diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml index 020e6e187a6..8a6ae53a7c4 100644 --- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml +++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml @@ -25,4 +25,4 @@ = yield :create_access_levels .card-footer - = f.submit 'Protect', class: 'btn-success btn', disabled: true + = f.submit 'Protect', class: 'btn-success btn', disabled: true, data: { qa_selector: 'protect_tag_button' } diff --git a/app/views/projects/protected_tags/shared/_dropdown.html.haml b/app/views/projects/protected_tags/shared/_dropdown.html.haml index 824a8604f6f..9c7f532fa29 100644 --- a/app/views/projects/protected_tags/shared/_dropdown.html.haml +++ b/app/views/projects/protected_tags/shared/_dropdown.html.haml @@ -6,7 +6,7 @@ footer_content: true, data: { show_no: true, show_any: true, show_upcoming: true, selected: params[:protected_tag_name], - project_id: @project.try(:id) } }) do + project_id: @project.try(:id), qa_selector: 'tags_dropdown' } }) do %ul.dropdown-footer-list %li diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml index b0c87ac8c17..4bf3ce09fc7 100644 --- a/app/views/projects/protected_tags/shared/_index.html.haml +++ b/app/views/projects/protected_tags/shared/_index.html.haml @@ -1,6 +1,6 @@ - expanded = expanded_by_default? -%section.settings.no-animate#js-protected-tags-settings{ class: ('expanded' if expanded) } +%section.settings.no-animate#js-protected-tags-settings{ class: ('expanded' if expanded), data: { qa_selector: 'protected_tag_settings_content' } } .settings-header %h4 Protected Tags diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 6ad7cf1848f..e3d3f2226a8 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -24,7 +24,7 @@ %li = link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value) - if can?(current_user, :admin_tag, @project) - = link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do + = link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn', data: { qa_selector: "new_tag_button" } do = s_('TagsPage|New tag') = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn d-none d-sm-inline-block has-tooltip' do = icon("rss") diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 5aabfdd022a..c874a510e61 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -14,7 +14,7 @@ .form-group.row = label_tag :tag_name, nil, class: 'col-form-label col-sm-2' .col-sm-10 - = text_field_tag :tag_name, params[:tag_name], required: true, autofocus: true, class: 'form-control' + = text_field_tag :tag_name, params[:tag_name], required: true, autofocus: true, class: 'form-control', data: { qa_selector: "tag_name_field" } .form-group.row = label_tag :ref, 'Create from', class: 'col-form-label col-sm-2' .col-sm-10.create-from @@ -29,7 +29,7 @@ .form-group.row = label_tag :message, nil, class: 'col-form-label col-sm-2' .col-sm-10 - = text_area_tag :message, @message, required: false, class: 'form-control', rows: 5 + = text_area_tag :message, @message, required: false, class: 'form-control', rows: 5, data: { qa_selector: "tag_message_field" } .form-text.text-muted = tag_description_help_text %hr @@ -47,10 +47,10 @@ = s_('TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}').html_safe % replacements = render layout: 'shared/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do - = render 'shared/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here…'), current_text: @release_description + = render 'shared/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here…'), current_text: @release_description, qa_selector: 'release_notes_field' = render 'shared/notes/hints' .form-actions - = button_tag s_('TagsPage|Create tag'), class: 'btn btn-success' + = button_tag s_('TagsPage|Create tag'), class: 'btn btn-success', data: { qa_selector: "create_tag_button" } = link_to s_('TagsPage|Cancel'), project_tags_path(@project), class: 'btn btn-cancel' -# haml-lint:disable InlineJavaScript %script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index 6f53a687fb9..b98906a6863 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -9,7 +9,7 @@ .top-area.multi-line.flex-wrap .nav-text .title - %span.item-title.ref-name + %span.item-title.ref-name{ data: { qa_selector: 'tag_name_content' } } = icon('tag') = @tag.name - if protected_tag?(@project, @tag) @@ -56,12 +56,12 @@ %i.fa.fa-trash-o - if @tag.message.present? - %pre.wrap + %pre.wrap{ data: { qa_selector: 'tag_message_content' } } = strip_signature(@tag.message) .append-bottom-default.prepend-top-default - if @release.description.present? - .description.md + .description.md{ data: { qa_selector: 'tag_release_notes_content' } } = markdown_field(@release, :description) - else = s_('TagsPage|This tag has no release notes.') diff --git a/app/views/shared/_zen.html.haml b/app/views/shared/_zen.html.haml index 8dd0e5a92a7..914409d0e65 100644 --- a/app/views/shared/_zen.html.haml +++ b/app/views/shared/_zen.html.haml @@ -14,6 +14,6 @@ supports_autocomplete: supports_autocomplete, qa_selector: qa_selector } - else - = text_area_tag attr, current_text, class: classes, placeholder: placeholder + = text_area_tag attr, current_text, data: { qa_selector: qa_selector }, class: classes, placeholder: placeholder %a.zen-control.zen-control-leave.js-zen-leave.gl-text-gray-700{ href: "#" } = sprite_icon('compress', size: 16) diff --git a/changelogs/unreleased/223162-enclose-release-cli-steps-in-an-array.yml b/changelogs/unreleased/223162-enclose-release-cli-steps-in-an-array.yml new file mode 100644 index 00000000000..c5fc7ee561f --- /dev/null +++ b/changelogs/unreleased/223162-enclose-release-cli-steps-in-an-array.yml @@ -0,0 +1,5 @@ +--- +title: Enclose `release-cli` steps in an array +merge_request: 34913 +author: +type: fixed diff --git a/changelogs/unreleased/223279-confidential-warning-doesnt-show-the-issuable-type.yml b/changelogs/unreleased/223279-confidential-warning-doesnt-show-the-issuable-type.yml new file mode 100644 index 00000000000..48451ea8c4b --- /dev/null +++ b/changelogs/unreleased/223279-confidential-warning-doesnt-show-the-issuable-type.yml @@ -0,0 +1,5 @@ +--- +title: Fix confidential warning not showing the issuable type +merge_request: 34988 +author: +type: fixed diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md index c850bbff1cf..2c70e38d041 100644 --- a/doc/update/restore_after_failure.md +++ b/doc/update/restore_after_failure.md @@ -10,7 +10,9 @@ the previous version you were using. First, roll back the code or package. For source installations this involves checking out the older version (branch or tag). For Omnibus installations this -means installing the older `.deb` or `.rpm` package. Then, restore from a backup. +means installing the older +[`.deb` or `.rpm` package](https://packages.gitlab.com/gitlab). Then, restore from a +backup. Follow the instructions in the [Backup and Restore](../raketasks/backup_restore.md#restore-gitlab) documentation. diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md index d9bd02518a4..f80b10275fc 100644 --- a/doc/user/project/requirements/index.md +++ b/doc/user/project/requirements/index.md @@ -76,7 +76,7 @@ As soon as a requirement is reopened, it no longer appears in the **Archived** t ## Search for a requirement from the requirements list page -> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212543) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. You can search for a requirement from the list of requirements using filtered search bar (similar to that of Issues and Merge Requests) based on following parameters: @@ -96,7 +96,8 @@ You can also sort requirements list by: ## Allow requirements to be satisfied from a CI job -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. +> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. +> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/215514) ability to specify individual requirements and their statuses in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2. GitLab supports [requirements test reports](../../../ci/pipelines/job_artifacts.md#artifactsreportsrequirements-ultimate) now. @@ -132,6 +133,32 @@ the requirement report is checked for the "all passed" record (`{"*":"passed"}`), and on success, it marks all existing open requirements as Satisfied. +#### Specifying individual requirements + +It is possible to specify individual requirements and their statuses. + +If the following requirements exist: + +- `REQ-1` (with IID `1`) +- `REQ-2` (with IID `2`) +- `REQ-3` (with IID `3`) + +It is possible to specify that the first requirement passed, and the second failed. +Valid values are "passed" and "failed". +By omitting a requirement IID (in this case `REQ-3`'s IID `3`), no result is noted. + +```yaml +requirements_confirmation: + when: manual + allow_failure: false + script: + - mkdir tmp + - echo "{\"1\":\"passed\", \"2\":\"failed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` + ### Add the manual job to CI conditionally To configure your CI to include the manual job only when there are some open diff --git a/lib/gitlab/ci/build/releaser.rb b/lib/gitlab/ci/build/releaser.rb index ba6c7857e96..cc28ed14464 100644 --- a/lib/gitlab/ci/build/releaser.rb +++ b/lib/gitlab/ci/build/releaser.rb @@ -16,7 +16,7 @@ module Gitlab command = BASE_COMMAND.dup config.each { |k, v| command.concat(" --#{k.to_s.dasherize} \"#{v}\"") } - command + [command] end end end diff --git a/qa/qa.rb b/qa/qa.rb index 6d4acffd3de..d848aca9a66 100644 --- a/qa/qa.rb +++ b/qa/qa.rb @@ -254,6 +254,12 @@ module QA autoload :Show, 'qa/page/project/pipeline/show' end + module Tag + autoload :Index, 'qa/page/project/tag/index' + autoload :New, 'qa/page/project/tag/new' + autoload :Show, 'qa/page/project/tag/show' + end + module Job autoload :Show, 'qa/page/project/job/show' end @@ -273,6 +279,7 @@ module QA autoload :Runners, 'qa/page/project/settings/runners' autoload :MergeRequest, 'qa/page/project/settings/merge_request' autoload :MirroringRepositories, 'qa/page/project/settings/mirroring_repositories' + autoload :ProtectedTags, 'qa/page/project/settings/protected_tags' autoload :VisibilityFeaturesPermissions, 'qa/page/project/settings/visibility_features_permissions' module Services diff --git a/qa/qa/page/component/dropdown_filter.rb b/qa/qa/page/component/dropdown_filter.rb index a39a04a668d..30c6f13eaf7 100644 --- a/qa/qa/page/component/dropdown_filter.rb +++ b/qa/qa/page/component/dropdown_filter.rb @@ -8,7 +8,7 @@ module QA page.has_css?('.dropdown-input-field', wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) find('.dropdown-input-field').set(item) - click_link item + click_on item end end end diff --git a/qa/qa/page/project/settings/protected_tags.rb b/qa/qa/page/project/settings/protected_tags.rb new file mode 100644 index 00000000000..a11c15fdc4f --- /dev/null +++ b/qa/qa/page/project/settings/protected_tags.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Settings + class ProtectedTags < Page::Base + include Page::Component::DropdownFilter + + view 'app/views/projects/protected_tags/shared/_dropdown.html.haml' do + element :tags_dropdown + end + + view 'app/views/projects/protected_tags/_create_protected_tag.html.haml' do + element :access_levels_dropdown + end + + view 'app/views/projects/protected_tags/shared/_create_protected_tag.html.haml' do + element :protect_tag_button + end + + def set_tag(tag_name) + click_element :tags_dropdown + filter_and_select(tag_name) + end + + def choose_access_level_role(role) + click_element :access_levels_dropdown + click_on role + end + + def click_protect_tag_button + click_element :protect_tag_button + end + end + end + end + end +end + +QA::Page::Project::Settings::ProtectedTags.prepend_if_ee('QA::EE::Page::Project::Settings::ProtectedTags') diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb index 8e9a24a4741..fd3a590c2c1 100644 --- a/qa/qa/page/project/settings/repository.rb +++ b/qa/qa/page/project/settings/repository.rb @@ -23,6 +23,10 @@ module QA element :deploy_keys_settings end + view 'app/views/projects/protected_tags/shared/_index.html.haml' do + element :protected_tag_settings_content + end + def expand_deploy_tokens(&block) expand_section(:deploy_tokens_settings) do Settings::DeployTokens.perform(&block) @@ -46,6 +50,12 @@ module QA MirroringRepositories.perform(&block) end end + + def expand_protected_tags(&block) + expand_section(:protected_tag_settings_content) do + ProtectedTags.perform(&block) + end + end end end end diff --git a/qa/qa/page/project/sub_menus/repository.rb b/qa/qa/page/project/sub_menus/repository.rb index 38d6b8e50f4..c78c7521b64 100644 --- a/qa/qa/page/project/sub_menus/repository.rb +++ b/qa/qa/page/project/sub_menus/repository.rb @@ -14,15 +14,16 @@ module QA include QA::Page::Project::SubMenus::Common view 'app/views/layouts/nav/sidebar/_project.html.haml' do - element :project_menu_repo + element :repository_link element :branches_link + element :tags_link end end end def click_repository within_sidebar do - click_element(:project_menu_repo) + click_element(:repository_link) end end @@ -34,11 +35,19 @@ module QA end end + def go_to_repository_tags + hover_repository do + within_submenu do + click_element(:tags_link) + end + end + end + private def hover_repository within_sidebar do - find_element(:project_menu_repo).hover + find_element(:repository_link).hover yield end diff --git a/qa/qa/page/project/tag/index.rb b/qa/qa/page/project/tag/index.rb new file mode 100644 index 00000000000..b8f7bd3b0b4 --- /dev/null +++ b/qa/qa/page/project/tag/index.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Tag + class Index < Page::Base + view 'app/views/projects/tags/index.html.haml' do + element :new_tag_button + end + + def click_new_tag_button + click_element :new_tag_button + end + end + end + end + end +end diff --git a/qa/qa/page/project/tag/new.rb b/qa/qa/page/project/tag/new.rb new file mode 100644 index 00000000000..dc59c07ec98 --- /dev/null +++ b/qa/qa/page/project/tag/new.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Tag + class New < Page::Base + view 'app/views/projects/tags/new.html.haml' do + element :tag_name_field + element :tag_message_field + element :release_notes_field + element :create_tag_button + end + + view 'app/views/shared/_zen.html.haml' do + # This partial adds the `release_notes_field` selector passed from 'app/views/projects/tags/new.html.haml' + # The checks below ensure that required lines are not removed without updating this page object + element :_, "qa_selector = local_assigns.fetch(:qa_selector, '')" # rubocop:disable QA/ElementWithPattern + element :_, "text_area_tag attr, current_text, data: { qa_selector: qa_selector }" # rubocop:disable QA/ElementWithPattern + end + + def fill_tag_name(text) + fill_element(:tag_name_field, text) + end + + def fill_tag_message(text) + fill_element(:tag_message_field, text) + end + + def fill_release_notes(text) + fill_element(:release_notes_field, text) + end + + def click_create_tag_button + click_element :create_tag_button + end + end + end + end + end +end diff --git a/qa/qa/page/project/tag/show.rb b/qa/qa/page/project/tag/show.rb new file mode 100644 index 00000000000..1974448a7c5 --- /dev/null +++ b/qa/qa/page/project/tag/show.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Tag + class Show < Page::Base + view 'app/views/projects/tags/show.html.haml' do + element :tag_name_content + element :tag_message_content + element :tag_release_notes_content + end + + def has_tag_name?(text) + has_element?(:tag_name_content, text: text) + end + + def has_tag_message?(text) + has_element?(:tag_message_content, text: text) + end + + def has_tag_release_notes?(text) + has_element?(:tag_release_notes_content, text: text) + end + end + end + end + end +end diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index 645f4e97ee0..358e87b0eb9 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -96,7 +96,11 @@ module QA end def has_file?(file_path) - repository_tree.any? { |file| file[:path] == file_path } + response = repository_tree + + raise ResourceNotFoundError, "#{response[:message]}" if response.is_a?(Hash) && response.has_key?(:message) + + response.any? { |file| file[:path] == file_path } end def api_get_path diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb new file mode 100644 index 00000000000..db1af970c40 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +module QA + context 'Manage' do + describe 'Repository tags' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-for-tags' + project.initialize_with_readme = true + end + end + + let(:developer_user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) } + let(:maintainer_user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) } + let(:tag_name) { 'v0.0.1' } + let(:tag_message) { 'Version 0.0.1' } + let(:tag_release_notes) { 'Release It!' } + + shared_examples 'successful tag creation' do |user| + it "can be created by #{user}" do + Flow::Login.sign_in(as: send(user)) + + create_tag_for_project(project, tag_name, tag_message, tag_release_notes) + + Page::Project::Tag::Show.perform do |show| + expect(show).to have_tag_name(tag_name) + expect(show).to have_tag_message(tag_message) + expect(show).to have_tag_release_notes(tag_release_notes) + expect(show).not_to have_element(:create_tag_button) + end + end + end + + shared_examples 'unsuccessful tag creation' do |user| + it "cannot be created by an unauthorized #{user}" do + Flow::Login.sign_in(as: send(user)) + + create_tag_for_project(project, tag_name, tag_message, tag_release_notes) + + Page::Project::Tag::New.perform do |new_tag| + expect(new_tag).to have_content('You are not allowed to create this tag as it is protected.') + expect(new_tag).to have_element(:create_tag_button) + end + end + end + + context 'when not protected' do + before do + add_members_to_project(project) + end + + it_behaves_like 'successful tag creation', :developer_user + it_behaves_like 'successful tag creation', :maintainer_user + end + + context 'when protected' do + before do + add_members_to_project(project) + + Flow::Login.sign_in + + protect_tag_for_project(project, 'v*', 'Maintainers') + + Page::Main::Menu.perform(&:sign_out) + end + + it_behaves_like 'unsuccessful tag creation', :developer_user + it_behaves_like 'successful tag creation', :maintainer_user + end + + def create_tag_for_project(project, name, message, release_notes) + project.visit! + + Page::Project::Menu.perform(&:go_to_repository_tags) + Page::Project::Tag::Index.perform(&:click_new_tag_button) + + Page::Project::Tag::New.perform do |new_tag| + new_tag.fill_tag_name(name) + new_tag.fill_tag_message(message) + new_tag.fill_release_notes(release_notes) + new_tag.click_create_tag_button + end + end + + def protect_tag_for_project(project, tag, role) + project.visit! + + Page::Project::Menu.perform(&:go_to_repository_settings) + + Page::Project::Settings::Repository.perform do |setting| + setting.expand_protected_tags do |protected_tags| + protected_tags.set_tag(tag) + protected_tags.choose_access_level_role(role) + + protected_tags.click_protect_tag_button + end + end + end + + def add_members_to_project(project) + @developer_user = developer_user + @maintainer_user = maintainer_user + + project.add_member(@developer_user, Resource::Members::AccessLevel::DEVELOPER) + project.add_member(@maintainer_user, Resource::Members::AccessLevel::MAINTAINER) + end + end + end +end diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js index 0ba58561f08..a77edfc3fa8 100644 --- a/spec/frontend/ide/components/repo_editor_spec.js +++ b/spec/frontend/ide/components/repo_editor_spec.js @@ -546,7 +546,7 @@ describe('RepoEditor', () => { store.state.viewer = viewerTypes.diff; // we delay returning the file to make sure editor doesn't initialize before we fetch file content - await waitUsingRealTimer(10); + await waitUsingRealTimer(30); return 'rawFileData123\n'; }); @@ -555,8 +555,7 @@ describe('RepoEditor', () => { vm.file = f; - // use the real timer to accurately simulate the race condition - await waitUsingRealTimer(20); + await waitForEditorSetup(); expect(vm.model.getModel().getValue()).toBe('rawFileData123\n'); }); @@ -575,14 +574,13 @@ describe('RepoEditor', () => { }) .mockImplementationOnce(async () => { // we delay returning fileB content to make sure the editor doesn't initialize prematurely - await waitUsingRealTimer(10); + await waitUsingRealTimer(30); return 'fileB-rawContent\n'; }); vm.file = fileA; - // use the real timer to accurately simulate the race condition - await waitUsingRealTimer(20); + await waitForEditorSetup(); expect(vm.model.getModel().getValue()).toBe('fileB-rawContent\n'); }); }); diff --git a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js index 67889c0cdb4..ae8c9a0928e 100644 --- a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js +++ b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js @@ -60,9 +60,12 @@ describe('Issue Warning Component', () => { }); }); - it('renders information about confidential issue', () => { + it('renders information about confidential issue', async () => { expect(findConfidentialBlock().exists()).toBe(true); expect(findConfidentialBlock().element).toMatchSnapshot(); + + await wrapper.vm.$nextTick(); + expect(findConfidentialBlock(wrapper).text()).toContain('This is a confidential issue.'); }); it('renders warning icon', () => { @@ -142,13 +145,13 @@ describe('Issue Warning Component', () => { it('renders confidential & locked messages with noteable "epic"', async () => { wrapperLocked.setProps({ - noteableType: 'epic', + noteableType: 'Epic', }); wrapperConfidential.setProps({ - noteableType: 'epic', + noteableType: 'Epic', }); wrapperLockedAndConfidential.setProps({ - noteableType: 'epic', + noteableType: 'Epic', }); await wrapperLocked.vm.$nextTick(); @@ -167,13 +170,13 @@ describe('Issue Warning Component', () => { it('renders confidential & locked messages with noteable "merge request"', async () => { wrapperLocked.setProps({ - noteableType: 'merge_request', + noteableType: 'MergeRequest', }); wrapperConfidential.setProps({ - noteableType: 'merge_request', + noteableType: 'MergeRequest', }); wrapperLockedAndConfidential.setProps({ - noteableType: 'merge_request', + noteableType: 'MergeRequest', }); await wrapperLocked.vm.$nextTick(); diff --git a/spec/lib/gitlab/ci/build/releaser_spec.rb b/spec/lib/gitlab/ci/build/releaser_spec.rb index 2f7bca777dd..b338cd3a2d2 100644 --- a/spec/lib/gitlab/ci/build/releaser_spec.rb +++ b/spec/lib/gitlab/ci/build/releaser_spec.rb @@ -19,7 +19,7 @@ describe Gitlab::Ci::Build::Releaser do end it 'generates the script' do - expect(subject).to eq('release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "release-$CI_COMMIT_SHA" --ref "$CI_COMMIT_SHA"') + expect(subject).to eq(['release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "release-$CI_COMMIT_SHA" --ref "$CI_COMMIT_SHA"']) end end @@ -43,7 +43,7 @@ describe Gitlab::Ci::Build::Releaser do end it 'generates the script' do - expect(subject).to eq(result) + expect(subject).to eq([result]) end end end diff --git a/spec/lib/gitlab/ci/build/step_spec.rb b/spec/lib/gitlab/ci/build/step_spec.rb index 1cebda2cc7e..ea36d38bb10 100644 --- a/spec/lib/gitlab/ci/build/step_spec.rb +++ b/spec/lib/gitlab/ci/build/step_spec.rb @@ -62,7 +62,7 @@ describe Gitlab::Ci::Build::Step do let(:job) { create(:ci_build, :release_options) } it 'returns the release-cli command line' do - expect(subject.script).to eq("release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" --tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\"") + expect(subject.script).to eq(["release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" --tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\""]) end end diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index fe1435826a0..fc0d4b91aa2 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -668,7 +668,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do { "name" => "release", "script" => - "release-cli create --ref \"$CI_COMMIT_SHA\" --name \"Release $CI_COMMIT_SHA\" --tag-name \"release-$CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\"", + ["release-cli create --ref \"$CI_COMMIT_SHA\" --name \"Release $CI_COMMIT_SHA\" --tag-name \"release-$CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\""], "timeout" => 3600, "when" => "on_success", "allow_failure" => false diff --git a/spec/services/spam/spam_verdict_service_spec.rb b/spec/services/spam/spam_verdict_service_spec.rb index fe70da7a894..b9f9657f20f 100644 --- a/spec/services/spam/spam_verdict_service_spec.rb +++ b/spec/services/spam/spam_verdict_service_spec.rb @@ -81,17 +81,6 @@ describe Spam::SpamVerdictService do end end - context 'and one is supported' do - before do - allow(service).to receive(:akismet_verdict).and_return('nonsense') - allow(service).to receive(:spam_verdict).and_return(BLOCK_USER) - end - - it 'renders the more restrictive verdict' do - expect(subject).to eq BLOCK_USER - end - end - context 'and none are supported' do before do allow(service).to receive(:akismet_verdict).and_return('nonsense') -- GitLab