// Module included in the following assemblies:
// * builds/build-strategies.adoc

:_mod-docs-content-type: PROCEDURE
[id="builds-tutorial-pipeline_{context}"]
= Pipeline build tutorial

[IMPORTANT]
====
The Pipeline build strategy is deprecated in {product-title} 4. Equivalent and improved functionality is present in the {product-title} Pipelines based on Tekton.

Jenkins images on {product-title} are fully supported and users should follow Jenkins user documentation for defining their `jenkinsfile` in a job or store it in a Source Control Management system.
====

This example demonstrates how to create an {product-title} Pipeline that will build, deploy, and verify a `Node.js/MongoDB` application using the `nodejs-mongodb.json` template.

.Procedure

. Create the Jenkins master:
+
[source,terminal]
----
  $ oc project <project_name>
----
+
Select the project that you want to use or create a new project with `oc new-project <project_name>`.
+
[source,terminal]
----
  $ oc new-app jenkins-ephemeral <2>
----
+
If you want to use persistent storage, use `jenkins-persistent` instead.
+
. Create a file named `nodejs-sample-pipeline.yaml` with the following content:
+
[NOTE]
====
This creates a `BuildConfig` object that employs the Jenkins pipeline strategy to build, deploy, and scale the `Node.js/MongoDB` example application.
====
+
[source,yaml]
+
----
kind: "BuildConfig"
apiVersion: "v1"
metadata:
  name: "nodejs-sample-pipeline"
spec:
  strategy:
    jenkinsPipelineStrategy:
      jenkinsfile: <pipeline content from below>
    type: JenkinsPipeline
----
+
. After you create a `BuildConfig` object with a `jenkinsPipelineStrategy`, tell the
pipeline what to do by using an inline `jenkinsfile`:
+
[NOTE]
====
This example does not set up a Git repository for the application.

The following `jenkinsfile` content is written in Groovy using the {product-title} DSL. For this example, include inline content in the `BuildConfig` object using the YAML Literal Style, though including a `jenkinsfile` in your source repository is the preferred method.
====
+
[source,groovy]
----
def templatePath = 'https://raw.githubusercontent.com/openshift/nodejs-ex/master/openshift/templates/nodejs-mongodb.json' <1>
def templateName = 'nodejs-mongodb-example' <2>
pipeline {
  agent {
    node {
      label 'nodejs' <3>
    }
  }
  options {
    timeout(time: 20, unit: 'MINUTES') <4>
  }
  stages {
    stage('preamble') {
        steps {
            script {
                openshift.withCluster() {
                    openshift.withProject() {
                        echo "Using project: ${openshift.project()}"
                    }
                }
            }
        }
    }
    stage('cleanup') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  openshift.selector("all", [ template : templateName ]).delete() <5>
                  if (openshift.selector("secrets", templateName).exists()) { <6>
                    openshift.selector("secrets", templateName).delete()
                  }
                }
            }
        }
      }
    }
    stage('create') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  openshift.newApp(templatePath) <7>
                }
            }
        }
      }
    }
    stage('build') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  def builds = openshift.selector("bc", templateName).related('builds')
                  timeout(5) { <8>
                    builds.untilEach(1) {
                      return (it.object().status.phase == "Complete")
                    }
                  }
                }
            }
        }
      }
    }
    stage('deploy') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  def rm = openshift.selector("dc", templateName).rollout()
                  timeout(5) { <9>
                    openshift.selector("dc", templateName).related('pods').untilEach(1) {
                      return (it.object().status.phase == "Running")
                    }
                  }
                }
            }
        }
      }
    }
    stage('tag') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  openshift.tag("${templateName}:latest", "${templateName}-staging:latest") <10>
                }
            }
        }
      }
    }
  }
}
----
<1> Path of the template to use.
<2> Name of the template that will be created.
<3> Spin up a `node.js` agent pod on which to run this build.
<4> Set a timeout of 20 minutes for this pipeline.
<5> Delete everything with this template label.
<6> Delete any secrets with this template label.
<7> Create a new application from the `templatePath`.
<8> Wait up to five minutes for the build to complete.
<9> Wait up to five minutes for the deployment to complete.
<10> If everything else succeeded, tag the `$ {templateName}:latest` image as
`$ {templateName}-staging:latest`. A pipeline build configuration for the staging
environment can watch for the `$ {templateName}-staging:latest` image to change
and then deploy it to the staging environment.
+
[NOTE]
====
The previous example was written using the declarative pipeline style, but the older scripted pipeline style is also supported.
====
+
. Create the Pipeline `BuildConfig` in your {product-title} cluster:
+
[source,terminal]
----
$ oc create -f nodejs-sample-pipeline.yaml
----
+
.. If you do not want to create your own file, you can use the sample from the Origin repository by running:
+
[source,terminal]
----
$ oc create -f https://raw.githubusercontent.com/openshift/origin/master/examples/jenkins/pipeline/nodejs-sample-pipeline.yaml
----
+
. Start the Pipeline:
+
[source,terminal]
----
$ oc start-build nodejs-sample-pipeline
----
+
[NOTE]
====
Alternatively, you can start your pipeline with the {product-title} web console by navigating to the Builds -> Pipeline section and clicking *Start Pipeline*, or by visiting the Jenkins Console, navigating to the Pipeline that you created, and clicking *Build Now*.
====
+
Once the pipeline is started, you should see the following actions performed within your project:
+
* A job instance is created on the Jenkins server.
* An agent pod is launched, if your pipeline requires one.
* The pipeline runs on the agent pod, or the master if no agent is required.
** Any previously created resources with the `template=nodejs-mongodb-example` label will be deleted.
** A new application, and all of its associated resources, will be created from the `nodejs-mongodb-example` template.
** A build will be started using the `nodejs-mongodb-example` `BuildConfig`.
*** The pipeline will wait until the build has completed to trigger the next stage.
** A deployment will be started using the `nodejs-mongodb-example` deployment configuration.
*** The pipeline will wait until the deployment has completed to trigger the next stage.
** If the build and deploy are successful, the `nodejs-mongodb-example:latest` image will be tagged as `nodejs-mongodb-example:stage`.
* The agent pod is deleted, if one was required for the pipeline.
+
[NOTE]
====
The best way to visualize the pipeline execution is by viewing it in the {product-title} web console. You can view your pipelines by logging in to the web console and navigating to Builds -> Pipelines.
====
