Skip to content
This repository was archived by the owner on Sep 30, 2025. It is now read-only.

Commit 9803260

Browse files
authored
Merge pull request #235 from MicroFocus/octane-dev-latest
Octane defect fixes 5.7.3
2 parents 797d2c2 + 4d4984e commit 9803260

26 files changed

+667
-466
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@
470470
<dependency>
471471
<artifactId>integrations-sdk</artifactId>
472472
<groupId>com.hpe.adm.octane.ciplugins</groupId>
473-
<version>2.0.38</version>
473+
<version>2.0.40</version>
474474
</dependency>
475475

476476
<!--BUILDER providers integration-->

src/main/java/com/microfocus/application/automation/tools/octane/CIJenkinsServicesImpl.java

Lines changed: 108 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@
5858
import com.microfocus.application.automation.tools.octane.model.processors.projects.AbstractProjectProcessor;
5959
import com.microfocus.application.automation.tools.octane.model.processors.projects.JobProcessorFactory;
6060
import com.microfocus.application.automation.tools.octane.tests.TestListener;
61+
import com.microfocus.application.automation.tools.octane.tests.junit.JUnitExtension;
6162
import hudson.ProxyConfiguration;
6263
import hudson.console.PlainTextConsoleOutputStream;
64+
import hudson.matrix.MatrixConfiguration;
6365
import hudson.model.*;
6466
import hudson.security.ACLContext;
6567
import jenkins.model.Jenkins;
@@ -75,6 +77,8 @@
7577
import java.io.*;
7678
import java.net.URL;
7779
import java.net.URLDecoder;
80+
import java.nio.charset.StandardCharsets;
81+
import java.nio.file.Files;
7882
import java.util.*;
7983
import java.util.function.BiConsumer;
8084
import java.util.function.Function;
@@ -111,13 +115,13 @@ public void suspendCIEvents(boolean suspend) {
111115

112116
@Override
113117
public File getAllowedOctaneStorage() {
114-
return new File(Jenkins.getInstance().getRootDir(), "userContent");
118+
return new File(Jenkins.get().getRootDir(), "userContent");
115119
}
116120

117121
@Override
118122
public CIProxyConfiguration getProxyConfiguration(URL targetUrl) {
119123
CIProxyConfiguration result = null;
120-
ProxyConfiguration proxy = Jenkins.getInstance().proxy;
124+
ProxyConfiguration proxy = Jenkins.get().proxy;
121125
if (proxy != null) {
122126
boolean noProxyHost = false;
123127
for (Pattern pattern : proxy.getNoProxyHostPatterns()) {
@@ -141,66 +145,50 @@ public CIProxyConfiguration getProxyConfiguration(URL targetUrl) {
141145
public CIJobsList getJobsList(boolean includeParameters) {
142146
ACLContext securityContext = startImpersonation();
143147
CIJobsList result = dtoFactory.newDTO(CIJobsList.class);
144-
PipelineNode tmpConfig;
145-
TopLevelItem tmpItem;
146-
List<PipelineNode> list = new ArrayList<>();
148+
Map<String, PipelineNode> jobsMap = new HashMap<>();
149+
147150
try {
148-
boolean hasReadPermission = Jenkins.getInstance().hasPermission(Item.READ);
151+
boolean hasReadPermission = Jenkins.get().hasPermission(Item.READ);
149152
if (!hasReadPermission) {
150-
stopImpersonation(securityContext);
151153
throw new PermissionException(403);
152154
}
153-
List<String> itemNames = (List<String>) Jenkins.getInstance().getTopLevelItemNames();
154-
for (String name : itemNames) {
155-
tmpItem = Jenkins.getInstance().getItem(name);
156-
157-
if (tmpItem == null) {
158-
continue;
159-
}
160155

161-
String jobName = tmpItem.getName();
162-
String jobClassName = tmpItem.getClass().getName();
156+
Collection<String> jobNames = Jenkins.get().getJobNames();
157+
for (String jobName : jobNames) {
158+
String tempJobName = jobName;
163159
try {
164-
if (tmpItem instanceof AbstractProject) {
165-
AbstractProject abstractProject = (AbstractProject) tmpItem;
166-
if (abstractProject.isDisabled()) {
167-
continue;
168-
}
169-
tmpConfig = createPipelineNode(name, abstractProject, includeParameters);
170-
list.add(tmpConfig);
171-
} else if (jobClassName.equals(JobProcessorFactory.WORKFLOW_JOB_NAME)) {
172-
tmpConfig = createPipelineNode(name, (Job) tmpItem, includeParameters);
173-
list.add(tmpConfig);
174-
} else if (jobClassName.equals(JobProcessorFactory.FOLDER_JOB_NAME)) {
175-
for (Job tmpJob : tmpItem.getAllJobs()) {
176-
jobName = tmpJob.getFullName();
177-
tmpConfig = createPipelineNode(jobName, tmpJob, includeParameters);
178-
list.add(tmpConfig);
179-
}
180-
} else if (jobClassName.equals(JobProcessorFactory.WORKFLOW_MULTI_BRANCH_JOB_NAME)) {
181-
tmpConfig = createPipelineNodeFromJobName(name);
182-
list.add(tmpConfig);
183-
} else if (jobClassName.equals(JobProcessorFactory.GITHUB_ORGANIZATION_FOLDER)) {
184-
Collection<? extends Item> items = ((AbstractFolder) tmpItem).getItems();
185-
for (Item item : items) {
186-
jobName = item.getFullName();
187-
tmpConfig = createPipelineNodeFromJobNameAndFolder(item.getDisplayName(), name);
188-
list.add(tmpConfig);
189-
}
160+
Job tmpJob = (Job) Jenkins.get().getItemByFullName(tempJobName);
161+
162+
if (tmpJob == null) {
163+
continue;
164+
}
165+
if (tmpJob instanceof AbstractProject && ((AbstractProject) tmpJob).isDisabled()) {
166+
continue;
167+
}
168+
if (tmpJob instanceof MatrixConfiguration) {
169+
continue;
170+
}
171+
172+
PipelineNode tmpConfig;
173+
if (JobProcessorFactory.WORKFLOW_MULTI_BRANCH_JOB_NAME.equals(tmpJob.getParent().getClass().getName())) {
174+
tempJobName = tmpJob.getParent().getFullName();
175+
tmpConfig = createPipelineNodeFromJobName(tempJobName);
190176
} else {
191-
logger.info(String.format("getJobsList : Item '%s' of type '%s' is not supported", jobName, jobClassName));
177+
tmpConfig = createPipelineNode(tempJobName, tmpJob, includeParameters);
192178
}
179+
jobsMap.put(tempJobName, tmpConfig);
193180
} catch (Throwable e) {
194-
logger.error("getJobsList : Failed to add job '" + jobName + "' to JobList : " + e.getClass().getCanonicalName() + " - " + e.getMessage(), e);
181+
logger.error("failed to add job '" + tempJobName + "' to JobList", e);
195182
}
196-
197183
}
198-
result.setJobs(list.toArray(new PipelineNode[0]));
199-
} catch (AccessDeniedException e) {
184+
185+
result.setJobs(jobsMap.values().toArray(new PipelineNode[0]));
186+
} catch (AccessDeniedException ade) {
200187
throw new PermissionException(403);
201188
} finally {
202189
stopImpersonation(securityContext);
203190
}
191+
204192
return result;
205193
}
206194

@@ -209,7 +197,7 @@ public PipelineNode getPipeline(String rootJobCiId) {
209197
ACLContext securityContext = startImpersonation();
210198
try {
211199
PipelineNode result;
212-
boolean hasRead = Jenkins.getInstance().hasPermission(Item.READ);
200+
boolean hasRead = Jenkins.get().hasPermission(Item.READ);
213201
if (!hasRead) {
214202
throw new PermissionException(403);
215203
}
@@ -340,6 +328,7 @@ public InputStream getTestsResult(String jobId, String buildId) {
340328
} catch (Exception fnfe) {
341329
logger.error("'" + TestListener.TEST_RESULT_FILE + "' file no longer exists, test results of '" + jobId + " #" + buildId + "' won't be pushed to Octane", fnfe);
342330
}
331+
tryRemoveTempTestResultFile(run);
343332
} else {
344333
logger.error("build '" + jobId + " #" + buildId + "' not found");
345334
}
@@ -349,6 +338,23 @@ public InputStream getTestsResult(String jobId, String buildId) {
349338
}
350339
}
351340

341+
private void tryRemoveTempTestResultFile(Run run) {
342+
try {
343+
File[] matches = run.getRootDir().listFiles((dir, name) -> name.startsWith(JUnitExtension.TEMP_TEST_RESULTS_FILE_NAME_PREFIX));
344+
if (matches != null) {
345+
for (File f : matches) {
346+
try {
347+
Files.deleteIfExists(f.toPath());
348+
} catch (Exception e) {
349+
logger.error("Failed to delete the temp test result file at '" + f.getPath() + "'", e);
350+
}
351+
}
352+
}
353+
} catch (Exception e) {
354+
logger.error("Fail to tryRemoveTempTestResultFile : " + e.getMessage());
355+
}
356+
}
357+
352358
@Override
353359
public InputStream getBuildLog(String jobId, String buildId) {
354360
ACLContext originalContext = startImpersonation();
@@ -415,12 +421,13 @@ public SSCProjectConfiguration getSSCProjectConfiguration(String jobId, String b
415421
stopImpersonation(originalContext);
416422
}
417423
}
424+
418425
@Override
419426
public Long getFodRelease(String jobId, String buildId) {
420427
ACLContext originalContext = startImpersonation();
421428
try {
422429
Run run = getRunByRefNames(jobId, buildId);
423-
if (run != null && run instanceof AbstractBuild) {
430+
if (run instanceof AbstractBuild) {
424431
return FodConfigUtil.getFODReleaseFromBuild((AbstractBuild) run);
425432
} else {
426433
logger.error("build '" + jobId + " #" + buildId + "' (of specific type AbstractBuild) not found");
@@ -431,7 +438,7 @@ public Long getFodRelease(String jobId, String buildId) {
431438
}
432439
}
433440

434-
@Override
441+
@Override
435442
public FodServerConfiguration getFodServerConfiguration() {
436443

437444
ACLContext originalContext = startImpersonation();
@@ -450,6 +457,7 @@ public FodServerConfiguration getFodServerConfiguration() {
450457
stopImpersonation(originalContext);
451458
}
452459
}
460+
453461
@Override
454462
public void runTestDiscovery(DiscoveryInfo discoveryInfo) {
455463
ACLContext securityContext = startImpersonation();
@@ -466,8 +474,7 @@ public PipelineNode createExecutor(DiscoveryInfo discoveryInfo) {
466474
ACLContext securityContext = startImpersonation();
467475
try {
468476
Job project = TestExecutionJobCreatorService.createExecutor(discoveryInfo);
469-
PipelineNode result = ModelFactory.createStructureItem(project);
470-
return result;
477+
return ModelFactory.createStructureItem(project);
471478
} finally {
472479
stopImpersonation(securityContext);
473480
}
@@ -480,8 +487,7 @@ public PipelineNode createExecutor(DiscoveryInfo discoveryInfo) {
480487
private Job createExecutorByJobName(String uftExecutorJobNameWithTestRunner) {
481488
ACLContext securityContext = startImpersonation();
482489
try {
483-
Job project = TestExecutionJobCreatorService.createExecutorByJobName(uftExecutorJobNameWithTestRunner);
484-
return project;
490+
return TestExecutionJobCreatorService.createExecutorByJobName(uftExecutorJobNameWithTestRunner);
485491
} catch (Exception e) {
486492
logger.warn("Failed to create createExecutor by name : " + e.getMessage());
487493
return null;
@@ -541,7 +547,7 @@ private void stopImpersonation(ACLContext impersonatedContext) {
541547

542548
private PipelineNode createPipelineNode(String name, Job job, boolean includeParameters) {
543549
PipelineNode tmpConfig = dtoFactory.newDTO(PipelineNode.class)
544-
.setJobCiId(JobProcessorFactory.getFlowProcessor(job).getTranslateJobName())
550+
.setJobCiId(JobProcessorFactory.getFlowProcessor(job).getTranslatedJobName())
545551
.setName(name);
546552
if (includeParameters) {
547553
tmpConfig.setParameters(ParameterProcessors.getConfigs(job));
@@ -555,20 +561,14 @@ private PipelineNode createPipelineNodeFromJobName(String name) {
555561
.setName(name);
556562
}
557563

558-
private PipelineNode createPipelineNodeFromJobNameAndFolder(String name, String folderName) {
559-
return dtoFactory.newDTO(PipelineNode.class)
560-
.setJobCiId(folderName + "/" + name)
561-
.setName(folderName + "/" + name);
562-
}
563-
564564
private InputStream getOctaneLogFile(Run run) {
565565
InputStream result = null;
566566
String octaneLogFilePath = run.getLogFile().getParent() + File.separator + "octane_log";
567567
File logFile = new File(octaneLogFilePath);
568568
if (!logFile.exists()) {
569569
try (FileOutputStream fileOutputStream = new FileOutputStream(logFile);
570-
InputStream logStream = run.getLogInputStream();
571-
PlainTextConsoleOutputStream out = new PlainTextConsoleOutputStream(fileOutputStream)) {
570+
InputStream logStream = run.getLogInputStream();
571+
PlainTextConsoleOutputStream out = new PlainTextConsoleOutputStream(fileOutputStream)) {
572572
IOUtils.copy(logStream, out);
573573
out.flush();
574574
} catch (IOException ioe) {
@@ -639,8 +639,6 @@ private List<ParameterValue> createParameters(Job project, CIParameters ciParame
639639
}
640640
break;
641641
case NUMBER:
642-
tmpValue = new StringParameterValue(ciParameter.getName(), ciParameter.getValue().toString());
643-
break;
644642
case STRING:
645643
tmpValue = new StringParameterValue(ciParameter.getName(), ciParameter.getValue().toString());
646644
break;
@@ -688,7 +686,7 @@ private Job getJobByRefId(String jobRefId) {
688686
Job result = null;
689687
if (jobRefId != null) {
690688
try {
691-
jobRefId = URLDecoder.decode(jobRefId, "UTF-8");
689+
jobRefId = URLDecoder.decode(jobRefId, StandardCharsets.UTF_8.name());
692690
TopLevelItem item = getTopLevelItem(jobRefId);
693691
if (item instanceof Job) {
694692
result = (Job) item;
@@ -713,34 +711,59 @@ private Job getJobByRefId(String jobRefId) {
713711
}
714712

715713
private Item getItemByRefId(String itemRefId) {
716-
Item result = null;
717-
if (itemRefId != null) {
718-
try {
719-
String itemRefIdUncoded = URLDecoder.decode(itemRefId, "UTF-8");
720-
if (itemRefIdUncoded.contains("/")) {
721-
String newItemRefId = itemRefIdUncoded.substring(0, itemRefIdUncoded.indexOf("/"));
722-
Item item = getTopLevelItem(newItemRefId);
723-
if (item != null && item.getClass().getName().equals(JobProcessorFactory.GITHUB_ORGANIZATION_FOLDER)) {
724-
Collection<? extends Item> allItems = ((AbstractFolder) item).getItems();
725-
for (Item multibranchItem : allItems) {
726-
if (itemRefIdUncoded.endsWith(multibranchItem.getName())) {
727-
result = multibranchItem;
728-
break;
729-
}
714+
if (itemRefId == null) {
715+
return null;
716+
}
717+
718+
try {
719+
String itemRefIdDecoded = URLDecoder.decode(itemRefId, StandardCharsets.UTF_8.name());
720+
if (!itemRefIdDecoded.contains("/")) {
721+
return null;
722+
}
723+
724+
String newItemRefId = itemRefIdDecoded.substring(0, itemRefIdDecoded.indexOf('/'));
725+
Item item = getTopLevelItem(newItemRefId);
726+
if (item == null) {
727+
return null;
728+
}
729+
730+
Item result = null;
731+
if (item.getClass().getName().equals(JobProcessorFactory.GITHUB_ORGANIZATION_FOLDER)) {
732+
Collection<? extends Item> allItems = ((AbstractFolder) item).getItems();
733+
for (Item multiBranchItem : allItems) {
734+
if (itemRefIdDecoded.endsWith(multiBranchItem.getName())) {
735+
result = multiBranchItem;
736+
break;
737+
}
738+
}
739+
} else {
740+
Collection<? extends Job> allJobs = item.getAllJobs();
741+
for (Job job : allJobs) {
742+
if (JobProcessorFactory.WORKFLOW_MULTI_BRANCH_JOB_NAME.equals(job.getParent().getClass().getName()) &&
743+
itemRefId.endsWith(job.getParent().getFullName())
744+
) {
745+
result = (Item) job.getParent();
746+
} else {
747+
if (itemRefId.endsWith(job.getName())) {
748+
result = job;
730749
}
731750
}
751+
if (result != null) {
752+
break;
753+
}
732754
}
733-
} catch (UnsupportedEncodingException uee) {
734-
logger.error("failed to decode job ref ID '" + itemRefId + "'", uee);
735755
}
756+
return result;
757+
} catch (UnsupportedEncodingException uee) {
758+
logger.error("failed to decode job ref ID '" + itemRefId + "'", uee);
759+
return null;
736760
}
737-
return result;
738761
}
739762

740763
private TopLevelItem getTopLevelItem(String jobRefId) {
741764
TopLevelItem item;
742765
try {
743-
item = Jenkins.getInstance().getItem(jobRefId);
766+
item = Jenkins.get().getItem(jobRefId);
744767
} catch (AccessDeniedException e) {
745768
String user = ConfigurationService.getSettings(getInstanceId()).getImpersonatedUser();
746769
if (user != null && !user.isEmpty()) {
@@ -754,7 +777,7 @@ private TopLevelItem getTopLevelItem(String jobRefId) {
754777

755778
public static CIServerInfo getJenkinsServerInfo() {
756779
CIServerInfo result = dtoFactory.newDTO(CIServerInfo.class);
757-
String serverUrl = Jenkins.getInstance().getRootUrl();
780+
String serverUrl = Jenkins.get().getRootUrl();
758781
if (serverUrl != null && serverUrl.endsWith("/")) {
759782
serverUrl = serverUrl.substring(0, serverUrl.length() - 1);
760783
}

src/main/java/com/microfocus/application/automation/tools/octane/configuration/JobConfigurationProxy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public JSONObject updatePipelineOnSever(JSONObject pipelineObject) {
159159
fields.put(jsonObject.getString("name"), assignedValues);
160160
}
161161

162-
final String jobCiId = JobProcessorFactory.getFlowProcessor(job).getTranslateJobName();
162+
final String jobCiId = JobProcessorFactory.getFlowProcessor(job).getTranslatedJobName();
163163

164164
PipelineContext pipelineContext = dtoFactory.newDTO(PipelineContext.class)
165165
.setContextEntityId(pipelineId)
@@ -250,7 +250,7 @@ public JSONObject loadJobConfigurationFromServer(String instanceId) {
250250
}
251251
ret.put("isUftJob", isUftJob);
252252

253-
final String jobCiId = JobProcessorFactory.getFlowProcessor(job).getTranslateJobName();
253+
final String jobCiId = JobProcessorFactory.getFlowProcessor(job).getTranslatedJobName();
254254
PipelineContextList pipelineContextList = octaneClient.getPipelineContextService().getJobConfiguration(octaneClient.getInstanceId(), jobCiId);
255255

256256
if (!pipelineContextList.getData().isEmpty()) {

0 commit comments

Comments
 (0)