Commit a570beca authored by John Jarvis's avatar John Jarvis

Merge branch '11-9-stable-patch-5' into '11-9-stable'

Prepare 11.9.5 release

See merge request gitlab-org/gitlab-ce!26866
parents 47339506 9a969fe4
...@@ -315,7 +315,7 @@ cloud-native-image: ...@@ -315,7 +315,7 @@ cloud-native-image:
variables: variables:
GIT_DEPTH: "1" GIT_DEPTH: "1"
cache: {} cache: {}
when: always when: manual
script: script:
- gem install gitlab --no-document - gem install gitlab --no-document
- CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng - CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng
......
...@@ -128,9 +128,6 @@ export default { ...@@ -128,9 +128,6 @@ export default {
isModeChanged() { isModeChanged() {
return this.diffFile.viewer.name === diffViewerModes.mode_changed; return this.diffFile.viewer.name === diffViewerModes.mode_changed;
}, },
showExpandDiffToFullFileEnabled() {
return gon.features.expandDiffFullFile && !this.diffFile.is_fully_expanded;
},
}, },
mounted() { mounted() {
polyfillSticky(this.$refs.header); polyfillSticky(this.$refs.header);
...@@ -258,7 +255,7 @@ export default { ...@@ -258,7 +255,7 @@ export default {
<icon name="external-link" /> <icon name="external-link" />
</gl-button> </gl-button>
<gl-button <gl-button
v-if="showExpandDiffToFullFileEnabled" v-if="!diffFile.is_fully_expanded"
class="expand-file js-expand-file" class="expand-file js-expand-file"
@click="toggleFullDiff(diffFile.file_path)" @click="toggleFullDiff(diffFile.file_path)"
> >
......
...@@ -16,11 +16,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -16,11 +16,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :authenticate_user!, only: [:assign_related_issues] before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do
push_frontend_feature_flag(:diff_tree_filtering, default_enabled: true)
push_frontend_feature_flag(:expand_diff_full_file)
end
def index def index
@merge_requests = @issuables @merge_requests = @issuables
......
...@@ -57,7 +57,7 @@ class DiffFileEntity < DiffFileBaseEntity ...@@ -57,7 +57,7 @@ class DiffFileEntity < DiffFileBaseEntity
diff_file.diff_lines_for_serializer diff_file.diff_lines_for_serializer
end end
expose :is_fully_expanded, if: -> (diff_file, _) { Feature.enabled?(:expand_diff_full_file, default_enabled: true) && diff_file.text? } do |diff_file| expose :is_fully_expanded, if: -> (diff_file, _) { diff_file.text? } do |diff_file|
diff_file.fully_expanded? diff_file.fully_expanded?
end end
......
...@@ -9,7 +9,7 @@ module Projects ...@@ -9,7 +9,7 @@ module Projects
end end
def execute def execute
Projects::HousekeepingService.new(@project).execute do Projects::HousekeepingService.new(@project, :gc).execute do
repository.delete_all_refs_except(RESERVED_REF_PREFIXES) repository.delete_all_refs_except(RESERVED_REF_PREFIXES)
end end
rescue Projects::HousekeepingService::LeaseTaken => e rescue Projects::HousekeepingService::LeaseTaken => e
......
...@@ -18,8 +18,9 @@ module Projects ...@@ -18,8 +18,9 @@ module Projects
end end
end end
def initialize(project) def initialize(project, task = nil)
@project = project @project = project
@task = task
end end
def execute def execute
...@@ -69,6 +70,8 @@ module Projects ...@@ -69,6 +70,8 @@ module Projects
end end
def task def task
return @task if @task
if pushes_since_gc % gc_period == 0 if pushes_since_gc % gc_period == 0
:gc :gc
elsif pushes_since_gc % full_repack_period == 0 elsif pushes_since_gc % full_repack_period == 0
......
---
title: Force to recreate all MR diffs on import
merge_request: 26480
author:
type: fixed
---
title: Fix API /project/:id/branches not returning correct merge status
merge_request: 26785
author:
type: fixed
---
title: Avoid excessive recursive calls with Rugged TreeEntries
merge_request: 26813
author:
type: fixed
---
title: Force a full GC after importing a project
merge_request: 26803
author:
type: performance
...@@ -523,7 +523,7 @@ Parameters: ...@@ -523,7 +523,7 @@ Parameters:
| `username` | string | yes | The username of the user created to be used with GitLab/JIRA. | | `username` | string | yes | The username of the user created to be used with GitLab/JIRA. |
| `password` | string | yes | The password of the user created to be used with GitLab/JIRA. | | `password` | string | yes | The password of the user created to be used with GitLab/JIRA. |
| `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). | | `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). |
| `jira_issue_transition_id` | integer | no | The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. | | `jira_issue_transition_id` | string | no | The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. |
### Delete JIRA service ### Delete JIRA service
......
...@@ -34,11 +34,11 @@ module API ...@@ -34,11 +34,11 @@ module API
repository = user_project.repository repository = user_project.repository
branches = BranchesFinder.new(repository, declared_params(include_missing: false)).execute branches = BranchesFinder.new(repository, declared_params(include_missing: false)).execute
branches = ::Kaminari.paginate_array(branches) branches = paginate(::Kaminari.paginate_array(branches))
merged_branch_names = repository.merged_branch_names(branches.map(&:name)) merged_branch_names = repository.merged_branch_names(branches.map(&:name))
present( present(
paginate(branches), branches,
with: Entities::Branch, with: Entities::Branch,
current_user: current_user, current_user: current_user,
project: user_project, project: user_project,
......
...@@ -15,12 +15,23 @@ module Gitlab ...@@ -15,12 +15,23 @@ module Gitlab
override :tree_entries override :tree_entries
def tree_entries(repository, sha, path, recursive) def tree_entries(repository, sha, path, recursive)
if Feature.enabled?(:rugged_tree_entries) if Feature.enabled?(:rugged_tree_entries)
tree_entries_from_rugged(repository, sha, path, recursive) tree_entries_with_flat_path_from_rugged(repository, sha, path, recursive)
else else
super super
end end
end end
def tree_entries_with_flat_path_from_rugged(repository, sha, path, recursive)
tree_entries_from_rugged(repository, sha, path, recursive).tap do |entries|
# This was an optimization to reduce N+1 queries for Gitaly
# (https://gitlab.com/gitlab-org/gitaly/issues/530). It
# used to be done lazily in the view via
# TreeHelper#flatten_tree, so it's possible there's a
# performance impact by loading this eagerly.
rugged_populate_flat_path(repository, sha, path, entries)
end
end
def tree_entries_from_rugged(repository, sha, path, recursive) def tree_entries_from_rugged(repository, sha, path, recursive)
current_path_entries = get_tree_entries_from_rugged(repository, sha, path) current_path_entries = get_tree_entries_from_rugged(repository, sha, path)
ordered_entries = [] ordered_entries = []
...@@ -32,13 +43,6 @@ module Gitlab ...@@ -32,13 +43,6 @@ module Gitlab
ordered_entries.concat(tree_entries_from_rugged(repository, sha, entry.path, true)) ordered_entries.concat(tree_entries_from_rugged(repository, sha, entry.path, true))
end end
end end
# This was an optimization to reduce N+1 queries for Gitaly
# (https://gitlab.com/gitlab-org/gitaly/issues/530). It
# used to be done lazily in the view via
# TreeHelper#flatten_tree, so it's possible there's a
# performance impact by loading this eagerly.
rugged_populate_flat_path(repository, sha, path, ordered_entries)
end end
def rugged_populate_flat_path(repository, sha, path, entries) def rugged_populate_flat_path(repository, sha, path, entries)
......
...@@ -38,7 +38,6 @@ module Gitlab ...@@ -38,7 +38,6 @@ module Gitlab
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists = false) def insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists = false)
# These fields are set so we can create the correct merge request # These fields are set so we can create the correct merge request
# diffs. # diffs.
...@@ -47,24 +46,21 @@ module Gitlab ...@@ -47,24 +46,21 @@ module Gitlab
merge_request.keep_around_commit merge_request.keep_around_commit
# We force to recreate all diffs to replace all existing data
# We use `.all` as otherwise `dependent: :nullify` (the default)
# takes an effect
merge_request.merge_request_diffs.all.delete_all if already_exists
# MR diffs normally use an "after_save" hook to pull data from Git. # MR diffs normally use an "after_save" hook to pull data from Git.
# All of this happens in the transaction started by calling # All of this happens in the transaction started by calling
# create/save/etc. This in turn can lead to these transactions being # create/save/etc. This in turn can lead to these transactions being
# held open for much longer than necessary. To work around this we # held open for much longer than necessary. To work around this we
# first save the diff, then populate it. # first save the diff, then populate it.
diff = diff = merge_request.merge_request_diffs.build
if already_exists
merge_request.merge_request_diffs.take ||
merge_request.merge_request_diffs.build
else
merge_request.merge_request_diffs.build
end
diff.importing = true diff.importing = true
diff.save diff.save
diff.save_git_content diff.save_git_content
end end
# rubocop: enable CodeReuse/ActiveRecord
end end
end end
end end
...@@ -29,7 +29,10 @@ namespace :gitlab do ...@@ -29,7 +29,10 @@ namespace :gitlab do
# If MySQL, turn off foreign key checks # If MySQL, turn off foreign key checks
connection.execute('SET FOREIGN_KEY_CHECKS=0') if Gitlab::Database.mysql? connection.execute('SET FOREIGN_KEY_CHECKS=0') if Gitlab::Database.mysql?
tables = connection.data_sources # connection.tables is deprecated in MySQLAdapter, but in PostgreSQLAdapter
# data_sources returns both views and tables, so use #tables instead
tables = Gitlab::Database.mysql? ? connection.data_sources : connection.tables
# Removes the entry from the array # Removes the entry from the array
tables.delete 'schema_migrations' tables.delete 'schema_migrations'
# Truncate schema_migrations to ensure migrations re-run # Truncate schema_migrations to ensure migrations re-run
......
...@@ -14,7 +14,7 @@ module QA ...@@ -14,7 +14,7 @@ module QA
def personal_access_token def personal_access_token
@personal_access_token ||= begin @personal_access_token ||= begin
# you can set the environment variable PERSONAL_ACCESS_TOKEN # you can set the environment variable GITLAB_QA_ACCESS_TOKEN
# to use a specific access token rather than create one from the UI # to use a specific access token rather than create one from the UI
Runtime::Env.personal_access_token ||= create_personal_access_token Runtime::Env.personal_access_token ||= create_personal_access_token
end end
......
...@@ -53,7 +53,7 @@ module QA ...@@ -53,7 +53,7 @@ module QA
# specifies token that can be used for the api # specifies token that can be used for the api
def personal_access_token def personal_access_token
@personal_access_token ||= ENV['PERSONAL_ACCESS_TOKEN'] @personal_access_token ||= ENV['GITLAB_QA_ACCESS_TOKEN']
end end
def remote_grid def remote_grid
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require_relative '../../qa' require_relative '../../qa'
# This script deletes all subgroups of a group specified by ENV['GROUP_NAME_OR_PATH'] # This script deletes all subgroups of a group specified by ENV['GROUP_NAME_OR_PATH']
# Required environment variables: PERSONAL_ACCESS_TOKEN and GITLAB_ADDRESS # Required environment variables: GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS
# Optional environment variable: GROUP_NAME_OR_PATH (defaults to 'gitlab-qa-sandbox-group') # Optional environment variable: GROUP_NAME_OR_PATH (defaults to 'gitlab-qa-sandbox-group')
# Run `rake delete_subgroups` # Run `rake delete_subgroups`
...@@ -14,9 +14,9 @@ module QA ...@@ -14,9 +14,9 @@ module QA
def initialize def initialize
raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS'] raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
raise ArgumentError, "Please provide PERSONAL_ACCESS_TOKEN" unless ENV['PERSONAL_ACCESS_TOKEN'] raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN" unless ENV['GITLAB_QA_ACCESS_TOKEN']
@api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['PERSONAL_ACCESS_TOKEN']) @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['GITLAB_QA_ACCESS_TOKEN'])
end end
def run def run
......
...@@ -4,7 +4,7 @@ require 'securerandom' ...@@ -4,7 +4,7 @@ require 'securerandom'
require 'faker' require 'faker'
require_relative '../../qa' require_relative '../../qa'
# This script generates testdata for Performance Testing. # This script generates testdata for Performance Testing.
# Required environment variables: PERSONAL_ACCESS_TOKEN and GITLAB_ADDRESS # Required environment variables: GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS
# This job creates a urls.txt which contains a hash of all the URLs needed for Performance Testing # This job creates a urls.txt which contains a hash of all the URLs needed for Performance Testing
# Run `rake generate_perf_testdata` # Run `rake generate_perf_testdata`
...@@ -15,9 +15,9 @@ module QA ...@@ -15,9 +15,9 @@ module QA
def initialize def initialize
raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS'] raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
raise ArgumentError, "Please provide PERSONAL_ACCESS_TOKEN" unless ENV['PERSONAL_ACCESS_TOKEN'] raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN" unless ENV['GITLAB_QA_ACCESS_TOKEN']
@api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['PERSONAL_ACCESS_TOKEN']) @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['GITLAB_QA_ACCESS_TOKEN'])
@group_name = "gitlab-qa-perf-sandbox-#{SecureRandom.hex(8)}" @group_name = "gitlab-qa-perf-sandbox-#{SecureRandom.hex(8)}"
@project_name = "my-test-project-#{SecureRandom.hex(8)}" @project_name = "my-test-project-#{SecureRandom.hex(8)}"
@urls = {} @urls = {}
......
...@@ -90,13 +90,13 @@ describe QA::Runtime::Env do ...@@ -90,13 +90,13 @@ describe QA::Runtime::Env do
described_class.instance_variable_set(:@personal_access_token, nil) described_class.instance_variable_set(:@personal_access_token, nil)
end end
context 'when PERSONAL_ACCESS_TOKEN is set' do context 'when GITLAB_QA_ACCESS_TOKEN is set' do
before do before do
stub_env('PERSONAL_ACCESS_TOKEN', 'a_token') stub_env('GITLAB_QA_ACCESS_TOKEN', 'a_token_too')
end end
it 'returns specified token from env' do it 'returns specified token from env' do
expect(described_class.personal_access_token).to eq 'a_token' expect(described_class.personal_access_token).to eq 'a_token_too'
end end
end end
......
...@@ -23,9 +23,6 @@ describe('diff_file_header', () => { ...@@ -23,9 +23,6 @@ describe('diff_file_header', () => {
}); });
beforeEach(() => { beforeEach(() => {
gon.features = {
expandDiffFullFile: true,
};
const diffFile = diffDiscussionMock.diff_file; const diffFile = diffDiscussionMock.diff_file;
diffFile.added_lines = 2; diffFile.added_lines = 2;
......
...@@ -19,7 +19,7 @@ describe Gitlab::Git::Tree, :seed_helper do ...@@ -19,7 +19,7 @@ describe Gitlab::Git::Tree, :seed_helper do
it 'returns a list of tree objects' do it 'returns a list of tree objects' do
entries = described_class.where(repository, SeedRepo::Commit::ID, 'files', true) entries = described_class.where(repository, SeedRepo::Commit::ID, 'files', true)
expect(entries.count).to be > 10 expect(entries.count).to be >= 5
expect(entries).to all(be_a(Gitlab::Git::Tree)) expect(entries).to all(be_a(Gitlab::Git::Tree))
end end
......
...@@ -11,6 +11,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -11,6 +11,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
let(:source_commit) { project.repository.commit('feature') } let(:source_commit) { project.repository.commit('feature') }
let(:target_commit) { project.repository.commit('master') } let(:target_commit) { project.repository.commit('master') }
let(:milestone) { create(:milestone, project: project) } let(:milestone) { create(:milestone, project: project) }
let(:state) { :closed }
let(:pull_request) do let(:pull_request) do
alice = Gitlab::GithubImport::Representation::User.new(id: 4, login: 'alice') alice = Gitlab::GithubImport::Representation::User.new(id: 4, login: 'alice')
...@@ -26,13 +27,13 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -26,13 +27,13 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
source_repository_id: 400, source_repository_id: 400,
target_repository_id: 200, target_repository_id: 200,
source_repository_owner: 'alice', source_repository_owner: 'alice',
state: :closed, state: state,
milestone_number: milestone.iid, milestone_number: milestone.iid,
author: alice, author: alice,
assignee: alice, assignee: alice,
created_at: created_at, created_at: created_at,
updated_at: updated_at, updated_at: updated_at,
merged_at: merged_at merged_at: state == :closed && merged_at
) )
end end
...@@ -260,58 +261,63 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -260,58 +261,63 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
end end
it 'does not create the source branch if merge request is merged' do it 'does not create the source branch if merge request is merged' do
mr, exists = importer.create_merge_request mr = insert_git_data
importer.insert_git_data(mr, exists)
expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
end end
it 'creates the source branch if merge request is open' do context 'when merge request is open' do
mr, exists = importer.create_merge_request let(:state) { :opened }
mr.state = 'opened'
mr.save
# Ensure the project creator is creating the branches because the it 'creates the source branch' do
# merge request author may not have access to push to this # Ensure the project creator is creating the branches because the
# repository. The project owner may also be a group. # merge request author may not have access to push to this
allow(project.repository).to receive(:add_branch).with(project.creator, anything, anything).and_call_original # repository. The project owner may also be a group.
allow(project.repository).to receive(:add_branch).with(project.creator, anything, anything).and_call_original
importer.insert_git_data(mr, exists) mr = insert_git_data
expect(project.repository.branch_exists?(mr.source_branch)).to be_truthy expect(project.repository.branch_exists?(mr.source_branch)).to be_truthy
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
end end
it 'ignores Git errors when creating a branch' do it 'is able to retry on pre-receive errors' do
mr, exists = importer.create_merge_request expect(importer).to receive(:insert_or_replace_git_data).twice.and_call_original
mr.state = 'opened' expect(project.repository).to receive(:add_branch).and_raise('exception')
mr.save
expect(project.repository).to receive(:add_branch).and_raise(Gitlab::Git::CommandError) expect { insert_git_data }.to raise_error('exception')
expect(Gitlab::Sentry).to receive(:track_acceptable_exception).and_call_original
importer.insert_git_data(mr, exists) expect(project.repository).to receive(:add_branch).with(project.creator, anything, anything).and_call_original
expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey mr = insert_git_data
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
expect(project.repository.branch_exists?(mr.source_branch)).to be_truthy
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
expect(mr.merge_request_diffs).to be_one
end
it 'ignores Git command errors when creating a branch' do
expect(project.repository).to receive(:add_branch).and_raise(Gitlab::Git::CommandError)
expect(Gitlab::Sentry).to receive(:track_acceptable_exception).and_call_original
mr = insert_git_data
expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
end
end end
it 'creates the merge request diffs' do it 'creates the merge request diffs' do
mr, exists = importer.create_merge_request mr = insert_git_data
importer.insert_git_data(mr, exists)
expect(mr.merge_request_diffs.exists?).to eq(true) expect(mr.merge_request_diffs.exists?).to eq(true)
end end
it 'creates the merge request diff commits' do it 'creates the merge request diff commits' do
mr, exists = importer.create_merge_request mr = insert_git_data
importer.insert_git_data(mr, exists)
diff = mr.merge_request_diffs.take diff = mr.merge_request_diffs.reload.first
expect(diff.merge_request_diff_commits.exists?).to eq(true) expect(diff.merge_request_diff_commits.exists?).to eq(true)
end end
...@@ -327,5 +333,11 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -327,5 +333,11 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
expect(mr.merge_request_diffs.exists?).to eq(true) expect(mr.merge_request_diffs.exists?).to eq(true)
end end
end end
def insert_git_data
mr, exists = importer.create_merge_request
importer.insert_git_data(mr, exists)
mr
end
end end
end end
...@@ -20,9 +20,9 @@ describe API::Branches do ...@@ -20,9 +20,9 @@ describe API::Branches do
let(:route) { "/projects/#{project_id}/repository/branches" } let(:route) { "/projects/#{project_id}/repository/branches" }
shared_examples_for 'repository branches' do shared_examples_for 'repository branches' do
RSpec::Matchers.define :has_merged_branch_names_count do |expected| RSpec::Matchers.define :has_up_to_merged_branch_names_count do |expected|
match do |actual| match do |actual|
actual[:merged_branch_names].count == expected expected >= actual[:merged_branch_names].count
end end
end end
...@@ -36,10 +36,30 @@ describe API::Branches do ...@@ -36,10 +36,30 @@ describe API::Branches do
expect(branch_names).to match_array(project.repository.branch_names) expect(branch_names).to match_array(project.repository.branch_names)
end end
def check_merge_status(json_response)
merged, unmerged = json_response.partition { |branch| branch['merged'] }
merged_branches = merged.map { |branch| branch['name'] }
unmerged_branches = unmerged.map { |branch| branch['name'] }
expect(Set.new(merged_branches)).to eq(project.repository.merged_branch_names(merged_branches + unmerged_branches))
expect(project.repository.merged_branch_names(unmerged_branches)).to be_empty
end
it 'determines only a limited number of merged branch names' do it 'determines only a limited number of merged branch names' do
expect(API::Entities::Branch).to receive(:represent).with(anything, has_merged_branch_names_count(2)) expect(API::Entities::Branch).to receive(:represent).with(anything, has_up_to_merged_branch_names_count(2)).and_call_original
get api(route, current_user), params: { per_page: 2 } get api(route, current_user), params: { per_page: 2 }
expect(response).to have_gitlab_http_status(200)
check_merge_status(json_response)
end
it 'merge status matches reality on paginated input' do
get api(route, current_user), params: { per_page: 20, page: 2 }
expect(response).to have_gitlab_http_status(200)
check_merge_status(json_response)
end end
context 'when repository is disabled' do context 'when repository is disabled' do
......
...@@ -13,7 +13,7 @@ describe Projects::AfterImportService do ...@@ -13,7 +13,7 @@ describe Projects::AfterImportService do
describe '#execute' do describe '#execute' do
before do before do
allow(Projects::HousekeepingService) allow(Projects::HousekeepingService)
.to receive(:new).with(project).and_return(housekeeping_service) .to receive(:new).with(project, :gc).and_return(housekeeping_service)
allow(housekeeping_service) allow(housekeeping_service)
.to receive(:execute).and_yield .to receive(:execute).and_yield
......
...@@ -88,6 +88,19 @@ describe Projects::HousekeepingService do ...@@ -88,6 +88,19 @@ describe Projects::HousekeepingService do
expect(project.pushes_since_gc).to eq(1) expect(project.pushes_since_gc).to eq(1)
end end
end end
it 'runs the task specifically requested' do
housekeeping = described_class.new(project, :gc)
allow(housekeeping).to receive(:try_obtain_lease).and_return(:gc_uuid)
allow(housekeeping).to receive(:lease_key).and_return(:gc_lease_key)
expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :gc_lease_key, :gc_uuid).twice