Expose the submit requirements in the Change API
Add requirements in the Change API, allowing PolyGerrit and API consumers to use this information, and hopefuly improve communication with the final users (change owner and contributors). The API is thought to be both human and programs friendly, by exposing a human readable description, a "type" identifying accurately the requirement, and additional values in a key-value fashion. For instance, the PolyGerrit UI might use these informations to display each requirement with markup depending on its type, and fallback on the fallbackText if the type is unknown (hence the name). Change-Id: Ifb9e15a3c08ebaf42d8eb1469257c6e41cc22882
This commit is contained in:
@@ -5642,6 +5642,9 @@ AccountInfo] entity.
|
||||
Actions the caller might be able to perform on this revision. The
|
||||
information is a map of view name to link:#action-info[ActionInfo]
|
||||
entities.
|
||||
|`requirements` |optional|
|
||||
List of the link:rest-api-changes.html#requirement[requirements] to be met before this change
|
||||
can be submitted.
|
||||
|`labels` |optional|
|
||||
The labels of the change as a map that maps the label names to
|
||||
link:#label-info[LabelInfo] entries. +
|
||||
@@ -6591,6 +6594,32 @@ describing the related changes. Sorted by git commit order, newest to
|
||||
oldest. Empty if there are no related changes.
|
||||
|===========================
|
||||
|
||||
|
||||
[[requirement]]
|
||||
=== Requirement
|
||||
The `Requirement` entity contains information about a requirement relative to a change.
|
||||
|
||||
type:: Alphanumerical (plus hyphens or underscores) string to identify what the requirement is and
|
||||
why it was triggered. Can be seen as a class: requirements sharing the same type were created for a
|
||||
similar reason, and the data structure will follow one set of rules.
|
||||
|
||||
data:: (Optional) Additional key-value data linked to this requirement. This is used in templates to
|
||||
render rich status messages.
|
||||
|
||||
[options="header",cols="1,^1,5"]
|
||||
|===========================
|
||||
|Field Name | |Description
|
||||
|`status` | | Status of the requirement. Can be either `OK`, `NOT_READY` or `RULE_ERROR`.
|
||||
|`fallbackText` | | A human readable reason
|
||||
|`type` | |
|
||||
Alphanumerical (plus hyphens or underscores) string to identify what the requirement is and why it
|
||||
was triggered. Can be seen as a class: requirements sharing the same type were created for a similar
|
||||
reason, and the data structure will follow one set of rules.
|
||||
|`data` |optional|
|
||||
Holds custom key-value strings, used in templates to render richer status messages
|
||||
|===========================
|
||||
|
||||
|
||||
[[restore-input]]
|
||||
=== RestoreInput
|
||||
The `RestoreInput` entity contains information for restoring a change.
|
||||
|
@@ -70,4 +70,5 @@ public class ChangeInfo {
|
||||
public List<ProblemInfo> problems;
|
||||
public List<PluginDefinedInfo> plugins;
|
||||
public Collection<TrackingIdInfo> trackingIds;
|
||||
public Collection<SubmitRequirementInfo> requirements;
|
||||
}
|
||||
|
@@ -0,0 +1,53 @@
|
||||
// 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.google.gerrit.extensions.common;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SubmitRequirementInfo {
|
||||
public final String status;
|
||||
public final String fallbackText;
|
||||
public final String type;
|
||||
public final Map<String, String> data;
|
||||
|
||||
public SubmitRequirementInfo(
|
||||
String status, String fallbackText, String type, Map<String, String> data) {
|
||||
this.status = status;
|
||||
this.fallbackText = fallbackText;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof SubmitRequirementInfo)) {
|
||||
return false;
|
||||
}
|
||||
SubmitRequirementInfo that = (SubmitRequirementInfo) o;
|
||||
return Objects.equals(status, that.status)
|
||||
&& Objects.equals(fallbackText, that.fallbackText)
|
||||
&& Objects.equals(type, that.type)
|
||||
&& Objects.equals(data, that.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(status, fallbackText, type, data);
|
||||
}
|
||||
}
|
@@ -63,6 +63,8 @@ import com.google.gerrit.common.data.LabelType;
|
||||
import com.google.gerrit.common.data.LabelTypes;
|
||||
import com.google.gerrit.common.data.LabelValue;
|
||||
import com.google.gerrit.common.data.SubmitRecord;
|
||||
import com.google.gerrit.common.data.SubmitRecord.Status;
|
||||
import com.google.gerrit.common.data.SubmitRequirement;
|
||||
import com.google.gerrit.common.data.SubmitTypeRecord;
|
||||
import com.google.gerrit.extensions.api.changes.FixInput;
|
||||
import com.google.gerrit.extensions.client.ListChangesOption;
|
||||
@@ -78,6 +80,7 @@ import com.google.gerrit.extensions.common.ProblemInfo;
|
||||
import com.google.gerrit.extensions.common.PushCertificateInfo;
|
||||
import com.google.gerrit.extensions.common.ReviewerUpdateInfo;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.extensions.common.SubmitRequirementInfo;
|
||||
import com.google.gerrit.extensions.common.TrackingIdInfo;
|
||||
import com.google.gerrit.extensions.common.VotingRangeInfo;
|
||||
import com.google.gerrit.extensions.common.WebLinkInfo;
|
||||
@@ -425,6 +428,23 @@ public class ChangeJson {
|
||||
return out;
|
||||
}
|
||||
|
||||
private static Collection<SubmitRequirementInfo> requirementsFor(ChangeData cd) {
|
||||
Collection<SubmitRequirementInfo> reqInfos = new ArrayList<>();
|
||||
for (SubmitRecord submitRecord : cd.submitRecords(SUBMIT_RULE_OPTIONS_STRICT)) {
|
||||
if (submitRecord.requirements == null) {
|
||||
continue;
|
||||
}
|
||||
for (SubmitRequirement requirement : submitRecord.requirements) {
|
||||
reqInfos.add(requirementToInfo(requirement, submitRecord.status));
|
||||
}
|
||||
}
|
||||
return reqInfos;
|
||||
}
|
||||
|
||||
private static SubmitRequirementInfo requirementToInfo(SubmitRequirement req, Status status) {
|
||||
return new SubmitRequirementInfo(status.name(), req.fallbackText(), req.type(), req.data());
|
||||
}
|
||||
|
||||
private void ensureLoaded(Iterable<ChangeData> all) throws OrmException {
|
||||
if (lazyLoad) {
|
||||
ChangeData.ensureChangeLoaded(all);
|
||||
@@ -603,6 +623,7 @@ public class ChangeJson {
|
||||
}
|
||||
|
||||
out.labels = labelsFor(cd, has(LABELS), has(DETAILED_LABELS));
|
||||
out.requirements = requirementsFor(cd);
|
||||
|
||||
if (out.labels != null && has(DETAILED_LABELS)) {
|
||||
// If limited to specific patch sets but not the current patch set, don't
|
||||
|
@@ -0,0 +1,78 @@
|
||||
// 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.google.gerrit.acceptance.api.change;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.common.data.SubmitRecord;
|
||||
import com.google.gerrit.common.data.SubmitRequirement;
|
||||
import com.google.gerrit.extensions.annotations.Exports;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.SubmitRequirementInfo;
|
||||
import com.google.gerrit.extensions.config.FactoryModule;
|
||||
import com.google.gerrit.server.project.SubmitRuleOptions;
|
||||
import com.google.gerrit.server.query.change.ChangeData;
|
||||
import com.google.gerrit.server.rules.SubmitRule;
|
||||
import com.google.inject.Module;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ChangeSubmitRequirementIT extends AbstractDaemonTest {
|
||||
private static final SubmitRequirement req =
|
||||
SubmitRequirement.builder()
|
||||
.setType("custom_rule")
|
||||
.setFallbackText("Fallback text")
|
||||
.addCustomValue("key", "value")
|
||||
.build();
|
||||
private static final SubmitRequirementInfo reqInfo =
|
||||
new SubmitRequirementInfo(
|
||||
"NOT_READY", "Fallback text", "custom_rule", ImmutableMap.of("key", "value"));
|
||||
|
||||
@Override
|
||||
public Module createModule() {
|
||||
return new FactoryModule() {
|
||||
@Override
|
||||
public void configure() {
|
||||
bind(SubmitRule.class)
|
||||
.annotatedWith(Exports.named("CustomSubmitRule"))
|
||||
.to(CustomSubmitRule.class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSubmitRequirementIsPropagated() throws Exception {
|
||||
PushOneCommit.Result r = createChange();
|
||||
|
||||
ChangeInfo result = gApi.changes().id(r.getChangeId()).get();
|
||||
assertThat(result.requirements).containsExactly(reqInfo);
|
||||
}
|
||||
|
||||
private static class CustomSubmitRule implements SubmitRule {
|
||||
@Override
|
||||
public Collection<SubmitRecord> evaluate(ChangeData changeData, SubmitRuleOptions options) {
|
||||
SubmitRecord record = new SubmitRecord();
|
||||
record.labels = new ArrayList<>();
|
||||
record.status = SubmitRecord.Status.NOT_READY;
|
||||
record.requirements = ImmutableList.of(req);
|
||||
return ImmutableList.of(record);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user