diff options
28 files changed, 311 insertions, 68 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue index 6a88c8a5ee3..067a727fe16 100644 --- a/app/assets/javascripts/monitoring/components/charts/time_series.vue +++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue @@ -253,23 +253,25 @@ export default { this.tooltip.title = dateFormat(params.value, dateFormats.default); this.tooltip.content = []; params.seriesData.forEach(dataPoint => { - const [xVal, yVal] = dataPoint.value; - this.tooltip.isDeployment = dataPoint.componentSubType === graphTypes.deploymentData; - if (this.tooltip.isDeployment) { - const [deploy] = this.recentDeployments.filter( - deployment => deployment.createdAt === xVal, - ); - this.tooltip.sha = deploy.sha.substring(0, 8); - this.tooltip.commitUrl = deploy.commitUrl; - } else { - const { seriesName, color, dataIndex } = dataPoint; - const value = yVal.toFixed(3); - this.tooltip.content.push({ - name: seriesName, - dataIndex, - value, - color, - }); + if (dataPoint.value) { + const [xVal, yVal] = dataPoint.value; + this.tooltip.isDeployment = dataPoint.componentSubType === graphTypes.deploymentData; + if (this.tooltip.isDeployment) { + const [deploy] = this.recentDeployments.filter( + deployment => deployment.createdAt === xVal, + ); + this.tooltip.sha = deploy.sha.substring(0, 8); + this.tooltip.commitUrl = deploy.commitUrl; + } else { + const { seriesName, color, dataIndex } = dataPoint; + const value = yVal.toFixed(3); + this.tooltip.content.push({ + name: seriesName, + dataIndex, + value, + color, + }); + } } }); }, diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index 72c82aec31d..39efc3f94dc 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -20,6 +20,14 @@ class Projects::ReleasesController < Projects::ApplicationController end end + def evidence + respond_to do |format| + format.json do + render json: release.evidence_summary + end + end + end + protected def releases diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 7e1898e7142..a8c15ef2028 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -241,6 +241,9 @@ class MergeRequest < ApplicationRecord alias_attribute :auto_merge_enabled, :merge_when_pipeline_succeeds alias_method :issuing_parent, :target_project + delegate :active?, to: :head_pipeline, prefix: true, allow_nil: true + delegate :success?, to: :actual_head_pipeline, prefix: true, allow_nil: true + RebaseLockTimeout = Class.new(StandardError) REBASE_LOCK_MESSAGE = _("Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later.") diff --git a/app/models/release.rb b/app/models/release.rb index 401e8359f47..4fac64689ab 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -73,6 +73,14 @@ class Release < ApplicationRecord self.read_attribute(:name) || tag end + def evidence_sha + evidence&.summary_sha + end + + def evidence_summary + evidence&.summary || {} + end + private def actual_sha diff --git a/app/presenters/release_presenter.rb b/app/presenters/release_presenter.rb index 42463d6dbda..4eed278661c 100644 --- a/app/presenters/release_presenter.rb +++ b/app/presenters/release_presenter.rb @@ -37,6 +37,12 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated edit_project_release_url(project, release) end + def evidence_file_path + return unless release.evidence.present? + + evidence_project_release_url(project, tag, format: :json) + end + private def can_download_code? diff --git a/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb b/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb index 6a33ec071db..7c0e9228b28 100644 --- a/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb +++ b/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb @@ -11,7 +11,7 @@ module AutoMerge end def process(merge_request) - return unless merge_request.actual_head_pipeline&.success? + return unless merge_request.actual_head_pipeline_success? return unless merge_request.mergeable? merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params) diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 8a6a7119508..1dc5503d368 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -87,7 +87,7 @@ module MergeRequests merge_request.update(merge_error: nil) - if merge_request.head_pipeline && merge_request.head_pipeline.active? + if merge_request.head_pipeline_active? AutoMergeService.new(project, current_user, { sha: last_diff_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS) else merge_request.merge_async(current_user.id, { sha: last_diff_sha }) diff --git a/changelogs/unreleased/26293-prevent-merge-if-pipeline-has-failed.yml b/changelogs/unreleased/26293-prevent-merge-if-pipeline-has-failed.yml new file mode 100644 index 00000000000..3bb3c785945 --- /dev/null +++ b/changelogs/unreleased/26293-prevent-merge-if-pipeline-has-failed.yml @@ -0,0 +1,5 @@ +--- +title: Update merging an MR behavior on the API when pipeline fails +merge_request: 19641 +author: briankabiro +type: fixed diff --git a/changelogs/unreleased/31397-go-get-meta-source.yml b/changelogs/unreleased/31397-go-get-meta-source.yml new file mode 100644 index 00000000000..b8ab155ab51 --- /dev/null +++ b/changelogs/unreleased/31397-go-get-meta-source.yml @@ -0,0 +1,5 @@ +--- +title: Support go-source meta tag for godoc.org +merge_request: 19888 +author: Ethan Reesor (@firelizzard) +type: changed diff --git a/changelogs/unreleased/32780-when-zooming-metrics-at-some-point-we-can-t-adjust-the-zoom-any-fur.yml b/changelogs/unreleased/32780-when-zooming-metrics-at-some-point-we-can-t-adjust-the-zoom-any-fur.yml new file mode 100644 index 00000000000..5a674f415d3 --- /dev/null +++ b/changelogs/unreleased/32780-when-zooming-metrics-at-some-point-we-can-t-adjust-the-zoom-any-fur.yml @@ -0,0 +1,5 @@ +--- +title: Fixed monitor charts from throwing error when zoomed +merge_request: 20331 +author: +type: fixed diff --git a/changelogs/unreleased/evidence-docs-and-release-api.yml b/changelogs/unreleased/evidence-docs-and-release-api.yml new file mode 100644 index 00000000000..23ce41b9460 --- /dev/null +++ b/changelogs/unreleased/evidence-docs-and-release-api.yml @@ -0,0 +1,5 @@ +--- +title: Update Release API with evidence related data. +merge_request: 19706 +author: +type: added diff --git a/config/routes/project.rb b/config/routes/project.rb index 3f913683b00..834a451cd95 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -179,7 +179,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do end end - resources :releases, only: [:index, :edit], param: :tag, constraints: { tag: %r{[^/]+} } + resources :releases, only: [:index, :edit], param: :tag, constraints: { tag: %r{[^/]+} } do + member do + get :evidence + end + end + resources :starrers, only: [:index] resources :forks, only: [:index, :new, :create] resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ } diff --git a/doc/administration/auth/ldap-ee.md b/doc/administration/auth/ldap-ee.md index e2894318fe5..b1d4c8e4298 100644 --- a/doc/administration/auth/ldap-ee.md +++ b/doc/administration/auth/ldap-ee.md @@ -10,6 +10,9 @@ This section documents LDAP features specific to to GitLab Enterprise Edition For documentation relevant to both Community Edition and Enterprise Edition, see the main [LDAP documentation](ldap.md). +NOTE: **Note:** +[Microsoft Active Directory Trusts](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771568(v=ws.10)) are not supported + ## Use cases - User sync: Once a day, GitLab will update users against LDAP. diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md index 7f41e237401..41c4bcd00ce 100644 --- a/doc/api/releases/index.md +++ b/doc/api/releases/index.md @@ -3,6 +3,7 @@ > - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/41766) in GitLab 11.7. > - Using this API you can manipulate GitLab's [Release](../../user/project/releases/index.md) entries. > - For manipulating links as a release asset, see [Release Links API](links.md). +> - Release Evidences were [introduced](https://gitlab.com/gitlab-org/gitlab/issues/26019) in GitLab 12.5. ## List Releases @@ -87,6 +88,7 @@ Example response: ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":6, "sources":[ @@ -120,7 +122,8 @@ Example response: "url":"http://192.168.10.15:3000", "external":true } - ] + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json" }, }, { @@ -154,6 +157,7 @@ Example response: "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, + "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ @@ -176,7 +180,8 @@ Example response: ], "links":[ - ] + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } ] @@ -265,8 +270,9 @@ Example response: ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ - "count":4, + "count":5, "sources":[ { "format":"zip", @@ -287,7 +293,8 @@ Example response: ], "links":[ - ] + ], + "evidence_url":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } ``` @@ -385,6 +392,7 @@ Example response: ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":5, "sources":[ @@ -412,7 +420,8 @@ Example response: "url":"https://google.com", "external":true } - ] + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.3/evidence.json" }, } ``` @@ -491,6 +500,7 @@ Example response: ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ @@ -513,7 +523,8 @@ Example response: ], "links":[ - ] + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } ``` @@ -573,6 +584,7 @@ Example response: }, "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ @@ -595,7 +607,8 @@ Example response: ], "links":[ - ] + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } ``` diff --git a/doc/user/project/index.md b/doc/user/project/index.md index c173d3d3e11..29de700af4d 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -200,9 +200,14 @@ When [renaming a user](../profile/index.md#changing-your-username), ## Use your project as a Go package -Any project can be used as a Go package including private projects in subgroups. To use packages -hosted in private projects with the `go get` command, use a [`.netrc` file](https://ec.haxx.se/usingcurl-netrc.html) -and a [personal access token](../profile/personal_access_tokens.md) in the password field. +Any project can be used as a Go package including private projects in subgroups. +GitLab responds correctly to `go get` and `godoc.org` discovery requests, +including the [`go-import`](https://golang.org/cmd/go/#hdr-Remote_import_paths) +and [`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links) meta +tags, respectively. To use packages hosted in private projects with the `go get` +command, use a [`.netrc` file](https://ec.haxx.se/usingcurl-netrc.html) and a +[personal access token](../profile/personal_access_tokens.md) in the password +field. For example: diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9617f1a8acf..0aef021f043 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1315,6 +1315,7 @@ module API expose :milestones, using: Entities::Milestone, if: -> (release, _) { release.milestones.present? } expose :commit_path, expose_nil: false expose :tag_path, expose_nil: false + expose :evidence_sha, expose_nil: false expose :assets do expose :assets_count, as: :count do |release, _| assets_to_exclude = can_download_code? ? [] : [:sources] @@ -1324,6 +1325,7 @@ module API expose :links, using: Entities::Releases::Link do |release, options| release.links.sorted end + expose :evidence_file_path, expose_nil: false end expose :_links do expose :merge_requests_url, expose_nil: false diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 6e10414def4..794237f8032 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -68,6 +68,10 @@ module API end end + def not_automatically_mergeable?(merge_when_pipeline_succeeds, merge_request) + merge_when_pipeline_succeeds && !merge_request.head_pipeline_active? && !merge_request.actual_head_pipeline_success? + end + def serializer_options_for(merge_requests) options = { with: Entities::MergeRequestBasic, current_user: current_user } @@ -391,12 +395,13 @@ module API merge_request = find_project_merge_request(params[:merge_request_iid]) merge_when_pipeline_succeeds = to_boolean(params[:merge_when_pipeline_succeeds]) + not_automatically_mergeable = not_automatically_mergeable?(merge_when_pipeline_succeeds, merge_request) # Merge request can not be merged # because user dont have permissions to push into target branch unauthorized! unless merge_request.can_be_merged_by?(current_user) - not_allowed! unless merge_request.mergeable_state?(skip_ci_check: merge_when_pipeline_succeeds) + not_allowed! if !merge_request.mergeable_state?(skip_ci_check: merge_when_pipeline_succeeds) || not_automatically_mergeable render_api_error!('Branch cannot be merged', 406) unless merge_request.mergeable?(skip_ci_check: merge_when_pipeline_succeeds) @@ -411,7 +416,7 @@ module API sha: params[:sha] || merge_request.diff_head_sha ) - if merge_when_pipeline_succeeds && merge_request.head_pipeline && merge_request.head_pipeline.active? + if merge_when_pipeline_succeeds AutoMergeService.new(merge_request.target_project, current_user, merge_params) .execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS) else diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb index f9efef38825..f207d91235f 100644 --- a/lib/gitlab/middleware/go.rb +++ b/lib/gitlab/middleware/go.rb @@ -25,13 +25,13 @@ module Gitlab def render_go_doc(request) return unless go_request?(request) - path = project_path(request) + path, branch = project_path(request) return unless path - body = go_body(path) + body, code = go_response(path, branch) return unless body - response = Rack::Response.new(body, 200, { 'Content-Type' => 'text/html' }) + response = Rack::Response.new(body, code, { 'Content-Type' => 'text/html' }) response.finish end @@ -39,8 +39,15 @@ module Gitlab request["go-get"].to_i == 1 && request.env["PATH_INFO"].present? end - def go_body(path) + def go_response(path, branch) config = Gitlab.config + body_tag = content_tag :body, "go get #{config.gitlab.url}/#{path}" + + unless branch + html_tag = content_tag :html, body_tag + return html_tag, 404 + end + project_url = Gitlab::Utils.append_path(config.gitlab.url, path) import_prefix = strip_url(project_url.to_s) @@ -52,9 +59,11 @@ module Gitlab "#{project_url}.git" end - meta_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{repository_url}" - head_tag = content_tag :head, meta_tag - content_tag :html, head_tag + meta_import_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{repository_url}" + meta_source_tag = tag :meta, name: 'go-source', content: "#{import_prefix} #{project_url} #{project_url}/tree/#{branch}{/dir} #{project_url}/blob/#{branch}{/dir}/{file}#L{line}" + head_tag = content_tag :head, meta_import_tag + meta_source_tag + html_tag = content_tag :html, head_tag + body_tag + [html_tag, 200] end def strip_url(url) @@ -80,9 +89,6 @@ module Gitlab path_segments = path.split('/') simple_project_path = path_segments.first(2).join('/') - # If the path is at most 2 segments long, it is a simple `namespace/project` path and we're done - return simple_project_path if path_segments.length <= 2 - project_paths = [] begin project_paths << path_segments.join('/') @@ -94,7 +100,7 @@ module Gitlab if project # If a project is found and the user has access, we return the full project path - project.full_path + return project.full_path, project.default_branch else # If not, we return the first two components as if it were a simple `namespace/project` path, # so that we don't reveal the existence of a nested project the user doesn't have access to. @@ -105,7 +111,7 @@ module Gitlab # `go get gitlab.com/group/subgroup/project/subpackage` will not work for private projects. # `go get gitlab.com/group/subgroup/project.git/subpackage` will work, since Go is smart enough # to figure that out. `import 'gitlab.com/...'` behaves the same as `go get`. - simple_project_path + return simple_project_path, 'master' end end diff --git a/package.json b/package.json index 016f4f96e21..cb37136eada 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@babel/plugin-syntax-import-meta": "^7.2.0", "@babel/preset-env": "^7.6.2", "@gitlab/svgs": "^1.82.0", - "@gitlab/ui": "7.11.0", + "@gitlab/ui": "7.14.0", "@gitlab/visual-review-tools": "1.2.0", "@sentry/browser": "^5.7.1", "@sourcegraph/code-host-integration": "^0.0.13", diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index 562119d967f..5b528c3be52 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -166,6 +166,41 @@ describe Projects::ReleasesController do end end + describe 'GET #evidence' do + let!(:release) { create(:release, :with_evidence, project: project) } + let(:tag) { CGI.escape(release.tag) } + let(:format) { :json } + + subject do + get :evidence, params: { + namespace_id: project.namespace, + project_id: project, + tag: tag, + format: format + } + end + + before do + sign_in(user) + end + + it 'returns the correct evidence summary as a json' do + subject + + expect(json_response).to eq(release.evidence.summary) + end + + context 'when the release was created before evidence existed' do + it 'returns an empty json' do + release.evidence.destroy + + subject + + expect(json_response).to eq({}) + end + end + end + private def get_index diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb index 2f77bb95ea3..182ee2378d4 100644 --- a/spec/factories/releases.rb +++ b/spec/factories/releases.rb @@ -14,5 +14,11 @@ FactoryBot.define do sha { nil } author { nil } end + + trait :with_evidence do + after(:create) do |release, _| + create(:evidence, release: release) + end + end end end diff --git a/spec/frontend/monitoring/charts/time_series_spec.js b/spec/frontend/monitoring/charts/time_series_spec.js index 554535418fe..c561c5edf3c 100644 --- a/spec/frontend/monitoring/charts/time_series_spec.js +++ b/spec/frontend/monitoring/charts/time_series_spec.js @@ -116,6 +116,19 @@ describe('Time series component', () => { }); }); + it('does not throw error if data point is outside the zoom range', () => { + const seriesDataWithoutValue = generateSeriesData('line'); + expect( + timeSeriesChart.vm.formatTooltipText({ + ...seriesDataWithoutValue, + seriesData: seriesDataWithoutValue.seriesData.map(data => ({ + ...data, + value: undefined, + })), + }), + ).toBeUndefined(); + }); + describe('when series is of line type', () => { beforeEach(done => { timeSeriesChart.vm.formatTooltipText(generateSeriesData('line')); diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb index 16595102375..c81c69e95c7 100644 --- a/spec/lib/gitlab/middleware/go_spec.rb +++ b/spec/lib/gitlab/middleware/go_spec.rb @@ -30,13 +30,13 @@ describe Gitlab::Middleware::Go do shared_examples 'go-get=1' do |enabled_protocol:| context 'with simple 2-segment project path' do - let!(:project) { create(:project, :private) } + let!(:project) { create(:project, :private, :repository) } context 'with subpackages' do let(:path) { "#{project.full_path}/subpackage" } it 'returns the full project path' do - expect_response_with_path(go, enabled_protocol, project.full_path) + expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch) end end @@ -44,19 +44,19 @@ describe Gitlab::Middleware::Go do let(:path) { project.full_path } it 'returns the full project path' do - expect_response_with_path(go, enabled_protocol, project.full_path) + expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch) end end end context 'with a nested project path' do let(:group) { create(:group, :nested) } - let!(:project) { create(:project, :public, namespace: group) } + let!(:project) { create(:project, :public, :repository, namespace: group) } shared_examples 'a nested project' do context 'when the project is public' do it 'returns the full project path' do - expect_response_with_path(go, enabled_protocol, project.full_path) + expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch) end end @@ -67,7 +67,7 @@ describe Gitlab::Middleware::Go do shared_examples 'unauthorized' do it 'returns the 2-segment group path' do - expect_response_with_path(go, enabled_protocol, group.full_path) + expect_response_with_path(go, enabled_protocol, group.full_path, project.default_branch) end end @@ -85,7 +85,7 @@ describe Gitlab::Middleware::Go do shared_examples 'authenticated' do context 'with access to the project' do it 'returns the full project path' do - expect_response_with_path(go, enabled_protocol, project.full_path) + expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch) end end @@ -160,6 +160,36 @@ describe Gitlab::Middleware::Go do go end end + + context 'with a public project without a repository' do + let!(:project) { create(:project, :public) } + let(:path) { project.full_path } + + it 'returns 404' do + response = go + expect(response[0]).to eq(404) + expect(response[1]['Content-Type']).to eq('text/html') + expected_body = %{<html><body>go get #{Gitlab.config.gitlab.url}/#{project.full_path}</body></html>} + expect(response[2].body).to eq([expected_body]) + end + end + + context 'with a non-standard head' do + let(:user) { create(:user) } + let!(:project) { create(:project, :public, :repository) } + let(:path) { project.full_path } + let(:default_branch) { 'default_branch' } + + before do + project.add_maintainer(user) + project.repository.add_branch(user, default_branch, 'master') + project.change_head(default_branch) + end + + it 'returns the full project path' do + expect_response_with_path(go, enabled_protocol, project.full_path, default_branch) + end + end end context 'with SSH disabled' do @@ -199,16 +229,17 @@ describe Gitlab::Middleware::Go do middleware.call(env) end - def expect_response_with_path(response, protocol, path) + def expect_response_with_path(response, protocol, path, branch) repository_url = case protocol when :ssh "ssh://#{Gitlab.config.gitlab.user}@#{Gitlab.config.gitlab.host}/#{path}.git" when :http, nil "http://#{Gitlab.config.gitlab.host}/#{path}.git" end + project_url = "http://#{Gitlab.config.gitlab.host}/#{path}" expect(response[0]).to eq(200) expect(response[1]['Content-Type']).to eq('text/html') - expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}" /></head></html>} + expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}" /><meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/tree/#{branch}{/dir} #{project_url}/blob/#{branch}{/dir}/{file}#L{line}" /></head><body>go get #{Gitlab.config.gitlab.url}/#{path}</body></html>} expect(response[2].body).to eq([expected_body]) end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index b5aa05fd8b4..310f806e3d3 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -2326,6 +2326,26 @@ describe MergeRequest do end end + describe "#head_pipeline_active? " do + it do + is_expected + .to delegate_method(:active?) + .to(:head_pipeline) + .with_prefix + .with_arguments(allow_nil: true) + end + end + + describe "#actual_head_pipeline_success? " do + it do + is_expected + .to delegate_method(:success?) + .to(:actual_head_pipeline) + .with_prefix + .with_arguments(allow_nil: true) + end + end + describe '#mergeable_ci_state?' do let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true) } let(:pipeline) { create(:ci_empty_pipeline) } diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index f9c7a14f1f3..cadb8793e15 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -53,6 +53,12 @@ RSpec.describe Release do end end + describe 'callbacks' do + it 'creates a new Evidence object on after_commit', :sidekiq_inline do + expect { release }.to change(Evidence, :count).by(1) + end + end + describe '#assets_count' do subject { release.assets_count } @@ -92,20 +98,22 @@ RSpec.describe Release do end end - describe 'evidence', :sidekiq_might_not_need_inline do + describe 'evidence' do + let(:release_with_evidence) { create(:release, :with_evidence, project: project) } + describe '#create_evidence!' do context 'when a release is created' do it 'creates one Evidence object too' do - expect { release }.to change(Evidence, :count).by(1) + expect { release_with_evidence }.to change(Evidence, :count).by(1) end end end context 'when a release is deleted' do it 'also deletes the associated evidence' do - release = create(:release) + release_with_evidence - expect { release.destroy }.to change(Evidence, :count).by(-1) + expect { release_with_evidence.destroy }.to change(Evidence, :count).by(-1) end end end @@ -141,4 +149,36 @@ RSpec.describe Release do end end end + + describe '#evidence_sha' do + subject { release.evidence_sha } + + context 'when a release was created before evidence collection existed' do + let!(:release) { create(:release) } + + it { is_expected.to be_nil } + end + + context 'when a release was created with evidence collection' do + let!(:release) { create(:release, :with_evidence) } + + it { is_expected.to eq(release.evidence.summary_sha) } + end + end + + describe '#evidence_summary' do + subject { release.evidence_summary } + + context 'when a release was created before evidence collection existed' do + let!(:release) { create(:release) } + + it { is_expected.to eq({}) } + end + + context 'when a release was created with evidence collection' do + let!(:release) { create(:release, :with_evidence) } + + it { is_expected.to eq(release.evidence.summary) } + end + end end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index c96c80b6998..e5ad1a6378e 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -1567,6 +1567,18 @@ describe API::MergeRequests do expect(response).to have_gitlab_http_status(200) end + it 'does not merge if merge_when_pipeline_succeeds is passed and the pipeline has failed' do + create(:ci_pipeline, + :failed, + sha: merge_request.diff_head_sha, + merge_requests_as_head_pipeline: [merge_request]) + + put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: { merge_when_pipeline_succeeds: true } + + expect(response).to have_gitlab_http_status(405) + expect(merge_request.reload.state).to eq('opened') + end + it "enables merge when pipeline succeeds if the pipeline is active" do allow_any_instance_of(MergeRequest).to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline) allow(pipeline).to receive(:active?).and_return(true) diff --git a/spec/support/matchers/navigation_matcher.rb b/spec/support/matchers/navigation_matcher.rb index ad73c96031e..a0beecbfb2c 100644 --- a/spec/support/matchers/navigation_matcher.rb +++ b/spec/support/matchers/navigation_matcher.rb @@ -9,6 +9,6 @@ end RSpec::Matchers.define :have_active_sub_navigation do |expected| match do |page| - expect(page.find('.sidebar-sub-level-items > li.active:not(.fly-out-top-item)')).to have_content(expected) + expect(page).to have_css('.sidebar-sub-level-items > li.active:not(.fly-out-top-item)', text: expected) end end diff --git a/yarn.lock b/yarn.lock index 3b359ee98e9..21017b61d40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -722,13 +722,13 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.82.0.tgz#c059c460afc13ebfe9df370521ca8963fa5afb80" integrity sha512-9L4Brys2LCk44lHvFsCFDKN768lYjoMVYDb4PD7FSjqUEruQQ1SRj0rvb1RWKLhiTCDKrtDOXkH6I1TTEms24w== -"@gitlab/ui@7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-7.11.0.tgz#b5c981f3b1edbf0ad75bcca8fa1cd81017676b3b" - integrity sha512-PxZkgdY2j/XdriTdp3jsnsif9cgcxd1wUF8PVOho2HIyJqU244E8ELewIXkDozQq3p3ZXzWnjR/GvYcNMZtGmA== +"@gitlab/ui@7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-7.14.0.tgz#942369c91ebbe12757bd379bfb2f2d9304d8af87" + integrity sha512-boA3w2KrTtSXox2yp/zzvy0LADVXtY/4Hmpipy5j+CRZEoh6z7p2XefSOhb/5hE89ekZUjtu2pfII96kJ2WI+w== dependencies: "@babel/standalone" "^7.0.0" - "@gitlab/vue-toasted" "^1.2.1" + "@gitlab/vue-toasted" "^1.3.0" bootstrap-vue "2.0.0-rc.27" copy-to-clipboard "^3.0.8" echarts "^4.2.1" @@ -745,10 +745,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.2.0.tgz#8d6757917193c1023012bb4a316dc1a97309a27a" integrity sha512-GaV/lYLmOF0hWtv8K8MLWGaCZ7PL1LF4D0/gargXYf9HO0Cw4wtz4oWyaLS15wFposJIYdPIHSNfrLVk4Dk9sQ== -"@gitlab/vue-toasted@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.2.1.tgz#f407b5aa710863e5b7f021f4a1f66160331ab263" - integrity sha512-ve2PLxKqrwNpsd+4bV5zGJT5+H5N/VJBZoFS2Vp1mH5cUDBYIHTzDmbS6AbBGUDh0F3TxmFMiqfXfpO/1VjBNQ== +"@gitlab/vue-toasted@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.3.0.tgz#f21550d4ce406ee5f99447a02abf36250ecc922d" + integrity sha512-xexu7YbbIkQS5FDqPaewrOTQ4/myth5VyU8+hWZ+Tj1e5CuAlDNha3dHbvwyLW8/2flm/2mfslFNPAX2DRe8ZQ== "@jest/console@^24.7.1": version "24.7.1" |