Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
de1b5595
Commit
de1b5595
authored
Dec 31, 2018
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
f02a5523
102c1870
Changes
35
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
1265 additions
and
190 deletions
+1265
-190
app/controllers/projects/releases_controller.rb
app/controllers/projects/releases_controller.rb
+3
-3
app/controllers/projects/tags_controller.rb
app/controllers/projects/tags_controller.rb
+14
-1
app/finders/releases_finder.rb
app/finders/releases_finder.rb
+14
-0
app/models/release.rb
app/models/release.rb
+28
-0
app/policies/project_policy.rb
app/policies/project_policy.rb
+7
-0
app/policies/release_policy.rb
app/policies/release_policy.rb
+5
-0
app/services/commits/tag_service.rb
app/services/commits/tag_service.rb
+1
-2
app/services/create_release_service.rb
app/services/create_release_service.rb
+0
-35
app/services/releases/concerns.rb
app/services/releases/concerns.rb
+48
-0
app/services/releases/create_service.rb
app/services/releases/create_service.rb
+54
-0
app/services/releases/destroy_service.rb
app/services/releases/destroy_service.rb
+25
-0
app/services/releases/update_service.rb
app/services/releases/update_service.rb
+32
-0
app/services/tags/create_service.rb
app/services/tags/create_service.rb
+2
-5
app/services/tags/destroy_service.rb
app/services/tags/destroy_service.rb
+6
-4
app/services/update_release_service.rb
app/services/update_release_service.rb
+0
-28
app/views/layouts/nav/sidebar/_project.html.haml
app/views/layouts/nav/sidebar/_project.html.haml
+1
-1
changelogs/unreleased/ac-releases-api.yml
changelogs/unreleased/ac-releases-api.yml
+5
-0
lib/api/api.rb
lib/api/api.rb
+1
-0
lib/api/entities.rb
lib/api/entities.rb
+11
-2
lib/api/releases.rb
lib/api/releases.rb
+138
-0
lib/api/tags.rb
lib/api/tags.rb
+56
-14
spec/factories/releases.rb
spec/factories/releases.rb
+7
-0
spec/finders/releases_finder_spec.rb
spec/finders/releases_finder_spec.rb
+42
-0
spec/fixtures/api/schemas/release.json
spec/fixtures/api/schemas/release.json
+18
-0
spec/fixtures/api/schemas/releases.json
spec/fixtures/api/schemas/releases.json
+4
-0
spec/lib/gitlab/legacy_github_import/importer_spec.rb
spec/lib/gitlab/legacy_github_import/importer_spec.rb
+1
-1
spec/models/release_spec.rb
spec/models/release_spec.rb
+3
-1
spec/policies/project_policy_spec.rb
spec/policies/project_policy_spec.rb
+6
-5
spec/requests/api/releases_spec.rb
spec/requests/api/releases_spec.rb
+532
-0
spec/requests/api/tags_spec.rb
spec/requests/api/tags_spec.rb
+18
-15
spec/services/create_release_service_spec.rb
spec/services/create_release_service_spec.rb
+0
-39
spec/services/releases/create_service_spec.rb
spec/services/releases/create_service_spec.rb
+72
-0
spec/services/releases/destroy_service_spec.rb
spec/services/releases/destroy_service_spec.rb
+61
-0
spec/services/releases/update_service_spec.rb
spec/services/releases/update_service_spec.rb
+50
-0
spec/services/update_release_service_spec.rb
spec/services/update_release_service_spec.rb
+0
-34
No files found.
app/controllers/projects/releases_controller.rb
View file @
de1b5595
...
...
@@ -3,7 +3,7 @@
class
Projects::ReleasesController
<
Projects
::
ApplicationController
# Authorize
before_action
:require_non_empty_project
before_action
:authorize_
download_cod
e!
before_action
:authorize_
read_releas
e!
before_action
:check_releases_page_feature_flag
def
index
...
...
@@ -12,8 +12,8 @@ class Projects::ReleasesController < Projects::ApplicationController
private
def
check_releases_page_feature_flag
return
render_404
unless
Feature
.
enabled?
(
:releases_page
)
return
render_404
unless
Feature
.
enabled?
(
:releases_page
,
@project
)
push_frontend_feature_flag
(
:releases_page
)
push_frontend_feature_flag
(
:releases_page
,
@project
)
end
end
app/controllers/projects/tags_controller.rb
View file @
de1b5595
...
...
@@ -43,9 +43,22 @@ class Projects::TagsController < Projects::ApplicationController
def
create
result
=
::
Tags
::
CreateService
.
new
(
@project
,
current_user
)
.
execute
(
params
[
:tag_name
],
params
[
:ref
],
params
[
:message
]
,
params
[
:release_description
]
)
.
execute
(
params
[
:tag_name
],
params
[
:ref
],
params
[
:message
])
if
result
[
:status
]
==
:success
# Release creation with Tags was deprecated in GitLab 11.7
if
params
[
:release_description
].
present?
release_params
=
{
tag:
params
[
:tag_name
],
name:
params
[
:tag_name
],
description:
params
[
:release_description
]
}
Releases
::
CreateService
.
new
(
@project
,
current_user
,
release_params
)
.
execute
end
@tag
=
result
[
:tag
]
redirect_to
project_tag_path
(
@project
,
@tag
.
name
)
...
...
app/finders/releases_finder.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
class
ReleasesFinder
def
initialize
(
project
,
current_user
=
nil
)
@project
=
project
@current_user
=
current_user
end
def
execute
return
Release
.
none
unless
Ability
.
allowed?
(
@current_user
,
:read_release
,
@project
)
@project
.
releases
.
sorted
end
end
app/models/release.rb
View file @
de1b5595
...
...
@@ -2,11 +2,39 @@
class
Release
<
ActiveRecord
::
Base
include
CacheMarkdownField
include
Gitlab
::
Utils
::
StrongMemoize
cache_markdown_field
:description
belongs_to
:project
# releases prior to 11.7 have no author
belongs_to
:author
,
class_name:
'User'
validates
:description
,
:project
,
:tag
,
presence:
true
scope
:sorted
,
->
{
order
(
created_at: :desc
)
}
delegate
:repository
,
to: :project
def
commit
strong_memoize
(
:commit
)
do
repository
.
commit
(
actual_sha
)
end
end
def
tag_missing?
actual_tag
.
nil?
end
private
def
actual_sha
sha
||
actual_tag
&
.
dereferenced_target
end
def
actual_tag
strong_memoize
(
:actual_tag
)
do
repository
.
find_tag
(
tag
)
end
end
end
app/policies/project_policy.rb
View file @
de1b5595
...
...
@@ -23,6 +23,7 @@ class ProjectPolicy < BasePolicy
container_image
pages
cluster
release
]
.
freeze
desc
"User is a project owner"
...
...
@@ -173,6 +174,7 @@ class ProjectPolicy < BasePolicy
enable
:read_cycle_analytics
enable
:award_emoji
enable
:read_pages_content
enable
:read_release
end
# These abilities are not allowed to admins that are not members of the project,
...
...
@@ -239,6 +241,8 @@ class ProjectPolicy < BasePolicy
enable
:update_container_image
enable
:create_environment
enable
:create_deployment
enable
:create_release
enable
:update_release
end
rule
{
can?
(
:maintainer_access
)
}.
policy
do
...
...
@@ -266,6 +270,7 @@ class ProjectPolicy < BasePolicy
enable
:update_cluster
enable
:admin_cluster
enable
:create_environment_terminal
enable
:destroy_release
end
rule
{
(
mirror_available
&
can?
(
:admin_project
))
|
admin
}.
enable
:admin_remote_mirror
...
...
@@ -325,6 +330,7 @@ class ProjectPolicy < BasePolicy
prevent
:download_code
prevent
:fork_project
prevent
:read_commit_status
prevent
(
*
create_read_update_admin_destroy
(
:release
))
end
rule
{
container_registry_disabled
}.
policy
do
...
...
@@ -354,6 +360,7 @@ class ProjectPolicy < BasePolicy
enable
:read_commit_status
enable
:read_container_image
enable
:download_code
enable
:read_release
enable
:download_wiki_code
enable
:read_cycle_analytics
enable
:read_pages_content
...
...
app/policies/release_policy.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
class
ReleasePolicy
<
BasePolicy
delegate
{
@subject
.
project
}
end
app/services/commits/tag_service.rb
View file @
de1b5595
...
...
@@ -9,11 +9,10 @@ module Commits
tag_name
=
params
[
:tag_name
]
message
=
params
[
:tag_message
]
release_description
=
nil
result
=
Tags
::
CreateService
.
new
(
commit
.
project
,
current_user
)
.
execute
(
tag_name
,
commit
.
sha
,
message
,
release_description
)
.
execute
(
tag_name
,
commit
.
sha
,
message
)
if
result
[
:status
]
==
:success
tag
=
result
[
:tag
]
...
...
app/services/create_release_service.rb
deleted
100644 → 0
View file @
f02a5523
# frozen_string_literal: true
class
CreateReleaseService
<
BaseService
# rubocop: disable CodeReuse/ActiveRecord
def
execute
(
tag_name
,
release_description
)
repository
=
project
.
repository
existing_tag
=
repository
.
find_tag
(
tag_name
)
# Only create a release if the tag exists
if
existing_tag
release
=
project
.
releases
.
find_by
(
tag:
tag_name
)
if
release
error
(
'Release already exists'
,
409
)
else
release
=
project
.
releases
.
create!
(
tag:
tag_name
,
name:
tag_name
,
sha:
existing_tag
.
dereferenced_target
.
sha
,
author:
current_user
,
description:
release_description
)
success
(
release
)
end
else
error
(
'Tag does not exist'
,
404
)
end
end
# rubocop: enable CodeReuse/ActiveRecord
def
success
(
release
)
super
().
merge
(
release:
release
)
end
end
app/services/releases/concerns.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
module
Releases
module
Concerns
extend
ActiveSupport
::
Concern
include
Gitlab
::
Utils
::
StrongMemoize
included
do
def
tag_name
params
[
:tag
]
end
def
ref
params
[
:ref
]
end
def
name
params
[
:name
]
end
def
description
params
[
:description
]
end
def
release
strong_memoize
(
:release
)
do
project
.
releases
.
find_by_tag
(
tag_name
)
end
end
def
existing_tag
strong_memoize
(
:existing_tag
)
do
repository
.
find_tag
(
tag_name
)
end
end
def
tag_exist?
existing_tag
.
present?
end
def
repository
strong_memoize
(
:repository
)
do
project
.
repository
end
end
end
end
end
app/services/releases/create_service.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
module
Releases
class
CreateService
<
BaseService
include
Releases
::
Concerns
def
execute
return
error
(
'Access Denied'
,
403
)
unless
allowed?
return
error
(
'Release already exists'
,
409
)
if
release
tag
=
ensure_tag
return
tag
unless
tag
.
is_a?
(
Gitlab
::
Git
::
Tag
)
create_release
(
tag
)
end
private
def
ensure_tag
existing_tag
||
create_tag
end
def
create_tag
return
error
(
'Ref is not specified'
,
422
)
unless
ref
result
=
Tags
::
CreateService
.
new
(
project
,
current_user
)
.
execute
(
tag_name
,
ref
,
nil
)
return
result
unless
result
[
:status
]
==
:success
result
[
:tag
]
end
def
allowed?
Ability
.
allowed?
(
current_user
,
:create_release
,
project
)
end
def
create_release
(
tag
)
release
=
project
.
releases
.
create!
(
name:
name
,
description:
description
,
author:
current_user
,
tag:
tag
.
name
,
sha:
tag
.
dereferenced_target
.
sha
)
success
(
tag:
tag
,
release:
release
)
rescue
ActiveRecord
::
RecordInvalid
=>
e
error
(
e
.
message
,
400
)
end
end
end
app/services/releases/destroy_service.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
module
Releases
class
DestroyService
<
BaseService
include
Releases
::
Concerns
def
execute
return
error
(
'Tag does not exist'
,
404
)
unless
existing_tag
return
error
(
'Release does not exist'
,
404
)
unless
release
return
error
(
'Access Denied'
,
403
)
unless
allowed?
if
release
.
destroy
success
(
tag:
existing_tag
,
release:
release
)
else
error
(
release
.
errors
.
messages
||
'400 Bad request'
,
400
)
end
end
private
def
allowed?
Ability
.
allowed?
(
current_user
,
:destroy_release
,
release
)
end
end
end
app/services/releases/update_service.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
module
Releases
class
UpdateService
<
BaseService
include
Releases
::
Concerns
def
execute
return
error
(
'Tag does not exist'
,
404
)
unless
existing_tag
return
error
(
'Release does not exist'
,
404
)
unless
release
return
error
(
'Access Denied'
,
403
)
unless
allowed?
return
error
(
'params is empty'
,
400
)
if
empty_params?
if
release
.
update
(
params
)
success
(
tag:
existing_tag
,
release:
release
)
else
error
(
release
.
errors
.
messages
||
'400 Bad request'
,
400
)
end
end
private
def
allowed?
Ability
.
allowed?
(
current_user
,
:update_release
,
release
)
end
# rubocop: disable CodeReuse/ActiveRecord
def
empty_params?
params
.
except
(
:tag
).
empty?
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
app/services/tags/create_service.rb
View file @
de1b5595
...
...
@@ -2,7 +2,7 @@
module
Tags
class
CreateService
<
BaseService
def
execute
(
tag_name
,
target
,
message
,
release_description
=
nil
)
def
execute
(
tag_name
,
target
,
message
)
valid_tag
=
Gitlab
::
GitRefValidator
.
validate
(
tag_name
)
return
error
(
'Tag name invalid'
)
unless
valid_tag
...
...
@@ -20,10 +20,7 @@ module Tags
end
if
new_tag
if
release_description
.
present?
CreateReleaseService
.
new
(
@project
,
@current_user
)
.
execute
(
tag_name
,
release_description
)
end
repository
.
expire_tags_cache
success
.
merge
(
tag:
new_tag
)
else
...
...
app/services/tags/destroy_service.rb
View file @
de1b5595
...
...
@@ -2,7 +2,6 @@
module
Tags
class
DestroyService
<
BaseService
# rubocop: disable CodeReuse/ActiveRecord
def
execute
(
tag_name
)
repository
=
project
.
repository
tag
=
repository
.
find_tag
(
tag_name
)
...
...
@@ -12,8 +11,12 @@ module Tags
end
if
repository
.
rm_tag
(
current_user
,
tag_name
)
release
=
project
.
releases
.
find_by
(
tag:
tag_name
)
release
&
.
destroy
##
# When a tag in a repository is destroyed,
# release assets will be destroyed too.
Releases
::
DestroyService
.
new
(
project
,
current_user
,
tag:
tag_name
)
.
execute
push_data
=
build_push_data
(
tag
)
EventCreateService
.
new
.
push
(
project
,
current_user
,
push_data
)
...
...
@@ -27,7 +30,6 @@ module Tags
rescue
Gitlab
::
Git
::
PreReceiveError
=>
ex
error
(
ex
.
message
)
end
# rubocop: enable CodeReuse/ActiveRecord
def
error
(
message
,
return_code
=
400
)
super
(
message
).
merge
(
return_code:
return_code
)
...
...
app/services/update_release_service.rb
deleted
100644 → 0
View file @
f02a5523
# frozen_string_literal: true
class
UpdateReleaseService
<
BaseService
# rubocop: disable CodeReuse/ActiveRecord
def
execute
(
tag_name
,
release_description
)
repository
=
project
.
repository
existing_tag
=
repository
.
find_tag
(
tag_name
)
if
existing_tag
release
=
project
.
releases
.
find_by
(
tag:
tag_name
)
if
release
release
.
update
(
description:
release_description
)
success
(
release
)
else
error
(
'Release does not exist'
,
404
)
end
else
error
(
'Tag does not exist'
,
404
)
end
end
# rubocop: enable CodeReuse/ActiveRecord
def
success
(
release
)
super
().
merge
(
release:
release
)
end
end
app/views/layouts/nav/sidebar/_project.html.haml
View file @
de1b5595
...
...
@@ -29,7 +29,7 @@
=
link_to
activity_project_path
(
@project
),
title:
_
(
'Activity'
),
class:
'shortcuts-project-activity'
do
%span
=
_
(
'Activity'
)
-
if
project_nav_tab?
(
:releases
)
&&
Feature
.
enabled?
(
:releases_page
)
-
if
project_nav_tab?
(
:releases
)
&&
Feature
.
enabled?
(
:releases_page
,
@project
)
=
nav_link
(
controller: :releases
)
do
=
link_to
project_releases_path
(
@project
),
title:
_
(
'Releases'
),
class:
'shortcuts-project-releases'
do
%span
=
_
(
'Releases'
)
...
...
changelogs/unreleased/ac-releases-api.yml
0 → 100644
View file @
de1b5595
---
title
:
Releases API
merge_request
:
23795
author
:
type
:
added
lib/api/api.rb
View file @
de1b5595
...
...
@@ -149,6 +149,7 @@ module API
mount
::
API
::
ProjectTemplates
mount
::
API
::
ProtectedBranches
mount
::
API
::
ProtectedTags
mount
::
API
::
Releases
mount
::
API
::
Repositories
mount
::
API
::
Runner
mount
::
API
::
Runners
...
...
lib/api/entities.rb
View file @
de1b5595
...
...
@@ -1115,11 +1115,20 @@ module API
expose
:password_authentication_enabled_for_web
,
as: :signin_enabled
end
class
Release
<
Grape
::
Entity
# deprecated old Release representation
class
TagRelease
<
Grape
::
Entity
expose
:tag
,
as: :tag_name
expose
:description
end
class
Release
<
TagRelease
expose
:name
expose
:description_html
expose
:created_at
expose
:author
,
using:
Entities
::
UserBasic
,
if:
->
(
release
,
_
)
{
release
.
author
.
present?
}
expose
:commit
,
using:
Entities
::
Commit
end
class
Tag
<
Grape
::
Entity
expose
:name
,
:message
,
:target
...
...
@@ -1128,7 +1137,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
expose
:release
,
using:
Entities
::
Release
do
|
repo_tag
,
options
|
expose
:release
,
using:
Entities
::
Tag
Release
do
|
repo_tag
,
options
|
options
[
:project
].
releases
.
find_by
(
tag:
repo_tag
.
name
)
end
# rubocop: enable CodeReuse/ActiveRecord
...
...
lib/api/releases.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
module
API
class
Releases
<
Grape
::
API
include
PaginationParams
RELEASE_ENDPOINT_REQUIREMETS
=
API
::
NAMESPACE_OR_PROJECT_REQUIREMENTS
.
merge
(
tag_name:
API
::
NO_SLASH_URL_PART_REGEX
)
before
{
error!
(
'404 Not Found'
,
404
)
unless
Feature
.
enabled?
(
:releases_page
,
user_project
)
}
before
{
authorize_read_releases!
}
params
do
requires
:id
,
type:
String
,
desc:
'The ID of a project'
end
resource
:projects
,
requirements:
API
::
NAMESPACE_OR_PROJECT_REQUIREMENTS
do
desc
'Get a project releases'
do
detail
'This feature was introduced in GitLab 11.7.'
success
Entities
::
Release
end
params
do
use
:pagination
end
get
':id/releases'
do
releases
=
::
ReleasesFinder
.
new
(
user_project
,
current_user
).
execute
present
paginate
(
releases
),
with:
Entities
::
Release
end
desc
'Get a single project release'
do
detail
'This feature was introduced in GitLab 11.7.'
success
Entities
::
Release
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
,
as: :tag
end
get
':id/releases/:tag_name'
,
requirements:
RELEASE_ENDPOINT_REQUIREMETS
do
authorize_read_release!
present
release
,
with:
Entities
::
Release
end
desc
'Create a new release'
do
detail
'This feature was introduced in GitLab 11.7.'
success
Entities
::
Release
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
,
as: :tag
requires
:name
,
type:
String
,
desc:
'The name of the release'
requires
:description
,
type:
String
,
desc:
'The release notes'
optional
:ref
,
type:
String
,
desc:
'The commit sha or branch name'
end
post
':id/releases'
do
authorize_create_release!
result
=
::
Releases
::
CreateService
.
new
(
user_project
,
current_user
,
declared_params
(
include_missing:
false
))
.
execute
if
result
[
:status
]
==
:success
present
result
[
:release
],
with:
Entities
::
Release
else
render_api_error!
(
result
[
:message
],
result
[
:http_status
])
end
end
desc
'Update a release'
do
detail
'This feature was introduced in GitLab 11.7.'
success
Entities
::
Release
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
,
as: :tag
optional
:name
,
type:
String
,
desc:
'The name of the release'
optional
:description
,
type:
String
,
desc:
'Release notes with markdown support'
end
put
':id/releases/:tag_name'
,
requirements:
RELEASE_ENDPOINT_REQUIREMETS
do
authorize_update_release!
result
=
::
Releases
::
UpdateService
.
new
(
user_project
,
current_user
,
declared_params
(
include_missing:
false
))
.
execute
if
result
[
:status
]
==
:success
present
result
[
:release
],
with:
Entities
::
Release
else
render_api_error!
(
result
[
:message
],
result
[
:http_status
])
end
end
desc
'Delete a release'
do
detail
'This feature was introduced in GitLab 11.7.'
success
Entities
::
Release
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
,
as: :tag
end
delete
':id/releases/:tag_name'
,
requirements:
RELEASE_ENDPOINT_REQUIREMETS
do
authorize_destroy_release!
result
=
::
Releases
::
DestroyService
.
new
(
user_project
,
current_user
,
declared_params
(
include_missing:
false
))
.
execute
if
result
[
:status
]
==
:success
present
result
[
:release
],
with:
Entities
::
Release
else
render_api_error!
(
result
[
:message
],
result
[
:http_status
])
end
end
end
helpers
do
def
authorize_create_release!
authorize!
:create_release
,
user_project
end
def
authorize_read_releases!
authorize!
:read_release
,
user_project
end
def
authorize_read_release!
authorize!
:read_release
,
release
end
def
authorize_update_release!
authorize!
:update_release
,
release
end
def
authorize_destroy_release!
authorize!
:destroy_release
,
release
end
def
release
@release
||=
user_project
.
releases
.
find_by_tag
(
params
[
:tag
])
end
end
end
end
lib/api/tags.rb
View file @
de1b5595
...
...
@@ -42,21 +42,35 @@ module API
end
desc
'Create a new repository tag'
do
detail
'This optional release_description parameter was deprecated in GitLab 11.7.'
success
Entities
::
Tag
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
requires
:ref
,
type:
String
,
desc:
'The commit sha or branch name'
optional
:message
,
type:
String
,
desc:
'Specifying a message creates an annotated tag'
optional
:release_description
,
type:
String
,
desc:
'Specifying release notes stored in the GitLab database'
optional
:release_description
,
type:
String
,
desc:
'Specifying release notes stored in the GitLab database
(deprecated in GitLab 11.7)
'
end
post
':id/repository/tags'
do
authorize_push_project
result
=
::
Tags
::
CreateService
.
new
(
user_project
,
current_user
)
.
execute
(
params
[
:tag_name
],
params
[
:ref
],
params
[
:message
]
,
params
[
:release_description
]
)
.
execute
(
params
[
:tag_name
],
params
[
:ref
],
params
[
:message
])
if
result
[
:status
]
==
:success
# Release creation with Tags API was deprecated in GitLab 11.7
if
params
[
:release_description
].
present?
release_create_params
=
{
tag:
params
[
:tag_name
],
name:
params
[
:tag_name
],
# Name can be specified in new API
description:
params
[
:release_description
]
}
::
Releases
::
CreateService
.
new
(
user_project
,
current_user
,
release_create_params
)
.
execute
end
present
result
[
:tag
],
with:
Entities
::
Tag
,
project:
user_project
...
...
@@ -88,44 +102,72 @@ module API
end
desc
'Add a release note to a tag'
do
success
Entities
::
Release
detail
'This feature was deprecated in GitLab 11.7.'
success
Entities
::
TagRelease
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
,
as: :tag
requires
:description
,
type:
String
,
desc:
'Release notes with markdown support'
end
post
':id/repository/tags/:tag_name/release'
,
requirements:
TAG_ENDPOINT_REQUIREMENTS
do
authorize_push_project
authorize_create_release!
##
# Legacy API does not support tag auto creation.
not_found!
(
'Tag'
)
unless
user_project
.
repository
.
find_tag
(
params
[
:tag
])
result
=
CreateReleaseService
.
new
(
user_project
,
current_user
)
.
execute
(
params
[
:tag_name
],
params
[
:description
])
release_create_params
=
{
tag:
params
[
:tag
],
name:
params
[
:tag
],
# Name can be specified in new API
description:
params
[
:description
]
}
result
=
::
Releases
::
CreateService
.
new
(
user_project
,
current_user
,
release_create_params
)
.
execute
if
result
[
:status
]
==
:success
present
result
[
:release
],
with:
Entities
::
Release
present
result
[
:release
],
with:
Entities
::
Tag
Release
else
render_api_error!
(
result
[
:message
],
result
[
:http_status
])
end
end
desc
"Update a tag's release note"
do
success
Entities
::
Release
detail
'This feature was deprecated in GitLab 11.7.'
success
Entities
::
TagRelease
end
params
do
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
requires
:tag_name
,
type:
String
,
desc:
'The name of the tag'
,
as: :tag
requires
:description
,
type:
String
,
desc:
'Release notes with markdown support'
end
put
':id/repository/tags/:tag_name/release'
,
requirements:
TAG_ENDPOINT_REQUIREMENTS
do
authorize_
push_project
authorize_
update_release!
result
=
UpdateReleaseService
.
new
(
user_project
,
current_user
)
.
execute
(
params
[
:tag_name
],
params
[
:description
])
result
=
::
Releases
::
UpdateService
.
new
(
user_project
,
current_user
,
declared_params
(
include_missing:
false
))
.
execute
if
result
[
:status
]
==
:success
present
result
[
:release
],
with:
Entities
::
Release
present
result
[
:release
],
with:
Entities
::
Tag
Release
else
render_api_error!
(
result
[
:message
],
result
[
:http_status
])
end
end
end
helpers
do
def
authorize_create_release!
authorize!
:create_release
,
user_project
end
def
authorize_update_release!
authorize!
:update_release
,
release
end
def
release
@release
||=
user_project
.
releases
.
find_by_tag
(
params
[
:tag
])
end
end
end
end
spec/factories/releases.rb
View file @
de1b5595
FactoryBot
.
define
do
factory
:release
do
tag
"v1.1.0"
sha
'b83d6e391c22777fca1ed3012fce84f633d7fed0'
name
{
tag
}
description
"Awesome release"
project
author
trait
:legacy
do
sha
nil
author
nil
end
end
end
spec/finders/releases_finder_spec.rb
0 → 100644
View file @
de1b5595
# frozen_string_literal: true
require
'spec_helper'
describe
ReleasesFinder
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:repository
)
{
project
.
repository
}
let
(
:v1_0_0
)
{
create
(
:release
,
project:
project
,
tag:
'v1.0.0'
)
}
let
(
:v1_1_0
)
{
create
(
:release
,
project:
project
,
tag:
'v1.1.0'
)
}
subject
{
described_class
.
new
(
project
,
user
)}
before
do
v1_0_0
.
update_attribute
(
:created_at
,
2
.
days
.
ago
)
v1_1_0
.
update_attribute
(
:created_at
,
1
.
day
.
ago
)
end
describe
'#execute'
do
context
'when the user is not part of the project'
do
it
'returns no releases'
do
releases
=
subject
.
execute
expect
(
releases
).
to
be_empty
end
end
context
'when the user is a project developer'
do
before
do
project
.
add_developer
(
user
)
end
it
'sorts by creation date'
do
releases
=
subject
.
execute
expect
(
releases
).
to
be_present
expect
(
releases
.
size
).
to
eq
(
2
)
expect
(
releases
).
to
eq
([
v1_1_0
,
v1_0_0
])
end
end
end
end
spec/fixtures/api/schemas/release.json
0 → 100644
View file @
de1b5595
{
"type"
:
"object"
,
"required"
:
[
"name"
,
"tag_name"
],
"properties"
:
{
"name"
:
{
"type"
:
"string"
},
"tag_name"
:
{
"type"
:
"string"
},
"description"
:
{
"type"
:
"string"
},
"description_html"
:
{
"type"
:
"string"
},
"created_at"
:
{
"type"
:
"date"
},
"commit"
:
{
"oneOf"
:
[{
"type"
:
"null"
},
{
"$ref"
:
"public_api/v4/commit/basic.json"
}]
},
"author"
:
{
"oneOf"
:
[{
"type"
:
"null"
},
{
"$ref"
:
"public_api/v4/user/basic.json"
}]
}
},
"additionalProperties"
:
false
}
spec/fixtures/api/schemas/releases.json
0 → 100644
View file @
de1b5595
{
"type"
:
"array"
,
"items"
:
{
"$ref"
:
"release.json"
}
}
spec/lib/gitlab/legacy_github_import/importer_spec.rb
View file @
de1b5595
...
...
@@ -138,7 +138,7 @@ describe Gitlab::LegacyGithubImport::Importer do
let
(
:release2
)
do
double
(
tag_name:
'v
2.0
.0'
,
tag_name:
'v
1.1
.0'
,
name:
'Second release'
,
body:
nil
,
draft:
false
,
...
...
spec/models/release_spec.rb
View file @
de1b5595
require
'rails_helper'
RSpec
.
describe
Release
do
let
(
:release
)
{
create
(
:release
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
:repository
)
}
let
(
:release
)
{
create
(
:release
,
project:
project
,
author:
user
)
}
it
{
expect
(
release
).
to
be_valid
}
...
...
spec/policies/project_policy_spec.rb
View file @
de1b5595
...
...
@@ -15,7 +15,7 @@ describe ProjectPolicy do
read_project_for_iids read_issue_iid read_merge_request_iid read_label
read_milestone read_project_snippet read_project_member read_note
create_project create_issue create_note upload_file create_merge_request_in
award_emoji
award_emoji
read_release
]
end
...
...
@@ -38,7 +38,7 @@ describe ProjectPolicy do
update_commit_status create_build update_build create_pipeline
update_pipeline create_merge_request_from create_wiki push_code
resolve_note create_container_image update_container_image
create_environment create_deployment
create_environment create_deployment
create_release update_release
]
end
...
...
@@ -48,7 +48,7 @@ describe ProjectPolicy do
update_deployment admin_project_snippet
admin_project_member admin_note admin_wiki admin_project
admin_commit_status admin_build admin_container_image
admin_pipeline admin_environment admin_deployment add_cluster
admin_pipeline admin_environment admin_deployment
destroy_release
add_cluster
]
end
...
...
@@ -56,7 +56,7 @@ describe ProjectPolicy do
%i[
download_code fork_project read_commit_status read_pipeline
read_container_image build_download_code build_read_container_image
download_wiki_code
download_wiki_code
read_release
]
end
...
...
@@ -183,7 +183,8 @@ describe ProjectPolicy do
:create_pipeline_schedule
,
:read_pipeline_schedule
,
:update_pipeline_schedule
,
:admin_pipeline_schedule
,
:destroy_pipeline_schedule
,
:create_environment
,
:read_environment
,
:update_environment
,
:admin_environment
,
:destroy_environment
,
:create_cluster
,
:read_cluster
,
:update_cluster
,
:admin_cluster
,
:create_deployment
,
:read_deployment
,
:update_deployment
,
:admin_deployment
,
:destroy_deployment
:create_deployment
,
:read_deployment
,
:update_deployment
,
:admin_deployment
,
:destroy_deployment
,
:destroy_release
]
expect_disallowed
(
*
repository_permissions
)
...
...
spec/requests/api/releases_spec.rb
0 → 100644
View file @
de1b5595
This diff is collapsed.
Click to expand it.
spec/requests/api/tags_spec.rb
View file @
de1b5595
...
...
@@ -107,9 +107,12 @@ describe API::Tags do
context
'with releases'
do
let
(
:description
)
{
'Awesome release!'
}
before
do
release
=
project
.
releases
.
find_or_initialize_by
(
tag:
tag_name
)
release
.
update
(
description:
description
)
let!
(
:release
)
do
create
(
:release
,
:legacy
,
project:
project
,
tag:
tag_name
,
description:
description
)
end
it
'returns an array of project tags with release info'
do
...
...
@@ -373,7 +376,7 @@ describe API::Tags do
it_behaves_like
'404 response'
do
let
(
:request
)
{
post
api
(
route
,
current_user
),
params:
{
description:
description
}
}
let
(
:message
)
{
'
Tag does not exist
'
}
let
(
:message
)
{
'
404 Tag Not Found
'
}
end
end
...
...
@@ -398,10 +401,7 @@ describe API::Tags do
end
context
'on tag with existing release'
do
before
do
release
=
project
.
releases
.
find_or_initialize_by
(
tag:
tag_name
)
release
.
update
(
description:
description
)
end
let!
(
:release
)
{
create
(
:release
,
:legacy
,
project:
project
,
tag:
tag_name
,
description:
description
)
}
it
'returns 409 if there is already a release'
do
post
api
(
route
,
user
),
params:
{
description:
description
}
...
...
@@ -420,9 +420,12 @@ describe API::Tags do
shared_examples_for
'repository update release'
do
context
'on tag with existing release'
do
before
do
release
=
project
.
releases
.
find_or_initialize_by
(
tag:
tag_name
)
release
.
update
(
description:
description
)
let!
(
:release
)
do
create
(
:release
,
:legacy
,
project:
project
,
tag:
tag_name
,
description:
description
)
end
it
'updates the release description'
do
...
...
@@ -437,9 +440,9 @@ describe API::Tags do
context
'when tag does not exist'
do
let
(
:tag_name
)
{
'unknown'
}
it_behaves_like
'40
4
response'
do
it_behaves_like
'40
3
response'
do
let
(
:request
)
{
put
api
(
route
,
current_user
),
params:
{
description:
new_description
}
}
let
(
:message
)
{
'
Tag does not exist
'
}
let
(
:message
)
{
'
403 Forbidden
'
}
end
end
...
...
@@ -464,9 +467,9 @@ describe API::Tags do
end
context
'when release does not exist'
do
it_behaves_like
'40
4
response'
do
it_behaves_like
'40
3
response'
do
let
(
:request
)
{
put
api
(
route
,
current_user
),
params:
{
description:
new_description
}
}
let
(
:message
)
{
'
Release does not exist
'
}
let
(
:message
)
{
'
403 Forbidden
'
}
end
end
end
...
...
spec/services/create_release_service_spec.rb
deleted
100644 → 0
View file @
f02a5523
require
'spec_helper'
describe
CreateReleaseService
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:tag_name
)
{
project
.
repository
.
tag_names
.
first
}
let
(
:description
)
{
'Awesome release!'
}
let
(
:service
)
{
described_class
.
new
(
project
,
user
)
}
let
(
:tag
)
{
project
.
repository
.
find_tag
(
tag_name
)
}
let
(
:sha
)
{
tag
.
dereferenced_target
.
sha
}
it
'creates a new release'
do
result
=
service
.
execute
(
tag_name
,
description
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
release
=
project
.
releases
.
find_by
(
tag:
tag_name
)
expect
(
release
).
not_to
be_nil
expect
(
release
.
description
).
to
eq
(
description
)
expect
(
release
.
name
).
to
eq
(
tag_name
)
expect
(
release
.
sha
).
to
eq
(
sha
)
expect
(
release
.
author
).
to
eq
(
user
)
end
it
'raises an error if the tag does not exist'
do
result
=
service
.
execute
(
"foobar"
,
description
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
context
'there already exists a release on a tag'
do
before
do
service
.
execute
(
tag_name
,
description
)
end
it
'raises an error and does not update the release'
do
result
=
service
.
execute
(
tag_name
,
'The best release!'
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
project
.
releases
.
find_by
(
tag:
tag_name
).
description
).
to
eq
(
description
)
end
end
end
spec/services/releases/create_service_spec.rb
0 → 100644
View file @
de1b5595
require
'spec_helper'
describe
Releases
::
CreateService
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:tag_name
)
{
project
.
repository
.
tag_names
.
first
}
let
(
:tag_sha
)
{
project
.
repository
.
find_tag
(
tag_name
).
dereferenced_target
.
sha
}
let
(
:name
)
{
'Bionic Beaver'
}
let
(
:description
)
{
'Awesome release!'
}
let
(
:params
)
{
{
tag:
tag_name
,
name:
name
,
description:
description
,
ref:
ref
}
}
let
(
:ref
)
{
nil
}
let
(
:service
)
{
described_class
.
new
(
project
,
user
,
params
)
}
before
do
project
.
add_maintainer
(
user
)
end
describe
'#execute'
do
shared_examples
'a successful release creation'
do
it
'creates a new release'
do
result
=
service
.
execute
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:tag
]).
not_to
be_nil
expect
(
result
[
:release
]).
not_to
be_nil
expect
(
result
[
:release
].
description
).
to
eq
(
description
)
expect
(
result
[
:release
].
name
).
to
eq
(
name
)
expect
(
result
[
:release
].
author
).
to
eq
(
user
)
expect
(
result
[
:release
].
sha
).
to
eq
(
tag_sha
)
end
end
it_behaves_like
'a successful release creation'
context
'when the tag does not exist'
do
let
(
:tag_name
)
{
'non-exist-tag'
}
it
'raises an error'
do
result
=
service
.
execute
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
end
context
'when ref is provided'
do
let
(
:ref
)
{
'master'
}
let
(
:tag_name
)
{
'foobar'
}
it_behaves_like
'a successful release creation'
it
'creates a tag if the tag does not exist'
do
expect
(
project
.
repository
.
ref_exists?
(
"refs/tags/
#{
tag_name
}
"
)).
to
be_falsey
result
=
service
.
execute
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:tag
]).
not_to
be_nil
expect
(
result
[
:release
]).
not_to
be_nil
end
end
context
'there already exists a release on a tag'
do
let!
(
:release
)
do
create
(
:release
,
project:
project
,
tag:
tag_name
,
description:
description
)
end
it
'raises an error and does not update the release'
do
result
=
service
.
execute
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
project
.
releases
.
find_by
(
tag:
tag_name
).
description
).
to
eq
(
description
)
end
end
end
end
spec/services/releases/destroy_service_spec.rb
0 → 100644
View file @
de1b5595
require
'spec_helper'
describe
Releases
::
DestroyService
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:mainatiner
)
{
create
(
:user
)
}
let
(
:repoter
)
{
create
(
:user
)
}
let
(
:tag
)
{
'v1.1.0'
}
let!
(
:release
)
{
create
(
:release
,
project:
project
,
tag:
tag
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
user
,
params
)
}
let
(
:params
)
{
{
tag:
tag
}
}
let
(
:user
)
{
mainatiner
}
before
do
project
.
add_maintainer
(
mainatiner
)
project
.
add_reporter
(
repoter
)
end
describe
'#execute'
do
subject
{
service
.
execute
}
context
'when there is a release'
do
it
'removes the release'
do
expect
{
subject
}.
to
change
{
project
.
releases
.
count
}.
by
(
-
1
)
end
it
'returns the destroyed object'
do
is_expected
.
to
include
(
status: :success
,
release:
release
)
end
end
context
'when tag is not found'
do
let
(
:tag
)
{
'v1.1.1'
}
it
'returns an error'
do
is_expected
.
to
include
(
status: :error
,
message:
'Tag does not exist'
,
http_status:
404
)
end
end
context
'when release is not found'
do
let!
(
:release
)
{
}
it
'returns an error'
do
is_expected
.
to
include
(
status: :error
,
message:
'Release does not exist'
,
http_status:
404
)
end
end
context
'when user does not have permission'
do
let
(
:user
)
{
repoter
}
it
'returns an error'
do
is_expected
.
to
include
(
status: :error
,
message:
'Access Denied'
,
http_status:
403
)
end
end
end
end
spec/services/releases/update_service_spec.rb
0 → 100644
View file @
de1b5595
require
'spec_helper'
describe
Releases
::
UpdateService
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:new_name
)
{
'A new name'
}
let
(
:new_description
)
{
'The best release!'
}
let
(
:params
)
{
{
name:
new_name
,
description:
new_description
,
tag:
tag_name
}
}
let
(
:service
)
{
described_class
.
new
(
project
,
user
,
params
)
}
let!
(
:release
)
{
create
(
:release
,
project:
project
,
author:
user
,
tag:
tag_name
)
}
let
(
:tag_name
)
{
'v1.1.0'
}
before
do
project
.
add_developer
(
user
)
end
describe
'#execute'
do
shared_examples
'a failed update'
do
it
'raises an error'
do
result
=
service
.
execute
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
end
it
'successfully updates an existing release'
do
result
=
service
.
execute
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:release
].
name
).
to
eq
(
new_name
)
expect
(
result
[
:release
].
description
).
to
eq
(
new_description
)
end
context
'when the tag does not exists'
do
let
(
:tag_name
)
{
'foobar'
}
it_behaves_like
'a failed update'
end
context
'when the release does not exist'
do
let!
(
:release
)
{
}
it_behaves_like
'a failed update'
end
context
'with an invalid update'
do
let
(
:new_description
)
{
''
}
it_behaves_like
'a failed update'
end
end
end
spec/services/update_release_service_spec.rb
deleted
100644 → 0
View file @
f02a5523
require
'spec_helper'
describe
UpdateReleaseService
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:tag_name
)
{
project
.
repository
.
tag_names
.
first
}
let
(
:description
)
{
'Awesome release!'
}
let
(
:new_description
)
{
'The best release!'
}
let
(
:service
)
{
described_class
.
new
(
project
,
user
)
}
context
'with an existing release'
do
let
(
:create_service
)
{
CreateReleaseService
.
new
(
project
,
user
)
}
before
do
create_service
.
execute
(
tag_name
,
description
)
end
it
'successfully updates an existing release'
do
result
=
service
.
execute
(
tag_name
,
new_description
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
releases
.
find_by
(
tag:
tag_name
).
description
).
to
eq
(
new_description
)
end
end
it
'raises an error if the tag does not exist'
do
result
=
service
.
execute
(
"foobar"
,
description
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
it
'raises an error if the release does not exist'
do
result
=
service
.
execute
(
tag_name
,
description
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment