package it;
import com.sonar.orchestrator.Orchestrator;
-import it.actionPlan.ActionPlanTest;
import it.administration.UsersPageTest;
import it.authorisation.DashboardSharingPermissionTest;
import it.authorisation.ExecuteAnalysisPermissionTest;
SincePreviousVersionHistoryTest.class,
SinceXDaysHistoryTest.class,
TimeMachineTest.class,
- // action plan
- ActionPlanTest.class,
// source code
EncodingTest.class,
HighlightingTest.class,
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package it.actionPlan;
-
-import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.locator.FileLocation;
-import it.Category1Suite;
-import java.util.List;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.wsclient.SonarClient;
-import org.sonar.wsclient.base.HttpException;
-import org.sonar.wsclient.issue.ActionPlan;
-import org.sonar.wsclient.issue.ActionPlanClient;
-import org.sonar.wsclient.issue.Issue;
-import org.sonar.wsclient.issue.IssueClient;
-import org.sonar.wsclient.issue.IssueQuery;
-import org.sonar.wsclient.issue.Issues;
-import org.sonar.wsclient.issue.NewActionPlan;
-import org.sonar.wsclient.issue.UpdateActionPlan;
-import org.sonar.wsclient.user.UserParameters;
-import org.sonarqube.ws.client.WsClient;
-import org.sonarqube.ws.client.permission.AddUserWsRequest;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static util.ItUtils.newAdminWsClient;
-import static util.ItUtils.runProjectAnalysis;
-import static util.ItUtils.toDate;
-import static util.ItUtils.verifyHttpException;
-
-import util.QaOnly;
-
-@Category(QaOnly.class)
-public class ActionPlanTest {
-
- @ClassRule
- public static final Orchestrator orchestrator = Category1Suite.ORCHESTRATOR;
- private static WsClient adminWsClient;
- private static final String PROJECT_KEY = "sample";
-
- @BeforeClass
- public static void analyzeProject() {
- orchestrator.resetData();
-
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/actionPlan/one-issue-per-line-profile.xml"));
- orchestrator.getServer().provisionProject("sample", "Sample");
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line-profile");
- runProjectAnalysis(orchestrator, "shared/xoo-sample");
-
- adminWsClient = newAdminWsClient(orchestrator);
- }
-
- protected static ActionPlanClient adminActionPlanClient() {
- return orchestrator.getServer().adminWsClient().actionPlanClient();
- }
-
- protected static ActionPlanClient actionPlanClient() {
- return orchestrator.getServer().wsClient().actionPlanClient();
- }
-
- protected static ActionPlan firstActionPlan(String projectKey) {
- List<ActionPlan> actionPlans = actionPlanClient().find(projectKey);
- assertThat(actionPlans).hasSize(1);
- return actionPlans.get(0);
- }
-
- protected static IssueClient adminIssueClient() {
- return orchestrator.getServer().adminWsClient().issueClient();
- }
-
- protected static Issue searchRandomIssue() {
- List<Issue> issues = search(IssueQuery.create()).list();
- assertThat(issues).isNotEmpty();
- return issues.get(0);
- }
-
- protected static Issues search(IssueQuery issueQuery) {
- return issueClient().find(issueQuery);
- }
-
- protected static IssueClient issueClient() {
- return orchestrator.getServer().wsClient().issueClient();
- }
-
- @Before
- public void resetData() {
- // TODO should be done by a WS
- orchestrator.getDatabase().truncate("action_plans");
- assertThat(adminActionPlanClient().find(PROJECT_KEY)).isEmpty();
- }
-
- @Test
- public void create_action_plan() {
- assertThat(adminActionPlanClient().find(PROJECT_KEY)).isEmpty();
-
- ActionPlan newActionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
- assertThat(newActionPlan.key()).isNotNull();
-
- ActionPlan actionPlan = firstActionPlan(PROJECT_KEY);
- assertThat(actionPlan.name()).isEqualTo("Short term");
- assertThat(actionPlan.description()).isEqualTo("Short term issues");
- assertThat(actionPlan.status()).isEqualTo("OPEN");
- assertThat(actionPlan.project()).isEqualTo(PROJECT_KEY);
- assertThat(actionPlan.deadLine()).isNotNull();
- assertThat(actionPlan.createdAt()).isNotNull();
- assertThat(actionPlan.updatedAt()).isNotNull();
- assertThat(actionPlan.totalIssues()).isEqualTo(0);
- assertThat(actionPlan.unresolvedIssues()).isEqualTo(0);
- }
-
- /**
- * SONAR-5179
- */
- @Test
- public void need_project_administrator_permission_to_create_action_plan() {
- String projectAdminUser = "with-admin-permission-on-project";
- String projectUser = "with-user-permission-on-project";
- SonarClient adminClient = orchestrator.getServer().adminWsClient();
- try {
- // Create a user having admin permission on the project
- adminClient.userClient().create(UserParameters.create().login(projectAdminUser).name(projectAdminUser).password("password").passwordConfirmation("password"));
- adminWsClient.permissions().addUser(
- new AddUserWsRequest()
- .setLogin(projectAdminUser)
- .setProjectKey(PROJECT_KEY)
- .setPermission("admin"));
-
- // Create a user having browse permission on the project
- adminClient.userClient().create(UserParameters.create().login(projectUser).name(projectUser).password("password").passwordConfirmation("password"));
- adminWsClient.permissions().addUser(
- new AddUserWsRequest()
- .setLogin(projectUser)
- .setProjectKey(PROJECT_KEY)
- .setPermission("user"));
-
- // Without project admin permission, a user cannot set action plan
- try {
- orchestrator.getServer().wsClient(projectUser, "password").actionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues"));
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(HttpException.class).describedAs("404");
- }
-
- // With project admin permission, a user can set action plan
- orchestrator.getServer().wsClient(projectAdminUser, "password").actionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues"));
- assertThat(actionPlanClient().find(PROJECT_KEY)).hasSize(1);
-
- } finally {
- adminClient.userClient().deactivate(projectAdminUser);
- adminClient.userClient().deactivate(projectUser);
- }
- }
-
- @Test
- public void fail_create_action_plan_if_missing_project() {
- try {
- adminActionPlanClient().create(NewActionPlan.create().name("Short term")
- .description("Short term issues").deadLine(toDate("2113-01-31")));
- fail();
- } catch (Exception e) {
- verifyHttpException(e, 400);
- }
- }
-
- @Test
- public void fail_create_action_plan_if_missing_name() {
- try {
- adminActionPlanClient().create(NewActionPlan.create().project(PROJECT_KEY)
- .description("Short term issues").deadLine(toDate("2113-01-31")));
- fail();
- } catch (Exception e) {
- verifyHttpException(e, 400);
- }
- }
-
- @Test
- public void update_action_plan() {
- ActionPlan newActionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
-
- ActionPlan updatedActionPlan = adminActionPlanClient().update(
- UpdateActionPlan.create().key(newActionPlan.key()).name("Long term").description("Long term issues").deadLine(toDate("2114-12-01")));
- assertThat(updatedActionPlan).isNotNull();
-
- ActionPlan actionPlan = firstActionPlan(PROJECT_KEY);
- assertThat(actionPlan.name()).isEqualTo("Long term");
- assertThat(actionPlan.description()).isEqualTo("Long term issues");
- assertThat(actionPlan.project()).isEqualTo(PROJECT_KEY);
- assertThat(actionPlan.deadLine()).isNotNull();
- assertThat(actionPlan.deadLine()).isNotEqualTo(newActionPlan.deadLine());
- assertThat(actionPlan.updatedAt()).isNotNull();
- }
-
- @Test
- public void fail_update_action_plan_if_missing_name() {
- try {
- adminActionPlanClient().create(
- NewActionPlan.create().project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
- fail();
- } catch (Exception e) {
- verifyHttpException(e, 400);
- }
- }
-
- @Test
- public void delete_action_plan() {
- ActionPlan newActionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
-
- adminActionPlanClient().delete(newActionPlan.key());
-
- List<ActionPlan> results = adminActionPlanClient().find(PROJECT_KEY);
- assertThat(results).isEmpty();
- }
-
- /**
- * SONAR-4449
- */
- @Test
- public void delete_action_plan_also_unplan_linked_issues() {
- // Create action plan
- ActionPlan newActionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
-
- Issue issue = searchRandomIssue();
- // Link an issue to the action plan
- adminIssueClient().plan(issue.key(), newActionPlan.key());
- // Delete action plan
- adminActionPlanClient().delete(newActionPlan.key());
-
- // Reload the issue
- Issue reloaded = searchIssueByKey(issue.key());
- assertThat(reloaded.actionPlan()).isNull();
- }
-
- @Test
- public void close_action_plan() {
- ActionPlan newActionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
- assertThat(firstActionPlan(PROJECT_KEY).status()).isEqualTo("OPEN");
-
- adminActionPlanClient().close(newActionPlan.key());
-
- ActionPlan actionPlan = firstActionPlan(PROJECT_KEY);
- assertThat(actionPlan.status()).isEqualTo("CLOSED");
- }
-
- @Test
- public void open_action_plan() {
- ActionPlan newActionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
-
- adminActionPlanClient().close(newActionPlan.key());
- adminActionPlanClient().open(newActionPlan.key());
-
- ActionPlan actionPlan = firstActionPlan(PROJECT_KEY);
- assertThat(actionPlan.status()).isEqualTo("OPEN");
- }
-
- @Test
- public void find_action_plans() {
- assertThat(actionPlanClient().find(PROJECT_KEY)).isEmpty();
-
- adminActionPlanClient().create(NewActionPlan.create().name("Short term").project(PROJECT_KEY).description("Short term issues").deadLine(toDate("2113-01-31")));
- adminActionPlanClient().create(NewActionPlan.create().name("Long term").project(PROJECT_KEY).description("Long term issues"));
-
- assertThat(actionPlanClient().find(PROJECT_KEY)).hasSize(2);
- }
-
- protected Issue searchIssueByKey(String issueKey) {
- IssueQuery query = IssueQuery.create().issues(issueKey);
- query.urlParams().put("additionalFields", "_all");
- List<Issue> issues = search(query).list();
- assertThat(issues).hasSize(1);
- return issues.get(0);
- }
-
-}
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonar.wsclient.base.HttpException;
-import org.sonar.wsclient.issue.ActionPlan;
-import org.sonar.wsclient.issue.ActionPlanClient;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueComment;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonar.wsclient.issue.Issues;
-import org.sonar.wsclient.issue.NewActionPlan;
import util.ProjectAnalysis;
import util.ProjectAnalysisRule;
import util.QaOnly;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
-import static util.ItUtils.toDate;
import static util.ItUtils.verifyHttpException;
@Category(QaOnly.class)
}
}
- /**
- * SONAR-4290
- */
- @Test
- public void plan() {
- assertThat(issue.actionPlan()).isNull();
-
- // Set action plan to issue
- ActionPlan newActionPlan = adminActionPlanClient().create(NewActionPlan.create().name("Short term").project("sample")
- .description("Short term issues").deadLine(toDate("2113-01-31")));
- assertThat(newActionPlan.key()).isNotNull();
- adminIssueClient().plan(issue.key(), newActionPlan.key());
- Assertions.assertThat(search(IssueQuery.create().actionPlans(newActionPlan.key())).list()).hasSize(1);
-
- projectAnalysis.run();
- Issue reloaded = searchIssueByKey(issue.key());
- assertThat(reloaded.actionPlan()).isEqualTo(newActionPlan.key());
- assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate());
- ActionPlan actionPlan = search(IssueQuery.create().actionPlans(newActionPlan.key())).actionPlans(reloaded);
- assertThat(actionPlan.name()).isEqualTo(newActionPlan.name());
- assertThat(actionPlan.deadLine()).isEqualTo(newActionPlan.deadLine());
- }
-
- @Test
- public void fail_plan_if_action_plan_does_not_exist() {
- assertThat(issue.actionPlan()).isNull();
- try {
- adminIssueClient().plan(issue.key(), "unknown");
- fail();
- } catch (Exception e) {
- verifyHttpException(e, 400);
- }
- }
-
- @Test
- public void unplan() {
- assertThat(issue.actionPlan()).isNull();
-
- // Set action plan to issue
- ActionPlan newActionPlan = adminActionPlanClient().create(NewActionPlan.create().name("Short term").project("sample")
- .description("Short term issues").deadLine(toDate("2113-01-31")));
- assertThat(newActionPlan.key()).isNotNull();
- adminIssueClient().plan(issue.key(), newActionPlan.key());
- Assertions.assertThat(search(IssueQuery.create().actionPlans(newActionPlan.key())).list()).hasSize(1);
-
- // Unplan
- adminIssueClient().plan(issue.key(), null);
- Assertions.assertThat(search(IssueQuery.create().actionPlans(newActionPlan.key())).list()).hasSize(0);
-
- projectAnalysis.run();
- Issue reloaded = searchIssueByKey(issue.key());
- assertThat(reloaded.actionPlan()).isNull();
- assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate());
- }
-
private static List<Issue> searchIssuesBySeverities(String componentKey, String... severities) {
return searchIssues(IssueQuery.create().componentRoots(componentKey).severities(severities));
}
- private static ActionPlanClient adminActionPlanClient() {
- return ORCHESTRATOR.getServer().adminWsClient().actionPlanClient();
- }
-
}
import org.sonar.wsclient.base.HttpException;
import org.sonar.wsclient.base.Paging;
import org.sonar.wsclient.component.Component;
-import org.sonar.wsclient.issue.ActionPlan;
-import org.sonar.wsclient.issue.ActionPlanClient;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonar.wsclient.issue.Issues;
-import org.sonar.wsclient.issue.NewActionPlan;
import org.sonar.wsclient.issue.NewIssue;
import org.sonarqube.ws.Common;
import org.sonarqube.ws.MediaTypes;
}
- @Test
- public void search_issues_by_action_plans() {
- // Create an action plan
- ActionPlan actionPlan = adminActionPlanClient().create(
- NewActionPlan.create().name("Short term").project("com.sonarsource.it.samples:multi-modules-sample").description("Short term issues")
- .deadLine(toDate("2113-01-31")));
-
- // Associate this action plan to an issue
- adminIssueClient().plan(searchRandomIssue().key(), actionPlan.key());
-
- assertThat(search(IssueQuery.create().actionPlans(actionPlan.key())).list()).hasSize(1);
- assertThat(search(IssueQuery.create().actionPlans("unknown")).list()).isEmpty();
- }
-
/**
* SONAR-5132
*/
));
}
- private static ActionPlanClient adminActionPlanClient() {
- return ORCHESTRATOR.getServer().adminWsClient().actionPlanClient();
- }
-
}
issue.setFilePath("src/main/java/Foo" + currentFile);
issue.setComponentUuid("FILE" + currentFile);
issue.setProjectUuid("PROJECT" + currentProject);
- issue.setActionPlanKey("PLAN" + currentProject);
issue.setAssignee(users.next());
issue.setAuthorLogin(users.next());
issue.setLine(RandomUtils.nextInt());
private final Collection<String> files;
private final Collection<String> views;
private final Collection<RuleKey> rules;
- private final Collection<String> actionPlans;
private final Collection<String> reporters;
private final Collection<String> assignees;
private final Collection<String> authors;
private final Collection<String> types;
private final Boolean onComponentOnly;
private final Boolean assigned;
- private final Boolean planned;
private final Boolean resolved;
private final Boolean hideRules;
private final Boolean hideComments;
this.files = defaultCollection(builder.files);
this.views = defaultCollection(builder.views);
this.rules = defaultCollection(builder.rules);
- this.actionPlans = defaultCollection(builder.actionPlans);
this.reporters = defaultCollection(builder.reporters);
this.assignees = defaultCollection(builder.assignees);
this.authors = defaultCollection(builder.authors);
this.types = defaultCollection(builder.types);
this.onComponentOnly = builder.onComponentOnly;
this.assigned = builder.assigned;
- this.planned = builder.planned;
this.resolved = builder.resolved;
this.hideRules = builder.hideRules;
this.hideComments = builder.hideComments;
return rules;
}
- public Collection<String> actionPlans() {
- return actionPlans;
- }
-
public Collection<String> reporters() {
return reporters;
}
return assigned;
}
- @CheckForNull
- public Boolean planned() {
- return planned;
- }
-
@CheckForNull
public Boolean resolved() {
return resolved;
private Collection<String> files;
private Collection<String> views;
private Collection<RuleKey> rules;
- private Collection<String> actionPlans;
private Collection<String> reporters;
private Collection<String> assignees;
private Collection<String> authors;
private Collection<String> types;
private Boolean onComponentOnly = false;
private Boolean assigned = null;
- private Boolean planned = null;
private Boolean resolved = null;
private Boolean hideRules = false;
private Boolean hideComments = false;
return this;
}
- public Builder actionPlans(@Nullable Collection<String> l) {
- this.actionPlans = l;
- return this;
- }
-
public Builder reporters(@Nullable Collection<String> l) {
this.reporters = l;
return this;
return this;
}
- /**
- * If true, it will return all issues linked to an action plan
- * If false, it will return all issues not linked to an action plan
- */
- public Builder planned(@Nullable Boolean planned) {
- this.planned = planned;
- return this;
- }
-
/**
* If true, it will return all resolved issues
* If false, it will return all none resolved issues
.resolutions(RubyUtils.toStrings(params.get(IssueFilterParameters.RESOLUTIONS)))
.resolved(RubyUtils.toBoolean(params.get(IssueFilterParameters.RESOLVED)))
.rules(toRules(params.get(IssueFilterParameters.RULES)))
- .actionPlans(RubyUtils.toStrings(params.get(IssueFilterParameters.ACTION_PLANS)))
.reporters(RubyUtils.toStrings(params.get(IssueFilterParameters.REPORTERS)))
.assignees(buildAssignees(RubyUtils.toStrings(params.get(IssueFilterParameters.ASSIGNEES))))
.languages(RubyUtils.toStrings(params.get(IssueFilterParameters.LANGUAGES)))
.tags(RubyUtils.toStrings(params.get(IssueFilterParameters.TAGS)))
.types(RubyUtils.toStrings(params.get(IssueFilterParameters.TYPES)))
.assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED)))
- .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED)))
.hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES)))
.createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT)))
.createdAfter(buildCreatedAfterFromDates(RubyUtils.toDate(params.get(CREATED_AFTER)), (String) params.get(CREATED_IN_LAST)))
.resolutions(request.getResolutions())
.resolved(request.getResolved())
.rules(stringsToRules(request.getRules()))
- .actionPlans(request.getActionPlans())
.reporters(request.getReporters())
.assignees(buildAssignees(request.getAssignees()))
.languages(request.getLanguages())
.tags(request.getTags())
.types(request.getTypes())
.assigned(request.getAssigned())
- .planned(request.getPlanned())
.createdAt(parseAsDateTime(request.getCreatedAt()))
.createdBefore(parseAsDateTime(request.getCreatedBefore()))
.facetMode(request.getFacetMode());
}
}
+ //TODO to delete
public void plan(String issueKey, @Nullable String actionPlanKey) {
userSession.checkLoggedIn();
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import com.google.common.base.Strings;
-import java.util.Collection;
-import java.util.Map;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.condition.IsUnResolved;
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.user.UserSession;
-
-@ServerSide
-public class PlanAction extends Action {
-
- public static final String PLAN_KEY = "plan";
- public static final String VERIFIED_ACTION_PLAN = "verifiedActionPlan";
-
- private final ActionPlanService actionPlanService;
- private final IssueUpdater issueUpdater;
-
- public PlanAction(ActionPlanService actionPlanService, IssueUpdater issueUpdater) {
- super(PLAN_KEY);
- this.actionPlanService = actionPlanService;
- this.issueUpdater = issueUpdater;
- super.setConditions(new IsUnResolved());
- }
-
- @Override
- public boolean verify(Map<String, Object> properties, Collection<Issue> issues, UserSession userSession) {
- String actionPlanValue = planValue(properties);
- if (!Strings.isNullOrEmpty(actionPlanValue)) {
- ActionPlan actionPlan = selectActionPlan(actionPlanValue, userSession);
- if (actionPlan == null) {
- throw new IllegalArgumentException("Unknown action plan: " + actionPlanValue);
- }
- verifyIssuesAreAllRelatedOnActionPlanProject(issues, actionPlan);
- properties.put(VERIFIED_ACTION_PLAN, actionPlan);
- } else {
- properties.put(VERIFIED_ACTION_PLAN, null);
- }
- return true;
- }
-
- @Override
- public boolean execute(Map<String, Object> properties, Context context) {
- if (!properties.containsKey(VERIFIED_ACTION_PLAN)) {
- throw new IllegalArgumentException("Action plan is missing from the execution parameters");
- }
- ActionPlan actionPlan = (ActionPlan) properties.get(VERIFIED_ACTION_PLAN);
- return issueUpdater.plan((DefaultIssue) context.issue(), actionPlan, context.issueChangeContext());
- }
-
- private String planValue(Map<String, Object> properties) {
- return (String) properties.get("plan");
- }
-
- private void verifyIssuesAreAllRelatedOnActionPlanProject(Collection<Issue> issues, ActionPlan actionPlan) {
- String projectKey = actionPlan.projectKey();
- for (Issue issue : issues) {
- DefaultIssue defaultIssue = (DefaultIssue) issue;
- String issueProjectKey = defaultIssue.projectKey();
- if (issueProjectKey == null || !issueProjectKey.equals(projectKey)) {
- throw new IllegalArgumentException("Issues are not all related to the action plan project: " + projectKey);
- }
- }
- }
-
- private ActionPlan selectActionPlan(String planValue, UserSession userSession) {
- return actionPlanService.findByKey(planValue, userSession);
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.actionplan;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.RailsHandler;
-import org.sonar.api.server.ws.WebService;
-
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-
-public class ActionPlanWs implements WebService {
-
- @Override
- public void define(Context context) {
- NewController controller = context.createController("api/action_plans");
- controller.setDescription("Action plans management");
-
- defineSearchAction(controller);
- defineCreateAction(controller);
- defineUpdateAction(controller);
- defineDeleteAction(controller);
- defineOpenAction(controller);
- defineCloseAction(controller);
-
- controller.done();
- }
-
- private static void defineSearchAction(NewController controller) {
- WebService.NewAction action = controller.createAction("search")
- .setDescription("Get a list of action plans. Requires Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setResponseExample(Resources.getResource(ActionPlanWs.class, "example-search.json"));
- addProjectParam(action);
- addFormatParam(action);
- }
-
- private static void defineCreateAction(NewController controller) {
- WebService.NewAction action = controller.createAction("create")
- .setDescription("Create an action plan. Requires Administer permission on project")
- .setSince("3.6")
- .setPost(true)
- .setHandler(RailsHandler.INSTANCE);
- addNameParam(action);
- addDescriptionParam(action);
- addDeadLineParam(action);
- addProjectParam(action);
- addFormatParam(action);
- }
-
- private static void defineUpdateAction(NewController controller) {
- WebService.NewAction action = controller.createAction("update")
- .setDescription("Update an action plan. Requires Administer permission on project")
- .setSince("3.6")
- .setPost(true)
- .setHandler(RailsHandler.INSTANCE);
- addKeyParam(action);
- addNameParam(action);
- addDescriptionParam(action);
- addDeadLineParam(action);
- addFormatParam(action);
- }
-
- private static void defineDeleteAction(NewController controller) {
- WebService.NewAction action = controller.createAction("delete")
- .setDescription("Delete an action plan. Requires Administer permission on project")
- .setSince("3.6")
- .setPost(true)
- .setHandler(RailsHandler.INSTANCE);
- addKeyParam(action);
- addFormatParam(action);
- }
-
- private static void defineOpenAction(NewController controller) {
- WebService.NewAction action = controller.createAction("open")
- .setDescription("Open an action plan. Requires Administer permission on project")
- .setSince("3.6")
- .setPost(true)
- .setHandler(RailsHandler.INSTANCE);
- addKeyParam(action);
- addFormatParam(action);
- }
-
- private static void defineCloseAction(NewController controller) {
- WebService.NewAction action = controller.createAction("close")
- .setDescription("Close an action plan. Requires Administer permission on project")
- .setSince("3.6")
- .setPost(true)
- .setHandler(RailsHandler.INSTANCE);
- addKeyParam(action);
- addFormatParam(action);
- }
-
- private static NewParam addKeyParam(WebService.NewAction action) {
- return action.createParam("key")
- .setDescription("Key of the action plan")
- .setExampleValue("3f19de90-1521-4482-a737-a311758ff513")
- .setRequired(true);
- }
-
- private static NewParam addNameParam(WebService.NewAction action) {
- return action.createParam("name")
- .setDescription("Name of the action plan")
- .setExampleValue("Version 3.6")
- .setRequired(true);
- }
-
- private static NewParam addDescriptionParam(WebService.NewAction action) {
- return action.createParam("description")
- .setDescription("Description of the action plan")
- .setExampleValue("Version 3.6");
- }
-
- private static NewParam addDeadLineParam(WebService.NewAction action) {
- return action.createParam("deadLine")
- .setDescription("Due date of the action plan. Format: YYYY-MM-DD")
- .setExampleValue("2013-12-31");
- }
-
- private static NewParam addProjectParam(WebService.NewAction action) {
- return action.createParam("project")
- .setDescription("Project key")
- .setExampleValue(KEY_PROJECT_EXAMPLE_001)
- .setRequired(true);
- }
-
- private static NewParam addFormatParam(WebService.NewAction action) {
- return RailsHandler.addFormatParam(action);
- }
-}
@Override
@CheckForNull
public String actionPlanKey() {
- return getNullableField(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN);
+ // since 5.5, action plan is dropped. Kept for API compatibility
+ return null;
}
@CheckForNull
return this;
}
- public IssueDoc setActionPlanKey(@Nullable String s) {
- setField(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN, s);
- return this;
- }
-
public IssueDoc setEffort(@Nullable Long l) {
setField(IssueIndexDefinition.FIELD_ISSUE_EFFORT, l);
return this;
import org.sonar.server.view.index.ViewIndexDefinition;
import static com.google.common.collect.Lists.newArrayList;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.AUTHORS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AT;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.DEPRECATED_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.DEPRECATED_FACET_MODE_DEBT;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.FACET_ASSIGNED_TO_ME;
SEVERITIES,
STATUSES,
RESOLUTIONS,
- ACTION_PLANS,
+ DEPRECATED_ACTION_PLANS,
PROJECT_UUIDS,
RULES,
ASSIGNEES,
filters.put(IS_ASSIGNED_FILTER, FilterBuilders.missingFilter(IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE));
}
- // Issue is planned Filter
- String isPlanned = "__isPlanned";
- if (BooleanUtils.isTrue(query.planned())) {
- filters.put(isPlanned, FilterBuilders.existsFilter(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN));
- } else if (BooleanUtils.isFalse(query.planned())) {
- filters.put(isPlanned, FilterBuilders.missingFilter(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN));
- }
-
// Issue is Resolved Filter
String isResolved = "__isResolved";
if (BooleanUtils.isTrue(query.resolved())) {
// Field Filters
filters.put(IssueIndexDefinition.FIELD_ISSUE_KEY, createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_KEY, query.issueKeys()));
- filters.put(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN, createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN, query.actionPlans()));
filters.put(IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE, createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE, query.assignees()));
addComponentRelatedFilters(query, filters);
esSearch.addAggregation(createAssigneesFacet(query, filters, esQuery));
}
addAssignedToMeFacetIfNeeded(esSearch, options, query, filters, esQuery);
- if (options.getFacets().contains(ACTION_PLANS)) {
- esSearch.addAggregation(createActionPlansFacet(query, filters, esQuery));
- }
if (options.getFacets().contains(CREATED_AT)) {
esSearch.addAggregation(getCreatedAtFacet(query, filters, esQuery));
}
.subAggregation(facetTopAggregation);
}
- private static AggregationBuilder createActionPlansFacet(IssueQuery query, Map<String, FilterBuilder> filters, QueryBuilder esQuery) {
- String fieldName = IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN;
- String facetName = ACTION_PLANS;
-
- // Same as in super.stickyFacetBuilder
- Map<String, FilterBuilder> actionPlanFilters = Maps.newHashMap(filters);
- actionPlanFilters.remove("__isPlanned");
- actionPlanFilters.remove(fieldName);
- StickyFacetBuilder actionPlanFacetBuilder = newStickyFacetBuilder(query, actionPlanFilters, esQuery);
- BoolFilterBuilder facetFilter = actionPlanFacetBuilder.getStickyFacetFilter(fieldName);
- FilterAggregationBuilder facetTopAggregation = actionPlanFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
- facetTopAggregation = actionPlanFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.actionPlans().toArray());
-
- // Add missing facet for unresolved issues
- facetTopAggregation.subAggregation(
- addEffortAggregationIfNeeded(query, AggregationBuilders
- .missing(facetName + FACET_SUFFIX_MISSING)
- .field(fieldName)));
-
- return AggregationBuilders
- .global(facetName)
- .subAggregation(facetTopAggregation);
- }
-
@CheckForNull
private FilterBuilder createTermsFilter(String field, Collection<?> values) {
if (!values.isEmpty()) {
public static final String FIELD_AUTHORIZATION_USERS = "users";
public static final String FIELD_AUTHORIZATION_UPDATED_AT = "updatedAt";
- public static final String FIELD_ISSUE_ACTION_PLAN = "actionPlan";
public static final String FIELD_ISSUE_ASSIGNEE = "assignee";
public static final String FIELD_ISSUE_ATTRIBUTES = "attributes";
public static final String FIELD_ISSUE_AUTHOR_LOGIN = "authorLogin";
issueMapping.setAttribute("_id", ImmutableMap.of("path", FIELD_ISSUE_KEY));
issueMapping.setAttribute("_parent", ImmutableMap.of("type", TYPE_AUTHORIZATION));
issueMapping.setAttribute("_routing", ImmutableMap.of("required", true, "path", FIELD_ISSUE_PROJECT_UUID));
- issueMapping.stringFieldBuilder(FIELD_ISSUE_ACTION_PLAN).docValues().build();
issueMapping.stringFieldBuilder(FIELD_ISSUE_ASSIGNEE).enableSorting().build();
issueMapping.stringFieldBuilder(FIELD_ISSUE_ATTRIBUTES).docValues().disableSearch().build();
issueMapping.stringFieldBuilder(FIELD_ISSUE_AUTHOR_LOGIN).docValues().build();
"i.kee",
"root.uuid",
"i.updated_at",
- "i.action_plan_key",
"i.assignee",
"i.gap",
"i.issue_attributes",
"i.line",
"i.message",
"i.resolution",
+ "i.severity",
// column 11
- "i.severity",
"i.manual_severity",
"i.checksum",
"i.status",
"i.issue_close_date",
"i.issue_creation_date",
"i.issue_update_date",
+ "r.plugin_name",
// column 21
- "r.plugin_name",
"r.plugin_rule_key",
"r.language",
"p.uuid",
doc.setKey(key);
doc.setProjectUuid(projectUuid);
doc.setTechnicalUpdateDate(new Date(rs.getLong(3)));
- doc.setActionPlanKey(rs.getString(4));
- doc.setAssignee(rs.getString(5));
- doc.setGap(DatabaseUtils.getDouble(rs, 6));
- doc.setAttributes(rs.getString(7));
- doc.setLine(DatabaseUtils.getInt(rs, 8));
- doc.setMessage(rs.getString(9));
- doc.setResolution(rs.getString(10));
- doc.setSeverity(rs.getString(11));
- doc.setManualSeverity(rs.getBoolean(12));
- doc.setChecksum(rs.getString(13));
- doc.setStatus(rs.getString(14));
- doc.setEffort(getLong(rs, 15));
- doc.setReporter(rs.getString(16));
- doc.setAuthorLogin(rs.getString(17));
- doc.setFuncCloseDate(longToDate(getLong(rs, 18)));
- doc.setFuncCreationDate(longToDate(getLong(rs, 19)));
- doc.setFuncUpdateDate(longToDate(getLong(rs, 20)));
- String ruleRepo = rs.getString(21);
- String ruleKey = rs.getString(22);
+ doc.setAssignee(rs.getString(4));
+ doc.setGap(DatabaseUtils.getDouble(rs, 5));
+ doc.setAttributes(rs.getString(6));
+ doc.setLine(DatabaseUtils.getInt(rs, 7));
+ doc.setMessage(rs.getString(8));
+ doc.setResolution(rs.getString(9));
+ doc.setSeverity(rs.getString(10));
+ doc.setManualSeverity(rs.getBoolean(11));
+ doc.setChecksum(rs.getString(12));
+ doc.setStatus(rs.getString(13));
+ doc.setEffort(getLong(rs, 14));
+ doc.setReporter(rs.getString(15));
+ doc.setAuthorLogin(rs.getString(16));
+ doc.setFuncCloseDate(longToDate(getLong(rs, 17)));
+ doc.setFuncCreationDate(longToDate(getLong(rs, 18)));
+ doc.setFuncUpdateDate(longToDate(getLong(rs, 19)));
+ String ruleRepo = rs.getString(20);
+ String ruleKey = rs.getString(21);
doc.setRuleKey(RuleKey.of(ruleRepo, ruleKey).toString());
- doc.setLanguage(rs.getString(23));
- doc.setComponentUuid(rs.getString(24));
- String moduleUuidPath = rs.getString(25);
+ doc.setLanguage(rs.getString(22));
+ doc.setComponentUuid(rs.getString(23));
+ String moduleUuidPath = rs.getString(24);
doc.setModuleUuid(extractModule(moduleUuidPath));
doc.setModuleUuidPath(moduleUuidPath);
- String scope = rs.getString(27);
- String filePath = extractFilePath(rs.getString(26), scope);
+ String scope = rs.getString(26);
+ String filePath = extractFilePath(rs.getString(25), scope);
doc.setFilePath(filePath);
doc.setDirectoryPath(extractDirPath(doc.filePath(), scope));
- String tags = rs.getString(28);
+ String tags = rs.getString(27);
doc.setTags(ImmutableList.copyOf(TAGS_SPLITTER.split(tags == null ? "" : tags)));
- doc.setType(RuleType.valueOf(rs.getInt(29)));
+ doc.setType(RuleType.valueOf(rs.getInt(28)));
return doc;
}
}
AssignAction.class,
CreateAction.class,
DoTransitionAction.class,
- PlanAction.class,
SearchAction.class,
SetSeverityAction.class,
TagsAction.class,
.setPossibleValues(RuleType.ALL_NAMES)
.setSince("5.5");
action.createParam("plan.plan")
- .setDescription("To plan the list of issues to a specific action plan (key), or unlink all the issues from an action plan")
+ .setDescription("Deprecated in 5.5. Has no effect. To plan the list of issues to a specific action plan (key), or unlink all the issues from an action plan")
+ .setDeprecatedSince("5.5")
.setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
action.createParam("do_transition.transition")
.setDescription("Transition")
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.issue.IssueService;
-
-import static com.google.common.base.Strings.emptyToNull;
-
-public class PlanAction implements IssuesWsAction {
-
- public static final String ACTION = "plan";
-
- private final IssueService issueService;
- private final OperationResponseWriter responseWriter;
-
- public PlanAction(IssueService issueService, OperationResponseWriter responseWriter) {
- this.issueService = issueService;
- this.responseWriter = responseWriter;
- }
-
- @Override
- public void define(WebService.NewController controller) {
- WebService.NewAction action = controller.createAction(ACTION)
- .setDescription("Plan/Unplan an issue. Requires authentication and Browse permission on project")
- .setSince("3.6")
- .setHandler(this)
- .setPost(true);
-
- action.createParam("issue")
- .setDescription("Key of the issue")
- .setRequired(true)
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- action.createParam("plan")
- .setDescription("Key of the action plan. Absent value removes the current plan.")
- .setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
- }
-
- @Override
- public void handle(Request request, Response response) throws Exception {
- String key = request.mandatoryParam("issue");
- issueService.plan(key, emptyToNull(request.param("plan")));
-
- responseWriter.write(key, request, response);
- }
-}
import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASC;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNED;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AT;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_BEFORE;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_IN_LAST;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.DEPRECATED_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.DEPRECATED_FACET_MODE_DEBT;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.FACET_ASSIGNED_TO_ME;
.setHandler(this)
.setDescription(
"Search for issues. Requires Browse permission on project(s).<br/>" +
- "Since 5.5, response field 'debt' has been renamed to 'effort'")
+ "Since 5.5, response field 'debt' has been renamed to 'effort'.<br/>" +
+ "Since 5.5, response field 'actionPlan' has been removed")
.setSince("3.6")
.setResponseExample(Resources.getResource(this.getClass(), "example-search.json"));
action.addPagingParams(100, MAX_LIMIT);
action.createParam(Param.FACETS)
- .setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
+ .setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.<br/>" +
+ "Since 5.5, facet 'actionPlans' is deprecated.")
.setPossibleValues(IssueIndex.SUPPORTED_FACETS);
action.createParam(FACET_MODE)
.setDefaultValue(FACET_MODE_COUNT)
action.addSortParams(IssueQuery.SORTS, null, true);
action.createParam(ADDITIONAL_FIELDS)
.setSince("5.2")
- .setDescription("Comma-separated list of the optional fields to be returned in response.")
+ .setDescription("Comma-separated list of the optional fields to be returned in response. Action plans are dropped in 5.5, it is not returned in the response.")
.setPossibleValues(SearchAdditionalField.possibleValues());
addComponentRelatedParams(action);
action.createParam(ISSUES)
.setSince("5.5")
.setPossibleValues(RuleType.values())
.setExampleValue(format("%s,%s", RuleType.CODE_SMELL, RuleType.BUG));
- action.createParam(ACTION_PLANS)
- .setDescription("Comma-separated list of action plan keys (not names)")
+ action.createParam(DEPRECATED_ACTION_PLANS)
+ .setDescription("Action plans are dropped in 5.5. This parameter has no effect. Comma-separated list of action plan keys (not names)")
+ .setDeprecatedSince("5.5")
.setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
action.createParam(PLANNED)
- .setDescription("To retrieve issues associated to an action plan or not")
+ .setDescription("Since 5.5 this parameter is no more used, as action plan feature has been dropped")
+ .setDeprecatedSince("5.5")
.setBooleanPossibleValues();
action.createParam(REPORTERS)
.setDescription("Comma-separated list of reporter logins")
if (actionPlansFromRequest != null) {
actionPlans.addAll(actionPlansFromRequest);
}
- addMandatoryValuesToFacet(facets, ACTION_PLANS, actionPlans);
+ addMandatoryValuesToFacet(facets, DEPRECATED_ACTION_PLANS, actionPlans);
addMandatoryValuesToFacet(facets, COMPONENT_UUIDS, request.getComponentUuids());
for (String facetName : request.getFacets()) {
collector.addComponentUuids(facets.getBucketKeys(MODULE_UUIDS));
collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(ASSIGNEES));
collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(REPORTERS));
- collector.addAll(SearchAdditionalField.ACTION_PLANS, facets.getBucketKeys(ACTION_PLANS));
}
private void collectRequestParams(SearchResponseLoader.Collector collector, SearchWsRequest request) {
collector.addComponentUuids(request.getComponentRootUuids());
collector.addAll(SearchAdditionalField.USERS, request.getAssignees());
collector.addAll(SearchAdditionalField.USERS, request.getReporters());
- collector.addAll(SearchAdditionalField.ACTION_PLANS, request.getActionPlans());
}
private static SearchWsRequest toSearchWsRequest(Request request) {
return new SearchWsRequest()
- .setActionPlans(request.paramAsStrings(ACTION_PLANS))
.setAdditionalFields(request.paramAsStrings(ADDITIONAL_FIELDS))
.setAsc(request.paramAsBoolean(ASC))
.setAssigned(request.paramAsBoolean(ASSIGNED))
.setOnComponentOnly(request.paramAsBoolean(ON_COMPONENT_ONLY))
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
- .setPlanned(request.paramAsBoolean(PLANNED))
.setProjectKeys(request.paramAsStrings(PROJECT_KEYS))
.setProjectUuids(request.paramAsStrings(PROJECT_UUIDS))
.setProjects(request.paramAsStrings(PROJECTS))
public enum SearchAdditionalField {
ACTIONS("actions"),
- ACTION_PLANS("actionPlans"),
+ /**
+ * @deprecated since 5.5, action plan feature has been removed
+ */
+ @Deprecated
+ DEPRECATED_ACTION_PLANS("actionPlans"),
COMMENTS("comments"),
LANGUAGES("languages"),
RULES("rules"),
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.issue.ActionPlanDto;
import org.sonar.db.issue.IssueChangeDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.rule.RuleDto;
private Long effortTotal = null;
private List<UserDto> users = null;
private List<RuleDto> rules = null;
- private List<ActionPlanDto> actionPlans = null;
private final Map<String, ComponentDto> componentsByUuid = new HashMap<>();
private final ListMultimap<String, IssueChangeDto> commentsByIssueKey = ArrayListMultimap.create();
private final ListMultimap<String, String> actionsByIssueKey = ArrayListMultimap.create();
return rules;
}
- @CheckForNull
- public List<ActionPlanDto> getActionPlans() {
- return actionPlans;
- }
-
@CheckForNull
public List<IssueChangeDto> getCommentsForIssueKey(String issueKey) {
if (commentsByIssueKey.containsKey(issueKey)) {
this.rules = rules;
}
- public void setActionPlans(@Nullable List<ActionPlanDto> actionPlans) {
- this.actionPlans = actionPlans;
- }
-
public void setComments(@Nullable List<IssueChangeDto> comments) {
for (IssueChangeDto comment : comments) {
commentsByIssueKey.put(comment.getIssueKey(), comment);
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.Paging;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.issue.ActionPlanDto;
import org.sonar.db.issue.IssueChangeDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.protobuf.DbCommons;
if (fields.contains(SearchAdditionalField.USERS)) {
response.setUsers(formatUsers(data));
}
- if (fields.contains(SearchAdditionalField.ACTION_PLANS)) {
- response.setActionPlans(formatActionPlans(data));
- }
if (fields.contains(SearchAdditionalField.LANGUAGES)) {
response.setLanguages(formatLanguages());
}
response.addAllComponents(formatComponents(data));
response.addAllRules(formatRules(data).getRulesList());
response.addAllUsers(formatUsers(data).getUsersList());
- response.addAllActionPlans(formatActionPlans(data).getActionPlansList());
return response.build();
}
issueBuilder.setResolution(dto.getResolution());
}
issueBuilder.setStatus(dto.getStatus());
- if (!Strings.isNullOrEmpty(dto.getActionPlanKey())) {
- issueBuilder.setActionPlan(dto.getActionPlanKey());
- }
issueBuilder.setMessage(nullToEmpty(dto.getMessage()));
issueBuilder.addAllTags(dto.getTags());
Long effort = dto.getEffort();
return wsUsers;
}
- private Issues.ActionPlans.Builder formatActionPlans(SearchResponseData data) {
- Issues.ActionPlans.Builder wsActionPlans = Issues.ActionPlans.newBuilder();
- List<ActionPlanDto> actionPlans = data.getActionPlans();
- if (actionPlans != null) {
- Issues.ActionPlan.Builder planBuilder = Issues.ActionPlan.newBuilder();
- for (ActionPlanDto actionPlan : actionPlans) {
- planBuilder
- .clear()
- .setKey(actionPlan.getKey())
- .setName(nullToEmpty(actionPlan.getName()))
- .setStatus(nullToEmpty(actionPlan.getStatus()))
- .setProject(nullToEmpty(actionPlan.getProjectKey()));
- Date deadLine = actionPlan.getDeadLine();
- if (deadLine != null) {
- planBuilder.setDeadLine(DateUtils.formatDateTime(deadLine));
- }
- wsActionPlans.addActionPlans(planBuilder);
- }
- }
- return wsActionPlans;
- }
-
private Issues.Languages.Builder formatLanguages() {
Issues.Languages.Builder wsLangs = Issues.Languages.newBuilder();
Issues.Language.Builder wsLang = Issues.Language.newBuilder();
import static com.google.common.collect.Lists.newArrayList;
import static org.sonar.server.issue.ws.SearchAdditionalField.ACTIONS;
-import static org.sonar.server.issue.ws.SearchAdditionalField.ACTION_PLANS;
+import static org.sonar.server.issue.ws.SearchAdditionalField.DEPRECATED_ACTION_PLANS;
import static org.sonar.server.issue.ws.SearchAdditionalField.COMMENTS;
import static org.sonar.server.issue.ws.SearchAdditionalField.RULES;
import static org.sonar.server.issue.ws.SearchAdditionalField.TRANSITIONS;
// before loadUsers()
loadComments(collector, dbSession, result);
loadUsers(collector, dbSession, result);
- loadActionPlans(collector, dbSession, result);
loadComponents(collector, dbSession, result);
loadActionsAndTransitions(collector, result);
completeTotalEffortFromFacet(facets, result);
}
}
- private void loadActionPlans(Collector collector, DbSession dbSession, SearchResponseData result) {
- if (collector.contains(ACTION_PLANS)) {
- result.setActionPlans(dbClient.actionPlanDao().selectByKeys(dbSession, collector.<String>get(ACTION_PLANS)));
- }
- }
-
private void loadRules(Collector collector, DbSession dbSession, SearchResponseData result) {
if (collector.contains(RULES)) {
result.setRules(dbClient.ruleDao().selectByKeys(dbSession, collector.<RuleKey>get(RULES)));
for (IssueDto issue : issues) {
componentUuids.add(issue.getComponentUuid());
projectUuids.add(issue.getProjectUuid());
- add(ACTION_PLANS, issue.getActionPlanKey());
+ add(DEPRECATED_ACTION_PLANS, issue.getActionPlanKey());
add(RULES, issue.getRuleKey());
add(USERS, issue.getReporter());
add(USERS, issue.getAssignee());
import org.sonar.server.issue.SetTypeAction;
import org.sonar.server.issue.TransitionAction;
import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.issue.actionplan.ActionPlanWs;
import org.sonar.server.issue.filter.IssueFilterWsModule;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexDefinition;
IssueFilterWsModule.class,
// action plan
- ActionPlanWs.class,
ActionPlanService.class,
// issues actions
import org.sonar.db.dashboard.DashboardDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.property.PropertyQuery;
-import org.sonar.server.component.ComponentFinder;
import org.sonar.server.ce.ws.ActivityAction;
+import org.sonar.server.component.ComponentFinder;
import org.sonar.server.ui.ViewProxy;
import org.sonar.server.ui.Views;
import org.sonar.server.user.UserSession;
json.prop("showQualityProfiles", isProject);
json.prop("showQualityGates", isProject);
json.prop("showManualMeasures", isAdmin);
- json.prop("showActionPlans", isAdmin && isProject);
+ // TODO delete showActionPlans when UI is updated
+ json.prop("showActionPlans", false);
json.prop("showLinks", isAdmin && isProject);
json.prop("showPermissions", isAdmin && componentTypeHasProperty(component, PROPERTY_HAS_ROLE_POLICY));
json.prop("showHistory", isAdmin && componentTypeHasProperty(component, PROPERTY_MODIFIABLE_HISTORY));
+++ /dev/null
-{
- "actionPlans": [
- {
- "key": "3f19de90-1521-4482-a737-a311758ff513",
- "name": "Version 3.6",
- "status": "OPEN",
- "project": "java-sonar-runner-simple",
- "userLogin": "admin",
- "deadLine": "2013-12-31T00:00:00+0100",
- "totalIssues": 1,
- "unresolvedIssues": 0,
- "createdAt": "2013-05-31T22:40:50+0200",
- "updatedAt": "2013-05-31T22:40:50+0200"
- },
- {
- "key": "8ab022c0-f0dc-41b7-a762-82502bda749f",
- "name": "Version 3.5",
- "status": "CLOSED",
- "project": "java-sonar-runner-simple4",
- "userLogin": "admin",
- "totalIssues": 0,
- "unresolvedIssues": 0,
- "createdAt": "2013-05-31T22:40:30+0200",
- "updatedAt": "2013-05-31T22:42:13+0200"
- }
- ]
-}
assertThat(query.tags()).containsOnly("tag1", "tag2");
assertThat(query.onComponentOnly()).isFalse();
assertThat(query.assigned()).isTrue();
- assertThat(query.planned()).isTrue();
assertThat(query.hideRules()).isTrue();
assertThat(query.rules()).hasSize(2);
assertThat(query.directories()).containsOnly("/src/main/java/example");
.componentUuids(newArrayList("org/struts/Action.java"))
.moduleUuids(newArrayList("org.struts:core"))
.rules(newArrayList(RuleKey.of("squid", "AvoidCycle")))
- .actionPlans(newArrayList("AP1", "AP2"))
.reporters(newArrayList("crunky"))
.assignees(newArrayList("gargantua"))
.languages(newArrayList("xoo"))
.createdAfter(new Date())
.createdBefore(new Date())
.createdAt(new Date())
- .planned(true)
.resolved(true)
.sort(IssueQuery.SORT_BY_ASSIGNEE)
.asc(true)
assertThat(query.assigned()).isTrue();
assertThat(query.hideRules()).isTrue();
assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle"));
- assertThat(query.actionPlans()).containsOnly("AP1", "AP2");
assertThat(query.createdAfter()).isNotNull();
assertThat(query.createdBefore()).isNotNull();
assertThat(query.createdAt()).isNotNull();
- assertThat(query.planned()).isTrue();
assertThat(query.resolved()).isTrue();
assertThat(query.sort()).isEqualTo(IssueQuery.SORT_BY_ASSIGNEE);
assertThat(query.asc()).isTrue();
.componentUuids(null)
.moduleUuids(null)
.statuses(null)
- .actionPlans(null)
.assignees(null)
.reporters(null)
.resolutions(null)
assertThat(query.componentUuids()).isEmpty();
assertThat(query.moduleUuids()).isEmpty();
assertThat(query.statuses()).isEmpty();
- assertThat(query.actionPlans()).isEmpty();
assertThat(query.assignees()).isEmpty();
assertThat(query.reporters()).isEmpty();
assertThat(query.resolutions()).isEmpty();
assertThat(query.componentUuids()).isEmpty();
assertThat(query.moduleUuids()).isEmpty();
assertThat(query.statuses()).isEmpty();
- assertThat(query.actionPlans()).isEmpty();
assertThat(query.assignees()).isEmpty();
assertThat(query.reporters()).isEmpty();
assertThat(query.resolutions()).isEmpty();
assertThat(query.assigned()).isNull();
assertThat(query.createdAfter()).isNull();
assertThat(query.createdBefore()).isNull();
- assertThat(query.planned()).isNull();
assertThat(query.resolved()).isNull();
assertThat(query.sort()).isNull();
import org.sonar.db.component.ComponentDao;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.issue.ActionPlanDto;
import org.sonar.db.issue.IssueDao;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.protobuf.DbFileSources;
}
}
- @Test
- public void plan() {
- RuleDto rule = newRule();
- ComponentDto project = newProject();
- ComponentDto file = newFile(project);
- userSessionRule.login("john").addProjectPermissions(UserRole.USER, project.key());
-
- IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
-
- String actionPlanKey = "EFGH";
- db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
- session.commit();
- index();
-
- assertThat(IssueIndex.getByKey(issue.getKey()).actionPlanKey()).isNull();
-
- service.plan(issue.getKey(), actionPlanKey);
-
- assertThat(IssueIndex.getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
- }
-
- @Test
- public void un_plan() {
- RuleDto rule = newRule();
- ComponentDto project = newProject();
- ComponentDto file = newFile(project);
- userSessionRule.login("john");
-
- String actionPlanKey = "EFGH";
- db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
- IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setActionPlanKey(actionPlanKey));
-
- assertThat(IssueIndex.getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
-
- service.plan(issue.getKey(), null);
-
- assertThat(IssueIndex.getByKey(issue.getKey()).actionPlanKey()).isNull();
- }
-
- @Test
- public void fail_plan_if_action_plan_not_found() {
- RuleDto rule = newRule();
- ComponentDto project = newProject();
- ComponentDto file = newFile(project);
- userSessionRule.login("john");
-
- IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
- try {
- service.plan(issue.getKey(), "unknown");
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Unknown action plan: unknown");
- }
- }
-
@Test
public void set_severity() {
RuleDto rule = newRule();
doc.setKey("ABC");
doc.setRuleKey(RuleTesting.XOO_X1.toString());
doc.setType(RuleType.CODE_SMELL);
- doc.setActionPlanKey(null);
doc.setReporter(null);
doc.setAssignee("steve");
doc.setAuthorLogin("roger");
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.IssueChangeContext;
-import org.sonar.core.issue.DefaultActionPlan;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.user.ThreadLocalUserSession;
-
-import java.util.List;
-import java.util.Map;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-
-public class PlanActionTest {
-
- private PlanAction action;
-
- private ActionPlanService actionPlanService = mock(ActionPlanService.class);
- private IssueUpdater issueUpdater = mock(IssueUpdater.class);
-
- @Rule
- public ExpectedException throwable = ExpectedException.none();
-
- @Before
- public void before(){
- action = new PlanAction(actionPlanService, issueUpdater);
- }
-
- @Test
- public void should_execute(){
- ActionPlan actionPlan = new DefaultActionPlan();
- Map<String, Object> properties = newHashMap();
- properties.put(PlanAction.VERIFIED_ACTION_PLAN, actionPlan);
- DefaultIssue issue = mock(DefaultIssue.class);
-
- Action.Context context = mock(Action.Context.class);
- when(context.issue()).thenReturn(issue);
-
- action.execute(properties, context);
- verify(issueUpdater).plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class));
- }
-
- @Test
- public void should_fail_on_unverified_action_plan() {
- throwable.expect(IllegalArgumentException.class);
- throwable.expectMessage("Action plan is missing from the execution parameters");
-
- Map<String, Object> properties = newHashMap();
- Action.Context context = mock(Action.Context.class);
-
- action.execute(properties, context);
- }
-
- @Test
- public void should_execute_on_null_action_plan(){
- Map<String, Object> properties = newHashMap();
- properties.put(PlanAction.VERIFIED_ACTION_PLAN, null);
- DefaultIssue issue = mock(DefaultIssue.class);
-
- Action.Context context = mock(Action.Context.class);
- when(context.issue()).thenReturn(issue);
-
- action.execute(properties, context);
- verify(issueUpdater).plan(eq(issue), eq((ActionPlan) null), any(IssueChangeContext.class));
- }
-
- @Test
- public void should_verify(){
- String planKey = "ABCD";
- Map<String, Object> properties = newHashMap();
- properties.put("plan", planKey);
- ActionPlan actionPlan = new DefaultActionPlan().setProjectKey("struts");
-
- List<Issue> issues = newArrayList((Issue) new DefaultIssue().setKey("ABC").setProjectKey("struts"));
- when(actionPlanService.findByKey(eq(planKey), any(ThreadLocalUserSession.class))).thenReturn(actionPlan);
- assertThat(action.verify(properties, issues, mock(ThreadLocalUserSession.class))).isTrue();
- assertThat(properties.get(PlanAction.VERIFIED_ACTION_PLAN)).isEqualTo(actionPlan);
- }
-
- @Test
- public void should_fail_if_action_plan_does_not_exist(){
- throwable.expect(IllegalArgumentException.class);
- throwable.expectMessage("Unknown action plan: ABCD");
-
- String planKey = "ABCD";
- Map<String, Object> properties = newHashMap();
- properties.put("plan", planKey);
-
- List<Issue> issues = newArrayList((Issue) new DefaultIssue().setKey("ABC").setProjectKey("struts"));
- when(actionPlanService.findByKey(eq(planKey), any(ThreadLocalUserSession.class))).thenReturn(null);
- action.verify(properties, issues, mock(ThreadLocalUserSession.class));
- }
-
- @Test
- public void should_unplan_if_action_plan_is_empty() {
- String planKey = "";
- Map<String, Object> properties = newHashMap();
- properties.put("plan", planKey);
-
- List<Issue> issues = newArrayList((Issue) new DefaultIssue().setKey("ABC").setProjectKey("struts"));
- action.verify(properties, issues, mock(ThreadLocalUserSession.class));
- assertThat(properties.containsKey(PlanAction.VERIFIED_ACTION_PLAN)).isTrue();
- assertThat(properties.get(PlanAction.VERIFIED_ACTION_PLAN)).isNull();
- }
-
- @Test
- public void should_verify_issues_are_on_the_same_project(){
- throwable.expect(IllegalArgumentException.class);
- throwable.expectMessage("Issues are not all related to the action plan project: struts");
-
- String planKey = "ABCD";
- Map<String, Object> properties = newHashMap();
- properties.put("plan", planKey);
-
- when(actionPlanService.findByKey(eq(planKey), any(ThreadLocalUserSession.class))).thenReturn(new DefaultActionPlan().setProjectKey("struts"));
- List<Issue> issues = newArrayList(new DefaultIssue().setKey("ABC").setProjectKey("struts"), (Issue) new DefaultIssue().setKey("ABE").setProjectKey("mybatis"));
- action.verify(properties, issues, mock(ThreadLocalUserSession.class));
- }
-
- @Test
- public void should_support_only_unresolved_issues(){
- assertThat(action.supports(new DefaultIssue().setResolution(null))).isTrue();
- assertThat(action.supports(new DefaultIssue().setResolution(Issue.RESOLUTION_FIXED))).isFalse();
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.actionplan;
-
-import org.junit.Test;
-import org.sonar.api.server.ws.RailsHandler;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ActionPlanWsTest {
-
- WsTester tester = new WsTester(new ActionPlanWs());
-
- @Test
- public void define_controller() {
- WebService.Controller controller = tester.controller("api/action_plans");
- assertThat(controller).isNotNull();
- assertThat(controller.description()).isNotEmpty();
- assertThat(controller.actions()).hasSize(6);
- }
-
- @Test
- public void define_search_action() {
- WebService.Controller controller = tester.controller("api/action_plans");
-
- WebService.Action action = controller.action("search");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(2);
- }
-
- @Test
- public void define_create_action() {
- WebService.Controller controller = tester.controller("api/action_plans");
-
- WebService.Action action = controller.action("create");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.params()).hasSize(5);
- }
-
- @Test
- public void define_delete_action() {
- WebService.Controller controller = tester.controller("api/action_plans");
-
- WebService.Action action = controller.action("delete");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.params()).hasSize(2);
- }
-
- @Test
- public void define_update_action() {
- WebService.Controller controller = tester.controller("api/action_plans");
-
- WebService.Action action = controller.action("update");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.params()).hasSize(5);
- }
-
- @Test
- public void define_open_action() {
- WebService.Controller controller = tester.controller("api/action_plans");
-
- WebService.Action action = controller.action("open");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.params()).hasSize(2);
- }
-
- @Test
- public void define_close_action() {
- WebService.Controller controller = tester.controller("api/action_plans");
-
- WebService.Action action = controller.action("close");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.params()).hasSize(2);
- }
-}
assertThat(result.getFacets().get(FACET_MODE_EFFORT)).containsOnly(entry("total", 30L));
}
- @Test
- public void facets_on_action_plans() {
- ComponentDto project = ComponentTesting.newProjectDto();
- ComponentDto file = ComponentTesting.newFileDto(project);
-
- indexIssues(
- IssueTesting.newDoc("ISSUE1", file).setActionPlanKey("plan1"),
- IssueTesting.newDoc("ISSUE2", file).setActionPlanKey("plan2"));
-
- SearchResult<IssueDoc> result = index.search(newQueryBuilder().build(), new SearchOptions().addFacets(newArrayList("actionPlans")));
- assertThat(result.getFacets().getNames()).containsOnly("actionPlans", FACET_MODE_EFFORT);
- assertThat(result.getFacets().get("actionPlans")).containsOnly(entry("plan1", 10L), entry("plan2", 10L));
- assertThat(result.getFacets().get(FACET_MODE_EFFORT)).containsOnly(entry("total", 20L));
- }
-
@Test
public void facets_on_languages() {
ComponentDto project = ComponentTesting.newProjectDto();
assertThat(index.search(IssueQuery.builder(userSessionRule).resolved(null).build(), new SearchOptions()).getDocs()).hasSize(3);
}
- @Test
- public void filter_by_action_plans() {
- ComponentDto project = ComponentTesting.newProjectDto();
- ComponentDto file = ComponentTesting.newFileDto(project);
-
- indexIssues(
- IssueTesting.newDoc("ISSUE1", file).setActionPlanKey("plan1"),
- IssueTesting.newDoc("ISSUE2", file).setActionPlanKey("plan2"));
-
- assertThat(index.search(IssueQuery.builder(userSessionRule).actionPlans(newArrayList("plan1")).build(), new SearchOptions()).getDocs()).hasSize(1);
- assertThat(index.search(IssueQuery.builder(userSessionRule).actionPlans(newArrayList("plan1", "plan2")).build(), new SearchOptions()).getDocs()).hasSize(2);
- assertThat(index.search(IssueQuery.builder(userSessionRule).actionPlans(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty();
- }
-
- @Test
- public void facets_on_action_plans() {
- ComponentDto project = ComponentTesting.newProjectDto();
- ComponentDto file = ComponentTesting.newFileDto(project);
-
- indexIssues(
- IssueTesting.newDoc("ISSUE1", file).setActionPlanKey("plan1"),
- IssueTesting.newDoc("ISSUE2", file).setActionPlanKey("plan2"));
-
- SearchResult<IssueDoc> result = index.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("actionPlans")));
- assertThat(result.getFacets().getNames()).containsOnly("actionPlans");
- assertThat(result.getFacets().get("actionPlans")).containsOnly(entry("plan1", 1L), entry("plan2", 1L));
- }
-
- @Test
- public void filter_by_planned() {
- ComponentDto project = ComponentTesting.newProjectDto();
- ComponentDto file = ComponentTesting.newFileDto(project);
-
- indexIssues(
- IssueTesting.newDoc("ISSUE1", file).setActionPlanKey("AP-KEY"),
- IssueTesting.newDoc("ISSUE2", file).setActionPlanKey(null),
- IssueTesting.newDoc("ISSUE3", file).setActionPlanKey(null));
-
- assertThat(index.search(IssueQuery.builder(userSessionRule).planned(true).build(), new SearchOptions()).getDocs()).hasSize(1);
- assertThat(index.search(IssueQuery.builder(userSessionRule).planned(false).build(), new SearchOptions()).getDocs()).hasSize(2);
- assertThat(index.search(IssueQuery.builder(userSessionRule).planned(null).build(), new SearchOptions()).getDocs()).hasSize(3);
- }
-
@Test
public void filter_by_rules() {
ComponentDto project = ComponentTesting.newProjectDto();
assertThat(issue.tags()).containsOnly("tag1", "tag2", "tag3");
assertThat(issue.effort().toMinutes()).isGreaterThan(0L);
assertThat(issue.gap()).isEqualTo(2d);
- assertThat(issue.actionPlanKey()).isEqualTo("PLAN1");
assertThat(issue.attribute("JIRA")).isEqualTo("http://jira.com");
assertThat(issue.type().getDbConstant()).isEqualTo(2);
}
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new IssueWsModule().configure(container);
- assertThat(container.size()).isEqualTo(17);
+ assertThat(container.size()).isEqualTo(2 + 14);
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.ws;
-
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.ws.WsAction;
-import org.sonar.server.ws.WsActionTester;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class PlanActionTest {
-
- IssueService issueService = mock(IssueService.class);
- OperationResponseWriter responseWriter = mock(OperationResponseWriter.class);
- WsAction underTest = new PlanAction(issueService, responseWriter);
- WsActionTester tester = new WsActionTester(underTest);
-
- @Test
- public void plan() throws Exception {
- tester.newRequest()
- .setParam("issue", "ABC")
- .setParam("plan", "P1")
- .execute();
-
- verify(issueService).plan("ABC", "P1");
- verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
- }
-
- @Test
- public void unplan_if_value_is_absent() throws Exception {
- tester.newRequest()
- .setParam("issue", "ABC")
- .execute();
-
- verify(issueService).plan("ABC", null);
- verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
- }
-}
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.issue.ActionPlanDao;
-import org.sonar.db.issue.ActionPlanDto;
import org.sonar.db.issue.IssueChangeDao;
import org.sonar.db.issue.IssueChangeDto;
import org.sonar.db.issue.IssueDao;
assertThat(result.outputAsString()).doesNotContain("fabrice");
}
- @Test
- public void issue_with_action_plan() throws Exception {
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("PROJECT_ID").setKey("PROJECT_KEY"));
- setDefaultProjectPermission(project);
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "FILE_ID").setKey("FILE_KEY"));
-
- tester.get(ActionPlanDao.class).save(new ActionPlanDto()
- .setKey("AP-ABCD")
- .setName("1.0")
- .setStatus("OPEN")
- .setProjectId(project.getId())
- .setUserLogin("simon")
- .setDeadLine(DateUtils.parseDateTime("2014-01-24T19:10:03+0000"))
- .setCreatedAt(DateUtils.parseDateTime("2014-01-22T19:10:03+0000"))
- .setUpdatedAt(DateUtils.parseDateTime("2014-01-23T19:10:03+0000")));
-
- IssueDto issue = IssueTesting.newDto(newRule(), file, project)
- .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
- .setActionPlanKey("AP-ABCD");
- db.issueDao().insert(session, issue);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam("additionalFields", "actionPlans")
- .execute();
- result.assertJson(this.getClass(), "issue_with_action_plan.json");
- }
-
@Test
public void load_additional_fields() throws Exception {
db.userDao().insert(session, new UserDto().setLogin("simon").setName("Simon").setEmail("simon@email.com"));
db.userDao().insert(session, new UserDto().setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("PROJECT_ID").setKey("PROJECT_KEY"));
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("PROJECT_ID").setKey("PROJECT_KEY").setLanguage("java"));
setDefaultProjectPermission(project);
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "FILE_ID").setKey("FILE_KEY"));
-
- tester.get(ActionPlanDao.class).save(new ActionPlanDto()
- .setKey("AP-ABCD")
- .setName("1.0")
- .setStatus("OPEN")
- .setProjectId(project.getId())
- .setUserLogin("simon"));
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "FILE_ID").setKey("FILE_KEY").setLanguage("js"));
IssueDto issue = IssueTesting.newDto(newRule(), file, project)
.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
.setAuthorLogin("John")
.setAssignee("simon")
- .setReporter("fabrice")
- .setActionPlanKey("AP-ABCD");
+ .setReporter("fabrice");
db.issueDao().insert(session, issue);
session.commit();
tester.get(IssueIndexer.class).indexAll();
}
]
},
- {
- "property": "actionPlans",
- "values": [
- {
- "val": "",
- "count": 1
- }
- ]
- },
{
"property": "types",
"values": [
"count": 10
}
]
- },
- {
- "property": "actionPlans",
- "values": [
- {
- "val": "",
- "count": 10
- }
- ]
}
]}
"count": 0
}
]
- },
- {
- "property": "actionPlans",
- "values": [
- {
- "val": "",
- "count": 1
- }
- ]
}
]}
"key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
"assignee": "simon",
"reporter": "fabrice",
- "actionPlan": "AP-ABCD",
"actions": [
- "comment", "assign", "set_tags", "set_type", "assign_to_me", "plan"
+ "comment", "assign", "set_tags", "set_type", "assign_to_me"
],
"transitions": [
"confirm", "resolve"
]
}
],
- "actionPlans": [
+ "users": [
{
- "key": "AP-ABCD",
- "name": "1.0",
- "status": "OPEN"
+ "login": "fabrice",
+ "name": "Fabrice",
+ "email": "fabrice@email.com",
+ "active": true
+ },
+ {
+ "login": "simon",
+ "name": "Simon",
+ "email": "simon@email.com",
+ "active": true
}
]
}
"assignee": "simon",
"reporter": "fabrice",
"author": "John",
- "actionPlan": "AP-ABCD",
"tags": [
"bug",
"owasp"
"showQualityProfiles": true,
"showQualityGates": true,
"showManualMeasures": true,
- "showActionPlans": true,
+ "showActionPlans": false,
"showLinks": true,
"showPermissions": false,
"showHistory": false,
"showQualityProfiles": true,
"showQualityGates": true,
"showManualMeasures": true,
- "showActionPlans": true,
+ "showActionPlans": false,
"showLinks": true,
"showPermissions": true,
"showHistory": true,
+++ /dev/null
-#
-# SonarQube, open source software quality management tool.
-# Copyright (C) 2008-2014 SonarSource
-# mailto:contact AT sonarsource DOT com
-#
-# SonarQube is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3 of the License, or (at your option) any later version.
-#
-# SonarQube is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-
-class Api::ActionPlansController < Api::ApiController
-
- #
- # GET /api/action_plans/search?project=<project>
- #
- # -- Example
- # curl -v -u 'http://localhost:9000/api/action_plans/search?project=org.sonar.Sample'
- #
- def search
- require_parameters :project
-
- action_plans = Internal.issues.findActionPlanStats(params[:project])
- hash = {:actionPlans => action_plans.map { |plan| ActionPlan.to_hash(plan)}}
-
- respond_to do |format|
- format.json { render :json => jsonp(hash) }
- format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'actionPlans') }
- end
- end
-
- #
- # POST /api/action_plans/create
- #
- # -- Mandatory parameters
- # 'name' is the name of the action plan
- # 'project' is the key of the project to link the action plan to
- #
- # -- Optional parameters
- # 'description' is the plain-text description
- # 'deadLine' is the due date of the action plan. Format is 'year-month-day', for instance, '2013-12-31'.
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/create?name=Current&project=org.sonar.Sample'
- #
- def create
- verify_post_request
- require_parameters :project, :name
-
- result = Internal.issues.createActionPlan(params)
- render_result(result)
- end
-
- #
- # POST /api/action_plans/delete
- #
- # -- Mandatory parameters
- # 'key' is the action plan key
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/delete?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
- #
- def delete
- verify_post_request
- require_parameters :key
-
- result = Internal.issues.deleteActionPlan(params[:key])
- render_result(result)
- end
-
- #
- # POST /api/action_plans/update
- #
- # -- Mandatory parameters
- # 'name' is the name of the action plan
- #
- # -- Optional parameters
- # 'description' is the plain-text description
- # 'deadLine' is the due date of the action plan. Format is 'year-month-day', for instance, '2013-12-31'.
- #
- # -- Information
- # 'project' cannot be update
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/update?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0&name=Current'
- #
- def update
- verify_post_request
- require_parameters :key, :name
-
- result = Internal.issues.updateActionPlan(params[:key], params)
- render_result(result)
- end
-
- #
- # POST /api/action_plans/close
- #
- # -- Mandatory parameters
- # 'key' is the action plan key
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/close?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
- #
- def close
- verify_post_request
- require_parameters :key
-
- result = Internal.issues.closeActionPlan(params[:key])
- render_result(result)
- end
-
- #
- # POST /api/action_plans/open
- #
- # -- Mandatory parameters
- # 'key' is the action plan key
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/open?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
- #
- def open
- verify_post_request
- require_parameters :key
-
- result = Internal.issues.openActionPlan(params[:key])
- render_result(result)
- end
-
-
- private
-
- def render_result(result)
- http_status = (result.ok ? 200 : 400)
- hash = result_to_hash(result)
- hash[:actionPlan] = ActionPlan.to_hash(result.get) if result.get
-
- respond_to do |format|
- # if the request header "Accept" is "*/*", then the default format is the first one (json)
- format.json { render :json => jsonp(hash), :status => result.httpStatus }
- format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'sonar', :status => http_status) }
- end
- end
-
- def result_to_hash(result)
- hash = {}
- if result.errors and !result.errors.empty?
- hash[:errors] = result.errors().map do |error|
- {
- :msg => (error.text ? error.text : Api::Utils.message(error.l10nKey, :params => error.l10nParams))
- }
- end
- end
- hash
- end
-
-end
# -- Optional parameters
# 'assign.assignee' to assign all issues to a user or un-assign.
# 'set_severity.severity' to change the severity of all issues.
- # 'plan.plan' to plan all issues to an action plan or unlink.
+ # Action Plan are dropped in 5.5'plan.plan' to plan all issues to an action plan or unlink.
# 'do_transition.transition' to execute a transition on all issues.
# 'add_tags.tags' to add tags on all issues.
# 'remove_tags.tags' to remove tags on all issues.
public static final String FILE_UUIDS = "fileUuids";
public static final String ON_COMPONENT_ONLY = "onComponentOnly";
public static final String RULES = "rules";
- public static final String ACTION_PLANS = "actionPlans";
+
+ /**
+ * @deprecated since 5.5, action plan feature has been removed
+ */
+ @Deprecated
+ public static final String DEPRECATED_ACTION_PLANS = "actionPlans";
public static final String REPORTERS = "reporters";
public static final String ASSIGNEES = "assignees";
public static final String AUTHORS = "authors";
public static final String TAGS = "tags";
public static final String TYPES = "types";
public static final String ASSIGNED = "assigned";
+
+ /**
+ * @deprecated since 5.5, action plan feature has been removed
+ */
+ @Deprecated
public static final String PLANNED = "planned";
public static final String HIDE_RULES = "hideRules";
public static final String HIDE_COMMENTS = "hideComments";
public static final String FACET_ASSIGNED_TO_ME = "assigned_to_me";
public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED,
- COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS, TAGS, TYPES,
+ COMPONENTS, COMPONENT_ROOTS, RULES, DEPRECATED_ACTION_PLANS, REPORTERS, TAGS, TYPES,
ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, CREATED_IN_LAST,
COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS, FACET_MODE,
PROJECTS, PROJECT_UUIDS, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS, AUTHORS,
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsConnector;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASC;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNED;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AT;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_BEFORE;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_IN_LAST;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.DEPRECATED_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.FACET_MODE;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.LANGUAGES;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.ON_COMPONENT_ONLY;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.PLANNED;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECTS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECT_KEYS;
import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECT_UUIDS;
public SearchWsResponse search(SearchWsRequest request) {
return call(
new GetRequest(path("search"))
- .setParam(ACTION_PLANS, inlineMultipleParamValue(request.getActionPlans()))
+ .setParam(DEPRECATED_ACTION_PLANS, inlineMultipleParamValue(request.getActionPlans()))
.setParam(ADDITIONAL_FIELDS, inlineMultipleParamValue(request.getAdditionalFields()))
.setParam(ASC, request.getAsc())
.setParam(ASSIGNED, request.getAssigned())
.setParam(ON_COMPONENT_ONLY, request.getOnComponentOnly())
.setParam("p", request.getPage())
.setParam("ps", request.getPageSize())
- .setParam(PLANNED, request.getPlanned())
.setParam(PROJECT_KEYS, inlineMultipleParamValue(request.getProjectKeys()))
.setParam(PROJECT_UUIDS, inlineMultipleParamValue(request.getProjectUuids()))
.setParam(PROJECTS, inlineMultipleParamValue(request.getProjects()))
private Boolean onComponentOnly;
private Integer page;
private Integer pageSize;
- private Boolean planned;
private List<String> projectKeys;
private List<String> projectUuids;
private List<String> projects;
return this;
}
- @CheckForNull
- public Boolean getPlanned() {
- return planned;
- }
-
- public SearchWsRequest setPlanned(@Nullable Boolean planned) {
- this.planned = planned;
- return this;
- }
-
@CheckForNull
public List<String> getProjectKeys() {
return projectKeys;
repeated Component components = 7;
optional sonarqube.ws.commons.Rules rules = 8;
optional sonarqube.ws.commons.Users users = 9;
- optional ActionPlans actionPlans = 10;
+
+ // Deprecated since 5.5, action plan has been removed
+ optional ActionPlans unusedActionPlans = 10;
optional Languages languages = 11;
optional sonarqube.ws.commons.Facets facets = 12;
}
repeated Component components = 2;
repeated sonarqube.ws.commons.Rule rules = 3;
repeated sonarqube.ws.commons.User users = 4;
- repeated ActionPlan actionPlans = 5;
+ // Deprecated since 5.5, action plan has been removed
+ repeated ActionPlan actiunusedActionPlansonPlans = 5;
}
message Issue {
// SCM login of the committer who introduced the issue
optional string author = 17;
+ // Deprecated since 5.5, action plan has been removed
optional string actionPlan = 18;
+
repeated string tags = 19;
// the transitions allowed for the requesting user.
repeated Comment comments = 1;
}
+// Deprecated since 5.5
message ActionPlan {
optional string key = 1;
optional string name = 2;
optional string project = 5;
}
+// Deprecated since 5.5
message ActionPlans {
repeated ActionPlan actionPlans = 1;
}
assertThat(underTest.getOnComponentOnly()).isFalse();
}
- @Test
- public void getPlanned_returns_null_when_SearchWsRequest_has_just_been_instantiated() {
- assertThat(underTest.getPlanned()).isNull();
- }
-
- @Test
- public void setPlanned_accepts_null() {
- underTest.setPlanned(null);
- }
-
- @Test
- public void getPlanned_returns_boolean_from_setPlanned() {
- underTest.setPlanned(true);
- assertThat(underTest.getPlanned()).isTrue();
- underTest.setPlanned(false);
- assertThat(underTest.getPlanned()).isFalse();
- }
-
@Test
public void getResolved_returns_null_when_SearchWsRequest_has_just_been_instantiated() {
assertThat(underTest.getResolved()).isNull();