CheckCodeOwner: Handle files owned by all users
If a file was owned by all users, it was incorrectly reported as not
owned by any user. Fix this and also add a new field in the response to
explicitly let the caller know that the file is owned by all users.
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I808f71f2817965ab83ef6517bab3989a1e540dc8
diff --git a/java/com/google/gerrit/plugins/codeowners/api/CodeOwnerCheckInfo.java b/java/com/google/gerrit/plugins/codeowners/api/CodeOwnerCheckInfo.java
index ec3cb4f..c22449d 100644
--- a/java/com/google/gerrit/plugins/codeowners/api/CodeOwnerCheckInfo.java
+++ b/java/com/google/gerrit/plugins/codeowners/api/CodeOwnerCheckInfo.java
@@ -83,6 +83,9 @@
*/
public boolean isGlobalCodeOwner;
+ /** Whether the the specified path in the branch is owned by all users (aka {@code *}). */
+ public boolean isOwnedByAllUsers;
+
/** Debug logs that may help to understand why the user is or isn't a code owner. */
public List<String> debugLogs;
}
diff --git a/java/com/google/gerrit/plugins/codeowners/restapi/CheckCodeOwner.java b/java/com/google/gerrit/plugins/codeowners/restapi/CheckCodeOwner.java
index 9ab1ed1..64aa0dd 100644
--- a/java/com/google/gerrit/plugins/codeowners/restapi/CheckCodeOwner.java
+++ b/java/com/google/gerrit/plugins/codeowners/restapi/CheckCodeOwner.java
@@ -133,6 +133,7 @@
List<String> messages = new ArrayList<>();
List<Path> codeOwnerConfigFilePaths = new ArrayList<>();
AtomicBoolean isCodeOwnershipAssignedToEmail = new AtomicBoolean(false);
+ AtomicBoolean isCodeOwnershipAssignedToAllUsers = new AtomicBoolean(false);
AtomicBoolean isDefaultCodeOwner = new AtomicBoolean(false);
AtomicBoolean hasRevelantCodeOwnerDefinitions = new AtomicBoolean(false);
AtomicBoolean parentCodeOwnersAreIgnored = new AtomicBoolean(false);
@@ -159,7 +160,8 @@
pathCodeOwnersResult.get().getPathCodeOwners().stream()
.filter(cor -> cor.email().equals(email))
.findAny();
- if (codeOwnerReference.isPresent()) {
+ if (codeOwnerReference.isPresent()
+ && !CodeOwnerResolver.ALL_USERS_WILDCARD.equals(email)) {
isCodeOwnershipAssignedToEmail.set(true);
if (RefNames.isConfigRef(codeOwnerConfig.key().ref())) {
@@ -174,7 +176,31 @@
"found email %s as code owner in %s", email, codeOwnerConfigFilePath));
codeOwnerConfigFilePaths.add(codeOwnerConfigFilePath);
}
- } else if (codeOwnerResolverProvider
+ }
+
+ if (pathCodeOwnersResult.get().getPathCodeOwners().stream()
+ .anyMatch(cor -> cor.email().equals(CodeOwnerResolver.ALL_USERS_WILDCARD))) {
+ isCodeOwnershipAssignedToAllUsers.set(true);
+
+ if (RefNames.isConfigRef(codeOwnerConfig.key().ref())) {
+ messages.add(
+ String.format(
+ "found email %s as code owner in default code owner config",
+ CodeOwnerResolver.ALL_USERS_WILDCARD));
+ isDefaultCodeOwner.set(true);
+ } else {
+ Path codeOwnerConfigFilePath = codeOwners.getFilePath(codeOwnerConfig.key());
+ messages.add(
+ String.format(
+ "found email %s as code owner in %s",
+ CodeOwnerResolver.ALL_USERS_WILDCARD, codeOwnerConfigFilePath));
+ if (!codeOwnerConfigFilePaths.contains(codeOwnerConfigFilePath)) {
+ codeOwnerConfigFilePaths.add(codeOwnerConfigFilePath);
+ }
+ }
+ }
+
+ if (codeOwnerResolverProvider
.get()
.resolvePathCodeOwners(codeOwnerConfig, absolutePath)
.hasRevelantCodeOwnerDefinitions()) {
@@ -189,31 +215,46 @@
return !pathCodeOwnersResult.get().ignoreParentCodeOwners();
});
- boolean isGlobalCodeOwner = isGlobalCodeOwner(branchResource.getNameKey());
- if (isGlobalCodeOwner) {
+ boolean isGlobalCodeOwner = false;
+
+ if (isGlobalCodeOwner(branchResource.getNameKey(), email)) {
+ isGlobalCodeOwner = true;
messages.add(String.format("found email %s as global code owner", email));
isCodeOwnershipAssignedToEmail.set(true);
}
+ if (isGlobalCodeOwner(branchResource.getNameKey(), CodeOwnerResolver.ALL_USERS_WILDCARD)) {
+ isGlobalCodeOwner = true;
+ messages.add(
+ String.format(
+ "found email %s as global code owner", CodeOwnerResolver.ALL_USERS_WILDCARD));
+ isCodeOwnershipAssignedToAllUsers.set(true);
+ }
+
OptionalResultWithMessages<Boolean> isResolvableResult = isResolvable();
boolean isResolvable = isResolvableResult.get();
messages.addAll(isResolvableResult.messages());
boolean isFallbackCodeOwner =
!isCodeOwnershipAssignedToEmail.get()
+ && !isCodeOwnershipAssignedToAllUsers.get()
&& !hasRevelantCodeOwnerDefinitions.get()
&& !parentCodeOwnersAreIgnored.get()
&& isFallbackCodeOwner(branchResource.getNameKey());
CodeOwnerCheckInfo codeOwnerCheckInfo = new CodeOwnerCheckInfo();
codeOwnerCheckInfo.isCodeOwner =
- (isCodeOwnershipAssignedToEmail.get() || isFallbackCodeOwner) && isResolvable;
+ (isCodeOwnershipAssignedToEmail.get()
+ || isCodeOwnershipAssignedToAllUsers.get()
+ || isFallbackCodeOwner)
+ && isResolvable;
codeOwnerCheckInfo.isResolvable = isResolvable;
codeOwnerCheckInfo.codeOwnerConfigFilePaths =
codeOwnerConfigFilePaths.stream().map(Path::toString).collect(toList());
codeOwnerCheckInfo.isFallbackCodeOwner = isFallbackCodeOwner && isResolvable;
codeOwnerCheckInfo.isDefaultCodeOwner = isDefaultCodeOwner.get();
codeOwnerCheckInfo.isGlobalCodeOwner = isGlobalCodeOwner;
+ codeOwnerCheckInfo.isOwnedByAllUsers = isCodeOwnershipAssignedToAllUsers.get();
codeOwnerCheckInfo.debugLogs = messages;
return Response.ok(codeOwnerCheckInfo);
}
@@ -238,7 +279,7 @@
}
}
- private boolean isGlobalCodeOwner(Project.NameKey projectName) {
+ private boolean isGlobalCodeOwner(Project.NameKey projectName, String email) {
return codeOwnersPluginConfiguration.getProjectConfig(projectName).getGlobalCodeOwners()
.stream()
.filter(cor -> cor.email().equals(email))
diff --git a/java/com/google/gerrit/plugins/codeowners/testing/CodeOwnerCheckInfoSubject.java b/java/com/google/gerrit/plugins/codeowners/testing/CodeOwnerCheckInfoSubject.java
index 8d6524b..2d33006 100644
--- a/java/com/google/gerrit/plugins/codeowners/testing/CodeOwnerCheckInfoSubject.java
+++ b/java/com/google/gerrit/plugins/codeowners/testing/CodeOwnerCheckInfoSubject.java
@@ -89,6 +89,14 @@
check("isGlobalCodeOwner").that(codeOwnerCheckInfo().isGlobalCodeOwner).isFalse();
}
+ public void isOwnedByAllUsers() {
+ check("isOwnedByAllUsers").that(codeOwnerCheckInfo().isOwnedByAllUsers).isTrue();
+ }
+
+ public void isNotOwnedByAllUsers() {
+ check("isOwnedByAllUsers").that(codeOwnerCheckInfo().isOwnedByAllUsers).isFalse();
+ }
+
public void hasDebugLogsThatContainAllOf(String... expectedMessages) {
for (String expectedMessage : expectedMessages) {
check("debugLogs").that(codeOwnerCheckInfo().debugLogs).contains(expectedMessage);
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CheckCodeOwnerIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CheckCodeOwnerIT.java
index 8b56cd5..3be9ea8 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CheckCodeOwnerIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CheckCodeOwnerIT.java
@@ -28,6 +28,7 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.restapi.AuthException;
@@ -35,6 +36,7 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
+import com.google.gerrit.plugins.codeowners.acceptance.testsuite.TestCodeOwnerConfigCreation;
import com.google.gerrit.plugins.codeowners.acceptance.testsuite.TestPathExpressions;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerCheckInfo;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
@@ -55,6 +57,7 @@
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Arrays;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;
@@ -138,6 +141,7 @@
.containsExactly(getCodeOwnerConfigFilePath("/foo/"));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -168,6 +172,7 @@
.inOrder();
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -211,6 +216,7 @@
.inOrder();
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -235,7 +241,7 @@
.addSecondaryEmail(secondaryEmail)
.update();
- setAsRootCodeOwner(secondaryEmail);
+ setAsRootCodeOwners(secondaryEmail);
CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, secondaryEmail);
assertThat(checkCodeOwnerInfo).isCodeOwner();
@@ -245,6 +251,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -254,6 +261,57 @@
}
@Test
+ public void checkCodeOwner_ownedByAllUsers() throws Exception {
+ TestAccount codeOwner =
+ accountCreator.create(
+ "codeOwner", "codeOwner@example.com", "Code Owner", /* displayName= */ null);
+
+ setAsRootCodeOwners(CodeOwnerResolver.ALL_USERS_WILDCARD);
+
+ CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, codeOwner.email());
+ assertThat(checkCodeOwnerInfo).isCodeOwner();
+ assertThat(checkCodeOwnerInfo).isResolvable();
+ assertThat(checkCodeOwnerInfo)
+ .hasCodeOwnerConfigFilePathsThat()
+ .containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
+ assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isOwnedByAllUsers();
+ assertThat(checkCodeOwnerInfo)
+ .hasDebugLogsThatContainAllOf(
+ String.format(
+ "found email %s as code owner in %s",
+ CodeOwnerResolver.ALL_USERS_WILDCARD, getCodeOwnerConfigFilePath(ROOT_PATH)));
+ }
+
+ @Test
+ public void checkCodeOwner_ownedByEmailAndOwnedByAllUsers() throws Exception {
+ TestAccount codeOwner =
+ accountCreator.create(
+ "codeOwner", "codeOwner@example.com", "Code Owner", /* displayName= */ null);
+
+ setAsRootCodeOwners(codeOwner.email(), CodeOwnerResolver.ALL_USERS_WILDCARD);
+
+ CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, codeOwner.email());
+ assertThat(checkCodeOwnerInfo).isCodeOwner();
+ assertThat(checkCodeOwnerInfo).isResolvable();
+ assertThat(checkCodeOwnerInfo)
+ .hasCodeOwnerConfigFilePathsThat()
+ .containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
+ assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isOwnedByAllUsers();
+ assertThat(checkCodeOwnerInfo)
+ .hasDebugLogsThatContainAllOf(
+ String.format(
+ "found email %s as code owner in %s",
+ codeOwner.email(), getCodeOwnerConfigFilePath(ROOT_PATH)),
+ String.format(
+ "found email %s as code owner in %s",
+ CodeOwnerResolver.ALL_USERS_WILDCARD, getCodeOwnerConfigFilePath(ROOT_PATH)));
+ }
+
+ @Test
public void checkNonCodeOwner() throws Exception {
CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, user.email());
assertThat(checkCodeOwnerInfo).isNotCodeOwner();
@@ -261,6 +319,7 @@
assertThat(checkCodeOwnerInfo).hasCodeOwnerConfigFilePathsThat().isEmpty();
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(String.format("resolved to account %s", user.id()));
}
@@ -269,7 +328,7 @@
public void checkNonExistingEmail() throws Exception {
String nonExistingEmail = "non-exiting@example.com";
- setAsRootCodeOwner(nonExistingEmail);
+ setAsRootCodeOwners(nonExistingEmail);
CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, nonExistingEmail);
assertThat(checkCodeOwnerInfo).isNotCodeOwner();
@@ -279,6 +338,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -293,7 +353,7 @@
public void checkAmbiguousExistingEmail() throws Exception {
String ambiguousEmail = "ambiguous@example.com";
- setAsRootCodeOwner(ambiguousEmail);
+ setAsRootCodeOwners(ambiguousEmail);
// Add the email to 2 accounts to make it ambiguous.
addEmail(user.id(), ambiguousEmail);
@@ -307,6 +367,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -328,7 +389,7 @@
extIdNotes.commit(md);
}
- setAsRootCodeOwner(orphanedEmail);
+ setAsRootCodeOwners(orphanedEmail);
CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, orphanedEmail);
assertThat(checkCodeOwnerInfo).isNotCodeOwner();
@@ -338,6 +399,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -368,6 +430,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -398,6 +461,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -431,6 +495,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -452,11 +517,12 @@
assertThat(checkCodeOwnerInfo).hasCodeOwnerConfigFilePathsThat().isEmpty();
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
}
@Test
public void checkAllUsersWildcard_ownedByAllUsers() throws Exception {
- setAsRootCodeOwner(CodeOwnerResolver.ALL_USERS_WILDCARD);
+ setAsRootCodeOwners(CodeOwnerResolver.ALL_USERS_WILDCARD);
CodeOwnerCheckInfo checkCodeOwnerInfo =
checkCodeOwner(ROOT_PATH, CodeOwnerResolver.ALL_USERS_WILDCARD);
@@ -467,6 +533,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -491,6 +558,7 @@
assertThat(checkCodeOwnerInfo).hasCodeOwnerConfigFilePathsThat().isEmpty();
assertThat(checkCodeOwnerInfo).isDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -500,6 +568,32 @@
}
@Test
+ public void checkDefaultCodeOwner_ownedByAllUsers() throws Exception {
+ TestAccount defaultCodeOwner =
+ accountCreator.create(
+ "defaultCodeOwner",
+ "defaultCodeOwner@example.com",
+ "Default Code Owner",
+ /* displayName= */ null);
+ setAsDefaultCodeOwner(CodeOwnerResolver.ALL_USERS_WILDCARD);
+
+ String path = "/foo/bar/baz.md";
+ CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(path, defaultCodeOwner.email());
+ assertThat(checkCodeOwnerInfo).isCodeOwner();
+ assertThat(checkCodeOwnerInfo).isResolvable();
+ assertThat(checkCodeOwnerInfo).hasCodeOwnerConfigFilePathsThat().isEmpty();
+ assertThat(checkCodeOwnerInfo).isDefaultCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isOwnedByAllUsers();
+ assertThat(checkCodeOwnerInfo)
+ .hasDebugLogsThatContainAllOf(
+ String.format(
+ "found email %s as code owner in default code owner config",
+ CodeOwnerResolver.ALL_USERS_WILDCARD),
+ String.format("resolved to account %s", defaultCodeOwner.id()));
+ }
+
+ @Test
@GerritConfig(name = "plugin.code-owners.globalCodeOwner", value = "globalCodeOwner@example.com")
public void checkGlobalCodeOwner() throws Exception {
TestAccount globalCodeOwner =
@@ -516,6 +610,7 @@
assertThat(checkCodeOwnerInfo).hasCodeOwnerConfigFilePathsThat().isEmpty();
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format("found email %s as global code owner", globalCodeOwner.email()),
@@ -523,6 +618,33 @@
}
@Test
+ @GerritConfig(
+ name = "plugin.code-owners.globalCodeOwner",
+ value = CodeOwnerResolver.ALL_USERS_WILDCARD)
+ public void checkGlobalCodeOwner_ownedByAllUsers() throws Exception {
+ TestAccount globalCodeOwner =
+ accountCreator.create(
+ "globalCodeOwner",
+ "globalCodeOwner@example.com",
+ "Global Code Owner",
+ /* displayName= */ null);
+
+ String path = "/foo/bar/baz.md";
+ CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(path, globalCodeOwner.email());
+ assertThat(checkCodeOwnerInfo).isCodeOwner();
+ assertThat(checkCodeOwnerInfo).isResolvable();
+ assertThat(checkCodeOwnerInfo).hasCodeOwnerConfigFilePathsThat().isEmpty();
+ assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
+ assertThat(checkCodeOwnerInfo).isGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isOwnedByAllUsers();
+ assertThat(checkCodeOwnerInfo)
+ .hasDebugLogsThatContainAllOf(
+ String.format(
+ "found email %s as global code owner", CodeOwnerResolver.ALL_USERS_WILDCARD),
+ String.format("resolved to account %s", globalCodeOwner.id()));
+ }
+
+ @Test
public void checkCodeOwnerForOtherUser() throws Exception {
TestAccount codeOwner =
accountCreator.create(
@@ -538,6 +660,7 @@
.containsExactly(getCodeOwnerConfigFilePath("/foo/"));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -576,6 +699,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -598,7 +722,7 @@
.addSecondaryEmail(secondaryEmail)
.update();
- setAsRootCodeOwner(secondaryEmail);
+ setAsRootCodeOwners(secondaryEmail);
CodeOwnerCheckInfo checkCodeOwnerInfo = checkCodeOwner(ROOT_PATH, secondaryEmail, user.email());
assertThat(checkCodeOwnerInfo).isNotCodeOwner();
@@ -608,6 +732,7 @@
.containsExactly(getCodeOwnerConfigFilePath(ROOT_PATH));
assertThat(checkCodeOwnerInfo).isNotDefaultCodeOwner();
assertThat(checkCodeOwnerInfo).isNotGlobalCodeOwner();
+ assertThat(checkCodeOwnerInfo).isNotOwnedByAllUsers();
assertThat(checkCodeOwnerInfo)
.hasDebugLogsThatContainAllOf(
String.format(
@@ -1193,11 +1318,22 @@
return folderPath + getCodeOwnerConfigFileName();
}
- private void setAsRootCodeOwner(String email) {
+ private void setAsRootCodeOwners(String... emails) {
+ TestCodeOwnerConfigCreation.Builder builder =
+ codeOwnerConfigOperations
+ .newCodeOwnerConfig()
+ .project(project)
+ .branch("master")
+ .folderPath(ROOT_PATH);
+ Arrays.stream(emails).forEach(builder::addCodeOwnerEmail);
+ builder.create();
+ }
+
+ private void setAsDefaultCodeOwner(String email) {
codeOwnerConfigOperations
.newCodeOwnerConfig()
.project(project)
- .branch("master")
+ .branch(RefNames.REFS_CONFIG)
.folderPath(ROOT_PATH)
.addCodeOwnerEmail(email)
.create();
diff --git a/resources/Documentation/rest-api.md b/resources/Documentation/rest-api.md
index 29d5fd8..232b619 100644
--- a/resources/Documentation/rest-api.md
+++ b/resources/Documentation/rest-api.md
@@ -807,6 +807,7 @@
| `is_default_code_owner` | Whether the given email is configured as a default code owner in the code owner config file in `refs/meta/config`. Note that if the email is configured as default code owner, but the email is not resolvable (see `is_resolvable` field), the user is not a code owner.
| `is_global_code_owner` | Whether the given email is configured as a global
code owner. Note that if the email is configured as global code owner, but the email is not resolvable (see `is_resolvable` field), the user is not a code owner.
+| `is_owned_by_all_users` | Whether the the specified path in the branch is owned by all users (aka `*`).
| `debug_logs` | List of debug logs that may help to understand why the user is or isn't a code owner.
---