Merge branch 'feature/entities-version-control' of github.com:thingsboard/thingsboard into feature/entities-version-control

This commit is contained in:
Andrii Shvaika 2022-05-31 13:19:28 +03:00
commit bf03475987
13 changed files with 71 additions and 25 deletions

View File

@ -119,7 +119,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
@SuppressWarnings("UnstableApiUsage")
@Override
public ListenableFuture<VersionCreationResult> saveEntitiesVersion(SecurityUser user, VersionCreateRequest request) throws Exception {
var pendingCommit = gitServiceQueue.prepareCommit(user.getTenantId(), request);
var pendingCommit = gitServiceQueue.prepareCommit(user, request);
return transformAsync(pendingCommit, commit -> {
List<ListenableFuture<Void>> gitFutures = new ArrayList<>();

View File

@ -27,6 +27,7 @@ import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.TenantId;
@ -66,10 +67,7 @@ import org.thingsboard.server.service.sync.vc.data.PendingGitRequest;
import org.thingsboard.server.service.sync.vc.data.VersionsDiffGitRequest;
import org.thingsboard.server.service.sync.vc.data.VoidGitRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -96,12 +94,12 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
}
@Override
public ListenableFuture<CommitGitRequest> prepareCommit(TenantId tenantId, VersionCreateRequest request) {
public ListenableFuture<CommitGitRequest> prepareCommit(User user, VersionCreateRequest request) {
SettableFuture<CommitGitRequest> future = SettableFuture.create();
CommitGitRequest commit = new CommitGitRequest(tenantId, request);
CommitGitRequest commit = new CommitGitRequest(user.getTenantId(), request);
registerAndSend(commit, builder -> builder.setCommitRequest(
buildCommitRequest(commit).setPrepareMsg(getCommitPrepareMsg(request)).build()
buildCommitRequest(commit).setPrepareMsg(getCommitPrepareMsg(user, request)).build()
).build(), wrap(future, commit));
return future;
}
@ -356,7 +354,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
} else if (vcResponseMsg.hasCommitResponse()) {
var commitResponse = vcResponseMsg.getCommitResponse();
var commitResult = new VersionCreationResult();
commitResult.setVersion(new EntityVersion(commitResponse.getTs(), commitResponse.getCommitId(), commitResponse.getName()));
commitResult.setVersion(new EntityVersion(commitResponse.getTs(), commitResponse.getCommitId(), commitResponse.getName(), commitResponse.getAuthor()));
commitResult.setAdded(commitResponse.getAdded());
commitResult.setRemoved(commitResponse.getRemoved());
commitResult.setModified(commitResponse.getModified());
@ -405,7 +403,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
}
private EntityVersion getEntityVersion(TransportProtos.EntityVersionProto proto) {
return new EntityVersion(proto.getTs(), proto.getId(), proto.getName());
return new EntityVersion(proto.getTs(), proto.getId(), proto.getName(), proto.getAuthor());
}
private VersionedEntityInfo getVersionedEntityInfo(TransportProtos.VersionedEntityInfoProto proto) {
@ -453,8 +451,23 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
return path;
}
private static PrepareMsg getCommitPrepareMsg(VersionCreateRequest request) {
return PrepareMsg.newBuilder().setCommitMsg(request.getVersionName()).setBranchName(request.getBranch()).build();
private static PrepareMsg getCommitPrepareMsg(User user, VersionCreateRequest request) {
return PrepareMsg.newBuilder().setCommitMsg(request.getVersionName())
.setBranchName(request.getBranch()).setAuthorName(getAuthorName(user)).setAuthorEmail(user.getEmail()).build();
}
private static String getAuthorName(User user) {
List<String> parts = new ArrayList<>();
if (StringUtils.isNotBlank(user.getFirstName())) {
parts.add(user.getFirstName());
}
if (StringUtils.isNotBlank(user.getLastName())) {
parts.add(user.getLastName());
}
if (parts.isEmpty()) {
parts.add(user.getName());
}
return String.join(" ", parts);
}
private ToVersionControlServiceMsg.Builder newRequestProto(PendingGitRequest<?> request, RepositorySettings settings) {

View File

@ -18,6 +18,7 @@ package org.thingsboard.server.service.sync.vc;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
@ -36,7 +37,7 @@ import java.util.List;
public interface GitVersionControlQueueService {
ListenableFuture<CommitGitRequest> prepareCommit(TenantId tenantId, VersionCreateRequest request);
ListenableFuture<CommitGitRequest> prepareCommit(User user, VersionCreateRequest request);
ListenableFuture<Void> addToCommit(CommitGitRequest commit, EntityExportData<ExportableEntity<EntityId>> entityData);

View File

@ -692,14 +692,17 @@ message CommitResponseMsg {
int64 ts = 1;
string commitId = 2;
string name = 3;
int32 added = 4;
int32 modified = 5;
int32 removed = 6;
string author = 4;
int32 added = 5;
int32 modified = 6;
int32 removed = 7;
}
message PrepareMsg {
string commitMsg = 1;
string branchName = 2;
string authorName = 3;
string authorEmail = 4;
}
message AddMsg {
@ -733,6 +736,7 @@ message EntityVersionProto {
int64 ts = 1;
string id = 2;
string name = 3;
string author = 4;
}
message ListVersionsResponseMsg {

View File

@ -26,4 +26,5 @@ public class EntityVersion {
private long timestamp;
private String id;
private String name;
private String author;
}

View File

@ -312,7 +312,7 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe
.setTotalElements(data.getTotalElements())
.setHasNext(data.hasNext())
.addAllVersions(data.getData().stream().map(
v -> EntityVersionProto.newBuilder().setTs(v.getTimestamp()).setId(v.getId()).setName(v.getName()).build()
v -> EntityVersionProto.newBuilder().setTs(v.getTimestamp()).setId(v.getId()).setName(v.getName()).setAuthor(v.getAuthor()).build()
).collect(Collectors.toList())))
);
}
@ -397,7 +397,8 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe
private void prepareCommit(VersionControlRequestCtx ctx, UUID txId, PrepareMsg prepareMsg) {
var tenantId = ctx.getTenantId();
var pendingCommit = new PendingCommit(tenantId, ctx.getNodeId(), txId, prepareMsg.getBranchName(), prepareMsg.getCommitMsg());
var pendingCommit = new PendingCommit(tenantId, ctx.getNodeId(), txId, prepareMsg.getBranchName(),
prepareMsg.getCommitMsg(), prepareMsg.getAuthorName(), prepareMsg.getAuthorEmail());
PendingCommit old = pendingCommitMap.get(tenantId);
if (old != null) {
doAbortCurrentCommit(tenantId, old);
@ -460,6 +461,7 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe
.setTs(result.getVersion().getTimestamp())
.setCommitId(result.getVersion().getId())
.setName(result.getVersion().getName())
.setAuthor(result.getVersion().getAuthor())
.setAdded(result.getAdded())
.setModified(result.getModified())
.setRemoved(result.getRemoved())));

View File

@ -117,7 +117,7 @@ public class DefaultGitRepositoryService implements GitRepositoryService {
result.setModified(status.getModified().size());
result.setRemoved(status.getRemoved().size());
GitRepository.Commit gitCommit = repository.commit(commit.getVersionName());
GitRepository.Commit gitCommit = repository.commit(commit.getVersionName(), commit.getAuthorName(), commit.getAuthorEmail());
repository.push(commit.getWorkingBranch(), commit.getBranch());
result.setVersion(toVersion(gitCommit));
@ -255,7 +255,15 @@ public class DefaultGitRepositoryService implements GitRepositoryService {
}
private EntityVersion toVersion(GitRepository.Commit commit) {
return new EntityVersion(commit.getTimestamp(), commit.getId(), commit.getMessage());
return new EntityVersion(commit.getTimestamp(), commit.getId(), commit.getMessage(), this.getAuthor(commit));
}
private String getAuthor(GitRepository.Commit commit) {
String author = String.format("<%s>", commit.getAuthorEmail());
if (StringUtils.isNotBlank(commit.getAuthorName())) {
author = String.format("%s %s", commit.getAuthorName(), author);
}
return author;
}
public static EntityId fromRelativePath(String path) {

View File

@ -255,8 +255,9 @@ public class GitRepository {
return new Status(status.getAdded(), modified, status.getRemoved());
}
public Commit commit(String message) throws GitAPIException {
public Commit commit(String message, String authorName, String authorEmail) throws GitAPIException {
RevCommit revCommit = execute(git.commit()
.setAuthor(authorName, authorEmail)
.setMessage(message));
return toCommit(revCommit);
}
@ -325,7 +326,8 @@ public class GitRepository {
}
private Commit toCommit(RevCommit revCommit) {
return new Commit(revCommit.getCommitTime() * 1000l, revCommit.getName(), revCommit.getFullMessage(), revCommit.getAuthorIdent().getName());
return new Commit(revCommit.getCommitTime() * 1000l, revCommit.getName(),
revCommit.getFullMessage(), revCommit.getAuthorIdent().getName(), revCommit.getAuthorIdent().getEmailAddress());
}
private RevCommit resolveCommit(String id) throws IOException {
@ -470,6 +472,7 @@ public class GitRepository {
private final String id;
private final String message;
private final String authorName;
private final String authorEmail;
}
@Data

View File

@ -30,12 +30,18 @@ public class PendingCommit {
private String branch;
private String versionName;
public PendingCommit(TenantId tenantId, String nodeId, UUID txId, String branch, String versionName) {
private String authorName;
private String authorEmail;
public PendingCommit(TenantId tenantId, String nodeId, UUID txId, String branch, String versionName, String authorName, String authorEmail) {
this.tenantId = tenantId;
this.nodeId = nodeId;
this.txId = txId;
this.branch = branch;
this.versionName = versionName;
this.authorName = authorName;
this.authorEmail = authorEmail;
this.workingBranch = txId.toString();
}
}

View File

@ -101,11 +101,17 @@
</mat-cell>
</ng-container>
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef style="width: 100%"> {{ 'version-control.version-name' | translate }} </mat-header-cell>
<mat-header-cell *matHeaderCellDef style="width: 50%"> {{ 'version-control.version-name' | translate }} </mat-header-cell>
<mat-cell *matCellDef="let entityVersion">
{{ entityVersion.name }}
</mat-cell>
</ng-container>
<ng-container matColumnDef="author">
<mat-header-cell *matHeaderCellDef style="width: 50%"> {{ 'version-control.author' | translate }} </mat-header-cell>
<mat-cell *matCellDef="let entityVersion">
{{ entityVersion.author }}
</mat-cell>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>
<mat-header-cell *matHeaderCellDef [ngStyle]="singleEntityMode ? {minWidth: '80px', maxWidth: '80px', width: '80px'} :
{minWidth: '40px', maxWidth: '40px', width: '40px'}">

View File

@ -62,7 +62,7 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni
@Input()
singleEntityMode = false;
displayedColumns = ['timestamp', 'id', 'name', 'actions'];
displayedColumns = ['timestamp', 'id', 'name', 'author', 'actions'];
pageLink: PageLink;
textSearchMode = false;
dataSource: EntityVersionsDatasource;

View File

@ -138,6 +138,7 @@ export interface EntityVersion {
timestamp: number;
id: string;
name: string;
author: string;
}
export interface VersionCreationResult {

View File

@ -3119,6 +3119,7 @@
"create-entity-version": "Create entity version",
"version-name": "Version name",
"version-name-required": "Version name is required",
"author": "Author",
"export-entity-relations": "Export entity relations",
"entity-versions": "Entity versions",
"versions": "Versions",