Allow validating code owner configs even if code owners is switched off
When rolling out code-owners, it can make sense to enable the validation
of code owner config files before enabling the code owners
functionality. To support this we add 'FORCED' and 'FORCED_DRY_RUN' as
new options for the enableValidationOnCommitReceived and
enableValidationOnSubmit configuration parameters, since 'TRUE' and
'DRY_RUN' only trigger the validation if the code owners functionality
is enabled.
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I29fdbd165e067bdab442f1d1d5e54dc537c67369
diff --git a/java/com/google/gerrit/plugins/codeowners/common/CodeOwnerConfigValidationPolicy.java b/java/com/google/gerrit/plugins/codeowners/common/CodeOwnerConfigValidationPolicy.java
index 5976c71..7b35079 100644
--- a/java/com/google/gerrit/plugins/codeowners/common/CodeOwnerConfigValidationPolicy.java
+++ b/java/com/google/gerrit/plugins/codeowners/common/CodeOwnerConfigValidationPolicy.java
@@ -19,6 +19,8 @@
/**
* The code owner config file validation is enabled and invalid code owner config files are
* rejected.
+ *
+ * <p>If the code owners functionality is disabled, no validation is performed.
*/
TRUE,
@@ -30,14 +32,39 @@
/**
* Code owner config files are validated, but invalid code owner config files are not rejected.
+ *
+ * <p>If the code owners functionality is disabled, no dry-run validation is performed.
*/
- DRY_RUN;
+ DRY_RUN,
+
+ /**
+ * Code owner config files are validated even if the code owners functionality is disabled.
+ *
+ * <p>This option is useful when the code owner config validation should be enabled as preparation
+ * to enabling the code owners functionality.
+ */
+ FORCED,
+
+ /**
+ * Code owner config files are validated even if the code owners functionality is disabled, but
+ * invalid code owner config files are not rejected.
+ *
+ * <p>This option is useful when the code owner config validation should be enabled as preparation
+ * to enabling the code owners functionality.
+ */
+ FORCED_DRY_RUN;
public boolean isDryRun() {
- return this == CodeOwnerConfigValidationPolicy.DRY_RUN;
+ return this == CodeOwnerConfigValidationPolicy.DRY_RUN
+ || this == CodeOwnerConfigValidationPolicy.FORCED_DRY_RUN;
}
public boolean runValidation() {
return this != CodeOwnerConfigValidationPolicy.FALSE;
}
+
+ public boolean isForced() {
+ return this == CodeOwnerConfigValidationPolicy.FORCED
+ || this == CodeOwnerConfigValidationPolicy.FORCED_DRY_RUN;
+ }
}
diff --git a/java/com/google/gerrit/plugins/codeowners/validation/CodeOwnerConfigValidator.java b/java/com/google/gerrit/plugins/codeowners/validation/CodeOwnerConfigValidator.java
index ce10743..80eece9 100644
--- a/java/com/google/gerrit/plugins/codeowners/validation/CodeOwnerConfigValidator.java
+++ b/java/com/google/gerrit/plugins/codeowners/validation/CodeOwnerConfigValidator.java
@@ -196,7 +196,8 @@
receiveEvent.repoConfig,
receiveEvent.revWalk,
receiveEvent.commit,
- receiveEvent.user);
+ receiveEvent.user,
+ codeOwnerConfigValidationPolicy.isForced());
} catch (RuntimeException e) {
if (!codeOwnerConfigValidationPolicy.isDryRun()) {
throw e;
@@ -266,7 +267,12 @@
IdentifiedUser patchSetUploader = userFactory.create(patchSet.uploader());
validationResult =
validateCodeOwnerConfig(
- branchNameKey, repository.getConfig(), revWalk, commit, patchSetUploader);
+ branchNameKey,
+ repository.getConfig(),
+ revWalk,
+ commit,
+ patchSetUploader,
+ codeOwnerConfigValidationPolicy.isForced());
} catch (RuntimeException e) {
if (!codeOwnerConfigValidationPolicy.isDryRun()) {
throw e;
@@ -297,6 +303,8 @@
* @param revCommit the commit for which newly added and modified code owner configs should be
* validated
* @param user user for which the code owner visibility checks should be performed
+ * @param force whether the validation should be done even if the code owners functionality is
+ * disabled for the branch
* @return the validation result, {@link Optional#empty()} if no validation is performed because
* the given commit doesn't contain newly added or modified code owner configs
*/
@@ -305,10 +313,12 @@
Config repoConfig,
RevWalk revWalk,
RevCommit revCommit,
- IdentifiedUser user) {
+ IdentifiedUser user,
+ boolean force) {
CodeOwnersPluginConfigSnapshot codeOwnersConfig =
codeOwnersPluginConfiguration.getProjectConfig(branchNameKey.project());
- if (codeOwnersConfig.isDisabled(branchNameKey.branch())) {
+ logger.atFine().log("force = %s", force);
+ if (!force && codeOwnersConfig.isDisabled(branchNameKey.branch())) {
return Optional.of(
ValidationResult.create(
pluginName,
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnerConfigValidatorIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnerConfigValidatorIT.java
index c35280c..d2ce328 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnerConfigValidatorIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnerConfigValidatorIT.java
@@ -425,6 +425,35 @@
}
@Test
+ @GerritConfig(name = "plugin.code-owners.enableValidationOnCommitReceived", value = "forced")
+ public void
+ cannotUploadNonParseableConfigIfCodeOwnersFunctionalityIsDisabledButValidationIsEnforced()
+ throws Exception {
+ disableCodeOwnersForProject(project);
+
+ CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
+
+ PushOneCommit.Result r =
+ createChange(
+ "Add code owners",
+ codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getJGitFilePath(),
+ "INVALID");
+ assertFatalWithMessages(
+ r,
+ "invalid code owner config files",
+ String.format(
+ "invalid code owner config file '%s' (project = %s, branch = master):\n %s",
+ codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath(),
+ project,
+ getParsingErrorMessage(
+ ImmutableMap.of(
+ FindOwnersBackend.class,
+ "invalid line: INVALID",
+ ProtoBackend.class,
+ "1:8: expected \"{\""))));
+ }
+
+ @Test
@GerritConfig(name = "plugin.code-owners.enableValidationOnCommitReceived", value = "dry_run")
public void canUploadNonParseableConfigIfValidationIsDoneAsDryRun() throws Exception {
CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
@@ -450,6 +479,37 @@
}
@Test
+ @GerritConfig(
+ name = "plugin.code-owners.enableValidationOnCommitReceived",
+ value = "forced_dry_run")
+ public void
+ canUploadNonParseableConfigIfCodeOwnersFunctionalityIsDisabledButDryRunValidationIsEnforced()
+ throws Exception {
+ disableCodeOwnersForProject(project);
+
+ CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
+
+ PushOneCommit.Result r =
+ createChange(
+ "Add code owners",
+ codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getJGitFilePath(),
+ "INVALID");
+ assertOkWithFatals(
+ r,
+ "invalid code owner config files",
+ String.format(
+ "invalid code owner config file '%s' (project = %s, branch = master):\n %s",
+ codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath(),
+ project,
+ getParsingErrorMessage(
+ ImmutableMap.of(
+ FindOwnersBackend.class,
+ "invalid line: INVALID",
+ ProtoBackend.class,
+ "1:8: expected \"{\""))));
+ }
+
+ @Test
@GerritConfig(name = "plugin.code-owners.readOnly", value = "true")
public void cannotUploadConfigIfConfigsAreConfiguredToBeReadOnly() throws Exception {
PushOneCommit.Result r =
@@ -1713,6 +1773,13 @@
testCanSubmitNonParseableConfig();
}
+ @Test
+ @GerritConfig(name = "plugin.code-owners.enableValidationOnSubmit", value = "forced_dry_run")
+ public void canSubmitNonParseableConfigIfValidationIsDoneAsForcedDryRun() throws Exception {
+ disableCodeOwnersForProject(project);
+ testCanSubmitNonParseableConfig();
+ }
+
private void testCanSubmitNonParseableConfig() throws Exception {
setAsDefaultCodeOwners(admin);
@@ -1739,6 +1806,48 @@
}
@Test
+ @GerritConfig(name = "plugin.code-owners.enableValidationOnSubmit", value = "forced")
+ public void
+ cannotSubmitConfigWithIssuesIfCodeOwnersFunctionalityIsDisabledButValidationIsEnforced()
+ throws Exception {
+ disableCodeOwnersForProject(project);
+
+ CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
+
+ // upload a change with a code owner config that has issues (non-resolvable code owners)
+ String unknownEmail = "non-existing-email@example.com";
+ PushOneCommit.Result r =
+ createChange(
+ "Add code owners",
+ codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getJGitFilePath(),
+ format(
+ CodeOwnerConfig.builder(codeOwnerConfigKey, TEST_REVISION)
+ .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(unknownEmail))
+ .build()));
+ r.assertOkStatus();
+
+ // approve the change
+ approve(r.getChangeId());
+
+ // try to submit the change
+ ResourceConflictException exception =
+ assertThrows(
+ ResourceConflictException.class,
+ () -> gApi.changes().id(r.getChangeId()).current().submit());
+ assertThat(exception)
+ .hasMessageThat()
+ .isEqualTo(
+ String.format(
+ "Failed to submit 1 change due to the following problems:\n"
+ + "Change %d: [code-owners] invalid code owner config files:\n"
+ + " ERROR: code owner email '%s' in '%s' cannot be resolved for %s",
+ r.getChange().getId().get(),
+ unknownEmail,
+ codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath(),
+ identifiedUserFactory.create(admin.id()).getLoggableName()));
+ }
+
+ @Test
@GerritConfig(name = "plugin.code-owners.enableValidationOnSubmit", value = "false")
public void canSubmitConfigWithIssuesIfValidationIsDisabled() throws Exception {
testCanSubmitConfigWithIssues();
diff --git a/resources/Documentation/config.md b/resources/Documentation/config.md
index 9dbb6a4..570af86 100644
--- a/resources/Documentation/config.md
+++ b/resources/Documentation/config.md
@@ -185,12 +185,38 @@
<a id="pluginCodeOwnersEnableValidationOnCommitReceived">plugin.@PLUGIN@.enableValidationOnCommitReceived</a>
: Policy for validating code owner config files when a commit is received.
- Allowed values are `true` (the code owner config file validation is
- enabled and the upload of invalid code owner config files is rejected),
- `false` (the code owner config file validation is disabled, invalid code
- owner config files are not rejected) and `dry_run` (code owner config
- files are validated, but invalid code owner config files are not
- rejected).\
+ \
+ Can be `TRUE`, `FALSE`, `DRY_RUN`, `FORCED` or `FORCED_DRY_RUN`.\
+ \
+ `TRUE`:\
+ The code owner config file validation is enabled and the upload of
+ invalid code owner config files is rejected.\
+ If the code owners functionality is disabled, no validation is
+ performed.\
+ \
+ `FALSE`:\
+ The code owner config file validation is disabled, invalid code owner
+ config files are not rejected.\
+ \
+ `DRY_RUN`:\
+ Code owner config files are validated, but invalid code owner config
+ files are not rejected.\
+ If the code owners functionality is disabled, no dry-run validation is
+ performed.\
+ \
+ `FORCED`:\
+ Code owner config files are validated even if the code owners
+ functionality is disabled.\
+ This option is useful when the code owner config validation should be
+ enabled as preparation to enabling the code owners functionality.\
+ \
+ `FORCED_DRY_RUN`:\
+ Code owner config files are validated even if the code owners
+ functionality is disabled, but invalid code owner config files are not
+ rejected.\
+ This option is useful when the code owner config validation should be
+ enabled as preparation to enabling the code owners functionality.\
+ \
Should only be disabled if there is bot that validates the code owner
config files in open changes as part of a pre-submit validation.\
Can be overridden per project by setting
@@ -200,12 +226,39 @@
<a id="pluginCodeOwnersEnableValidationOnSubmit">plugin.@PLUGIN@.enableValidationOnSubmit</a>
: Policy for validating code owner config files when a change is
- submitted. Allowed values are `true` (the code owner config file
- validation is enabled and the submission of invalid code owner config
- files is rejected), `false` (the code owner config file validation is
- disabled, invalid code owner config files are not rejected) and
- `dry_run` (code owner config files are validated, but invalid code owner
- config files are not rejected).\
+ submitted.
+ \
+ Can be `TRUE`, `FALSE`, `DRY_RUN`, `FORCED` or `FORCED_DRY_RUN`.\
+ \
+ `TRUE`:\
+ The code owner config file validation is enabled and the submission of
+ invalid code owner config files is rejected.\
+ If the code owners functionality is disabled, no validation is
+ performed.\
+ \
+ `FALSE`:\
+ The code owner config file validation is disabled, invalid code owner
+ config files are not rejected.\
+ \
+ `DRY_RUN`:\
+ Code owner config files are validated, but invalid code owner config
+ files are not rejected.\
+ If the code owners functionality is disabled, no dry-run validation is
+ performed.\
+ \
+ `FORCED`:\
+ Code owner config files are validated even if the code owners
+ functionality is disabled.\
+ This option is useful when the code owner config validation should be
+ enabled as preparation to enabling the code owners functionality.\
+ \
+ `FORCED_DRY_RUN`:\
+ Code owner config files are validated even if the code owners
+ functionality is disabled, but invalid code owner config files are not
+ rejected.\
+ This option is useful when the code owner config validation should be
+ enabled as preparation to enabling the code owners functionality.\
+ \
Disabling the submit validation is not recommended.\
Can be overridden per project by setting
[codeOwners.enableValidationOnSubmit](#codeOwnersEnableValidationOnSubmit)
@@ -592,13 +645,11 @@
in `gerrit.config` is used.
<a id="codeOwnersEnableValidationOnCommitReceived">codeOwners.enableValidationOnCommitReceived</a>
-: Policy for validating code owner config files when a commit is received.
- Allowed values are `true` (the code owner config file validation is
- enabled and the upload of invalid code owner config files is rejected),
- `false` (the code owner config file validation is disabled, invalid code
- owner config files are not rejected) and `dry_run` (code owner config
- files are validated, but invalid code owner config files are not
- rejected).\
+: Policy for validating code owner config files when a commit is
+ received.\
+ Can be `TRUE`, `FALSE`, `DRY_RUN`, `FORCED` or `FORCED_DRY_RUN`. For a
+ description of the values see
+ [plugin.@PLUGIN@.enableValidationOnCommitReceived](#pluginCodeOwnersEnableValidationOnCommitReceived).\
Should only be disabled if there is bot that validates the code owner
config files in open changes as part of a pre-submit validation.\
Overrides the global setting
@@ -627,12 +678,10 @@
<a id="codeOwnersEnableValidationOnSubmit">codeOwners.enableValidationOnSubmit</a>
: Policy for validating code owner config files when a change is
- submitted. Allowed values are `true` (the code owner config file
- validation is enabled and the submit of invalid code owner config files
- is rejected), `false` (the code owner config file validation is
- disabled, invalid code owner config files are not rejected) and
- `dry_run` (code owner config files are validated, but invalid code owner
- config files are not rejected).\
+ submitted.\
+ Can be `TRUE`, `FALSE`, `DRY_RUN`, `FORCED` or `FORCED_DRY_RUN`. For a
+ description of the values see
+ [plugin.@PLUGIN@.enableValidationOnSubmit](#pluginCodeOwnersEnableValidationOnSubmit).\
Disabling the submit validation is not recommended.\
Overrides the global setting
[plugin.@PLUGIN@.enableValidationOnSubmit](#pluginCodeOwnersEnableValidationOnSubmit)