Rework pipeline for testing oss/devops-portal

The pipeline was renamed and a symbolic link was created on the old
name, so, after reconfiguration of jenkins-mk the symlink can be
removed.

Change-Id: Ife70d9e507936a82e96a56efcf4c009ebab6b3f1
diff --git a/test-devops-portal-pipeline.groovy b/test-devops-portal-pipeline.groovy
new file mode 100644
index 0000000..a720745
--- /dev/null
+++ b/test-devops-portal-pipeline.groovy
@@ -0,0 +1,127 @@
+/**
+* OSS - The DevOps Portal Testing Pipeline
+* CREDENTIALS_ID - gerrit credentials id
+**/
+
+gerrit = new com.mirantis.mk.Gerrit()
+common = new com.mirantis.mk.Common()
+
+def getProjectName(gerritRef, defaultGitRef) {
+    def refSpec
+    if (gerritRef) {
+        refSpec = gerritRef
+    } else {
+        refSpec = defaultGitRef
+    }
+    def refValue = refSpec.tokenize('/').takeRight(2).join('')
+    return "oss${BUILD_NUMBER}${refValue}"
+}
+
+def executeCmd(user, project, cmd) {
+    common.infoMsg("Starting command: ${cmd}")
+    wrap([$class: 'AnsiColorBuildWrapper']) {
+        // Docker sets HOME=/ ignoring that it have to be HOME=/opt/workspace,
+        // as `docker-compose exec` does not support to pass environment
+        // variables, then `docker exec` is used.
+        sh("docker exec --user=${user} --env=HOME=/opt/workspace ${project}_devopsportal_1 ${cmd}")
+    }
+    common.successMsg("Successfully completed: ${cmd}")
+}
+
+def gerritRef
+try {
+    gerritRef = GERRIT_REFSPEC
+} catch (MissingPropertyException e) {
+    gerritRef = null
+}
+
+def defaultGitRef, defaultGitUrl
+try {
+    defaultGitRef = DEFAULT_GIT_REF
+    defaultGitUrl = DEFAULT_GIT_URL
+} catch (MissingPropertyException e) {
+    defaultGitRef = null
+    defaultGitUrl = null
+}
+def checkouted = false
+
+node("vm") {
+    def composePath = 'docker/stack/docker-compose.yml'
+    def projectName
+    def jenkinsUser
+
+    try {
+        stage('Checkout Source Code') {
+            if (gerritRef) {
+                // job is triggered by Gerrit
+                checkouted = gerrit.gerritPatchsetCheckout ([
+                    credentialsId : CREDENTIALS_ID,
+                    withWipeOut : true,
+                ])
+             } else if(defaultGitRef && defaultGitUrl) {
+                 checkouted = gerrit.gerritPatchsetCheckout(defaultGitUrl, defaultGitRef, "HEAD", CREDENTIALS_ID)
+             }
+             if(!checkouted){
+                 throw new Exception("Cannot checkout gerrit patchset, GERRIT_REFSPEC and DEFAULT_GIT_REF is null")
+             }
+        }
+
+        projectName = getProjectName(gerritRef, defaultGitRef)
+
+        stage('Setup Up Stack') {
+            sh("docker-compose --file ${composePath} --project-name=${projectName} pull")
+            sh("docker-compose --file ${composePath} --project-name=${projectName} up -d --force-recreate")
+            common.successMsg("Stack with the ${projectName} is started.")
+        }
+
+        def jenkinsUID = common.getJenkinsUid()
+        def jenkinsGID = common.getJenkinsGid()
+
+        jenkinsUser = "${jenkinsUID}:${jenkinsGID}"
+
+        stage('Print Environment Information') {
+            sh("docker-compose version")
+            sh("docker version")
+            executeCmd(jenkinsUser, projectName, "npm config get")
+            executeCmd(jenkinsUser, projectName, "env")
+            executeCmd(jenkinsUser, projectName, "ls -lan")
+        }
+
+        stage('Install Dependencies') {
+            executeCmd(jenkinsUser, projectName, "npm install")
+        }
+        stage('Run Linter Tests') {
+            executeCmd(jenkinsUser, projectName, "npm run lint")
+        }
+        stage('Run Unit Tests') {
+            timeout(4) {
+                executeCmd(jenkinsUser, projectName, "npm run test:unit")
+            }
+        }
+        stage('Run Function Tests') {
+            timeout(8) {
+                try {
+                    executeCmd(jenkinsUser, projectName, "npm run test:functional")
+                } catch (err) {
+                    archiveArtifacts(
+                        artifacts: "test_output/**/*.png",
+                        allowEmptyArchive: true,
+                    )
+                    throw err
+                }
+            }
+        }
+    } catch (err) {
+        currentBuild.result = 'FAILURE'
+        common.errorMsg("Build failed due to error: ${err}")
+        throw err
+    } finally {
+        common.sendNotification(currentBuild.result, "" ,["slack"])
+        stage('Cleanup') {
+            wrap([$class: 'AnsiColorBuildWrapper']) {
+                sh("docker-compose -f ${composePath} -p ${projectName} down")
+            }
+        }
+    }
+}
+
diff --git a/test-nodejs-pipeline.groovy b/test-nodejs-pipeline.groovy
index 36abbd7..a720745 100644
--- a/test-nodejs-pipeline.groovy
+++ b/test-nodejs-pipeline.groovy
@@ -1,23 +1,31 @@
 /**
-* JS testing pipeline
+* OSS - The DevOps Portal Testing Pipeline
 * CREDENTIALS_ID - gerrit credentials id
-* COMPOSE_PATH - path to compose file in repository
-* NODE_IMAGE - NodeJS with NPM Docker image name
-* COMMANDS - a list of command(s) to run
 **/
 
 gerrit = new com.mirantis.mk.Gerrit()
 common = new com.mirantis.mk.Common()
 
-def executeCmd(user, containerName, cmd) {
-    stage(cmd) {
-        assert containerName != null
-        common.infoMsg("Starting command: ${cmd}")
-        wrap([$class: 'AnsiColorBuildWrapper']) {
-            sh("docker exec --user=${user} ${containerName} ${cmd}")
-        }
-        common.successMsg("Successfully completed: ${cmd}")
+def getProjectName(gerritRef, defaultGitRef) {
+    def refSpec
+    if (gerritRef) {
+        refSpec = gerritRef
+    } else {
+        refSpec = defaultGitRef
     }
+    def refValue = refSpec.tokenize('/').takeRight(2).join('')
+    return "oss${BUILD_NUMBER}${refValue}"
+}
+
+def executeCmd(user, project, cmd) {
+    common.infoMsg("Starting command: ${cmd}")
+    wrap([$class: 'AnsiColorBuildWrapper']) {
+        // Docker sets HOME=/ ignoring that it have to be HOME=/opt/workspace,
+        // as `docker-compose exec` does not support to pass environment
+        // variables, then `docker exec` is used.
+        sh("docker exec --user=${user} --env=HOME=/opt/workspace ${project}_devopsportal_1 ${cmd}")
+    }
+    common.successMsg("Successfully completed: ${cmd}")
 }
 
 def gerritRef
@@ -38,10 +46,12 @@
 def checkouted = false
 
 node("vm") {
-    def containerName
-    def uniqId
+    def composePath = 'docker/stack/docker-compose.yml'
+    def projectName
+    def jenkinsUser
+
     try {
-        stage('Checkout source code') {
+        stage('Checkout Source Code') {
             if (gerritRef) {
                 // job is triggered by Gerrit
                 checkouted = gerrit.gerritPatchsetCheckout ([
@@ -55,30 +65,51 @@
                  throw new Exception("Cannot checkout gerrit patchset, GERRIT_REFSPEC and DEFAULT_GIT_REF is null")
              }
         }
-       stage('Start container') {
-            def workspace = common.getWorkspace()
-            def timeStamp = new Date().format("HHmmss", TimeZone.getTimeZone('UTC'))
-            if (gerritRef) {
-                uniqId = gerritRef.tokenize('/').takeRight(2).join('') + timeStamp
-            } else {
-                uniqId = defaultGitRef.tokenize('/').takeRight(2).join('') + timeStamp
-            }
-            sh("docker-compose -f ${COMPOSE_PATH} -p ${uniqId} up -d")
-            containerName = "${uniqId}_devopsportal_1"
-            common.successMsg("Container with id ${containerName} started.")
+
+        projectName = getProjectName(gerritRef, defaultGitRef)
+
+        stage('Setup Up Stack') {
+            sh("docker-compose --file ${composePath} --project-name=${projectName} pull")
+            sh("docker-compose --file ${composePath} --project-name=${projectName} up -d --force-recreate")
+            common.successMsg("Stack with the ${projectName} is started.")
         }
 
         def jenkinsUID = common.getJenkinsUid()
         def jenkinsGID = common.getJenkinsGid()
-        def jenkinsUser = "${jenkinsUID}:${jenkinsGID}"
 
-        executeCmd(jenkinsUser, containerName, "npm install")
+        jenkinsUser = "${jenkinsUID}:${jenkinsGID}"
 
-        def cmds = COMMANDS.tokenize('\n')
-        for (int i = 0; i < cmds.size(); i++) {
-           timeout(5) {
-               executeCmd(jenkinsUser, containerName, cmds[i])
-           }
+        stage('Print Environment Information') {
+            sh("docker-compose version")
+            sh("docker version")
+            executeCmd(jenkinsUser, projectName, "npm config get")
+            executeCmd(jenkinsUser, projectName, "env")
+            executeCmd(jenkinsUser, projectName, "ls -lan")
+        }
+
+        stage('Install Dependencies') {
+            executeCmd(jenkinsUser, projectName, "npm install")
+        }
+        stage('Run Linter Tests') {
+            executeCmd(jenkinsUser, projectName, "npm run lint")
+        }
+        stage('Run Unit Tests') {
+            timeout(4) {
+                executeCmd(jenkinsUser, projectName, "npm run test:unit")
+            }
+        }
+        stage('Run Function Tests') {
+            timeout(8) {
+                try {
+                    executeCmd(jenkinsUser, projectName, "npm run test:functional")
+                } catch (err) {
+                    archiveArtifacts(
+                        artifacts: "test_output/**/*.png",
+                        allowEmptyArchive: true,
+                    )
+                    throw err
+                }
+            }
         }
     } catch (err) {
         currentBuild.result = 'FAILURE'
@@ -86,22 +117,11 @@
         throw err
     } finally {
         common.sendNotification(currentBuild.result, "" ,["slack"])
-        stage('Attach artifacts') {
-            if (containerName != null) {
-                archiveArtifacts(
-                    artifacts: "test_output/screenshots/*.png",
-                )
-            }
-        }
         stage('Cleanup') {
-            if (containerName != null) {
-                dockerCleanupCommands = ['stop', 'rm -f']
-                for (int i = 0; i < dockerCleanupCommands.size(); i++) {
-                    sh("docker-compose -f ${COMPOSE_PATH} -p ${uniqId} ${dockerCleanupCommands[i]} || true")
-                }
-                sh("docker network rm ${uniqId}_default || true")
-                common.infoMsg("Container with id ${containerName} was removed.")
+            wrap([$class: 'AnsiColorBuildWrapper']) {
+                sh("docker-compose -f ${composePath} -p ${projectName} down")
             }
         }
     }
 }
+