-
Notifications
You must be signed in to change notification settings - Fork 729
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 offline support to the API to make parsing events easier #306
Conversation
- When we receive events from a webhook, it is non-trivial to determine which GitHub instance the event came from or for that matter even if the event actually came from GitHub or GitHub Enterprise. - In order to ensure that the logic for parsing events does not get replicated in clients, we need to be able to call GitHub.parseEventPayload(Reader,Class) without knowing which GitHub the event originates from and without the resulting objects triggering API calls back to a GitHub - Thus we add GitHub.offline() to provide an off-line connection - Thus we modify some of the object classes to return best-effort objects when off-line - Add support for more of the event types into GHEventPayload - Add tests of the event payload and accessing critical fields when using GitHub.offline()
This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐝 (assuming a downstream PR is in the making)
@@ -35,7 +35,7 @@ | |||
GHIssue owner; | |||
|
|||
private String body, gravatar_id; | |||
private GHUser user; | |||
private GHUser user; // not fully populated. beware. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this sort of comment would better be placed in the Javadoc of the getter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep... just copying existing code style
@@ -216,13 +216,39 @@ public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOExce | |||
} | |||
|
|||
/** | |||
* An off-line only {@link GitHub} useful for parsing event notification from an unknown source. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
offline-only
return IOUtils.toByteArray(input); | ||
} finally { | ||
IOUtils.closeQuietly(input); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try (InputStream input = asInputStream()) {
return IOUtils.toByteArray(input);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Java 5 (yes WAT!)
} | ||
|
||
public Reader asReader() throws FileNotFoundException { | ||
return new InputStreamReader(asInputStream(), Charset.defaultCharset()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is being used for JSON, I would think UTF-8 would be more appropriate.
"avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", | ||
"gravatar_id": "", | ||
"url": "https://api.github.com/users/baxterthehacker", | ||
"html_url": "https://github.com/baxterthehacker", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who are you really @baxterthehacker? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are the samples from github's api docs
/** | ||
* @author Stephen Connolly | ||
*/ | ||
public class PayloadRule implements TestRule { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not going to use jenkinsci/jenkins-test-harness#39?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a kohsuke project not a jenkins project (would be nice if it was something we could release without KK)
210b1f7
to
498d63e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re:bee:
*/ | ||
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, | ||
justification = "Constructed by JSON deserialization") | ||
public static class CommitComment extends GHEventPayload { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe its better to place this classes in separate files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would have been better if the design was originally that way... but needs to be in same package due to current API design (FTR I would not have designed this API this way as it is very tricky to unpick the stuff that requires a connection from the stuff that doesn't... but we are where we are)
public void pull_request() throws Exception { | ||
GHEventPayload.PullRequest event = | ||
GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); | ||
assertThat(event.getAction(), is("opened")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can create expected object and use haveSameProperties
matcher
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That runs the risk of following requests for the partial objects that are not available from the event objects. safer to just test the paths
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Should be a nice improvement. And 🐝
* Gets the sender or {@code null} if accessed via the events API. | ||
* @return the sender or {@code null} if accessed via the events API. | ||
*/ | ||
public GHUser getSender() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CheckForNull
. Nobody reads Javadoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But generally applies to all deserialized fields :(
@@ -147,6 +489,11 @@ public String getBefore() { | |||
return before; | |||
} | |||
|
|||
@JsonSetter // alias | |||
private void setAfter(String after) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it worth to add getter as well. Just to avoid confusing people
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's private
just using this as an alias field name... the documented sample event payload says "after" the documented event says "head" and my tests say "head" but the alias is here as a "just in case"
or for that matter even if the event actually came from GitHub or GitHub Enterprise.
able to call
GitHub.parseEventPayload(Reader,Class)
without knowing whichGitHub
the event originates fromand without the resulting objects triggering API calls back to a GitHub
GitHub.offline()
to provide an off-line connectionGHEventPayload
GitHub.offline()
@reviewbybees