Commit 2bb32cd2 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'evidence-docs-and-release-api' into 'master'

Evidence docs and release api

See merge request gitlab-org/gitlab!19706
parents d31775d9 a07c7590
...@@ -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
......
...@@ -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?
......
---
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+/ }
......
...@@ -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"
}, },
} }
``` ```
......
...@@ -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
......
...@@ -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
...@@ -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
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