diff --git a/Jenkinsfile b/Jenkinsfile index 200f2c9..03a977b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,12 +19,12 @@ if ("${params.gCube_release_version}" || "${params.RELEASE_URL}"){ //locate the release file releaseURL = "https://code-repo.d4science.org/gCubeCI/gCubeReleases/raw/branch/master/open/gcube-${gCube_release_version}.yaml" }else{ - releaseURL = "${params.RELEASE_URL}" + releaseURL = "${params.RELEASE_URL}" } //load the release file text = releaseURL.toURL().getText() //parsing - yamlConfig = new Yaml().load(text) + yamlConfig = new Yaml().load(text) if (verbose) println yamlConfig.inspect() echo "Building gCube v. ${yamlConfig.gCube_release.Version}" @@ -55,33 +55,33 @@ pipeline { environment { AGENT_ROOT_FOLDER = "${agent_root_folder}" -// folder where all the pending deployment will be added +// folder where all the pending deployment will be added PENDING_DEPLOY_FOLDER="${agent_root_folder}/CD/" ANSIBLE_ROOT_FOLDER = "${agent_root_folder}/ansible-repos/ansible-playbooks/d4science-ghn-cluster/CD" PIPELINE_BUILD_NUMBER = "${env.BUILD_NUMBER}" -// deploy file related to the current pipeline job +// deploy file related to the current pipeline job DEPLOY_FILE = "${PENDING_DEPLOY_FOLDER}deploy.${PIPELINE_BUILD_NUMBER}.csv" BACKUP_FILE = "${PENDING_DEPLOY_FOLDER}deploy.${PIPELINE_BUILD_NUMBER}.bck" - // deploy folder that contains all the pending jobs associated to the current pipeline execution + // deploy folder that contains all the pending jobs associated to the current pipeline execution DEPLOY_FOLDER= "${WORKSPACE}/CD-${PIPELINE_BUILD_NUMBER}" - // artifacts coordinates + // artifacts coordinates TRIGGER_JOB= "${params.TRIGGER_JOB}" TRIGGER_VERSION= "${params.TRIGGER_VERSION}" TRIGGER_HOST="${params.TRIGGER_HOST}" - // enable the ContinuousDeployment if TRUE + // enable the ContinuousDeployment if TRUE TRIGGER_CD="${params.TRIGGER_CD}" - // Useful to identify the remote YAML file + // Useful to identify the remote YAML file GCUBE_RELEASE_NUMBER = "${params.gCube_release_version}" - //Category name of the components candidates to the remote deployment + //Category name of the components candidates to the remote deployment DEPLOY_CATEGORY="${env.DEPLOY_CATEGORY}" - //Job name of the release pipeline - RELEASE_JOB='gCubeBuilder' - //URL to the YAML file. Used alternatively to RELEASE_JOB + //Job name of the release pipeline + RELEASE_JOB='Pipeline-gCubeBuilder' + //URL to the YAML file. Used alternatively to RELEASE_JOB RELEASE_URL= "${params.RELEASE_URL}" - // username of ReleaseManager. Used for limiting the preproduction deployments + // username of ReleaseManager. Used for limiting the preproduction deployments RELEASE_MANAGER_USER='roberto.cirillo' - // name of Smartgears distribution group, defined in the yaml file ( only for release deployments) - DISTRIBUTION_CATEGORY='Distribution' + // name of Smartgears distribution group, defined in the yaml file ( only for release deployments) + DISTRIBUTION_CATEGORY='Distribution' } parameters { @@ -99,10 +99,7 @@ pipeline { description: 'Set to false to avoid current deploy') string(name: 'gCube_release_version', defaultValue: '', - description: 'The number of the gCube release. Leave blank if executed outside gCube release.') - string(name: 'report_number', - defaultValue: '', - description: 'The build report number on Git to pull the notes. Leave blank if executed outside gCube release.') + description: 'The number of the current gCube release. Leave blank if executed outside gCube release.') string(name: 'RELEASE_URL', defaultValue: '', description: 'URL to the yaml file. Leave blank if executed outside gCube release.') @@ -129,29 +126,26 @@ pipeline { } } steps { - echo 'Cron build enabled. Deploy from system ongoing' + echo 'Cron build enabled. \033[31;1;4mDeploy from system ongoing\033[0m' script { echo "pipeline was triggered by ${params.TRIGGER_JOB}" - println("Going to deploy all the pending deployments") + println("Going to deploy all the pending deployments") def deployFolder="CD-${env.BUILD_NUMBER}"; - parseDeployPendingJobs(deployFolder); + parseDeployPendingJobs(deployFolder); } - + } } stage('Nothing to do ') { when{ - anyOf{ - allOf{ - triggeredBy 'TimerTrigger' - environment name: 'IS_SCHEDULED', value: 'False' - } + allOf{ + triggeredBy 'TimerTrigger' + environment name: 'IS_SCHEDULED', value: 'False' } - } steps { - echo 'Going to sleep' - sh ' exit 1; ' + echo '\033[31;1;4mGoing to sleep\033[0m' + sh ' exit 0; ' } } stage('New pending deploy ') { @@ -166,16 +160,17 @@ pipeline { } steps { sh ''' - echo "Cron build enabled. New deploy of ${TRIGGER_JOB} - ${TRIGGER_VERSION} will be added to the pending deploy file" + echo '\033[31;1;4mNew pending deploy added to the queue/033[0m' + echo "Cron build enabled. Adding ${TRIGGER_JOB} - ${TRIGGER_VERSION} to the queue" touch $DEPLOY_FILE; if grep -q \"\${TRIGGER_JOB}\" \${DEPLOY_FILE}; then echo "component ${TRIGGER_JOB} already added. Nothing to add." else echo "${TRIGGER_JOB},${TRIGGER_VERSION},${TRIGGER_HOST}" >> ${DEPLOY_FILE} - fi - ''' - // the following catch give always an error in order to return a feedback UNSTABLE to the final user since the deploy is still not performed. - // Not sure this is the best approach + fi + ''' + // the following catch give always an error in order to return a feedback UNSTABLE to the final user since the deploy is still not performed. + // Not sure this is the best approach catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') { sh(""" exit 126; @@ -193,20 +188,21 @@ pipeline { triggeredBy 'BuildUpstreamCause' triggeredBy 'UpstreamCause' } - expression { params.TRIGGER_JOB != "${RELEASE_JOB}" } + expression { params.TRIGGER_JOB != "${RELEASE_JOB}" } } steps { script{ - echo "Cron build disabled. New deploy of ${params.TRIGGER_JOB} - ${params.TRIGGER_VERSION} ongoing" - ansiColor("xterm") { - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + echo '\033[31;1;4mNew upstream deploy ongoing\033[0m' + echo "Cron build disabled. Component: ${params.TRIGGER_JOB} - ${params.TRIGGER_VERSION}" + ansiColor('xterm') { + catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { checkup("${params.TRIGGER_JOB}", "${params.TRIGGER_VERSION}", "${params.TRIGGER_HOST}"); deploy("${params.TRIGGER_JOB}", "${params.TRIGGER_VERSION}", "${params.TRIGGER_HOST}"); } } } - + } } stage('Deploy from gCubeRelease ') { @@ -214,10 +210,10 @@ pipeline { anyOf{ triggeredBy 'BuildUpstreamCause' triggeredBy 'UpstreamCause' - //added just for testing . To Remove. + //added just for testing . To Remove. triggeredBy cause: "UserIdCause", detail: "${RELEASE_MANAGER_USER}" } - // we should improve this conditional check + // we should improve this conditional check equals(actual: "${params.TRIGGER_JOB}", expected: "${RELEASE_JOB}") } steps { @@ -228,23 +224,21 @@ pipeline { }else { println ("CATEGORIES NOT FOUND ON YAML FILE. SKIP TO NEXT STAGE");} } } - } + } stage('Deploy manually ') { when{ allOf{ environment name: 'IS_SCHEDULED', value: 'False'; triggeredBy 'UserIdCause' } - expression { params.TRIGGER_JOB != "${RELEASE_JOB}" } + expression { params.TRIGGER_JOB != "${RELEASE_JOB}" } } steps { + echo '\033[31;1;4mNew deploy ongoing manually triggered\033[0m' echo "Cron build disabled. Pipeline executed Manually. New deploy of ${params.TRIGGER_JOB} - ${params.TRIGGER_VERSION} ongoing" - ansiColor("xterm") { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - deploy("${params.TRIGGER_JOB}", "${params.TRIGGER_VERSION}", "${params.TRIGGER_HOST}"); - } + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + deploy("${params.TRIGGER_JOB}", "${params.TRIGGER_VERSION}", "${params.TRIGGER_HOST}"); } - } } } @@ -278,7 +272,7 @@ pipeline { def deploy(String service, String version, String host){ def now = new Date(); println("Going to deploy the service "+service+" with version: "+version+" on target: "+host); - def statusCode = sh( script: "cd $ANSIBLE_ROOT_FOLDER;git pull;./deployService.sh $service $version $host;", returnStdout: true); + def statusCode = sh( script: "cd $ANSIBLE_ROOT_FOLDER;./deployService.sh $service $version $host;", returnStdout: true); sh(""" echo " last exit code \$?"; """) @@ -330,12 +324,12 @@ def parseDeployPendingJobs( def deployFolder){ for (def record : records) { println("Processing record: "+record) serviceList += "${record.get(0)},${record.get(1)},${record.get(2)}"; - } + } sh "rm ${file.path}" } sh "rm -Rf ${deployFolder}" deployJobs(serviceList.unique()) - } + } } //Deploy jobs from an input list with the following elements: serviceName,serviceVersion,targetHost. Create a new stage for any job def deployJobs(def serviceList){ @@ -349,7 +343,7 @@ def deployJobs(def serviceList){ } } } - + } //Deploy only release components. All the component are passed as: componentName,componentVersion def deployReleaseJobs(def serviceList, String smartgears){ @@ -363,7 +357,7 @@ def deployReleaseJobs(def serviceList, String smartgears){ if (smartgears) deployRelease(service[0], service[ 1 ], smartgears); else - deployRelease(service[0], service[ 1 ], null); + deployRelease(service[0], service[ 1 ], null); } } } @@ -377,7 +371,7 @@ def deployRelease(def categoryList, def yaml){ if (categories.contains(group_name)){ for ( def category : categories){ if("${group_name}" == "$category"){ - if (category == "${DISTRIBUTION_CATEGORY}"){ + if (category == "${DISTRIBUTION_CATEGORY}"){ //searching smartgears-distribution version in Distribution component of defined inside the yaml file def sg= component_list?.collect{ if ("$it.name" == 'smartgears-distribution'){ return "$it.version"; }} smartgears=(sg !=null ) ? sg[0] : null @@ -389,5 +383,5 @@ def deployRelease(def categoryList, def yaml){ } } } - deployReleaseJobs(releaseList, smartgears); + deployReleaseJobs(releaseList, smartgears); } \ No newline at end of file diff --git a/README.md b/README.md index 21a978e..c71c91e 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,11 @@ Jenkins Pipeline script to manage one or more gCube components deployment * Manually from Jenkins GUI ## Expected environment variables +The variables below must be specified as environment variables on the agent where the deployments will be executed: +* IS_SCHEDULED (True | False): if true all the deployment requests will be performed periodically as specified by cron +* ENVIRONMENT: ( DEV | PREPROD | PROD) Indicates the target environment where will be deployed all the artifacts +* DEPLOY_CATEGORY: (Related to release build) one or more Component group on yaml file where search the components to deploy +* CD: (Continuous Deployment: True | False) if True the remote deploy will be performed ## References * [Jenkins Pipeline](https://jenkins.io/doc/book/pipeline/) diff --git a/images/FlowChartgCubeDeployer.png b/images/FlowChartgCubeDeployer.png deleted file mode 100644 index eeec902..0000000 Binary files a/images/FlowChartgCubeDeployer.png and /dev/null differ