From 0eeb1736417d4768a1e2ee34b62f25c1f591c6ca Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 30 Mar 2021 06:09:35 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../issue_show/components/edit_actions.vue | 12 +- .../javascripts/packages/shared/utils.js | 16 +-- app/models/project_services/asana_service.rb | 25 ++-- app/views/shared/_recaptcha_form.html.haml | 2 +- app/views/shared/issuable/_form.html.haml | 28 ++-- .../container_expiration_policy_worker.rb | 20 ++- ...-and-update-buttons-on-projects-issues.yml | 5 + ...ew-and-revise-settings-related-ui-text.yml | 5 + ..._registry_expiration_policies_loopless.yml | 8 ++ doc/api/services.md | 10 +- doc/user/project/integrations/asana.md | 44 ++++++ doc/user/project/integrations/overview.md | 3 +- locale/gitlab.pot | 75 +++++----- .../reload_boards_on_browser_back_spec.rb | 2 +- spec/features/issues/form_spec.rb | 2 +- spec/features/issues/spam_issues_spec.rb | 22 +-- .../issues/user_creates_issue_spec.rb | 8 +- ...ommits_from_memebers_who_can_merge_spec.rb | 2 +- .../user_creates_merge_request_spec.rb | 4 +- .../user_sees_merge_widget_spec.rb | 2 +- .../user_selects_branches_for_new_mr_spec.rb | 4 +- .../user_squashes_merge_request_spec.rb | 4 +- .../components/edit_actions_spec.js | 8 +- ...creatable_merge_request_shared_examples.rb | 2 +- ...g_discussions_in_issues_shared_examples.rb | 6 +- .../close_quick_action_shared_examples.rb | 2 +- ...container_expiration_policy_worker_spec.rb | 135 +++++++++++------- 27 files changed, 281 insertions(+), 175 deletions(-) create mode 100644 changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml create mode 100644 changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml create mode 100644 config/feature_flags/development/container_registry_expiration_policies_loopless.yml create mode 100644 doc/user/project/integrations/asana.md diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue index 20c759cfbbd..7733e366c4f 100644 --- a/app/assets/javascripts/issue_show/components/edit_actions.vue +++ b/app/assets/javascripts/issue_show/components/edit_actions.vue @@ -47,7 +47,7 @@ export default { }, deleteIssuableButtonText() { return sprintf(__('Delete %{issuableType}'), { - issuableType: issuableTypes[this.issuableType], + issuableType: issuableTypes[this.issuableType].toLowerCase(), }); }, }, @@ -79,23 +79,23 @@ export default { :loading="formState.updateLoading" :disabled="formState.updateLoading || !isSubmitEnabled" category="primary" - variant="success" - class="float-left qa-save-button" + variant="confirm" + class="float-left qa-save-button gl-mr-3" type="submit" @click.prevent="updateIssuable" > {{ __('Save changes') }} - + {{ __('Cancel') }} {{ deleteIssuableButtonText }} diff --git a/app/assets/javascripts/packages/shared/utils.js b/app/assets/javascripts/packages/shared/utils.js index 1f9cb8bf477..bd35a47ca4d 100644 --- a/app/assets/javascripts/packages/shared/utils.js +++ b/app/assets/javascripts/packages/shared/utils.js @@ -10,21 +10,21 @@ export const beautifyPath = (path) => (path ? path.split('/').join(' / ') : ''); export const getPackageTypeLabel = (packageType) => { switch (packageType) { case PackageType.CONAN: - return s__('PackageType|Conan'); + return s__('PackageRegistry|Conan'); case PackageType.MAVEN: - return s__('PackageType|Maven'); + return s__('PackageRegistry|Maven'); case PackageType.NPM: - return s__('PackageType|npm'); + return s__('PackageRegistry|npm'); case PackageType.NUGET: - return s__('PackageType|NuGet'); + return s__('PackageRegistry|NuGet'); case PackageType.PYPI: - return s__('PackageType|PyPI'); + return s__('PackageRegistry|PyPI'); case PackageType.RUBYGEMS: - return s__('PackageType|RubyGems'); + return s__('PackageRegistry|RubyGems'); case PackageType.COMPOSER: - return s__('PackageType|Composer'); + return s__('PackageRegistry|Composer'); case PackageType.GENERIC: - return s__('PackageType|Generic'); + return s__('PackageRegistry|Generic'); default: return null; } diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 4fbbca9d5e9..f31bf931a41 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -3,6 +3,8 @@ require 'asana' class AsanaService < Service + include ActionView::Helpers::UrlHelper + prop_accessor :api_key, :restrict_to_branch validates :api_key, presence: true, if: :activated? @@ -11,20 +13,12 @@ class AsanaService < Service end def description - s_('AsanaService|Asana - Teamwork without email') + s_('AsanaService|Add commit messages as comments to Asana tasks') end def help - 'This service adds commit messages as comments to Asana tasks. -Once enabled, commit messages are checked for Asana task URLs -(for example, `https://app.asana.com/0/123456/987654`) or task IDs -starting with # (for example, `#987654`). Every task ID found will -get the commit comment added to it. - -You can also close a task with a message containing: `fix #123456`. - -You can create a Personal Access Token here: -https://app.asana.com/0/developer-console' + docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/asana'), target: '_blank', rel: 'noopener noreferrer' + s_('Add commit messages as comments to Asana tasks. %{docs_link}').html_safe % { docs_link: docs_link.html_safe } end def self.to_param @@ -36,14 +30,17 @@ https://app.asana.com/0/developer-console' { type: 'text', name: 'api_key', - title: _('API key'), - placeholder: s_('AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user.'), + title: 'API key', + help: s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.'), + # Example Personal Access Token from Asana docs + placeholder: '0/68a9e79b868c6789e79a124c30b0', required: true }, { type: 'text', name: 'restrict_to_branch', - placeholder: s_('AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.') + title: 'Restrict to branch (optional)', + help: s_('AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches.') } ] end diff --git a/app/views/shared/_recaptcha_form.html.haml b/app/views/shared/_recaptcha_form.html.haml index f524747dea0..5c5fc714aea 100644 --- a/app/views/shared/_recaptcha_form.html.haml +++ b/app/views/shared/_recaptcha_form.html.haml @@ -20,4 +20,4 @@ - if has_submit .row-content-block.footer-block - = f.submit _("Submit %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm' + = f.submit _("Create %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm' diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 41b7d7e9e1b..de657e39453 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -62,26 +62,24 @@ - is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?) .row-content-block{ class: (is_footer ? "footer-block" : "middle-block") } - .float-right - - if issuable.new_record? - = link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'gl-button btn btn-cancel' - - else - - if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project) - = link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: "#{issuable.human_class_name} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped' - = link_to _('Cancel'), polymorphic_path([@project, issuable]), class: 'gl-button btn btn-grouped btn-default btn-cancel' - - %span.gl-mr-3 - - if issuable.new_record? - = form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'gl-button btn btn-confirm', data: { qa_selector: 'issuable_create_button' } - - else - = form.submit 'Save changes', class: 'gl-button btn btn-confirm' - - if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = issuable.project.present.contribution_guide_path) - .inline.gl-mt-3 + .gl-mb-5 Please review the %strong= link_to('contribution guidelines', guide_url) for this project. + - if issuable.new_record? + = form.submit "Create #{issuable.class.model_name.human.downcase}", class: 'gl-button btn btn-confirm gl-mr-2', data: { qa_selector: 'issuable_create_button' } + - else + = form.submit 'Save changes', class: 'gl-button btn btn-confirm gl-mr-2' + + - if issuable.new_record? + = link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'btn gl-button btn-default' + - else + = link_to _('Cancel'), polymorphic_path([@project, issuable]), class: 'gl-button btn btn-default' + - if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project) + = link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: _('%{issuableType} will be removed! Are you sure?') % { issuableType: issuable.human_class_name } }, method: :delete, class: 'btn gl-button btn-danger btn-danger-secondary gl-float-right' + = render_if_exists 'shared/issuable/remove_approver' - if issuable.respond_to?(:issue_type) diff --git a/app/workers/container_expiration_policy_worker.rb b/app/workers/container_expiration_policy_worker.rb index b855d2a6998..5ca89179099 100644 --- a/app/workers/container_expiration_policy_worker.rb +++ b/app/workers/container_expiration_policy_worker.rb @@ -29,13 +29,15 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo def perform_throttled try_obtain_lease do - with_runnable_policy do |policy| - ContainerExpirationPolicy.transaction do - policy.schedule_next_run! - ContainerRepository.for_project_id(policy.id) - .each_batch do |relation| - relation.update_all(expiration_policy_cleanup_status: :cleanup_scheduled) - end + unless loopless_enabled? + with_runnable_policy do |policy| + ContainerExpirationPolicy.transaction do + policy.schedule_next_run! + ContainerRepository.for_project_id(policy.id) + .each_batch do |relation| + relation.update_all(expiration_policy_cleanup_status: :cleanup_scheduled) + end + end end end @@ -75,6 +77,10 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo Feature.enabled?(:container_registry_expiration_policies_throttling) end + def loopless_enabled? + Feature.enabled?(:container_registry_expiration_policies_loopless) + end + def lease_timeout 5.hours end diff --git a/changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml b/changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml new file mode 100644 index 00000000000..d1dcf7ba06e --- /dev/null +++ b/changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml @@ -0,0 +1,5 @@ +--- +title: Update issuable submit content order, button variants, and button alignment +merge_request: 57172 +author: +type: other diff --git a/changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml b/changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml new file mode 100644 index 00000000000..536f23bee35 --- /dev/null +++ b/changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml @@ -0,0 +1,5 @@ +--- +title: Review and revise Integrations/Asana UI text +merge_request: 57362 +author: +type: other diff --git a/config/feature_flags/development/container_registry_expiration_policies_loopless.yml b/config/feature_flags/development/container_registry_expiration_policies_loopless.yml new file mode 100644 index 00000000000..5c581151d0e --- /dev/null +++ b/config/feature_flags/development/container_registry_expiration_policies_loopless.yml @@ -0,0 +1,8 @@ +--- +name: container_registry_expiration_policies_loopless +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56962 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325273 +milestone: '13.11' +type: development +group: group::package +default_enabled: false diff --git a/doc/api/services.md b/doc/api/services.md index 189dfc48cd5..429d824fcb1 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -68,14 +68,14 @@ Example response: ## Asana -Asana - Teamwork without email +Add commit messages as comments to Asana tasks. + +See also the [Asana service documentation](../user/project/integrations/asana.md). ### Create/Edit Asana service Set Asana service for a project. -> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found gets the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your API Keys here: . - ```plaintext PUT /projects/:id/services/asana ``` @@ -84,8 +84,8 @@ Parameters: | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `api_key` | string | true | User API token. User must have access to task, all comments are attributed to this user. | -| `restrict_to_branch` | string | false | Comma-separated list of branches which are automatically inspected. Leave blank to include all branches. | +| `api_key` | string | true | User API token. User must have access to task. All comments are attributed to this user. | +| `restrict_to_branch` | string | false | Comma-separated list of branches to be are automatically inspected. Leave blank to include all branches. | | `push_events` | boolean | false | Enable notifications for push events | ### Delete Asana service diff --git a/doc/user/project/integrations/asana.md b/doc/user/project/integrations/asana.md new file mode 100644 index 00000000000..b9552fff110 --- /dev/null +++ b/doc/user/project/integrations/asana.md @@ -0,0 +1,44 @@ +--- +stage: Create +group: Ecosystem +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Asana service **(FREE)** + +This service adds commit messages as comments to Asana tasks. +Once enabled, commit messages are checked for Asana task URLs (for example, +`https://app.asana.com/0/123456/987654`) or task IDs starting with `#` +(for example, `#987654`). Every task ID found gets the commit comment added to it. + +You can also close a task with a message containing: `fix #123456`. +You can use either of these words: + +- `fix` +- `fixed` +- `fixes` +- `fixing` +- `close` +- `closes` +- `closed` +- `closing` + +See also the [Asana service API documentation](../../../api/services.md#asana). + +## Setup + +In Asana, create a Personal Access Token. +[Learn about Personal Access Tokens in Asana](https://developers.asana.com/docs/personal-access-token). + +Complete these steps in GitLab: + +1. Go to the project you want to configure. +1. Go to the [Integrations page](overview.md#accessing-integrations). +1. Select **Asana**. +1. Ensure that the **Active** toggle is enabled. +1. Paste the token you generated in Asana. +1. (Optional) To restrict this setting to specific branches, list them in the **Restrict to branch** + field, separated with commas. +1. Select **Save changes** or optionally select **Test settings**. + + diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md index 59f1e37e401..69b7e8a51d3 100644 --- a/doc/user/project/integrations/overview.md +++ b/doc/user/project/integrations/overview.md @@ -25,8 +25,7 @@ want to configure. Click on the service links to see further configuration instructions and details. | Service | Description | Service Hooks | -| ------- | ----------- | ------------- | -| Asana | Asana - Teamwork without email | No | +| Asana | Add commit messages as comments to Asana tasks | No | | Assembla | Project Management Software (Source Commits Endpoint) | No | | [Atlassian Bamboo CI](bamboo.md) | A continuous integration and build server | Yes | | Buildkite | Continuous integration and deployments | Yes | diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 84142147d00..eb157519e30 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1896,6 +1896,9 @@ msgstr "" msgid "Add comment to design" msgstr "" +msgid "Add commit messages as comments to Asana tasks. %{docs_link}" +msgstr "" + msgid "Add deploy freeze" msgstr "" @@ -4176,13 +4179,13 @@ msgstr "" msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):" msgstr "" -msgid "AsanaService|Asana - Teamwork without email" +msgid "AsanaService|Add commit messages as comments to Asana tasks" msgstr "" -msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches." +msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches." msgstr "" -msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user." +msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user." msgstr "" msgid "Ascending" @@ -8771,6 +8774,9 @@ msgstr "" msgid "Create %{environment}" msgstr "" +msgid "Create %{humanized_resource_name}" +msgstr "" + msgid "Create %{type}" msgstr "" @@ -13907,9 +13913,15 @@ msgstr "" msgid "Geo|Could not remove tracking entry for an existing upload." msgstr "" +msgid "Geo|Data replication lag" +msgstr "" + msgid "Geo|Discover GitLab Geo" msgstr "" +msgid "Geo|Does not match the primary storage configuration" +msgstr "" + msgid "Geo|Failed" msgstr "" @@ -13937,6 +13949,12 @@ msgstr "" msgid "Geo|Internal URL" msgstr "" +msgid "Geo|Last event ID from primary" +msgstr "" + +msgid "Geo|Last event ID processed by cursor" +msgstr "" + msgid "Geo|Last repository check run" msgstr "" @@ -14021,12 +14039,27 @@ msgstr "" msgid "Geo|Replicated data is verified with the secondary node(s) using checksums." msgstr "" +msgid "Geo|Replication Details" +msgstr "" + +msgid "Geo|Replication counts" +msgstr "" + +msgid "Geo|Replication details" +msgstr "" + msgid "Geo|Replication slot WAL" msgstr "" msgid "Geo|Replication slots" msgstr "" +msgid "Geo|Replication status" +msgstr "" + +msgid "Geo|Replication summary" +msgstr "" + msgid "Geo|Resync" msgstr "" @@ -14045,9 +14078,6 @@ msgstr "" msgid "Geo|Review replication status, and resynchronize and reverify items with the primary node." msgstr "" -msgid "Geo|Secondary Details" -msgstr "" - msgid "Geo|Secondary node" msgstr "" @@ -14057,6 +14087,9 @@ msgstr "" msgid "Geo|Status" msgstr "" +msgid "Geo|Storage config" +msgstr "" + msgid "Geo|Synced" msgstr "" @@ -14069,6 +14102,9 @@ msgstr "" msgid "Geo|Synchronization of %{itemTitle} is disabled." msgstr "" +msgid "Geo|Synchronization settings" +msgstr "" + msgid "Geo|The database is currently %{db_lag} behind the primary node." msgstr "" @@ -22139,30 +22175,6 @@ msgstr "" msgid "PackageRegistry|yarn command" msgstr "" -msgid "PackageType|Composer" -msgstr "" - -msgid "PackageType|Conan" -msgstr "" - -msgid "PackageType|Generic" -msgstr "" - -msgid "PackageType|Maven" -msgstr "" - -msgid "PackageType|NuGet" -msgstr "" - -msgid "PackageType|PyPI" -msgstr "" - -msgid "PackageType|RubyGems" -msgstr "" - -msgid "PackageType|npm" -msgstr "" - msgid "Packages" msgstr "" @@ -29256,9 +29268,6 @@ msgstr "" msgid "Submit" msgstr "" -msgid "Submit %{humanized_resource_name}" -msgstr "" - msgid "Submit a review" msgstr "" diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb index 3530be20009..36682036d48 100644 --- a/spec/features/boards/reload_boards_on_browser_back_spec.rb +++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb @@ -27,7 +27,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do fill_in 'issue_title', with: 'issue should be shown' - click_button 'Submit issue' + click_button 'Create issue' page.go_back wait_for_requests diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index dac066856c0..5ca20028485 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -156,7 +156,7 @@ RSpec.describe 'New/edit issue', :js do expect(page.all('input[name="issue[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) expect(page.all('input[name="issue[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) - click_button 'Submit issue' + click_button 'Create issue' page.within '.issuable-sidebar' do page.within '.assignee' do diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb index aec806c566d..461030d3176 100644 --- a/spec/features/issues/spam_issues_spec.rb +++ b/spec/features/issues/spam_issues_spec.rb @@ -43,7 +43,7 @@ RSpec.describe 'New issue', :js do end it 'rejects issue creation' do - click_button 'Submit issue' + click_button 'Create issue' expect(page).to have_content('discarded') expect(page).not_to have_content('potential spam') @@ -51,7 +51,7 @@ RSpec.describe 'New issue', :js do end it 'creates a spam log record' do - expect { click_button 'Submit issue' } + expect { click_button 'Create issue' } .to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue') end end @@ -63,14 +63,14 @@ RSpec.describe 'New issue', :js do end it 'allows issue creation' do - click_button 'Submit issue' + click_button 'Create issue' expect(page.find('.issue-details h2.title')).to have_content('issue title') expect(page.find('.issue-details .description')).to have_content('issue description') end it 'creates a spam log record' do - expect { click_button 'Submit issue' } + expect { click_button 'Create issue' } .to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue') end end @@ -101,14 +101,14 @@ RSpec.describe 'New issue', :js do fill_in 'issue_title', with: 'issue title' fill_in 'issue_description', with: 'issue description' - click_button 'Submit issue' + click_button 'Create issue' # it is impossible to test reCAPTCHA automatically and there is no possibility to fill in recaptcha # reCAPTCHA verification is skipped in test environment and it always returns true expect(page).not_to have_content('issue title') expect(page).to have_css('.recaptcha') - click_button 'Submit issue' + click_button 'Create issue' expect(page.find('.issue-details h2.title')).to have_content('issue title') expect(page.find('.issue-details .description')).to have_content('issue description') @@ -122,7 +122,7 @@ RSpec.describe 'New issue', :js do end it 'creates an issue without a need to solve reCAPTCHA' do - click_button 'Submit issue' + click_button 'Create issue' expect(page).not_to have_css('.recaptcha') expect(page.find('.issue-details h2.title')).to have_content('issue title') @@ -130,7 +130,7 @@ RSpec.describe 'New issue', :js do end it 'creates a spam log record' do - expect { click_button 'Submit issue' } + expect { click_button 'Create issue' } .to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue') end end @@ -148,7 +148,7 @@ RSpec.describe 'New issue', :js do end it 'creates an issue without a need to solve reCaptcha' do - click_button 'Submit issue' + click_button 'Create issue' expect(page).not_to have_css('.recaptcha') expect(page.find('.issue-details h2.title')).to have_content('issue title') @@ -156,7 +156,7 @@ RSpec.describe 'New issue', :js do end it 'creates a spam log record' do - expect { click_button 'Submit issue' } + expect { click_button 'Create issue' } .to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue') end end @@ -178,7 +178,7 @@ RSpec.describe 'New issue', :js do fill_in 'issue_title', with: 'issue title' fill_in 'issue_description', with: 'issue description' - click_button 'Submit issue' + click_button 'Create issue' expect(page.find('.issue-details h2.title')).to have_content('issue title') expect(page.find('.issue-details .description')).to have_content('issue description') diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index 98f9ed6c6a2..6e380bdbc0a 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -54,7 +54,7 @@ RSpec.describe "User creates issue" do first('.js-md').click first('.rspec-issuable-form-description').native.send_keys('Description') - click_button("Submit issue") + click_button("Create issue") expect(page).to have_content(issue_title) .and have_content(user.name) @@ -112,7 +112,7 @@ RSpec.describe "User creates issue" do fill_in("Title", with: issue_title) click_button("Label") click_link(label_titles.first) - click_button("Submit issue") + click_button("Create issue") expect(page).to have_content(issue_title) .and have_content(user.name) @@ -135,7 +135,7 @@ RSpec.describe "User creates issue" do expect(find('#issuable-due-date').value).to eq date.to_s - click_button 'Submit issue' + click_button 'Create issue' page.within '.issuable-sidebar' do expect(page).to have_content date.to_s(:medium) @@ -259,7 +259,7 @@ RSpec.describe "User creates issue" do fill_in 'issue_title', with: 'bug 345' fill_in 'issue_description', with: 'bug description' - click_button 'Submit issue' + click_button 'Create issue' end end end diff --git a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb index fd13083c185..d36abf86518 100644 --- a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb +++ b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb @@ -28,7 +28,7 @@ RSpec.describe 'create a merge request, allowing commits from members who can me check 'Allow commits from members who can merge to the target branch' - click_button 'Submit merge request' + click_button 'Create merge request' wait_for_requests diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb index 37d329d4d5d..6b0c7733ab4 100644 --- a/spec/features/merge_request/user_creates_merge_request_spec.rb +++ b/spec/features/merge_request/user_creates_merge_request_spec.rb @@ -31,7 +31,7 @@ RSpec.describe "User creates a merge request", :js do end fill_in("Title", with: title) - click_button("Submit merge request") + click_button("Create merge request") page.within(".merge-request") do expect(page).to have_content(title) @@ -103,7 +103,7 @@ RSpec.describe "User creates a merge request", :js do end find('.js-assignee-search').click - click_button("Submit merge request") + click_button("Create merge request") expect(page).to have_content(title).and have_content("Request to merge #{user.namespace.path}:#{source_branch} into master") end diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 05fa5459e06..0cb4107c21d 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -32,7 +32,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows widget status after creating new merge request' do - click_button 'Submit merge request' + click_button 'Create merge request' wait_for_requests diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb index 9850ca3f173..275a87ca391 100644 --- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb +++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb @@ -60,7 +60,7 @@ RSpec.describe 'Merge request > User selects branches for new MR', :js do expect(page).to have_content "wm.png" fill_in "merge_request_title", with: "Orphaned MR test" - click_button "Submit merge request" + click_button "Create merge request" click_button "Check out branch" @@ -200,7 +200,7 @@ RSpec.describe 'Merge request > User selects branches for new MR', :js do click_button "Compare branches" - expect(page).to have_button("Submit merge request") + expect(page).to have_button("Create merge request") end end end diff --git a/spec/features/merge_request/user_squashes_merge_request_spec.rb b/spec/features/merge_request/user_squashes_merge_request_spec.rb index 84964bd0637..15f59c0d7bc 100644 --- a/spec/features/merge_request/user_squashes_merge_request_spec.rb +++ b/spec/features/merge_request/user_squashes_merge_request_spec.rb @@ -92,7 +92,7 @@ RSpec.describe 'User squashes a merge request', :js do before do visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch }) check 'merge_request[squash]' - click_on 'Submit merge request' + click_on 'Create merge request' wait_for_requests end @@ -121,7 +121,7 @@ RSpec.describe 'User squashes a merge request', :js do context 'when squash is not enabled on merge request creation', :sidekiq_might_not_need_inline do before do visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch }) - click_on 'Submit merge request' + click_on 'Create merge request' wait_for_requests end diff --git a/spec/frontend/issue_show/components/edit_actions_spec.js b/spec/frontend/issue_show/components/edit_actions_spec.js index 6a00eec4b1f..54707879f63 100644 --- a/spec/frontend/issue_show/components/edit_actions_spec.js +++ b/spec/frontend/issue_show/components/edit_actions_spec.js @@ -48,7 +48,7 @@ describe('Edit Actions components', () => { vm.formState.title = ''; Vue.nextTick(() => { - expect(vm.$el.querySelector('.btn-success').getAttribute('disabled')).toBe('disabled'); + expect(vm.$el.querySelector('.btn-confirm').getAttribute('disabled')).toBe('disabled'); done(); }); @@ -65,16 +65,16 @@ describe('Edit Actions components', () => { describe('updateIssuable', () => { it('sends update.issauble event when clicking save button', () => { - vm.$el.querySelector('.btn-success').click(); + vm.$el.querySelector('.btn-confirm').click(); expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable'); }); it('disabled button after clicking save button', (done) => { - vm.$el.querySelector('.btn-success').click(); + vm.$el.querySelector('.btn-confirm').click(); Vue.nextTick(() => { - expect(vm.$el.querySelector('.btn-success').getAttribute('disabled')).toBe('disabled'); + expect(vm.$el.querySelector('.btn-confirm').getAttribute('disabled')).toBe('disabled'); done(); }); diff --git a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb index da966fd2200..1c816ee4b0a 100644 --- a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb +++ b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb @@ -43,7 +43,7 @@ RSpec.shared_examples 'a creatable merge request' do expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) - click_button 'Submit merge request' + click_button 'Create merge request' page.within '.issuable-sidebar' do page.within '.assignee' do diff --git a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb index 06127f2ed8c..6d44a6fde85 100644 --- a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb +++ b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb @@ -14,11 +14,11 @@ RSpec.shared_examples 'creating an issue for a thread' do end it 'can create a new issue for the project' do - expect { click_button 'Submit issue' }.to change { project.issues.reload.size }.by(1) + expect { click_button 'Create issue' }.to change { project.issues.reload.size }.by(1) end it 'resolves the discussion in the merge request' do - click_button 'Submit issue' + click_button 'Create issue' discussion.first_note.reload @@ -26,7 +26,7 @@ RSpec.shared_examples 'creating an issue for a thread' do end it 'shows a flash messaage after resolving a discussion' do - click_button 'Submit issue' + click_button 'Create issue' page.within '.flash-notice' do # Only check for the word 'Resolved' since the spec might have resolved diff --git a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb index 4fde68efd60..ca6536444fd 100644 --- a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb +++ b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb @@ -23,7 +23,7 @@ RSpec.shared_examples 'close quick action' do |issuable_type| it "creates the #{issuable_type} and interprets close quick action accordingly" do fill_in "#{issuable_type}_title", with: 'bug 345' fill_in "#{issuable_type}_description", with: "bug description\n/close" - click_button "Submit #{issuable_type}".humanize + click_button "Create #{issuable_type}".humanize issuable = project.public_send(issuable_type.to_s.pluralize).first diff --git a/spec/workers/container_expiration_policy_worker_spec.rb b/spec/workers/container_expiration_policy_worker_spec.rb index d9a4f6396f8..2d5176e874d 100644 --- a/spec/workers/container_expiration_policy_worker_spec.rb +++ b/spec/workers/container_expiration_policy_worker_spec.rb @@ -11,7 +11,7 @@ RSpec.describe ContainerExpirationPolicyWorker do describe '#perform' do subject { worker.perform } - RSpec.shared_examples 'not executing any policy' do + shared_examples 'not executing any policy' do it 'does not run any policy' do expect(ContainerExpirationPolicyService).not_to receive(:new) @@ -19,6 +19,21 @@ RSpec.describe ContainerExpirationPolicyWorker do end end + shared_examples 'handling a taken exclusive lease' do + context 'with exclusive lease taken' do + before do + stub_exclusive_lease_taken(worker.lease_key, timeout: 5.hours) + end + + it 'does not do anything' do + expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).not_to receive(:perform_with_capacity) + expect(worker).not_to receive(:runnable_policies) + + expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count } + end + end + end + context 'With no container expiration policies' do it 'does not execute any policies' do expect(ContainerRepository).not_to receive(:for_project_id) @@ -27,18 +42,77 @@ RSpec.describe ContainerExpirationPolicyWorker do end end - context 'with container expiration policies' do - let_it_be(:container_expiration_policy) { create(:container_expiration_policy, :runnable) } - let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) } + context 'with throttling enabled' do + before do + stub_feature_flags(container_registry_expiration_policies_throttling: true) + end - context 'with a valid container expiration policy' do - it 'schedules the next run' do - expect { subject }.to change { container_expiration_policy.reload.next_run_at } + context 'with loopless disabled' do + before do + stub_feature_flags(container_registry_expiration_policies_loopless: false) end - it 'marks the container repository as scheduled for cleanup' do - expect { subject }.to change { container_repository.reload.cleanup_scheduled? }.from(false).to(true) - expect(ContainerRepository.cleanup_scheduled.count).to eq(1) + context 'with container expiration policies' do + let_it_be(:container_expiration_policy) { create(:container_expiration_policy, :runnable) } + let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) } + + before do + expect(worker).to receive(:with_runnable_policy).and_call_original + end + + context 'with a valid container expiration policy' do + it 'schedules the next run' do + expect { subject }.to change { container_expiration_policy.reload.next_run_at } + end + + it 'marks the container repository as scheduled for cleanup' do + expect { subject }.to change { container_repository.reload.cleanup_scheduled? }.from(false).to(true) + expect(ContainerRepository.cleanup_scheduled.count).to eq(1) + end + + it 'calls the limited capacity worker' do + expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity) + + subject + end + end + + context 'with a disabled container expiration policy' do + before do + container_expiration_policy.disable! + end + + it 'does not run the policy' do + expect(ContainerRepository).not_to receive(:for_project_id) + + expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count } + end + end + + context 'with an invalid container expiration policy' do + let(:user) { container_expiration_policy.project.owner } + + before do + container_expiration_policy.update_column(:name_regex, '*production') + end + + it 'disables the policy and tracks an error' do + expect(ContainerRepository).not_to receive(:for_project_id) + expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(described_class::InvalidPolicyError), container_expiration_policy_id: container_expiration_policy.id) + + expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false) + expect(ContainerRepository.cleanup_scheduled).to be_empty + end + end + end + + it_behaves_like 'handling a taken exclusive lease' + end + + context 'with loopless enabled' do + before do + stub_feature_flags(container_registry_expiration_policies_loopless: true) + expect(worker).not_to receive(:with_runnable_policy) end it 'calls the limited capacity worker' do @@ -46,47 +120,8 @@ RSpec.describe ContainerExpirationPolicyWorker do subject end - end - context 'with a disabled container expiration policy' do - before do - container_expiration_policy.disable! - end - - it 'does not run the policy' do - expect(ContainerRepository).not_to receive(:for_project_id) - - expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count } - end - end - - context 'with an invalid container expiration policy' do - let(:user) { container_expiration_policy.project.owner } - - before do - container_expiration_policy.update_column(:name_regex, '*production') - end - - it 'disables the policy and tracks an error' do - expect(ContainerRepository).not_to receive(:for_project_id) - expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(described_class::InvalidPolicyError), container_expiration_policy_id: container_expiration_policy.id) - - expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false) - expect(ContainerRepository.cleanup_scheduled).to be_empty - end - end - end - - context 'with exclusive lease taken' do - before do - stub_exclusive_lease_taken(worker.lease_key, timeout: 5.hours) - end - - it 'does not execute any policy' do - expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).not_to receive(:perform_with_capacity) - expect(worker).not_to receive(:runnable_policies) - - expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count } + it_behaves_like 'handling a taken exclusive lease' end end