Commit c859c3bf authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 28ce39a3
......@@ -12,7 +12,7 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="loading" />
<div class="media-body space-children">
<span class="bold"> {{ s__('mrWidget|Checking ability to merge automatically') }} </span>
<span class="bold"> {{ s__('mrWidget|Checking ability to merge automatically') }} </span>
</div>
</div>
</template>
......@@ -7,7 +7,7 @@ export default function deviseState(data) {
return stateKey.missingBranch;
} else if (!data.commits_count) {
return stateKey.nothingToMerge;
} else if (this.mergeStatus === 'unchecked') {
} else if (this.mergeStatus === 'unchecked' || this.mergeStatus === 'checking') {
return stateKey.checking;
} else if (data.has_conflicts) {
return stateKey.conflicts;
......
......@@ -45,7 +45,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
def show
close_merge_request_if_no_source_project
@merge_request.check_mergeability
@merge_request.check_mergeability(async: true)
respond_to do |format|
format.html do
......
......@@ -26,7 +26,7 @@ module MilestonesHelper
end
end
def milestones_label_path(opts = {})
def milestones_issues_path(opts = {})
if @project
project_issues_path(@project, opts)
elsif @group
......@@ -281,6 +281,26 @@ module MilestonesHelper
can?(current_user, :admin_milestone, @project.group)
end
end
def display_issues_count_warning?
milestone_visible_issues_count > Milestone::DISPLAY_ISSUES_LIMIT
end
def milestone_issues_count_message
total_count = milestone_visible_issues_count
limit = Milestone::DISPLAY_ISSUES_LIMIT
message = _('Showing %{limit} of %{total_count} issues. ') % { limit: limit, total_count: total_count }
message += link_to(_('View all issues'), milestones_issues_path)
message.html_safe
end
private
def milestone_visible_issues_count
@milestone_visible_issues_count ||= @milestone.issues_visible_to_user(current_user).size
end
end
MilestonesHelper.prepend_if_ee('EE::MilestonesHelper')
# frozen_string_literal: true
module Milestoneish
DISPLAY_ISSUES_LIMIT = 20
def total_issues_count(user)
count_issues_by_state(user).values.sum
end
......@@ -53,7 +55,11 @@ module Milestoneish
end
def sorted_issues(user)
issues_visible_to_user(user).preload_associated_models.sort_by_attribute('label_priority')
# This method is used on milestone view to filter opened assigned, opened unassigned and closed issues columns.
# We want a limit of DISPLAY_ISSUES_LIMIT for total issues present on all columns.
limited_ids = issues_visible_to_user(user).limit(DISPLAY_ISSUES_LIMIT).select(:id)
Issue.where(id: limited_ids).preload_associated_models.sort_by_attribute('label_priority')
end
def sorted_merge_requests(user)
......
......@@ -160,20 +160,25 @@ class MergeRequest < ApplicationRecord
state_machine :merge_status, initial: :unchecked do
event :mark_as_unchecked do
transition [:can_be_merged, :unchecked] => :unchecked
transition [:can_be_merged, :checking, :unchecked] => :unchecked
transition [:cannot_be_merged, :cannot_be_merged_recheck] => :cannot_be_merged_recheck
end
event :mark_as_checking do
transition [:unchecked, :cannot_be_merged_recheck] => :checking
end
event :mark_as_mergeable do
transition [:unchecked, :cannot_be_merged_recheck] => :can_be_merged
transition [:unchecked, :cannot_be_merged_recheck, :checking] => :can_be_merged
end
event :mark_as_unmergeable do
transition [:unchecked, :cannot_be_merged_recheck] => :cannot_be_merged
transition [:unchecked, :cannot_be_merged_recheck, :checking] => :cannot_be_merged
end
state :unchecked
state :cannot_be_merged_recheck
state :checking
state :can_be_merged
state :cannot_be_merged
......@@ -191,7 +196,7 @@ class MergeRequest < ApplicationRecord
# rubocop: enable CodeReuse/ServiceClass
def check_state?(merge_status)
[:unchecked, :cannot_be_merged_recheck].include?(merge_status.to_sym)
[:unchecked, :cannot_be_merged_recheck, :checking].include?(merge_status.to_sym)
end
end
......@@ -812,10 +817,16 @@ class MergeRequest < ApplicationRecord
MergeRequests::ReloadDiffsService.new(self, current_user).execute
end
def check_mergeability
def check_mergeability(async: false)
return if Feature.enabled?(:merge_requests_conditional_mergeability_check, default_enabled: true) && !recheck_merge_status?
MergeRequests::MergeabilityCheckService.new(self).execute(retry_lease: false)
check_service = MergeRequests::MergeabilityCheckService.new(self)
if async && Feature.enabled?(:async_merge_request_check_mergeability, project)
check_service.async_execute
else
check_service.execute(retry_lease: false)
end
end
# rubocop: enable CodeReuse/ServiceClass
......
......@@ -2,16 +2,7 @@
module AkismetMethods
def spammable_owner
@user ||= User.find(spammable_owner_id)
end
def spammable_owner_id
@owner_id ||=
if spammable.respond_to?(:author_id)
spammable.author_id
elsif spammable.respond_to?(:creator_id)
spammable.creator_id
end
@user ||= User.find(spammable.author_id)
end
def akismet
......
......@@ -12,6 +12,13 @@ module MergeRequests
@merge_request = merge_request
end
def async_execute
return service_error if service_error
return unless merge_request.mark_as_checking
MergeRequestMergeabilityCheckWorker.perform_async(merge_request.id)
end
# Updates the MR merge_status. Whenever it switches to a can_be_merged state,
# the merge-ref is refreshed.
#
......@@ -30,8 +37,7 @@ module MergeRequests
# and the merge-ref is synced. Success in case of being/becoming mergeable,
# error otherwise.
def execute(recheck: false, retry_lease: true)
return ServiceResponse.error(message: 'Invalid argument') unless merge_request
return ServiceResponse.error(message: 'Unsupported operation') if Gitlab::Database.read_only?
return service_error if service_error
return check_mergeability(recheck) unless merge_ref_auto_sync_lock_enabled?
in_write_lock(retry_lease: retry_lease) do |retried|
......@@ -155,5 +161,15 @@ module MergeRequests
def merge_ref_auto_sync_lock_enabled?
Feature.enabled?(:merge_ref_auto_sync_lock, project, default_enabled: true)
end
def service_error
strong_memoize(:service_error) do
if !merge_request
ServiceResponse.error(message: 'Invalid argument')
elsif Gitlab::Database.read_only?
ServiceResponse.error(message: 'Unsupported operation')
end
end
end
end
end
......@@ -3,9 +3,6 @@
module PagesDomains
class CreateAcmeOrderService
attr_reader :pages_domain
# TODO: remove this hack after https://gitlab.com/gitlab-org/gitlab/issues/30146 is implemented
# This makes GitLab automatically retry the certificate obtaining process every 2 hours if process wasn't finished
SHORT_EXPIRATION_DELAY = 2.hours
def initialize(pages_domain)
@pages_domain = pages_domain
......@@ -20,7 +17,7 @@ module PagesDomains
private_key = OpenSSL::PKey::RSA.new(4096)
saved_order = pages_domain.acme_orders.create!(
url: order.url,
expires_at: [order.expires, SHORT_EXPIRATION_DELAY.from_now].min,
expires_at: order.expires,
private_key: private_key.to_pem,
challenge_token: challenge.token,
......
......@@ -53,7 +53,7 @@ class SpamService
def create_spam_log(api)
@spam_log = SpamLog.create!(
{
user_id: spammable_owner_id,
user_id: spammable.author_id,
title: spammable.spam_title,
description: spammable.spam_description,
source_ip: options[:ip_address],
......
......@@ -76,7 +76,7 @@
- if Feature.enabled?(:user_mode_in_session)
- if header_link?(:admin_mode)
= nav_link(controller: 'admin/sessions', html_options: { class: "d-none d-lg-block d-xl-block"}) do
= link_to destroy_admin_session_path, title: _('Leave Admin Mode'), aria: { label: _('Leave Admin Mode') }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= link_to destroy_admin_session_path, method: :post, title: _('Leave Admin Mode'), aria: { label: _('Leave Admin Mode') }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('lock-open', size: 18)
- elsif current_user.admin?
= nav_link(controller: 'admin/sessions', html_options: { class: "d-none d-lg-block d-xl-block"}) do
......
......@@ -10,4 +10,4 @@
- unless Gitlab.config.registry.enabled
%div
= icon('exclamation-triangle')
= _('Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for AutoDevOps to work.')
= _('Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work.')
- args = { show_project_name: local_assigns.fetch(:show_project_name, false),
show_full_project_name: local_assigns.fetch(:show_full_project_name, false) }
- if display_issues_count_warning?
.flash-container
.flash-warning#milestone-issue-count-warning
= milestone_issues_count_message
.row.prepend-top-default
.col-md-4
= render 'shared/milestones/issuables', args.merge(title: 'Unstarted Issues (open and unassigned)', issuables: issues.opened.unassigned, id: 'unassigned', show_counter: true)
......
......@@ -5,12 +5,12 @@
%li.no-border
%span.label-row
%span.label-name
= render_label(label, tooltip: false, link: milestones_label_path(options))
= render_label(label, tooltip: false, link: milestones_issues_path(options))
%span.prepend-description-left
= markdown_field(label, :description)
.float-right.d-none.d-lg-block.d-xl-block
= link_to milestones_label_path(options.merge(state: 'opened')), class: 'btn btn-transparent btn-action' do
= link_to milestones_issues_path(options.merge(state: 'opened')), class: 'btn btn-transparent btn-action' do
- pluralize milestone_issues_by_label_count(@milestone, label, state: :opened), 'open issue'
= link_to milestones_label_path(options.merge(state: 'closed')), class: 'btn btn-transparent btn-action' do
= link_to milestones_issues_path(options.merge(state: 'closed')), class: 'btn btn-transparent btn-action' do
- pluralize milestone_issues_by_label_count(@milestone, label, state: :closed), 'closed issue'
......@@ -191,3 +191,4 @@
- group_export
- self_monitoring_project_create
- self_monitoring_project_delete
- merge_request_mergeability_check
# frozen_string_literal: true
class MergeRequestMergeabilityCheckWorker
include ApplicationWorker
feature_category :source_code_management
def perform(merge_request_id)
merge_request = MergeRequest.find_by_id(merge_request_id)
unless merge_request
logger.error("Failed to find merge request with ID: #{merge_request_id}")
return
end
result =
::MergeRequests::MergeabilityCheckService
.new(merge_request)
.execute(recheck: false, retry_lease: false)
logger.error("Failed to check mergeability of merge request (#{merge_request_id}): #{result.message}") if result.error?
end
end
---
title: Check mergeability of MR asynchronously
merge_request: 21026
author:
type: performance
---
title: Retry obtaining Let's Encrypt certificates every 2 hours if it wasn't successful
merge_request: 22336
author:
type: fixed
---
title: Fix POST method in dashboard link for disabling admin mode
merge_request: 23363
author: Diego Louzán
type: fixed
---
title: Limits issues displayed on milestones
merge_request: 23102
author:
type: performance
......@@ -102,6 +102,7 @@
- [self_monitoring_project_create, 2]
- [self_monitoring_project_delete, 2]
- [error_tracking_issue_link, 2]
- [merge_request_mergeability_check, 5]
# EE-specific queues
- [analytics, 1]
......
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class UpdateTimestampSoftwarelicensespolicy < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
time = Time.zone.now
update_column_in_batches(:software_license_policies, :created_at, time) do |table, query|
query.where(table[:created_at].eq(nil))
end
update_column_in_batches(:software_license_policies, :updated_at, time) do |table, query|
query.where(table[:updated_at].eq(nil))
end
end
def down
# no-op
end
end
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class UpdateTimestampSoftwarelicensespolicyNotNull < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
change_column_null(:software_license_policies, :created_at, false)
change_column_null(:software_license_policies, :updated_at, false)
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_01_17_112554) do
ActiveRecord::Schema.define(version: 2020_01_21_132641) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
......@@ -3857,8 +3857,8 @@ ActiveRecord::Schema.define(version: 2020_01_17_112554) do
t.integer "project_id", null: false
t.integer "software_license_id", null: false
t.integer "classification", default: 0, null: false
t.datetime_with_timezone "created_at"
t.datetime_with_timezone "updated_at"
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.index ["project_id", "software_license_id"], name: "index_software_license_policies_unique_per_project", unique: true
t.index ["software_license_id"], name: "index_software_license_policies_on_software_license_id"
end
......
......@@ -61,6 +61,12 @@ Parameters:
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
NOTE: **Note:**
[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/issues/29984),
the mergeability (`merge_status`) of each merge request will be checked
asynchronously when a request is made to this endpoint. Poll this API endpoint
to get updated status.
```json
[
{
......@@ -526,6 +532,12 @@ Parameters:
- `include_diverged_commits_count` (optional) - If `true` response includes the commits behind the target branch
- `include_rebase_in_progress` (optional) - If `true` response includes whether a rebase operation is in progress
NOTE: **Note:**
[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/issues/29984),
the mergeability (`merge_status`) of a merge request will be checked
asynchronously when a request is made to this endpoint. Poll this API endpoint
to get updated status.
```json
{
"id": 1,
......
......@@ -2103,7 +2103,7 @@ The `codequality` report collects [CodeQuality issues](../../user/project/merge_
as artifacts.
The collected Code Quality report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
be summarized in merge requests. It is not available for download through the web interface.
##### `artifacts:reports:sast` **(ULTIMATE)**
......@@ -2113,8 +2113,8 @@ The `sast` report collects [SAST vulnerabilities](../../user/application_securit
as artifacts.
The collected SAST report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
be summarized in the merge requests and pipeline view. It is also used to provide data for security
dashboards. It is not available for download through the web interface.
##### `artifacts:reports:dependency_scanning` **(ULTIMATE)**
......@@ -2124,8 +2124,8 @@ The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](
as artifacts.
The collected Dependency Scanning report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
be summarized in the merge requests and pipeline view. It is also used to provide data for security
dashboards. It is not available for download through the web interface.
##### `artifacts:reports:container_scanning` **(ULTIMATE)**
......@@ -2135,8 +2135,8 @@ The `container_scanning` report collects [Container Scanning vulnerabilities](..
as artifacts.
The collected Container Scanning report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
be summarized in the merge requests and pipeline view. It is also used to provide data for security
dashboards. It is not available for download through the web interface.
##### `artifacts:reports:dast` **(ULTIMATE)**
......@@ -2146,8 +2146,8 @@ The `dast` report collects [DAST vulnerabilities](../../user/application_securit
as artifacts.
The collected DAST report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
be summarized in the merge requests and pipeline view. It is also used to provide data for security
dashboards. It is not available for download through the web interface.
##### `artifacts:reports:license_management` **(ULTIMATE)**
......@@ -2157,8 +2157,8 @@ The `license_management` report collects [Licenses](../../user/application_secur
as artifacts.
The collected License Compliance report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
be summarized in the merge requests and pipeline view. It is also used to provide data for security
dashboards. It is not available for download through the web interface.
##### `artifacts:reports:performance` **(PREMIUM)**
......@@ -2168,7 +2168,7 @@ The `performance` report collects [Performance metrics](../../user/project/merge
as artifacts.
The collected Performance report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
be automatically shown in merge requests. It is not available for download through the web interface.
##### `artifacts:reports:metrics` **(PREMIUM)**
......@@ -2178,7 +2178,7 @@ The `metrics` report collects [Metrics](../../ci/metrics_reports.md)
as artifacts.
The collected Metrics report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
be automatically shown in merge requests. It is not available for download through the web interface.
### `dependencies`
......
......@@ -23,10 +23,14 @@ noted information:
If you hover over a commit in the UI, you'll see a precise date and time
for that commit.
![Blame previous commit](img/file_blame_previous_commit_v12_7.png "Blame previous commit")
## Blame previous commit
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/19299) in GitLab 12.7.
To see earlier revisions of a specific line, click **View blame prior to this change**
until you've found the changes you're interested in viewing.
until you've found the changes you're interested in viewing:
![Blame previous commit](img/file_blame_previous_commit_v12_7.png "Blame previous commit")
## Associated `git` command
......
......@@ -69,7 +69,7 @@ Follow these steps to do so:
have access to your GitLab instance. We recommend **putting this behind an alias** so it can be
changed if needed, and **[enabling Akismet](../../integration/akismet.md)** on your GitLab
instance to add spam checking to this service. Unblocked email spam would result in many spam
issues being created, and may disrupt your GitLab service.
issues being created.
If you have [templates](description_templates.md) in your repository, you can optionally select
one from the selector menu to append it to all Service Desk issues.
......
......@@ -811,7 +811,7 @@ module API
# See https://gitlab.com/gitlab-org/gitlab-foss/issues/42344 for more
# information.
expose :merge_status do |merge_request|
merge_request.check_mergeability
merge_request.check_mergeability(async: true)
merge_request.merge_status
end
expose :diff_head_sha, as: :sha
......
......@@ -4951,7 +4951,7 @@ msgstr ""
msgid "Container registry images"
msgstr ""
msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for AutoDevOps to work."
msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work."
msgstr ""
msgid "ContainerRegistry|Automatically remove extra images that aren't designed to be kept."
......@@ -5759,13 +5759,22 @@ msgstr ""
msgid "CycleAnalytics|Days to completion"
msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
msgid "CycleAnalytics|No stages selected"
msgstr ""
msgid "CycleAnalytics|Number of tasks"
msgstr ""
msgid "CycleAnalytics|Showing %{subject} and %{selectedLabelsCount} labels"
msgid "CycleAnalytics|Select labels"
msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
msgstr ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
......@@ -17051,6 +17060,9 @@ msgid_plural "Showing %d events"
msgstr[0] ""
msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
......@@ -20671,6 +20683,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
msgid "View all issues"
msgstr ""
msgid "View blame prior to this change"
msgstr ""
......@@ -22442,7 +22457,7 @@ msgstr ""
msgid "mrWidget|Check out branch"
msgstr ""
msgid "mrWidget|Checking ability to merge automatically"
msgid "mrWidget|Checking ability to merge automatically"
msgstr ""
msgid "mrWidget|Cherry-pick"
......
......@@ -44,6 +44,21 @@ describe Projects::MergeRequestsController do
get :show, params: params.merge(extra_params)
end
context 'when merge request is unchecked' do
before do
merge_request.mark_as_unchecked!
end
it 'checks mergeability asynchronously' do
expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
expect(service).not_to receive(:execute)
expect(service).to receive(:async_execute)
end
go
end
end
describe 'as html' do
context 'when diff files were cleaned' do
render_views
......
......@@ -9,7 +9,7 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc
let(:admin) { create(:admin) }
context 'feature flag :user_mode_in_session is enabled' do
context 'feature flag :user_mode_in_session is enabled', :request_store do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
......@@ -486,10 +486,24 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc
end
end
it 'can leave admin mode' do
it 'can leave admin mode using main dashboard link', :js do
page.within('.navbar-sub-nav') do
# Select first, link is also included in mobile view list
click_on 'Leave Admin Mode', match: :first
click_on 'Leave Admin Mode'
expect(page).to have_link(href: new_admin_session_path)
end
end
it 'can leave admin mode using dropdown menu on smaller screens', :js do
resize_screen_xs
visit root_dashboard_path
find('.header-more').click
page.within '.navbar-sub-nav' do
click_on 'Leave Admin Mode'
find('.header-more').click
expect(page).to have_link(href: new_admin_session_path)
end
......
......@@ -19,7 +19,7 @@ describe 'Merge request > User sees merge widget', :js do
sign_in(user)
end
context 'new merge request' do
context 'new merge request', :sidekiq_might_not_need_inline do
before do
visit project_new_merge_request_path(
project,
......
......@@ -67,7 +67,7 @@ describe 'User squashes a merge request', :js do
end
end
context 'when squash is enabled on merge request creation' do
context 'when squash is 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 })
check 'merge_request[squash]'
......@@ -97,7 +97,7 @@ describe 'User squashes a merge request', :js do
end
end
context 'when squash is not enabled on merge request creation' 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'
......
......@@ -25,6 +25,37 @@ describe "User views milestone" do
expect { visit_milestone }.not_to exceed_query_limit(control)
end
context 'limiting milestone issues' do
before_all do
2.times do
create(:issue, milestone: milestone, project: project)
create(:issue, milestone: milestone, project: project, assignees: [user])
create(:issue, milestone: milestone, project: project, state: :closed)
end
end
context 'when issues on milestone are over DISPLAY_ISSUES_LIMIT' do
it "limits issues to display and shows warning" do
stub_const('Milestoneish::DISPLAY_ISSUES_LIMIT', 3)
visit(project_milestone_path(project, milestone))
expect(page).to have_selector('.issuable-row', count: 3)
expect(page).to have_selector('#milestone-issue-count-warning', text: 'Showing 3 of 6 issues. View all issues')
expect(page).to have_link('View all issues', href: project_issues_path(project))
end
end
context 'when issues on milestone are below DISPLAY_ISSUES_LIMIT' do
it 'does not display warning' do
visit(project_milestone_path(project, milestone))
expect(page).not_to have_selector('#milestone-issue-count-warning', text: 'Showing 3 of 6 issues. View all issues')
expect(page).to have_selector('.issuable-row', count: 6)
end
end
end
private
def visit_milestone
......
......@@ -25,7 +25,7 @@ describe('MRWidgetChecking', () => {
it('renders information about merging', () => {
expect(vm.$el.querySelector('.media-body').textContent.trim()).toEqual(
'Checking ability to merge automatically',
'Checking ability to merge automatically',
);
});
});
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20200116175538_update_timestamp_softwarelicensespolicy.rb')
describe UpdateTimestampSoftwarelicensespolicy, :migration do
let(:software_licenses_policy) { table(:software_license_policies) }
let(:projects) { table(:projects) }
let(:licenses) { table(:software_licenses) }
before do
projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1)
licenses.create!(name: 'MIT')
software_licenses_policy.create!(project_id: projects.first.id, software_license_id: licenses.first.id, created_at: nil, updated_at: nil)
end
it 'creates timestamps' do
migrate!
expect(software_licenses_policy.first.created_at).to be_present
expect(software_licenses_policy.first.updated_at).to be_present
end
end
......@@ -33,17 +33,32 @@ describe Milestone, 'Milestoneish' do
end
describe '#sorted_issues' do
it 'sorts issues by label priority' do
before do
issue.labels << label_1
security_issue_1.labels << label_2
closed_issue_1.labels << label_3
end
it 'sorts issues by label priority' do
issues = milestone.sorted_issues(member)
expect(issues.first).to eq(issue)
expect(issues.second).to eq(security_issue_1)
expect(issues.third).not_to eq(closed_issue_1)
end
it 'limits issue count' do
stub_const('Milestoneish::DISPLAY_ISSUES_LIMIT', 4)
issues = milestone.sorted_issues(member)
# Cannot use issues.count here because it is sorting
# by a virtual column 'highest_priority' and it will break
# the query.
total_issues_count = issues.opened.unassigned.length + issues.opened.assigned.length + issues.closed.length
expect(issues.length).to eq(4)
expect(total_issues_count).to eq(4)
end
end
context 'attributes visibility' do
......
......@@ -277,6 +277,7 @@ describe MergeRequest do
describe 'respond to' do
it { is_expected.to respond_to(:unchecked?) }
it { is_expected.to respond_to(:checking?) }
it { is_expected.to respond_to(:can_be_merged?) }
it { is_expected.to respond_to(:cannot_be_merged?) }
it { is_expected.to respond_to(:merge_params) }
......@@ -2084,43 +2085,75 @@ describe MergeRequest do
describe '#check_mergeability' do
let(:mergeability_service) { double }
subject { create(:merge_request, merge_status: 'unchecked') }
before do
allow(MergeRequests::MergeabilityCheckService).to receive(:new) do
mergeability_service
end
end
context 'if the merge status is unchecked' do
before do
subject.mark_as_unchecked!
end
shared_examples_for 'method that executes MergeabilityCheckService' do
it 'executes MergeabilityCheckService' do
expect(mergeability_service).to receive(:execute)
subject.check_mergeability
end
context 'when async is true' do
context 'and async_merge_request_check_mergeability feature flag is enabled' do
it 'executes MergeabilityCheckService asynchronously' do
expect(mergeability_service).to receive(:async_execute)
subject.check_mergeability(async: true)
end
end
context 'and async_merge_request_check_mergeability feature flag is disabled' do
before do
stub_feature_flags(async_merge_request_check_mergeability: false)
end
it 'executes MergeabilityCheckService' do
expect(mergeability_service).to receive(:execute)
subject.check_mergeability(async: true)
end
end
end
end
context 'if the merge status is unchecked' do
it_behaves_like 'method that executes MergeabilityCheckService'
end
context 'if the merge status is checking' do
before do
subject.mark_as_checking!
end
it_behaves_like 'method that executes MergeabilityCheckService'
end
context 'if the merge status is checked' do
context 'and feature flag is enabled' do
it 'executes MergeabilityCheckService' do
expect(mergeability_service).not_to receive(:execute)
before do
subject.mark_as_mergeable!
end
context 'and merge_requests_conditional_mergeability_check feature flag is enabled' do
it 'does not call MergeabilityCheckService' do
expect(MergeRequests::MergeabilityCheckService).not_to receive(:new)
subject.check_mergeability
end
end
context 'and feature flag is disabled' do
context 'and merge_requests_conditional_mergeability_check feature flag is disabled' do
before do
stub_feature_flags(merge_requests_conditional_mergeability_check: false)
end
it 'does not execute MergeabilityCheckService' do
expect(mergeability_service).to receive(:execute)
subject.check_mergeability
end
it_behaves_like 'method that executes MergeabilityCheckService'
end
end
end
......@@ -3145,7 +3178,7 @@ describe MergeRequest do
describe 'check_state?' do
it 'indicates whether MR is still checking for mergeability' do
state_machine = described_class.state_machines[:merge_status]
check_states = [:unchecked, :cannot_be_merged_recheck]
check_states = [:unchecked, :cannot_be_merged_recheck, :checking]
check_states.each do |merge_status|
expect(state_machine.check_state?(merge_status)).to be true
......
......@@ -65,6 +65,21 @@ describe API::MergeRequests do
end.not_to exceed_query_limit(control)
end
context 'when merge request is unchecked' do
before do
merge_request.mark_as_unchecked!
end
it 'checks mergeability asynchronously' do
expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
expect(service).not_to receive(:execute)
expect(service).to receive(:async_execute)
end
get api(endpoint_path, user)
end
end
context 'with labels' do
include_context 'with labels'
......@@ -1003,6 +1018,21 @@ describe API::MergeRequests do
expect(json_response['user']['can_merge']).to be_falsy
end
context 'when merge request is unchecked' do
before do
merge_request.mark_as_unchecked!
end
it 'checks mergeability asynchronously' do
expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
expect(service).not_to receive(:execute)
expect(service).to receive(:async_execute)
end
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
end
end
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/participants' do
......
......@@ -53,9 +53,42 @@ describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shared_sta
end
end
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, merge_status: :unchecked, source_project: project, target_project: project) }
describe '#async_execute' do
shared_examples_for 'no job is enqueued' do
it 'does not enqueue MergeRequestMergeabilityCheckWorker' do
expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async)
described_class.new(merge_request).async_execute
end
end
it 'enqueues MergeRequestMergeabilityCheckWorker' do
expect(MergeRequestMergeabilityCheckWorker).to receive(:perform_async)
described_class.new(merge_request).async_execute
end
context 'when read only DB' do
before do
allow(Gitlab::Database).to receive(:read_only?) { true }
end
it_behaves_like 'no job is enqueued'
end
context 'when merge_status is already checking' do
before do
merge_request.mark_as_checking
end
it_behaves_like 'no job is enqueued'
end
end
describe '#execute' do
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, merge_status: :unchecked, source_project: project, target_project: project) }
let(:repo) { project.repository }
subject { described_class.new(merge_request).execute }
......
......@@ -45,34 +45,12 @@ describe PagesDomains::CreateAcmeOrderService do
expect { OpenSSL::PKey::RSA.new(saved_order.private_key) }.not_to raise_error
end
it 'properly saves order url' do
it 'properly saves order attributes' do
service.execute
saved_order = PagesDomainAcmeOrder.last
expect(saved_order.url).to eq(order_double.url)
end
context 'when order expires in 2 days' do
it 'sets expiration time in 2 hours' do
Timecop.freeze do
service.execute
saved_order = PagesDomainAcmeOrder.last
expect(saved_order.expires_at).to be_like_time(2.hours.from_now)
end
end
end
context 'when order expires in an hour' do
it 'sets expiration time accordingly to order' do
Timecop.freeze do
allow(order_double).to receive(:expires).and_return(1.hour.from_now)
service.execute
saved_order = PagesDomainAcmeOrder.last
expect(saved_order.expires_at).to be_like_time(1.hour.from_now)
end
end
expect(saved_order.expires_at).to be_like_time(order_double.expires)
end
it 'properly saves challenge attributes' do
......
# frozen_string_literal: true
require 'spec_helper'
describe MergeRequestMergeabilityCheckWorker do
subject { described_class.new }
describe '#perform' do
context 'when merge request does not exist' do
it 'does not execute MergeabilityCheckService' do
expect(MergeRequests::MergeabilityCheckService).not_to receive(:new)
subject.perform(1)
end
end
context 'when merge request exists' do
let(:merge_request) { create(:merge_request) }
it 'executes MergeabilityCheckService' do
expect_next_instance_of(MergeRequests::MergeabilityCheckService, merge_request) do |service|
expect(service).to receive(:execute).and_return(double(error?: false))
end
subject.perform(merge_request.id)
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment