Skip to content

Commit

Permalink
Simplify file matching to not distinguish between files and directories
Browse files Browse the repository at this point in the history
  • Loading branch information
holly-cummins committed Aug 25, 2022
1 parent 2c3bbae commit edda867
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 87 deletions.
12 changes: 5 additions & 7 deletions README.adoc
Expand Up @@ -210,24 +210,22 @@ workflows:
- allow:
directories:
- ./src
- ./documentation
files:
- README.md
- ./doc*
- "**/README.md"
users:
minContributions: 5
unless:
directories:
- ./github
files:
- bad.xml
- ./.github
- "**/pom.xml"
----

Workflows will be allowed if they meet one of the rules in the `allow` section,
unless one of the rules in the `unless` section is triggered.

In the example above, any file called `README.md` would be allowed, except for `./github/README.md`.
Users who had made at least 5 commits to the repository would be allowed to make any changes,
except to `bad.xml` and any files in `.github`. Other users could make changes to `./src` or `./documentation`.
except to a `pom.xml` or any files in `.github`. Other users could make changes to `./src` or directories whose name started with `./doc`.

If the rule is triggered, the following actions will be executed:

Expand Down
30 changes: 2 additions & 28 deletions src/main/java/io/quarkus/bot/ApproveWorkflow.java
Expand Up @@ -132,38 +132,12 @@ public static boolean matchRuleFromChangedFiles(GHPullRequest pullRequest,
return false;
}

boolean matches = false;

PullRequestFilesMatcher prMatcher = new PullRequestFilesMatcher(pullRequest);
if (matchDirectories(prMatcher, rule)) {
matches = true;
} else if (matchFiles(prMatcher, rule)) {
matches = true;
}

return matches;
}

private static boolean matchDirectories(PullRequestFilesMatcher prMatcher,
QuarkusGitHubBotConfigFile.WorkflowApprovalCondition rule) {
if (rule.directories == null || rule.directories.isEmpty()) {
return false;
}
if (prMatcher.changedFilesMatchDirectory(rule.directories)) {
return true;
}
return false;
}

private static boolean matchFiles(PullRequestFilesMatcher prMatcher,
QuarkusGitHubBotConfigFile.WorkflowApprovalCondition rule) {
if (rule.files == null || rule.files.isEmpty()) {
return false;
}
if (prMatcher.changedFilesMatchFile(rule.files)) {
return true;
}
return false;
PullRequestFilesMatcher prMatcher = new PullRequestFilesMatcher(pullRequest);
return prMatcher.changedFilesMatch(rule.directories);
}

private boolean matchRuleForUser(GHRepositoryStatistics.ContributorStats stats,
Expand Down
61 changes: 20 additions & 41 deletions src/main/java/io/quarkus/bot/util/PullRequestFilesMatcher.java
Expand Up @@ -2,6 +2,7 @@

import com.hrakaroo.glob.GlobPattern;
import com.hrakaroo.glob.MatchingEngine;
import io.quarkus.cache.CacheResult;
import org.jboss.logging.Logger;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GHPullRequestFileDetail;
Expand All @@ -19,56 +20,34 @@ public PullRequestFilesMatcher(GHPullRequest pullRequest) {
this.pullRequest = pullRequest;
}

public boolean changedFilesMatchDirectory(Collection<String> directories) {
for (GHPullRequestFileDetail changedFile : pullRequest.listFiles()) {
for (String directory : directories) {
public boolean changedFilesMatch(Collection<String> filenamePatterns) {
PagedIterable<GHPullRequestFileDetail> prFiles = pullRequest.listFiles();
if (prFiles != null) {
for (GHPullRequestFileDetail changedFile : prFiles) {
for (String filenamePattern : filenamePatterns) {

if (!directory.contains("*")) {
if (changedFile.getFilename().startsWith(directory)) {
return true;
}
} else {
try {
MatchingEngine matchingEngine = GlobPattern.compile(directory);
if (matchingEngine.matches(changedFile.getFilename())) {
if (!filenamePattern.contains("*")) {
if (changedFile.getFilename().startsWith(filenamePattern)) {
return true;
}
} catch (Exception e) {
LOG.error("Error evaluating glob expression: " + directory, e);
} else {
try {
MatchingEngine matchingEngine = compileGlob(filenamePattern);
if (matchingEngine.matches(changedFile.getFilename())) {
return true;
}
} catch (Exception e) {
LOG.error("Error evaluating glob expression: " + filenamePattern, e);
}
}
}
}
}
return false;
}

public boolean changedFilesMatchFile(Collection<String> files) {

PagedIterable<GHPullRequestFileDetail> prFiles = pullRequest.listFiles();

if (prFiles == null || files == null) {
return false;
}

for (GHPullRequestFileDetail changedFile : prFiles) {
for (String file : files) {

if (!file.contains("*")) {
if (changedFile.getFilename().endsWith(file)) {
return true;
}
} else {
try {
MatchingEngine matchingEngine = GlobPattern.compile(file);
if (matchingEngine.matches(changedFile.getFilename())) {
return true;
}
} catch (Exception e) {
LOG.error("Error evaluating glob expression: " + file, e);
}
}
}
}
return false;
@CacheResult(cacheName = "glob-cache")
MatchingEngine compileGlob(String filenamePattern) {
return GlobPattern.compile(filenamePattern);
}
}
2 changes: 1 addition & 1 deletion src/main/java/io/quarkus/bot/util/Triage.java
Expand Up @@ -83,7 +83,7 @@ public static boolean matchRuleFromChangedFiles(GHPullRequest pullRequest, Triag
}

PullRequestFilesMatcher prMatcher = new PullRequestFilesMatcher(pullRequest);
if (prMatcher.changedFilesMatchDirectory(rule.directories)) {
if (prMatcher.changedFilesMatch(rule.directories)) {
return true;
}

Expand Down
20 changes: 10 additions & 10 deletions src/test/java/io/quarkus/bot/it/WorkflowApprovalTest.java
Expand Up @@ -213,8 +213,8 @@ void changeToAnAllowedFileShouldBeApproved() throws Exception {
workflows:
rules:
- allow:
files:
- pom.xml
directories:
- "**/pom.xml"
""");
setupMockQueriesAndCommits(mocks);
PagedIterable<GHPullRequestFileDetail> paths = MockHelper
Expand Down Expand Up @@ -242,8 +242,8 @@ void changeToAFileInAnAllowedDirectoryWithAnIrrelevantUnlessShouldBeAllowed() th
directories:
- ./src
unless:
files:
- bad.xml
directories:
- "**/bad.xml"
""");
setupMockQueriesAndCommits(mocks);
PagedIterable<GHPullRequestFileDetail> paths = MockHelper
Expand Down Expand Up @@ -271,8 +271,8 @@ void changeToAnUnlessedFileInAnAllowedDirectoryShouldBeSoftRejected() throws Exc
directories:
- ./src
unless:
files:
- bad.xml
directories:
- "**/bad.xml"
""");
setupMockQueriesAndCommits(mocks);
PagedIterable<GHPullRequestFileDetail> paths = MockHelper
Expand Down Expand Up @@ -375,8 +375,8 @@ void changeFromAnEstablishedUserToADangerousFileShouldBeSoftRejected() throws Ex
users:
minContributions: 5
unless:
files:
- bad.xml
directories:
- "**/bad.xml"
""");
setupMockQueriesAndCommits(mocks);
setupMockUsers(mocks);
Expand Down Expand Up @@ -405,8 +405,8 @@ void workflowIsPreApprovedShouldDoNothing() throws Exception {
directories:
- ./src
unless:
files:
- bad.xml
directories:
- "**/bad.xml"
"""))
.when().payloadFromClasspath("/workflow-from-committer.json")
.event(GHEvent.WORKFLOW_RUN)
Expand Down

0 comments on commit edda867

Please sign in to comment.