Skip to content

Commit 1bd762f

Browse files
authored
Add new endpoint - List public organization events (#789)
1 parent 7f3c9f0 commit 1bd762f

File tree

11 files changed

+156
-2
lines changed

11 files changed

+156
-2
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ If you wish to add your library here please consider a PR to include it in the l
2828

2929
Github4s is designed and developed by 47 Degrees
3030

31-
Copyright (C) 2016-2020 47 Degrees. <http://47deg.com>
31+
Copyright (C) 2016-2022 47 Degrees. <http://47deg.com>

docs/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ If you wish to add your library here please consider a PR to include it in the l
2828

2929
Github4s is designed and developed by 47 Degrees
3030

31-
Copyright (C) 2016-2020 47 Degrees. <http://47deg.com>
31+
Copyright (C) 2016-2022 47 Degrees. <http://47deg.com>

github4s/shared/src/main/scala/github4s/Decoders.scala

+19
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ object Decoders {
246246
)
247247
)
248248

249+
implicit val decodePublicOrganizationEvent: Decoder[PublicOrganizationEvent] =
250+
Decoder.instance(c =>
251+
for {
252+
id <- c.downField("id").as[Long]
253+
event_type <- c.downField("type").as[String]
254+
actor_login <- c.downField("actor").downField("login").as[String]
255+
repo_full_name <- c.downField("repo").downField("full_name").as[String]
256+
public <- c.downField("public").as[Boolean]
257+
created_at <- c.downField("created_at").as[String]
258+
} yield PublicOrganizationEvent(
259+
id,
260+
event_type,
261+
actor_login,
262+
repo_full_name,
263+
public,
264+
created_at
265+
)
266+
)
267+
249268
implicit val decoderFileComparisonNotRenamed: Decoder[FileComparison.FileComparisonNotRenamed] =
250269
deriveDecoder[FileComparison.FileComparisonNotRenamed]
251270
implicit val decoderFileComparisonRenamed: Decoder[FileComparison.FileComparisonRenamed] =

github4s/shared/src/main/scala/github4s/Encoders.scala

+17
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ object Encoders {
238238
case None => repo
239239
}
240240
}
241+
242+
implicit val encoderPublicOrganizationEvents: Encoder[PublicOrganizationEvent] =
243+
Encoder.instance { e =>
244+
Json.obj(
245+
"id" -> e.id.asJson,
246+
"type" -> e.`type`.asJson,
247+
"public" -> e.public.asJson,
248+
"created_at" -> e.created_at.asJson,
249+
"actor" -> Json.obj(
250+
"login" -> e.actor_login.asJson
251+
),
252+
"repo" -> Json.obj(
253+
"full_name" -> e.repo_full_name.asJson
254+
)
255+
)
256+
}
257+
241258
implicit val encoderIssue: Encoder[Issue] = deriveEncoder[Issue]
242259
implicit val encoderIssuePullRequest: Encoder[IssuePullRequest] = deriveEncoder[IssuePullRequest]
243260
implicit val encoderGistFile: Encoder[GistFile] = deriveEncoder[GistFile]

github4s/shared/src/main/scala/github4s/algebras/Activities.scala

+14
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,18 @@ trait Activities[F[_]] {
7676
headers: Map[String, String] = Map()
7777
): F[GHResponse[List[StarredRepository]]]
7878

79+
/**
80+
* List the events of a particular public organization
81+
*
82+
* @param org Organization for which we wish to retrieve the events
83+
* @param pagination Limit and Offset for pagination
84+
* @param headers Optional user headers to include in the request
85+
* @return GHResponse with the list of events for this public organization
86+
*/
87+
def listPublicOrganizationEvents(
88+
org: String,
89+
pagination: Option[Pagination] = None,
90+
headers: Map[String, String] = Map()
91+
): F[GHResponse[List[PublicOrganizationEvent]]]
92+
7993
}

github4s/shared/src/main/scala/github4s/domain/Activity.scala

+9
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,12 @@ final case class StarredRepository(
3939
repo: Repository,
4040
starred_at: Option[String] = None
4141
)
42+
43+
final case class PublicOrganizationEvent(
44+
id: Long,
45+
`type`: String,
46+
actor_login: String,
47+
repo_full_name: String,
48+
public: Boolean,
49+
created_at: String
50+
)

github4s/shared/src/main/scala/github4s/interpreters/ActivitiesInterpreter.scala

+15
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class ActivitiesInterpreter[F[_]](implicit client: HttpClient[F]) extends Activi
2727

2828
private val timelineHeader = ("Accept" -> "application/vnd.github.v3.star+json")
2929

30+
private val eventsRecommendedHeader = ("Accept" -> "application/vnd.github.v3+json")
31+
3032
override def setThreadSub(
3133
id: Long,
3234
subscribed: Boolean,
@@ -69,4 +71,17 @@ class ActivitiesInterpreter[F[_]](implicit client: HttpClient[F]) extends Activi
6971
).collect { case (key, Some(value)) => key -> value },
7072
pagination = pagination
7173
)
74+
75+
override def listPublicOrganizationEvents(
76+
org: String,
77+
pagination: Option[Pagination],
78+
headers: Map[String, String]
79+
): F[GHResponse[List[PublicOrganizationEvent]]] =
80+
client.get[List[PublicOrganizationEvent]](
81+
method = s"orgs/$org/events",
82+
headers + eventsRecommendedHeader,
83+
Map.empty,
84+
pagination = pagination
85+
)
86+
7287
}

github4s/shared/src/test/scala/github4s/integration/ActivitiesSpec.scala

+33
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,37 @@ trait ActivitiesSpec extends BaseIntegrationSpec {
143143
testIsLeft[NotFoundError, List[StarredRepository]](response)
144144
response.statusCode shouldBe notFoundStatusCode
145145
}
146+
147+
"Activity >> PublicOrganizationEvents" should "return the expected list of events" taggedAs Integration in {
148+
val response = clientResource
149+
.use { client =>
150+
Github[IO](client, accessToken).activities
151+
.listPublicOrganizationEvents(validOrganizationName, headers = headerUserAgent)
152+
}
153+
.unsafeRunSync()
154+
155+
testIsRight[List[PublicOrganizationEvent]](
156+
response,
157+
{ r =>
158+
r.nonEmpty shouldBe true
159+
forAll(r)(s => s.public shouldBe true)
160+
forAll(r)(s => s.actor_login.nonEmpty shouldBe true)
161+
forAll(r)(s => s.repo_full_name.nonEmpty shouldBe true)
162+
}
163+
)
164+
response.statusCode shouldBe okStatusCode
165+
}
166+
167+
it should "return error for invalid organization" taggedAs Integration in {
168+
val response = clientResource
169+
.use { client =>
170+
Github[IO](client, accessToken).activities
171+
.listPublicOrganizationEvents(invalidOrganizationName, headers = headerUserAgent)
172+
}
173+
.unsafeRunSync()
174+
175+
testIsLeft[NotFoundError, List[PublicOrganizationEvent]](response)
176+
response.statusCode shouldBe notFoundStatusCode
177+
}
178+
146179
}

github4s/shared/src/test/scala/github4s/unit/ActivitiesSpec.scala

+14
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,18 @@ class ActivitiesSpec extends BaseSpec {
7070
.shouldNotFail
7171
}
7272

73+
"Activity.listPublicOrganizationEvents" should "call to httpClient.get with the right parameters" in {
74+
75+
implicit val httpClientMock: HttpClient[IO] = httpClientMockGet[List[PublicOrganizationEvent]](
76+
url = s"orgs/$validOrganizationName/events",
77+
response = IO.pure(List(publicOrganizationEvent))
78+
)
79+
80+
val activities = new ActivitiesInterpreter[IO]
81+
82+
activities
83+
.listPublicOrganizationEvents(validUsername, None, headerUserAgent)
84+
.shouldNotFail
85+
}
86+
7387
}

github4s/shared/src/test/scala/github4s/utils/TestData.scala

+9
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,15 @@ trait TestData {
439439
val stargazer = Stargazer(user)
440440
val starredRepository = StarredRepository(repo)
441441

442+
val publicOrganizationEvent = PublicOrganizationEvent(
443+
id = 21492285567L,
444+
`type` = "PushEvent",
445+
actor_login = "47erbot",
446+
repo_full_name = "47degrees/github4s",
447+
public = true,
448+
created_at = "2022-04-27T05:29:31Z"
449+
)
450+
442451
val pullRequestReview = PullRequestReview(
443452
id = validPullRequestReviewNumber,
444453
user = Some(user),

microsite/docs/activity.md

+24
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ with Github4s, you can interact with:
1414
- [Starring](#starring)
1515
- [List stargazers](#list-stargazers)
1616
- [List starred repositories](#list-starred-repositories)
17+
- [List public organization events](#list-public-organization-events)
1718

1819
The following examples assume the following code:
1920

@@ -106,6 +107,29 @@ The `result` on the right is the corresponding [List[StarredRepository]][activit
106107
See [the API doc](https://developer.github.com/v3/activity/starring/#list-repositories-being-starred)
107108
for full reference.
108109

110+
### List public organization events
111+
112+
You can list the events of a particular public organization with `listPublicOrganizationEvents`; it takes
113+
as arguments:
114+
115+
- `org`: name of the organization for which we want to retrieve the events.
116+
- `pagination`: Limit and Offset for pagination, optional.
117+
118+
To list the events for org `47degrees`:
119+
120+
```scala mdoc:compile-only
121+
val listPublicOrganizationEvents = gh.activities.listPublicOrganizationEvents("47degrees")
122+
listPublicOrganizationEvents.flatMap(_.result match {
123+
case Left(e) => IO.println(s"Something went wrong: ${e.getMessage}")
124+
case Right(r) => IO.println(r)
125+
})
126+
```
127+
128+
The `result` on the right is the corresponding [List[PublicOrganizationEvent]][activity-scala].
129+
130+
See [the API doc](https://docs.github.com/en/rest/activity/events#list-public-organization-events)
131+
for full reference.
132+
109133
As you can see, a few features of the activity endpoint are missing.
110134

111135
As a result, if you'd like to see a feature supported, feel free to create an issue and/or a pull request!

0 commit comments

Comments
 (0)