Skip to content

Commit

Permalink
Merge pull request #293 from Checkmarx/feature/miryamFoifer/useLocalB…
Browse files Browse the repository at this point in the history
…ranch

Create A CxOne Scan From A Local branch (AST-75821)
  • Loading branch information
miryamfoiferCX authored Dec 17, 2024
2 parents 05d83e8 + 1e8d1e7 commit ce2bb59
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 25 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ jobs:
# Save report if tests fail
- name: Save fails report
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-fails-report
path: |
build/reports
# Save idea log if tests fail
- name: Save idea log
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: idea.log
path: |
Expand All @@ -99,7 +99,7 @@ jobs:
# Save report if tests fail
- name: Save fails report
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-fails-report-integration
path: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-ui-mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ jobs:
# Save report if tests fail
- name: Save fails report
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-mac-fails-report
path: build/reports
# Save idea log if tests fail
- name: Save idea log
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: idea.log
path: idea.log
4 changes: 2 additions & 2 deletions .github/workflows/test-ui-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ jobs:
# Save report if tests fail
- name: Save fails report
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-fails-report
path: build/reports
# Save idea log if tests fail
- name: Save idea log
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: idea.log
path: idea.log
4 changes: 2 additions & 2 deletions .github/workflows/test-ui-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ jobs:
# Save report if tests fail
- name: Save fails report
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-fails-report
path: build/reports
# Save idea log if tests fail
- name: Save idea log
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: idea.log
path: idea.log
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ dependencies {
}
implementation(platform("com.fasterxml.jackson:jackson-bom:2.16.1"))
// Temporary workaround https://github.com/FasterXML/jackson-databind/issues/3428

testImplementation 'org.mockito:mockito-core:5.0.0'
testImplementation 'org.mockito:mockito-junit-jupiter:5.0.0' // maybe remove
}

// See https://github.com/JetBrains/gradle-intellij-plugin/
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/checkmarx/intellij/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,6 @@ private Constants() {
public static final String ASCA_HIGH_SEVERITY = "High";
public static final String ASCA_MEDIUM_SEVERITY = "Medium";
public static final String ASCA_LOW_SEVERITY = "Low";

public static final String USE_LOCAL_BRANCH = "scan my local branch";
}
11 changes: 9 additions & 2 deletions src/main/java/com/checkmarx/intellij/commands/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.checkmarx.ast.wrapper.CxConfig;
import com.checkmarx.ast.wrapper.CxException;
import com.checkmarx.intellij.Constants;
import com.checkmarx.intellij.Utils;
import com.checkmarx.intellij.settings.global.CxWrapperFactory;
import lombok.NonNull;

Expand All @@ -26,14 +28,19 @@ public static List<com.checkmarx.ast.project.Project> getList()
return CxWrapperFactory.build().projectList("limit=10000");
}

public static List<String> getBranches(@NonNull UUID projectId)
public static List<String> getBranches(@NonNull UUID projectId, boolean isSCMProject)
throws
IOException,
URISyntaxException,
InterruptedException,
CxConfig.InvalidCLIConfigException,
CxException {

return CxWrapperFactory.build().projectBranches(projectId, "");
List<String> branches = CxWrapperFactory.build().projectBranches(projectId, "");
if(isSCMProject) {
branches.add(0, Constants.USE_LOCAL_BRANCH);
}

return branches;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ public void actionPerformed(@NotNull AnActionEvent e) {
// Case it is a git repo check for project and branch match
if (repository != null) {
String storedBranch = Optional.ofNullable(propertiesComponent.getValue(Constants.SELECTED_BRANCH_PROPERTY)).orElse(StringUtils.EMPTY);
if(storedBranch.equals(Constants.USE_LOCAL_BRANCH)) {
storedBranch = getActiveBranch(workspaceProject);
}
boolean matchBranch = storedBranch.equals(Objects.requireNonNull(repository).getCurrentBranchName());
if(matchBranch && matchProject) {
createScan();
Expand Down Expand Up @@ -159,6 +162,9 @@ private void createScan() {
@Override
public void run(@NotNull ProgressIndicator indicator) {
String storedBranch = propertiesComponent.getValue(Constants.SELECTED_BRANCH_PROPERTY);
if(storedBranch.equals(Constants.USE_LOCAL_BRANCH)) {
storedBranch = getActiveBranch(workspaceProject);
}
String storedProject = propertiesComponent.getValue(Constants.SELECTED_PROJECT_PROPERTY);

LOGGER.info(msg(Resource.STARTING_SCAN_IDE, storedProject, storedBranch));
Expand Down Expand Up @@ -187,7 +193,7 @@ public void onFinished() {
*
* @param scanId - scan id
*/
private void pollScan(String scanId) {
public void pollScan(String scanId) {
isPollingScan = true;

pollScanTask = new Task.Backgroundable(workspaceProject, msg(Resource.SCAN_RUNNING_TITLE)) {
Expand Down Expand Up @@ -260,6 +266,7 @@ private Runnable pollingScan(String scanId) {
private void loadResults(com.checkmarx.ast.scan.Scan scan) {
LOGGER.info(msg(Resource.LOAD_RESULTS, scan.getId()));
ScanSelectionGroup scanSelectionGroup = cxToolWindowPanel.getRootGroup().getScanSelectionGroup();
propertiesComponent.setValue(Constants.SELECTED_BRANCH_PROPERTY, scan.getBranch());
scanSelectionGroup.refresh(scan.getProjectId(), scan.getBranch(), true);
}

Expand Down Expand Up @@ -315,4 +322,8 @@ private static String msg(Resource resource, Object... params) {
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.BGT;
}

public String getActiveBranch(Project project) {
return Utils.getRootRepository(project) == null ? null : Objects.requireNonNull(Utils.getRootRepository(project)).getCurrentBranchName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.checkmarx.intellij.Constants;
import com.checkmarx.intellij.Resource;
import com.checkmarx.intellij.Utils;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
Expand Down Expand Up @@ -42,14 +41,39 @@ public BranchSelectionGroup(@NotNull Project project,
@Override
protected @NotNull String getTitle() {
if (getChildrenCount() == 0) {
return Bundle.message(Resource.BRANCH_SELECT_PREFIX) + ": " + (isEnabled() ? NONE_SELECTED : "...");
return Bundle.message(Resource.BRANCH_SELECT_PREFIX) + ": " + (isEnabled() ? setDefaultBranch() : "...");
}
String storedBranch = propertiesComponent.getValue(Constants.SELECTED_BRANCH_PROPERTY);
return Bundle.message(Resource.BRANCH_SELECT_PREFIX)
+ ": "
+ (StringUtils.isBlank(storedBranch) ? NONE_SELECTED : storedBranch);
+ (StringUtils.isBlank(storedBranch) ? setDefaultBranch() : storedBranch);
}

private String setDefaultBranch() {
if(branches == null || branches.isEmpty()) {
return NONE_SELECTED;
}
String activeBranch = getActiveBranch();
if(activeBranch == null) {
return NONE_SELECTED;
}
if(branches.contains(activeBranch)) {
updateActiveBranchAndFetchScans(activeBranch);
return activeBranch;
}
updateLocalBranch();
return branches.get(0);

}

private void updateLocalBranch() {
propertiesComponent.setValue(Constants.SELECTED_BRANCH_PROPERTY, Constants.USE_LOCAL_BRANCH);
scanSelectionGroup.clear();
setEnabled(true);
refreshPanel(project);
}


@Override
protected void clear() {
projectId = null;
Expand Down Expand Up @@ -78,7 +102,8 @@ void refresh(String projectId, boolean inherit) {
CompletableFuture.supplyAsync(() -> {
List<String> branches = null;
try {
branches = com.checkmarx.intellij.commands.Project.getBranches(UUID.fromString(projectId));
boolean isSCMProject = Utils.getRootRepository(project) != null;
branches = com.checkmarx.intellij.commands.Project.getBranches(UUID.fromString(projectId), isSCMProject);
} catch (Exception e) {
LOGGER.warn(e);
}
Expand All @@ -87,19 +112,25 @@ void refresh(String projectId, boolean inherit) {
this.branches = branches;
String storedBranch = propertiesComponent.getValue(Constants.SELECTED_BRANCH_PROPERTY);
String activeBranch = getActiveBranch();
branches.forEach(branch -> add(new Action(projectId, branch)));
for (String branch : branches) {
add(new Action(projectId, branch));
if (inherit && storedBranch == null && Objects.equals(branch, activeBranch)) {
propertiesComponent.setValue(Constants.SELECTED_BRANCH_PROPERTY, branch);
refreshScanGroup(projectId, branch, false);
} else if (branch.equals(storedBranch)) {
if(Objects.equals(branch, activeBranch)) {
updateActiveBranchAndFetchScans(branch);
break;
}
else if (branch.equals(storedBranch) && !branch.equals(Constants.USE_LOCAL_BRANCH)) {
refreshScanGroup(projectId, branch, false);
}
}
setEnabled(true);
refreshPanel(project);
}));
}

private void updateActiveBranchAndFetchScans(String branchName) {
propertiesComponent.setValue(Constants.SELECTED_BRANCH_PROPERTY, branchName);
refreshScanGroup(projectId, branchName, false);
}
/**
* Repopulate the scan selection according to the given branch
* @param projectId selected project
Expand All @@ -119,7 +150,7 @@ private void refreshScanGroup(String projectId, String branch, boolean autoSelec
* @return active branch name or null
*/
@Nullable
private String getActiveBranch() {
public String getActiveBranch() {
return Utils.getRootRepository(project) == null ? null : Objects.requireNonNull(Utils.getRootRepository(project)).getCurrentBranchName();
}

Expand All @@ -141,7 +172,12 @@ public void actionPerformed(@NotNull AnActionEvent e) {
String branch = getTemplatePresentation().getText();
propertiesComponent.setValue(Constants.SELECTED_BRANCH_PROPERTY, branch);
scanSelectionGroup.clear();
refreshScanGroup(projectId, branch, true);
if(!branch.equals(Constants.USE_LOCAL_BRANCH)) {
refreshScanGroup(projectId, branch, true);
}
else {
refreshPanel(project);
}
}
}

Expand Down
93 changes: 93 additions & 0 deletions src/test/java/com/checkmarx/intellij/BranchSelectionGroupTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.checkmarx.intellij;

import com.checkmarx.intellij.tool.window.actions.selection.BranchSelectionGroup;
import com.checkmarx.intellij.tool.window.actions.selection.ScanSelectionGroup;
import com.intellij.openapi.project.Project;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.lang.reflect.Field;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

public class BranchSelectionGroupTest {

@Mock
private Project project;

@Mock
private ScanSelectionGroup scanSelectionGroup;

@Mock
private PropertiesComponent propertiesComponent;

private Method setDefaultBranchMethod;

private BranchSelectionGroup branchSelectionGroup;

@BeforeEach
public void setUp() throws NoSuchMethodException {
MockitoAnnotations.openMocks(this);
when(project.getService(PropertiesComponent.class)).thenReturn(propertiesComponent);
MessageBus messageBus = mock(MessageBus.class);
MessageBusConnection messageBusConnection = mock(MessageBusConnection.class);
when(project.getMessageBus()).thenReturn(messageBus);
when(messageBus.connect()).thenReturn(messageBusConnection);

ToolWindowManager toolWindowManager = mock(ToolWindowManager.class);
when(project.getService(ToolWindowManager.class)).thenReturn(toolWindowManager);

branchSelectionGroup = spy(new BranchSelectionGroup(project, scanSelectionGroup));

setDefaultBranchMethod = BranchSelectionGroup.class.getDeclaredMethod("setDefaultBranch");
setDefaultBranchMethod.setAccessible(true);
}

private void setBranches(BranchSelectionGroup branchSelectionGroup, List<String> branches) throws NoSuchFieldException, IllegalAccessException {
Field branchesField = BranchSelectionGroup.class.getDeclaredField("branches");
branchesField.setAccessible(true);
branchesField.set(branchSelectionGroup, branches);
}

@Test
public void testSetDefaultBranch_WhenBranches_shouldReturnNone() throws Exception {
setBranches(branchSelectionGroup, Collections.emptyList());
String result = (String) setDefaultBranchMethod.invoke(branchSelectionGroup);
assertEquals("none", result);
}

@Test
public void testSetDefaultBranch_WhenActiveBranchInList_shouldReturnActiveBranch() throws Exception {
List<String> branches = List.of("main", "develop");
setBranches(branchSelectionGroup, branches);

doReturn("main").when(branchSelectionGroup).getActiveBranch();

String result = (String) setDefaultBranchMethod.invoke(branchSelectionGroup);
assertEquals("main", result);
verify(propertiesComponent).setValue("Checkmarx.SelectedBranch", "main");
}

@Test
public void testSetDefaultBranch_WhenActiveBranchNotInList_shouldReturnLocalBranchTitle() throws Exception {
List<String> branches = List.of("main", "develop");
setBranches(branchSelectionGroup, branches);

doReturn(Constants.USE_LOCAL_BRANCH).when(branchSelectionGroup).getActiveBranch();

String result = (String) setDefaultBranchMethod.invoke(branchSelectionGroup);
assertEquals("main", result);
verify(propertiesComponent).setValue("Checkmarx.SelectedBranch", Constants.USE_LOCAL_BRANCH);
}
}
Loading

0 comments on commit ce2bb59

Please sign in to comment.