* If there is no body of the linked issue or PR, don't render markdown Return a readable and actionable error to the user when they're linking a PR that doesn't have a body (and we can't render). This is not needed if there's a fallback path to render _something_ in the absence of a body (or if it's safe to just skip the `body` rendered inside the github issue liquid template partial). * When there is no issue body to render, just show PR title and link Set the body to an empty string and let github return an empty html body. It would be possible to substitute this with a conditional to only post if a body was present, or assign processed_html directly if not. * Don't use github api when we have an empty body Save a network trip and just replace the processed html body with an empty string when the issue body was nil.
82 lines
2.5 KiB
Ruby
82 lines
2.5 KiB
Ruby
# NOTE: we are using `GithubIssue` to store issues, pull requests and comments
|
|
class GithubIssue < ApplicationRecord
|
|
CATEGORIES = %w[issue issue_comment].freeze
|
|
API_URL_REGEXP = %r{\Ahttps://api.github.com/repos/.*\z}
|
|
PATH_COMMENT_REGEXP = %r{/issues/comments/}
|
|
PATH_ISSUE_REGEXP = %r{/issues/}
|
|
PATH_PULL_REQUEST_REGEXP = %r{/pulls/}
|
|
PATH_REPO_REGEXP = %r{.*github.com/repos/}
|
|
|
|
serialize :issue_serialized, Hash
|
|
|
|
validates :category, inclusion: { in: CATEGORIES }
|
|
validates :url, presence: true, length: { maximum: 400 }, format: API_URL_REGEXP
|
|
validates :url, uniqueness: true
|
|
|
|
class << self
|
|
def find_or_fetch(url)
|
|
find_by(url: url) || fetch(url)
|
|
end
|
|
|
|
private
|
|
|
|
def fetch(url)
|
|
retrieve_and_save_issue(url)
|
|
rescue Github::Errors::NotFound => e
|
|
raise e, error_message(url)
|
|
end
|
|
|
|
def retrieve_and_save_issue(url)
|
|
issue = new(url: url)
|
|
|
|
if PATH_COMMENT_REGEXP.match?(url)
|
|
repo, issue_id = comment_repo_and_issue_id(url)
|
|
issue.issue_serialized = Github::OauthClient.new.issue_comment(repo, issue_id).to_h
|
|
issue.category = "issue_comment"
|
|
else
|
|
repo, issue_id = issue_or_pull_repo_and_issue_id(url)
|
|
issue.issue_serialized = Github::OauthClient.new.issue(repo, issue_id).to_h
|
|
issue.category = "issue"
|
|
end
|
|
|
|
issue.processed_html = if issue.issue_serialized[:body].present?
|
|
# despite the counter intuitive name `.markdown` returns HTML rendered
|
|
# from the original markdown
|
|
Github::OauthClient.new.markdown(issue.issue_serialized[:body])
|
|
else
|
|
""
|
|
end
|
|
issue.save!
|
|
|
|
issue
|
|
end
|
|
|
|
def clean_url(url)
|
|
url.gsub(PATH_REPO_REGEXP, "")
|
|
end
|
|
|
|
def comment_repo_and_issue_id(url)
|
|
clean_url(url).split(PATH_COMMENT_REGEXP)
|
|
end
|
|
|
|
def issue_or_pull_repo_and_issue_id(url)
|
|
splitter = if PATH_PULL_REQUEST_REGEXP.match?(url)
|
|
PATH_PULL_REQUEST_REGEXP
|
|
else
|
|
PATH_ISSUE_REGEXP
|
|
end
|
|
|
|
clean_url(url).split(splitter)
|
|
end
|
|
|
|
def error_message(url)
|
|
if PATH_COMMENT_REGEXP.match?(url)
|
|
_, issue_id = comment_repo_and_issue_id(url)
|
|
"Issue comment #{issue_id} not found"
|
|
else
|
|
_, issue_id = issue_or_pull_repo_and_issue_id(url)
|
|
"Issue #{issue_id} not found"
|
|
end
|
|
end
|
|
end
|
|
end
|