Skip to content

Commit 150230a

Browse files
Add support for retrieving the latest release (#493)
1 parent bf4fb40 commit 150230a

5 files changed

Lines changed: 72 additions & 0 deletions

File tree

docs/docs/repository.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ with Github4s, you can interact with:
2323
- [Update a File](#update-a-file)
2424
- [Delete a File](#delete-a-file)
2525
- [Releases](#releases)
26+
- [List of releases](#list-of-releases)
27+
- [The latest release](#the-latest-release)
2628
- [Create a release](#create-a-release)
2729
- [Statuses](#statuses)
2830
- [Create a status](#create-a-status)
@@ -379,6 +381,28 @@ response.result match {
379381

380382
The `result` on the right is the corresponding [List[Release]][repository-scala].
381383

384+
### The latest release
385+
386+
You can get the latest release using `latestRelease`, it takes as arguments:
387+
388+
- the repository coordinates (`owner` and `name` of the repository).
389+
390+
Get the latest release:
391+
392+
```scala mdoc:compile-only
393+
val latestRelease =
394+
gh.repos.latestRelease(
395+
"47deg",
396+
"github4s")
397+
val response = latestRelease.unsafeRunSync()
398+
response.result match {
399+
case Left(e) => println(s"Something went wrong: ${e.getMessage}")
400+
case Right(r) => println(r)
401+
}
402+
```
403+
404+
The `result` on the right is the corresponding [Option[Release]][repository-scala].
405+
382406
### Create a release
383407

384408
Users with push access to the repository can create a release using `createRelease`; it takes as arguments:

github4s/src/main/scala/github4s/algebras/Repositories.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,20 @@ trait Repositories[F[_]] {
271271
headers: Map[String, String] = Map()
272272
): F[GHResponse[List[User]]]
273273

274+
/**
275+
* Latest release
276+
*
277+
* @param owner of the repo
278+
* @param repo name of the repo
279+
* @param headers optional user headers to include in the request
280+
* @return a GHResponse with List[Release]
281+
*/
282+
def latestRelease(
283+
owner: String,
284+
repo: String,
285+
headers: Map[String, String] = Map()
286+
): F[GHResponse[Option[Release]]]
287+
274288
/**
275289
* List of releases
276290
*

github4s/src/main/scala/github4s/interpreters/RepositoriesInterpreter.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,14 @@ class RepositoriesInterpreter[F[_]](implicit client: HttpClient[F], accessToken:
217217
pagination
218218
)
219219

220+
override def latestRelease(
221+
owner: String,
222+
repo: String,
223+
headers: Map[String, String]
224+
): F[GHResponse[Option[Release]]] =
225+
client
226+
.get[Option[Release]](accessToken, s"repos/$owner/$repo/releases/latest", headers, Map.empty)
227+
220228
override def listReleases(
221229
owner: String,
222230
repo: String,

github4s/src/test/scala/github4s/integration/ReposSpec.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ trait ReposSpec extends BaseIntegrationSpec {
6161
response.statusCode shouldBe okStatusCode
6262
}
6363

64+
"Repos >> LatestRelease" should "return the expected repos when a valid org is provided" taggedAs Integration in {
65+
val response = clientResource
66+
.use { client =>
67+
Github[IO](client, accessToken).repos
68+
.latestRelease(validRepoOwner, validRepoName, headers = headerUserAgent)
69+
}
70+
.unsafeRunSync()
71+
72+
testIsRight[Option[Release]](response, r => r.nonEmpty shouldBe true)
73+
response.statusCode shouldBe okStatusCode
74+
}
75+
6476
"Repos >> ListOrgRepos" should "return the expected repos when a valid org is provided" taggedAs Integration in {
6577
val response = clientResource
6678
.use { client =>

github4s/src/test/scala/github4s/unit/ReposSpec.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ class ReposSpec extends BaseSpec {
5757
repos.listReleases(validRepoOwner, validRepoName, None, headers = headerUserAgent)
5858
}
5959

60+
"Repos.latestRelease" should "call to httpClient.get with the right parameters" in {
61+
val response: IO[GHResponse[Option[Release]]] =
62+
IO(GHResponse(Option(release).asRight, okStatusCode, Map.empty))
63+
64+
implicit val httpClientMock = httpClientMockGet[Option[Release]](
65+
url = s"repos/$validRepoOwner/$validRepoName/releases/latest",
66+
response = response
67+
)
68+
69+
val repos = new RepositoriesInterpreter[IO]
70+
71+
repos.latestRelease(validRepoOwner, validRepoName, headers = headerUserAgent)
72+
}
73+
6074
"Repos.listOrgRepos" should "call to httpClient.get with the right parameters" in {
6175
val response: IO[GHResponse[List[Repository]]] =
6276
IO(GHResponse(List(repo).asRight, okStatusCode, Map.empty))

0 commit comments

Comments
 (0)