Skip to content

Commit 5d1233f

Browse files
committed
Merge branch '__rultor'
2 parents 7a4abb5 + 5980129 commit 5d1233f

File tree

4 files changed

+253
-10
lines changed

4 files changed

+253
-10
lines changed

src/jekyll/_posts/2014/jul/2014-07-07-index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ with an easy-to-use intuitive interface:
2020

2121
To start working with Rultor, all you need to do
2222
is give him [commands]({% post_url 2014/jul/2014-07-14-commands %})
23-
via one of your Github tickets.
23+
via one of your Github issue or pull request.
2424
Try a simple `@rultor hello` and see how it works.
2525

2626
Rultor is not a replacement, but rather a powerful addition
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2009-2024 Yegor Bugayenko
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met: 1) Redistributions of source code must retain the above
8+
* copyright notice, this list of conditions and the following
9+
* disclaimer. 2) Redistributions in binary form must reproduce the above
10+
* copyright notice, this list of conditions and the following
11+
* disclaimer in the documentation and/or other materials provided
12+
* with the distribution. 3) Neither the name of the rultor.com nor
13+
* the names of its contributors may be used to endorse or promote
14+
* products derived from this software without specific prior written
15+
* permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19+
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21+
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28+
* OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.rultor.agents.github;
31+
32+
import com.jcabi.aspects.Immutable;
33+
import java.util.regex.Matcher;
34+
import java.util.regex.Pattern;
35+
import lombok.EqualsAndHashCode;
36+
import lombok.ToString;
37+
38+
/**
39+
* GitHub URL for Issue.
40+
*
41+
* @since 2.0
42+
*/
43+
@Immutable
44+
@ToString
45+
@EqualsAndHashCode(of = "url")
46+
@SuppressWarnings("PMD.ConstructorShouldDoInitialization")
47+
final class IssueUrl {
48+
49+
/**
50+
* Pattern for issue Url.
51+
*/
52+
private final Pattern correct =
53+
Pattern.compile(".*/(?:issues|pull)/(\\d+)(?:/|$).*");
54+
55+
/**
56+
* Url.
57+
*/
58+
private final String url;
59+
60+
/**
61+
* Ctor.
62+
* @param url Issue url.
63+
*/
64+
@SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors")
65+
IssueUrl(final String url) {
66+
if (url == null || url.isEmpty()) {
67+
throw new IllegalArgumentException("URL should not be empty");
68+
}
69+
this.url = url;
70+
}
71+
72+
/**
73+
* Get issue id from url.
74+
* @return Issue id
75+
* @checkstyle MethodNameCheck (10 lines)
76+
*/
77+
@SuppressWarnings("PMD.ShortMethodName")
78+
public int id() {
79+
final Matcher matcher = this.correct.matcher(this.url);
80+
if (matcher.matches()) {
81+
return Integer.parseInt(matcher.group(1));
82+
}
83+
throw new IllegalStateException(
84+
String.format("Url %s is not valid issue url", this.url)
85+
);
86+
}
87+
88+
/**
89+
* Check if url is a valid url for Issue.
90+
* @return True if valid
91+
*/
92+
public boolean valid() {
93+
return this.correct.matcher(this.url).matches();
94+
}
95+
}

src/main/java/com/rultor/agents/github/StartsTalks.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,19 @@
4949
import javax.json.JsonObject;
5050
import lombok.EqualsAndHashCode;
5151
import lombok.ToString;
52-
import org.apache.commons.lang3.StringUtils;
5352
import org.apache.commons.lang3.time.DateUtils;
5453
import org.xembly.Directives;
5554

5655
/**
5756
* Starts talk when I'm mentioned in a Github issue.
5857
*
5958
* @since 1.0
59+
* @todo #1074:1h Current implementation can answer only for
60+
* issue and PR comments, mostly because of Issue structure
61+
* from jcabi-github (id is integer). For now mentions NOT
62+
* from issue or PR will be ignored. Can be extended if
63+
* more generic entity will be created to cover commits
64+
* and may be other types.
6065
*/
6166
@Immutable
6267
@ToString
@@ -93,8 +98,11 @@ public void execute(final Talks talks) throws IOException {
9398
);
9499
final Collection<String> names = new LinkedList<>();
95100
for (final JsonObject event : events) {
96-
final String reason = event.getString("reason");
97-
if ("mention".equals(reason)) {
101+
if ("mention".equals(event.getString("reason"))
102+
&& new IssueUrl(
103+
event.getJsonObject("subject").getString("url")
104+
).valid()
105+
) {
98106
names.add(this.activate(talks, event));
99107
}
100108
}
@@ -122,12 +130,7 @@ private String activate(final Talks talks, final JsonObject event)
122130
throws IOException {
123131
final Coordinates coords = this.coords(event);
124132
final Issue issue = this.github.repos().get(coords).issues().get(
125-
Integer.parseInt(
126-
StringUtils.substringAfterLast(
127-
event.getJsonObject("subject").getString("url"),
128-
"/"
129-
)
130-
)
133+
new IssueUrl(event.getJsonObject("subject").getString("url")).id()
131134
);
132135
final String name = String.format("%s#%d", coords, issue.number());
133136
if (!talks.exists(name)) {
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright (c) 2009-2024 Yegor Bugayenko
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met: 1) Redistributions of source code must retain the above
8+
* copyright notice, this list of conditions and the following
9+
* disclaimer. 2) Redistributions in binary form must reproduce the above
10+
* copyright notice, this list of conditions and the following
11+
* disclaimer in the documentation and/or other materials provided
12+
* with the distribution. 3) Neither the name of the rultor.com nor
13+
* the names of its contributors may be used to endorse or promote
14+
* products derived from this software without specific prior written
15+
* permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19+
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21+
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28+
* OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.rultor.agents.github;
31+
32+
import org.hamcrest.MatcherAssert;
33+
import org.hamcrest.Matchers;
34+
import org.junit.jupiter.api.Assertions;
35+
import org.junit.jupiter.api.Test;
36+
37+
/**
38+
* Tests for ${@link IssueUrl}.
39+
*
40+
* @since 2.0
41+
*/
42+
final class IssueUrlTest {
43+
@Test
44+
void pullRequestUrlShouldBeValid() {
45+
final IssueUrl issue =
46+
new IssueUrl("https://api.github.com/repos/USER/REPO/pull/5086");
47+
MatcherAssert.assertThat(
48+
issue.valid(),
49+
Matchers.is(true)
50+
);
51+
}
52+
53+
@Test
54+
void pullRequestReviewUrlShouldBeValid() {
55+
final IssueUrl issue = new IssueUrl(
56+
"https://api.github.com/repos/USER/REPO/pull/5386/files#r123"
57+
);
58+
MatcherAssert.assertThat(
59+
issue.valid(),
60+
Matchers.is(true)
61+
);
62+
}
63+
64+
@Test
65+
void issueUrlShouldBeValid() {
66+
final IssueUrl issue = new IssueUrl(
67+
"https://api.github.com/repos/USER/REPO/issues/5182"
68+
);
69+
MatcherAssert.assertThat(
70+
issue.valid(),
71+
Matchers.is(true)
72+
);
73+
}
74+
75+
@Test
76+
void commitUrlShouldBeNotValid() {
77+
final IssueUrl issue = new IssueUrl(
78+
"https://api.github.com/repos/USER/REPO/commit/2a1f8"
79+
);
80+
MatcherAssert.assertThat(
81+
issue.valid(),
82+
Matchers.is(false)
83+
);
84+
}
85+
86+
@Test
87+
void pullRequestIdShouldBeReturned() {
88+
final IssueUrl issue = new IssueUrl(
89+
"https://api.github.com/repos/USER/REPO/pull/5186"
90+
);
91+
MatcherAssert.assertThat(
92+
issue.id(),
93+
Matchers.is(5186)
94+
);
95+
}
96+
97+
@Test
98+
void issueIdShouldBeReturned() {
99+
final IssueUrl issue = new IssueUrl(
100+
"https://api.github.com/repos/USER/REPO/issues/5782"
101+
);
102+
MatcherAssert.assertThat(
103+
issue.id(),
104+
Matchers.is(5782)
105+
);
106+
}
107+
108+
@Test
109+
void pullRequestIdFromReviewUrlShouldBeValid() {
110+
final IssueUrl issue = new IssueUrl(
111+
"https://api.github.com/repos/USER/REPO/pull/5886/files#r123"
112+
);
113+
MatcherAssert.assertThat(
114+
issue.id(),
115+
Matchers.is(5886)
116+
);
117+
}
118+
119+
@Test
120+
void commitIdShouldNotBeReturned() {
121+
final IssueUrl issue = new IssueUrl(
122+
"https://api.github.com/repos/USER/REPO/commit/2a4f8"
123+
);
124+
Assertions.assertThrows(
125+
IllegalStateException.class,
126+
issue::id
127+
);
128+
}
129+
130+
@Test
131+
void urlShouldNotBeEmpty() {
132+
Assertions.assertThrows(
133+
IllegalArgumentException.class,
134+
() -> new IssueUrl("")
135+
);
136+
}
137+
138+
@Test
139+
void urlShouldNotBeNull() {
140+
Assertions.assertThrows(
141+
IllegalArgumentException.class,
142+
() -> new IssueUrl(null)
143+
);
144+
}
145+
}

0 commit comments

Comments
 (0)