Migrating Jenkins Environments to Jenkins 2

Revision 1.4 - 03/27/16

Brent Laster

IMPORTANT NOTES:

1. You must have internet access through your VM for some of the labs.

2. Due to recent regression in one of the pipeline plugins used by Jenkins, you will see a LOT of these type of messages
in the build logs:

Cannot contact worker_node1: java.io.IOException: Remote call on worker_node1 failed
Cannot contact worker_node1: java.io.IOException: Remote call on worker_node1 failed
Cannot contact worker_node1: java.io.IOException: Remote call on worker_node1 failed

These occur during the “idle time” while Jenkins is waiting on a node to do something. They are just noise for us and
do not indicate a problem. A ticket has been opened with Cloudbees to get this fixed.

3. If you run into problems, double-check your typing!

4. When the system tells you to save a file you’ve been working on in the editor (such as gedit), you will also need to
exit the editor unless you started it running in the background.

5. Lab 1 starts on the next page!

1
Page

© 2017 Brent Laster
Brent Laster

Lab 1 - Creating a Simple Pipeline Script

Purpose: In this first lab, we’ll start with a sample pipeline script and change it to work for our setup to illustrate
some basic pipeline concepts.

1. Start Jenkins by clicking on the “Jenkins 2” shortcut on the desktop OR opening the Firefox browser and navigating to
“http://localhost:8080”.

2. You should be on the login screen. Log in to Jenkins with User = jenkins2 and Password = jenkins2

(Note: If at some point during the workshop you try to do something in Jenkins and find that you can’t, check to see if
you’ve been logged out. Log back in if needed.)

3. Click on the “Manage Jenkins” link in the menu on the left-hand side. Next, look in the list of selections in the lower
section of the screen, and find and click on “Manage Nodes”.

4. On the next screen, notice that you already have nodes (formerly known as slaves) named “worker_node1”,
“workder_node2”, and “worker_node3”. We’ll use these to run our processes on. Note that you wouldn’t normally
have a node defined on the same system as the master, but we are using this setup to simplify things for the workshop.

2

5. Click on “Back to Dashboard” (upper left) to get back to the Jenkins Dashboard. Now we’ll create our first pipeline
Page

project. In the left column, click on “New Item”. Notice that there are quite a few different types of items that we can
© 2017 Brent Laster
Brent Laster

select here. Type a name into the “Enter an item name” field. As a suggestion, you can use “simple-pipe”. Then
choose the “Pipeline” project type and click on the “OK” button to create the new project.

6. Once Jenkins finishes loading the page for our new item, scroll down and find the Pipeline section. Leave the
Definition selection as “Pipeline script”. Now, we’ll create a simple script to pull down a Git repository already installed
on the image. We’ll create a node block to have it run on “worker_node1”, and then a stage block within that to do the
actual source management command. The Pipeline DSL here provides a “git” command that we can leverage for that.

Inside the input area for the Script section, type (or paste) the code below. (You can leave out the comments if you
prefer.)
node ('worker_node1') {
stage('Source') { // for display purposes
// Get some code from our Git repository
git 'git@diyvb2:/opt/git/gradle-demo.git'
}
}

This is what it will look like afterwards.

3
Page

© 2017 Brent Laster
Brent Laster

4 Page © 2017 Brent Laster Brent Laster . Notice the reference to the “Stage View”. 8. (It may take a moment to startup and run. click the Save button to save your changes. Now. We also have the time the stage took and the green block indicating success. as the message indicates. 7. The “Source” name is what we had in our stage definition. Since we haven’t run the job yet.) After it runs. You’ll now be on the job view for your new job. Click on the “Build Now” link to build your job. notice that you now see a Stage View that is more informative. there’s nothing to show here.

Close the popup window for the logs and click on Back to Dashboard to be ready for the next lab. click on that smaller “Logs” box inside the “Success” box to see the log for the run of the stage pop up. 9.) 11. Hover over the green box for the Source stage until you see another box pop up with a smaller box named “Logs”. 10. ============================================================================================= END OF LAB 5 Page ============================================================================================= © 2017 Brent Laster Brent Laster . you could also use the traditional Console Output route to see the logs. Let’s look at the logs for this stage via this page. Now. (Of course.

To see the Gradle configuration. and then selecting Configure or just entering the URL: http://localhost:8080/view/All/job/simple-pipe/configure . You should be back on the Jenkins Dashboard (home page) after the last lab. We’ll need to use that name in our pipeline script to refer to it.either by going to the Dashboard. 1. This sets us up to use the Gradle tool that we have installed. Lab 2 . We already have Gradle installed and configured on this Jenkins instance. Switch back to the configuration for your simple-pipe job . (Notice that the closing brace for the node has to come after the Build stage definition. 5. Click on the “Gradle Installations” button.) node ('worker_node1') { def gradleHome stage('Source') { // for display purposes 6 Page // Get some code from our Git repository © 2017 Brent Laster Brent Laster . click on Manage Jenkins and then select Global Tool Configuration in the list. On the Global Tool Configurations page. then selecting the job. Scroll down to the pipeline script input area again and add the lines in bold below (continued on next page) to your job. 3. 2. scroll down and find the Gradle section. For this lab. Notice that we have our local Gradle instance named as “gradle32” here. we’ll add a new stage to our pipeline project to build the code we download. we’ll add a stage to use Gradle to build our gradle-demo project. 4. So we just need to understand how to reference it in our pipeline script. We’ll also see how to use the Retry functionality and include tools defined globally in Jenkins.Adding a Build Stage Purpose: In this lab.

we just need to add the command to actually run gradle and do the build. To get to the executable. Wait for the run to complete. (There is a double quote and then a single quote before ${gradleHome … ) stage('Build') { // Run the gradle build gradleHome = tool 'gradle32' sh "'${gradleHome}/bin/gradle' clean buildAll" } 7. Save your changes and click on the “Build Now” link in the left column. 9. Hover over each box for the stages in the most recent run (#2) to see the status information for that stage. git ‘git@diyvb2:/opt/git/gradle-demo. That command is effectively just gradle followed by a list of tasks to run. and the color of the boxes. The gradleHome value we have is what’s configured for that value . To make this all work. we’ll need to add on “bin/gradle”. The “pink” indicates a successful stage in an overall failure.the home path for Gradle. Note the use of the single quotes and the double quotes.git’ } stage('Build') { // Run the gradle build gradleHome = tool 'gradle32' } } 6. Then we’ll add in the gradle tasks that we want to run. (This will take a while for the gradle part.) Notice the Stage View now. We’ll use a shell command to run this. Now that we have the stage and have told Jenkins how to find the gradle installation that we want to use. add in the line in bold below in the Build stage. 7 Page © 2017 Brent Laster Brent Laster . Now. The pink and red stripe indicates a failures (as does the “failed” note in the bottom right corner).

the task should be “build”. The reason is that. In the left column. notice the message telling you which step failed (“Shell Script”). To use this. 12. we’ll need to get to the screen for the specific build that failed. Click on the small down arrow in the square next to “Shell Script” to expand the log information. for Gradle. The log shows the problem . Click on the Logs link to bring those up. Let’s fix that. 8 Page © 2017 Brent Laster Brent Laster . In the pop-up box. What is the error message? 11. click on the red ball next to the latest build. 10. you’ll see a description of the steps involved in this stage. In the “Build History” window. let’s use the Replay functionality to test this change out. 13. click on the Replay menu item. While hovering over the Build stage box. or click on the “Last build (#2)” link in the Permalinks section. the replay screen will appear with a copy of the pipeline script as it is for this build.there is not a “buildAll” task. Before we change our script though. Use the escape key or X in the corner to close the Stage Logs (Build) window. After a moment.

14. Save your changes and then Build Now (left menu). ============================================================================================= END OF LAB ============================================================================================= 9 Page © 2017 Brent Laster Brent Laster . Then click the “Run” button. This build (#4) should complete successfully after a few moments. On the line that has the gradle command and the “buildAll” task. Edit the same line in this window as in the previous step to change “buildAll” to just “build”. Scroll down to the Pipeline section and look at the code in the Pipeline script window. Click on the Configure menu item on the left. 15. The Replay allowed us to try something out without changing the code. which should complete successfully after a few moments. Notice that it still has the old code in it (“buildAll”). change “buildAll” to just “build”. Notice that this kicks off another build.

3. 10 Page © 2017 Brent Laster Brent Laster . click on Manage Jenkins. Note that while a branch name can be used here. we have defined some shared libraries and functions in a “shared-libraries” Git repository. We have one named “Utilities” that we’ll use to replace our build step here. @Library(‘libname@version’)) For Retrieval method.foo class Utilities { static def gbuild(script. we need to add it into our Jenkins system configuration. For the workshop.e. enter a tagged version. Click the “Add” button. select Modern SCM. 1. updates to that may not be picked up over time.tool 'gradle32'}/bin/gradle ${args}" } } 2. (i.sh "${script. To make this available to our pipeline scripts. so enter that. Check the “Allow default version to be overridden” box to tell Jenkins to allow loading a different version of this library in your script if you specify the version in conjunction with the @Library directive. 4. package org. the latest version is “1. but we don’t want to have it loaded for every project we create. Fill in the general fields in this section as follows: For Name. Loading a library implicitly is a convenience. Leave the “Load implicitly” checkbox unchecked. Scroll down until you find the “Global Pipeline Libraries” section. args) { script. enter “Utilities”. we’ll replace our use of the build command with code defined in a shared library. For Default version.Using Shared Libraries Purpose: In this lab. Lab 3 .5”. It takes a reference to our script and build arguments to pass to our gradle instance for a build. You can see the definition of it in the directory ~/shared-libraries/src/org/conf/Utilities.groovy. This will be the name you refer to the library by in the script. This is allowing pulling the library from source control via the Git plugin that has been updated for pipeline. then Configure System. From the dashboard. In this case.

) @Library('Utilities@1. 5. After selecting Git. (Lines referencing gradleHome are no longer needed and can be removed.note the added/changed lines in bold. import the method from our library.conf. 6. So we’ll need to select Git in that section and configure it to point to that repository. and use the new call to build the code.* node ('worker_node1') { stage('Source') { // for display purposes // Get some code from our Git repository git ‘git@diyvb2:/opt/git/gradle-demo. (See listing below.git’ } stage('Build') { // Run the gradle build gbuild this. enter git@diyvb2:/opt/git/shared-libraries in the Project Repository field. We’ll use Git as our Source Code Management system to include the library since it is stored in a Git repository.Utilities.) Afterwards. The gbuild line replaces the previous gradle line. your pipeline script should look like below .5') import static org. Now. Modify the pipeline script in your job to load the shared library. Save your changes to the system configuration. 'clean build' } } 11 Page © 2017 Brent Laster Brent Laster . go back to your simple-pipe job and select the Configure item. 7.

8. Save your changes and Build Now.grooy that has these contents: def call(String message) { input "${message}" } It allows us to wait on user input to proceed. ============================================================================================= END OF LAB ============================================================================================= Lab 4 .Loading Groovy Code Directly. def verifyCall = load("/home/diyuser2/shared-libraries/src/verify. and the Snippet Generator Purpose: In this lab. 2. There is a file in the ~/shared-libraries/src area named verify. We can also load groovy code directly and use it in our scripts. User Inputs. We’ll wrap this in a new stage section. we’ll see how to load Groovy code directly into our pipeline scripts. but before the closing bracket of the node definition. stage ('Verify') { // Now load 'verify.groovy'. 1. Add the following code after the ‘build’ stage.groovy") verifyCall("Please Verify the build") } 12 Page © 2017 Brent Laster Brent Laster . Timeouts. how to work with user inputs and timeouts and how to use the built-in Snippet Generator to help construct Groovy code for our script. Let’s add it to our script.

Save your changes and Build Now. When the build reaches this stage. 13 Page © 2017 Brent Laster Brent Laster . if you hover over the box in the Verify section. You will now have a new stage Verify that shows up in the stage output view. 4. you’ll see the process waiting for you to tell it to proceed or abort ( via clicking on one of the links). you’ll see the pop-up for you to tell it to Proceed or Abort. 3. if you look at the console output. As well.

select “timeout: Enforce time limit” For the Timeout value. 14 Page © 2017 Brent Laster Brent Laster . enter 5. 7. then scroll to the bottom and click on the Pipeline Syntax link. 6. Here you can select what you want to do and then have Jenkins generate the Groovy pipeline code for you. Note the failed status in the Stage View. 5. Go ahead and click the button or link to Abort the build. For the Unit value. To get our timeout code. we’ll use the Snippet Generator tool. select SECONDS 8. You’ll now be in the Snippet Generator page. select the following values: In the Sample Step dropdown. Click on the Generate Pipeline Script button to see the resulting code. To figure out the exact syntax. Click on the Configure button for the job. Let’s add a timeout to make sure the build doesn’t go on forever.

the basic text for the body of the function came from the Snippet Generator. timeout(time: 5."Finished") 15 } Page } // end node (already in pipeline) © 2017 Brent Laster Brent Laster . Save your changes and Build Now. ============================================================================================= END OF LAB ============================================================================================= Lab 5 . but before the ending bracket for the node definition.) 3. Copy and paste the timeout block lines around the verifyCall invocation in your pipeline script. For use in this workshop. You can use Back- >Configure to get back to the script page. For shared libraries. unit: 'SECONDS') { verifyCall("Please Verify the build") } 10.Using global functions and exception handling Purpose: In this lab. result) { // Add mail message from snippet generator here mail bcc: ''. we have a function named “mailUser” defined in ~/shared- libraries/vars/mailUser. subject: 'Build Status’" } 2. (We have changed some quoting and variables. (Substitute in whatever email address is appropriate. In our pipeline script. 9. we’ll add a “Notify” stage to send a basic message when the build is done. As an optional exercise. we can also define global functions under the “vars” subdirectory of our shared library repository. cc: ''. replyTo: ''. Let the job run to see the timeout pass and the job fail. (Jenkins is already configured globally to be able to send email.) Add the following stage at the end of your pipeline script after the Verify stage. body: "The current build

s result is ${result}.". from: ''. As suggested by the comment. The code in this function is: def call(user. you can go to the Snippet Generator (see Lab 4) and plug in the parts to create the basic “mail” line here.groovy.) } // end verify stage stage ('Notify') { mailUser(<email address in single quotes>. we’ll see how to reference global functions and one way to handle exception processing 1.

Add the “try {“ line after the node definition and the “catch” block after the “Verify” stage (and before the “Notify”stage) as shown below. Try it with selecting Proceed and also with selecting Abort or letting the timeout happen. How do we do this? We can handle this by adding a try/catch block around the other stages to catch the error and still allow the Notify stage to proceed. We want to be able to send the notification no matter what. we’d like Jenkins to automatically setup a project for our test branch. ============================================================================================= END OF LAB ============================================================================================= Lab 6 . so we will 16 need to access them there. we’ll see how to setup a multibranch pipeline project 1.Multibranch projects Purpose: In this lab. Save and Build Now. the Notify stage is never reached. (Note: It may be easier to set the timeout value to 10 seconds instead of 5 to give you time to find and click Proceed. 6.) 5. As well. Save and Build Now. we want to add some tests to our pipeline. 4. Notice that unless we select Proceed. node ('worker_node1') { try { stage('Source') { // for display purposes … verifyCall("Please Verify the build") } // end timeout } // end verify } // end try catch (err) { echo "Caught: ${err}" } stage ('Notify') 7. Page © 2017 Brent Laster Brent Laster . The tests are in the “test” branch of our repository. For this lab. Let the process timeout and note that the mail is now sent regardless.

Then cat the file. Notice the #!groovy declaration at the top. So we don’t need the import any longer. 3. To see it. The code for the gbuild2 function is: def call(args) { sh "${tool 'gradle32'}/bin/gradle ${args}" } This code is simpler than the gbuild code. this is defined in the vars subdirectory .specifically in in ~/shared-libraries/vars/gbuild2. Our cloned copy of our project . The reason for this is that we have switched from using the gbuild routine defined in a package in org. Also. Then we have our @Library annotation to load our shared library.conf.groovy extension to denote them as being groovy code. (More on that to come.as a marker in the branch. We have the “_” character there because it is required to have something after an annotation (@Library). cd ~/gradle-demo git checkout test cat Jenkinsfile 4. in a terminal cd to the ~/gradle-demo project and checkout the test branch. This is a best practice for Jenkinsfiles since they don’t have the . 2.Utilities to a global variable (function) named gbuild2. We’ve also changed our build step to use the call to gbuild2 instead of gbuild. i. Like the mailUser function we used in the last lab. It is followed by the “_” character instead of an import statement. Since global variables/functions already have the script context. ii. we don’t have to pass in the “script” object as we did for gbuild. we need to have a Jenkinsfile .similar to a build script . This file has a couple of changes that we need to talk through. To get Jenkins to recognize the branch in our project. iii.at ~/gradle-demo already has one.groovy. this is more portable between scripted and declarative pipelines.) 17 Page © 2017 Brent Laster Brent Laster .

5. we want Jenkins to automatically setup a project for this branch. uncomment the line (remove the leading //). Also. The function is available due to the “Workspace Cleanup” plugin being installed. We have to use the “step” syntax here because the plugin doesn’t provide a nicer way for pipeline scripts to call it. in the Branch Sources section. make sure that the Build Configuration Mode is set to “By Jenkinsfile”. notice the line “step([$class: ‘WsCleanup’])”. Currently the call to mailUser is commented out. This is a shortcut. This is telling Jenkins to wipe out (cleanup) the workspace before beginning the operation. If you do this. Then select OK. Now. v. This is specific to the node. If you want. Notice that this file has a different way of specifying how to get the source. then save the file and commit and push the updated file back into the repository. Give it a name of “demo-all” and select “Multibranch Pipeline” for the type. 7. Jenkins already knows the project and branch by virtue of the Jenkinsfile being in source control. available because. Finally. you can edit the file (gedit Jenkinsfile). You can leave the rest of the Branch Sources section as is. since this is a multibranch project. Select Git from the dropdown and enter our repository location (git@diyvb2:/opt/git/gradle-demo) for the Project Repository section. iv. 18 Page © 2017 Brent Laster Brent Laster . click on the “Add source” button. $ git add Jenkinsfile $ git commit -m “updated email address” $ git push origin test 6. OPTIONAL. and replace <your email address> with a valid email address (and change the “Finished” message if you want). It simply says checkout scm. From the dashboard. On the Configuration page. click on New Item.

we don’t need to add anything here. it can setup a build for it. Scroll down to the bottom of the page. 7. Now Save your changes. Jenkins now runs a branch indexing function looking for a Jenkinsfile in branches of the projects. 19 9. Page © 2017 Brent Laster Brent Laster . Notice the log output identifying the master and test branches and the Jenkinsfile in the test branch. then go back into demo-all and notice that Jenkins has created a new job for the test branch and run it. Where it finds one. Since we have already defined the Global Shared Libraries. Notice there is a Pipeline Libraries section there. 8. Click on the Up link in the top left.

We have two tests in our Gradle project: TestExample1. So our initial pass at a parallel block might look like this. we can reuse it here to call each test. ============================================================================================= END OF LAB ============================================================================================= Lab 7 . parallel ( worker2: { node ('worker_node2'){ // always run with a new workspace step([$class: 'WsCleanup']) gbuild2 '-D test. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) gbuild2 '-D test. For a simple demonstration of parallel execution. ) 3. Go ahead and copy and paste this code in for the test stage in your Jenkinsfile in the test branch of the gradle-demo project.test and TestExample2. we’ll run each of these tests on a separate node. 20 Page © 2017 Brent Laster Brent Laster .test.single=<Test Name> test.single=TestExample1 test' }}. gedit ~/gradle-demo/Jenkinsfile Your file should look like the one below ( plus your email address if you changed that in the optional step in the previous lab ). Since we earlier defined the gbuild2 function as running “gradle”. To run either of these independently. 1. We’ll wrap each call to gradle (via the gbuild2 function) in a different node.single=TestExample2 test' }}. we’ll see how to add code to a script to do parallel processing and run across multiple nodes. we can use the Gradle invocation -D test. Now we want to add the missing code for the Test stage. 2.Running in parallel and across multiple nodes Purpose: In this lab.

Go back and re-run the branch indexing for demo-all again. 6. select “Build Now”). Why is this? … [Pipeline] // stage [Pipeline] stage [Pipeline] { (Test) 21 [Pipeline] parallel [Pipeline] [worker2] { (Branch: worker2) Page [Pipeline] [worker3] { (Branch: worker3) © 2017 Brent Laster Brent Laster . Scroll down to find the section where the output for the “Test” stage starts. Select the “Scan Multibranch Pipeline Now” left menu item. It should have run again (if not. Save your changes. Click back to “demo-all”. Open up the Console Log output for the latest run. commit and push the file. Further down find the lines for “not found in root project” when worker2 and worker3 were trying to run the tests. 4. <Save changes to Jenkinsfile> git add Jenkinsfile git commit -m “updated for testing” git push origin test 5. stage. Now switch back to the “test” project under “demo-all”.

Add a line after the checkout scm command like this: stash name: 'test-sources'. (See listing below. The reason we can’t run the Test stage on worker2 ( worker-node2) is because the cloned content is only on worker- node1 (where the original node was running and where the source management clone was done). 8.) unstash ‘test-sources’ 22 When you have made the changes. Run with --stacktrace option to get the stack trace.862 secs [worker3] [worker3] FAILURE: Build failed with an exception. Edit the Jenkinsfile again. Add lines to do the “un-stashing” after the step call to cleanup the workspace in each node specification in the parallel block. [worker3] [worker3] * Try: [worker3] Run gradle tasks to get a list of available tasks. your file should look like this (with the new lines in bold).gradle. [Pipeline] [worker2] node [worker2] Running on worker_node2 in /home/jenkins2/worker_node2/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ [Pipeline] [worker3] node [worker3] Running on worker_node3 in /home/jenkins2/worker_node3/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ … [worker2] [worker2] FAILURE: Build failed with an exception. Fortunately.gradle file from the worker-node1 node. To begin using this. [worker3] [worker3] * What went wrong: [worker3] Task 'test' not found in root project 'demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ'. For the nodes where we are running the parallel tests. Run with --info or --debug option to get more log output. [worker2] [worker2] BUILD FAILED [worker2] [worker2] Total time: 3. includes: 'build. [worker2] [worker2] * What went wrong: [worker2] Task 'test' not found in root project 'demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ'. Jenkins provides a way to save and share content between nodes with the stash command. Run with --stacktrace option to get the stack trace. Page © 2017 Brent Laster Brent Laster .src/test/' 9. [worker3] [worker3] BUILD FAILED [worker3] … 7. we use the corresponding unstash command to recover the files needed from the original node. Run with --info or --debug option to get more log output. [worker2] [worker2] * Try: [worker2] Run gradle tasks to get a list of available tasks. we first need to stash the src directory (where the test content is) and the build.

includes: 'build.single=TestExample2 test' }}. stage.5')_ node ('worker_node1') { try { stage('Source') { // always run with a new workspace step([$class: 'WsCleanup']) checkout scm stash name: 'test-sources'.gradle. ) } } catch (err) { echo "Caught: ${err}" } stage ('Notify') { // mailUser('<your email address>'.src/test/' } stage('Build') { // Run the gradle build gbuild2 'clean build -x test' } stage ('Test') { // execute required unit tests in parallel parallel ( worker2: { node ('worker_node2'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. commit. "Finished") } } 9. Save your changes to the file. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. <Save changes to Jenkinsfile> git add Jenkinsfile git commit -m “updated for stashing” git push 23 Page © 2017 Brent Laster Brent Laster . and push it. #!groovy @Library('Utilities@1.single=TestExample1 test' }}.

[worker3] > There were failing tests. Eventually one will succeed and and one will fail (with a legitimate test failure). ============================================================================================= 24 END OF LAB Page ============================================================================================= © 2017 Brent Laster Brent Laster . Now. 10.java:10 [worker3] [worker3] 1 test completed.ComparisonFailure at TestExample2.junit. … [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Test) [Pipeline] parallel [Pipeline] [worker2] { (Branch: worker2) [Pipeline] [worker3] { (Branch: worker3) [Pipeline] [worker2] node [worker2] Running on worker_node2 in /home/jenkins2/worker_node2/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ [Pipeline] [worker3] node [Pipeline] [worker2] { [worker3] Running on worker_node3 in /home/jenkins2/worker_node3/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ … [worker2] [worker2] [worker2] BUILD SUCCESSFUL [worker2] [worker2] Total time: 26. go back and Build Now the test project. 1 failed [worker3] :test FAILED … [worker3] [worker3] FAILURE: Build failed with an exception.408 secs [Pipeline] [worker2] } [Pipeline] [worker2] // node [Pipeline] [worker2] } [worker3] :compileJava UP-TO-DATE [worker3] :processResources UP-TO-DATE [worker3] :classes UP-TO-DATE [worker3] :compileTestJava [worker3] :processTestResources UP-TO-DATE [worker3] :testClasses [worker3] :test [worker3] [worker3] [worker3] TestExample2 > example2 FAILED [worker3] org. [worker3] [worker3] * What went wrong: [worker3] Execution failed for task ':test'. In the Console Output. you should be able to see the two parallel tests being executed.

) Switch back to the terminal session. we’ll see how to convert a scripted pipeline to a declarative pipeline. (This will also be incorporated into our multibranch pipeline later on. We can also remove the Library block as we’ll do this in a different way in the declarative model. To begin the process. $ gedit Jenkinsfile 3. You should be in the /home/diyuser2/gradle-demo directory. Lab 8 . We need to first make some changes in the beginning section of the pipeline script. we’re going to convert the scripted pipeline in the Jenkinsfile from Lab 7 into a declarative pipeline. we can just replace that with the stages closure. In a declarative pipeline.Creating a Declarative Pipeline Purpose: In this lab. 25 Change the Page © 2017 Brent Laster Brent Laster . our collection of stages need to be wrapped in a stages closure. Then instead of the node definition here. Run the following command to create the new branch and switch to it. Now we want to create a new branch in our project so we can separate the declarative Jenkinsfile from the scripted one in branch test.5') } 5. because we are using the Groovy try-catch mechanism to wrap all the stages. To start to get a handle on how declarative pipelines are structured. In our scripted pipeline. Put this directive under the agent declaration from step 3 (under the agent { line and before the try { line). let’s add the load of our shared-library via the libraries directive. Change these lines: @Library('Utilities@1. We will keep the #!groovy as an indicator that this is a Jenkins script. But we need to wrap everything in our pipeline in a pipeline closure. we’ll create a new branch to work in. $ git checkout -b decl test 2. Next. Open the file in an editor. libraries { lib('Utilities@1. Now we’ll edit the Jenkinsfile in this branch and convert it from a scripted pipeline to a declarative pipeline. 1. we need an agent specification.5') _ node ('worker_node1') { to pipeline { agent{ label 'worker_node1'} 4.

add a steps closure around the statements.gradle. Within each individual stage section (except for the Notify one).src/test/' } } Make sure to add the steps {} closure in the Build and Test stages as well! 7. after the changes. Since we’re not adding any other directives in the stages. each set of individual steps in a stage needs to be enclosed in a steps closure. Next. you can just add “steps {“ after each “stage (…) {“ line and a closing bracket “}” at the end of each stage. For example. our first stage for Source would look like this (indention updated for clarity). Change the line for gbuild2 '-D test.single=TestExample2 test' to gbuild2 '-D test.5') } stages { stage('Source') { 6. let’s change the failing test in the ‘Test’ stage to one that will pass so we can see a successful run of the declarative pipeline.single=TestExample3 test' 26 Page © 2017 Brent Laster Brent Laster . includes: 'build. In the declarative structure. try { statement to be stages { The top part of your Jenkinsfile should now look like this (changed lines in bold): #!groovy pipeline { agent{ label 'worker_node1'} libraries { lib('Utilities@1. stage('Source') { steps { step([$class: 'WsCleanup']) checkout scm stash name: 'test-sources'.

"Finished") } 9. We’re going to replace the scripted catch section with a declarative post section. to: '<your email address>' } success { echo "Build succeeded" mail body: 'build succeeded'. subject: 'Build failed!'. except that you should have 27 your email address inserted for “<your email address>”. add the section below at the place in the file where you just deleted the lines in the last step. Now.) The lines below are the ones to remove. 8. Leave that ending bracket. Lastly. In the Jenkinsfile. Page © 2017 Brent Laster Brent Laster . Substitute in an email address where you can receive email for the “<your email address>” parts. Add these lines before the final closing bracket of the pipeline block. (Note there should still be a closing bracket after this from the original node closure we had. erase/delete the catch and notify blocks from the pipeline. to: '<your email address>' } } IMPORTANT: Don’t forget to put in a valid email address in the lines starting with “mail”! 9. catch (err) { echo "Caught: ${err}" } stage ('Notify') { // mailUser('<your email address>'. your pipeline in the Jenkinsfile should look like the one below. post { always { echo "Build stage complete" } failure { echo "Build failed" mail body: 'build failed'. in declarative syntax. subject: 'Build Succeeded'. Verify and then save the file as Jenkinsfile in the directory. After all of these changes. we have a post section that we can use to emulate the post-build actions of freestyle jobs.

subject: 'Build failed!'.5') } stages { stage('Source') { steps { step([$class: 'WsCleanup']) checkout scm stash name: 'test-sources'.gradle.src/test/' } } stage('Build') { // Run the gradle build steps { gbuild2 'clean build -x test' } } stage ('Test') { // execute required unit tests in parallel steps { parallel ( worker2: { node ('worker_node2'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. ) } } } // end stages post { always { echo "Build stage complete" } failure{ 28 echo "Build failed" Page mail body: 'build failed'. #!groovy pipeline { agent{ label 'worker_node1'} libraries { lib('Utilities@1.single=TestExample1 test' }}.single=TestExample3 test' }}. includes: 'build. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. to: '<your email address>' © 2017 Brent Laster Brent Laster .

} success { echo "Build succeeded" mail body: 'build succeeded'. commit. Open the Blue Ocean interface either by going to 29 http://localhost:8080/blue or by clicking the “Open Blue Ocean” button in the title bar. Page © 2017 Brent Laster Brent Laster . Switch back to Jenkins and go into the demo-all project (if not already there). $ git add Jenkinsfile $ git commit -m “Add declarative Jenkinsfile” $ git push origin decl 11.Using Blue Ocean Purpose: In this lab. Click on the “Scan Multibranch Pipeline Now” to generate a new job for the decl branch and run the script. go back to the dashboard (localhost:8080). It should succeed. In Jenkins. ============================================================================================= END OF LAB ============================================================================================= Lab 9 . to: '<your email address>' } } } // end pipeline 10. we’ll see how to use Jenkin’s new Blue Ocean interface 1. Now we want Jenkins to create a new project for it. subject: 'Build Succeeded'. After saving the file. add. We’ve now created a new branch in our multibranch setup. and push the updated Jenkinsfile (in branch decl).

Once the main Blue Ocean page finishes loading. Click on that symbol. For project types with subitems. This takes you to the Activity page for demo-all. You can click on them again to remove something from the favorites area. It allows you to see a list of defined projects and their health (the weather icon) and success/failure status. you can see the set of runs related to this project. this shows the list of branches associated with this multi-branch pipeline. 2. As expected. Click on some of the stars to see how the favorite action works. 3. ( This option ( clicking on Branches ) only works for multibranch projects. Click on the demo-all project. Find the row for our decl branch. we’ll take a closer look at our pipeline for the decl branch through it. 4. Now. 30 Page © 2017 Brent Laster Brent Laster . The star on the end is a way to add a favorite for quick reference at the top of the page. You can think of this page as being like the dashboard in the traditional interface. ) 5. Since Blue Ocean is optimized for declarative pipelines. Near the end of the row is a circle with an arrow in it. The PR column is for Pull Requests if we have any related to a project. If you hover over that. in the row above the list. click on the Branches item. Here. you should be on the Pipelines page. You can think of this like the page in the traditional interface that shows the runs for a project. ) The star is a toggle. you’ll see that it says “Run”. it may not be able to “favorite” them. (Note: This only works if Jenkins can determine what the “default” item in the project should be. A small box should pop up in the lower left corner with an “OPEN” link. Click on that (or click anywhere in the row for decl).

© 2017 Brent Laster Brent Laster . To do this. click on the circle at the end labeled worker2. Now. click on one of the circles representing a stage in the figure. When the pipeline completes the run. This is one of the parallel parts of our Test stage. and then click on the one of the steps listed in the bottom half of the page. along with the running log at the bottom. 7. It will look something like the picture below. Notice that Jenkins displays the part of the log for this part of the pipeline Clicking on Shell Script again collapses the log information. 31 Page Note that this opens up the configure page in a new tab. That will take you to the screen showing the pipeline executing. For example. Click on the Gear icon now to try this out. 6. Notice the circle shapes representing each stage as it progresses. Find the icon that looks like a gear in the upper left section of the page. take a look at the logs for one of the stages. That opens up a browser tab that puts you into the traditional Configure page for the project. click on the Shell Script item in the bottom section (under Steps .worker2).

9. Let’s look at a couple of other features in Blue Ocean. Enter git@diyvb2:/opt/git/gradle-demo in the Repository URL field. Click on the Adminstration link. (If not. We will just reference one on our local system to see how this is done. Then click on the back arrow in the browser to get back to the Blue Ocean interface. The idea is you would create a Jenkinsfile in a project stored in Git and that becomes the basis for your new pipeline. 10. Let’s see how that works. 9. we’ll just enter the location of the same Git repository we’ve been using. For the Repository URL. click on the Pipelines link at the top of the page. 32 Page © 2017 Brent Laster Brent Laster . Click on it to go to the Manage Jenkins page. You are first asked if your project is stored in Git or Github. Exit the log of this run by clicking on the X in the upper right corner. Switch back to the Blue Ocean tab for the decl job. Click on the button. The Administration link is like the Manage Jenkins link in the classic interface. This page is essentially the “New Item” interface for a project stored in Git.) Notice that there is a button here to create a New Pipeline. Then click Pipelines in the top row to get back to the Blue Ocean dashboard. You should be back on the Pipelines page (http://localhost:8080/blue/pipelines). 8. Select the Git option. 11.

Jenkins will setup a pipeline for the projects/branches that it finds with a Jenkinsfile in it. 12. select the jenkins2 credentials that we have already defined. the Create Pipeline screen should look like below. After filling in these fields. You’ll see the classic interface of the pipeline that was created. ============================================================================================= 33 END OF LAB Page © 2017 Brent Laster Brent Laster . 14. 15. Click on the symbol with the arrow in the square (next to Logout) to go back to the “classic” interface. Click on the Create Pipeline button to create the new pipeline. For the Credentials field. Then it will start a build for all of those projects/branches (eventually). 13.

For simplicity. $ cat /home/diyuser2/docker/Dockerfile 2. Then create the new branch and edit the Jenkinsfile. we’ll create a custom Docker image containing Gradle to use in our Gradle operations. we need to make a couple of changes for using Docker. we’ll create a new Docker agent to use for the build.Integrating Docker Purpose: In this lab. stage('Build') { agent { dockerfile { dir '/home/diyuser2/docker' 34 } Page } © 2017 Brent Laster Brent Laster . For some parts of the pipeline. run this command: $ docker images The image named gradle with tag 3. Add the lines shown in bold below to tell Jenkins to construct the Docker container built from the Dockerfile. To see it. we’ll use a ready-made version of this image already existing on your disk. Delete the lines below from your Jenkinsfile. libraries { lib('Utilities@1. we’ll work with Docker images in two ways. In this lab. In the Jenkinsfile. ============================================================================================= Lab 10 . First. We’ll create this image using an agent specification that takes a Dockerfile. Now. We have a Dockerfile already on disk. Note that they are after the Build stage closure . in a terminal session. To do this create a new branch based off of branch decl in our gradle-demo project.4. 1.5') } 5. 3. First. we’ll see how to use Docker in our pipeline. we’ll start with a copy of our declarative Jenkinsfile from the last lab and just update it to use Docker.1 is the one that contains Gradle for us to use.but before the steps closure. This agent will be created using the Dockerfile we looked at earlier. To start working on this version separately. since we are going to be using Docker images instead of library routines to run Gradle. we need to create a separate branch in our demo-all project with its own copy of the Jenkinsfile. $ git checkout -b docker decl $ gedit Jenkinsfile 4. Take a look at it with the following command in a terminal session. we can remove the libraries directive and information. Make sure you are in the gradle-demo project directory in a terminal session. in the Build stage.

1 image for this. we need to change our build command. it will map our workspace into the container (assuming it has access). We’ll wrap our build command in each parallel part in a “withDockerContainer” block.1” (indicating the version). It will create an image with Gradle in it .4. we will update the existing steps to just use a predefined instance of our image.1”.4. 7. that image is named “gradle” with a Docker tag of “3. worker2: { node ('worker_node2') { // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3.4.1') { gbuild2 ’ -D test. change the line gbuild2 'clean build -x test' to be sh 'gradle clean build -x test' 8. In the Build stage. in the steps block.1') { gbuild2 ‘-D test.based on the statements in the Dockerfile.single=TestExample1 test' } }} . This will do several things for us. This means add the lines in bold below. the mappings for worker2 and worker3 already have nodes specified. Then it will start a Docker container that runs the image. withDockerContainer takes the name of an image to run as an argument. As a reminder. And. steps { // Run the gradle build 6. then it will run any steps starting with “sh” (shell) inside the context of the container.4. Add a withDockerContainer closure around each build command in the Test stage. so we’ll use another approach. So we can refer to the image by the identifier “gradle:3. Since we will be running our Gradle build command inside the Docker agent’s container and not through the library anymore. Within the parallel step in the Test stage. Next. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3. Page © 2017 Brent Laster Brent Laster .single=TestExample3 test' 35 } }}. We will use the predefined gradle:3. We cannot create multiple agents in a step.4. Now. in the Test stage.

Change the start of the build lines in the Test stage from: gbuild2 ‘-D test. the main part of your Test stage should look like this (changed or added lines are in bold): worker2: { node ('worker_node2') { step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3.1') { sh 'gradle -D test. Switch back to Jenkins.1') { sh 'gradle -D test. Also.single 10. After these changes. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3. It should succeed. and are replacing that with Gradle running in the Docker container. 11. Click on the “Scan Multibranch Pipeline Now” to generate a new job for the docker branch and run the script. 9. Now we want Jenkins to create a new project for it. Switch to that project (if not already there).single=TestExample3 test' } }}. 12. This is because we removed the library reference that had the gbuild2 command. commit. We can use the gradle-demo multibranch project that got created in our last lab through Blue Ocean. Save your Jenkinsfile.4. 36 Page © 2017 Brent Laster Brent Laster . $ git add Jenkinsfile $ git commit -am “Update to use Docker” $ git push origin docker 13. We’ve created a new branch in our multibranch setup. we’ll need to change the gbuild2 commands to the same kind of sh commands we used above. Now add.single=TestExample1 test' } }} .single to sh ‘gradle -D test. and push the updated Jenkinsfile (in branch docker).4.

Name it whatever you like. you’ll see a field called Definition. 2. (Switch back to the dashboard at http://localhost:8080 and click on the New Item menu item. Click on that arrow and select Pipeline script from SCM. At the end of that field is an arrow to select entries from a list. we’ll see how to take a Jenkinsfile and include it in a native Jenkins pipeline project. scroll down to the text entry block for the code. Take a look at the console output for the run to see the construction of the Docker image and use of Docker in the Test stage.Including a Jenkinsfile back into a native Jenkins project Purpose: In this optional lab. 37 Page © 2017 Brent Laster Brent Laster . On the Pipeline section of the page. Once you are on the configuration page. You’l l now see a new field named SCM. 14. 1. In Jenkins. We’ll use the Docker project we just created in the previous lab as our example. create a new project from the dashboard. This will have Pipeline script in it by default. Select Git from the list in that field.) Select Pipeline for type of project. ============================================================================================= END OF LAB ============================================================================================= OPTIONAL Lab 11 . 3.

============================================================================================= END OF LAB ============================================================================================= 38 Page © 2017 Brent Laster Brent Laster . additional fields will show up on the screen.git Fill in the Branches field with docker 5. Fill in the Repository URL field with git@diyvb2:/opt/git/gradle-demo. Now Save the changes and select Build Now to build the pipeline. You can leave everything else as-is. Once you select Git. 4.

Related Interests

s result is ${result}.". from: ''. As suggested by the comment. The code in this function is: def call(user. you can go to the Snippet Generator (see Lab 4) and plug in the parts to create the basic “mail” line here.groovy.) } // end verify stage stage ('Notify') { mailUser(<email address in single quotes>. we’ll see how to reference global functions and one way to handle exception processing 1.

Add the “try {“ line after the node definition and the “catch” block after the “Verify” stage (and before the “Notify”stage) as shown below. Try it with selecting Proceed and also with selecting Abort or letting the timeout happen. How do we do this? We can handle this by adding a try/catch block around the other stages to catch the error and still allow the Notify stage to proceed. We want to be able to send the notification no matter what. we’d like Jenkins to automatically setup a project for our test branch. ============================================================================================= END OF LAB ============================================================================================= Lab 6 . so we will 16 need to access them there. we’ll see how to setup a multibranch pipeline project 1.Multibranch projects Purpose: In this lab. Save and Build Now. the Notify stage is never reached. (Note: It may be easier to set the timeout value to 10 seconds instead of 5 to give you time to find and click Proceed. 6.) 5. As well. Save and Build Now. we want to add some tests to our pipeline. 4. Notice that unless we select Proceed. node ('worker_node1') { try { stage('Source') { // for display purposes … verifyCall("Please Verify the build") } // end timeout } // end verify } // end try catch (err) { echo "Caught: ${err}" } stage ('Notify') 7. Page © 2017 Brent Laster Brent Laster . The tests are in the “test” branch of our repository. For this lab. Let the process timeout and note that the mail is now sent regardless.

Then cat the file. Notice the #!groovy declaration at the top. So we don’t need the import any longer. 3. To see it. The code for the gbuild2 function is: def call(args) { sh "${tool 'gradle32'}/bin/gradle ${args}" } This code is simpler than the gbuild code. this is defined in the vars subdirectory .specifically in in ~/shared-libraries/vars/gbuild2. Our cloned copy of our project . The reason for this is that we have switched from using the gbuild routine defined in a package in org. Also. Then we have our @Library annotation to load our shared library.conf.groovy extension to denote them as being groovy code. (More on that to come.as a marker in the branch. We have the “_” character there because it is required to have something after an annotation (@Library). cd ~/gradle-demo git checkout test cat Jenkinsfile 4. in a terminal cd to the ~/gradle-demo project and checkout the test branch. This is a best practice for Jenkinsfiles since they don’t have the . 2.Utilities to a global variable (function) named gbuild2. We’ve also changed our build step to use the call to gbuild2 instead of gbuild. i. Like the mailUser function we used in the last lab. It is followed by the “_” character instead of an import statement. Since global variables/functions already have the script context. ii. we don’t have to pass in the “script” object as we did for gbuild. we need to have a Jenkinsfile .similar to a build script . This file has a couple of changes that we need to talk through. To get Jenkins to recognize the branch in our project. iii.at ~/gradle-demo already has one.groovy. this is more portable between scripted and declarative pipelines.) 17 Page © 2017 Brent Laster Brent Laster .

5. we want Jenkins to automatically setup a project for this branch. uncomment the line (remove the leading //). Also. The function is available due to the “Workspace Cleanup” plugin being installed. We have to use the “step” syntax here because the plugin doesn’t provide a nicer way for pipeline scripts to call it. in the Branch Sources section. make sure that the Build Configuration Mode is set to “By Jenkinsfile”. notice the line “step([$class: ‘WsCleanup’])”. Currently the call to mailUser is commented out. This is a shortcut. This is telling Jenkins to wipe out (cleanup) the workspace before beginning the operation. If you do this. Then select OK. Now. v. This is specific to the node. If you want. Notice that this file has a different way of specifying how to get the source. then save the file and commit and push the updated file back into the repository. Give it a name of “demo-all” and select “Multibranch Pipeline” for the type. 7. Jenkins already knows the project and branch by virtue of the Jenkinsfile being in source control. available because. Finally. you can edit the file (gedit Jenkinsfile). You can leave the rest of the Branch Sources section as is. since this is a multibranch project. Select Git from the dropdown and enter our repository location (git@diyvb2:/opt/git/gradle-demo) for the Project Repository section. iv. 18 Page © 2017 Brent Laster Brent Laster . click on the “Add source” button. $ git add Jenkinsfile $ git commit -m “updated email address” $ git push origin test 6. OPTIONAL. and replace <your email address> with a valid email address (and change the “Finished” message if you want). It simply says checkout scm. From the dashboard. On the Configuration page. click on New Item.

we don’t need to add anything here. it can setup a build for it. Scroll down to the bottom of the page. 7. Now Save your changes. Jenkins now runs a branch indexing function looking for a Jenkinsfile in branches of the projects. 19 9. Page © 2017 Brent Laster Brent Laster . Notice the log output identifying the master and test branches and the Jenkinsfile in the test branch. then go back into demo-all and notice that Jenkins has created a new job for the test branch and run it. Where it finds one. Since we have already defined the Global Shared Libraries. Notice there is a Pipeline Libraries section there. 8. Click on the Up link in the top left.

We have two tests in our Gradle project: TestExample1. So our initial pass at a parallel block might look like this. we can reuse it here to call each test. ============================================================================================= END OF LAB ============================================================================================= Lab 7 . parallel ( worker2: { node ('worker_node2'){ // always run with a new workspace step([$class: 'WsCleanup']) gbuild2 '-D test. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) gbuild2 '-D test. For a simple demonstration of parallel execution. ) 3. Go ahead and copy and paste this code in for the test stage in your Jenkinsfile in the test branch of the gradle-demo project.test and TestExample2. we’ll run each of these tests on a separate node. 20 Page © 2017 Brent Laster Brent Laster .test.single=<Test Name> test.single=TestExample1 test' }}. gedit ~/gradle-demo/Jenkinsfile Your file should look like the one below ( plus your email address if you changed that in the optional step in the previous lab ). Since we earlier defined the gbuild2 function as running “gradle”. To run either of these independently. 1. We’ll wrap each call to gradle (via the gbuild2 function) in a different node.single=TestExample2 test' }}. we’ll see how to add code to a script to do parallel processing and run across multiple nodes. we can use the Gradle invocation -D test. Now we want to add the missing code for the Test stage. 2.Running in parallel and across multiple nodes Purpose: In this lab.

Go back and re-run the branch indexing for demo-all again. 6. select “Build Now”). Why is this? … [Pipeline] // stage [Pipeline] stage [Pipeline] { (Test) 21 [Pipeline] parallel [Pipeline] [worker2] { (Branch: worker2) Page [Pipeline] [worker3] { (Branch: worker3) © 2017 Brent Laster Brent Laster . Scroll down to find the section where the output for the “Test” stage starts. Select the “Scan Multibranch Pipeline Now” left menu item. It should have run again (if not. Save your changes. Click back to “demo-all”. Open up the Console Log output for the latest run. commit and push the file. Further down find the lines for “not found in root project” when worker2 and worker3 were trying to run the tests. 4. <Save changes to Jenkinsfile> git add Jenkinsfile git commit -m “updated for testing” git push origin test 5. stage. Now switch back to the “test” project under “demo-all”.

Add a line after the checkout scm command like this: stash name: 'test-sources'. (See listing below. The reason we can’t run the Test stage on worker2 ( worker-node2) is because the cloned content is only on worker- node1 (where the original node was running and where the source management clone was done). 8.) unstash ‘test-sources’ 22 When you have made the changes. Run with --stacktrace option to get the stack trace.862 secs [worker3] [worker3] FAILURE: Build failed with an exception. Edit the Jenkinsfile again. Add lines to do the “un-stashing” after the step call to cleanup the workspace in each node specification in the parallel block. [worker3] [worker3] * Try: [worker3] Run gradle tasks to get a list of available tasks. your file should look like this (with the new lines in bold).gradle. [Pipeline] [worker2] node [worker2] Running on worker_node2 in /home/jenkins2/worker_node2/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ [Pipeline] [worker3] node [worker3] Running on worker_node3 in /home/jenkins2/worker_node3/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ … [worker2] [worker2] FAILURE: Build failed with an exception. Fortunately.gradle file from the worker-node1 node. To begin using this. [worker3] [worker3] * What went wrong: [worker3] Task 'test' not found in root project 'demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ'. For the nodes where we are running the parallel tests. Run with --info or --debug option to get more log output. [worker2] [worker2] BUILD FAILED [worker2] [worker2] Total time: 3. includes: 'build. [worker2] [worker2] * What went wrong: [worker2] Task 'test' not found in root project 'demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ'. Jenkins provides a way to save and share content between nodes with the stash command. Run with --stacktrace option to get the stack trace. Page © 2017 Brent Laster Brent Laster .src/test/' 9. [worker3] [worker3] BUILD FAILED [worker3] … 7. we use the corresponding unstash command to recover the files needed from the original node. Run with --info or --debug option to get more log output. [worker2] [worker2] * Try: [worker2] Run gradle tasks to get a list of available tasks. we first need to stash the src directory (where the test content is) and the build.

includes: 'build.single=TestExample2 test' }}. stage.5')_ node ('worker_node1') { try { stage('Source') { // always run with a new workspace step([$class: 'WsCleanup']) checkout scm stash name: 'test-sources'.gradle. ) } } catch (err) { echo "Caught: ${err}" } stage ('Notify') { // mailUser('<your email address>'.src/test/' } stage('Build') { // Run the gradle build gbuild2 'clean build -x test' } stage ('Test') { // execute required unit tests in parallel parallel ( worker2: { node ('worker_node2'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. commit. "Finished") } } 9. Save your changes to the file. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. <Save changes to Jenkinsfile> git add Jenkinsfile git commit -m “updated for stashing” git push 23 Page © 2017 Brent Laster Brent Laster . and push it. #!groovy @Library('Utilities@1.single=TestExample1 test' }}.

[worker3] > There were failing tests. Eventually one will succeed and and one will fail (with a legitimate test failure). ============================================================================================= 24 END OF LAB Page ============================================================================================= © 2017 Brent Laster Brent Laster . Now. 10.java:10 [worker3] [worker3] 1 test completed.ComparisonFailure at TestExample2.junit. … [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Test) [Pipeline] parallel [Pipeline] [worker2] { (Branch: worker2) [Pipeline] [worker3] { (Branch: worker3) [Pipeline] [worker2] node [worker2] Running on worker_node2 in /home/jenkins2/worker_node2/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ [Pipeline] [worker3] node [Pipeline] [worker2] { [worker3] Running on worker_node3 in /home/jenkins2/worker_node3/workspace/demo-all_test- ZQC7KCTZRKI2O5V23U5SXILJOWC6TUBFMWH2SZ3ND747GW7SHEKQ … [worker2] [worker2] [worker2] BUILD SUCCESSFUL [worker2] [worker2] Total time: 26. go back and Build Now the test project. 1 failed [worker3] :test FAILED … [worker3] [worker3] FAILURE: Build failed with an exception.408 secs [Pipeline] [worker2] } [Pipeline] [worker2] // node [Pipeline] [worker2] } [worker3] :compileJava UP-TO-DATE [worker3] :processResources UP-TO-DATE [worker3] :classes UP-TO-DATE [worker3] :compileTestJava [worker3] :processTestResources UP-TO-DATE [worker3] :testClasses [worker3] :test [worker3] [worker3] [worker3] TestExample2 > example2 FAILED [worker3] org. [worker3] [worker3] * What went wrong: [worker3] Execution failed for task ':test'. In the Console Output. you should be able to see the two parallel tests being executed.

) Switch back to the terminal session. we’ll see how to convert a scripted pipeline to a declarative pipeline. (This will also be incorporated into our multibranch pipeline later on. We can also remove the Library block as we’ll do this in a different way in the declarative model. To begin the process. $ gedit Jenkinsfile 3. You should be in the /home/diyuser2/gradle-demo directory. Lab 8 . We need to first make some changes in the beginning section of the pipeline script. we’re going to convert the scripted pipeline in the Jenkinsfile from Lab 7 into a declarative pipeline. we can just replace that with the stages closure. In a declarative pipeline.Creating a Declarative Pipeline Purpose: In this lab. 25 Change the Page © 2017 Brent Laster Brent Laster . our collection of stages need to be wrapped in a stages closure. Then instead of the node definition here. Run the following command to create the new branch and switch to it. Now we want to create a new branch in our project so we can separate the declarative Jenkinsfile from the scripted one in branch test.5') } 5. because we are using the Groovy try-catch mechanism to wrap all the stages. To start to get a handle on how declarative pipelines are structured. In our scripted pipeline. Put this directive under the agent declaration from step 3 (under the agent { line and before the try { line). let’s add the load of our shared-library via the libraries directive. Change these lines: @Library('Utilities@1. We will keep the #!groovy as an indicator that this is a Jenkins script. But we need to wrap everything in our pipeline in a pipeline closure. we’ll create a new branch to work in. $ git checkout -b decl test 2. Next. Open the file in an editor. libraries { lib('Utilities@1. Now we’ll edit the Jenkinsfile in this branch and convert it from a scripted pipeline to a declarative pipeline. 1. we need an agent specification.5') _ node ('worker_node1') { to pipeline { agent{ label 'worker_node1'} 4.

add a steps closure around the statements.gradle. Within each individual stage section (except for the Notify one).src/test/' } } Make sure to add the steps {} closure in the Build and Test stages as well! 7. after the changes. Since we’re not adding any other directives in the stages. each set of individual steps in a stage needs to be enclosed in a steps closure. Next. you can just add “steps {“ after each “stage (…) {“ line and a closing bracket “}” at the end of each stage. For example. our first stage for Source would look like this (indention updated for clarity). Change the line for gbuild2 '-D test.single=TestExample2 test' to gbuild2 '-D test.5') } stages { stage('Source') { 6. let’s change the failing test in the ‘Test’ stage to one that will pass so we can see a successful run of the declarative pipeline.single=TestExample3 test' 26 Page © 2017 Brent Laster Brent Laster . includes: 'build. In the declarative structure. try { statement to be stages { The top part of your Jenkinsfile should now look like this (changed lines in bold): #!groovy pipeline { agent{ label 'worker_node1'} libraries { lib('Utilities@1. stage('Source') { steps { step([$class: 'WsCleanup']) checkout scm stash name: 'test-sources'.

"Finished") } 9. We’re going to replace the scripted catch section with a declarative post section. to: '<your email address>' } success { echo "Build succeeded" mail body: 'build succeeded'. subject: 'Build failed!'. except that you should have 27 your email address inserted for “<your email address>”. add the section below at the place in the file where you just deleted the lines in the last step. Now.) The lines below are the ones to remove. 8. Leave that ending bracket. Lastly. In the Jenkinsfile. Page © 2017 Brent Laster Brent Laster . Substitute in an email address where you can receive email for the “<your email address>” parts. Add these lines before the final closing bracket of the pipeline block. (Note there should still be a closing bracket after this from the original node closure we had. erase/delete the catch and notify blocks from the pipeline. to: '<your email address>' } } IMPORTANT: Don’t forget to put in a valid email address in the lines starting with “mail”! 9. catch (err) { echo "Caught: ${err}" } stage ('Notify') { // mailUser('<your email address>'. your pipeline in the Jenkinsfile should look like the one below. post { always { echo "Build stage complete" } failure { echo "Build failed" mail body: 'build failed'. in declarative syntax. subject: 'Build Succeeded'. Verify and then save the file as Jenkinsfile in the directory. After all of these changes. we have a post section that we can use to emulate the post-build actions of freestyle jobs.

subject: 'Build failed!'.5') } stages { stage('Source') { steps { step([$class: 'WsCleanup']) checkout scm stash name: 'test-sources'.gradle.src/test/' } } stage('Build') { // Run the gradle build steps { gbuild2 'clean build -x test' } } stage ('Test') { // execute required unit tests in parallel steps { parallel ( worker2: { node ('worker_node2'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. ) } } } // end stages post { always { echo "Build stage complete" } failure{ 28 echo "Build failed" Page mail body: 'build failed'. #!groovy pipeline { agent{ label 'worker_node1'} libraries { lib('Utilities@1.single=TestExample1 test' }}.single=TestExample3 test' }}. includes: 'build. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' gbuild2 '-D test. to: '<your email address>' © 2017 Brent Laster Brent Laster .

} success { echo "Build succeeded" mail body: 'build succeeded'. commit. Open the Blue Ocean interface either by going to 29 http://localhost:8080/blue or by clicking the “Open Blue Ocean” button in the title bar. Page © 2017 Brent Laster Brent Laster . Switch back to Jenkins and go into the demo-all project (if not already there). $ git add Jenkinsfile $ git commit -m “Add declarative Jenkinsfile” $ git push origin decl 11.Using Blue Ocean Purpose: In this lab. Click on the “Scan Multibranch Pipeline Now” to generate a new job for the decl branch and run the script. go back to the dashboard (localhost:8080). It should succeed. In Jenkins. ============================================================================================= END OF LAB ============================================================================================= Lab 9 . to: '<your email address>' } } } // end pipeline 10. we’ll see how to use Jenkin’s new Blue Ocean interface 1. Now we want Jenkins to create a new project for it. subject: 'Build Succeeded'. After saving the file. add. We’ve now created a new branch in our multibranch setup. and push the updated Jenkinsfile (in branch decl).

Once the main Blue Ocean page finishes loading. Click on that symbol. For project types with subitems. This takes you to the Activity page for demo-all. You can click on them again to remove something from the favorites area. It allows you to see a list of defined projects and their health (the weather icon) and success/failure status. you can see the set of runs related to this project. this shows the list of branches associated with this multi-branch pipeline. 2. As expected. Click on some of the stars to see how the favorite action works. 3. ( This option ( clicking on Branches ) only works for multibranch projects. Click on the demo-all project. Find the row for our decl branch. we’ll take a closer look at our pipeline for the decl branch through it. 4. Now. 30 Page © 2017 Brent Laster Brent Laster . The star on the end is a way to add a favorite for quick reference at the top of the page. You can think of this page as being like the dashboard in the traditional interface. ) 5. Since Blue Ocean is optimized for declarative pipelines. Near the end of the row is a circle with an arrow in it. The PR column is for Pull Requests if we have any related to a project. If you hover over that. in the row above the list. click on the Branches item. Here. you should be on the Pipelines page. You can think of this like the page in the traditional interface that shows the runs for a project. ) The star is a toggle. you’ll see that it says “Run”. it may not be able to “favorite” them. (Note: This only works if Jenkins can determine what the “default” item in the project should be. A small box should pop up in the lower left corner with an “OPEN” link. Click on that (or click anywhere in the row for decl).

© 2017 Brent Laster Brent Laster . To do this. click on the circle at the end labeled worker2. Now. click on one of the circles representing a stage in the figure. When the pipeline completes the run. This is one of the parallel parts of our Test stage. and then click on the one of the steps listed in the bottom half of the page. along with the running log at the bottom. 7. It will look something like the picture below. Notice that Jenkins displays the part of the log for this part of the pipeline Clicking on Shell Script again collapses the log information. 31 Page Note that this opens up the configure page in a new tab. That will take you to the screen showing the pipeline executing. For example. Click on the Gear icon now to try this out. 6. Notice the circle shapes representing each stage as it progresses. Find the icon that looks like a gear in the upper left section of the page. take a look at the logs for one of the stages. That opens up a browser tab that puts you into the traditional Configure page for the project. click on the Shell Script item in the bottom section (under Steps .worker2).

9. Let’s look at a couple of other features in Blue Ocean. Enter git@diyvb2:/opt/git/gradle-demo in the Repository URL field. Click on the Adminstration link. (If not. We will just reference one on our local system to see how this is done. Then click on the back arrow in the browser to get back to the Blue Ocean interface. The idea is you would create a Jenkinsfile in a project stored in Git and that becomes the basis for your new pipeline. 10. Let’s see how that works. 9. we’ll just enter the location of the same Git repository we’ve been using. For the Repository URL. click on the Pipelines link at the top of the page. 32 Page © 2017 Brent Laster Brent Laster . Click on it to go to the Manage Jenkins page. You are first asked if your project is stored in Git or Github. Exit the log of this run by clicking on the X in the upper right corner. Switch back to the Blue Ocean tab for the decl job. Click on the button. The Administration link is like the Manage Jenkins link in the classic interface. This page is essentially the “New Item” interface for a project stored in Git.) Notice that there is a button here to create a New Pipeline. Then click Pipelines in the top row to get back to the Blue Ocean dashboard. You should be back on the Pipelines page (http://localhost:8080/blue/pipelines). 8. Select the Git option. 11.

Jenkins will setup a pipeline for the projects/branches that it finds with a Jenkinsfile in it. 12. select the jenkins2 credentials that we have already defined. the Create Pipeline screen should look like below. After filling in these fields. You’ll see the classic interface of the pipeline that was created. ============================================================================================= 33 END OF LAB Page © 2017 Brent Laster Brent Laster . 14. 15. Click on the symbol with the arrow in the square (next to Logout) to go back to the “classic” interface. Click on the Create Pipeline button to create the new pipeline. For the Credentials field. Then it will start a build for all of those projects/branches (eventually). 13.

For simplicity. $ cat /home/diyuser2/docker/Dockerfile 2. Then create the new branch and edit the Jenkinsfile. we’ll create a custom Docker image containing Gradle to use in our Gradle operations. we need to make a couple of changes for using Docker. we’ll create a new Docker agent to use for the build.Integrating Docker Purpose: In this lab. stage('Build') { agent { dockerfile { dir '/home/diyuser2/docker' 34 } Page } © 2017 Brent Laster Brent Laster . For some parts of the pipeline. run this command: $ docker images The image named gradle with tag 3. Add the lines shown in bold below to tell Jenkins to construct the Docker container built from the Dockerfile. To see it. we’ll use a ready-made version of this image already existing on your disk. Delete the lines below from your Jenkinsfile. libraries { lib('Utilities@1. we’ll work with Docker images in two ways. In this lab. In the Jenkinsfile. ============================================================================================= Lab 10 . First. We’ll create this image using an agent specification that takes a Dockerfile. Now. We have a Dockerfile already on disk. Note that they are after the Build stage closure . in a terminal session. To do this create a new branch based off of branch decl in our gradle-demo project.4. 1.5') } 5. 3. First. we’ll see how to use Docker in our pipeline. we’ll start with a copy of our declarative Jenkinsfile from the last lab and just update it to use Docker.1 is the one that contains Gradle for us to use.but before the steps closure. This agent will be created using the Dockerfile we looked at earlier. To start working on this version separately. since we are going to be using Docker images instead of library routines to run Gradle. we need to create a separate branch in our demo-all project with its own copy of the Jenkinsfile. $ git checkout -b docker decl $ gedit Jenkinsfile 4. Take a look at it with the following command in a terminal session. we can remove the libraries directive and information. Make sure you are in the gradle-demo project directory in a terminal session. in the Build stage.

1 image for this. we need to change our build command. it will map our workspace into the container (assuming it has access). We’ll wrap our build command in each parallel part in a “withDockerContainer” block.1” (indicating the version). It will create an image with Gradle in it .4. we will update the existing steps to just use a predefined instance of our image.1”.4. 7. that image is named “gradle” with a Docker tag of “3. worker2: { node ('worker_node2') { // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3.4.1') { gbuild2 ’ -D test. change the line gbuild2 'clean build -x test' to be sh 'gradle clean build -x test' 8. In the Build stage. in the steps block.1') { gbuild2 ‘-D test.based on the statements in the Dockerfile.single=TestExample1 test' } }} . This will do several things for us. This means add the lines in bold below. the mappings for worker2 and worker3 already have nodes specified. Then it will start a Docker container that runs the image. withDockerContainer takes the name of an image to run as an argument. As a reminder. And. steps { // Run the gradle build 6. then it will run any steps starting with “sh” (shell) inside the context of the container.4. Add a withDockerContainer closure around each build command in the Test stage. so we’ll use another approach. So we can refer to the image by the identifier “gradle:3. Since we will be running our Gradle build command inside the Docker agent’s container and not through the library anymore. Within the parallel step in the Test stage. Next. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3. Page © 2017 Brent Laster Brent Laster .single=TestExample3 test' 35 } }}. We will use the predefined gradle:3. We cannot create multiple agents in a step.4. Now. in the Test stage.

Change the start of the build lines in the Test stage from: gbuild2 ‘-D test. the main part of your Test stage should look like this (changed or added lines are in bold): worker2: { node ('worker_node2') { step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3.1') { sh 'gradle -D test. Switch back to Jenkins.1') { sh 'gradle -D test. Also.single 10. After these changes. worker3: { node ('worker_node3'){ // always run with a new workspace step([$class: 'WsCleanup']) unstash 'test-sources' withDockerContainer('gradle:3. It should succeed. and are replacing that with Gradle running in the Docker container. 11. Click on the “Scan Multibranch Pipeline Now” to generate a new job for the docker branch and run the script. 9. Now we want Jenkins to create a new project for it. Switch to that project (if not already there).single=TestExample3 test' } }}. 12. This is because we removed the library reference that had the gbuild2 command. commit. We can use the gradle-demo multibranch project that got created in our last lab through Blue Ocean. Save your Jenkinsfile.4. 36 Page © 2017 Brent Laster Brent Laster . $ git add Jenkinsfile $ git commit -am “Update to use Docker” $ git push origin docker 13. We’ve created a new branch in our multibranch setup. we’ll need to change the gbuild2 commands to the same kind of sh commands we used above. Now add.single=TestExample1 test' } }} .single to sh ‘gradle -D test. and push the updated Jenkinsfile (in branch docker).4.

Name it whatever you like. you’ll see a field called Definition. 2. (Switch back to the dashboard at http://localhost:8080 and click on the New Item menu item. Click on that arrow and select Pipeline script from SCM. At the end of that field is an arrow to select entries from a list. we’ll see how to take a Jenkinsfile and include it in a native Jenkins pipeline project. scroll down to the text entry block for the code. Take a look at the console output for the run to see the construction of the Docker image and use of Docker in the Test stage.Including a Jenkinsfile back into a native Jenkins project Purpose: In this optional lab. 37 Page © 2017 Brent Laster Brent Laster . On the Pipeline section of the page. Once you are on the configuration page. You’l l now see a new field named SCM. 14. 1. In Jenkins. We’ll use the Docker project we just created in the previous lab as our example. create a new project from the dashboard. This will have Pipeline script in it by default. Select Git from the list in that field.) Select Pipeline for type of project. ============================================================================================= END OF LAB ============================================================================================= OPTIONAL Lab 11 . 3.

============================================================================================= END OF LAB ============================================================================================= 38 Page © 2017 Brent Laster Brent Laster . additional fields will show up on the screen.git Fill in the Branches field with docker 5. Fill in the Repository URL field with git@diyvb2:/opt/git/gradle-demo. Now Save the changes and select Build Now to build the pipeline. You can leave everything else as-is. Once you select Git. 4.

","doc_promotions_enabled":false,"static_promo_banner_cta_url":""},"eligible_for_exclusive_trial_roadblock":false,"eligible_for_seo_roadblock":false,"exclusive_free_trial_roadblock_props_path":"/doc-page/exclusive-free-trial-props/354232669","flashes":[],"footer_props":{"urls":{"about":"/about","press":"/press","blog":"http://literally.scribd.com/","careers":"/careers","contact":"/contact","plans_landing":"/subscribe","referrals":"/referrals?source=footer","giftcards":"/giftcards","faq":"/faq","accessibility":"/accessibility-policy","faq_paths":{"accounts":"https://support.scribd.com/hc/sections/202246346","announcements":"https://support.scribd.com/hc/sections/202246066","copyright":"https://support.scribd.com/hc/sections/202246086","downloading":"https://support.scribd.com/hc/articles/210135046","publishing":"https://support.scribd.com/hc/sections/202246366","reading":"https://support.scribd.com/hc/sections/202246406","selling":"https://support.scribd.com/hc/sections/202246326","store":"https://support.scribd.com/hc/sections/202246306","status":"https://support.scribd.com/hc/en-us/articles/360001202872","terms":"https://support.scribd.com/hc/sections/202246126","writing":"https://support.scribd.com/hc/sections/202246366","adchoices":"https://support.scribd.com/hc/articles/210129366","paid_features":"https://support.scribd.com/hc/sections/202246306","failed_uploads":"https://support.scribd.com/hc/en-us/articles/210134586-Troubleshooting-uploads-and-conversions","copyright_infringement":"https://support.scribd.com/hc/en-us/articles/210128946-DMCA-copyright-infringement-takedown-notification-policy","end_user_license":"https://support.scribd.com/hc/en-us/articles/210129486","terms_of_use":"https://support.scribd.com/hc/en-us/articles/210129326-General-Terms-of-Use"},"publishers":"/publishers","static_terms":"/terms","static_privacy":"/privacy","copyright":"/copyright","ios_app":"https://itunes.apple.com/us/app/scribd-worlds-largest-online/id542557212?mt=8&uo=4&at=11lGEE","android_app":"https://play.google.com/store/apps/details?id=com.scribd.app.reader0&hl=en","books":"/books","sitemap":"/directory"}},"global_nav_props":{"header_props":{"logo_src":"/images/landing/home2_landing/scribd_logo_horiz_small.svg","root_url":"https://www.scribd.com/","search_term":"","small_logo_src":"/images/logos/scribd_s_logo.png","uploads_url":"/upload-document","search_props":{"redirect_to_app":true,"search_url":"/search","query":"","search_page":false}},"user_menu_props":null,"sidebar_props":{"urls":{"bestsellers":"https://www.scribd.com/bestsellers","home":"https://www.scribd.com/","saved":"/saved","subscribe":"/archive/pmp_checkout?doc=354232669&metadata=%7B%22context%22%3A%22pmp%22%2C%22action%22%3A%22start_trial%22%2C%22logged_in%22%3Afalse%2C%22platform%22%3A%22web%22%7D","top_charts":"/bestsellers","upload":"https://www.scribd.com/upload-document"},"categories":{"book":{"icon":"icon-ic_book","icon_filled":"icon-ic_book_fill","url":"https://www.scribd.com/books","name":"Books","type":"book"},"news":{"icon":"icon-ic_articles","icon_filled":"icon-ic_articles_fill","url":"https://www.scribd.com/news","name":"News","type":"news"},"audiobook":{"icon":"icon-ic_audiobook","icon_filled":"icon-ic_audiobook_fill","url":"https://www.scribd.com/audiobooks","name":"Audiobooks","type":"audiobook"},"magazine":{"icon":"icon-ic_magazine","icon_filled":"icon-ic_magazine_fill","url":"https://www.scribd.com/magazines","name":"Magazines","type":"magazine"},"document":{"icon":"icon-ic_document","icon_filled":"icon-ic_document_fill","url":"https://www.scribd.com/docs","name":"Documents","type":"document"},"sheet_music":{"icon":"icon-ic_songbook","icon_filled":"icon-ic_songbook_fill","url":"https://www.scribd.com/sheetmusic","name":"Sheet Music","type":"sheet_music"}},"categories_array":["mixed","book","audiobook","magazine","news","document","sheet_music"],"selected_content_type":"mixed","username":"","search_overlay_props":{"search_input_props":{"focused":false,"keep_suggestions_on_blur":false}}}},"recommenders":{"related_titles_recommender":{"ids":[236228839,103589217,41379469,164806171,75448972,335233758,110385582,126544940,186754315,55618817,78387508,368677395,2262633,98911804,292048739,272846021,126216902,119112271,374841289,47232525,76947113,49842413,148063266,20736661,7091814,318162540,294219765,105279936,317341964,218639828,354232228,354232521,354232227,161030937],"title_link":null,"title":null,"track_opts":{"compilation_id":"6QCoSZpSlpQ/bcP7MIYiwkKj6b4=","module_id":"RrXiUswCi43z4PulerljNtuuXRU=","widget_name":"right sidebar","track_id":"flattened_recommender"}},"footer_recommenders":{"recommenders":[{"ids":[236228839,103589217,41379469,164806171,75448972,335233758,110385582,126544940,186754315,55618817,78387508,368677395,2262633,98911804,292048739,272846021,126216902,119112271,374841289,47232525,76947113,49842413,148063266,20736661,7091814,318162540,294219765,105279936,317341964,218639828],"title_link":null,"title":"Documents Similar To m2j2labs","track_opts":{"compilation_id":"6QCoSZpSlpQ/bcP7MIYiwkKj6b4=","module_id":"vOtFgHQzdzxPlX4vl0UiuOMj734=","widget_name":"document_carousel"}},{"ids":[354232228,354232521,354232227,161030937],"title_link":null,"title":"More From Shubham Harnal","track_opts":{"compilation_id":"6QCoSZpSlpQ/bcP7MIYiwkKj6b4=","module_id":"TGD0LNa/+5WnxvbHmi+SUgSFu3M=","widget_name":"document_carousel"}}]},"seo_new_docs_recommenders":{"recommenders":[]},"documents":{"2262633":{"type":"document","id":2262633,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/2262633/108x144/8055fc15f3/1432482602?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/2262633/216x288/32742dad69/1432482602?v=1","title":"VisualSVN -Subversion for Visual Studio","short_title":"VisualSVN -Subversion for Visual Studio","author":"jishin","tracking":{"object_type":"document","object_id":2262633,"track":"flattened_recommender","doc_uuid":"2hlpn9Lfj9lfopzMcEbV9xxUFHY="},"url":"https://www.scribd.com/document/2262633/VisualSVN-Subversion-for-Visual-Studio"},"7091814":{"type":"document","id":7091814,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/7091814/108x144/317c1f6f58/1395169438?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/7091814/216x288/9d7888a78c/1395169438?v=1","title":"18 - Writing and Compiling Your Programs","short_title":"18 - Writing and Compiling Your Programs","author":"api-3747983","tracking":{"object_type":"document","object_id":7091814,"track":"flattened_recommender","doc_uuid":"fxYQHWUWFT76l55p77AeK1vqjm0="},"url":"https://www.scribd.com/document/7091814/18-Writing-and-Compiling-Your-Programs"},"20736661":{"type":"document","id":20736661,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/20736661/108x144/701f3c9f0c/1260225258?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/20736661/216x288/ec19eda076/1260225258?v=1","title":"This is Python Version 2.5.4 = ============================ Copyright (c) 2001,","short_title":"This is Python Version 2.5.4 = ============================ Copyright (c) 2001,","author":"bakasa","tracking":{"object_type":"document","object_id":20736661,"track":"flattened_recommender","doc_uuid":"GHe18WS5jd1guZGlviYSPGCP7s0="},"url":"https://www.scribd.com/document/20736661/This-is-Python-Version-2-5-4-Copyright-c-2001"},"41379469":{"type":"document","id":41379469,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/41379469/108x144/958250eb98/1289116177?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/41379469/216x288/1c2947d99d/1289116177?v=1","title":"slaa290","short_title":"slaa290","author":"aakashsbabu","tracking":{"object_type":"document","object_id":41379469,"track":"flattened_recommender","doc_uuid":"N3i8K9Ww7zedE9tFVyHrXH2HHms="},"url":"https://www.scribd.com/document/41379469/slaa290"},"47232525":{"type":"document","id":47232525,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/47232525/108x144/c9b9cca8f0/1295510271?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/47232525/216x288/c664affb65/1295510271?v=1","title":"jstl_core","short_title":"jstl_core","author":"GURUMS","tracking":{"object_type":"document","object_id":47232525,"track":"flattened_recommender","doc_uuid":"uWZGhbE+pyp+AdvaZqBGkXMAdp8="},"url":"https://www.scribd.com/presentation/47232525/jstl-core"},"49842413":{"type":"document","id":49842413,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/49842413/108x144/ffcbeb6222/1299058566?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/49842413/216x288/9985432844/1299058566?v=1","title":"WP-Hacking_and_protecting_Oracle_Database_Vault","short_title":"WP-Hacking_and_protecting_Oracle_Database_Vault","author":"Emmanuel Bulinda","tracking":{"object_type":"document","object_id":49842413,"track":"flattened_recommender","doc_uuid":"lQYawDZU+d1g7MU6hW1LC1v1Qr8="},"url":"https://www.scribd.com/document/49842413/WP-Hacking-and-protecting-Oracle-Database-Vault"},"55618817":{"type":"document","id":55618817,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/55618817/108x144/5d0fb3d142/1305637128?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/55618817/216x288/2d7d5b01a8/1305637128?v=1","title":"Eclipse Axis 2","short_title":"Eclipse Axis 2","author":"ttaaxx","tracking":{"object_type":"document","object_id":55618817,"track":"flattened_recommender","doc_uuid":"lYBpXPId8I4Tuvgb9yjMnsTjI2I="},"url":"https://www.scribd.com/document/55618817/Eclipse-Axis-2"},"75448972":{"type":"document","id":75448972,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/75448972/108x144/2b51793a16/1378955885?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/75448972/216x288/4082817e17/1378955885?v=1","title":" Helpinator Manual","short_title":" Helpinator Manual","author":"Iguodala Owie","tracking":{"object_type":"document","object_id":75448972,"track":"flattened_recommender","doc_uuid":"WHzCFUJLnLW2yQAUlzBudyPPujc="},"url":"https://www.scribd.com/document/75448972/Helpinator-Manual"},"76947113":{"type":"document","id":76947113,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/76947113/108x144/3501b4744f/1408797597?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/76947113/216x288/15f3f97162/1408797597?v=1","title":"tra","short_title":"tra","author":"Guillermo Garcia Martin","tracking":{"object_type":"document","object_id":76947113,"track":"flattened_recommender","doc_uuid":"CdZoUTdaHnqJ4HKziYwdL3N1f3k="},"url":"https://www.scribd.com/document/76947113/tra"},"78387508":{"type":"document","id":78387508,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/78387508/108x144/dd8e964acb/1326697748?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/78387508/216x288/1b6d39a49b/1326697748?v=1","title":"SCM(Final)","short_title":"SCM(Final)","author":"cparth1990","tracking":{"object_type":"document","object_id":78387508,"track":"flattened_recommender","doc_uuid":"khefplj8NtdueBFlxseCbWkxXls="},"url":"https://www.scribd.com/presentation/78387508/SCM-Final"},"98911804":{"type":"document","id":98911804,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/98911804/108x144/e6ca8a95c3/1420732249?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/98911804/216x288/4bdbed57a9/1420732249?v=1","title":"Sparx Enterprise Architect Guidelines","short_title":"Sparx Enterprise Architect Guidelines","author":"Pedro Humberto Ramirez Guzman","tracking":{"object_type":"document","object_id":98911804,"track":"flattened_recommender","doc_uuid":"M+ZG5O//Av+t48KypQJG7Ausv7I="},"url":"https://www.scribd.com/document/98911804/Sparx-Enterprise-Architect-Guidelines"},"103589217":{"type":"document","id":103589217,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/103589217/108x144/060e665fd3/1345650081?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/103589217/216x288/b5a36365a3/1345650081?v=1","title":"VCS","short_title":"VCS","author":"Reema Sawal","tracking":{"object_type":"document","object_id":103589217,"track":"flattened_recommender","doc_uuid":"cowiCtYVjNk4Vej5tm2bHNsmMMU="},"url":"https://www.scribd.com/presentation/103589217/VCS"},"105279936":{"type":"document","id":105279936,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/105279936/108x144/5d66e2318d/1417360376?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/105279936/216x288/d967d7f95d/1417360376?v=1","title":"Altium Designer - Schematic Library Editor","short_title":"Altium Designer - Schematic Library Editor","author":"nooriusef","tracking":{"object_type":"document","object_id":105279936,"track":"flattened_recommender","doc_uuid":"BIHAMbTGsIUQIyDuXZ8RGiS4Kww="},"url":"https://www.scribd.com/document/105279936/Altium-Designer-Schematic-Library-Editor"},"110385582":{"type":"document","id":110385582,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/110385582/108x144/b523fe62ec/1350532414?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/110385582/216x288/257db9555e/1350532414?v=1","title":"MELJUN CORTES Engr1a_engineering Drawing 1_rev 01","short_title":"MELJUN CORTES Engr1a_engineering Drawing 1_rev 01","author":"MELJUN CORTES, MBA,MPA","tracking":{"object_type":"document","object_id":110385582,"track":"flattened_recommender","doc_uuid":"VZvRqmt573uDGPWAKIv6+qVibNE="},"url":"https://www.scribd.com/document/110385582/MELJUN-CORTES-Engr1a-engineering-Drawing-1-rev-01"},"119112271":{"type":"document","id":119112271,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/119112271/108x144/ce12e43226/1372969320?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/119112271/216x288/a085b43911/1372969320?v=1","title":"An Overview of the SWI-Prolog Programming Environment","short_title":"An Overview of the SWI-Prolog Programming Environment","author":"Dragon1700","tracking":{"object_type":"document","object_id":119112271,"track":"flattened_recommender","doc_uuid":"t9HINcmK8wi1+wW1U6yJIuj4rps="},"url":"https://www.scribd.com/document/119112271/An-Overview-of-the-SWI-Prolog-Programming-Environment"},"126216902":{"type":"document","id":126216902,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/126216902/108x144/748d40e84e/1408623199?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/126216902/216x288/b0648ab8a0/1408623199?v=1","title":"Ko Fax Capture Developers Guide","short_title":"Ko Fax Capture Developers Guide","author":"miguelangel_mg","tracking":{"object_type":"document","object_id":126216902,"track":"flattened_recommender","doc_uuid":"6GD8FneYjBuNNNgs+/iY+eCdoRY="},"url":"https://www.scribd.com/document/126216902/Ko-Fax-Capture-Developers-Guide"},"126544940":{"type":"document","id":126544940,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/126544940/108x144/166232ee48/1406461589?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/126544940/216x288/c8ffcf4fac/1406461589?v=1","title":"Git With Eclipse (EGit) - Tutorial","short_title":"Git With Eclipse (EGit) - Tutorial","author":"raniendu","tracking":{"object_type":"document","object_id":126544940,"track":"flattened_recommender","doc_uuid":"EAvWM1zsyQbLkvDAwV5zu2NxvJo="},"url":"https://www.scribd.com/document/126544940/Git-With-Eclipse-EGit-Tutorial"},"148063266":{"type":"document","id":148063266,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/148063266/108x144/9384ee0281/1371338825?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/148063266/216x288/1d6f9864fc/1371338825?v=1","title":"C in 26","short_title":"C in 26","author":"Ralph Dede Joralphs","tracking":{"object_type":"document","object_id":148063266,"track":"flattened_recommender","doc_uuid":"EsQSg+3D5SRV9gTnh/4wpRM6eio="},"url":"https://www.scribd.com/document/148063266/C-in-26"},"161030937":{"type":"document","id":161030937,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/161030937/108x144/96339bfee2/1382992397?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/161030937/216x288/e3b19ac2c6/1382992397?v=1","title":"Hohner Harmonicas 2012 Eng","short_title":"Hohner Harmonicas 2012 Eng","author":"Shubham Harnal","tracking":{"object_type":"document","object_id":161030937,"track":"flattened_recommender","doc_uuid":"chFpX2emEYt/Cu+QVkbEXNxD49c="},"url":"https://www.scribd.com/document/161030937/Hohner-Harmonicas-2012-Eng"},"164806171":{"type":"document","id":164806171,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/164806171/108x144/f9fdab60f2/1426680961?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/164806171/216x288/03ddc6f3c7/1426680961?v=1","title":"Image Acquisition Toolbox Adaptor Kit 1","short_title":"Image Acquisition Toolbox Adaptor Kit 1","author":"Anonymous TVDaNPe","tracking":{"object_type":"document","object_id":164806171,"track":"flattened_recommender","doc_uuid":"RERj00iATv3cEM/Drh1/Z+wf8mc="},"url":"https://www.scribd.com/document/164806171/Image-Acquisition-Toolbox-Adaptor-Kit-1"},"186754315":{"type":"document","id":186754315,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/186754315/108x144/72ae63443f/1385319677?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/186754315/216x288/62989ae559/1385319677?v=1","title":"ETAP-TIP-005","short_title":"ETAP-TIP-005","author":"limres","tracking":{"object_type":"document","object_id":186754315,"track":"flattened_recommender","doc_uuid":"prxbQrIvcIdiO5OnefcZacKp+Gc="},"url":"https://www.scribd.com/document/186754315/ETAP-TIP-005"},"218639828":{"type":"document","id":218639828,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/218639828/108x144/a3c4a9e406/1397666075?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/218639828/216x288/3bacc426b9/1397666075?v=1","title":"Computer Programming","short_title":"Computer Programming","author":"Muhammad Usman Ghani","tracking":{"object_type":"document","object_id":218639828,"track":"flattened_recommender","doc_uuid":"Tu+rkKY4fMmgDik/QzbEWoWmous="},"url":"https://www.scribd.com/document/218639828/Computer-Programming"},"236228839":{"type":"document","id":236228839,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/236228839/108x144/a8a43e9a98/1427848263?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/236228839/216x288/2cae63c018/1427848263?v=1","title":"Ada Guide","short_title":"Ada Guide","author":"gem","tracking":{"object_type":"document","object_id":236228839,"track":"flattened_recommender","doc_uuid":"baNAdTno1BBL8PBFRIm/hm1GpaM="},"url":"https://www.scribd.com/document/236228839/Ada-Guide"},"272846021":{"type":"document","id":272846021,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/272846021/108x144/6f1e7b0b48/1438102003?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/272846021/216x288/2612d44b7a/1438102003?v=1","title":"Cs01 Into Framework Labs","short_title":"Cs01 Into Framework Labs","author":"Vincentius Yosephat Suryo","tracking":{"object_type":"document","object_id":272846021,"track":"flattened_recommender","doc_uuid":"WGFQp57nyqKR6w80ccr1OA5SZxA="},"url":"https://www.scribd.com/presentation/272846021/Cs01-Into-Framework-Labs"},"292048739":{"type":"document","id":292048739,"thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/292048739/108x144/a8ab5e26bc/1449651948?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/292048739/216x288/d1f28a71da/1449651948?v=1","title":"PunchMan-85","short_title":"PunchMan-85","author":"sssf-doboj","tracking":{"object_type":"document","object_id":292048739,"track":"flattened_recommender","doc_uuid":"goPFGvy+GOibPFe70U8EunjC3u0="},"url":"https://www.scribd.com/document/292048739/PunchMan-85"},"294219765":{"type":"document","id":294219765,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/294219765/108x144/27fafd76f2/1451402645?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/294219765/216x288/ae55f526fc/1451402645?v=1","title":"VBS","short_title":"VBS","author":"Vladan Dakic","tracking":{"object_type":"document","object_id":294219765,"track":"flattened_recommender","doc_uuid":"5iZPp4Tt37G9gX4HgTjLT1UhrUo="},"url":"https://www.scribd.com/document/294219765/VBS"},"317341964":{"type":"document","id":317341964,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/317341964/108x144/ed89807227/1467527145?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/317341964/216x288/013337f2ed/1467527145?v=1","title":"27","short_title":"27","author":"scribdir","tracking":{"object_type":"document","object_id":317341964,"track":"flattened_recommender","doc_uuid":"SWxQCYk45ZLTMmip6gxnJ4KtfNw="},"url":"https://www.scribd.com/document/317341964/27"},"318162540":{"type":"document","id":318162540,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/318162540/108x144/1dd77b06bb/1468393467?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/318162540/216x288/7e756673d7/1468393467?v=1","title":"Guide Troubleshooting","short_title":"Guide Troubleshooting","author":"Æshok IncreĐible King","tracking":{"object_type":"document","object_id":318162540,"track":"flattened_recommender","doc_uuid":"GEYSKRW+B4/RP/3yjQl28fPDA3U="},"url":"https://www.scribd.com/document/318162540/Guide-Troubleshooting"},"335233758":{"type":"document","id":335233758,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/335233758/108x144/682e166c05/1482954697?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/335233758/216x288/a7b61f7b9b/1482954697?v=1","title":"8e7398b5-5b7c-0010-82c7-eda71af511fa","short_title":"8e7398b5-5b7c-0010-82c7-eda71af511fa","author":"Richard Miller","tracking":{"object_type":"document","object_id":335233758,"track":"flattened_recommender","doc_uuid":"l5o1inrvvUxt6qydVwXOE8wxTjo="},"url":"https://www.scribd.com/document/335233758/8e7398b5-5b7c-0010-82c7-eda71af511fa"},"354232227":{"type":"document","id":354232227,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/354232227/108x144/b19519533b/1500523679?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/354232227/216x288/0eb8f74bad/1500523679?v=1","title":"Cdpj2 Setup","short_title":"Cdpj2 Setup","author":"Shubham Harnal","tracking":{"object_type":"document","object_id":354232227,"track":"flattened_recommender","doc_uuid":"LaeRIcYyp0A6s/sVcteAGcvFLi0="},"url":"https://www.scribd.com/document/354232227/Cdpj2-Setup"},"354232228":{"type":"document","id":354232228,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/354232228/108x144/8b2d7ed45a/1500523681?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/354232228/216x288/df26e9c04c/1500523681?v=1","title":"m2j2setup","short_title":"m2j2setup","author":"Shubham Harnal","tracking":{"object_type":"document","object_id":354232228,"track":"flattened_recommender","doc_uuid":"QaVaJG+9d66dBrhVrykGu+1Wnu8="},"url":"https://www.scribd.com/document/354232228/m2j2setup"},"354232521":{"type":"document","id":354232521,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/354232521/108x144/6cd9d82a96/1500523837?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/354232521/216x288/cbc4fe14e1/1500523837?v=1","title":"Jenkins Deploy Pipeline Labs","short_title":"Jenkins Deploy Pipeline Labs","author":"Shubham Harnal","tracking":{"object_type":"document","object_id":354232521,"track":"flattened_recommender","doc_uuid":"eqRrbWTozqMwCl9ZDCc2RRwiSLE="},"url":"https://www.scribd.com/document/354232521/Jenkins-Deploy-Pipeline-Labs"},"368677395":{"type":"document","id":368677395,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/368677395/108x144/9c7c26cf01/1515428335?v=1","retina_thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/368677395/216x288/105184587b/1515428335?v=1","title":"Vremena","short_title":"Vremena","author":"Dejan","tracking":{"object_type":"document","object_id":368677395,"track":"flattened_recommender","doc_uuid":"afRrfs6cPS7eG/Lw4poX+aGLZnY="},"url":"https://www.scribd.com/document/368677395/Vremena"},"374841289":{"type":"document","id":374841289,"thumb_url":"https://imgv2-1-f.scribdassets.com/img/document/374841289/108x144/1c481d8c06/1522039762?v=1","retina_thumb_url":"https://imgv2-2-f.scribdassets.com/img/document/374841289/216x288/85194b70cb/1522039762?v=1","title":"lec06","short_title":"lec06","author":"Hameem Ul Islam","tracking":{"object_type":"document","object_id":374841289,"track":"flattened_recommender","doc_uuid":"EaCvRendRTYCzytAvuWTHQ8OKsg="},"url":"https://www.scribd.com/document/374841289/lec06"}}},"seo_roadblock_props_path":"/doc-page/seo-roadblock-props/354232669","signup_context":null,"toolbar":{"search_path":"/search-4gen?allowed_pages=1%2C2%2C3&auth_token=DvyLnK7I%2BDcRbdCn%2FOViNP%2FJ5rE%3D&authenticity_token=OP2HdofTK1jNu2BR2Z9g9kep0g0RypTE%2FzX%2BxeWv8mTfAww7l%2F79s5SLWAGWeQUdRQkYr4tQ3RQI920bvbvQ7w%3D%3D&expires=1538340432&wordDocumentId=354232669&wordUploadId=361005406"},"renewal_nag_props":null}-->