Commit 34b3567c authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 3209c1a4
...@@ -253,6 +253,7 @@ export default { ...@@ -253,6 +253,7 @@ export default {
this.tooltip.title = dateFormat(params.value, dateFormats.default); this.tooltip.title = dateFormat(params.value, dateFormats.default);
this.tooltip.content = []; this.tooltip.content = [];
params.seriesData.forEach(dataPoint => { params.seriesData.forEach(dataPoint => {
if (dataPoint.value) {
const [xVal, yVal] = dataPoint.value; const [xVal, yVal] = dataPoint.value;
this.tooltip.isDeployment = dataPoint.componentSubType === graphTypes.deploymentData; this.tooltip.isDeployment = dataPoint.componentSubType === graphTypes.deploymentData;
if (this.tooltip.isDeployment) { if (this.tooltip.isDeployment) {
...@@ -271,6 +272,7 @@ export default { ...@@ -271,6 +272,7 @@ export default {
color, color,
}); });
} }
}
}); });
}, },
setSvg(name) { setSvg(name) {
......
...@@ -20,6 +20,14 @@ class Projects::ReleasesController < Projects::ApplicationController ...@@ -20,6 +20,14 @@ class Projects::ReleasesController < Projects::ApplicationController
end end
end end
def evidence
respond_to do |format|
format.json do
render json: release.evidence_summary
end
end
end
protected protected
def releases def releases
......
...@@ -241,6 +241,9 @@ class MergeRequest < ApplicationRecord ...@@ -241,6 +241,9 @@ class MergeRequest < ApplicationRecord
alias_attribute :auto_merge_enabled, :merge_when_pipeline_succeeds alias_attribute :auto_merge_enabled, :merge_when_pipeline_succeeds
alias_method :issuing_parent, :target_project 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) RebaseLockTimeout = Class.new(StandardError)
REBASE_LOCK_MESSAGE = _("Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later.") REBASE_LOCK_MESSAGE = _("Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later.")
......
...@@ -73,6 +73,14 @@ class Release < ApplicationRecord ...@@ -73,6 +73,14 @@ class Release < ApplicationRecord
self.read_attribute(:name) || tag self.read_attribute(:name) || tag
end end
def evidence_sha
evidence&.summary_sha
end
def evidence_summary
evidence&.summary || {}
end
private private
def actual_sha def actual_sha
......
...@@ -37,6 +37,12 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated ...@@ -37,6 +37,12 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
edit_project_release_url(project, release) edit_project_release_url(project, release)
end end
def evidence_file_path
return unless release.evidence.present?
evidence_project_release_url(project, tag, format: :json)
end
private private
def can_download_code? def can_download_code?
......
...@@ -11,7 +11,7 @@ module AutoMerge ...@@ -11,7 +11,7 @@ module AutoMerge
end end
def process(merge_request) 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? return unless merge_request.mergeable?
merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params) merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params)
......
...@@ -87,7 +87,7 @@ module MergeRequests ...@@ -87,7 +87,7 @@ module MergeRequests
merge_request.update(merge_error: nil) 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) AutoMergeService.new(project, current_user, { sha: last_diff_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
else else
merge_request.merge_async(current_user.id, { sha: last_diff_sha }) merge_request.merge_async(current_user.id, { sha: last_diff_sha })
......
---
title: Update merging an MR behavior on the API when pipeline fails
merge_request: 19641
author: briankabiro
type: fixed
---
title: Support go-source meta tag for godoc.org
merge_request: 19888
author: Ethan Reesor (@firelizzard)
type: changed
---
title: Fixed monitor charts from throwing error when zoomed
merge_request: 20331
author:
type: fixed
---
title: Update Release API with evidence related data.
merge_request: 19706
author:
type: added
...@@ -179,7 +179,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -179,7 +179,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end end
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 :starrers, only: [:index]
resources :forks, only: [:index, :new, :create] resources :forks, only: [:index, :new, :create]
resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ } resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ }
......
...@@ -10,6 +10,9 @@ This section documents LDAP features specific to to GitLab Enterprise Edition ...@@ -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, For documentation relevant to both Community Edition and Enterprise Edition,
see the main [LDAP documentation](ldap.md). 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 ## Use cases
- User sync: Once a day, GitLab will update users against LDAP. - User sync: Once a day, GitLab will update users against LDAP.
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/41766) in GitLab 11.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. > - 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). > - 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 ## List Releases
...@@ -87,6 +88,7 @@ Example response: ...@@ -87,6 +88,7 @@ Example response:
], ],
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
"tag_path":"/root/awesome-app/-/tags/v0.11.1", "tag_path":"/root/awesome-app/-/tags/v0.11.1",
"evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
"assets":{ "assets":{
"count":6, "count":6,
"sources":[ "sources":[
...@@ -120,7 +122,8 @@ Example response: ...@@ -120,7 +122,8 @@ Example response:
"url":"http://192.168.10.15:3000", "url":"http://192.168.10.15:3000",
"external":true "external":true
} }
] ],
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json"
}, },
}, },
{ {
...@@ -154,6 +157,7 @@ Example response: ...@@ -154,6 +157,7 @@ Example response:
"committer_email":"admin@example.com", "committer_email":"admin@example.com",
"committed_date":"2019-01-03T01:53:28.000Z" "committed_date":"2019-01-03T01:53:28.000Z"
}, },
"evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
"assets":{ "assets":{
"count":4, "count":4,
"sources":[ "sources":[
...@@ -176,7 +180,8 @@ Example response: ...@@ -176,7 +180,8 @@ Example response:
], ],
"links":[ "links":[
] ],
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json"
}, },
} }
] ]
...@@ -265,8 +270,9 @@ Example response: ...@@ -265,8 +270,9 @@ Example response:
], ],
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
"tag_path":"/root/awesome-app/-/tags/v0.11.1", "tag_path":"/root/awesome-app/-/tags/v0.11.1",
"evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
"assets":{ "assets":{
"count":4, "count":5,
"sources":[ "sources":[
{ {
"format":"zip", "format":"zip",
...@@ -287,7 +293,8 @@ Example response: ...@@ -287,7 +293,8 @@ Example response:
], ],
"links":[ "links":[
] ],
"evidence_url":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json"
}, },
} }
``` ```
...@@ -385,6 +392,7 @@ Example response: ...@@ -385,6 +392,7 @@ Example response:
], ],
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
"tag_path":"/root/awesome-app/-/tags/v0.11.1", "tag_path":"/root/awesome-app/-/tags/v0.11.1",
"evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
"assets":{ "assets":{
"count":5, "count":5,
"sources":[ "sources":[
...@@ -412,7 +420,8 @@ Example response: ...@@ -412,7 +420,8 @@ Example response:
"url":"https://google.com", "url":"https://google.com",
"external":true "external":true
} }
] ],
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.3/evidence.json"
}, },
} }
``` ```
...@@ -491,6 +500,7 @@ Example response: ...@@ -491,6 +500,7 @@ Example response:
], ],
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
"tag_path":"/root/awesome-app/-/tags/v0.11.1", "tag_path":"/root/awesome-app/-/tags/v0.11.1",
"evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
"assets":{ "assets":{
"count":4, "count":4,
"sources":[ "sources":[
...@@ -513,7 +523,8 @@ Example response: ...@@ -513,7 +523,8 @@ Example response:
], ],
"links":[ "links":[
] ],
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json"
}, },
} }
``` ```
...@@ -573,6 +584,7 @@ Example response: ...@@ -573,6 +584,7 @@ Example response:
}, },
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
"tag_path":"/root/awesome-app/-/tags/v0.11.1", "tag_path":"/root/awesome-app/-/tags/v0.11.1",
"evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
"assets":{ "assets":{
"count":4, "count":4,
"sources":[ "sources":[
...@@ -595,7 +607,8 @@ Example response: ...@@ -595,7 +607,8 @@ Example response:
], ],
"links":[ "links":[
] ],
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json"
}, },
} }
``` ```
......
...@@ -200,9 +200,14 @@ When [renaming a user](../profile/index.md#changing-your-username), ...@@ -200,9 +200,14 @@ When [renaming a user](../profile/index.md#changing-your-username),
## Use your project as a Go package ## Use your project as a Go package
Any project can be used as a Go package including private projects in subgroups. To use packages Any project can be used as a Go package including private projects in subgroups.
hosted in private projects with the `go get` command, use a [`.netrc` file](https://ec.haxx.se/usingcurl-netrc.html) GitLab responds correctly to `go get` and `godoc.org` discovery requests,
and a [personal access token](../profile/personal_access_tokens.md) in the password field. 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: For example:
......
...@@ -1315,6 +1315,7 @@ module API ...@@ -1315,6 +1315,7 @@ module API
expose :milestones, using: Entities::Milestone, if: -> (release, _) { release.milestones.present? } expose :milestones, using: Entities::Milestone, if: -> (release, _) { release.milestones.present? }
expose :commit_path, expose_nil: false expose :commit_path, expose_nil: false
expose :tag_path, expose_nil: false expose :tag_path, expose_nil: false
expose :evidence_sha, expose_nil: false
expose :assets do expose :assets do
expose :assets_count, as: :count do |release, _| expose :assets_count, as: :count do |release, _|
assets_to_exclude = can_download_code? ? [] : [:sources] assets_to_exclude = can_download_code? ? [] : [:sources]
...@@ -1324,6 +1325,7 @@ module API ...@@ -1324,6 +1325,7 @@ module API
expose :links, using: Entities::Releases::Link do |release, options| expose :links, using: Entities::Releases::Link do |release, options|
release.links.sorted release.links.sorted
end end
expose :evidence_file_path, expose_nil: false
end end
expose :_links do expose :_links do
expose :merge_requests_url, expose_nil: false expose :merge_requests_url, expose_nil: false
......
...@@ -68,6 +68,10 @@ module API ...@@ -68,6 +68,10 @@ module API
end end
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) def serializer_options_for(merge_requests)
options = { with: Entities::MergeRequestBasic, current_user: current_user } options = { with: Entities::MergeRequestBasic, current_user: current_user }
...@@ -391,12 +395,13 @@ module API ...@@ -391,12 +395,13 @@ module API
merge_request = find_project_merge_request(params[:merge_request_iid]) merge_request = find_project_merge_request(params[:merge_request_iid])
merge_when_pipeline_succeeds = to_boolean(params[:merge_when_pipeline_succeeds]) 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 # Merge request can not be merged
# because user dont have permissions to push into target branch # because user dont have permissions to push into target branch
unauthorized! unless merge_request.can_be_merged_by?(current_user) 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) 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 ...@@ -411,7 +416,7 @@ module API
sha: params[:sha] || merge_request.diff_head_sha 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) AutoMergeService.new(merge_request.target_project, current_user, merge_params)
.execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS) .execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
else else
......
...@@ -25,13 +25,13 @@ module Gitlab ...@@ -25,13 +25,13 @@ module Gitlab
def render_go_doc(request) def render_go_doc(request)
return unless go_request?(request) return unless go_request?(request)
path = project_path(request) path, branch = project_path(request)
return unless path return unless path
body = go_body(path) body, code = go_response(path, branch)
return unless body 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 response.finish
end end
...@@ -39,8 +39,15 @@ module Gitlab ...@@ -39,8 +39,15 @@ module Gitlab
request["go-get"].to_i == 1 && request.env["PATH_INFO"].present? request["go-get"].to_i == 1 && request.env["PATH_INFO"].present?
end end
def go_body(path) def go_response(path, branch)
config = Gitlab.config 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) project_url = Gitlab::Utils.append_path(config.gitlab.url, path)
import_prefix = strip_url(project_url.to_s) import_prefix = strip_url(project_url.to_s)
...@@ -52,9 +59,11 @@ module Gitlab ...@@ -52,9 +59,11 @@ module Gitlab
"#{project_url}.git" "#{project_url}.git"
end end
meta_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{repository_url}" meta_import_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{repository_url}"
head_tag = content_tag :head, meta_tag 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}"
content_tag :html, head_tag head_tag = content_tag :head, meta_import_tag + meta_source_tag
html_tag = content_tag :html, head_tag + body_tag
[html_tag, 200]
end end
def strip_url(url) def strip_url(url)
...@@ -80,9 +89,6 @@ module Gitlab ...@@ -80,9 +89,6 @@ module Gitlab
path_segments = path.split('/') path_segments = path.split('/')
simple_project_path = path_segments.first(2).join('/') 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 = [] project_paths = []
begin begin
project_paths << path_segments.join('/') project_paths << path_segments.join('/')
...@@ -94,7 +100,7 @@ module Gitlab ...@@ -94,7 +100,7 @@ module Gitlab
if project if project
# If a project is found and the user has access, we return the full project path # 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 else
# If not, we return the first two components as if it were a simple `namespace/project` path, # 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. # 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 ...@@ -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/subpackage` will not work for private projects.
# `go get gitlab.com/group/subgroup/project.git/subpackage` will work, since Go is smart enough # `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`. # to figure that out. `import 'gitlab.com/...'` behaves the same as `go get`.
simple_project_path return simple_project_path, 'master'
end end
end end
......
...@@ -166,6 +166,41 @@ describe Projects::ReleasesController do ...@@ -166,6 +166,41 @@ describe Projects::ReleasesController do
end end
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 private
def get_index def get_index
......
...@@ -14,5 +14,11 @@ FactoryBot.define do ...@@ -14,5 +14,11 @@ FactoryBot.define do
sha { nil } sha { nil }
author { nil } author { nil }
end end
trait :with_evidence do
after(:create) do |release, _|
create(:evidence, release: release)
end
end
end end
end end
...@@ -116,6 +116,19 @@ describe('Time series component', () => { ...@@ -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', () => { describe('when series is of line type', () => {
beforeEach(done => { beforeEach(done => {
timeSeriesChart.vm.formatTooltipText(generateSeriesData('line')); timeSeriesChart.vm.formatTooltipText(generateSeriesData('line'));
......
...@@ -30,13 +30,13 @@ describe Gitlab::Middleware::Go do ...@@ -30,13 +30,13 @@ describe Gitlab::Middleware::Go do
shared_examples 'go-get=1' do |enabled_protocol:| shared_examples 'go-get=1' do |enabled_protocol:|
context 'with simple 2-segment project path' do context 'with simple 2-segment project path' do
let!(:project) { create(:project, :private) } let!(:project) { create(:project, :private, :repository) }
context 'with subpackages' do context 'with subpackages' do
let(:path) { "#{project.full_path}/subpackage" } let(:path) { "#{project.full_path}/subpackage" }
it 'returns the full project path' 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
end end
...@@ -44,19 +44,19 @@ describe Gitlab::Middleware::Go do ...@@ -44,19 +44,19 @@ describe Gitlab::Middleware::Go do
let(:path) { project.full_path } let(:path) { project.full_path }
it 'returns the full project path' 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
end end
end end
context 'with a nested project path' do context 'with a nested project path' do
let(:group) { create(:group, :nested) } 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 shared_examples 'a nested project' do
context 'when the project is public' do context 'when the project is public' do
it 'returns the full project path' 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
end end
...@@ -67,7 +67,7 @@ describe Gitlab::Middleware::Go do ...@@ -67,7 +67,7 @@ describe Gitlab::Middleware::Go do
shared_examples 'unauthorized' do shared_examples 'unauthorized' do
it 'returns the 2-segment group path' 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
end end
...@@ -85,7 +85,7 @@ describe Gitlab::Middleware::Go do ...@@ -85,7 +85,7 @@ describe Gitlab::Middleware::Go do
shared_examples 'authenticated' do shared_examples 'authenticated' do
context 'with access to the project' do context 'with access to the project' do
it 'returns the full project path' 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
end end
...@@ -160,6 +160,36 @@ describe Gitlab::Middleware::Go do ...@@ -160,6 +160,36 @@ describe Gitlab::Middleware::Go do
go go
end end
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 end
context 'with SSH disabled' do context 'with SSH disabled' do
...@@ -199,16 +229,17 @@ describe Gitlab::Middleware::Go do ...@@ -199,16 +229,17 @@ describe Gitlab::Middleware::Go do
middleware.call(env) middleware.call(env)
end end
def expect_response_with_path(response, protocol, path) def expect_response_with_path(response, protocol, path, branch)
repository_url = case protocol repository_url = case protocol
when :ssh when :ssh
"ssh://#{Gitlab.config.gitlab.user}@#{Gitlab.config.gitlab.host}/#{path}.git" "ssh://#{Gitlab.config.gitlab.user}@#{Gitlab.config.gitlab.host}/#{path}.git"
when :http, nil when :http, nil
"http://#{Gitlab.config.gitlab.host}/#{path}.git" "http://#{Gitlab.config.gitlab.host}/#{path}.git"
end end
project_url = "http://#{Gitlab.config.gitlab.host}/#{path}"
expect(response[0]).to eq(200) expect(response[0]).to eq(200)
expect(response[1]['Content-Type']).to eq('text/html') 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]) expect(response[2].body).to eq([expected_body])
end end
end end
......
...@@ -2326,6 +2326,26 @@ describe MergeRequest do ...@@ -2326,6 +2326,26 @@ describe MergeRequest do
end end
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 describe '#mergeable_ci_state?' do
let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true) } let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true) }
let(:pipeline) { create(:ci_empty_pipeline) } let(:pipeline) { create(:ci_empty_pipeline) }
......
...@@ -53,6 +53,12 @@ RSpec.describe Release do ...@@ -53,6 +53,12 @@ RSpec.describe Release do
end end
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 describe '#assets_count' do
subject { release.assets_count } subject { release.assets_count }
...@@ -92,20 +98,22 @@ RSpec.describe Release do ...@@ -92,20 +98,22 @@ RSpec.describe Release do
end end
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 describe '#create_evidence!' do
context 'when a release is created' do context 'when a release is created' do
it 'creates one Evidence object too' 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 end
end end
context 'when a release is deleted' do context 'when a release is deleted' do
it 'also deletes the associated evidence' 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 end
end end
...@@ -141,4 +149,36 @@ RSpec.describe Release do ...@@ -141,4 +149,36 @@ RSpec.describe Release do
end end
end 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 end
...@@ -1567,6 +1567,18 @@ describe API::MergeRequests do ...@@ -1567,6 +1567,18 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
end 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 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_any_instance_of(MergeRequest).to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
allow(pipeline).to receive(:active?).and_return(true) allow(pipeline).to receive(:active?).and_return(true)
......
...@@ -9,6 +9,6 @@ end ...@@ -9,6 +9,6 @@ end
RSpec::Matchers.define :have_active_sub_navigation do |expected| RSpec::Matchers.define :have_active_sub_navigation do |expected|
match do |page| 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
end end
...@@ -722,13 +722,13 @@ ...@@ -722,13 +722,13 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.82.0.tgz#c059c460afc13ebfe9df370521ca8963fa5afb80" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.82.0.tgz#c059c460afc13ebfe9df370521ca8963fa5afb80"
integrity sha512-9L4Brys2LCk44lHvFsCFDKN768lYjoMVYDb4PD7FSjqUEruQQ1SRj0rvb1RWKLhiTCDKrtDOXkH6I1TTEms24w== integrity sha512-9L4Brys2LCk44lHvFsCFDKN768lYjoMVYDb4PD7FSjqUEruQQ1SRj0rvb1RWKLhiTCDKrtDOXkH6I1TTEms24w==
"@gitlab/ui@7.11.0": "@gitlab/ui@7.14.0":
version "7.11.0" version "7.14.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-7.11.0.tgz#b5c981f3b1edbf0ad75bcca8fa1cd81017676b3b" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-7.14.0.tgz#942369c91ebbe12757bd379bfb2f2d9304d8af87"
integrity sha512-PxZkgdY2j/XdriTdp3jsnsif9cgcxd1wUF8PVOho2HIyJqU244E8ELewIXkDozQq3p3ZXzWnjR/GvYcNMZtGmA== integrity sha512-boA3w2KrTtSXox2yp/zzvy0LADVXtY/4Hmpipy5j+CRZEoh6z7p2XefSOhb/5hE89ekZUjtu2pfII96kJ2WI+w==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.2.1" "@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.0.0-rc.27" bootstrap-vue "2.0.0-rc.27"
copy-to-clipboard "^3.0.8" copy-to-clipboard "^3.0.8"
echarts "^4.2.1" echarts "^4.2.1"
...@@ -745,10 +745,10 @@ ...@@ -745,10 +745,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.2.0.tgz#8d6757917193c1023012bb4a316dc1a97309a27a" resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.2.0.tgz#8d6757917193c1023012bb4a316dc1a97309a27a"
integrity sha512-GaV/lYLmOF0hWtv8K8MLWGaCZ7PL1LF4D0/gargXYf9HO0Cw4wtz4oWyaLS15wFposJIYdPIHSNfrLVk4Dk9sQ== integrity sha512-GaV/lYLmOF0hWtv8K8MLWGaCZ7PL1LF4D0/gargXYf9HO0Cw4wtz4oWyaLS15wFposJIYdPIHSNfrLVk4Dk9sQ==
"@gitlab/vue-toasted@^1.2.1": "@gitlab/vue-toasted@^1.3.0":
version "1.2.1" version "1.3.0"
resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.2.1.tgz#f407b5aa710863e5b7f021f4a1f66160331ab263" resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.3.0.tgz#f21550d4ce406ee5f99447a02abf36250ecc922d"
integrity sha512-ve2PLxKqrwNpsd+4bV5zGJT5+H5N/VJBZoFS2Vp1mH5cUDBYIHTzDmbS6AbBGUDh0F3TxmFMiqfXfpO/1VjBNQ== integrity sha512-xexu7YbbIkQS5FDqPaewrOTQ4/myth5VyU8+hWZ+Tj1e5CuAlDNha3dHbvwyLW8/2flm/2mfslFNPAX2DRe8ZQ==
"@jest/console@^24.7.1": "@jest/console@^24.7.1":
version "24.7.1" version "24.7.1"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment