Explorar el Código

SONAR-19790 Return managed status for project in /api/project/search

tags/10.2.0.77647
Antoine Vigneau hace 10 meses
padre
commit
dd463f2cc9

+ 17
- 0
server/sonar-db-dao/src/it/java/org/sonar/db/alm/setting/ProjectAlmSettingDaoIT.java Ver fichero

.containsExactlyInAnyOrder(githubProject1, githubProject2); .containsExactlyInAnyOrder(githubProject1, githubProject2);
} }


@Test
public void selectByProjectUuidsAndAlm_whenGivenGithubAndProjectUuids_shouldOnlyReturnThose() {
AlmSettingDto githubSetting = db.almSettings().insertGitHubAlmSetting();
ProjectAlmSettingDto githubProject = createAlmProject(githubSetting);
createAlmProject(githubSetting);

AlmSettingDto gitlabSetting = db.almSettings().insertGitlabAlmSetting();
ProjectAlmSettingDto gitlabProject = createAlmProject(gitlabSetting);

List<ProjectAlmSettingDto> projectAlmSettingDtos =
underTest.selectByProjectUuidsAndAlm(dbSession, Set.of(githubProject.getProjectUuid(), gitlabProject.getProjectUuid()), ALM.GITHUB);

assertThat(projectAlmSettingDtos)
.usingRecursiveFieldByFieldElementComparator()
.containsExactlyInAnyOrder(githubProject);
}

private ProjectAlmSettingDto createAlmProject(AlmSettingDto almSettingsDto) { private ProjectAlmSettingDto createAlmProject(AlmSettingDto almSettingsDto) {
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); ProjectDto project = db.components().insertPrivateProject().getProjectDto();
when(uuidFactory.create()).thenReturn(project.getUuid() + "_forSetting"); when(uuidFactory.create()).thenReturn(project.getUuid() + "_forSetting");

+ 4
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/ProjectAlmSettingDao.java Ver fichero

return getMapper(dbSession).selectByAlm(alm.getId().toLowerCase(Locale.ROOT)); return getMapper(dbSession).selectByAlm(alm.getId().toLowerCase(Locale.ROOT));
} }


public List<ProjectAlmSettingDto> selectByProjectUuidsAndAlm(DbSession dbSession, Set<String> projectUuids, ALM alm) {
return getMapper(dbSession).selectByProjectUuidsAndAlm(projectUuids, alm.getId().toLowerCase(Locale.ROOT));
}

public List<ProjectAlmKeyAndProject> selectAlmTypeAndUrlByProject(DbSession dbSession) { public List<ProjectAlmKeyAndProject> selectAlmTypeAndUrlByProject(DbSession dbSession) {
return getMapper(dbSession).selectAlmTypeAndUrlByProject(); return getMapper(dbSession).selectAlmTypeAndUrlByProject();
} }

+ 3
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/ProjectAlmSettingMapper.java Ver fichero

package org.sonar.db.alm.setting; package org.sonar.db.alm.setting;


import java.util.List; import java.util.List;
import java.util.Set;
import javax.annotation.CheckForNull; import javax.annotation.CheckForNull;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;




List<ProjectAlmSettingDto> selectByAlm(@Param("alm") String alm); List<ProjectAlmSettingDto> selectByAlm(@Param("alm") String alm);


List<ProjectAlmSettingDto> selectByProjectUuidsAndAlm(@Param("projectUuids") Set<String> projectUuids, @Param("alm") String alm);

List<ProjectAlmKeyAndProject> selectAlmTypeAndUrlByProject(); List<ProjectAlmKeyAndProject> selectAlmTypeAndUrlByProject();
} }

+ 13
- 1
server/sonar-db-dao/src/main/resources/org/sonar/db/alm/setting/ProjectAlmSettingMapper.xml Ver fichero

</foreach> </foreach>
</select> </select>


<select id="selectByAlm" parameterType="string" resultType="org.sonar.db.alm.setting.ProjectAlmSettingDto">
<sql id="selectByAlmSql">
select <include refid="sqlColumns"/> select <include refid="sqlColumns"/>
from from
project_alm_settings p project_alm_settings p
alm_settings alm_settings on p.alm_setting_uuid = alm_settings.uuid alm_settings alm_settings on p.alm_setting_uuid = alm_settings.uuid
where where
alm_settings.alm_id=#{alm, jdbcType=VARCHAR} alm_settings.alm_id=#{alm, jdbcType=VARCHAR}
</sql>

<select id="selectByAlm" parameterType="string" resultType="org.sonar.db.alm.setting.ProjectAlmSettingDto">
<include refid="selectByAlmSql"/>
</select>

<select id="selectByProjectUuidsAndAlm" parameterType="map" resultType="org.sonar.db.alm.setting.ProjectAlmSettingDto">
<include refid="selectByAlmSql"/>
and p.project_uuid in
<foreach collection="projectUuids" open="(" close=")" item="projectUuid" separator=",">
#{projectUuid, jdbcType=VARCHAR}
</foreach>
</select> </select>


<insert id="insert" parameterType="Map" useGeneratedKeys="false"> <insert id="insert" parameterType="Map" useGeneratedKeys="false">

+ 7
- 0
server/sonar-server-common/src/main/java/org/sonar/server/management/DelegatingManagedServices.java Ver fichero

return resourcesUuid.stream().collect(toMap(identity(), any -> false)); return resourcesUuid.stream().collect(toMap(identity(), any -> false));
} }


@Override
public Map<String, Boolean> getProjectUuidToManaged(DbSession dbSession, Set<String> projectUuids) {
return findManagedProjectService()
.map(managedProjectService -> managedProjectService.getProjectUuidToManaged(dbSession, projectUuids))
.orElse(returnNonManagedForAll(projectUuids));
}

@Override @Override
public boolean isProjectManaged(DbSession dbSession, String projectUuid) { public boolean isProjectManaged(DbSession dbSession, String projectUuid) {
return findManagedProjectService() return findManagedProjectService()

+ 4
- 0
server/sonar-server-common/src/main/java/org/sonar/server/management/ManagedProjectService.java Ver fichero

*/ */
package org.sonar.server.management; package org.sonar.server.management;


import java.util.Map;
import java.util.Set;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;


public interface ManagedProjectService { public interface ManagedProjectService {


Map<String, Boolean> getProjectUuidToManaged(DbSession dbSession, Set<String> projectUuids);

boolean isProjectManaged(DbSession dbSession, String projectUuid); boolean isProjectManaged(DbSession dbSession, String projectUuid);


} }

+ 42
- 0
server/sonar-server-common/src/test/java/org/sonar/server/management/DelegatingManagedServicesTest.java Ver fichero

import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;


@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class DelegatingManagedServicesTest { public class DelegatingManagedServicesTest {
return anotherManagedInstanceService; return anotherManagedInstanceService;
} }


@Test
public void getProjectUuidToManaged_whenNoDelegates_setAllProjectsAsNonManaged() {
Set<String> projectUuids = Set.of("a", "b");
DelegatingManagedServices managedInstanceService = NO_MANAGED_SERVICES;

Map<String, Boolean> projectUuidToManaged = managedInstanceService.getProjectUuidToManaged(dbSession, projectUuids);

assertThat(projectUuidToManaged).containsExactlyInAnyOrderEntriesOf(Map.of("a", false, "b", false));
}

@Test
public void getProjectUuidToManaged_delegatesToRightService_andPropagateAnswer() {
Set<String> projectUuids = Set.of("a", "b");
Map<String, Boolean> serviceResponse = Map.of("a", false, "b", true);

ManagedInstanceService anotherManagedProjectService = getManagedProjectService(projectUuids, serviceResponse);
DelegatingManagedServices managedInstanceService = new DelegatingManagedServices(Set.of(new NeverManagedInstanceService(), anotherManagedProjectService));

Map<String, Boolean> projectUuidToManaged = managedInstanceService.getProjectUuidToManaged(dbSession, projectUuids);

assertThat(projectUuidToManaged).containsExactlyInAnyOrderEntriesOf(serviceResponse);
}

private ManagedInstanceService getManagedProjectService(Set<String> projectUuids, Map<String, Boolean> uuidsToManaged) {
ManagedInstanceService anotherManagedProjectService = mock(ManagedInstanceService.class, withSettings().extraInterfaces(ManagedProjectService.class));
when(anotherManagedProjectService.isInstanceExternallyManaged()).thenReturn(true);
doReturn(uuidsToManaged).when((ManagedProjectService) anotherManagedProjectService).getProjectUuidToManaged(dbSession, projectUuids);
return anotherManagedProjectService;
}

@Test @Test
public void isProjectManaged_whenManagedInstanceServices_shouldDelegatesToRightService() { public void isProjectManaged_whenManagedInstanceServices_shouldDelegatesToRightService() {
DelegatingManagedServices managedInstanceService = new DelegatingManagedServices(Set.of(new NeverManagedInstanceService(), new AlwaysManagedInstanceService())); DelegatingManagedServices managedInstanceService = new DelegatingManagedServices(Set.of(new NeverManagedInstanceService(), new AlwaysManagedInstanceService()));
return false; return false;
} }


@Override
public Map<String, Boolean> getProjectUuidToManaged(DbSession dbSession, Set<String> projectUuids) {
return null;
}

@Override @Override
public boolean isProjectManaged(DbSession dbSession, String projectUuid) { public boolean isProjectManaged(DbSession dbSession, String projectUuid) {
return false; return false;
return true; return true;
} }


@Override
public Map<String, Boolean> getProjectUuidToManaged(DbSession dbSession, Set<String> projectUuids) {
return null;
}

@Override @Override
public boolean isProjectManaged(DbSession dbSession, String projectUuid) { public boolean isProjectManaged(DbSession dbSession, String projectUuid) {
return true; return true;

+ 31
- 2
server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/SearchActionIT.java Ver fichero

import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.db.component.ProjectData; import org.sonar.db.component.ProjectData;
import org.sonar.db.project.ProjectDto; import org.sonar.db.project.ProjectDto;
import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.management.ManagedProjectService;
import org.sonar.server.tester.UserSessionRule; import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester; import org.sonar.server.ws.WsActionTester;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple; import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.api.server.ws.WebService.Param.PAGE; import static org.sonar.api.server.ws.WebService.Param.PAGE;
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY; import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
@Rule @Rule
public final DbTester db = DbTester.create(); public final DbTester db = DbTester.create();


private final WsActionTester ws = new WsActionTester(new SearchAction(db.getDbClient(), userSession));
private final ManagedProjectService managedProjectService = mock(ManagedProjectService.class);

private final WsActionTester ws = new WsActionTester(new SearchAction(db.getDbClient(), userSession, managedProjectService));


@Test @Test
public void search_by_key_query_with_partial_match_case_insensitive() { public void search_by_key_query_with_partial_match_case_insensitive() {
assertThat(result.getComponentsList()).isEmpty(); assertThat(result.getComponentsList()).isEmpty();
} }


@Test
public void search_return_manage_status() {
userSession.addPermission(ADMINISTER);
ProjectData managedProject = db.components().insertPrivateProject();
ProjectData notManagedProject = db.components().insertPrivateProject();

when(managedProjectService.getProjectUuidToManaged(any(), eq(Set.of(managedProject.projectUuid(), notManagedProject.projectUuid()))))
.thenReturn(Map.of(
managedProject.projectUuid(), true,
notManagedProject.projectUuid(), false
));

SearchWsResponse result = call(SearchRequest.builder().build());
assertThat(result.getComponentsList())
.extracting(Component::getKey, Component::getManaged)
.containsExactlyInAnyOrder(
tuple(managedProject.projectKey(), true),
tuple(notManagedProject.projectKey(), false));
}

private static String toStringAtUTC(Date d) { private static String toStringAtUTC(Date d) {
OffsetDateTime offsetTime = d.toInstant().atOffset(ZoneOffset.UTC); OffsetDateTime offsetTime = d.toInstant().atOffset(ZoneOffset.UTC);
return DateUtils.formatDateTime(offsetTime); return DateUtils.formatDateTime(offsetTime);
public void json_example() { public void json_example() {
userSession.addPermission(ADMINISTER); userSession.addPermission(ADMINISTER);
ProjectData publicProject = db.components().insertPublicProject("project-uuid-1", p -> p.setName("Project Name 1").setKey("project-key-1").setPrivate(false)); ProjectData publicProject = db.components().insertPublicProject("project-uuid-1", p -> p.setName("Project Name 1").setKey("project-key-1").setPrivate(false));
ProjectData privateProject = db.components().insertPrivateProject("project-uuid-2", p -> p.setName("Project Name 1").setKey("project-key-2"));
ProjectData privateProject = db.components().insertPrivateProject("project-uuid-2", p -> p.setName("Project Name 2").setKey("project-key-2"));
db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(publicProject.getMainBranchDto()) db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(publicProject.getMainBranchDto())
.setCreatedAt(parseDateTime("2017-03-01T11:39:03+0300").getTime()) .setCreatedAt(parseDateTime("2017-03-01T11:39:03+0300").getTime())
.setRevision("cfb82f55c6ef32e61828c4cb3db2da12795fd767")); .setRevision("cfb82f55c6ef32e61828c4cb3db2da12795fd767"));

+ 28
- 7
server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchAction.java Ver fichero

import org.sonar.db.component.ProjectLastAnalysisDateDto; import org.sonar.db.component.ProjectLastAnalysisDateDto;
import org.sonar.db.component.SnapshotDto; import org.sonar.db.component.SnapshotDto;
import org.sonar.db.permission.GlobalPermission; import org.sonar.db.permission.GlobalPermission;
import org.sonar.server.management.ManagedProjectService;
import org.sonar.server.project.Visibility; import org.sonar.server.project.Visibility;
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Projects.SearchWsResponse; import org.sonarqube.ws.Projects.SearchWsResponse;


import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity; import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.sonar.api.resources.Qualifiers.APP; import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.api.resources.Qualifiers.VIEW; import static org.sonar.api.resources.Qualifiers.VIEW;


private final DbClient dbClient; private final DbClient dbClient;
private final UserSession userSession; private final UserSession userSession;
private final ManagedProjectService managedProjectService;


public SearchAction(DbClient dbClient, UserSession userSession) {
public SearchAction(DbClient dbClient, UserSession userSession, ManagedProjectService managedProjectService) {
this.dbClient = dbClient; this.dbClient = dbClient;
this.userSession = userSession; this.userSession = userSession;
this.managedProjectService = managedProjectService;
} }


@Override @Override
"Requires 'Administer System' permission") "Requires 'Administer System' permission")
.addPagingParams(100, MAX_PAGE_SIZE) .addPagingParams(100, MAX_PAGE_SIZE)
.setResponseExample(getClass().getResource("search-example.json")) .setResponseExample(getClass().getResource("search-example.json"))
.setChangelog(new Change("10.2", "Response includes 'managed' field."))
.setChangelog(new Change("9.1", "The parameter '" + PARAM_ANALYZED_BEFORE + "' and the field 'lastAnalysisDate' of the returned projects " .setChangelog(new Change("9.1", "The parameter '" + PARAM_ANALYZED_BEFORE + "' and the field 'lastAnalysisDate' of the returned projects "
+ "take into account the analysis of all branches and pull requests, not only the main branch.")) + "take into account the analysis of all branches and pull requests, not only the main branch."))
.setHandler(this); .setHandler(this);
List<ComponentDto> components = dbClient.componentDao().selectByQuery(dbSession, query, paging.offset(), paging.pageSize()); List<ComponentDto> components = dbClient.componentDao().selectByQuery(dbSession, query, paging.offset(), paging.pageSize());
Set<String> componentUuids = components.stream().map(ComponentDto::uuid).collect(Collectors.toSet()); Set<String> componentUuids = components.stream().map(ComponentDto::uuid).collect(Collectors.toSet());
List<BranchDto> branchDtos = dbClient.branchDao().selectByUuids(dbSession, componentUuids); List<BranchDto> branchDtos = dbClient.branchDao().selectByUuids(dbSession, componentUuids);
Map<String, String> projectUuidByComponentUuid = branchDtos.stream().collect(Collectors.toMap(BranchDto::getUuid,BranchDto::getProjectUuid));
Map<String, Long> lastAnalysisDateByComponentUuid = dbClient.snapshotDao().selectLastAnalysisDateByProjectUuids(dbSession, projectUuidByComponentUuid.values()).stream()
Map<String, String> componentUuidToProjectUuid = branchDtos.stream().collect(Collectors.toMap(BranchDto::getUuid,BranchDto::getProjectUuid));
Map<String, Boolean> projectUuidToManaged = managedProjectService.getProjectUuidToManaged(dbSession, new HashSet<>(componentUuidToProjectUuid.values()));
Map<String, Boolean> componentUuidToManaged = toComponentUuidToManaged(componentUuidToProjectUuid, projectUuidToManaged);
Map<String, Long> lastAnalysisDateByComponentUuid = dbClient.snapshotDao().selectLastAnalysisDateByProjectUuids(dbSession, componentUuidToProjectUuid.values()).stream()
.collect(Collectors.toMap(ProjectLastAnalysisDateDto::getProjectUuid, ProjectLastAnalysisDateDto::getDate)); .collect(Collectors.toMap(ProjectLastAnalysisDateDto::getProjectUuid, ProjectLastAnalysisDateDto::getDate));
Map<String, SnapshotDto> snapshotsByComponentUuid = dbClient.snapshotDao() Map<String, SnapshotDto> snapshotsByComponentUuid = dbClient.snapshotDao()
.selectLastAnalysesByRootComponentUuids(dbSession, componentUuids).stream() .selectLastAnalysesByRootComponentUuids(dbSession, componentUuids).stream()
.collect(Collectors.toMap(SnapshotDto::getRootComponentUuid, identity())); .collect(Collectors.toMap(SnapshotDto::getRootComponentUuid, identity()));


return buildResponse(components, snapshotsByComponentUuid, lastAnalysisDateByComponentUuid, projectUuidByComponentUuid, paging);
return buildResponse(components, snapshotsByComponentUuid, lastAnalysisDateByComponentUuid, componentUuidToProjectUuid, componentUuidToManaged, paging);
} }
} }


private Map<String, Boolean> toComponentUuidToManaged(Map<String, String> componentUuidToProjectUuid, Map<String, Boolean> projectUuidToManaged) {
return componentUuidToProjectUuid.keySet().stream()
.collect(toMap(identity(), componentUuid -> isComponentManaged(
componentUuidToProjectUuid.get(componentUuid),
projectUuidToManaged))
);
}

private boolean isComponentManaged(String projectUuid, Map<String, Boolean> projectUuidToManaged) {
return ofNullable(projectUuidToManaged.get(projectUuid)).orElse(false);
}

static ComponentQuery buildDbQuery(SearchRequest request) { static ComponentQuery buildDbQuery(SearchRequest request) {
List<String> qualifiers = request.getQualifiers(); List<String> qualifiers = request.getQualifiers();
ComponentQuery.Builder query = ComponentQuery.builder() ComponentQuery.Builder query = ComponentQuery.builder()
} }


private static SearchWsResponse buildResponse(List<ComponentDto> components, Map<String, SnapshotDto> snapshotsByComponentUuid, private static SearchWsResponse buildResponse(List<ComponentDto> components, Map<String, SnapshotDto> snapshotsByComponentUuid,
Map<String, Long> lastAnalysisDateByComponentUuid, Map<String, String> projectUuidByComponentUuid, Paging paging) {
Map<String, Long> lastAnalysisDateByComponentUuid, Map<String, String> projectUuidByComponentUuid, Map<String, Boolean> componentUuidToManaged, Paging paging) {
SearchWsResponse.Builder responseBuilder = newBuilder(); SearchWsResponse.Builder responseBuilder = newBuilder();
responseBuilder.getPagingBuilder() responseBuilder.getPagingBuilder()
.setPageIndex(paging.pageIndex()) .setPageIndex(paging.pageIndex())
.build(); .build();


components.stream() components.stream()
.map(dto -> dtoToProject(dto, snapshotsByComponentUuid.get(dto.uuid()), lastAnalysisDateByComponentUuid.get(projectUuidByComponentUuid.get(dto.uuid()))))
.map(dto -> dtoToProject(dto, snapshotsByComponentUuid.get(dto.uuid()), lastAnalysisDateByComponentUuid.get(projectUuidByComponentUuid.get(dto.uuid())),
PROJECT.equals(dto.qualifier()) ? componentUuidToManaged.get(dto.uuid()) : null))
.forEach(responseBuilder::addComponents); .forEach(responseBuilder::addComponents);
return responseBuilder.build(); return responseBuilder.build();
} }


private static Component dtoToProject(ComponentDto dto, @Nullable SnapshotDto snapshot, @Nullable Long lastAnalysisDate) {
private static Component dtoToProject(ComponentDto dto, @Nullable SnapshotDto snapshot, @Nullable Long lastAnalysisDate, @Nullable Boolean isManaged) {
Component.Builder builder = Component.newBuilder() Component.Builder builder = Component.newBuilder()
.setKey(dto.getKey()) .setKey(dto.getKey())
.setName(dto.name()) .setName(dto.name())
ofNullable(lastAnalysisDate).ifPresent(d -> builder.setLastAnalysisDate(formatDateTime(d))); ofNullable(lastAnalysisDate).ifPresent(d -> builder.setLastAnalysisDate(formatDateTime(d)));
ofNullable(snapshot.getRevision()).ifPresent(builder::setRevision); ofNullable(snapshot.getRevision()).ifPresent(builder::setRevision);
} }
ofNullable(isManaged).ifPresent(builder::setManaged);


return builder.build(); return builder.build();
} }

+ 5
- 3
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/project/ws/search-example.json Ver fichero

"qualifier": "TRK", "qualifier": "TRK",
"visibility": "public", "visibility": "public",
"lastAnalysisDate": "2017-03-01T11:39:03+0300", "lastAnalysisDate": "2017-03-01T11:39:03+0300",
"revision": "cfb82f55c6ef32e61828c4cb3db2da12795fd767"
"revision": "cfb82f55c6ef32e61828c4cb3db2da12795fd767",
"managed": false
}, },
{ {
"key": "project-key-2", "key": "project-key-2",
"name": "Project Name 1",
"name": "Project Name 2",
"qualifier": "TRK", "qualifier": "TRK",
"visibility": "private", "visibility": "private",
"lastAnalysisDate": "2017-03-02T15:21:47+0300", "lastAnalysisDate": "2017-03-02T15:21:47+0300",
"revision": "7be96a94ac0c95a61ee6ee0ef9c6f808d386a355"
"revision": "7be96a94ac0c95a61ee6ee0ef9c6f808d386a355",
"managed": false
} }
] ]
} }

+ 1
- 0
sonar-ws/src/main/protobuf/ws-projects.proto Ver fichero

optional string visibility = 6; optional string visibility = 6;
optional string lastAnalysisDate = 7; optional string lastAnalysisDate = 7;
optional string revision = 8; optional string revision = 8;
optional bool managed = 9;
} }
} }



Cargando…
Cancelar
Guardar