Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-03-30 06:09:35 +00:00
parent 38d957659e
commit 0eeb173641
27 changed files with 281 additions and 175 deletions

View file

@ -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') }}
</gl-button>
<gl-button class="float-right" @click="closeForm">
<gl-button @click="closeForm">
{{ __('Cancel') }}
</gl-button>
<gl-button
v-if="shouldShowDeleteButton"
:loading="deleteLoading"
:disabled="deleteLoading"
category="primary"
category="secondary"
variant="danger"
class="float-right gl-mr-3 qa-delete-button"
class="float-right qa-delete-button"
@click="deleteIssuable"
>
{{ deleteIssuableButtonText }}

View file

@ -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;
}

View file

@ -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

View file

@ -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'

View file

@ -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)

View file

@ -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

View file

@ -0,0 +1,5 @@
---
title: Update issuable submit content order, button variants, and button alignment
merge_request: 57172
author:
type: other

View file

@ -0,0 +1,5 @@
---
title: Review and revise Integrations/Asana UI text
merge_request: 57362
author:
type: other

View file

@ -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

View file

@ -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: <https://developers.asana.com/docs/#authentication-basics>.
```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

View file

@ -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**.
<!-- ## Troubleshooting -->

View file

@ -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 |

View file

@ -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 ""

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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();
});

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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