Skip to content

Commit 6956922

Browse files
authored
Merge pull request hub4j#579 from martinvanzijl/issue_512_methods_to_update_milestones
Add methods to update and delete milestones.
2 parents d4ddf45 + 03edacf commit 6956922

20 files changed

Lines changed: 1119 additions & 1 deletion

src/main/java/org/kohsuke/github/GHMilestone.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,29 @@ public void reopen() throws IOException {
8585
edit("state", "open");
8686
}
8787

88+
/**
89+
* Deletes this milestone.
90+
*/
91+
public void delete() throws IOException {
92+
root.retrieve().method("DELETE").to(getApiRoute());
93+
}
94+
8895
private void edit(String key, Object value) throws IOException {
8996
new Requester(root)._with(key, value).method("PATCH").to(getApiRoute());
9097
}
9198

99+
public void setTitle(String title) throws IOException {
100+
edit("title", title);
101+
}
102+
103+
public void setDescription(String description) throws IOException {
104+
edit("description", description);
105+
}
106+
107+
public void setDueOn(Date dueOn) throws IOException {
108+
edit("due_on", GitHub.printDate(dueOn));
109+
}
110+
92111
protected String getApiRoute() {
93112
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/milestones/"+number;
94113
}

src/main/java/org/kohsuke/github/GitHub.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,9 @@ public Reader renderMarkdown(String text) throws IOException {
956956
}
957957

958958
/*package*/ static String printDate(Date dt) {
959-
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(dt);
959+
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
960+
df.setTimeZone(TimeZone.getTimeZone("GMT"));
961+
return df.format(dt);
960962
}
961963

962964
/*package*/ static final ObjectMapper MAPPER = new ObjectMapper();
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.kohsuke.github;
2+
3+
import org.junit.After;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
7+
import java.io.IOException;
8+
import java.util.Date;
9+
10+
/**
11+
* @author Martin van Zijl
12+
*/
13+
public class GHMilestoneTest extends AbstractGitHubWireMockTest {
14+
15+
@Before
16+
@After
17+
public void cleanUp() throws Exception {
18+
// Cleanup is only needed when proxying
19+
if (!mockGitHub.isUseProxy()) {
20+
return;
21+
}
22+
23+
for (GHMilestone milestone : getRepository(gitHubBeforeAfter).listMilestones(GHIssueState.ALL)) {
24+
if ("Original Title".equals(milestone.getTitle()) ||
25+
"Updated Title".equals(milestone.getTitle())) {
26+
milestone.delete();
27+
}
28+
}
29+
}
30+
31+
@Test
32+
public void testUpdateMilestone() throws Exception {
33+
GHRepository repo = getRepository();
34+
GHMilestone milestone = repo.createMilestone("Original Title",
35+
"To test the update methods");
36+
37+
String NEW_TITLE = "Updated Title";
38+
String NEW_DESCRIPTION = "Updated Description";
39+
Date NEW_DUE_DATE = GitHub.parseDate("2020-10-05T13:00:00Z");
40+
Date OUTPUT_DUE_DATE = GitHub.parseDate("2020-10-05T07:00:00Z");
41+
42+
milestone.setTitle(NEW_TITLE);
43+
milestone.setDescription(NEW_DESCRIPTION);
44+
milestone.setDueOn(NEW_DUE_DATE);
45+
46+
// Force reload.
47+
milestone = repo.getMilestone(milestone.getNumber());
48+
49+
assertEquals(NEW_TITLE, milestone.getTitle());
50+
assertEquals(NEW_DESCRIPTION, milestone.getDescription());
51+
52+
// The time is truncated when sent to the server, but still part of the returned value
53+
// 07:00 midnight PDT
54+
assertEquals(OUTPUT_DUE_DATE, milestone.getDueOn());
55+
}
56+
57+
protected GHRepository getRepository() throws IOException {
58+
return getRepository(gitHub);
59+
}
60+
61+
private GHRepository getRepository(GitHub gitHub) throws IOException {
62+
return gitHub.getOrganization("github-api-test-org").getRepository("github-api");
63+
}
64+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package org.kohsuke.github;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
6+
import java.text.SimpleDateFormat;
7+
import java.time.Instant;
8+
import java.time.temporal.ChronoUnit;
9+
import java.util.Date;
10+
import java.util.TimeZone;
11+
12+
import static org.hamcrest.CoreMatchers.equalTo;
13+
import static org.hamcrest.CoreMatchers.not;
14+
15+
/**
16+
* Unit test for {@link GitHub} static helpers.
17+
*
18+
* @author Liam Newman
19+
*/
20+
public class GitHubStaticTest extends Assert {
21+
22+
@Test
23+
public void timeRoundTrip() throws Exception {
24+
Instant instantNow = Instant.now();
25+
26+
Date instantSeconds = Date.from(instantNow.truncatedTo(ChronoUnit.SECONDS));
27+
Date instantMillis = Date.from(instantNow.truncatedTo(ChronoUnit.MILLIS));
28+
29+
// TODO: other formats
30+
String instantFormatSlash = formatDate(instantMillis, "yyyy/MM/dd HH:mm:ss ZZZZ");
31+
String instantFormatDash = formatDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss'Z'");
32+
String instantFormatMillis = formatDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.S'Z'");
33+
String instantSecondsFormatMillis = formatDate(instantSeconds, "yyyy-MM-dd'T'HH:mm:ss.S'Z'");
34+
String instantBadFormat = formatDate(instantMillis, "yy-MM-dd'T'HH:mm'Z'");
35+
36+
37+
assertThat(GitHub.parseDate(GitHub.printDate(instantSeconds)),
38+
equalTo(GitHub.parseDate(GitHub.printDate(instantMillis))));
39+
40+
assertThat(instantSeconds,
41+
equalTo(GitHub.parseDate(GitHub.printDate(instantSeconds))));
42+
43+
assertThat(instantMillis,
44+
not(equalTo(GitHub.parseDate(GitHub.printDate(instantMillis)))));
45+
46+
assertThat(instantSeconds,
47+
equalTo(GitHub.parseDate(instantFormatSlash)));
48+
49+
assertThat(instantSeconds,
50+
equalTo(GitHub.parseDate(instantFormatDash)));
51+
52+
assertThat(instantMillis,
53+
equalTo(GitHub.parseDate(instantFormatMillis)));
54+
55+
assertThat(instantSeconds,
56+
equalTo(GitHub.parseDate(instantSecondsFormatMillis)));
57+
58+
try {
59+
GitHub.parseDate(instantBadFormat);
60+
fail("Bad time format should throw.");
61+
} catch (IllegalStateException e) {
62+
assertThat(e.getMessage(), equalTo("Unable to parse the timestamp: " + instantBadFormat));
63+
}
64+
}
65+
66+
static String formatDate(Date dt, String format) {
67+
SimpleDateFormat df = new SimpleDateFormat(format);
68+
df.setTimeZone(TimeZone.getTimeZone("GMT"));
69+
return df.format(dt);
70+
}
71+
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"login": "github-api-test-org",
3+
"id": 7544739,
4+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=",
5+
"url": "https://api.github.com/orgs/github-api-test-org",
6+
"repos_url": "https://api.github.com/orgs/github-api-test-org/repos",
7+
"events_url": "https://api.github.com/orgs/github-api-test-org/events",
8+
"hooks_url": "https://api.github.com/orgs/github-api-test-org/hooks",
9+
"issues_url": "https://api.github.com/orgs/github-api-test-org/issues",
10+
"members_url": "https://api.github.com/orgs/github-api-test-org/members{/member}",
11+
"public_members_url": "https://api.github.com/orgs/github-api-test-org/public_members{/member}",
12+
"avatar_url": "https://avatars3.githubusercontent.com/u/7544739?v=4",
13+
"description": null,
14+
"is_verified": false,
15+
"has_organization_projects": true,
16+
"has_repository_projects": true,
17+
"public_repos": 10,
18+
"public_gists": 0,
19+
"followers": 0,
20+
"following": 0,
21+
"html_url": "https://github.com/github-api-test-org",
22+
"created_at": "2014-05-10T19:39:11Z",
23+
"updated_at": "2015-04-20T00:42:30Z",
24+
"type": "Organization",
25+
"total_private_repos": 0,
26+
"owned_private_repos": 0,
27+
"private_gists": 0,
28+
"disk_usage": 132,
29+
"collaborators": 0,
30+
"billing_email": "kk@kohsuke.org",
31+
"default_repository_permission": "none",
32+
"members_can_create_repositories": false,
33+
"two_factor_requirement_enabled": false,
34+
"plan": {
35+
"name": "free",
36+
"space": 976562499,
37+
"private_repos": 0,
38+
"filled_seats": 7,
39+
"seats": 0
40+
}
41+
}

0 commit comments

Comments
 (0)