Skip to content

Commit 86d4077

Browse files
author
Toni Saario
committed
Add a button to trigger CI early check
This allow users to start a early check integration from gerrit. Precheck requires that user is able to approve the change. Task-number: QTQAINFRA-3099 Change-Id: Ib5e8188317993f1c7c33e34e333f91648e33ebe9 Reviewed-by: Toni Saario <[email protected]> Reviewed-by: Paul Wicking <[email protected]> Reviewed-by: Jukka Jokiniva <[email protected]>
1 parent e8b5ec3 commit 86d4077

File tree

6 files changed

+223
-1
lines changed

6 files changed

+223
-1
lines changed

qt-gerrit-ui-plugin/qt-gerrit-ui-plugin.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
'gerrit-plugin-qt-workflow~defer',
1414
'gerrit-plugin-qt-workflow~reopen',
1515
'gerrit-plugin-qt-workflow~stage',
16-
'gerrit-plugin-qt-workflow~unstage'
16+
'gerrit-plugin-qt-workflow~unstage',
17+
'gerrit-plugin-qt-workflow~precheck'
1718
];
1819

1920
Gerrit.install(plugin => {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// Copyright (C) 2021 The Qt Company
3+
//
4+
5+
package com.googlesource.gerrit.plugins.qtcodereview;
6+
7+
import com.google.gerrit.entities.Change;
8+
import com.google.gerrit.server.events.PatchSetEvent;
9+
10+
public class QtChangePreCheckEvent extends PatchSetEvent {
11+
public static final String TYPE = "precheck";
12+
public String commitID = "";
13+
14+
public QtChangePreCheckEvent(Change change) {
15+
super(TYPE, change);
16+
}
17+
}

src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class QtModule extends FactoryModule {
2121
static {
2222
EventTypes.register(QtChangeStagedEvent.TYPE, QtChangeStagedEvent.class);
2323
EventTypes.register(QtChangeUnStagedEvent.TYPE, QtChangeUnStagedEvent.class);
24+
EventTypes.register(QtChangePreCheckEvent.TYPE, QtChangePreCheckEvent.class);
2425
}
2526

2627
@Override
@@ -39,6 +40,7 @@ protected void configure() {
3940
post(CHANGE_KIND, "reopen").to(QtReOpen.class);
4041
post(REVISION_KIND, "stage").to(QtStage.class);
4142
post(REVISION_KIND, "unstage").to(QtUnStage.class);
43+
post(REVISION_KIND, "precheck").to(QtPreCheck.class);
4244
}
4345
});
4446
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//
2+
// Copyright (C) 2021 The Qt Company
3+
//
4+
5+
package com.googlesource.gerrit.plugins.qtcodereview;
6+
7+
import com.google.common.base.MoreObjects;
8+
import com.google.common.base.Strings;
9+
import com.google.common.collect.ImmutableMap;
10+
import com.google.common.flogger.FluentLogger;
11+
import com.google.gerrit.common.data.ParameterizedString;
12+
import com.google.gerrit.extensions.api.changes.SubmitInput;
13+
import com.google.gerrit.extensions.restapi.RestApiException;
14+
import com.google.gerrit.extensions.restapi.RestModifyView;
15+
import com.google.gerrit.extensions.restapi.AuthException;
16+
import com.google.gerrit.extensions.restapi.Response;
17+
import com.google.gerrit.extensions.webui.UiAction;
18+
import com.google.gerrit.entities.Change;
19+
import com.google.gerrit.server.change.RevisionResource;
20+
import com.google.gerrit.server.config.GerritServerConfig;
21+
import com.google.gerrit.server.permissions.LabelPermission;
22+
import com.google.gerrit.server.permissions.PermissionBackend;
23+
import com.google.gerrit.server.permissions.PermissionBackendException;
24+
import com.google.gerrit.server.permissions.LabelPermission.ForUser;
25+
import com.google.gerrit.server.query.change.ChangeData;
26+
import com.google.gerrit.server.update.UpdateException;
27+
import com.google.inject.Inject;
28+
import com.google.inject.Singleton;
29+
import org.eclipse.jgit.lib.Config;
30+
import org.eclipse.jgit.lib.ObjectId;
31+
import org.eclipse.jgit.errors.RepositoryNotFoundException;
32+
import org.eclipse.jgit.errors.ConfigInvalidException;
33+
import java.io.IOException;
34+
import java.util.Map;
35+
36+
@Singleton
37+
public class QtPreCheck
38+
implements RestModifyView<RevisionResource, SubmitInput>, UiAction<RevisionResource> {
39+
40+
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
41+
private static final String DEFAULT_TOOLTIP = "Trigger a precheck integration";
42+
private static final String LABEL_CODE_REVIEW = "Code-Review";
43+
private static final short LABEL_CODE_REVIEW_VALUE = 2;
44+
45+
public static class Output {
46+
transient Change change;
47+
48+
private Output(Change c) {
49+
change = c;
50+
}
51+
}
52+
53+
private final PermissionBackend permissionBackend;
54+
private final ChangeData.Factory changeDataFactory;
55+
private final QtUtil qtUtil;
56+
private final String label;
57+
private final ParameterizedString titlePattern;
58+
59+
private Change change;
60+
61+
@Inject
62+
QtPreCheck(
63+
PermissionBackend permissionBackend,
64+
@GerritServerConfig Config cfg,
65+
ChangeData.Factory changeDataFactory,
66+
QtUtil qtUtil) {
67+
68+
this.permissionBackend = permissionBackend;
69+
this.changeDataFactory = changeDataFactory;
70+
this.qtUtil = qtUtil;
71+
this.label = "PreCheck";
72+
this.titlePattern =
73+
new ParameterizedString(
74+
MoreObjects.firstNonNull(
75+
cfg.getString("precheck", null, "precheckTooltip"), DEFAULT_TOOLTIP));
76+
}
77+
78+
@Override
79+
public Response<Output> apply(RevisionResource rsrc, SubmitInput input)
80+
throws RestApiException, RepositoryNotFoundException, IOException, PermissionBackendException,
81+
UpdateException, ConfigInvalidException {
82+
logger.atInfo().log("qtcodereview: precheck request for %s", rsrc.getChange().toString());
83+
boolean canReview;
84+
85+
canReview = rsrc.permissions().test(new LabelPermission.
86+
WithValue(ForUser.SELF, LABEL_CODE_REVIEW, LABEL_CODE_REVIEW_VALUE));
87+
88+
if (!canReview) {
89+
throw new AuthException(String.format("Precheck request from user %s without permission, %s",
90+
rsrc.getUser().getUserName(), rsrc.getChange().toString()));
91+
}
92+
93+
Change change = rsrc.getChange();
94+
Output output;
95+
output = new Output(change);
96+
this.qtUtil.postChangePreCheckEvent(change, rsrc.getPatchSet());
97+
return Response.ok(output);
98+
}
99+
100+
@Override
101+
public UiAction.Description getDescription(RevisionResource resource) {
102+
boolean canReview;
103+
try {
104+
canReview = resource.permissions().test(new LabelPermission
105+
.WithValue(ForUser.SELF, LABEL_CODE_REVIEW, LABEL_CODE_REVIEW_VALUE));
106+
} catch (PermissionBackendException e) {
107+
logger.atInfo().log(e.getMessage());
108+
return null;
109+
}
110+
111+
if (!canReview) {
112+
return null;
113+
}
114+
115+
Change change = resource.getChange();
116+
if (!change.getStatus().isOpen()
117+
|| !resource.isCurrent()) {
118+
return null; // precheck not visible
119+
}
120+
121+
ObjectId revId = resource.getPatchSet().commitId();
122+
Map<String, String> params =
123+
ImmutableMap.of(
124+
"patchSet", String.valueOf(resource.getPatchSet().number()),
125+
"branch", change.getDest().shortName(),
126+
"commit", revId.abbreviate(7).name());
127+
return new UiAction.Description()
128+
.setLabel(this.label)
129+
.setTitle(Strings.emptyToNull(titlePattern.replace(params)))
130+
.setVisible(true)
131+
.setEnabled(true);
132+
}
133+
}

src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtUtil.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,4 +682,15 @@ public void postChangeIntegrationFailEvent(Change change) {
682682
}
683683
}
684684

685+
public void postChangePreCheckEvent(Change change, PatchSet patchSet) {
686+
try {
687+
ChangeNotes notes = changeNotesFactory.createChecked(change.getId());
688+
QtChangePreCheckEvent event = new QtChangePreCheckEvent(change);
689+
event.change = changeAttributeSupplier(change, notes);
690+
event.commitID = patchSet.commitId().name();
691+
eventDispatcher.get().postEvent(event);
692+
} catch (StorageException | PermissionBackendException e) {
693+
logger.atWarning().log("qtcodereview: postChangePreCheckEvent failed: %s", e);
694+
}
695+
}
685696
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (C) 2021 The Qt Company
2+
3+
package com.googlesource.gerrit.plugins.qtcodereview;
4+
5+
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
6+
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
7+
8+
import com.google.gerrit.acceptance.PushOneCommit;
9+
import com.google.gerrit.acceptance.RestResponse;
10+
import com.google.gerrit.acceptance.TestPlugin;
11+
import com.google.gerrit.acceptance.UseSsh;
12+
import com.google.gerrit.entities.AccountGroup;
13+
import org.apache.http.HttpStatus;
14+
import org.junit.Test;
15+
16+
@TestPlugin(
17+
name = "gerrit-plugin-qt-workflow",
18+
sysModule = "com.googlesource.gerrit.plugins.qtcodereview.QtModule",
19+
sshModule = "com.googlesource.gerrit.plugins.qtcodereview.QtSshModule")
20+
21+
@UseSsh
22+
public class QtPreCheckIT extends QtCodeReviewIT {
23+
24+
@Test
25+
public void preCheck_Ok() throws Exception {
26+
PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1");
27+
28+
AccountGroup.UUID registered = systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
29+
projectOperations.project(project).forUpdate()
30+
.add(allowLabel("Code-Review").ref("refs/heads/*").group(registered).range(-2, 2))
31+
.update();
32+
33+
RestResponse response = call_REST_API_PreCheck(c.getChangeId(), c.getCommit().getName());
34+
response.assertOK();
35+
}
36+
37+
@Test
38+
public void errorPreCheck_No_Permission() throws Exception {
39+
PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1");
40+
41+
AccountGroup.UUID registered = systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
42+
projectOperations.project(project).forUpdate()
43+
.add(allowLabel("Code-Review").ref("refs/heads/*").group(registered).range(-1, 1))
44+
.update();
45+
46+
RestResponse response = call_REST_API_PreCheck(c.getChangeId(), c.getCommit().getName());
47+
response.assertStatus(HttpStatus.SC_FORBIDDEN);
48+
}
49+
50+
protected RestResponse call_REST_API_PreCheck(String changeId, String revisionId)
51+
throws Exception {
52+
String url =
53+
"/changes/" + changeId + "/revisions/" + revisionId + "/gerrit-plugin-qt-workflow~precheck";
54+
RestResponse response = userRestSession.post(url);
55+
return response;
56+
}
57+
58+
}

0 commit comments

Comments
 (0)