Skip to content

Commit 25f48f4

Browse files
authored
git-tasks: add list commits action to GitHub task (#209)
1 parent 1a34849 commit 25f48f4

File tree

8 files changed

+454
-28
lines changed

8 files changed

+454
-28
lines changed

tasks/git/src/main/java/com/walmartlabs/concord/plugins/git/GitHubTask.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import com.fasterxml.jackson.core.type.TypeReference;
2424
import com.fasterxml.jackson.databind.ObjectMapper;
25+
import com.walmartlabs.concord.plugins.git.actions.ListCommitsAction;
2526
import com.walmartlabs.concord.plugins.git.actions.ShortCommitShaAction;
2627
import com.walmartlabs.concord.plugins.git.model.Auth;
2728
import com.walmartlabs.concord.plugins.git.model.GitHubApiInfo;
@@ -173,6 +174,7 @@ public Map<String, Object> execute(Map<String, Object> in, Map<String, Object> d
173174
case GETPRFILES -> getPRFiles(in, apiInfo);
174175
case CREATEAPPTOKEN -> createAppToken(apiInfo);
175176
case GETSHORTSHA -> new ShortCommitShaAction().execute(txId, apiInfo, VariablesGithubTaskParams.getShortSha(input));
177+
case LISTCOMMITS -> new ListCommitsAction().execute(txId, apiInfo, VariablesGithubTaskParams.listCommits(input));
176178
};
177179
}
178180

tasks/git/src/main/java/com/walmartlabs/concord/plugins/git/GitHubTaskParams.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* =====
2121
*/
2222

23+
import java.util.regex.Pattern;
24+
2325
public sealed interface GitHubTaskParams {
2426

2527
record GetShortCommitSha(
@@ -29,4 +31,17 @@ record GetShortCommitSha(
2931
int minLength
3032
) implements GitHubTaskParams {
3133
}
34+
35+
record ListCommits(
36+
String org,
37+
String repo,
38+
String shaOrBranch,
39+
String since,
40+
String fromSha,
41+
String toSha,
42+
int pageSize,
43+
int searchDepth,
44+
Pattern filter
45+
) implements GitHubTaskParams {
46+
}
3247
}

tasks/git/src/main/java/com/walmartlabs/concord/plugins/git/VariablesGithubTaskParams.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
* Licensed under the Apache License, Version 2.0 (the "License");
1010
* you may not use this file except in compliance with the License.
1111
* You may obtain a copy of the License at
12-
*
12+
*
1313
* http://www.apache.org/licenses/LICENSE-2.0
14-
*
14+
*
1515
* Unless required by applicable law or agreed to in writing, software
1616
* distributed under the License is distributed on an "AS IS" BASIS,
1717
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,11 +21,13 @@
2121
*/
2222

2323
import com.walmartlabs.concord.runtime.v2.sdk.MapBackedVariables;
24+
import com.walmartlabs.concord.runtime.v2.sdk.UserDefinedException;
2425
import com.walmartlabs.concord.runtime.v2.sdk.Variables;
2526

2627
import java.util.HashMap;
2728
import java.util.Map;
2829
import java.util.Objects;
30+
import java.util.regex.Pattern;
2931
import java.util.stream.Stream;
3032

3133
import static com.walmartlabs.concord.plugins.git.GitHubTaskParams.*;
@@ -58,7 +60,8 @@ public enum Action {
5860
DELETEREPO,
5961
GETCONTENT,
6062
CREATEAPPTOKEN,
61-
GETSHORTSHA
63+
GETSHORTSHA,
64+
LISTCOMMITS
6265
}
6366

6467
public static Variables merge(Map<String, Object> taskDefaults, Map<String, Object> input) {
@@ -78,11 +81,37 @@ public static GetShortCommitSha getShortSha(Variables variables) {
7881
variables.getInt("minLength", 7));
7982
}
8083

84+
public static ListCommits listCommits(Variables variables) {
85+
return new ListCommits(
86+
assertOrg(variables),
87+
assertRepo(variables),
88+
variables.assertString("sha"),
89+
variables.getString("since"),
90+
variables.assertString("fromSha"),
91+
variables.assertString("toSha"),
92+
variables.getInt("pageSize", 100),
93+
variables.getInt("searchDepth", 1000),
94+
pattern(variables, "filter")
95+
);
96+
}
97+
8198
private static String assertOrg(Variables variables) {
8299
return variables.assertString("org");
83100
}
84101

85102
private static String assertRepo(Variables variables) {
86103
return variables.assertString("repo");
87104
}
105+
106+
private static Pattern pattern(Variables variables, String key) {
107+
var str = variables.getString(key);
108+
if (str == null) {
109+
return null;
110+
}
111+
try {
112+
return Pattern.compile(str);
113+
} catch (Exception e) {
114+
throw new UserDefinedException("Invalid '" + key + "' value: " + e.getMessage());
115+
}
116+
}
88117
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package com.walmartlabs.concord.plugins.git.actions;
2+
3+
/*-
4+
* *****
5+
* Concord
6+
* -----
7+
* Copyright (C) 2017 - 2025 Walmart Inc., Concord Authors
8+
* -----
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* =====
21+
*/
22+
23+
import com.walmartlabs.concord.common.ConfigurationUtils;
24+
import com.walmartlabs.concord.plugins.git.GitHubTaskAction;
25+
import com.walmartlabs.concord.plugins.git.GitHubTaskParams;
26+
import com.walmartlabs.concord.plugins.git.client.GitHubClient;
27+
import com.walmartlabs.concord.plugins.git.model.GitHubApiInfo;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
31+
import java.util.*;
32+
import java.util.concurrent.atomic.AtomicBoolean;
33+
import java.util.concurrent.atomic.AtomicInteger;
34+
import java.util.regex.Pattern;
35+
36+
public class ListCommitsAction extends GitHubTaskAction<GitHubTaskParams.ListCommits> {
37+
38+
private final static Logger log = LoggerFactory.getLogger(ListCommitsAction.class);
39+
40+
@Override
41+
public Map<String, Object> execute(UUID txId, GitHubApiInfo apiInfo, GitHubTaskParams.ListCommits input) {
42+
if (input.toSha().equals(input.fromSha())) {
43+
return Map.of(
44+
"commits", List.of(),
45+
"filterMatches", List.of(),
46+
"searchDepthReached", false);
47+
}
48+
49+
var client = new GitHubClient(txId, apiInfo);
50+
try {
51+
var parameters = new HashMap<String, String>();
52+
if (input.shaOrBranch() != null) {
53+
parameters.put("sha", input.shaOrBranch());
54+
}
55+
if (input.since() != null) {
56+
parameters.put("since", input.since());
57+
}
58+
59+
var resultCommits = new ArrayList<Map<String, Object>>();
60+
var filterMatches = new ArrayList<String>();
61+
62+
var counted = new AtomicInteger(0);
63+
var started = new AtomicBoolean(false);
64+
var shouldStop = new AtomicBoolean(false);
65+
66+
client.forEachPage("/repos/" + input.org() + "/" + input.repo() + "/commits", parameters, input.pageSize(), commits -> {
67+
for (var commit : commits) {
68+
var sha = commit.get("sha");
69+
70+
if (input.toSha().equals(sha)) {
71+
started.set(true);
72+
}
73+
if (input.fromSha().equals(sha) || counted.get() >= input.searchDepth()) {
74+
shouldStop.set(true);
75+
break;
76+
}
77+
78+
if (started.get()) {
79+
processCommit(commit, input.filter(), resultCommits, filterMatches);
80+
}
81+
counted.incrementAndGet();
82+
}
83+
84+
return !shouldStop.get();
85+
});
86+
87+
log.info("✅ Loaded {} commits in '{}/{}' since '{}': ('{}', '{}']",
88+
resultCommits.size(), input.org(), input.repo(), input.since(), input.fromSha(), input.toSha());
89+
90+
return Map.of(
91+
"commits", resultCommits,
92+
"filterMatches", filterMatches,
93+
"searchDepthReached", counted.get() >= input.searchDepth());
94+
} catch (Exception e) {
95+
log.error("❌ Failed to list commits '{}/{}' since '{}'", input.org(), input.repo(), input.since(), e);
96+
throw new RuntimeException(" Failed to list commits: " + e.getMessage());
97+
}
98+
}
99+
100+
private static void processCommit(Map<String, Object> commit, Pattern filter, List<Map<String, Object>> commits, List<String> filterMatches) {
101+
if (filter == null) {
102+
commits.add(commit);
103+
return;
104+
}
105+
106+
var message = (String)ConfigurationUtils.get(commit, "commit", "message");
107+
if (message == null) {
108+
return;
109+
}
110+
111+
var matcher = filter.matcher(message);
112+
if (matcher.matches()) {
113+
commits.add(commit);
114+
if (matcher.groupCount() > 0) {
115+
var match = matcher.group(1);
116+
if (match != null) {
117+
filterMatches.add(match.trim());
118+
}
119+
}
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)