diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index a9d42925fc70e1d05d54dade9e33acbeabdea307..1b3658930d23e26c791529b5a007132e5bf8cfba 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -4ea88e921af65ba0577c40f8b54830c97adaa56c +8752fc1097114316889560502579ddf477a20a2d diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb index 244bd7f6f86fd49212736e7937414fc533af142c..39c018818d1237c58e7411f945fc70d3c088121f 100644 --- a/app/finders/concerns/packages/finder_helper.rb +++ b/app/finders/concerns/packages/finder_helper.rb @@ -13,7 +13,7 @@ def packages_visible_to_user(user, within_group:) return ::Packages::Package.none unless within_group return ::Packages::Package.none unless Ability.allowed?(user, :read_group, within_group) - projects = projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id)) + projects = projects_visible_to_reporters(user, within_group: within_group) ::Packages::Package.for_projects(projects.select(:id)) end @@ -21,12 +21,16 @@ def projects_visible_to_user(user, within_group:) return ::Project.none unless within_group return ::Project.none unless Ability.allowed?(user, :read_group, within_group) - projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id)) + projects_visible_to_reporters(user, within_group: within_group) end - def projects_visible_to_reporters(user, namespace_ids) - ::Project.in_namespace(namespace_ids) - .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER) + def projects_visible_to_reporters(user, within_group:) + if user.is_a?(DeployToken) && Feature.enabled?(:packages_finder_helper_deploy_token) + user.accessible_projects + else + within_group.all_projects + .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER) + end end def package_type diff --git a/app/finders/packages/maven/package_finder.rb b/app/finders/packages/maven/package_finder.rb index 973496ca9c49b6def64e510a70352a4858758b2e..eefcdaba3c83f8c36966c4c8fb4fd375492f3cb9 100644 --- a/app/finders/packages/maven/package_finder.rb +++ b/app/finders/packages/maven/package_finder.rb @@ -76,7 +76,7 @@ def projects_visible_to_current_user def group_level_improvements? strong_memoize(:group_level_improvements) do - Feature.enabled?(:maven_packages_group_level_improvements) + Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml) end end end diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb index 08e9f06a6a1b28bf9647f12d10548a1029bda887..e510432be8f15836bebcc88ee27f34d92e2819f2 100644 --- a/app/models/packages/package.rb +++ b/app/models/packages/package.rb @@ -138,7 +138,7 @@ class Packages::Package < ApplicationRecord after_commit :update_composer_cache, on: :destroy, if: -> { composer? } def self.for_projects(projects) - unless Feature.enabled?(:maven_packages_group_level_improvements) + unless Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml) return none unless projects.any? end diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 0c0b67640195473c01768e7869c8d8a2cf5a535a..3a3765355d8f825ba996f322c75e5463e04fe560 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -143,8 +143,12 @@ def create_reviewer_note(merge_request, old_reviewers) merge_request, merge_request.project, current_user, old_reviewers) end - def create_pipeline_for(merge_request, user) - MergeRequests::CreatePipelineService.new(project, user).execute(merge_request) + def create_pipeline_for(merge_request, user, async: false) + if async + MergeRequests::CreatePipelineWorker.perform_async(project.id, user.id, merge_request.id) + else + MergeRequests::CreatePipelineService.new(project, user).execute(merge_request) + end end def abort_auto_merge(merge_request, reason) diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index 0fb16597aff5923bc3b55b74c79b012fb9f01d89..e04c5168cef6e04e0b6b54df2eb49cd1812a7a8d 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -162,9 +162,12 @@ def outdate_service end def refresh_pipelines_on_merge_requests(merge_request) - create_pipeline_for(merge_request, current_user) - - UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id) + if Feature.enabled?(:code_review_async_pipeline_creation, project, default_enabled: :yaml) + create_pipeline_for(merge_request, current_user, async: true) + else + create_pipeline_for(merge_request, current_user, async: false) + UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id) + end end def abort_auto_merges(merge_request) diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index ef7b5eb026e926b901fc2fe29ff3d11d6ecb47ee..f14497509e199695c8719804c1891576793b5dd8 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -1227,6 +1227,14 @@ :weight: 4 :idempotent: :tags: [] +- :name: pipeline_creation:merge_requests_create_pipeline + :feature_category: :continuous_integration + :has_external_dependencies: + :urgency: :high + :resource_boundary: :cpu + :weight: 4 + :idempotent: true + :tags: [] - :name: pipeline_creation:run_pipeline_schedule :feature_category: :continuous_integration :has_external_dependencies: diff --git a/app/workers/merge_requests/create_pipeline_worker.rb b/app/workers/merge_requests/create_pipeline_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..244ba1af300d57d2b1c7cbc54e11571cd7a5e267 --- /dev/null +++ b/app/workers/merge_requests/create_pipeline_worker.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module MergeRequests + class CreatePipelineWorker + include ApplicationWorker + include PipelineQueue + + queue_namespace :pipeline_creation + feature_category :continuous_integration + urgency :high + worker_resource_boundary :cpu + idempotent! + + def perform(project_id, user_id, merge_request_id) + project = Project.find_by_id(project_id) + return unless project + + user = User.find_by_id(user_id) + return unless user + + merge_request = MergeRequest.find_by_id(merge_request_id) + return unless merge_request + + MergeRequests::CreatePipelineService.new(project, user).execute(merge_request) + merge_request.update_head_pipeline + end + end +end diff --git a/changelogs/unreleased/220680-update-gatsby-project-template.yml b/changelogs/unreleased/220680-update-gatsby-project-template.yml new file mode 100644 index 0000000000000000000000000000000000000000..d3bbe24b99224ea69271cffad23b5f347d483e2e --- /dev/null +++ b/changelogs/unreleased/220680-update-gatsby-project-template.yml @@ -0,0 +1,5 @@ +--- +title: Update gatsby project template to address the pipeline failure +merge_request: 37410 +author: Takuya Noguchi +type: fixed diff --git a/changelogs/unreleased/326099-enabled-by-default.yml b/changelogs/unreleased/326099-enabled-by-default.yml new file mode 100644 index 0000000000000000000000000000000000000000..e73620bfc76f67469ede3dd519c6538439f7c071 --- /dev/null +++ b/changelogs/unreleased/326099-enabled-by-default.yml @@ -0,0 +1,5 @@ +--- +title: Reduce the number of SQL queries executed on Maven file API endpoints +merge_request: 59136 +author: +type: performance diff --git a/changelogs/unreleased/move_pipeline_creation_async.yml b/changelogs/unreleased/move_pipeline_creation_async.yml new file mode 100644 index 0000000000000000000000000000000000000000..2017a518f29644e496319ca082e44341f183de7a --- /dev/null +++ b/changelogs/unreleased/move_pipeline_creation_async.yml @@ -0,0 +1,5 @@ +--- +title: Create the pipelines asynchronously when refreshing merge requests +merge_request: 58542 +author: +type: performance diff --git a/config/feature_flags/development/code_review_async_pipeline_creation.yml b/config/feature_flags/development/code_review_async_pipeline_creation.yml new file mode 100644 index 0000000000000000000000000000000000000000..d0e5a3286aafc4ce1c560dadfcfd885949a126cc --- /dev/null +++ b/config/feature_flags/development/code_review_async_pipeline_creation.yml @@ -0,0 +1,8 @@ +--- +name: code_review_async_pipeline_creation +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58542 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327559 +milestone: '13.11' +type: development +group: group::code review +default_enabled: false diff --git a/config/feature_flags/development/maven_packages_group_level_improvements.yml b/config/feature_flags/development/maven_packages_group_level_improvements.yml index 6b8a8ac5b1179b33d6e5c369b5bb15b2fad53124..8dfd5ab0f8b65645afdbb0a6c240099ff9c76eca 100644 --- a/config/feature_flags/development/maven_packages_group_level_improvements.yml +++ b/config/feature_flags/development/maven_packages_group_level_improvements.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326099 milestone: '13.11' type: development group: group::package -default_enabled: false +default_enabled: true diff --git a/config/feature_flags/development/packages_finder_helper_deploy_token.yml b/config/feature_flags/development/packages_finder_helper_deploy_token.yml new file mode 100644 index 0000000000000000000000000000000000000000..fcc73cafd647dc7521e9b8454ccf9a2b7771932b --- /dev/null +++ b/config/feature_flags/development/packages_finder_helper_deploy_token.yml @@ -0,0 +1,8 @@ +--- +name: packages_finder_helper_deploy_token +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58497 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326808 +milestone: '13.11' +type: development +group: group::package +default_enabled: false diff --git a/ee/app/models/project_services/ee/jira_service.rb b/ee/app/models/project_services/ee/jira_service.rb index 9a0c5bdd9b874130ed96b6f8ff8b4b1618fa61fc..66fca4d87d125a4e4c80fca64ec57db13e182d9b 100644 --- a/ee/app/models/project_services/ee/jira_service.rb +++ b/ee/app/models/project_services/ee/jira_service.rb @@ -89,6 +89,8 @@ def jira_project # # @return [Array] the array of IDs def project_issuetype_scheme_ids + raise NotImplementedError unless data_fields.deployment_cloud? + query_url = Addressable::URI.join("#{client.options[:rest_base_path]}/", 'issuetypescheme/', 'project') query_url.query_values = { 'projectId' => jira_project_id } @@ -103,13 +105,24 @@ def project_issuetype_scheme_ids # @return [Array] the array of IDs def project_issuetype_ids strong_memoize(:project_issuetype_ids) do - query_url = Addressable::URI.join("#{client.options[:rest_base_path]}/", 'issuetypescheme/', 'mapping') - query_url.query_values = { 'issueTypeSchemeId' => project_issuetype_scheme_ids } - - client - .get(query_url.to_s) - .fetch('values', []) - .map { |schemes| schemes['issueTypeId'] } + if data_fields.deployment_server? + query_url = Addressable::URI.join("#{client.options[:rest_base_path]}/", 'project/', project_key) + + client + .get(query_url.to_s) + .fetch('issueTypes', []) + .map { |issue_type| issue_type['id'] } + elsif data_fields.deployment_cloud? + query_url = Addressable::URI.join("#{client.options[:rest_base_path]}/", 'issuetypescheme/', 'mapping') + query_url.query_values = { 'issueTypeSchemeId' => project_issuetype_scheme_ids } + + client + .get(query_url.to_s) + .fetch('values', []) + .map { |schemes| schemes['issueTypeId'] } + else + raise NotImplementedError + end end end diff --git a/ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml b/ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml index 27db25b26bde3e284ac59d07f541ede1c2743453..69a183e7588acdad15834f228901789f06a848d9 100644 --- a/ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml +++ b/ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml @@ -1,7 +1,7 @@ - return unless Gitlab.com? - minutes_quota = namespace.ci_minutes_quota -- return unless minutes_quota.enabled? +- return unless minutes_quota.enabled? && minutes_quota.purchased_minutes_report.limit > 0 .row .col-sm-6 diff --git a/ee/changelogs/unreleased/327458-ci-minutes-ee.yml b/ee/changelogs/unreleased/327458-ci-minutes-ee.yml new file mode 100644 index 0000000000000000000000000000000000000000..bccd348ad72e1a9da7d1f328c9dd6e41cb6c8df8 --- /dev/null +++ b/ee/changelogs/unreleased/327458-ci-minutes-ee.yml @@ -0,0 +1,5 @@ +--- +title: Remove additional minutes when no minutes purchased +merge_request: 59112 +author: Takuya Noguchi +type: changed diff --git a/ee/spec/models/project_services/jira_service_spec.rb b/ee/spec/models/project_services/jira_service_spec.rb index 472bc274a7f45d97737a05e5f8e7af92504628c2..c4b6b6f9c3ef25129f23eaf03be707be09e78640 100644 --- a/ee/spec/models/project_services/jira_service_spec.rb +++ b/ee/spec/models/project_services/jira_service_spec.rb @@ -15,6 +15,11 @@ } end + before do + allow(jira_service.data_fields).to receive(:deployment_cloud?).and_return(true) + allow(jira_service.data_fields).to receive(:deployment_server?).and_return(false) + end + describe 'validations' do it 'validates presence of project_key if issues_enabled' do jira_service.project_key = '' @@ -111,80 +116,150 @@ end context 'when vulnerabilities integration is enabled' do - let(:project_info_result) { { 'id' => '10000' } } + before do + allow(jira_service.project).to receive(:jira_vulnerabilities_integration_enabled?).and_return(true) + end - let(:issue_type_scheme_response) do - { - values: [ - { - issueTypeScheme: { - id: '10126', - name: 'GV: Software Development Issue Type Scheme', - defaultIssueTypeId: '10001' + context 'when deployment type is cloud' do + let(:project_info_result) { { 'id' => '10000' } } + + let(:issue_type_scheme_response) do + { + values: [ + { + issueTypeScheme: { + id: '10126', + name: 'GV: Software Development Issue Type Scheme', + defaultIssueTypeId: '10001' + }, + projectIds: [ + '10000' + ] + } + ] + } + end + + let(:issue_type_mapping_response) do + { + values: [ + { + issueTypeSchemeId: '10126', + issueTypeId: '10003' }, - projectIds: [ - '10000' - ] - } - ] - } - end + { + issueTypeSchemeId: '10126', + issueTypeId: '10001' + } + ] + } + end - let(:issue_type_mapping_response) do - { - values: [ + let(:issue_types_response) do + [ + { + id: '10004', + description: 'A new feature of the product, which has yet to be developed.', + name: 'New Feature', + untranslatedName: 'New Feature', + subtask: false, + avatarId: 10311 + }, { - issueTypeSchemeId: '10126', - issueTypeId: '10003' + id: '10001', + description: 'Jira Bug', + name: 'Bug', + untranslatedName: 'Bug', + subtask: false, + avatarId: 10303 }, { - issueTypeSchemeId: '10126', - issueTypeId: '10001' + id: '10003', + description: 'A small piece of work thats part of a larger task.', + name: 'Sub-task', + untranslatedName: 'Sub-task', + subtask: true, + avatarId: 10316 } ] - } + end + + before do + WebMock.stub_request(:get, /api\/2\/project\/GL/).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password)).to_return(body: project_info_result.to_json ) + WebMock.stub_request(:get, /api\/2\/project\/GL\z/).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password)).to_return(body: { 'id' => '10000' }.to_json, headers: headers) + WebMock.stub_request(:get, /api\/2\/issuetype\z/).to_return(body: issue_types_response.to_json, headers: headers) + WebMock.stub_request(:get, /api\/2\/issuetypescheme\/project\?projectId\=10000\z/).to_return(body: issue_type_scheme_response.to_json, headers: headers) + WebMock.stub_request(:get, /api\/2\/issuetypescheme\/mapping\?issueTypeSchemeId\=10126\z/).to_return(body: issue_type_mapping_response.to_json, headers: headers) + end + + it { is_expected.to eq(success: true, result: { jira: true }, data: { issuetypes: [{ id: '10001', name: 'Bug', description: 'Jira Bug' }] }) } end - let(:issue_types_response) do - [ + context 'when deployment type is server' do + let(:project_info_result) do { - id: '10004', - description: 'A new feature of the product, which has yet to be developed.', - name: 'New Feature', - untranslatedName: 'New Feature', - subtask: false, - avatarId: 10311 - }, - { - id: '10001', - description: 'Jira Bug', - name: 'Bug', - untranslatedName: 'Bug', - subtask: false, - avatarId: 10303 - }, - { - id: '10003', - description: 'A small piece of work thats part of a larger task.', - name: 'Sub-task', - untranslatedName: 'Sub-task', - subtask: true, - avatarId: 10316 + "id": "10000", + "issueTypes": issue_types_response } - ] - end + end - before do - allow(jira_service.project).to receive(:jira_vulnerabilities_integration_enabled?).and_return(true) + let(:issue_types_response) do + [ + { + "avatarId": 10318, + "description": "A task that needs to be done.", + "iconUrl": "http://jira.reali.sh:8080/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype", + "id": "10003", + "name": "Task", + "self": "http://jira.reali.sh:8080/rest/api/2/issuetype/10003", + "subtask": false + }, + { + "description": "The sub-task of the issue", + "iconUrl": "http://jira.reali.sh:8080/images/icons/issuetypes/subtask_alternate.png", + "id": "10000", + "name": "Sub-task", + "self": "http://jira.reali.sh:8080/rest/api/2/issuetype/10000", + "subtask": true + }, + { + "description": "Created by Jira Software - do not edit or delete. Issue type for a user story.", + "iconUrl": "http://jira.reali.sh:8080/images/icons/issuetypes/story.svg", + "id": "10002", + "name": "Story", + "self": "http://jira.reali.sh:8080/rest/api/2/issuetype/10002", + "subtask": false + }, + { + "avatarId": 10303, + "description": "A problem which impairs or prevents the functions of the product.", + "iconUrl": "http://jira.reali.sh:8080/secure/viewavatar?size=xsmall&avatarId=10303&avatarType=issuetype", + "id": "10004", + "name": "Bug", + "self": "http://jira.reali.sh:8080/rest/api/2/issuetype/10004", + "subtask": false + }, + { + "description": "Created by Jira Software - do not edit or delete. Issue type for a big user story that needs to be broken down.", + "iconUrl": "http://jira.reali.sh:8080/images/icons/issuetypes/epic.svg", + "id": "10001", + "name": "Epic", + "self": "http://jira.reali.sh:8080/rest/api/2/issuetype/10001", + "subtask": false + } + ] + end - WebMock.stub_request(:get, /api\/2\/project\/GL/).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password)).to_return(body: project_info_result.to_json ) - WebMock.stub_request(:get, /api\/2\/project\/GL\z/).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password)).to_return(body: { 'id' => '10000' }.to_json, headers: headers) - WebMock.stub_request(:get, /api\/2\/issuetype\z/).to_return(body: issue_types_response.to_json, headers: headers) - WebMock.stub_request(:get, /api\/2\/issuetypescheme\/project\?projectId\=10000\z/).to_return(body: issue_type_scheme_response.to_json, headers: headers) - WebMock.stub_request(:get, /api\/2\/issuetypescheme\/mapping\?issueTypeSchemeId\=10126\z/).to_return(body: issue_type_mapping_response.to_json, headers: headers) - end + before do + allow(jira_service.data_fields).to receive(:deployment_cloud?).and_return(false) + allow(jira_service.data_fields).to receive(:deployment_server?).and_return(true) - it { is_expected.to eq(success: true, result: { jira: true }, data: { issuetypes: [{ id: '10001', name: 'Bug', description: 'Jira Bug' }] }) } + WebMock.stub_request(:get, /api\/2\/project\/GL/).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password)).to_return(body: project_info_result.to_json, headers: headers) + WebMock.stub_request(:get, /api\/2\/issuetype\z/).to_return(body: issue_types_response.to_json, headers: headers) + end + + it { is_expected.to eq(success: true, result: { jira: true }, data: { issuetypes: [{ description: "A task that needs to be done.", id: "10003", name: "Task" }, { description: "Created by Jira Software - do not edit or delete. Issue type for a user story.", id: "10002", name: "Story" }, { description: "A problem which impairs or prevents the functions of the product.", id: "10004", name: "Bug" }, { description: "Created by Jira Software - do not edit or delete. Issue type for a big user story that needs to be broken down.", id: "10001", name: "Epic" }] }) } + end end end end diff --git a/ee/spec/services/ee/merge_requests/refresh_service_spec.rb b/ee/spec/services/ee/merge_requests/refresh_service_spec.rb index 05bb3cdb3682c005ecd0eb7422f7e29bab88d026..c3ccefe23da0ad382ff0632b53c0b13961572064 100644 --- a/ee/spec/services/ee/merge_requests/refresh_service_spec.rb +++ b/ee/spec/services/ee/merge_requests/refresh_service_spec.rb @@ -249,7 +249,7 @@ end end - describe 'Pipelines for merge requests' do + describe 'Pipelines for merge requests', :sidekiq_inline do let(:service) { described_class.new(project, current_user) } let(:current_user) { merge_request.author } diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb index 5d255c309f7c5de5bf182ef25e8a6ac77e09e487..879f1ea5d50e531ea282932c8323ac8e86562a32 100644 --- a/lib/api/maven_packages.rb +++ b/lib/api/maven_packages.rb @@ -80,7 +80,7 @@ def head_request_on_aws_file?(file, supports_direct_download) def fetch_package(file_name:, project: nil, group: nil) order_by_package_file = false - if Feature.enabled?(:maven_packages_group_level_improvements) + if Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml) order_by_package_file = file_name.include?(::Packages::Maven::Metadata.filename) && !params[:path].include?(::Packages::Maven::FindOrCreatePackageService::SNAPSHOT_TERM) end diff --git a/spec/factories/services.rb b/spec/factories/services.rb index 7b9d7bfb3e0fe4f7b7a441132e4a357c826136f6..25ef75880bb48d1b5e53b0c2540cce3db3f7a177 100644 --- a/spec/factories/services.rb +++ b/spec/factories/services.rb @@ -62,6 +62,7 @@ project_key { nil } vulnerabilities_enabled { false } vulnerabilities_issuetype { nil } + deployment_type { 'cloud' } end before(:create) do |service, evaluator| @@ -72,7 +73,7 @@ jira_issue_transition_id: evaluator.jira_issue_transition_id, username: evaluator.username, password: evaluator.password, issues_enabled: evaluator.issues_enabled, project_key: evaluator.project_key, vulnerabilities_enabled: evaluator.vulnerabilities_enabled, - vulnerabilities_issuetype: evaluator.vulnerabilities_issuetype + vulnerabilities_issuetype: evaluator.vulnerabilities_issuetype, deployment_type: evaluator.deployment_type ) end end diff --git a/spec/finders/concerns/packages/finder_helper_spec.rb b/spec/finders/concerns/packages/finder_helper_spec.rb index 73f7764757312d6316bc004c3107458bececb679..c1740ee17964da5199c4040ade99ccd367cd6ca9 100644 --- a/spec/finders/concerns/packages/finder_helper_spec.rb +++ b/spec/finders/concerns/packages/finder_helper_spec.rb @@ -6,7 +6,6 @@ describe '#packages_visible_to_user' do using RSpec::Parameterized::TableSyntax - let_it_be(:user) { create(:user) } let_it_be_with_reload(:group) { create(:group) } let_it_be_with_reload(:project1) { create(:project, namespace: group) } let_it_be(:package1) { create(:package, project: project1) } @@ -44,41 +43,87 @@ def execute(group) it { is_expected.to be_empty } end - where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both packages' - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both packages' - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both packages' - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages' + context 'with a user' do + let_it_be(:user) { create(:user) } + + where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages' + end + + with_them do + before do + unless user_role == :anonymous + group.send("add_#{user_role}", user) + subgroup.send("add_#{user_role}", user) + project1.send("add_#{user_role}", user) + project2.send("add_#{user_role}", user) + end + + project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false)) + subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false)) + project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + end + + it_behaves_like params[:shared_example_name] + end end - with_them do - before do - unless user_role == :anonymous - group.send("add_#{user_role}", user) - subgroup.send("add_#{user_role}", user) - project1.send("add_#{user_role}", user) - project2.send("add_#{user_role}", user) + context 'with a group deploy token' do + let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) } + let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) } + + shared_examples 'handling all conditions' do + where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both packages' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both packages' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both packages' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both packages' + end + + with_them do + before do + project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false)) + subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false)) + project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + end + + it_behaves_like params[:shared_example_name] + end + end + + context 'with packages_finder_helper_deploy_token enabled' do + before do + expect(group).not_to receive(:all_projects) end - project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false)) - subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false)) - project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) - group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + it_behaves_like 'handling all conditions' end - it_behaves_like params[:shared_example_name] + context 'with packages_finder_helper_deploy_token disabled' do + before do + stub_feature_flags(packages_finder_helper_deploy_token: false) + expect(group).to receive(:all_projects).and_call_original + end + + it_behaves_like 'handling all conditions' + end end end @@ -121,41 +166,87 @@ def execute(group) it { is_expected.to be_empty } end - where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both projects' - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both projects' - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both projects' - 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1' - 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1' - 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project' - 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project' + context 'with a user' do + let_it_be(:user) { create(:user) } + + where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project' + end + + with_them do + before do + unless user_role == :anonymous + group.send("add_#{user_role}", user) + subgroup.send("add_#{user_role}", user) + project1.send("add_#{user_role}", user) + project2.send("add_#{user_role}", user) + end + + project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false)) + subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false)) + project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + end + + it_behaves_like params[:shared_example_name] + end end - with_them do - before do - unless user_role == :anonymous - group.send("add_#{user_role}", user) - subgroup.send("add_#{user_role}", user) - project1.send("add_#{user_role}", user) - project2.send("add_#{user_role}", user) + context 'with a group deploy token' do + let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) } + let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) } + + shared_examples 'handling all conditions' do + where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do + 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both projects' + 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both projects' + 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both projects' + 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both projects' end - project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false)) - subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false)) - project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) - group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + with_them do + before do + project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false)) + subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false)) + project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false)) + end + + it_behaves_like params[:shared_example_name] + end end - it_behaves_like params[:shared_example_name] + context 'with packages_finder_helper_deploy_token enabled' do + before do + expect(group).not_to receive(:all_projects) + end + + it_behaves_like 'handling all conditions' + end + + context 'with packages_finder_helper_deploy_token disabled' do + before do + stub_feature_flags(packages_finder_helper_deploy_token: false) + expect(group).to receive(:all_projects).and_call_original + end + + it_behaves_like 'handling all conditions' + end end end end diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb index 93310d3e90fc409831d05eef858746e854ef43f5..07c00a338f64a996451b52ba2fbbb3c42ae09865 100644 --- a/spec/requests/api/maven_packages_spec.rb +++ b/spec/requests/api/maven_packages_spec.rb @@ -387,7 +387,7 @@ def download_file_with_token(file_name, params = {}, request_headers = headers_w subject - status = Feature.enabled?(:maven_packages_group_level_improvements) ? :not_found : :forbidden + status = Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml) ? :not_found : :forbidden expect(response).to have_gitlab_http_status(status) end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 2abe7a23bfed345fc68440ac5770e31cf45b66c5..f9b76db877b143e229b473a85cf76da221d71477 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -198,7 +198,7 @@ end end - describe 'Pipelines for merge requests' do + shared_examples 'Pipelines for merge requests' do before do stub_ci_pipeline_yaml_file(config) end @@ -256,7 +256,7 @@ stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false) end - it 'creates detached merge request pipeline for fork merge request', :sidekiq_inline do + it 'creates detached merge request pipeline for fork merge request' do expect { subject } .to change { @fork_merge_request.pipelines_for_merge_request.count }.by(1) @@ -364,6 +364,18 @@ end end + context 'when the code_review_async_pipeline_creation feature flag is on', :sidekiq_inline do + it_behaves_like 'Pipelines for merge requests' + end + + context 'when the code_review_async_pipeline_creation feature flag is off', :sidekiq_inline do + before do + stub_feature_flags(code_review_async_pipeline_creation: false) + end + + it_behaves_like 'Pipelines for merge requests' + end + context 'push to origin repo source branch' do let(:refresh_service) { service.new(@project, @user) } let(:notification_service) { spy('notification_service') } diff --git a/spec/workers/merge_requests/create_pipeline_worker_spec.rb b/spec/workers/merge_requests/create_pipeline_worker_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8efce5220be68ffe76acff884408d2ade3e383ab --- /dev/null +++ b/spec/workers/merge_requests/create_pipeline_worker_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe MergeRequests::CreatePipelineWorker do + subject(:worker) { described_class.new } + + describe '#perform' do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:merge_request) { create(:merge_request) } + + context 'when the objects exist' do + it 'calls the merge request create pipeline service and calls update head pipeline' do + aggregate_failures do + expect_next_instance_of(MergeRequests::CreatePipelineService, project, user) do |service| + expect(service).to receive(:execute).with(merge_request) + end + + expect(MergeRequest).to receive(:find_by_id).with(merge_request.id).and_return(merge_request) + expect(merge_request).to receive(:update_head_pipeline) + + subject.perform(project.id, user.id, merge_request.id) + end + end + end + + shared_examples 'when object does not exist' do + it 'does not call the create pipeline service' do + expect(MergeRequests::CreatePipelineService).not_to receive(:new) + + expect { subject.perform(project.id, user.id, merge_request.id) } + .not_to raise_exception + end + end + + context 'when the project does not exist' do + before do + project.destroy! + end + + it_behaves_like 'when object does not exist' + end + + context 'when the user does not exist' do + before do + user.destroy! + end + + it_behaves_like 'when object does not exist' + end + + context 'when the merge request does not exist' do + before do + merge_request.destroy! + end + + it_behaves_like 'when object does not exist' + end + end +end diff --git a/vendor/project_templates/gatsby.tar.gz b/vendor/project_templates/gatsby.tar.gz index a4ae5f99047fd97ba05c56b63ef4256132477d58..52bb056630e56cd64e0999a898c927741320be9a 100644 Binary files a/vendor/project_templates/gatsby.tar.gz and b/vendor/project_templates/gatsby.tar.gz differ