quarkiverse / quarkus-github-app

Develop your GitHub Apps in Java with Quarkus.
https://docs.quarkiverse.io/quarkus-github-app/dev/index.html
Apache License 2.0
60 stars 27 forks source link

Team events fail because there is no repository information #572

Closed ebullient closed 4 months ago

ebullient commented 4 months ago

Team membership changes happen at the org level, so there is no repository.

The bot fails handling those events because we parse assuming the repository will be there.

2024-02-27 08:38:32,701 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (vert.x-eventloop-thread-2) HTTP Request to /replay/events failed, error id: 4d5b3606-d5aa-4392-8cac-26290cf1c140-1037: io.vertx.core.json.EncodeException: Failed to encode as JSON: The payload did not provide any repository information (through reference chain: io.quarkiverse.githubapp.GitHubEvent["repositoryOrThrow"])
        at io.quarkus.vertx.runtime.jackson.QuarkusJacksonJsonCodec.toBuffer(QuarkusJacksonJsonCodec.java:157)
        at io.vertx.core.spi.json.JsonCodec.toBuffer(JsonCodec.java:69)
        at io.vertx.core.json.Json.encodeToBuffer(Json.java:60)
        at io.quarkus.vertx.web.runtime.MultiSseSupport$5.apply(MultiSseSupport.java:142)
        at io.quarkus.vertx.web.runtime.MultiSseSupport$5.apply(MultiSseSupport.java:135)
        at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
        at io.smallrye.mutiny.operators.multi.MultiMapOp$MapProcessor.onItem(MultiMapOp.java:42)
        at io.smallrye.mutiny.subscription.MultiSubscriber.onNext(MultiSubscriber.java:61)
        at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapMainSubscriber.tryEmit(MultiFlatMapOp.java:219)
        at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapInner.onItem(MultiFlatMapOp.java:554)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti$IteratorSubscription.slowPath(IterableBasedMulti.java:159)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti$IteratorSubscription.request(IterableBasedMulti.java:71)
        at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapInner.onSubscribe(MultiFlatMapOp.java:548)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti.subscribe(IterableBasedMulti.java:48)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti.subscribe(IterableBasedMulti.java:32)
        at io.smallrye.mutiny.operators.AbstractMulti.subscribe(AbstractMulti.java:39)
        at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapMainSubscriber.onItem(MultiFlatMapOp.java:182)
        at io.smallrye.mutiny.operators.multi.builders.CollectionBasedMulti$CollectionSubscription.followRequests(CollectionBasedMulti.java:89)
        at io.smallrye.mutiny.operators.multi.builders.CollectionBasedMulti$CollectionSubscription.request(CollectionBasedMulti.java:68)
        at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapMainSubscriber.onSubscribe(MultiFlatMapOp.java:154)
        at io.smallrye.mutiny.operators.multi.builders.CollectionBasedMulti.subscribe(CollectionBasedMulti.java:36)
        at io.smallrye.mutiny.operators.AbstractMulti.subscribe(AbstractMulti.java:39)
        at io.smallrye.mutiny.operators.multi.MultiFlatMapOp.subscribe(MultiFlatMapOp.java:51)
        at io.smallrye.mutiny.groups.MultiSubscribe.withSubscriber(MultiSubscribe.java:70)
        at io.smallrye.mutiny.operators.multi.MultiMapOp.subscribe(MultiMapOp.java:24)
        at io.smallrye.mutiny.operators.AbstractMulti.subscribe(AbstractMulti.java:39)
        at io.smallrye.mutiny.groups.MultiSubscribe.withSubscriber(MultiSubscribe.java:50)
        at io.quarkus.vertx.web.runtime.MultiSseSupport.write(MultiSseSupport.java:54)
        at io.quarkus.vertx.web.runtime.MultiSseSupport.subscribeObject(MultiSseSupport.java:135)
        at io.quarkiverse.githubapp.runtime.replay.ReplayEventsRoute_RouteHandler_replayEvents_e2fe30ad4c6ae8d5c92daaad3256d2d0826c0a60.invoke(Unknown Source)
        at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:97)
        at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:22)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1285)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:140)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:137)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$16.handle(VertxHttpRecorder.java:1382)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$16.handle(VertxHttpRecorder.java:1351)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1285)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:137)
        at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:62)
        at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:40)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1285)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:137)
        at io.quarkus.vertx.web.runtime.VertxWebRecorder$2.handle(VertxWebRecorder.java:159)
        at io.quarkus.vertx.web.runtime.VertxWebRecorder$2.handle(VertxWebRecorder.java:143)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1285)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:137)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:192)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:181)
        at io.vertx.core.impl.future.FutureImpl$4.onSuccess(FutureImpl.java:176)
        at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:60)
        at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: The payload did not provide any repository information (through reference chain: io.quarkiverse.githubapp.GitHubEvent["repositoryOrThrow"])
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:402)
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:361)
        at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:323)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:778)
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:183)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:502)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:341)
        at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4793)
        at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsBytes(ObjectMapper.java:4061)
        at io.quarkus.vertx.runtime.jackson.QuarkusJacksonJsonCodec.toBuffer(QuarkusJacksonJsonCodec.java:155)
        ... 61 more
Caused by: java.lang.IllegalStateException: The payload did not provide any repository information
        at io.quarkiverse.githubapp.GitHubEvent.lambda$getRepositoryOrThrow$0(GitHubEvent.java:58)
        at java.base/java.util.Optional.orElseThrow(Optional.java:403)
        at io.quarkiverse.githubapp.GitHubEvent.getRepositoryOrThrow(GitHubEvent.java:58)
        at jdk.internal.reflect.GeneratedMethodAccessor139.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWerializeAsField(BeanPropertyWriter.java:688)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
        ... 67 more

To reproduce: subscribe to org membership events, and make a change to a team. Here is an example payload you can drop into unit tests:

{
  "action": "added",
  "scope": "team",
  "member": {
    "login": "commonhaus-bot",
    "id": 156364140,
    "node_id": "U_kgDOCVHtbA",
    "avatar_url": "https://avatars.githubusercontent.com/u/156364140?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/commonhaus-bot",
    "html_url": "https://github.com/commonhaus-bot",
    "followers_url": "https://api.github.com/users/commonhaus-bot/followers",
    "following_url": "https://api.github.com/users/commonhaus-bot/following{/other_user}",
    "gists_url": "https://api.github.com/users/commonhaus-bot/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/commonhaus-bot/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/commonhaus-bot/subscriptions",
    "organizations_url": "https://api.github.com/users/commonhaus-bot/orgs",
    "repos_url": "https://api.github.com/users/commonhaus-bot/repos",
    "events_url": "https://api.github.com/users/commonhaus-bot/events{/privacy}",
    "received_events_url": "https://api.github.com/users/commonhaus-bot/received_events",
    "type": "User",
    "site_admin": false
  },
  "sender": {
    "login": "ebullient",
    "id": 808713,
    "node_id": "MDQ6VXNlcjgwODcxMw==",
    "avatar_url": "https://avatars.githubusercontent.com/u/808713?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/ebullient",
    "html_url": "https://github.com/ebullient",
    "followers_url": "https://api.github.com/users/ebullient/followers",
    "following_url": "https://api.github.com/users/ebullient/following{/other_user}",
    "gists_url": "https://api.github.com/users/ebullient/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/ebullient/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/ebullient/subscriptions",
    "organizations_url": "https://api.github.com/users/ebullient/orgs",
    "repos_url": "https://api.github.com/users/ebullient/repos",
    "events_url": "https://api.github.com/users/ebullient/events{/privacy}",
    "received_events_url": "https://api.github.com/users/ebullient/received_events",
    "type": "User",
    "site_admin": false
  },
  "team": {
    "name": "test-quorum-larger",
    "id": 9331843,
    "node_id": "T_kwDOCJzKmc4AjmSD",
    "slug": "test-quorum-larger",
    "description": "Larger (not-default) group for testing quorum",
    "privacy": "closed",
    "notification_setting": "notifications_disabled",
    "url": "https://api.github.com/organizations/144493209/team/9331843",
    "html_url": "https://github.com/orgs/commonhaus/teams/test-quorum-larger",
    "members_url": "https://api.github.com/organizations/144493209/team/9331843/members{/member}",
    "repositories_url": "https://api.github.com/organizations/144493209/team/9331843/repos",
    "permission": "pull",
    "parent": {
      "name": "automation",
      "id": 9281706,
      "node_id": "T_kwDOCJzKmc4AjaCq",
      "slug": "automation",
      "description": "",
      "privacy": "closed",
      "notification_setting": "notifications_enabled",
      "url": "https://api.github.com/organizations/144493209/team/9281706",
      "html_url": "https://github.com/orgs/commonhaus/teams/automation",
      "members_url": "https://api.github.com/organizations/144493209/team/9281706/members{/member}",
      "repositories_url": "https://api.github.com/organizations/144493209/team/9281706/repos",
      "permission": "pull"
    }
  },
  "organization": {
    "login": "commonhaus",
    "id": 144493209,
    "node_id": "O_kgDOCJzKmQ",
    "url": "https://api.github.com/orgs/commonhaus",
    "repos_url": "https://api.github.com/orgs/commonhaus/repos",
    "events_url": "https://api.github.com/orgs/commonhaus/events",
    "hooks_url": "https://api.github.com/orgs/commonhaus/hooks",
    "issues_url": "https://api.github.com/orgs/commonhaus/issues",
    "members_url": "https://api.github.com/orgs/commonhaus/members{/member}",
    "public_members_url": "https://api.github.com/orgs/commonhaus/public_members{/member}",
    "avatar_url": "https://avatars.githubusercontent.com/u/144493209?v=4",
    "description": ""
  },
  "installation": {
    "id": 46053716,
    "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDYwNTM3MTY="
  }
}