Skip to content

Commit

Permalink
Merge pull request #1502 from gsmet/projectv2-payload
Browse files Browse the repository at this point in the history
Add ProjectsV2Item event payload
  • Loading branch information
bitwiseman committed Aug 18, 2022
2 parents 262cf84 + 5e26d18 commit e5fb0cd
Show file tree
Hide file tree
Showing 9 changed files with 640 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/main/java/org/kohsuke/github/GHEventPayload.java
Expand Up @@ -1630,4 +1630,26 @@ public Date getStarredAt() {
return GitHubClient.parseDate(starredAt);
}
}

/**
* A project v2 item was archived, converted, created, edited, restored, deleted, or reordered.
*
* @see <a href=
* "https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2_item">star
* event</a>
*/
public static class ProjectsV2Item extends GHEventPayload {

private GHProjectsV2Item projectsV2Item;
private GHProjectsV2ItemChanges changes;

@SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected")
public GHProjectsV2Item getProjectsV2Item() {
return projectsV2Item;
}

public GHProjectsV2ItemChanges getChanges() {
return changes;
}
}
}
59 changes: 59 additions & 0 deletions src/main/java/org/kohsuke/github/GHProjectsV2Item.java
@@ -0,0 +1,59 @@
package org.kohsuke.github;

import org.kohsuke.github.internal.EnumUtils;

import java.io.IOException;
import java.net.URL;
import java.util.Date;

/**
* A Projects V2 item in the organization.
* <p>
* Projects V2 are not attached to a repository but to an organization, even if it is possible to create shortcuts at
* the repository level.
* <p>
* This event exposes the GraphQL object (more or less - the ids are handled differently for instance) directly. The new
* Projects V2 API is only available through GraphQL so for now you cannot execute any actions on this object.
*
* @author Guillaume Smet
* @see <a href=
* "https://docs.github.com/en/issues/planning-and-tracking-with-projects/automating-your-project/using-the-api-to-manage-projects">The
* GraphQL API for Projects V2</a>
*/
public class GHProjectsV2Item extends GHObject {

private String projectNodeId;
private String contentNodeId;
private String contentType;

private GHUser creator;
private String archivedAt;

public String getProjectNodeId() {
return projectNodeId;
}

public String getContentNodeId() {
return contentNodeId;
}

public ContentType getContentType() {
return EnumUtils.getEnumOrDefault(ContentType.class, contentType, ContentType.UNKNOWN);
}

public GHUser getCreator() throws IOException {
return root().intern(creator);
}

public Date getArchivedAt() {
return GitHubClient.parseDate(archivedAt);
}

public URL getHtmlUrl() {
throw new IllegalStateException(getClass().getName() + " does not offer a HTML URL.");
}

public enum ContentType {
ISSUE, DRAFTISSUE, PULLREQUEST, UNKNOWN;
}
}
80 changes: 80 additions & 0 deletions src/main/java/org/kohsuke/github/GHProjectsV2ItemChanges.java
@@ -0,0 +1,80 @@
package org.kohsuke.github;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.kohsuke.github.internal.EnumUtils;

import java.util.Date;

/**
* An object to track changes in projects_v2_item payloads.
* <p>
* Note that this is best effort only as nothing is documented in the GitHub documentation.
*/
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API")
public class GHProjectsV2ItemChanges {

private FieldValue fieldValue;

private FromToDate archivedAt;

private FromTo previousProjectsV2ItemNodeId;

public FieldValue getFieldValue() {
return fieldValue;
}

public FromToDate getArchivedAt() {
return archivedAt;
}

public FromTo getPreviousProjectsV2ItemNodeId() {
return previousProjectsV2ItemNodeId;
}

public static class FieldValue {

private String fieldNodeId;
private String fieldType;

public String getFieldNodeId() {
return fieldNodeId;
}

public FieldType getFieldType() {
return EnumUtils.getEnumOrDefault(FieldType.class, fieldType, FieldType.UNKNOWN);
}
}

public static class FromTo {

private String from;
private String to;

public String getFrom() {
return from;
}

public String getTo() {
return to;
}
}

public static class FromToDate {

private String from;
private String to;

public Date getFrom() {
return GitHubClient.parseDate(from);
}

public Date getTo() {
return GitHubClient.parseDate(to);
}
}

public enum FieldType {

TEXT, NUMBER, DATE, SINGLE_SELECT, ITERATION, UNKNOWN;
}
}
100 changes: 100 additions & 0 deletions src/test/java/org/kohsuke/github/GHEventPayloadTest.java
Expand Up @@ -4,6 +4,8 @@
import org.junit.Test;
import org.kohsuke.github.GHCheckRun.Conclusion;
import org.kohsuke.github.GHCheckRun.Status;
import org.kohsuke.github.GHProjectsV2Item.ContentType;
import org.kohsuke.github.GHProjectsV2ItemChanges.FieldType;

import java.io.IOException;
import java.text.SimpleDateFormat;
Expand Down Expand Up @@ -1152,4 +1154,102 @@ public void starred() throws Exception {
assertThat(starPayload.getSender().getLogin(), is("gsmet"));
assertThat(starPayload.getStarredAt().getTime(), is(1654017876000L));
}

@Test
public void projectsv2item_created() throws Exception {
final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline()
.parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class);

assertThat(projectsV2ItemPayload.getAction(), is("created"));

assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getNodeId(), is("PVTI_lADOBNft-M4AEjBWzgB7VzY"));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getProjectNodeId(), is("PVT_kwDOBNft-M4AEjBW"));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getContentNodeId(), is("I_kwDOFOkjw85Ozz26"));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getContentType(), is(ContentType.ISSUE));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreator().getLogin(), is("gsmet"));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreator().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk="));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532028000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532028000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue()));

assertThat(projectsV2ItemPayload.getOrganization().getLogin(), is("gsmet-bot-playground"));
assertThat(projectsV2ItemPayload.getOrganization().getId(), is(81260024L));
assertThat(projectsV2ItemPayload.getOrganization().getNodeId(), is("MDEyOk9yZ2FuaXphdGlvbjgxMjYwMDI0"));

assertThat(projectsV2ItemPayload.getSender().getLogin(), is("gsmet"));
assertThat(projectsV2ItemPayload.getSender().getId(), is(1279749L));
assertThat(projectsV2ItemPayload.getSender().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk="));

assertThat(projectsV2ItemPayload.getInstallation().getId(), is(16779846L));
assertThat(projectsV2ItemPayload.getInstallation().getNodeId(),
is("MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY3Nzk4NDY="));
}

@Test
public void projectsv2item_edited() throws Exception {
final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline()
.parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class);

assertThat(projectsV2ItemPayload.getAction(), is("edited"));

assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532028000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532033000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue()));

assertThat(projectsV2ItemPayload.getChanges().getFieldValue().getFieldNodeId(),
is("PVTF_lADOBNft-M4AEjBWzgCnp5Q"));
assertThat(projectsV2ItemPayload.getChanges().getFieldValue().getFieldType(), is(FieldType.SINGLE_SELECT));
}

@Test
public void projectsv2item_archived() throws Exception {
final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline()
.parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class);

assertThat(projectsV2ItemPayload.getAction(), is("archived"));

assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083794L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532431000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1660086629000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt().getTime(), is(1660086629000L));

assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getFrom(), is(nullValue()));
assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getTo().getTime(), is(1660086629000L));
}

@Test
public void projectsv2item_restored() throws Exception {
final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline()
.parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class);

assertThat(projectsV2ItemPayload.getAction(), is("restored"));

assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532028000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532419000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue()));

assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getFrom().getTime(), is(1659532142000L));
assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getTo(), is(nullValue()));
}

@Test
public void projectsv2item_reordered() throws Exception {
final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline()
.parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class);

assertThat(projectsV2ItemPayload.getAction(), is("reordered"));

assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083794L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532431000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532439000L));
assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue()));

assertThat(projectsV2ItemPayload.getChanges().getPreviousProjectsV2ItemNodeId().getFrom(),
is("PVTI_lADOBNft-M4AEjBWzgB7VzY"));
assertThat(projectsV2ItemPayload.getChanges().getPreviousProjectsV2ItemNodeId().getTo(),
is("PVTI_lADOBNft-M4AEjBWzgB7VzY"));
}
}
@@ -0,0 +1,77 @@
{
"action": "archived",
"projects_v2_item": {
"id": 8083794,
"node_id": "PVTI_lADOBNft-M4AEjBWzgB7WVI",
"project_node_id": "PVT_kwDOBNft-M4AEjBW",
"content_node_id": "I_kwDOFOkjw85OzN4w",
"content_type": "Issue",
"creator": {
"login": "gsmet",
"id": 1279749,
"node_id": "MDQ6VXNlcjEyNzk3NDk=",
"avatar_url": "https://avatars.githubusercontent.com/u/1279749?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/gsmet",
"html_url": "https://github.com/gsmet",
"followers_url": "https://api.github.com/users/gsmet/followers",
"following_url": "https://api.github.com/users/gsmet/following{/other_user}",
"gists_url": "https://api.github.com/users/gsmet/gists{/gist_id}",
"starred_url": "https://api.github.com/users/gsmet/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/gsmet/subscriptions",
"organizations_url": "https://api.github.com/users/gsmet/orgs",
"repos_url": "https://api.github.com/users/gsmet/repos",
"events_url": "https://api.github.com/users/gsmet/events{/privacy}",
"received_events_url": "https://api.github.com/users/gsmet/received_events",
"type": "User",
"site_admin": false
},
"created_at": "2022-08-03T13:13:51Z",
"updated_at": "2022-08-09T23:10:29Z",
"archived_at": "2022-08-09T23:10:29Z"
},
"changes": {
"archived_at": {
"from": null,
"to": "2022-08-10T01:10:29+02:00"
}
},
"organization": {
"login": "gsmet-bot-playground",
"id": 81260024,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjgxMjYwMDI0",
"url": "https://api.github.com/orgs/gsmet-bot-playground",
"repos_url": "https://api.github.com/orgs/gsmet-bot-playground/repos",
"events_url": "https://api.github.com/orgs/gsmet-bot-playground/events",
"hooks_url": "https://api.github.com/orgs/gsmet-bot-playground/hooks",
"issues_url": "https://api.github.com/orgs/gsmet-bot-playground/issues",
"members_url": "https://api.github.com/orgs/gsmet-bot-playground/members{/member}",
"public_members_url": "https://api.github.com/orgs/gsmet-bot-playground/public_members{/member}",
"avatar_url": "https://avatars.githubusercontent.com/u/81260024?v=4",
"description": null
},
"sender": {
"login": "gsmet",
"id": 1279749,
"node_id": "MDQ6VXNlcjEyNzk3NDk=",
"avatar_url": "https://avatars.githubusercontent.com/u/1279749?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/gsmet",
"html_url": "https://github.com/gsmet",
"followers_url": "https://api.github.com/users/gsmet/followers",
"following_url": "https://api.github.com/users/gsmet/following{/other_user}",
"gists_url": "https://api.github.com/users/gsmet/gists{/gist_id}",
"starred_url": "https://api.github.com/users/gsmet/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/gsmet/subscriptions",
"organizations_url": "https://api.github.com/users/gsmet/orgs",
"repos_url": "https://api.github.com/users/gsmet/repos",
"events_url": "https://api.github.com/users/gsmet/events{/privacy}",
"received_events_url": "https://api.github.com/users/gsmet/received_events",
"type": "User",
"site_admin": false
},
"installation": {
"id": 16779846,
"node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY3Nzk4NDY="
}
}

0 comments on commit e5fb0cd

Please sign in to comment.