summaryrefslogtreecommitdiff
path: root/lib/api/github/entities.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/api/github/entities.rb')
-rw-r--r--lib/api/github/entities.rb217
1 files changed, 217 insertions, 0 deletions
diff --git a/lib/api/github/entities.rb b/lib/api/github/entities.rb
new file mode 100644
index 00000000000..c28a0b8eb7e
--- /dev/null
+++ b/lib/api/github/entities.rb
@@ -0,0 +1,217 @@
+# frozen_string_literal: true
+
+# Simplified version of Github API entities.
+# It's mainly used to mimic Github API and integrate with Jira Development Panel.
+#
+module API
+ module Github
+ module Entities
+ class Repository < Grape::Entity
+ expose :id
+ expose :owner do |project, options|
+ root_namespace = options[:root_namespace] || project.root_namespace
+
+ { login: root_namespace.path }
+ end
+ expose :name do |project, options|
+ ::Gitlab::Jira::Dvcs.encode_project_name(project)
+ end
+ end
+
+ class BranchCommit < Grape::Entity
+ expose :id, as: :sha
+ expose :type do |_|
+ 'commit'
+ end
+ end
+
+ class RepoCommit < Grape::Entity
+ expose :id, as: :sha
+ expose :author do |commit|
+ {
+ login: commit.author&.username,
+ email: commit.author_email
+ }
+ end
+ expose :committer do |commit|
+ {
+ login: commit.author&.username,
+ email: commit.committer_email
+ }
+ end
+ expose :commit do |commit|
+ {
+ author: {
+ name: commit.author_name,
+ email: commit.author_email,
+ date: commit.authored_date.iso8601,
+ type: 'User'
+ },
+ committer: {
+ name: commit.committer_name,
+ email: commit.committer_email,
+ date: commit.committed_date.iso8601,
+ type: 'User'
+ },
+ message: commit.safe_message
+ }
+ end
+ expose :parents do |commit|
+ commit.parent_ids.map { |id| { sha: id } }
+ end
+ expose :files do |commit|
+ commit.diffs.diff_files.flat_map do |diff|
+ additions = diff.added_lines
+ deletions = diff.removed_lines
+
+ if diff.new_file?
+ {
+ status: 'added',
+ filename: diff.new_path,
+ additions: additions,
+ changes: additions
+ }
+ elsif diff.deleted_file?
+ {
+ status: 'removed',
+ filename: diff.old_path,
+ deletions: deletions,
+ changes: deletions
+ }
+ elsif diff.renamed_file?
+ [
+ {
+ status: 'removed',
+ filename: diff.old_path,
+ deletions: deletions,
+ changes: deletions
+ },
+ {
+ status: 'added',
+ filename: diff.new_path,
+ additions: additions,
+ changes: additions
+ }
+ ]
+ else
+ {
+ status: 'modified',
+ filename: diff.new_path,
+ additions: additions,
+ deletions: deletions,
+ changes: (additions + deletions)
+ }
+ end
+ end
+ end
+ end
+
+ class Branch < Grape::Entity
+ expose :name
+
+ expose :commit, using: BranchCommit do |repo_branch, options|
+ options[:project].repository.commit(repo_branch.dereferenced_target)
+ end
+ end
+
+ class User < Grape::Entity
+ expose :id
+ expose :username, as: :login
+ expose :user_url, as: :url
+ expose :user_url, as: :html_url
+ expose :avatar_url
+
+ private
+
+ def user_url
+ Gitlab::Routing.url_helpers.user_url(object)
+ end
+ end
+
+ class NoteableComment < Grape::Entity
+ expose :id
+ expose :author, as: :user, using: User
+ expose :note, as: :body
+ expose :created_at
+ end
+
+ class PullRequest < Grape::Entity
+ expose :title
+ expose :assignee, using: User do |merge_request|
+ merge_request.assignee
+ end
+ expose :author, as: :user, using: User
+ expose :created_at
+ expose :description, as: :body
+ # Since Jira service requests `/repos/-/jira/pulls` (without project
+ # scope), we need to make it work with ID instead IID.
+ expose :id, as: :number
+ # GitHub doesn't have a "merged" or "closed" state. It's just "open" or
+ # "closed".
+ expose :state do |merge_request|
+ case merge_request.state
+ when 'opened', 'locked'
+ 'open'
+ when 'merged'
+ 'closed'
+ else
+ merge_request.state
+ end
+ end
+ expose :merged?, as: :merged
+ expose :merged_at do |merge_request|
+ merge_request.metrics&.merged_at
+ end
+ expose :closed_at do |merge_request|
+ merge_request.metrics&.latest_closed_at
+ end
+ expose :updated_at
+ expose :html_url do |merge_request|
+ Gitlab::UrlBuilder.build(merge_request)
+ end
+ expose :head do
+ expose :source_branch, as: :label
+ expose :source_branch, as: :ref
+ expose :source_project, as: :repo, using: Repository
+ end
+ expose :base do
+ expose :target_branch, as: :label
+ expose :target_branch, as: :ref
+ expose :target_project, as: :repo, using: Repository
+ end
+ end
+
+ class PullRequestPayload < Grape::Entity
+ expose :action do |merge_request|
+ case merge_request.state
+ when 'merged', 'closed'
+ 'closed'
+ else
+ 'opened'
+ end
+ end
+
+ expose :id
+ expose :pull_request, using: PullRequest do |merge_request|
+ merge_request
+ end
+ end
+
+ class PullRequestEvent < Grape::Entity
+ expose :id do |merge_request|
+ updated_at = merge_request.updated_at.to_i
+ "#{merge_request.id}-#{updated_at}"
+ end
+ expose :type do |_merge_request|
+ 'PullRequestEvent'
+ end
+ expose :updated_at, as: :created_at
+ expose :payload, using: PullRequestPayload do |merge_request|
+ # The merge request data is used by PullRequestPayload and PullRequest, so we just provide it
+ # here. Otherwise Grape::Entity would try to access a field "payload" on Merge Request.
+ merge_request
+ end
+ end
+ end
+ end
+end