Merge branch 'stable-2.16' into stable-3.0
* stable-2.16:
Check Jira connectivity at startup
Reintroduce Jira URL normalization
Fix its-jira init step
Apply GJF to the resulting merge.
Change-Id: I7267aff74f1c722122d8449b6f4b27cd8a223387
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java
index e362d3e..a5c16ec 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java
@@ -109,7 +109,10 @@
ui.header("Jira issue-tracking association");
jiraComment.string("Jira issue-Id regex", "match", "([A-Z]+-[0-9]+)");
- jiraComment.set("html", String.format("<a href=\"%s/browse/$1\">$1</a>", jiraUrl));
+ jiraComment.string(
+ "What html would you like to use?",
+ "html",
+ String.format("<a href=\"%s/browse/$1\">$1</a>", jiraUrl));
Section pluginConfig = sections.get("plugin", pluginName);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
index c17affd..e76e66c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
@@ -25,13 +25,18 @@
import com.googlesource.gerrit.plugins.its.base.its.InvalidTransitionException;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraComment;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraIssue;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraIssueUpdate;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraPageRequest;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraProject;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraRestApi;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraRestApiProvider;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraServerInfo;
import com.googlesource.gerrit.plugins.its.jira.restapi.JiraTransition;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraVersion;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraVersionsPage;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -101,6 +106,67 @@
}
}
+ public void createVersion(JiraItsServerInfo server, String projectKey, String version)
+ throws IOException {
+ log.debug("Trying to create version {} on project {}", version, projectKey);
+ JiraVersion jiraVersion = JiraVersion.builder().project(projectKey).name(version).build();
+ apiBuilder.getVersions(server).doPost("", gson.toJson(jiraVersion), HTTP_CREATED);
+ log.debug("Version {} created on project {}", version, projectKey);
+ }
+
+ public void markVersionAsReleased(JiraItsServerInfo server, String projectKey, String version)
+ throws IOException {
+ JiraVersion jiraVersion = findVersion(server, projectKey, version);
+ if (jiraVersion == null) {
+ log.error(
+ "Version {} of project {} does not exist or no access permission", version, projectKey);
+ return;
+ }
+
+ log.debug(
+ "Trying to mark version {} with id {} of project {} as released",
+ version,
+ jiraVersion.getId(),
+ projectKey);
+
+ JiraVersion markAsReleased =
+ JiraVersion.builder().released(true).releaseDate(new Date()).build();
+ apiBuilder.getVersions(server).doPut(jiraVersion.getId(), gson.toJson(markAsReleased), HTTP_OK);
+
+ log.debug("Version {} of project {} was marked as released", version, projectKey);
+ }
+
+ private JiraVersion findVersion(JiraItsServerInfo server, String projectKey, String version)
+ throws IOException {
+ JiraRestApi<JiraVersionsPage> api = apiBuilder.getProjectVersions(server, projectKey);
+
+ JiraPageRequest pageRequest = JiraPageRequest.builder().orderBy("-sequence").build();
+ JiraVersion jiraVersion = null;
+ while (pageRequest != null) {
+ JiraVersionsPage versionsPage = api.doGet(pageRequest.toSpec(), HTTP_OK);
+ jiraVersion = versionsPage.findByName(version);
+ if (jiraVersion != null) {
+ break;
+ }
+ pageRequest = versionsPage.nextPageRequest(pageRequest);
+ }
+
+ return jiraVersion;
+ }
+
+ public void addValueToField(
+ JiraItsServerInfo server, String issueKey, String value, String fieldId) throws IOException {
+ if (!issueExists(server, issueKey)) {
+ log.error("Issue {} does not exist", issueKey);
+ return;
+ }
+
+ log.debug("Trying to add value {} to field {} for issue {}", value, fieldId, issueKey);
+ JiraIssueUpdate edition = JiraIssueUpdate.builder().appendUpdate(fieldId, "add", value).build();
+ apiBuilder.getIssue(server).doPut(issueKey, gson.toJson(edition), HTTP_NO_CONTENT);
+ log.debug("Value {} added to field {} for issue {}", value, fieldId, issueKey);
+ }
+
/**
* @param issueKey Jira Issue key
* @param transition JiraTransition.Item to perform
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraConfig.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraConfig.java
index 5b4e197..f4cf11d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraConfig.java
@@ -60,6 +60,7 @@
private final JiraItsServerInfo defaultJiraServerInfo;
private final GitRepositoryManager repoManager;
private final ProjectCache projectCache;
+ private final ProjectConfig.Factory projectConfigFactory;
private final PersonIdent serverUser;
@Inject
@@ -69,13 +70,15 @@
PluginConfigFactory cfgFactory,
@GerritPersonIdent PersonIdent serverUser,
ProjectCache projectCache,
- GitRepositoryManager repoManager) {
+ GitRepositoryManager repoManager,
+ ProjectConfig.Factory projectConfigFactory) {
this.gerritConfig = config;
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.serverUser = serverUser;
this.projectCache = projectCache;
this.repoManager = repoManager;
+ this.projectConfigFactory = projectConfigFactory;
this.defaultJiraServerInfo = buildDefaultServerInfo(gerritConfig, pluginName);
}
@@ -107,7 +110,7 @@
void addCommentLinksSection(Project.NameKey projectName, JiraItsServerInfo jiraItsServerInfo) {
try (Repository git = repoManager.openRepository(projectName);
MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
- ProjectConfig config = ProjectConfig.read(md);
+ ProjectConfig config = projectConfigFactory.read(md);
String link =
CharMatcher.is('/').trimFrom(jiraItsServerInfo.getUrl().toString()) + JiraURL.URL_SUFFIX;
if (!commentLinksExist(config, link)) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
index 00f965f..c67cabf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
@@ -69,6 +69,17 @@
}
@Override
+ public void addValueToField(String issueKey, String value, String fieldId) throws IOException {
+ execute(
+ () -> {
+ log.debug("Adding value {} to field {} on issue {}", value, fieldId, issueKey);
+ jiraClient.addValueToField(itsServerInfo, issueKey, value, fieldId);
+ // No value to return
+ return null;
+ });
+ }
+
+ @Override
public void performAction(String issueKey, String actionName) throws IOException {
execute(
() -> {
@@ -90,6 +101,16 @@
}
@Override
+ public void createVersion(String projectKey, String version) throws IOException {
+ execute(
+ () -> {
+ log.debug("Creating version {} on project {}", version, projectKey);
+ jiraClient.createVersion(itsServerInfo, projectKey, version);
+ return projectKey;
+ });
+ }
+
+ @Override
public boolean exists(String issueKey) throws IOException {
return execute(() -> jiraClient.issueExists(getJiraServerInstance(), issueKey));
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServer.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServer.java
index 0a698aa..7666239 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServer.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServer.java
@@ -24,16 +24,13 @@
* to its-base to perform the its-actions.
*/
public class JiraItsServer implements ItsFacadeFactory {
- private final JiraConfig jiraConfig;
+ private final JiraItsServerInfoProvider serverInfoProvider;
private final JiraItsFacade itsFacade;
- private final JiraItsServerCache serverCache;
@Inject
- public JiraItsServer(
- JiraConfig jiraConfig, JiraItsFacade itsFacade, JiraItsServerCache serverCache) {
- this.jiraConfig = jiraConfig;
+ public JiraItsServer(JiraItsServerInfoProvider serverInfoProvider, JiraItsFacade itsFacade) {
+ this.serverInfoProvider = serverInfoProvider;
this.itsFacade = itsFacade;
- this.serverCache = serverCache;
}
/**
@@ -48,25 +45,7 @@
*/
@Override
public JiraItsFacade getFacade(Project.NameKey projectName) {
- JiraItsServerInfo jiraItsServerInfo = serverCache.get(projectName.get());
- if (jiraItsServerInfo.isValid()) {
- jiraConfig.addCommentLinksSection(projectName, jiraItsServerInfo);
- } else {
- jiraItsServerInfo = jiraConfig.getDefaultServerInfo();
- }
-
- if (!jiraItsServerInfo.isValid()) {
- throw new RuntimeException(
- String.format(
- "No valid Jira server configuration was found for project '%s' %n."
- + "Missing one or more configuration values: url: %s, username: %s, password: %s",
- projectName.get(),
- jiraItsServerInfo.getUrl(),
- jiraItsServerInfo.getUsername(),
- jiraItsServerInfo.getPassword()));
- }
-
- itsFacade.setJiraServerInstance(jiraItsServerInfo);
+ itsFacade.setJiraServerInstance(serverInfoProvider.get(projectName));
return itsFacade;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerInfoProvider.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerInfoProvider.java
new file mode 100644
index 0000000..b5e0128
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerInfoProvider.java
@@ -0,0 +1,52 @@
+// Copyright (C) 2019 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.jira;
+
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.inject.Inject;
+
+public class JiraItsServerInfoProvider {
+
+ private final JiraConfig jiraConfig;
+ private final JiraItsServerCache serverCache;
+
+ @Inject
+ public JiraItsServerInfoProvider(JiraConfig jiraConfig, JiraItsServerCache serverCache) {
+ this.jiraConfig = jiraConfig;
+ this.serverCache = serverCache;
+ }
+
+ public JiraItsServerInfo get(Project.NameKey projectName) {
+ JiraItsServerInfo jiraItsServerInfo = serverCache.get(projectName.get());
+ if (jiraItsServerInfo.isValid()) {
+ jiraConfig.addCommentLinksSection(projectName, jiraItsServerInfo);
+ } else {
+ jiraItsServerInfo = jiraConfig.getDefaultServerInfo();
+ }
+
+ if (!jiraItsServerInfo.isValid()) {
+ throw new RuntimeException(
+ String.format(
+ "No valid Jira server configuration was found for project '%s' %n."
+ + "Missing one or more configuration values: url: %s, username: %s, password: %s",
+ projectName.get(),
+ jiraItsServerInfo.getUrl(),
+ jiraItsServerInfo.getUsername(),
+ jiraItsServerInfo.getPassword()));
+ }
+
+ return jiraItsServerInfo;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraModule.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraModule.java
index 65026bc..3d59458 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraModule.java
@@ -28,6 +28,8 @@
import com.googlesource.gerrit.plugins.its.base.its.ItsConfig;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacadeFactory;
+import com.googlesource.gerrit.plugins.its.base.workflow.CustomAction;
+import com.googlesource.gerrit.plugins.its.jira.workflow.MarkPropertyAsReleasedVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,6 +60,10 @@
.annotatedWith(Exports.named(PROJECT_CONFIG_PASSWORD_KEY))
.toInstance(new ProjectConfigEntry("JIRA password", ""));
bind(ItsConfig.class);
+ bind(JiraItsServerInfoProvider.class);
+ bind(CustomAction.class)
+ .annotatedWith(Exports.named(MarkPropertyAsReleasedVersion.ACTION_NAME))
+ .to(MarkPropertyAsReleasedVersion.class);
install(new ItsHookModule(pluginName, pluginCfgFactory));
install(JiraItsServerCacheImpl.module());
listener().to(JiraItsStartupHealthcheck.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssueUpdate.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssueUpdate.java
new file mode 100644
index 0000000..bf9ea15
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssueUpdate.java
@@ -0,0 +1,62 @@
+// 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.jira.restapi;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JiraIssueUpdate {
+
+ private final Map<String, List<Map<String, Object>>> update;
+
+ private JiraIssueUpdate(Map<String, List<Map<String, Object>>> update) {
+ this.update = Collections.unmodifiableMap(update);
+ }
+
+ public Map<String, List<Map<String, Object>>> getUpdate() {
+ return update;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private final Map<String, List<Map<String, Object>>> update;
+
+ private Builder() {
+ this.update = new HashMap<>();
+ }
+
+ public Builder appendUpdate(String fieldId, String operation, String value) {
+ Object valueToPut = value;
+ if ("fixVersions".equals(fieldId)) {
+ valueToPut = Collections.singletonMap("name", value);
+ }
+
+ this.update
+ .computeIfAbsent(fieldId, key -> new ArrayList<>())
+ .add(Collections.singletonMap(operation, valueToPut));
+ return this;
+ }
+
+ public JiraIssueUpdate build() {
+ return new JiraIssueUpdate(update);
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraPage.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraPage.java
new file mode 100644
index 0000000..3de05f4
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraPage.java
@@ -0,0 +1,80 @@
+// 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.jira.restapi;
+
+import java.util.List;
+
+public class JiraPage<T> {
+
+ private final String self;
+ private final String nextPage;
+ private final long maxResults;
+ private final long startAt;
+ private final long total;
+ private final boolean isLast;
+ private final List<T> values;
+
+ public JiraPage(
+ String self,
+ String nextPage,
+ long maxResults,
+ long startAt,
+ long total,
+ boolean isLast,
+ List<T> values) {
+ this.self = self;
+ this.nextPage = nextPage;
+ this.maxResults = maxResults;
+ this.startAt = startAt;
+ this.total = total;
+ this.isLast = isLast;
+ this.values = values;
+ }
+
+ public JiraPageRequest nextPageRequest(JiraPageRequest currentPageRequest) {
+ if (isLast) {
+ return null;
+ }
+ return currentPageRequest.nextPageRequest();
+ }
+
+ public String getSelf() {
+ return self;
+ }
+
+ public String getNextPage() {
+ return nextPage;
+ }
+
+ public long getMaxResults() {
+ return maxResults;
+ }
+
+ public long getStartAt() {
+ return startAt;
+ }
+
+ public long getTotal() {
+ return total;
+ }
+
+ public boolean isLast() {
+ return isLast;
+ }
+
+ public List<T> getValues() {
+ return values;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraPageRequest.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraPageRequest.java
new file mode 100644
index 0000000..5e87ec3
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraPageRequest.java
@@ -0,0 +1,88 @@
+// 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.jira.restapi;
+
+import com.google.common.base.Strings;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class JiraPageRequest {
+
+ private final Long startAt;
+ private final Long maxResults;
+ private final String orderBy;
+
+ private JiraPageRequest(Long startAt, Long maxResults, String orderBy) {
+ this.startAt = startAt;
+ this.maxResults = maxResults;
+ this.orderBy = orderBy;
+ }
+
+ public JiraPageRequest nextPageRequest() {
+ return new JiraPageRequest(startAt + 1, maxResults, orderBy);
+ }
+
+ public String toSpec() {
+ Map<String, Object> parameters = new HashMap<>();
+ if (startAt != null) {
+ parameters.put("startAt", startAt);
+ }
+ if (maxResults != null) {
+ parameters.put("maxResults", maxResults);
+ }
+ if (!Strings.isNullOrEmpty(orderBy)) {
+ parameters.put("orderBy", orderBy);
+ }
+ String requestParameters =
+ parameters
+ .entrySet()
+ .stream()
+ .map(parameter -> parameter.getKey() + "=" + parameter.getValue())
+ .collect(Collectors.joining("&"));
+ return "?" + requestParameters;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private Long startAt;
+ private Long maxResults;
+ private String orderBy;
+
+ private Builder() {}
+
+ public Builder startAt(Long startAt) {
+ this.startAt = startAt;
+ return this;
+ }
+
+ public Builder maxResults(Long maxResults) {
+ this.maxResults = maxResults;
+ return this;
+ }
+
+ public Builder orderBy(String orderBy) {
+ this.orderBy = orderBy;
+ return this;
+ }
+
+ public JiraPageRequest build() {
+ return new JiraPageRequest(startAt, maxResults, orderBy);
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java
index 2e31d1b..9159068 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java
@@ -39,4 +39,13 @@
public JiraRestApi<JiraProject[]> getProjects(JiraItsServerInfo serverInfo) {
return get(serverInfo, JiraProject[].class, "/project");
}
+
+ public JiraRestApi<JiraVersion[]> getVersions(JiraItsServerInfo serverInfo) {
+ return get(serverInfo, JiraVersion[].class, "/version");
+ }
+
+ public JiraRestApi<JiraVersionsPage> getProjectVersions(
+ JiraItsServerInfo serverInfo, String projectKey) {
+ return get(serverInfo, JiraVersionsPage.class, "/project/" + projectKey + "/version");
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraVersion.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraVersion.java
new file mode 100644
index 0000000..36022be
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraVersion.java
@@ -0,0 +1,148 @@
+// 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.jira.restapi;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/** Represents a version in JIRA. */
+public class JiraVersion {
+
+ private final String id;
+ private final String description;
+ private final String name;
+ private final boolean archived;
+ private final boolean released;
+ private final String releaseDate;
+ private final String project;
+ private final Long projectId;
+
+ private JiraVersion(
+ String id,
+ String description,
+ String name,
+ boolean archived,
+ boolean released,
+ Date releaseDate,
+ String project,
+ Long projectId) {
+ this.id = id;
+ this.description = description;
+ this.name = name;
+ this.archived = archived;
+ this.released = released;
+ if (releaseDate == null) {
+ this.releaseDate = null;
+ } else {
+ this.releaseDate = new SimpleDateFormat("yyyy-MM-dd").format(releaseDate);
+ }
+ this.project = project;
+ this.projectId = projectId;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isArchived() {
+ return archived;
+ }
+
+ public boolean isReleased() {
+ return released;
+ }
+
+ public String getReleaseDate() {
+ return releaseDate;
+ }
+
+ public String getProject() {
+ return project;
+ }
+
+ public Long getProjectId() {
+ return projectId;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String id;
+ private String description;
+ private String name;
+ private boolean archived;
+ private boolean released;
+ private Date releaseDate;
+ private String project;
+ private Long projectId;
+
+ private Builder() {}
+
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder archived(boolean archived) {
+ this.archived = archived;
+ return this;
+ }
+
+ public Builder released(boolean released) {
+ this.released = released;
+ return this;
+ }
+
+ public Builder releaseDate(Date releaseDate) {
+ this.releaseDate = releaseDate;
+ return this;
+ }
+
+ public Builder project(String project) {
+ this.project = project;
+ return this;
+ }
+
+ public Builder projectId(Long projectId) {
+ this.projectId = projectId;
+ return this;
+ }
+
+ public JiraVersion build() {
+ return new JiraVersion(
+ id, description, name, archived, released, releaseDate, project, projectId);
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraVersionsPage.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraVersionsPage.java
new file mode 100644
index 0000000..5fa684f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraVersionsPage.java
@@ -0,0 +1,25 @@
+package com.googlesource.gerrit.plugins.its.jira.restapi;
+
+import java.util.List;
+
+/**
+ * Created on 03/06/18.
+ *
+ * @author Reda.Housni-Alaoui
+ */
+public class JiraVersionsPage extends JiraPage<JiraVersion> {
+ public JiraVersionsPage(
+ String self,
+ String nextPage,
+ int maxResults,
+ int startAt,
+ int total,
+ boolean isLast,
+ List<JiraVersion> values) {
+ super(self, nextPage, maxResults, startAt, total, isLast, values);
+ }
+
+ public JiraVersion findByName(String name) {
+ return this.getValues().stream().filter(v -> name.equals(v.getName())).findFirst().orElse(null);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersion.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersion.java
new file mode 100644
index 0000000..db6de54
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersion.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.jira.workflow;
+
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
+import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
+import com.googlesource.gerrit.plugins.its.base.workflow.ActionType;
+import com.googlesource.gerrit.plugins.its.base.workflow.CustomAction;
+import com.googlesource.gerrit.plugins.its.jira.JiraClient;
+import com.googlesource.gerrit.plugins.its.jira.JiraItsServerInfo;
+import com.googlesource.gerrit.plugins.its.jira.JiraItsServerInfoProvider;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Optional;
+
+public class MarkPropertyAsReleasedVersion implements CustomAction {
+
+ public static final String ACTION_NAME = "mark-property-as-released-version";
+
+ private final JiraItsServerInfoProvider serverInfoProvider;
+ private final JiraClient jiraClient;
+ private final MarkPropertyAsReleasedVersionParametersExtractor parametersExtractor;
+
+ @Inject
+ public MarkPropertyAsReleasedVersion(
+ JiraItsServerInfoProvider serverInfoProvider,
+ JiraClient jiraClient,
+ MarkPropertyAsReleasedVersionParametersExtractor parametersExtractor) {
+ this.serverInfoProvider = serverInfoProvider;
+ this.jiraClient = jiraClient;
+ this.parametersExtractor = parametersExtractor;
+ }
+
+ @Override
+ public void execute(
+ ItsFacade its, String itsProject, ActionRequest actionRequest, Map<String, String> properties)
+ throws IOException {
+ Optional<MarkPropertyAsReleasedVersionParameters> parameters =
+ parametersExtractor.extract(actionRequest, properties);
+ if (!parameters.isPresent()) {
+ return;
+ }
+ Project.NameKey projectName = new Project.NameKey(properties.get("project"));
+ JiraItsServerInfo jiraItsServerInfo = serverInfoProvider.get(projectName);
+ jiraClient.markVersionAsReleased(
+ jiraItsServerInfo, itsProject, parameters.get().getPropertyValue());
+ }
+
+ @Override
+ public ActionType getType() {
+ return ActionType.PROJECT;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParameters.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParameters.java
new file mode 100644
index 0000000..43b1a9a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParameters.java
@@ -0,0 +1,32 @@
+// 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.jira.workflow;
+
+/** Parameters needed by {@link MarkPropertyAsReleasedVersion} action */
+public class MarkPropertyAsReleasedVersionParameters {
+
+ private final String propertyValue;
+
+ public MarkPropertyAsReleasedVersionParameters(String propertyValue) {
+ this.propertyValue = propertyValue;
+ }
+
+ /**
+ * @return The extracted property value that will be used as the version value to mark as released
+ */
+ public String getPropertyValue() {
+ return propertyValue;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParametersExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParametersExtractor.java
new file mode 100644
index 0000000..d55e550
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParametersExtractor.java
@@ -0,0 +1,58 @@
+// 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.jira.workflow;
+
+import com.google.common.base.Strings;
+import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class MarkPropertyAsReleasedVersionParametersExtractor {
+
+ private static final Logger log =
+ LoggerFactory.getLogger(MarkPropertyAsReleasedVersionParametersExtractor.class);
+
+ @Inject
+ public MarkPropertyAsReleasedVersionParametersExtractor() {}
+
+ public Optional<MarkPropertyAsReleasedVersionParameters> extract(
+ ActionRequest actionRequest, Map<String, String> properties) {
+ String[] parameters = actionRequest.getParameters();
+ if (parameters.length != 1) {
+ log.error(
+ "Wrong number of received parameters. Received parameters are {}. Only one parameter is expected, the 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();
+ }
+
+ 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 MarkPropertyAsReleasedVersionParameters(propertyValue));
+ }
+}
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index db66b9b..62a30df 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -240,3 +240,21 @@
limitation and the reason why this feature is marked as experimental, i.e., not
production ready. Additional work is needed in order to offer a secure level of
encryption for this information.
+
+Specific actions
+----------------
+
+### mark-property-as-released-version
+
+The `mark-property-as-released-version` action marks a version as released in
+JIRA.
+The version to mark as released is identified by an event property value.
+
+This is useful when you want to mark a version as released in JIRA when a
+tag is created in the Gerrit project.
+
+Example with the event property `ref`:
+
+```
+ action = mark-property-as-released-version ref
+```
\ No newline at end of file
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraConfigTest.java
index 66e151e..5348e8f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraConfigTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraConfigTest.java
@@ -23,6 +23,7 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectConfig;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.junit.Before;
@@ -44,13 +45,21 @@
@Mock private PersonIdent serverUser;
@Mock private ProjectCache projectCache;
@Mock private GitRepositoryManager repoManager;
+ @Mock private ProjectConfig.Factory projectConfigFactory;
private JiraConfig jiraConfig;
@Before
public void createJiraConfig() {
jiraConfig =
- new JiraConfig(cfg, PLUGIN_NAME, cfgFactory, serverUser, projectCache, repoManager);
+ new JiraConfig(
+ cfg,
+ PLUGIN_NAME,
+ cfgFactory,
+ serverUser,
+ projectCache,
+ repoManager,
+ projectConfigFactory);
}
@Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraITTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraITTest.java
index 5ec0021..0071eea 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraITTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraITTest.java
@@ -257,7 +257,7 @@
private void createChangeWithIssue() throws Exception {
pushFactory
- .create(db, admin.getIdent(), testRepo, JIRA_ISSUE, "a.txt", "test")
+ .create(admin.newIdent(), testRepo, JIRA_ISSUE, "a.txt", "test")
.to("refs/for/master");
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java
index 9241d36..793f09f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java
@@ -31,6 +31,9 @@
private static final String ACTION = "action";
private static final String COMMENT = "comment";
private static final String ISSUE_KEY = "issueKey";
+ private static final String PROJECT_KEY = "projectKey";
+ private static final String FIELD_ID = "fieldId";
+ private static final String VALUE = "value";
@Mock private JiraClient jiraClient;
private JiraItsServerInfo server;
@@ -65,6 +68,13 @@
}
@Test
+ public void addValueToField() throws IOException {
+ jiraFacade = new JiraItsFacade(jiraClient);
+ jiraFacade.addValueToField(ISSUE_KEY, VALUE, FIELD_ID);
+ verify(jiraClient).addValueToField(server, ISSUE_KEY, VALUE, FIELD_ID);
+ }
+
+ @Test
public void performAction() throws IOException, InvalidTransitionException {
jiraFacade = new JiraItsFacade(jiraClient);
jiraFacade.performAction(ISSUE_KEY, ACTION);
@@ -72,6 +82,13 @@
}
@Test
+ public void createVersion() throws IOException {
+ jiraFacade = new JiraItsFacade(jiraClient);
+ jiraFacade.createVersion(PROJECT_KEY, "1.0");
+ verify(jiraClient).createVersion(server, PROJECT_KEY, "1.0");
+ }
+
+ @Test
public void exists() throws IOException {
jiraFacade = new JiraItsFacade(jiraClient);
jiraFacade.exists(ISSUE_KEY);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerInfoProviderTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerInfoProviderTest.java
new file mode 100644
index 0000000..c8fabc7
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerInfoProviderTest.java
@@ -0,0 +1,69 @@
+// Copyright (C) 2018 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.jira;
+
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.when;
+
+import com.google.gerrit.reviewdb.client.Project;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JiraItsServerInfoProviderTest {
+
+ private static final Project.NameKey PROJECT_NAMEKEY = new Project.NameKey("project");
+
+ @Mock private JiraConfig jiraConfig;
+ @Mock private JiraItsServerCache serverCache;
+ @Mock private JiraItsServerInfo jiraItsServerInfo;
+
+ @Rule public ExpectedException expectedException = ExpectedException.none();
+
+ private JiraItsServerInfoProvider jiraItsServerInfoProvider;
+
+ @Test
+ public void testValidServerInfoIsreturnedFromTheCache() {
+ when(jiraItsServerInfo.isValid()).thenReturn(true);
+ when(serverCache.get(PROJECT_NAMEKEY.get())).thenReturn(jiraItsServerInfo);
+ jiraItsServerInfoProvider = new JiraItsServerInfoProvider(jiraConfig, serverCache);
+ jiraItsServerInfoProvider.get(PROJECT_NAMEKEY);
+ verify(jiraConfig).addCommentLinksSection(PROJECT_NAMEKEY, jiraItsServerInfo);
+ }
+
+ @Test
+ public void testGetDefaultServerInfo() {
+ when(jiraItsServerInfo.isValid()).thenReturn(false).thenReturn(true);
+ when(serverCache.get(PROJECT_NAMEKEY.get())).thenReturn(jiraItsServerInfo);
+ when(jiraConfig.getDefaultServerInfo()).thenReturn(jiraItsServerInfo);
+ jiraItsServerInfoProvider = new JiraItsServerInfoProvider(jiraConfig, serverCache);
+ jiraItsServerInfoProvider.get(PROJECT_NAMEKEY);
+ verify(jiraConfig, never()).addCommentLinksSection(PROJECT_NAMEKEY, jiraItsServerInfo);
+ }
+
+ @Test
+ public void testNoConfiguredServerInfo() {
+ when(serverCache.get(PROJECT_NAMEKEY.get())).thenReturn(jiraItsServerInfo);
+ when(jiraItsServerInfo.isValid()).thenReturn(false).thenReturn(false);
+ when(jiraConfig.getDefaultServerInfo()).thenReturn(jiraItsServerInfo);
+ jiraItsServerInfoProvider = new JiraItsServerInfoProvider(jiraConfig, serverCache);
+ expectedException.expect(RuntimeException.class);
+ jiraItsServerInfoProvider.get(PROJECT_NAMEKEY);
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerTest.java
index 06daa15..78cb0fb 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsServerTest.java
@@ -14,7 +14,6 @@
package com.googlesource.gerrit.plugins.its.jira;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -30,43 +29,17 @@
public class JiraItsServerTest {
private static final Project.NameKey PROJECT_NAMEKEY = new Project.NameKey("project");
- @Mock private JiraConfig jiraConfig;
+ @Mock private JiraItsServerInfoProvider jiraItsserverInfoProvider;
@Mock private JiraItsFacade itsFacade;
- @Mock private JiraItsServerCache serverCache;
@Mock private JiraItsServerInfo jiraItsServerInfo;
@Rule public ExpectedException expectedException = ExpectedException.none();
- private JiraItsServer jiraItsServer;
-
@Test
- public void testValidServerInfoIsreturnedFromTheCache() throws Exception {
- when(jiraItsServerInfo.isValid()).thenReturn(true);
- when(serverCache.get(PROJECT_NAMEKEY.get())).thenReturn(jiraItsServerInfo);
- jiraItsServer = new JiraItsServer(jiraConfig, itsFacade, serverCache);
+ public void testGetFacade() {
+ when(jiraItsserverInfoProvider.get(PROJECT_NAMEKEY)).thenReturn(jiraItsServerInfo);
+ JiraItsServer jiraItsServer = new JiraItsServer(jiraItsserverInfoProvider, itsFacade);
jiraItsServer.getFacade(PROJECT_NAMEKEY);
- verify(jiraConfig).addCommentLinksSection(PROJECT_NAMEKEY, jiraItsServerInfo);
verify(itsFacade).setJiraServerInstance(jiraItsServerInfo);
}
-
- @Test
- public void testGetDefaultServerInfo() throws Exception {
- when(jiraItsServerInfo.isValid()).thenReturn(false).thenReturn(true);
- when(serverCache.get(PROJECT_NAMEKEY.get())).thenReturn(jiraItsServerInfo);
- when(jiraConfig.getDefaultServerInfo()).thenReturn(jiraItsServerInfo);
- jiraItsServer = new JiraItsServer(jiraConfig, itsFacade, serverCache);
- jiraItsServer.getFacade(PROJECT_NAMEKEY);
- verify(jiraConfig, never()).addCommentLinksSection(PROJECT_NAMEKEY, jiraItsServerInfo);
- verify(itsFacade).setJiraServerInstance(jiraItsServerInfo);
- }
-
- @Test
- public void testNoConfiguredServerInfo() throws Exception {
- when(serverCache.get(PROJECT_NAMEKEY.get())).thenReturn(jiraItsServerInfo);
- when(jiraItsServerInfo.isValid()).thenReturn(false).thenReturn(false);
- when(jiraConfig.getDefaultServerInfo()).thenReturn(jiraItsServerInfo);
- jiraItsServer = new JiraItsServer(jiraConfig, itsFacade, serverCache);
- expectedException.expect(RuntimeException.class);
- jiraItsServer.getFacade(PROJECT_NAMEKEY);
- }
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssueUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssueUpdateTest.java
new file mode 100644
index 0000000..1ecba22
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssueUpdateTest.java
@@ -0,0 +1,50 @@
+// 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.jira.restapi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.json.OutputFormat;
+import com.google.gson.Gson;
+import org.junit.Test;
+
+public class JiraIssueUpdateTest {
+
+ private static final String FIELD_ID = "fieldId";
+ private static final String OPERATION = "operation";
+ private static final String VALUE = "value";
+
+ @Test
+ public void testSerialization() {
+ JiraIssueUpdate issueUpdate =
+ JiraIssueUpdate.builder().appendUpdate(FIELD_ID, OPERATION, VALUE).build();
+
+ assertThat(newGson().toJson(issueUpdate))
+ .isEqualTo("{\"update\":{\"fieldId\":[{\"operation\":\"value\"}]}}");
+ }
+
+ @Test
+ public void testSerializationForFixVersions() {
+ JiraIssueUpdate issueUpdate =
+ JiraIssueUpdate.builder().appendUpdate("fixVersions", OPERATION, VALUE).build();
+
+ assertThat(newGson().toJson(issueUpdate))
+ .isEqualTo("{\"update\":{\"fixVersions\":[{\"operation\":{\"name\":\"value\"}}]}}");
+ }
+
+ private Gson newGson() {
+ return OutputFormat.JSON_COMPACT.newGson();
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParametersExtractorTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParametersExtractorTest.java
new file mode 100644
index 0000000..81dc49a
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionParametersExtractorTest.java
@@ -0,0 +1,90 @@
+// 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.jira.workflow;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
+import java.util.Collections;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MarkPropertyAsReleasedVersionParametersExtractorTest {
+
+ private static final String PROPERTY_ID = "propertyId";
+ private static final String PROPERTY_VALUE = "propertyValue";
+
+ private MarkPropertyAsReleasedVersionParametersExtractor extractor;
+
+ @Before
+ public void before() {
+ extractor = new MarkPropertyAsReleasedVersionParametersExtractor();
+ }
+
+ @Test
+ public void testNoParameter() {
+ testWrongNumberOfReceivedParameters(new String[] {});
+ }
+
+ @Test
+ public void testTwoParameters() {
+ testWrongNumberOfReceivedParameters(new String[] {PROPERTY_ID, PROPERTY_ID});
+ }
+
+ private void testWrongNumberOfReceivedParameters(String[] parameters) {
+ ActionRequest actionRequest = mock(ActionRequest.class);
+ when(actionRequest.getParameters()).thenReturn(parameters);
+
+ Optional<MarkPropertyAsReleasedVersionParameters> extractedParameters =
+ extractor.extract(actionRequest, Collections.emptyMap());
+ assertFalse(extractedParameters.isPresent());
+ }
+
+ @Test
+ public void testBlankPropertyId() {
+ ActionRequest actionRequest = mock(ActionRequest.class);
+ when(actionRequest.getParameters()).thenReturn(new String[] {""});
+
+ Optional<MarkPropertyAsReleasedVersionParameters> extractedParameters =
+ extractor.extract(actionRequest, Collections.emptyMap());
+ assertFalse(extractedParameters.isPresent());
+ }
+
+ @Test
+ public void testUnknownPropertyId() {
+ ActionRequest actionRequest = mock(ActionRequest.class);
+ when(actionRequest.getParameters()).thenReturn(new String[] {PROPERTY_ID});
+
+ Optional<MarkPropertyAsReleasedVersionParameters> extractedParameters =
+ extractor.extract(actionRequest, Collections.emptyMap());
+ assertFalse(extractedParameters.isPresent());
+ }
+
+ @Test
+ public void testHappyPath() {
+ ActionRequest actionRequest = mock(ActionRequest.class);
+ when(actionRequest.getParameters()).thenReturn(new String[] {PROPERTY_ID});
+
+ Optional<MarkPropertyAsReleasedVersionParameters> extractedParameters =
+ extractor.extract(actionRequest, Collections.singletonMap(PROPERTY_ID, PROPERTY_VALUE));
+ assertTrue(extractedParameters.isPresent());
+ assertEquals(PROPERTY_VALUE, extractedParameters.get().getPropertyValue());
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionTest.java
new file mode 100644
index 0000000..ad29c2a
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/workflow/MarkPropertyAsReleasedVersionTest.java
@@ -0,0 +1,80 @@
+// 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.jira.workflow;
+
+import static org.mockito.Mockito.*;
+
+import com.google.gerrit.reviewdb.client.Project;
+import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
+import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
+import com.googlesource.gerrit.plugins.its.jira.JiraClient;
+import com.googlesource.gerrit.plugins.its.jira.JiraItsServerInfo;
+import com.googlesource.gerrit.plugins.its.jira.JiraItsServerInfoProvider;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MarkPropertyAsReleasedVersionTest {
+
+ private static final String ITS_PROJECT = "test-project";
+ private static final String PROJECT_KEY = "project";
+ private static final String PROJECT_NAME = "projectName";
+ private static final String PROPERTY_ID = "propertyId";
+ private static final String PROPERTY_VALUE = "propertyValue";
+
+ private ItsFacade its;
+ private JiraItsServerInfo serverInfo;
+ private JiraClient jiraClient;
+ private MarkPropertyAsReleasedVersionParametersExtractor parametersExtractor;
+ private MarkPropertyAsReleasedVersion markPropertyAsReleasedVersion;
+
+ @Before
+ public void before() {
+ its = mock(ItsFacade.class);
+ JiraItsServerInfoProvider serverInfoProvider = mock(JiraItsServerInfoProvider.class);
+ serverInfo = mock(JiraItsServerInfo.class);
+ when(serverInfoProvider.get(new Project.NameKey(PROJECT_NAME))).thenReturn(serverInfo);
+ jiraClient = mock(JiraClient.class);
+ parametersExtractor = mock(MarkPropertyAsReleasedVersionParametersExtractor.class);
+ markPropertyAsReleasedVersion =
+ new MarkPropertyAsReleasedVersion(serverInfoProvider, jiraClient, parametersExtractor);
+ }
+
+ @Test
+ public void testHappyPath() throws IOException {
+ MarkPropertyAsReleasedVersionParameters extractedParameters =
+ mock(MarkPropertyAsReleasedVersionParameters.class);
+ when(extractedParameters.getPropertyValue()).thenReturn(PROPERTY_VALUE);
+
+ ActionRequest actionRequest = mock(ActionRequest.class);
+ Map<String, String> properties = buildProperties();
+ when(parametersExtractor.extract(actionRequest, properties))
+ .thenReturn(Optional.of(extractedParameters));
+
+ markPropertyAsReleasedVersion.execute(its, ITS_PROJECT, actionRequest, properties);
+
+ verify(jiraClient).markVersionAsReleased(serverInfo, ITS_PROJECT, PROPERTY_VALUE);
+ }
+
+ private Map<String, String> buildProperties() {
+ Map<String, String> properties = new HashMap<>();
+ properties.put(PROPERTY_ID, PROJECT_NAME);
+ properties.put(PROJECT_KEY, PROJECT_NAME);
+ return properties;
+ }
+}