gCubeDepsWalker/Jenkinsfile

155 lines
5.8 KiB
Plaintext
Raw Normal View History

def projects2artifacts = [:]
def artifacts2projects = [:]
def modules2deps = [:]
def alreadyInTheTree = []
def inputProject = params.jenkins_project.trim()
def report = [:]
report['project'] = inputProject
pipeline {
agent {
label 'CD'
}
parameters {
string(name: 'jenkins_project',
2020-03-12 16:13:24 +01:00
defaultValue: '',
description: 'The name of the Jenkins project to analyze.')
}
stages {
2020-03-11 17:11:38 +01:00
stage('walking projects') {
steps {
2020-03-12 16:13:24 +01:00
script {
Jenkins.get().getAllItems(TopLevelItem.class).each { p ->
2020-03-12 16:13:24 +01:00
projects2artifacts[p.name] = []
p.getAllJobs().each { j -> projects2artifacts[p.name] << j.name; artifacts2projects[j.name] = p.name }
}
println "FOUND ${projects2artifacts.size()} projects"
2020-03-12 15:33:09 +01:00
//projects2artifacts.each { k,v -> println ("PROJECT ${k} BUILDS ${v}") }
2020-03-12 16:13:24 +01:00
}
}
}
2020-03-11 17:11:38 +01:00
stage('walking maven modules') {
steps {
script {
// get all the maven modules and their dependencies
Jenkins.get().getAllItems(hudson.maven.MavenModule.class).each { m ->
2020-03-12 16:13:24 +01:00
modules2deps[m.name] = []
m.getDependencies().each { d -> modules2deps[m.name] << "${d.groupId}:${d.artifactId}" }
}
println "FOUND ${modules2deps.size()} modules"
//modules2deps.each { k,v -> println ("MODULE ${k} DEPENDS on ${v}") }
}
}
}
2020-03-11 17:11:38 +01:00
stage('analyze downstream projects') {
2020-03-12 16:13:24 +01:00
steps {
script {
// println "PROJECT ${inputProject} BUILDS ${projects2artifacts[inputProject]} artifacts"
// first, let's find out what components depend on the project's artifacts (i.e. downstream dependencies)
def downstreamdeps = [:]
report['downstream_modules'] = [:]
report['downstream_projects'] = []
for ( level in 1..50 ) report['downstream_modules']["L${level}"] = [:] // can't initialize with withDefault closure in jenkins
2020-03-12 16:26:18 +01:00
projects2artifacts[inputProject].each { a ->
2020-03-12 16:27:45 +01:00
if (a.split(':').length > 1) { //skip the parent (only groupId)
report = analyzeDependency(modules2deps, alreadyInTheTree, artifacts2projects, report, a, 1) }
2020-03-12 16:26:18 +01:00
}
2020-03-11 16:22:06 +01:00
}
}
2020-03-12 16:13:24 +01:00
}
2020-03-11 17:08:55 +01:00
2020-03-11 17:11:38 +01:00
stage('print report') {
steps {
script {
printReport(report)
}
2020-03-11 17:08:55 +01:00
}
}
2020-03-12 16:13:24 +01:00
}
2020-03-11 17:10:18 +01:00
}
2020-03-11 17:08:55 +01:00
// look for modules that use this artifact
def findDownstreamDependencies(modules2deps, artifact) {
def downdeps = []
//println "Looking for users of ${artifact}"
2020-03-12 16:13:24 +01:00
modules2deps.each { k, v -> if (v.contains("${artifact}")) downdeps << k }
return downdeps
}
2020-03-11 17:08:55 +01:00
//build the report of the given dependency, go recursive on its dependencies
def analyzeDependency(modules2deps, alreadyInTheTree, artifacts2projects, report, artifact, depth) {
2020-03-12 16:17:33 +01:00
def level = "L${depth}"
def downdeps = findDownstreamDependencies(modules2deps, artifact)
2020-03-12 18:57:17 +01:00
def skipTree = alreadyInTheTree.contains(artifact)
if (!skipTree) {
report['downstream_modules'][level][artifact] = ['dependencies': [], 'projects': []]
// get all downstream dependencies
report['downstream_modules'][level][artifact]['dependencies'].addAll(downdeps)
//println "${artifact} is used by ${report['downstream_modules'][level][artifact]['dependencies']}"
2020-03-11 16:22:06 +01:00
// add the project that builds the artifact
report['downstream_modules'][level][artifact]['projects'] << artifacts2projects[artifact]
report['downstream_projects'] << artifacts2projects[artifact]
alreadyInTheTree << artifact
}
// then we look for the projects that build the downstream dependencies and finally we go recursive
if (downdeps.size() > 0) {
2020-03-12 16:13:24 +01:00
def nextDepth = ++depth
downdeps.each { d ->
if (!skipTree) {
report['downstream_modules'][level][artifact]['projects'] << artifacts2projects[d]
report['downstream_projects'] << artifacts2projects[d]
}
// go recursive
report = analyzeDependency(modules2deps, alreadyInTheTree, artifacts2projects, report, d, nextDepth)
}
2020-03-11 16:22:06 +01:00
}
report
}
2020-03-11 17:08:55 +01:00
// print the final report
def printReport(report) {
2020-03-12 16:17:33 +01:00
def text = ''
def indent = '\t'
text += "Dependency Report for ${report['project']} (jenkins project)"
text += "\n\n"
2020-03-12 15:29:12 +01:00
text += "|--Project Maven Modules\n"
2020-03-12 16:13:24 +01:00
report['downstream_modules'].each { depth, artifacts ->
artifacts.each { name, data ->
text += "${indent}|--Module: ${name}\n"
text += "${indent * 2}|--Dependency Level: ${depth}\n"
text += "${indent * 2}|--Used by (Maven Modules)\n"
data['dependencies'].each { d ->
text += "${indent * 3}|--${d}"
text += "\n"
2020-03-11 16:22:06 +01:00
}
2020-03-12 16:13:24 +01:00
text += "${indent * 2}|--Referred by (Jenkins Projects)\n"
data['projects'].each { p ->
text += "${indent * 3}|--${p}"
text += "\n"
}
}
}
2020-03-11 16:22:06 +01:00
text += "\n\n"
2020-03-11 19:16:39 +01:00
text += "|--All Downstream Projects\n"
report['downstream_projects'].unique().sort()
report['downstream_projects'].each { p ->
2020-03-12 16:13:24 +01:00
text += "${indent}|--${p}"
text += "\n"
}
println text
}
2020-03-11 17:08:55 +01:00
// debug job
def printJob(job) {
2020-03-12 16:13:24 +01:00
println("fullname ${job.fullName}")
println("name ${job.name}")
println("display name ${job.displayName}")
job.getAllJobs().each { j -> println("dep: ${j.name}") }
2020-03-11 16:22:06 +01:00
}