-
Notifications
You must be signed in to change notification settings - Fork 54
Adding parent-child job support to the pipeline job. #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
41efd1f
9df77f8
6abe177
cc13d94
691cdaa
cd1fb7c
c1f4865
a8fcb9f
b1d7a80
5056c1a
bddc072
5df30d4
25cc14b
bea898d
e2cad42
631cf69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,25 +9,28 @@ | |
| import hudson.Extension; | ||
| import hudson.init.InitMilestone; | ||
| import hudson.init.Initializer; | ||
| import hudson.model.Job; | ||
| import hudson.model.Result; | ||
| import hudson.model.Run; | ||
| import java.sql.Timestamp; | ||
| import java.time.Instant; | ||
| import jenkins.model.Jenkins; | ||
| import okhttp3.*; | ||
| import org.jenkinsci.plugins.workflow.job.WorkflowJob; | ||
| import org.jenkinsci.plugins.workflow.job.WorkflowRun; | ||
| import java.time.temporal.ChronoUnit; | ||
| import java.io.IOException; | ||
| import java.net.HttpURLConnection; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.logging.Logger; | ||
|
|
||
| @Extension | ||
| public class QualityDashboardInit { | ||
|
|
||
| private static final Logger LOGGER = Logger.getLogger(QualityDashboardInit.class.getName()); | ||
| static QualityDashboardAPIUtil apiUtil = new QualityDashboardAPIUtil(); | ||
|
|
||
| @Initializer(after = InitMilestone.PLUGINS_PREPARED) | ||
| @Initializer(after = InitMilestone.JOB_LOADED) | ||
| public static void postInstall() { | ||
| try { | ||
| initQDSetupIfRequired(); | ||
|
|
@@ -51,9 +54,11 @@ private static String exceptionToString(Throwable throwable) { | |
| private static void initQDSetupIfRequired() throws JsonProcessingException { | ||
| BrowserStackCredentials browserStackCredentials = QualityDashboardUtil.getBrowserStackCreds(); | ||
| try { | ||
| if(browserStackCredentials!=null) { | ||
| if(browserStackCredentials != null) { | ||
| apiUtil.logToQD(browserStackCredentials,"Starting plugin data export to QD"); | ||
| checkQDIntegrationAndDumpMetaData(browserStackCredentials); | ||
| } else { | ||
| LOGGER.info("BrowserStack credentials not found. Skipping Quality Dashboard initialization."); | ||
| } | ||
| } catch (Exception e) { | ||
| try { | ||
|
|
@@ -114,32 +119,38 @@ private static List<String> getAllPipelines(BrowserStackCredentials browserStack | |
| totalPipelines = jenkins.getAllItems().size(); | ||
| jenkins.getAllItems().forEach(job -> { | ||
| try { | ||
| String jobType = job.getClass().getSimpleName(); | ||
| boolean isWorkflowJob = job instanceof WorkflowJob; | ||
|
|
||
| // Logging job details | ||
| apiUtil.logToQD( | ||
| browserStackCredentials, | ||
| String.format( | ||
| "Job name: %s, instance type: %s, and is_workflow_job: %s", | ||
| job.getName(), | ||
| job.getClass().getSimpleName(), | ||
| (job instanceof WorkflowJob) ? "yes" : "no" | ||
| jobType, | ||
| isWorkflowJob ? "yes" : "no" | ||
| ) | ||
| ); | ||
| if ( job instanceof Job) { | ||
| String pipelineName = job.getFullName(); | ||
| allPipelines.add(pipelineName); | ||
| } | ||
| else{ | ||
| apiUtil.logToQD(browserStackCredentials, "Skipping job: " + job.getName() + " as it is not a Job instance"); | ||
| } | ||
|
|
||
| } catch (JsonProcessingException e) { | ||
| // Handling the exception and logging an error | ||
| System.err.println("Error processing JSON for job: " + job.getName()); | ||
| LOGGER.info("Error processing JSON for job: " + job.getName() + " - " + e.getMessage()); | ||
|
||
| e.printStackTrace(); | ||
| } | ||
|
|
||
| if (job instanceof WorkflowJob) { | ||
| String pipelineName = job.getFullName(); // Getting pipeline name | ||
| allPipelines.add(pipelineName); | ||
| } | ||
| }); | ||
| } else { | ||
| try { | ||
| apiUtil.logToQD(browserStackCredentials, "Issue getting Jenkins Instance"); | ||
| } catch (JsonProcessingException e) { | ||
| System.err.println("Error logging issue with Jenkins instance."); | ||
| LOGGER.info("Error logging issue with Jenkins instance."); | ||
|
||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
|
@@ -149,7 +160,7 @@ private static List<String> getAllPipelines(BrowserStackCredentials browserStack | |
| apiUtil.logToQD(browserStackCredentials,"Total Pipelines detected : " + allPipelines.size()); | ||
| } catch (JsonProcessingException e) { | ||
| // Handling the exception and logging an error | ||
| System.err.println("Error processing JSON for total pipelines: "); | ||
| LOGGER.info("Error processing JSON for total pipelines: " + e.getMessage()); | ||
| e.printStackTrace(); | ||
| } | ||
| // Returning the list of filtered pipelines | ||
|
|
@@ -188,10 +199,12 @@ private static List<PipelineDetails> getAllBuilds(BrowserStackCredentials browse | |
| Jenkins jenkins = Jenkins.getInstanceOrNull(); | ||
| Instant thresholdInstant = Instant.now().minus(getHistoryForDays(browserStackCredentials), ChronoUnit.DAYS); | ||
| if (jenkins != null) { | ||
| jenkins.getAllItems().forEach(job -> { | ||
| if (job instanceof WorkflowJob) { | ||
| jenkins.getAllItems().forEach(item -> { | ||
| // Support both WorkflowJob and Matrix projects (and potentially other job types) | ||
| if (item instanceof Job) { | ||
| Job<?, ?> job = (Job<?, ?>) item; | ||
| String pipelineName = job.getFullName(); | ||
| List<WorkflowRun> allBuilds = ((WorkflowJob) job).getBuilds(); | ||
| List<? extends Run<?, ?>> allBuilds = job.getBuilds(); | ||
| if(!allBuilds.isEmpty()) { | ||
| allBuilds.stream().filter(build -> Instant.ofEpochMilli(build.getTimeInMillis()).isAfter(thresholdInstant)).forEach( | ||
| build -> { | ||
|
|
@@ -201,7 +214,19 @@ private static List<PipelineDetails> getAllBuilds(BrowserStackCredentials browse | |
| long endTimeInMillis = build.getTimeInMillis(); | ||
| Timestamp endTime = new Timestamp(endTimeInMillis); | ||
| String result = overallResult != null ? overallResult.toString() : null; | ||
| PipelineDetails pipelineDetail = new PipelineDetails(pipelineName, buildNumber, duration, result, endTime); | ||
|
|
||
| // Get root upstream project information for QEI with build number (returns in format "project#build") | ||
| String rootUpstreamProject = ""; | ||
| String immediateParentProject = ""; | ||
| try { | ||
| rootUpstreamProject = UpstreamPipelineResolver.resolveRootUpstreamProject(build, browserStackCredentials); | ||
| immediateParentProject = UpstreamPipelineResolver.resolveImmediateUpstreamProjectForQEI(build, browserStackCredentials); | ||
| } catch (Exception e) { | ||
| LOGGER.info("Error resolving upstream project for " + pipelineName + " build number " + buildNumber + ": " + e.getMessage()); | ||
| e.printStackTrace(); | ||
| } | ||
| PipelineDetails pipelineDetail = new PipelineDetails(pipelineName, buildNumber, duration, result, | ||
| endTime, rootUpstreamProject, immediateParentProject); | ||
| allBuildResults.add(pipelineDetail); | ||
| } | ||
| ); | ||
|
|
@@ -249,9 +274,8 @@ private static int getHistoryForDays(BrowserStackCredentials browserStackCredent | |
| } | ||
| } catch(IOException e) { | ||
| e.printStackTrace(); | ||
| } finally { | ||
| return no_of_days; | ||
| } | ||
| return no_of_days; | ||
| } | ||
|
|
||
| private static int getProjectPageSize(BrowserStackCredentials browserStackCredentials) { | ||
|
|
@@ -268,9 +292,8 @@ private static int getProjectPageSize(BrowserStackCredentials browserStackCreden | |
| } | ||
| } catch(IOException e) { | ||
| e.printStackTrace(); | ||
| } finally { | ||
| return projectPageSize; | ||
| } | ||
| return projectPageSize; | ||
| } | ||
|
|
||
| private static int getResultPageSize(BrowserStackCredentials browserStackCredentials) { | ||
|
|
@@ -287,9 +310,8 @@ private static int getResultPageSize(BrowserStackCredentials browserStackCredent | |
| } | ||
| } catch(IOException e) { | ||
| e.printStackTrace(); | ||
| } finally { | ||
| return resultPageSize; | ||
| } | ||
| return resultPageSize; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -307,13 +329,22 @@ class PipelineDetails { | |
|
|
||
| @JsonProperty("endTime") | ||
| private Timestamp endTime; | ||
|
|
||
| public PipelineDetails(String pipelineName, Integer buildNumber, Long buildDuration, String buildStatus, Timestamp endTime) { | ||
|
|
||
| @JsonProperty("rootProject") | ||
| private String rootProject; | ||
|
|
||
| @JsonProperty("immediateParentProject") | ||
| private String immediateParentProject; | ||
|
|
||
| public PipelineDetails(String pipelineName, Integer buildNumber, Long buildDuration, String buildStatus, | ||
| Timestamp endTime, String rootProject, String immediateParentProject) { | ||
| this.pipelineName = pipelineName; | ||
| this.buildNumber = buildNumber; | ||
| this.buildDuration = buildDuration; | ||
| this.buildStatus = buildStatus; | ||
| this.endTime = endTime; | ||
| this.rootProject = rootProject; | ||
| this.immediateParentProject = immediateParentProject; | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok for now but ideally it should be configurable either on client side or server side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted. As discussed, we will handle this in the future.