Add an event property value to an ITS field Change-Id: Ief770151ad38fb2f61f1ca93c0730c80f9814da8
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java index cfb6168..de80229 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java
@@ -31,6 +31,7 @@ import com.googlesource.gerrit.plugins.its.base.workflow.ActionController; import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest; import com.googlesource.gerrit.plugins.its.base.workflow.AddComment; +import com.googlesource.gerrit.plugins.its.base.workflow.AddPropertyToField; import com.googlesource.gerrit.plugins.its.base.workflow.AddSoyComment; import com.googlesource.gerrit.plugins.its.base.workflow.AddStandardComment; import com.googlesource.gerrit.plugins.its.base.workflow.Condition; @@ -70,6 +71,7 @@ factory(AddSoyComment.Factory.class); factory(AddStandardComment.Factory.class); factory(LogEvent.Factory.class); + factory(AddPropertyToField.Factory.class); install(ItsRulesProjectCacheImpl.module()); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsFacade.java index 9d7b3fa..4cd7bc2 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsFacade.java +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsFacade.java
@@ -31,6 +31,11 @@ public void addComment(String issueId, String comment) throws IOException; + default void addValueToField(String issueId, String value, String fieldId) throws IOException { + throw new UnsupportedOperationException( + "add-value-to-field is not currently implemented by " + getClass()); + } + public void performAction(String issueId, String actionName) throws IOException; public boolean exists(final String issueId) throws IOException;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/NoopItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/NoopItsFacade.java index de4acd9..85d806e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/NoopItsFacade.java +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/NoopItsFacade.java
@@ -32,6 +32,13 @@ } @Override + public void addValueToField(String issueId, String value, String fieldId) throws IOException { + if (log.isDebugEnabled()) { + log.debug("addValueToField({},{},{})", issueId, fieldId, value); + } + } + + @Override public void addRelatedLink(String issueId, URL relatedUrl, String description) throws IOException { if (log.isDebugEnabled()) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java index 26ae4e7..e209daf 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java
@@ -32,6 +32,7 @@ private final AddStandardComment.Factory addStandardCommentFactory; private final AddSoyComment.Factory addSoyCommentFactory; private final LogEvent.Factory logEventFactory; + private final AddPropertyToField.Factory addPropertyToFieldFactory; @Inject public ActionExecutor( @@ -39,12 +40,14 @@ AddComment.Factory addCommentFactory, AddStandardComment.Factory addStandardCommentFactory, AddSoyComment.Factory addSoyCommentFactory, - LogEvent.Factory logEventFactory) { + LogEvent.Factory logEventFactory, + AddPropertyToField.Factory addPropertyToFieldFactory) { this.itsFactory = itsFactory; this.addCommentFactory = addCommentFactory; this.addStandardCommentFactory = addStandardCommentFactory; this.addSoyCommentFactory = addSoyCommentFactory; this.logEventFactory = logEventFactory; + this.addPropertyToFieldFactory = addPropertyToFieldFactory; } private Action getAction(String actionName) { @@ -57,6 +60,8 @@ return addSoyCommentFactory.create(); case "log-event": return logEventFactory.create(); + case "add-property-to-field": + return addPropertyToFieldFactory.create(); default: return null; }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToField.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToField.java new file mode 100644 index 0000000..1979183 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToField.java
@@ -0,0 +1,47 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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. + +package com.googlesource.gerrit.plugins.its.base.workflow; + +import com.google.inject.Inject; +import com.googlesource.gerrit.plugins.its.base.its.ItsFacade; +import java.io.IOException; +import java.util.Map; +import java.util.Optional; + +public class AddPropertyToField implements Action { + + public interface Factory { + AddPropertyToField create(); + } + + private final AddPropertyToFieldParametersExtractor parametersExtractor; + + @Inject + public AddPropertyToField(AddPropertyToFieldParametersExtractor parametersExtractor) { + this.parametersExtractor = parametersExtractor; + } + + @Override + public void execute( + ItsFacade its, String issue, ActionRequest actionRequest, Map<String, String> properties) + throws IOException { + Optional<AddPropertyToFieldParameters> parameters = + parametersExtractor.extract(actionRequest, properties); + if (!parameters.isPresent()) { + return; + } + its.addValueToField(issue, parameters.get().getPropertyValue(), parameters.get().getFieldId()); + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParameters.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParameters.java new file mode 100644 index 0000000..55b029d --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParameters.java
@@ -0,0 +1,37 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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. + +package com.googlesource.gerrit.plugins.its.base.workflow; + +/** Parameters needed by {@link AddPropertyToField} action */ +public class AddPropertyToFieldParameters { + + private final String propertyValue; + private final String fieldId; + + public AddPropertyToFieldParameters(String propertyValue, String fieldId) { + this.propertyValue = propertyValue; + this.fieldId = fieldId; + } + + /** @return The event property's value to add to the ITS field */ + public String getPropertyValue() { + return propertyValue; + } + + /** @return The id of the ITS field to which the property value is added */ + public String getFieldId() { + return fieldId; + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParametersExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParametersExtractor.java new file mode 100644 index 0000000..7a259f1 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParametersExtractor.java
@@ -0,0 +1,67 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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. + +package com.googlesource.gerrit.plugins.its.base.workflow; + +import com.google.common.base.Strings; +import com.google.inject.Inject; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AddPropertyToFieldParametersExtractor { + + private static final Logger log = + LoggerFactory.getLogger(AddPropertyToFieldParametersExtractor.class); + + @Inject + public AddPropertyToFieldParametersExtractor() {} + + /** + * @return The parameters needed to perform an AddPropertyToField action. Empty if the parameters + * could not be extracted. + */ + public Optional<AddPropertyToFieldParameters> extract( + ActionRequest actionRequest, Map<String, String> properties) { + String[] parameters = actionRequest.getParameters(); + if (parameters.length != 2) { + log.error( + "Wrong number of received parameters. Received parameters are {}. Exactly two parameters are expected. The first one is the ITS field id, the second one is the event property id", + Arrays.toString(parameters)); + return Optional.empty(); + } + + String propertyId = parameters[0]; + if (Strings.isNullOrEmpty(propertyId)) { + log.error("Received property id is blank"); + return Optional.empty(); + } + + String fieldId = parameters[1]; + if (Strings.isNullOrEmpty(fieldId)) { + log.error("Received field id is blank"); + return Optional.empty(); + } + + if (!properties.containsKey(propertyId)) { + log.error("No event property found for id {}", propertyId); + return Optional.empty(); + } + + String propertyValue = properties.get(propertyId); + return Optional.of(new AddPropertyToFieldParameters(propertyValue, fieldId)); + } +}
diff --git a/src/main/resources/Documentation/config-rulebase-common.md b/src/main/resources/Documentation/config-rulebase-common.md index 128dac5..65c18b1 100644 --- a/src/main/resources/Documentation/config-rulebase-common.md +++ b/src/main/resources/Documentation/config-rulebase-common.md
@@ -634,6 +634,20 @@ the event's subject property, and `$changeNumber` would refer to the change's number. +[action-add-property-to-field]: #action-add-property-to-field +### <a name="action-add-property-to-field">Action: add-property-to-field</a> + +The `add-property-to-field` action adds an event property value to an ITS designated field. + +The field is expected to be able to hold multiple values. +The ITS field value deduplication depends on the its implementation. + +Example with the event property `branch` and a field identified as `labels`: + +``` + action = add-property-to-field branch labels +``` + [action-log-event]: #action-log-event ### <a name="action-log-event">Action: log-event</a>
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java index 69c9be9..3864cdf 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java
@@ -38,6 +38,7 @@ private AddStandardComment.Factory addStandardCommentFactory; private AddSoyComment.Factory addSoyCommentFactory; private LogEvent.Factory logEventFactory; + private AddPropertyToField.Factory addPropertyToFieldFactory; private Map<String, String> properties = ImmutableMap.of("issue", "4711", "project", "testProject"); @@ -212,6 +213,25 @@ actionExecutor.execute(actionRequests, properties); } + public void testAddPropertyToFieldDelegation() throws IOException { + ActionRequest actionRequest = createMock(ActionRequest.class); + expect(actionRequest.getName()).andReturn("add-property-to-field"); + + Set<ActionRequest> actionRequests = ImmutableSet.of(actionRequest); + + AddPropertyToField addPropertyToField = createMock(AddPropertyToField.class); + expect(addPropertyToFieldFactory.create()).andReturn(addPropertyToField); + expect(itsFacadeFactory.getFacade(new Project.NameKey(properties.get("project")))) + .andReturn(its); + + addPropertyToField.execute(its, "4711", actionRequest, properties); + + replayMocks(); + + ActionExecutor actionExecutor = createActionExecutor(); + actionExecutor.execute(actionRequests, properties); + } + private ActionExecutor createActionExecutor() { return injector.getInstance(ActionExecutor.class); } @@ -242,6 +262,9 @@ itsFacadeFactory = createMock(ItsFacadeFactory.class); bind(ItsFacadeFactory.class).toInstance(itsFacadeFactory); + + addPropertyToFieldFactory = createMock(AddPropertyToField.Factory.class); + bind(AddPropertyToField.Factory.class).toInstance(addPropertyToFieldFactory); } } }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParametersExtractorTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParametersExtractorTest.java new file mode 100644 index 0000000..fb047f7 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldParametersExtractorTest.java
@@ -0,0 +1,105 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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. + +package com.googlesource.gerrit.plugins.its.base.workflow; + +import static org.easymock.EasyMock.expect; + +import com.google.gerrit.extensions.config.FactoryModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.googlesource.gerrit.plugins.its.base.testutil.MockingTestCase; +import java.util.Collections; +import java.util.Optional; + +public class AddPropertyToFieldParametersExtractorTest extends MockingTestCase { + + private static final String FIELD_ID = "fieldId"; + private static final String PROPERTY_ID = "propertyId"; + private static final String PROPERTY_VALUE = "propertyValue"; + + private AddPropertyToFieldParametersExtractor extractor; + + @Override + public void setUp() throws Exception { + super.setUp(); + Injector injector = Guice.createInjector(new TestModule()); + extractor = injector.getInstance(AddPropertyToFieldParametersExtractor.class); + } + + private class TestModule extends FactoryModule {} + + public void testNoParameter() { + testWrongNumberOfReceivedParameters(new String[] {}); + } + + public void testOneParameter() { + testWrongNumberOfReceivedParameters(new String[] {PROPERTY_ID}); + } + + public void testThreeParameters() { + testWrongNumberOfReceivedParameters(new String[] {PROPERTY_ID, PROPERTY_ID, PROPERTY_ID}); + } + + private void testWrongNumberOfReceivedParameters(String[] parameters) { + ActionRequest actionRequest = createMock(ActionRequest.class); + expect(actionRequest.getParameters()).andReturn(parameters); + + replayMocks(); + + assertFalse(extractor.extract(actionRequest, Collections.emptyMap()).isPresent()); + } + + public void testBlankFieldId() { + ActionRequest actionRequest = createMock(ActionRequest.class); + expect(actionRequest.getParameters()).andReturn(new String[] {PROPERTY_ID, ""}); + + replayMocks(); + + assertFalse(extractor.extract(actionRequest, Collections.emptyMap()).isPresent()); + } + + public void testBlankPropertyId() { + ActionRequest actionRequest = createMock(ActionRequest.class); + expect(actionRequest.getParameters()).andReturn(new String[] {"", FIELD_ID}); + + replayMocks(); + + assertFalse(extractor.extract(actionRequest, Collections.emptyMap()).isPresent()); + } + + public void testUnknownPropertyId() { + ActionRequest actionRequest = createMock(ActionRequest.class); + expect(actionRequest.getParameters()).andReturn(new String[] {FIELD_ID, PROPERTY_ID}); + + replayMocks(); + + assertFalse(extractor.extract(actionRequest, Collections.emptyMap()).isPresent()); + } + + public void testHappyPath() { + ActionRequest actionRequest = createMock(ActionRequest.class); + expect(actionRequest.getParameters()).andReturn(new String[] {PROPERTY_ID, FIELD_ID}); + + replayMocks(); + + Optional<AddPropertyToFieldParameters> extractedParameters = + extractor.extract(actionRequest, Collections.singletonMap(PROPERTY_ID, PROPERTY_VALUE)); + if (!extractedParameters.isPresent()) { + fail(); + } + assertEquals(PROPERTY_VALUE, extractedParameters.get().getPropertyValue()); + assertEquals(FIELD_ID, extractedParameters.get().getFieldId()); + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldTest.java new file mode 100644 index 0000000..a601b04 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/AddPropertyToFieldTest.java
@@ -0,0 +1,77 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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. + +package com.googlesource.gerrit.plugins.its.base.workflow; + +import static org.easymock.EasyMock.expect; + +import com.google.gerrit.extensions.config.FactoryModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.googlesource.gerrit.plugins.its.base.its.ItsFacade; +import com.googlesource.gerrit.plugins.its.base.testutil.MockingTestCase; +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import org.easymock.EasyMock; + +public class AddPropertyToFieldTest extends MockingTestCase { + + private static final String ISSUE_ID = "4711"; + private static final String FIELD_ID = "fieldId"; + private static final String PROPERTY_ID = "propertyId"; + private static final String PROPERTY_VALUE = "propertyValue"; + + private Injector injector; + private AddPropertyToFieldParametersExtractor parametersExtractor; + private ItsFacade its; + + @Override + public void setUp() throws Exception { + super.setUp(); + injector = Guice.createInjector(new TestModule()); + } + + private class TestModule extends FactoryModule { + @Override + protected void configure() { + parametersExtractor = createMock(AddPropertyToFieldParametersExtractor.class); + bind(AddPropertyToFieldParametersExtractor.class).toInstance(parametersExtractor); + + its = createMock(ItsFacade.class); + bind(ItsFacade.class).toInstance(its); + } + } + + public void testHappyPath() throws IOException { + ActionRequest actionRequest = createMock(ActionRequest.class); + + Map<String, String> properties = Collections.singletonMap(PROPERTY_ID, PROPERTY_VALUE); + expect(parametersExtractor.extract(actionRequest, properties)) + .andReturn(Optional.of(new AddPropertyToFieldParameters(PROPERTY_VALUE, FIELD_ID))); + + its.addValueToField(ISSUE_ID, PROPERTY_VALUE, FIELD_ID); + EasyMock.expectLastCall().once(); + + replayMocks(); + + AddPropertyToField addPropertyToField = createAddPropertyToField(); + addPropertyToField.execute(its, ISSUE_ID, actionRequest, properties); + } + + private AddPropertyToField createAddPropertyToField() { + return injector.getInstance(AddPropertyToField.class); + } +}