Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.walmartlabs.concord.plugins.git.actions.ListCommitsAction;
import com.walmartlabs.concord.plugins.git.actions.ShortCommitShaAction;
import com.walmartlabs.concord.plugins.git.model.Auth;
import com.walmartlabs.concord.plugins.git.model.GitHubApiInfo;
Expand Down Expand Up @@ -173,6 +174,7 @@ public Map<String, Object> execute(Map<String, Object> in, Map<String, Object> d
case GETPRFILES -> getPRFiles(in, apiInfo);
case CREATEAPPTOKEN -> createAppToken(apiInfo);
case GETSHORTSHA -> new ShortCommitShaAction().execute(txId, apiInfo, VariablesGithubTaskParams.getShortSha(input));
case LISTCOMMITS -> new ListCommitsAction().execute(txId, apiInfo, VariablesGithubTaskParams.listCommits(input));
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* =====
*/

import java.util.regex.Pattern;

public sealed interface GitHubTaskParams {

record GetShortCommitSha(
Expand All @@ -29,4 +31,17 @@ record GetShortCommitSha(
int minLength
) implements GitHubTaskParams {
}

record ListCommits(
String org,
String repo,
String shaOrBranch,
String since,
String fromSha,
String toSha,
int pageSize,
int searchDepth,
Pattern filter
) implements GitHubTaskParams {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -21,11 +21,13 @@
*/

import com.walmartlabs.concord.runtime.v2.sdk.MapBackedVariables;
import com.walmartlabs.concord.runtime.v2.sdk.UserDefinedException;
import com.walmartlabs.concord.runtime.v2.sdk.Variables;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static com.walmartlabs.concord.plugins.git.GitHubTaskParams.*;
Expand Down Expand Up @@ -58,7 +60,8 @@ public enum Action {
DELETEREPO,
GETCONTENT,
CREATEAPPTOKEN,
GETSHORTSHA
GETSHORTSHA,
LISTCOMMITS
}

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

public static ListCommits listCommits(Variables variables) {
return new ListCommits(
assertOrg(variables),
assertRepo(variables),
variables.assertString("sha"),
variables.getString("since"),
variables.assertString("fromSha"),
variables.assertString("toSha"),
variables.getInt("pageSize", 100),
variables.getInt("searchDepth", 1000),
pattern(variables, "filter")
);
}

private static String assertOrg(Variables variables) {
return variables.assertString("org");
}

private static String assertRepo(Variables variables) {
return variables.assertString("repo");
}

private static Pattern pattern(Variables variables, String key) {
var str = variables.getString(key);
if (str == null) {
return null;
}
try {
return Pattern.compile(str);
} catch (Exception e) {
throw new UserDefinedException("Invalid '" + key + "' value: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.walmartlabs.concord.plugins.git.actions;

/*-
* *****
* Concord
* -----
* Copyright (C) 2017 - 2025 Walmart Inc., Concord Authors
* -----
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =====
*/

import com.walmartlabs.concord.common.ConfigurationUtils;
import com.walmartlabs.concord.plugins.git.GitHubTaskAction;
import com.walmartlabs.concord.plugins.git.GitHubTaskParams;
import com.walmartlabs.concord.plugins.git.client.GitHubClient;
import com.walmartlabs.concord.plugins.git.model.GitHubApiInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

public class ListCommitsAction extends GitHubTaskAction<GitHubTaskParams.ListCommits> {

private final static Logger log = LoggerFactory.getLogger(ListCommitsAction.class);

@Override
public Map<String, Object> execute(UUID txId, GitHubApiInfo apiInfo, GitHubTaskParams.ListCommits input) {
if (input.toSha().equals(input.fromSha())) {
return Map.of(
"commits", List.of(),
"filterMatches", List.of(),
"searchDepthReached", false);
}

var client = new GitHubClient(txId, apiInfo);
try {
var parameters = new HashMap<String, String>();
if (input.shaOrBranch() != null) {
parameters.put("sha", input.shaOrBranch());
}
if (input.since() != null) {
parameters.put("since", input.since());
}

var resultCommits = new ArrayList<Map<String, Object>>();
var filterMatches = new ArrayList<String>();

var counted = new AtomicInteger(0);
var started = new AtomicBoolean(false);
var shouldStop = new AtomicBoolean(false);

client.forEachPage("/repos/" + input.org() + "/" + input.repo() + "/commits", parameters, input.pageSize(), commits -> {
for (var commit : commits) {
var sha = commit.get("sha");

if (input.toSha().equals(sha)) {
started.set(true);
}
if (input.fromSha().equals(sha) || counted.get() >= input.searchDepth()) {
shouldStop.set(true);
break;
}

if (started.get()) {
processCommit(commit, input.filter(), resultCommits, filterMatches);
}
counted.incrementAndGet();
}

return !shouldStop.get();
});

log.info("✅ Loaded {} commits in '{}/{}' since '{}': ('{}', '{}']",
resultCommits.size(), input.org(), input.repo(), input.since(), input.fromSha(), input.toSha());

return Map.of(
"commits", resultCommits,
"filterMatches", filterMatches,
"searchDepthReached", counted.get() >= input.searchDepth());
} catch (Exception e) {
log.error("❌ Failed to list commits '{}/{}' since '{}'", input.org(), input.repo(), input.since(), e);
throw new RuntimeException(" Failed to list commits: " + e.getMessage());
}
}

private static void processCommit(Map<String, Object> commit, Pattern filter, List<Map<String, Object>> commits, List<String> filterMatches) {
if (filter == null) {
commits.add(commit);
return;
}

var message = (String)ConfigurationUtils.get(commit, "commit", "message");
if (message == null) {
return;
}

var matcher = filter.matcher(message);
if (matcher.matches()) {
commits.add(commit);
if (matcher.groupCount() > 0) {
var match = matcher.group(1);
if (match != null) {
filterMatches.add(match.trim());
}
}
}
}
}
Loading