@Transactional
  public Release rollbackTo(long releaseId, long toReleaseId, String operator) {
    if (releaseId == toReleaseId) {
      throw new BadRequestException("current release equal to target release");
    }

    Release release = findOne(releaseId);
    Release toRelease = findOne(toReleaseId);

    if (release == null) {
      throw NotFoundException.releaseNotFound(releaseId);
    }
    if (toRelease == null) {
      throw NotFoundException.releaseNotFound(toReleaseId);
    }
    if (release.isAbandoned() || toRelease.isAbandoned()) {
      throw new BadRequestException("release is not active");
    }

    String appId = release.getAppId();
    String clusterName = release.getClusterName();
    String namespaceName = release.getNamespaceName();

    List<Release> releases = findActiveReleasesBetween(appId, clusterName, namespaceName,
                                                       toReleaseId, releaseId);

    for (int i = 0; i < releases.size() - 1; i++) {
      releases.get(i).setAbandoned(true);
      releases.get(i).setDataChangeLastModifiedBy(operator);
    }

    releaseRepository.saveAll(releases);

    releaseHistoryService.createReleaseHistory(appId, clusterName,
                                               namespaceName, clusterName, toReleaseId,
                                               release.getId(), ReleaseOperation.ROLLBACK, null, operator);

    //publish child namespace if namespace has child
    rollbackChildNamespace(appId, clusterName, namespaceName, Lists.newArrayList(release, toRelease), operator);

    return release;
  }
@Test
  public void testRollbackTo() {
    List<Release> releaseList = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
      Release release = new Release();
      release.setId(3 - i);
      release.setAppId(appId);
      release.setClusterName(clusterName);
      release.setNamespaceName(namespaceName);
      release.setAbandoned(false);
      releaseList.add(release);
    }
    long releaseId1 = 1;
    long releaseId3 = 3;
    when(releaseRepository.findById(releaseId1)).thenReturn(Optional.of(releaseList.get(2)));
    when(releaseRepository.findById(releaseId3)).thenReturn(Optional.of(releaseList.get(0)));
    when(releaseRepository.findByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseAndIdBetweenOrderByIdDesc(appId,
                                                                                                                 clusterName,
                                                                                                                 namespaceName,
                                                                                                                 releaseId1,
                                                                                                                 releaseId3))
        .thenReturn(releaseList);

    releaseService.rollbackTo(releaseId3, releaseId1, user);

    verify(releaseRepository).saveAll(releaseList);
    Assert.assertTrue(releaseList.get(0).isAbandoned());
    Assert.assertTrue(releaseList.get(1).isAbandoned());
    Assert.assertFalse(releaseList.get(2).isAbandoned());
    Assert.assertEquals(user, releaseList.get(0).getDataChangeLastModifiedBy());
    Assert.assertEquals(user, releaseList.get(1).getDataChangeLastModifiedBy());
  }