diff options
author | Alessio Caiazza <acaiazza@gitlab.com> | 2018-12-13 12:08:53 +0100 |
---|---|---|
committer | Shinya Maeda <shinya@gitlab.com> | 2018-12-31 12:05:56 +0900 |
commit | 1ea2d9faa518f6b769b05a71a1f93b4ea0226bc1 (patch) | |
tree | 291cd8d7a6c6113e75219dc873e24fb414df119d /app | |
parent | c07bf1abf2a5c3751e575ee5926e9a052fa0b341 (diff) | |
download | gitlab-ce-1ea2d9faa518f6b769b05a71a1f93b4ea0226bc1.tar.gz |
Add releases API
This commit introduces Releases API under /api/v4/projects/:id/releases
* We are introducing release policies at project level.
* We are deprecating releases changes from tags, both api and web
interface.
* Tags::CreateService no longer create a release
This feature is controlled by :releases_page feature flag
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects/releases_controller.rb | 6 | ||||
-rw-r--r-- | app/controllers/projects/tags/releases_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/tags_controller.rb | 8 | ||||
-rw-r--r-- | app/finders/releases_finder.rb | 16 | ||||
-rw-r--r-- | app/models/release.rb | 8 | ||||
-rw-r--r-- | app/policies/project_policy.rb | 7 | ||||
-rw-r--r-- | app/services/commits/tag_service.rb | 3 | ||||
-rw-r--r-- | app/services/create_release_service.rb | 59 | ||||
-rw-r--r-- | app/services/tags/create_service.rb | 7 | ||||
-rw-r--r-- | app/services/update_release_service.rb | 22 | ||||
-rw-r--r-- | app/views/layouts/nav/sidebar/_project.html.haml | 2 |
11 files changed, 99 insertions, 41 deletions
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index 58d5ea4762f..62bdc84b41a 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -3,7 +3,7 @@ class Projects::ReleasesController < Projects::ApplicationController # Authorize before_action :require_non_empty_project - before_action :authorize_download_code! + before_action :authorize_read_release! 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 diff --git a/app/controllers/projects/tags/releases_controller.rb b/app/controllers/projects/tags/releases_controller.rb index 334e1847cc8..3725df010b0 100644 --- a/app/controllers/projects/tags/releases_controller.rb +++ b/app/controllers/projects/tags/releases_controller.rb @@ -4,7 +4,7 @@ class Projects::Tags::ReleasesController < Projects::ApplicationController # Authorize before_action :require_non_empty_project before_action :authorize_download_code! - before_action :authorize_push_code! + before_action :authorize_update_release! before_action :tag before_action :release diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index a50a1475eb2..35d798c0fda 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -43,9 +43,15 @@ 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? + CreateReleaseService.new(@project, current_user) + .execute(params[:tag_name], params[:release_description]) + end + @tag = result[:tag] redirect_to project_tag_path(@project, @tag.name) diff --git a/app/finders/releases_finder.rb b/app/finders/releases_finder.rb new file mode 100644 index 00000000000..c185f77afa2 --- /dev/null +++ b/app/finders/releases_finder.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ReleasesFinder + def initialize(project, current_user = nil) + @project = project + @current_user = current_user + end + + # rubocop: disable CodeReuse/ActiveRecord + def execute + return [] unless Ability.allowed?(@current_user, :read_release, @project) + + @project.releases.order('created_at DESC') + end + # rubocop: enable CodeReuse/ActiveRecord +end diff --git a/app/models/release.rb b/app/models/release.rb index 7a09ee459a6..a4272dd63aa 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -6,7 +6,15 @@ class Release < ActiveRecord::Base 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 + + delegate :repository, to: :project + + def commit + git_tag = repository.find_tag(tag) + repository.commit(git_tag.dereferenced_target) + end end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index bcbd9676f2e..88cab816fe4 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -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 :admin_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 diff --git a/app/services/commits/tag_service.rb b/app/services/commits/tag_service.rb index 7961ba4d3c4..bb8cfb63f98 100644 --- a/app/services/commits/tag_service.rb +++ b/app/services/commits/tag_service.rb @@ -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] diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb index ab2dc5337aa..223670a935d 100644 --- a/app/services/create_release_service.rb +++ b/app/services/create_release_service.rb @@ -1,35 +1,50 @@ # frozen_string_literal: true class CreateReleaseService < BaseService - # rubocop: disable CodeReuse/ActiveRecord - def execute(tag_name, release_description) + def execute(tag_name, release_description, name: nil, ref: nil) 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 + tag = repository.find_tag(tag_name) + + if tag.blank? && ref.present? + result = create_tag(tag_name, ref) + return result unless result[:status] == :success + + tag = result[:tag] + end + + if tag.present? + create_release(tag, name, release_description) else error('Tag does not exist', 404) end end - # rubocop: enable CodeReuse/ActiveRecord def success(release) super().merge(release: release) end + + private + + def create_release(tag, name, description) + release = project.releases.find_by(tag: tag.name) # rubocop: disable CodeReuse/ActiveRecord + + if release + error('Release already exists', 409) + else + release = project.releases.create!( + tag: tag.name, + name: name || tag.name, + sha: tag.dereferenced_target.sha, + author: current_user, + description: description + ) + + success(release) + end + end + + def create_tag(tag_name, ref) + Tags::CreateService.new(project, current_user) + .execute(tag_name, ref, nil) + end end diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index 6bb9bb3988e..4de6b2d2774 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -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 diff --git a/app/services/update_release_service.rb b/app/services/update_release_service.rb index e2228ca026c..b51e72c7bfc 100644 --- a/app/services/update_release_service.rb +++ b/app/services/update_release_service.rb @@ -1,18 +1,28 @@ # frozen_string_literal: true class UpdateReleaseService < BaseService + attr_accessor :tag_name + + def initialize(project, user, tag_name, params) + super(project, user, params) + + @tag_name = tag_name + end + # rubocop: disable CodeReuse/ActiveRecord - def execute(tag_name, release_description) + def execute repository = project.repository - existing_tag = repository.find_tag(tag_name) + existing_tag = repository.find_tag(@tag_name) if existing_tag - release = project.releases.find_by(tag: tag_name) + release = project.releases.find_by(tag: @tag_name) if release - release.update(description: release_description) - - success(release) + if release.update(params) + success(release) + else + error(release.errors.messages || '400 Bad request', 400) + end else error('Release does not exist', 404) end diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index 59557c70904..d8017742c90 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -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') |