deploy-templates/JobProvisionerDefault.groovy (316 lines of code) (raw):

import groovy.json.* import jenkins.model.Jenkins Jenkins jenkins = Jenkins.instance def stages = [:] def jiraIntegrationEnabled = Boolean.parseBoolean("${JIRA_INTEGRATION_ENABLED}" as String) def commitValidateStage = jiraIntegrationEnabled ? ',{"name": "commit-validate"}' : '' def createJFVStage = jiraIntegrationEnabled ? ',{"name": "create-jira-fix-version"}' : '' def buildTool = "${BUILD_TOOL}" def goBuildStage = buildTool.toString() == "go" ? ',{"name": "build"}' : ',{"name": "compile"}' stages['Code-review-application'] = '[{"name": "gerrit-checkout"}' + "${commitValidateStage}" + goBuildStage + ',{"name": "tests"},{"name": "sonar"}]' stages['Code-review-library'] = '[{"name": "gerrit-checkout"}' + "${commitValidateStage}" + ',{"name": "compile"},{"name": "tests"},{"name": "sonar"}]' stages['Code-review-autotests'] = '[{"name": "gerrit-checkout"}' + "${commitValidateStage}" + ',{"name": "tests"},{"name": "sonar"}]' stages['Code-review-default'] = '[{"name": "gerrit-checkout"}' + "${commitValidateStage}" + ']' stages['Build-library-maven'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "compile"},' + '{"name": "tests"},{"name": "sonar"},{"name": "build"},{"name": "push"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-library-npm'] = stages['Build-library-maven'] stages['Build-library-gradle'] = stages['Build-library-maven'] stages['Build-library-dotnet'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "compile"},' + '{"name": "tests"},{"name": "sonar"},{"name": "push"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-application-maven'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "compile"},' + '{"name": "tests"},{"name": "sonar"},{"name": "build"},{"name": "build-image-from-dockerfile"},' + '{"name": "push"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-application-npm'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "compile"},' + '{"name": "tests"},{"name": "sonar"},{"name": "build"},{"name": "build-image-from-dockerfile"},' + '{"name": "push"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-application-gradle'] = stages['Build-application-maven'] stages['Build-application-dotnet'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "compile"},' + '{"name": "tests"},{"name": "sonar"},{"name": "build-image-from-dockerfile"},' + '{"name": "push"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-application-go'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "tests"},{"name": "sonar"},' + '{"name": "build"},{"name": "build-image-from-dockerfile"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-application-python'] = '[{"name": "checkout"},{"name": "get-version"},{"name": "compile"},{"name": "tests"},{"name": "sonar"},' + '{"name": "build-image-from-dockerfile"},{"name": "push"}' + "${createJFVStage}" + ',{"name": "git-tag"}]' stages['Build-application-gitops'] = '[{"name": "checkout"},{"name": "deploy-via-helmfile"}]' stages['Build-library-gitops'] = '[{"name": "checkout"},{"name": "deploy-via-helmfile"}]' stages['Build-autotests-gitops'] = '[{"name": "checkout"},{"name": "deploy-via-helmfile"}]' stages['Build-clustermgmt-gitops'] = '[{"name": "checkout"},{"name": "deploy-via-helmfile"}]' stages['Build-registry-gitops'] = '[{"name": "checkout"},{"name": "validating-values"},{"name": "registry-integration"},{"name": "deploy-via-helmfile"}]' stages['Build-registry-group-gitops'] = '[{"name": "checkout"},{"name": "deploy-registry-group"}]' stages['Create-release'] = '[{"name": "checkout"},{"name": "create-branch"},{"name": "trigger-job"}]' stages['Delete-release'] = '[{"name": "checkout"},{"name": "delete-registry"}]' stages['Delete-registry-group'] = '[{"name": "checkout"},{"name": "delete-registry-group"}]' stages['Create-registry-backup'] = '[{"name": "checkout"},{"name": "create-backup"}]' stages['Restore-registry'] = '[{"name": "checkout"},{"name": "cleanup-registry-before-restore"},{"name": "restore-registry-bucket"}]' def buildToolsOutOfTheBox = ["maven","npm","gradle","dotnet","none","go","python"] def defaultBuild = '[{"name": "checkout"}]' def codebaseName = "${NAME}" def gitServerCrName = "${GIT_SERVER_CR_NAME}" def gitServerCrVersion = "${GIT_SERVER_CR_VERSION}" def gitCredentialsId = "${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}" def repositoryPath = "${REPOSITORY_PATH}" def edpLibraryStagesVersion = "${EDP_LIBRARY_STAGES_VERSION}" def edpLibraryPipelinesVersion = "${EDP_LIBRARY_PIPELINES_VERSION}" def codebaseFolder = jenkins.getItem(codebaseName) if (codebaseFolder == null) { folder(codebaseName) } createListView(codebaseName, "Releases") createReleasePipeline("Create-release-${codebaseName}", codebaseName, stages["Create-release"], repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, edpLibraryStagesVersion, edpLibraryPipelinesVersion) if (buildTool.toString().equalsIgnoreCase('none')) { return true } if (BRANCH) { def branch = "${BRANCH}" def formattedBranch = "${branch.toUpperCase().replaceAll(/\//, "-")}" createListView(codebaseName, formattedBranch) def type = "${TYPE}" def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString()) def crKey = supBuildTool ? "Code-review-${type}" : "Code-review-default" createCiPipeline("Code-review-${codebaseName}", codebaseName, stages[crKey], "CodeReview", repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) def buildKey = "Build-${type}-${buildTool.toLowerCase()}".toString() if ( type.equalsIgnoreCase('registry') || type.equalsIgnoreCase('clustermgmt') || type.equalsIgnoreCase('registry-group')) { def jobExists = false if("${formattedBranch}-Build-${codebaseName}".toString() in Jenkins.instance.getAllItems().collect{it.name}) jobExists = true createCiPipeline("Build-${codebaseName}", codebaseName, stages.get(buildKey, defaultBuild), "Build", repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) if(!type.equalsIgnoreCase('registry-group')) createReleaseDeletePipeline("Delete-release-${codebaseName}", codebaseName, stages["Delete-release"], repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) // only needed for registryGroup if (type.equalsIgnoreCase('registry-group')) { createReleaseDeletePipeline("Delete-release-${codebaseName}", codebaseName, stages["Delete-registry-group"], repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) } // only needed for registry Boolean isRegistryBackupEnabled = false String schedule String scriptPath = "/tmp/parse_yaml.sh" String valuesFolderPath = "/tmp/${codebaseName}/deploy-templates" String parsedValuesPath = "${valuesFolderPath}/parsed_values.yaml" //delete the folder of the previously downloaded registry def rmProc = new ProcessBuilder( 'sh', '-c', "rm -rf /tmp/${codebaseName}").redirectErrorStream(true).start() //wait for the command execution rmProc.waitForOrKill(1000) //clone registry repository new ProcessBuilder( 'sh', '-c', "git clone ${repositoryPath} /tmp/${codebaseName}").redirectErrorStream(true).start().text //create the file for script def createFileProc = new ProcessBuilder( 'sh', '-c', "touch ${scriptPath}").redirectErrorStream(true).start() //wait for the command execution createFileProc.waitForOrKill(1000) //put the script into the created file def putScriptProc = new ProcessBuilder( 'sh', '-c', "echo \"#!/bin/sh\n" + "function parse_yaml {\n" + "\tsed 's/ / /g' ${valuesFolderPath}/values.yaml > ${valuesFolderPath}/updated_values.yaml\n" + "\tlocal prefix=\\\$2\n" + "\tlocal s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=\\\$(echo @|tr @ '\\034')\n" + "\tsed -ne \\\"s|,\\\$s\\]\\\$s\\\\\\\$|]|\\\" \\\\\n" + "\t\t-e \\\":1;s|^\\(\\\$s\\)\\(\\\$w\\)\\\$s:\\\$s\\[\\\$s\\(.*\\)\\\$s,\\\$s\\(.*\\)\\\$s\\]|\\1\\2: [\\3]\\n\\1 - \\4|;t1\\\" \\\\\n" + "\t\t-e \\\"s|^\\(\\\$s\\)\\(\\\$w\\)\\\$s:\\\$s\\[\\\$s\\(.*\\)\\\$s\\]|\\1\\2:\\n\\1 - \\3|;p\\\" \\\$1 | \\\\\n" + "\tsed -ne \\\"s|,\\\$s}\\\$s\\\\\\\$|}|\\\" \\\\\n" + "\t\t-e \\\":1;s|^\\(\\\$s\\)-\\\$s{\\\$s\\(.*\\)\\\$s,\\\$s\\(\\\$w\\)\\\$s:\\\$s\\(.*\\)\\\$s}|\\1- {\\2}\\n\\1 \\3: \\4|;t1\\\" \\\\\n" + "\t\t-e \\\"s|^\\(\\\$s\\)-\\\$s{\\\$s\\(.*\\)\\\$s}|\\1-\\n\\1 \\2|;p\\\" | \\\\\n" + "\tsed -ne \\\"s|^\\(\\\$s\\):|\\1|\\\" \\\\\n" + "\t\t-e \\\"s|^\\(\\\$s\\)-\\\$s[\\\\\\\"']\\(.*\\)[\\\\\\\"']\\\$s\\\\\\\$|\\1\\\$fs\\\$fs\\2|p\\\" \\\\\n" + "\t\t-e \\\"s|^\\(\\\$s\\)-\\\$s\\(.*\\)\\\$s\\\\\\\$|\\1\\\$fs\\\$fs\\2|p\\\" \\\\\n" + "\t\t-e \\\"s|^\\(\\\$s\\)\\(\\\$w\\)\\\$s:\\\$s[\\\\\\\"']\\(.*\\)[\\\\\\\"']\\\$s\\\\\\\$|\\1\\\$fs\\2\\\$fs\\3|p\\\" \\\\\n" + "\t\t-e \\\"s|^\\(\\\$s\\)\\(\\\$w\\)\\\$s:\\\$s\\(.*\\)\\\$s\\\\\\\$|\\1\\\$fs\\2\\\$fs\\3|p\\\" | \\\\\n" + "\tawk -F\\\$fs '{\n" + "\t\tindent = length(\\\$1)/2;\n" + "\t\tvname[indent] = \\\$2;\n" + "\t\tfor (i in vname) {if (i > indent) {delete vname[i]; idx[i]=0}}\n" + "\t\tif(length(\\\$2)== 0) {vname[indent]= ++idx[indent]};\n" + "\t\tif (length(\\\$3) > 0) {\n" + "\t\t\tvn=\\\"\\\"; for (i=0; i<indent; i++) {vn=(vn)(vname[i])(\\\"_\\\")}\n" + "\t\t\tprintf(\\\"%s%s%s=\\\\\\\"%s\\\\\\\"\\\\n\\\", \\\"'\\\$prefix'\\\",vn, vname[indent], \\\$3);\n" + "\t\t}\n" + "\t}'\n" + "}\n" + "parse_yaml ${valuesFolderPath}/updated_values.yaml > ${parsedValuesPath}\" > ${scriptPath}").redirectErrorStream(true).start() putScriptProc.waitForOrKill(1000) //make a script executable def makeExecProc = new ProcessBuilder( 'sh', '-c', "chmod +x ${scriptPath}").redirectErrorStream(true).start() makeExecProc.waitForOrKill(1000) //run a script for yaml parsing def runScriptProc = new ProcessBuilder( 'sh', '-c', ".${scriptPath}").redirectErrorStream(true).start() runScriptProc.waitForOrKill(1000) def valuesConfig = new ConfigSlurper().parse(new File("${parsedValuesPath}").toURL()) valuesConfig.each { key, value -> key == 'global_registryBackup_enabled' ? isRegistryBackupEnabled = value.toBoolean() : false (key == 'global_registryBackup_schedule' && isRegistryBackupEnabled) ? schedule = value : "" } //rm temp files def rmBackupValuesFilesProc = new ProcessBuilder( 'sh', '-c', "rm -rf ${valuesFolderPath}/updated_values.yaml ${parsedValuesPath} ${scriptPath}").redirectErrorStream(true).start() rmBackupValuesFilesProc.waitForOrKill(1000) if (type.equalsIgnoreCase('registry')) { createReleaseBackupPipeline("Create-registry-backup-${codebaseName}", codebaseName, stages["Create-registry-backup"], repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion, isRegistryBackupEnabled, schedule) createReleaseRestorePipeline("Restore-registry-${codebaseName}", codebaseName, stages["Restore-registry"], repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) } if(!jobExists) queue("${codebaseName}/${formattedBranch}-Build-${codebaseName}") } } def createCiPipeline(pipelineName, codebaseName, codebaseStages, makeAction, repository, credId, watchBranch = "master", gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) { pipelineJob("${codebaseName}/${watchBranch.toUpperCase().replaceAll(/\//, "-")}-${pipelineName}") { if(watchBranch == "master" && pipelineName.startsWith("Build")) concurrentBuild(false) logRotator { numToKeep(10) daysToKeep(7) } triggers { gerrit { events { if (pipelineName.contains("Build")) changeMerged() else patchsetCreated() } project("plain:${codebaseName}", ["plain:${watchBranch}"]) } } definition { cps { script("@Library([\"edp-library-stages@${edpLibraryStagesVersion}\", \"edp-library-pipelines@${edpLibraryPipelinesVersion}\"]) _ \n${makeAction}()") sandbox(true) parameters { stringParam("GIT_SERVER_CR_NAME", "${gitServerCrName}", "Name of Git Server CR to generate link to Git server") stringParam("GIT_SERVER_CR_VERSION", "${gitServerCrVersion}", "Version of GitServer CR Resource") stringParam("STAGES", "${codebaseStages}", "Consequence of stages in JSON format to be run during execution") stringParam("GERRIT_PROJECT_NAME", "${codebaseName}", "Gerrit project name(Codebase name) to be build") if (pipelineName.contains("Build")) stringParam("BRANCH", "${watchBranch}", "Branch to build artifact from") } } } } } def createReleasePipeline(pipelineName, codebaseName, codebaseStages, repository, credId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, edpLibraryStagesVersion, edpLibraryPipelinesVersion) { pipelineJob("${codebaseName}/${pipelineName}") { logRotator { numToKeep(14) daysToKeep(30) } definition { cps { script("@Library([\"edp-library-stages@${edpLibraryStagesVersion}\", \"edp-library-pipelines@${edpLibraryPipelinesVersion}\"]) _ \nCreateRelease()") sandbox(true) parameters { stringParam("STAGES", "${codebaseStages}", "") if (pipelineName.contains("Create-release") || pipelineName.contains("Delete-release")) { stringParam("JIRA_INTEGRATION_ENABLED", "${jiraIntegrationEnabled}", "Is Jira integration enabled") stringParam("GERRIT_PROJECT", "${codebaseName}", "") stringParam("RELEASE_NAME", "", "Name of the release(branch to be created)") stringParam("COMMIT_ID", "", "Commit ID that will be used to create branch from for new release. If empty, HEAD of master will be used") stringParam("GIT_SERVER_CR_NAME", "${gitServerCrName}", "Name of Git Server CR to generate link to Git server") stringParam("GIT_SERVER_CR_VERSION", "${gitServerCrVersion}", "Version of GitServer CR Resource") stringParam("REPOSITORY_PATH", "${repository}", "Full repository path") } if (pipelineName.contains("Delete-release")) stringParam("BRANCH", "${watchBranch}", "Branch to build artifact from") } } } } } def createListView(codebaseName, branchName) { listView("${codebaseName}/${branchName}") { if (branchName.toLowerCase() == "releases") { jobFilters { regex { matchType(MatchType.INCLUDE_MATCHED) matchValue(RegexMatchValue.NAME) regex("^Create-release.*") } } } else { jobFilters { regex { matchType(MatchType.INCLUDE_MATCHED) matchValue(RegexMatchValue.NAME) regex("^${branchName}-(Code-review|Build).*") } } } columns { status() weather() name() lastSuccess() lastFailure() lastDuration() buildButton() } } } def createReleaseDeletePipeline(pipelineName, codebaseName, codebaseStages, repository, credId, watchBranch = "master", gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) { pipelineJob("${codebaseName}/${pipelineName}") { logRotator { numToKeep(10) daysToKeep(7) } definition { cps { script("@Library([\"edp-library-stages@${edpLibraryStagesVersion}\", \"edp-library-pipelines@${edpLibraryPipelinesVersion}\"]) _ \nBuild()") sandbox(true) parameters { stringParam("GIT_SERVER_CR_NAME", "${gitServerCrName}", "Name of Git Server CR to generate link to Git server") stringParam("GIT_SERVER_CR_VERSION", "${gitServerCrVersion}", "Version of GitServer CR Resource") stringParam("STAGES", "${codebaseStages}", "Consequence of stages in JSON format to be run during execution") stringParam("GERRIT_PROJECT_NAME", "${codebaseName}", "Gerrit project name(Codebase name) to be build") stringParam("BRANCH", "${watchBranch}", "Branch to build artifact from") } } } } } def createReleaseBackupPipeline(pipelineName, codebaseName, codebaseStages, repository, credId, watchBranch = "master", gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion, isRegistryBackupEnabled, schedule) { pipelineJob("${codebaseName}/${pipelineName}") { logRotator { numToKeep(10) daysToKeep(7) } if (isRegistryBackupEnabled.toBoolean()) { triggers { cron("TZ=Europe/Kiev\n" + schedule) } } definition { cps { script("@Library([\"edp-library-stages@${edpLibraryStagesVersion}\", \"edp-library-pipelines@${edpLibraryPipelinesVersion}\"]) _ \nBuild()") sandbox(true) parameters { stringParam("STAGES", "${codebaseStages}", "Consequence of stages in JSON format to be run during execution") stringParam("GIT_SERVER_CR_NAME", "${gitServerCrName}", "Name of Git Server CR to generate link to Git server") stringParam("GIT_SERVER_CR_VERSION", "${gitServerCrVersion}", "Version of GitServer CR Resource") stringParam("GERRIT_PROJECT_NAME", "${codebaseName}", "Gerrit project name(Codebase name) to be build") stringParam("BRANCH", "${watchBranch}", "Branch to build artifact from") } } } } } def createReleaseRestorePipeline(pipelineName, codebaseName, codebaseStages, repository, credId, watchBranch = "master", gitServerCrName, gitServerCrVersion, edpLibraryStagesVersion, edpLibraryPipelinesVersion) { pipelineJob("${codebaseName}/${pipelineName}") { logRotator { numToKeep(10) daysToKeep(7) } definition { cps { script("@Library([\"edp-library-stages@${edpLibraryStagesVersion}\", \"edp-library-pipelines@${edpLibraryPipelinesVersion}\"]) _ \nBuild()") sandbox(true) parameters { stringParam("GIT_SERVER_CR_NAME", "${gitServerCrName}", "Name of Git Server CR to generate link to Git server") stringParam("GIT_SERVER_CR_VERSION", "${gitServerCrVersion}", "Version of GitServer CR Resource") stringParam("STAGES", "${codebaseStages}", "Consequence of stages in JSON format to be run during execution") stringParam("GERRIT_PROJECT_NAME", "${codebaseName}", "Gerrit project name(Codebase name) to be build") stringParam("BRANCH", "${watchBranch}", "Branch to build artifact from") } } } } }