Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add merge pull request method #750

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions github4s/src/main/scala/github4s/Decoders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ object Decoders {
val issue = deriveDecoder[CreatePullRequestIssue]
data.widen[CreatePullRequest] or issue.widen[CreatePullRequest]
}
implicit val decoderPullRequestMergeMethod: Decoder[PullRequestMergeMethod] =
Decoder[String].emap {
case PRMergeMethodMerge.value => PRMergeMethodMerge.asRight
case PRMergeMethodRebase.value => PRMergeMethodRebase.asRight
case PRMergeMethodSquash.value => PRMergeMethodSquash.asRight
case other => s"Unknown pull request merge method: $other".asLeft
}
implicit val decoderPullRequestMergeResponse: Decoder[PullRequestMergeResponse] = deriveDecoder[PullRequestMergeResponse]
implicit val decoderCreateReferenceRequest: Decoder[CreateReferenceRequest] =
deriveDecoder[CreateReferenceRequest]
implicit val decoderDeleteFileRequest: Decoder[DeleteFileRequest] =
Expand Down
6 changes: 6 additions & 0 deletions github4s/src/main/scala/github4s/Encoders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,18 @@ object Encoders {
}
}

implicit val encoderPullRequestMergeRequest: Encoder[PullRequestMergeRequest] =
deriveEncoder[PullRequestMergeRequest]

implicit val encodePrrStatus: Encoder[PullRequestReviewState] =
Encoder.encodeString.contramap(_.value)

implicit val encodePrrEvent: Encoder[PullRequestReviewEvent] =
Encoder.encodeString.contramap(_.value)

implicit val encodePrMergeMethod: Encoder[PullRequestMergeMethod] =
Encoder.encodeString.contramap(_.value)

implicit val encodeEditGistFile: Encoder[EditGistFile] = {
deriveEncoder[EditGistFile].mapJsonObject(
_.filter(e => !(e._1.equals("filename") && e._2.isNull))
Expand Down
24 changes: 24 additions & 0 deletions github4s/src/main/scala/github4s/GHError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ object GHError {
deriveDecoder[NotFoundError]
}

/**
* Corresponds to a 405 status code
* @param message that was given in the response body
*/
final case class MethodNotAllowed(message: String) extends GHError(message) {
override def toString: String = s"MethodNotAllowed($message)"
}
object MethodNotAllowed {
private[github4s] implicit val methodNotAllowedDecoder: Decoder[MethodNotAllowed] =
deriveDecoder[MethodNotAllowed]
}

/**
* Corresponds to a 409 status code
* @param message that was given in the response body
*/
final case class Conflict(message: String) extends GHError(message) {
override def toString: String = s"Conflict($message)"
}
object Conflict {
private[github4s] implicit val conflictDecoder: Decoder[Conflict] =
deriveDecoder[Conflict]
}

sealed trait ErrorCode
object ErrorCode {
case object MissingResource extends ErrorCode
Expand Down
23 changes: 23 additions & 0 deletions github4s/src/main/scala/github4s/algebras/PullRequests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,29 @@ trait PullRequests[F[_]] {
headers: Map[String, String] = Map()
): F[GHResponse[PullRequest]]

/**
* Merge a pull request
*
* @param owner Owner of the repo
* @param repo Name of the repo
* @param number of the pull request for which we want to merge
* @param commitTitle Title for the automatic commit message
* @param commitMessage Extra detail to append to automatic commit message
* @param sha SHA that pull request head must match to allow merge
* @param mergeMethod Merge method to use. Possible values are merge, squash or rebase. Default is merge.
* @param headers Optional user headers to include in the request
*/
def mergePullRequest(
owner: String,
repo: String,
number: Long,
commitTitle: Option[String] = None,
commitMessage: Option[String] = None,
sha: Option[String] = None,
mergeMethod: Option[PullRequestMergeMethod] = None,
headers: Map[String, String] = Map()
): F[GHResponse[PullRequestMergeResponse]]

/**
* List pull request reviews.
*
Expand Down
15 changes: 15 additions & 0 deletions github4s/src/main/scala/github4s/domain/PullRequest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ final case class CreatePullRequestIssue(
maintainer_can_modify: Option[Boolean] = Some(true)
) extends CreatePullRequest

final case class PullRequestMergeRequest(
commit_title: Option[String],
commit_message: Option[String],
sha: Option[String],
merge_method: Option[PullRequestMergeMethod]
)

final case class PullRequestMergeResponse(sha: String, merged: Boolean, message: String)

sealed abstract class PRFilter(val name: String, val value: String)
extends Product
with Serializable {
Expand Down Expand Up @@ -154,3 +163,9 @@ final case class ReviewersResponse(

final case class BranchUpdateRequest(expected_head_sha: Option[String])
final case class BranchUpdateResponse(message: String, url: String)

sealed abstract class PullRequestMergeMethod(val value: String) extends Product with Serializable

case object PRMergeMethodMerge extends PullRequestMergeMethod("merge")
case object PRMergeMethodSquash extends PullRequestMergeMethod("squash")
case object PRMergeMethodRebase extends PullRequestMergeMethod("rebase")
2 changes: 2 additions & 0 deletions github4s/src/main/scala/github4s/http/HttpClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ object HttpClient {
case 401 => response.attemptAs[UnauthorizedError].map(_.asLeft)
case 403 => response.attemptAs[ForbiddenError].map(_.asLeft)
case 404 => response.attemptAs[GHError](notFoundEntityDecoder).map(_.asLeft)
case 405 => response.attemptAs[MethodNotAllowed].map(_.asLeft)
case 409 => response.attemptAs[Conflict].map(_.asLeft)
case 422 => response.attemptAs[UnprocessableEntityError].map(_.asLeft)
case 423 => response.attemptAs[RateLimitExceededError].map(_.asLeft)
case _ =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,30 @@ class PullRequestsInterpreter[F[_]](implicit client: HttpClient[F]) extends Pull
.post[CreatePullRequest, PullRequest](s"repos/$owner/$repo/pulls", headers, data)
}

override def mergePullRequest(
owner: String,
repo: String,
number: Long,
commitTitle: Option[String],
commitMessage: Option[String],
sha: Option[String],
mergeMethod: Option[PullRequestMergeMethod],
headers: Map[String, String]
) = {
val request = PullRequestMergeRequest(
commitTitle,
commitMessage,
sha,
mergeMethod
)
client
.put[PullRequestMergeRequest, PullRequestMergeResponse](
s"/repos/$owner/$repo/pulls/$number/merge",
headers,
request
)
}

override def listReviews(
owner: String,
repo: String,
Expand Down