Skip to content
Snippets Groups Projects
Commit e52a3d37 authored by Wayne Beaton's avatar Wayne Beaton
Browse files

Add a means of deciding whether or not a repository is interesting.

parent f3c47be4
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,22 @@ The Eclipse Project Code Review Creator creates IP review requests in IPLab for
This tool identifies projects for which we are waiting for an initial contribution. An initial contribution takes the form of a new Git repository being identified in the project's metadata. When the tool encounters a Git repository that it hasn't seen before, it creates a review request record in IPLab with a pointer to the contents of the top commit in the default branch of the repository and then links that IPLab record to the issue being used by the EMO to track the project creation process.
This tool will only create a review for a repository when:
* It is not archived;
* It is not empty; and
* It is "interesting".
The current implementation checks _only the root_ of each repository and decides that a repository is interesting when it at least one file with a name that:
* does not start with a a dot;
* is not "otterdog"; and
* the name (not including the extension) entirely upper case.
The rules rely on file names that follow certain conventions. A file named "README.md" would not be considered interesting, but "Readme.md" (because it is not entirely upper case) would be considered interesting. Note that the test is more that the name part of the files does not contain any lower case characters (e.g., "EPL-2.0.txt" is not considered interesting despite having characters that are neither upper or lower case).
A file/directory named, for example, "doc" would be considered interesting.
This is a bit of a prototype/experiment. This implementation is neither complete, nor is it particularly robust. In its current form, it provides exactly what we need and nothing more.
## License
......
......@@ -15,6 +15,7 @@ import java.util.stream.Stream;
import jakarta.inject.Inject;
import org.eclipse.dash.api.SourceRepository;
import org.kohsuke.github.GHContent;
import org.kohsuke.github.GHLicense;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
......@@ -58,10 +59,11 @@ public class GitHubService {
@Override
public boolean isEmpty() {
try {
return repository.getBranches().isEmpty();
if (repository.getBranches().isEmpty()) return true;
} catch (IOException e) {
throw new RuntimeException(e);
}
return false;
}
@Override
......@@ -127,5 +129,50 @@ public class GitHubService {
public boolean isArchived() {
return repository.isArchived();
}
@Override
public boolean hasPotentiallyInterestingContent() {
if (isEmpty()) return false;
try {
repository.getDirectoryContent(".").stream().anyMatch(each -> isPotentiallyInterestingContent(each));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
boolean isPotentiallyInterestingContent(GHContent content) {
if (content.isDirectory()) {
return isPotentiallyInterestingDirectory(content);
} else {
return isPotentiallyInterestingFile(content);
}
}
/**
* This method answers whether or not the file is potentially interesting. Any
* file with a name that starts with a dot or is entirely upper case (except in
* the file extension) is assumed to be a metadata file (e.g., "README.md") and
* not considered interesting. Everything else is potentially interesting.
*/
boolean isPotentiallyInterestingFile(GHContent content) {
var name = content.getName();
if (name.startsWith(".")) return false;
var last = name.lastIndexOf('.');
if (last > 0) name = name.substring(0, last);
return !name.chars().allMatch(each -> !Character.isLowerCase(each));
}
boolean isPotentiallyInterestingDirectory(GHContent content) {
if (content.getName().startsWith(".")) return false;
if (content.getName().equals("otterdog")) return false;
return true;
}
}
}
......@@ -14,6 +14,7 @@ import java.util.stream.Stream;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.TreeItem;
import jakarta.inject.Inject;
......@@ -69,6 +70,28 @@ public class GitLabService {
throw new RuntimeException(e);
}
}
@Override
public boolean hasPotentiallyInterestingContent() {
if (isEmpty()) return false;
try {
return api.getRepositoryApi().getTree(repository.getId(), ".", null).stream().anyMatch(each -> isPotentiallyInterestingFile(each));
} catch (GitLabApiException e) {
throw new RuntimeException(e);
}
}
boolean isPotentiallyInterestingFile(TreeItem content) {
var name = content.getName();
System.out.println(name);
if (name.startsWith(".")) return false;
var last = name.lastIndexOf('.');
if (last > 0) name = name.substring(0, last);
return !name.chars().allMatch(each -> !Character.isLowerCase(each));
}
@Override
public String getDefaultBranch() {
......
......@@ -33,4 +33,8 @@ public interface IRepository {
boolean isArchived();
default boolean hasPotentiallyInterestingContent() {
return false;
};
}
......@@ -54,7 +54,7 @@ public class ReviewTaskFinder {
try {
IssueFilter filter = new IssueFilter()
.withState(IssueState.OPENED)
.withLabels(Collections.singletonList("EDP::Initial Contribution"));
.withLabels(Arrays.asList("EDP::Initial Contribution", "IP review"));
return gitlabApi.getIssuesApi()
.getIssuesStream(InitialContributionProcess.getEmoProjectPath(), filter)
.map(each -> createInitialContributionTaskFromProjectId(each, getProjectId(each)))
......@@ -204,7 +204,11 @@ public class ReviewTaskFinder {
var review = getExisting();
if (review == null) {
if (!repository.isEmpty()) {
review = createReview();
if (repository.hasPotentiallyInterestingContent()) {
review = createReview();
} else {
logger.info("Did not create a review; repository doesn't look interesting {}", repository.getWebUrl());
}
} else {
logger.info("Did not create a review; repository is empty {}", repository.getWebUrl());
return;
......@@ -227,7 +231,7 @@ public class ReviewTaskFinder {
.replace("{name}", repository.getName());
try {
IssueFilter filter = new IssueFilter().withLabels(Arrays.asList(new String[]{"Project Content","Initial Contribution"}));
IssueFilter filter = new IssueFilter().withLabels(Arrays.asList(getSearchLabels()));
return gitlabApi.getIssuesApi()
.getIssuesStream(InitialContributionProcess.getIPLabPath(), filter)
.filter(issue -> issue.getTitle().startsWith(match))
......@@ -236,6 +240,10 @@ public class ReviewTaskFinder {
throw new RuntimeException(e);
}
}
String[] getSearchLabels() {
return new String[]{"Project Content","Initial Contribution"};
}
}
abstract class CreateRepositoryReview {
......@@ -253,8 +261,12 @@ public class ReviewTaskFinder {
public void createAndLinkReview() {
logger.info("Setting up review for {}", repository.getWebUrl());
if (!repository.isEmpty()) {
Issue review = createReview();
linkReview(review);
if (repository.hasPotentiallyInterestingContent()) {
Issue review = createReview();
linkReview(review);
} else {
logger.info("Did not create a review; repository doesn't look interesting {}", repository.getWebUrl());
}
} else {
logger.info("Did not create a review; repository is empty {}", repository.getWebUrl());
return;
......@@ -380,7 +392,11 @@ public class ReviewTaskFinder {
var review = getExisting();
if (review == null) {
if (!repository.isEmpty()) {
review = createReview();
if (repository.hasPotentiallyInterestingContent()) {
review = createReview();
} else {
logger.info("Did not create a review; repository doesn't look interesting {}", repository.getWebUrl());
}
} else {
logger.info("Did not create a review; repository is empty {}", repository.getWebUrl());
return;
......@@ -400,7 +416,7 @@ public class ReviewTaskFinder {
.replace("{sha}", repository.getTopCommitSha());
try {
IssueFilter filter = new IssueFilter().withLabels(Arrays.asList(new String[]{"Project Content"}));
IssueFilter filter = new IssueFilter().withLabels(Arrays.asList(new String[]{"Project Content", "Initial Contribution"}));
return gitlabApi.getIssuesApi()
.getIssuesStream(InitialContributionProcess.getIPLabPath(), filter)
.filter(issue -> issue.getTitle().equals(match))
......
package org.eclipse.dash.ip.project.code;
import static org.junit.jupiter.api.Assertions.*;
import org.eclipse.dash.api.EclipseApi;
import org.eclipse.dash.ip.project.code.context.ProjectCodeReviewModule;
import org.junit.jupiter.api.Test;
......@@ -43,4 +41,14 @@ class TaskFinderTests {
gitlab.getProjects("eclipse/xfsc").forEach(each -> System.out.println(each.getNameWithNamespace()));
}
@Test
void test4() {
Injector injector = Guice.createInjector(new ProjectCodeReviewModule());
var gitlab = injector.getInstance(GitLabService.class);
gitlab.getRepositories("eclipse/xfsc").forEach(each -> System.out.println(each.getBrowseUrl() + " => " + each.hasPotentiallyInterestingContent()));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment