diff options
Diffstat (limited to 'lib/api')
-rw-r--r-- | lib/api/api.rb | 1 | ||||
-rw-r--r-- | lib/api/commit_statuses.rb | 2 | ||||
-rw-r--r-- | lib/api/entities.rb | 25 | ||||
-rw-r--r-- | lib/api/groups.rb | 12 | ||||
-rw-r--r-- | lib/api/helpers.rb | 7 | ||||
-rw-r--r-- | lib/api/merge_requests.rb | 80 | ||||
-rw-r--r-- | lib/api/project_hooks.rb | 2 | ||||
-rw-r--r-- | lib/api/projects.rb | 25 | ||||
-rw-r--r-- | lib/api/tags.rb | 37 | ||||
-rw-r--r-- | lib/api/triggers.rb | 48 |
10 files changed, 192 insertions, 47 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb index fe1bf8a4816..7834262d612 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -53,5 +53,6 @@ module API mount Settings mount Keys mount Tags + mount Triggers end end diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 2c0596c9dfb..1162271f5fc 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -53,7 +53,7 @@ module API name = params[:name] || params[:context] status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref]) - status ||= GenericCommitStatus.new(commit: ci_commit, user: current_user) + status ||= GenericCommitStatus.new(project: @project, commit: ci_commit, user: current_user) status.update(attrs) case params[:state].to_s diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3da6bc415d6..f8511ac5f5c 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -45,7 +45,8 @@ module API class ProjectHook < Hook expose :project_id, :push_events - expose :issues_events, :merge_requests_events, :tag_push_events, :note_events, :enable_ssl_verification + expose :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events + expose :enable_ssl_verification end class ForkedFromProject < Grape::Entity @@ -63,11 +64,13 @@ module API expose :name, :name_with_namespace expose :path, :path_with_namespace expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :created_at, :last_activity_at + expose :shared_runners_enabled expose :creator_id expose :namespace - expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } + expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ |project, options| project.forked? } expose :avatar_url expose :star_count, :forks_count + expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? } end class ProjectMember < UserBasic @@ -163,12 +166,15 @@ module API class MergeRequest < ProjectEntity expose :target_branch, :source_branch + # deprecated, always returns 0 + expose :upvotes, :downvotes expose :author, :assignee, using: Entities::UserBasic expose :source_project_id, :target_project_id expose :label_names, as: :labels expose :description expose :work_in_progress?, as: :work_in_progress expose :milestone, using: Entities::Milestone + expose :merge_when_build_succeeds end class MergeRequestChanges < MergeRequest @@ -192,6 +198,10 @@ module API expose :author, using: Entities::UserBasic expose :created_at expose :system?, as: :system + expose :noteable_id, :noteable_type + # upvote? and downvote? are deprecated, always return false + expose :upvote?, as: :upvote + expose :downvote?, as: :downvote end class MRNote < Grape::Entity @@ -219,6 +229,8 @@ module API expose :target_id, :target_type, :author_id expose :data, :target_title expose :created_at + expose :note, using: Entities::Note, if: ->(event, options) { event.note? } + expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author } expose :author_username do |event, options| if event.author @@ -243,7 +255,7 @@ module API class ProjectService < Grape::Entity expose :id, :title, :created_at, :updated_at, :active - expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events + expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. @@ -322,7 +334,8 @@ module API end class Release < Grape::Entity - expose :tag, :description + expose :tag, as: :tag_name + expose :description end class RepoTag < Grape::Entity @@ -349,5 +362,9 @@ module API end end end + + class TriggerRequest < Grape::Entity + expose :id, :variables + end end end diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 024aeec2e14..1a14d870a4a 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -65,6 +65,18 @@ module API DestroyGroupService.new(group, current_user).execute end + # Get a list of projects in this group + # + # Example Request: + # GET /groups/:id/projects + get ":id/projects" do + group = find_group(params[:id]) + projects = group.projects + projects = filter_projects(projects) + projects = paginate projects + present projects, with: Entities::Project + end + # Transfer a project to the Group namespace # # Parameters: diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 92540ccf2b1..a4df810e755 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -266,12 +266,7 @@ module API projects = projects.search(params[:search]) end - if params[:ci_enabled_first].present? - projects.includes(:gitlab_ci_service). - reorder("services.active DESC, projects.#{project_order_by} #{project_sort}") - else - projects.reorder(project_order_by => project_sort) - end + projects.reorder(project_order_by => project_sort) end def project_order_by diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 6eb84baf9cb..3c1c6bda260 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -76,6 +76,22 @@ module API present merge_request, with: Entities::MergeRequest end + # Show MR commits + # + # Parameters: + # id (required) - The ID of a project + # merge_request_id (required) - The ID of MR + # + # Example: + # GET /projects/:id/merge_request/:merge_request_id/commits + # + get ':id/merge_request/:merge_request_id/commits' do + merge_request = user_project.merge_requests. + find(params[:merge_request_id]) + authorize! :read_merge_request, merge_request + present merge_request.commits, with: Entities::RepoCommit + end + # Show MR changes # # Parameters: @@ -179,46 +195,54 @@ module API # Merge MR # # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - ID of MR - # merge_commit_message (optional) - Custom merge commit message + # id (required) - The ID of a project + # merge_request_id (required) - ID of MR + # merge_commit_message (optional) - Custom merge commit message + # should_remove_source_branch (optional) - When true, the source branch will be deleted if possible + # merge_when_build_succeeds (optional) - When true, this MR will be merged when the build succeeds # Example: # PUT /projects/:id/merge_request/:merge_request_id/merge # put ":id/merge_request/:merge_request_id/merge" do merge_request = user_project.merge_requests.find(params[:merge_request_id]) - allowed = ::Gitlab::GitAccess.new(current_user, user_project). - can_push_to_branch?(merge_request.target_branch) + # Merge request can not be merged + # because user dont have permissions to push into target branch + unauthorized! unless merge_request.can_be_merged_by?(current_user) + not_allowed! if !merge_request.open? || merge_request.work_in_progress? - if allowed - if merge_request.unchecked? - merge_request.check_if_can_be_merged - end + merge_request.check_if_can_be_merged if merge_request.unchecked? - if merge_request.open? && !merge_request.work_in_progress? - if merge_request.can_be_merged? - commit_message = params[:merge_commit_message] || merge_request.merge_commit_message - - ::MergeRequests::MergeService.new(merge_request.target_project, current_user). - execute(merge_request, commit_message) - - present merge_request, with: Entities::MergeRequest - else - render_api_error!('Branch cannot be merged', 405) - end - else - # Merge request can not be merged - # because it is already closed/merged or marked as WIP - not_allowed! - end + render_api_error!('Branch cannot be merged', 406) unless merge_request.can_be_merged? + + merge_params = { + commit_message: params[:merge_commit_message], + should_remove_source_branch: params[:should_remove_source_branch] + } + + if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.ci_commit && merge_request.ci_commit.active? + ::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params). + execute(merge_request) else - # Merge request can not be merged - # because user dont have permissions to push into target branch - unauthorized! + ::MergeRequests::MergeService.new(merge_request.target_project, current_user, merge_params). + execute(merge_request) end + + present merge_request, with: Entities::MergeRequest end + # Cancel Merge if Merge When build succeeds is enabled + # Parameters: + # id (required) - The ID of a project + # merge_request_id (required) - ID of MR + # + post ":id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds" do + merge_request = user_project.merge_requests.find(params[:merge_request_id]) + + unauthorized! unless merge_request.can_cancel_merge_when_build_succeeds?(current_user) + + ::MergeRequest::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user).cancel(merge_request) + end # Get a merge request's comments # diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index 882d1a083ad..cf9938d25a7 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -45,6 +45,7 @@ module API :merge_requests_events, :tag_push_events, :note_events, + :build_events, :enable_ssl_verification ] @hook = user_project.hooks.new(attrs) @@ -77,6 +78,7 @@ module API :merge_requests_events, :tag_push_events, :note_events, + :build_events, :enable_ssl_verification ] diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 2b4ada6e2eb..5e75cd35c56 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -7,8 +7,12 @@ module API helpers do def map_public_to_visibility_level(attrs) publik = attrs.delete(:public) - publik = parse_boolean(publik) - attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true + if publik.present? && !attrs[:visibility_level].present? + publik = parse_boolean(publik) + # Since setting the public attribute to private could mean either + # private or internal, use the more conservative option, private. + attrs[:visibility_level] = (publik == true) ? Gitlab::VisibilityLevel::PUBLIC : Gitlab::VisibilityLevel::PRIVATE + end attrs end end @@ -35,6 +39,17 @@ module API present @projects, with: Entities::Project end + # Gets starred project for the authenticated user + # + # Example Request: + # GET /projects/starred + get '/starred' do + @projects = current_user.starred_projects + @projects = filter_projects(@projects) + @projects = paginate @projects + present @projects, with: Entities::Project + end + # Get all projects for admin user # # Example Request: @@ -78,6 +93,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # shared_runners_enabled (optional) # namespace_id (optional) - defaults to user namespace # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - 0 by default @@ -94,6 +110,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :shared_runners_enabled, :namespace_id, :public, :visibility_level, @@ -122,6 +139,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) # import_url (optional) @@ -138,6 +156,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :shared_runners_enabled, :public, :visibility_level, :import_url] @@ -179,6 +198,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - visibility level of a project # Example Request @@ -193,6 +213,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :shared_runners_enabled, :public, :visibility_level] attrs = map_public_to_visibility_level(attrs) diff --git a/lib/api/tags.rb b/lib/api/tags.rb index 673342dd447..47621f443e6 100644 --- a/lib/api/tags.rb +++ b/lib/api/tags.rb @@ -44,17 +44,42 @@ module API # # Parameters: # id (required) - The ID of a project - # tag (required) - The name of the tag + # tag_name (required) - The name of the tag + # description (required) - Release notes with markdown support + # Example Request: + # POST /projects/:id/repository/tags/:tag_name/release + post ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do + authorize_push_project + required_attributes! [:description] + result = CreateReleaseService.new(user_project, current_user). + execute(params[:tag_name], params[:description]) + + if result[:status] == :success + present result[:release], with: Entities::Release + else + render_api_error!(result[:message], result[:http_status]) + end + end + + # Updates a release notes of a tag + # + # Parameters: + # id (required) - The ID of a project + # tag_name (required) - The name of the tag # description (required) - Release notes with markdown support # Example Request: - # PUT /projects/:id/repository/tags - put ':id/repository/:tag/release', requirements: { tag: /.*/ } do + # PUT /projects/:id/repository/tags/:tag_name/release + put ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do authorize_push_project required_attributes! [:description] - release = user_project.releases.find_or_initialize_by(tag: params[:tag]) - release.update_attributes(description: params[:description]) + result = UpdateReleaseService.new(user_project, current_user). + execute(params[:tag_name], params[:description]) - present release, with: Entities::Release + if result[:status] == :success + present result[:release], with: Entities::Release + else + render_api_error!(result[:message], result[:http_status]) + end end end end diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb new file mode 100644 index 00000000000..2781f1cf191 --- /dev/null +++ b/lib/api/triggers.rb @@ -0,0 +1,48 @@ +module API + # Triggers API + class Triggers < Grape::API + resource :projects do + # Trigger a GitLab project build + # + # Parameters: + # id (required) - The ID of a CI project + # ref (required) - The name of project's branch or tag + # token (required) - The uniq token of trigger + # variables (optional) - The list of variables to be injected into build + # Example Request: + # POST /projects/:id/trigger/builds + post ":id/trigger/builds" do + required_attributes! [:ref, :token] + + project = Project.find_with_namespace(params[:id]) || Project.find_by(id: params[:id]) + trigger = Ci::Trigger.find_by_token(params[:token].to_s) + not_found! unless project && trigger + unauthorized! unless trigger.project == project + + # validate variables + variables = params[:variables] + if variables + unless variables.is_a?(Hash) + render_api_error!('variables needs to be a hash', 400) + end + + unless variables.all? { |key, value| key.is_a?(String) && value.is_a?(String) } + render_api_error!('variables needs to be a map of key-valued strings', 400) + end + + # convert variables from Mash to Hash + variables = variables.to_h + end + + # create request and trigger builds + trigger_request = Ci::CreateTriggerRequestService.new.execute(project, trigger, params[:ref].to_s, variables) + if trigger_request + present trigger_request, with: Entities::TriggerRequest + else + errors = 'No builds created' + render_api_error!(errors, 400) + end + end + end + end +end |