diff --git a/Jenkinsfile b/Jenkinsfile index 65f8428034..2a17a4b664 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,13 +12,10 @@ node('docker') { properties([ // Keep only the last 10 build to preserve space buildDiscarder(logRotator(numToKeepStr: '10')), - disableConcurrentBuilds(), - parameters([ - string(name: 'dockerTag', trim: true, defaultValue: 'latest', description: 'Extra Docker Tag for cloudogu/scm-manager image') - ]) + disableConcurrentBuilds() ]) - timeout(activity: true, time: 40, unit: 'MINUTES') { + timeout(activity: true, time: 60, unit: 'MINUTES') { Git git = new Git(this) @@ -30,16 +27,47 @@ node('docker') { checkout scm } + if (isReleaseBranch()) { + stage('Set Version') { + String releaseVersion = getReleaseVersion(); + // set maven versions + mvn "versions:set -DgenerateBackupPoms=false -DnewVersion=${releaseVersion}" + // set versions for ui packages + // we need to install in order to set version with ui-scripts + mvn "-pl :scm-ui buildfrontend:install@install" + mvn "-pl :scm-ui buildfrontend:run@set-version" + + // stage pom changes + sh "git status --porcelain | sed s/^...// | grep pom.xml | xargs git add" + // stage package.json changes + sh "git status --porcelain | sed s/^...// | grep package.json | xargs git add" + // stage lerna.json changes + sh "git add lerna.json" + + // commit changes + sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' commit -m 'release version ${releaseVersion}'" + + // merge release branch into master + sh "git checkout master" + sh "git merge --ff-only ${env.BRANCH_NAME}" + + // set tag + sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' tag -m 'release version ${releaseVersion}' ${releaseVersion}" + } + } + stage('Build') { mvn 'clean install -DskipTests' } stage('Unit Test') { mvn 'test -Pcoverage -Dmaven.test.failure.ignore=true' + junit allowEmptyResults: true, testResults: '**/target/surefire-reports/TEST-*.xml,**/target/jest-reports/TEST-*.xml' } stage('Integration Test') { - mvn 'verify -Pit -pl :scm-webapp,:scm-it -Dmaven.test.failure.ignore=true -Dscm.git.core.trustfolderstat=false' + mvn 'verify -Pit -pl :scm-webapp,:scm-it -Dmaven.test.failure.ignore=true -Dscm.git.core.supportsatomicfilecreation=false' + junit allowEmptyResults: true, testResults: '**/target/failsafe-reports/TEST-*.xml' } stage('SonarQube') { @@ -51,10 +79,7 @@ node('docker') { } } - def commitHash = git.getCommitHash() - def dockerImageTag = "2.0.0-dev-${commitHash.substring(0,7)}-${BUILD_NUMBER}" - - if (isMainBranch()) { + if (isMainBranch() || isReleaseBranch()) { stage('Lifecycle') { try { @@ -66,38 +91,97 @@ node('docker') { } } - stage('Archive') { - archiveArtifacts 'scm-webapp/target/scm-webapp.war' - archiveArtifacts 'scm-server/target/scm-server-app.*' - } + if (isBuildSuccessful()) { - stage('Docker') { - def image = docker.build('cloudogu/scm-manager') - docker.withRegistry('', 'hub.docker.com-cesmarvin') { - image.push(dockerImageTag) - image.push('latest') - if (!'latest'.equals(params.dockerTag)) { - image.push(params.dockerTag) + def commitHash = git.getCommitHash() - def newDockerTag = "2.0.0-${commitHash.substring(0,7)}-dev-${params.dockerTag}" - currentBuild.description = newDockerTag - image.push(newDockerTag) + def imageVersion = mvn.getVersion() + if (imageVersion.endsWith('-SNAPSHOT')) { + imageVersion = imageVersion.replace('-SNAPSHOT', "${commitHash.substring(0,7)}-${BUILD_NUMBER}") + } + + stage('Archive') { + archiveArtifacts 'scm-webapp/target/scm-webapp.war' + archiveArtifacts 'scm-server/target/scm-server-app.*' + } + + stage('Maven Deployment') { + // TODO why is the server recreated + // delete appassembler target, because the maven plugin fails to recreate the tar + sh "rm -rf scm-server/target/appassembler" + + // deploy java artifacts + mvn.useRepositoryCredentials([id: 'maven.scm-manager.org', url: 'https://maven.scm-manager.org/nexus', credentialsId: 'oss-jenkins_maven.scm-manager.org', type: 'Nexus2']) + mvn.deployToNexusRepository() + + // deploy frontend bits + withCredentials([string(credentialsId: 'cesmarvin_npm_token', variable: 'NPM_TOKEN')]) { + writeFile encoding: 'UTF-8', file: '.npmrc', text: "//registry.npmjs.org/:_authToken='${NPM_TOKEN}'" + writeFile encoding: 'UTF-8', file: '.yarnrc', text: ''' + registry "https://registry.npmjs.org/" + always-auth true + email cesmarvin@cloudogu.com + '''.trim() + mvn "-pl :scm-ui buildfrontend:run@deploy" + } + } + + stage('Docker') { + docker.withRegistry('', 'hub.docker.com-cesmarvin') { + def image = docker.build('cloudogu/scm-manager') + image.push(imageVersion) + if (isReleaseBranch()) { + image = docker.build('scmmanager/scm-manager') + image.push(imageVersion) + } + } + } + + stage('Presentation Environment') { + build job: 'scm-manager/next-scm.cloudogu.com', propagate: false, wait: false, parameters: [ + string(name: 'changeset', value: commitHash), + string(name: 'imageTag', value: imageVersion) + ] + } + + if (isReleaseBranch()) { + stage('Update Repository') { + + // merge changes into develop + sh "git checkout develop" + // TODO what if we have an conflict + // e.g.: someone has edit the changelog durring the release + sh "git merge master" + + // set versions for maven packages + mvn "build-helper:parse-version versions:set -DgenerateBackupPoms=false -DnewVersion='\${parsedVersion.majorVersion}.\${parsedVersion.nextMinorVersion}.0-SNAPSHOT'" + + // set versions for ui packages + mvn "-pl :scm-ui buildfrontend:run@set-version" + + // stage pom changes + sh "git status --porcelain | sed s/^...// | grep pom.xml | xargs git add" + // stage package.json changes + sh "git status --porcelain | sed s/^...// | grep package.json | xargs git add" + // stage lerna.json changes + sh "git add lerna.json" + + // commit changes + sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' commit -m 'prepare for next development iteration'" + + // push changes back to remote repository + withCredentials([usernamePassword(credentialsId: 'cesmarvin-github', usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) { + sh "git -c credential.helper=\"!f() { echo username='\$GIT_AUTH_USR'; echo password='\$GIT_AUTH_PSW'; }; f\" push origin master --tags" + sh "git -c credential.helper=\"!f() { echo username='\$GIT_AUTH_USR'; echo password='\$GIT_AUTH_PSW'; }; f\" push origin develop --tags" + sh "git -c credential.helper=\"!f() { echo username='\$GIT_AUTH_USR'; echo password='\$GIT_AUTH_PSW'; }; f\" push origin :${env.BRANCH_NAME}" + } } } - } - stage('Deployment') { - build job: 'scm-manager/next-scm.cloudogu.com', propagate: false, wait: false, parameters: [ - string(name: 'changeset', value: commitHash), - string(name: 'imageTag', value: dockerImageTag) - ] } } } - // Archive Unit and integration test results, if any - junit allowEmptyResults: true, testResults: '**/target/failsafe-reports/TEST-*.xml,**/target/surefire-reports/TEST-*.xml,**/target/jest-reports/TEST-*.xml' - mailIfStatusChanged(git.commitAuthorEmail) } } @@ -107,7 +191,7 @@ String mainBranch Maven setupMavenBuild() { Maven mvn = new MavenWrapperInDocker(this, "scmmanager/java-build:11.0.6_10") - if (isMainBranch()) { + if (isMainBranch() || isReleaseBranch()) { // Release starts javadoc, which takes very long, so do only for certain branches mvn.additionalArgs += ' -DperformRelease' // JDK8 is more strict, we should fix this before the next release. Right now, this is just not the focus, yet. @@ -144,6 +228,14 @@ void analyzeWith(Maven mvn) { } } +boolean isReleaseBranch() { + return env.BRANCH_NAME.startsWith("release/"); +} + +String getReleaseVersion() { + return env.BRANCH_NAME.substring("release/".length()); +} + boolean isMainBranch() { return mainBranch.equals(env.BRANCH_NAME) }