diff --git a/labs/06_environment.md b/labs/06_environment.md index 17e34c3..13e524d 100644 --- a/labs/06_environment.md +++ b/labs/06_environment.md @@ -34,6 +34,41 @@ pipeline { } ``` +To add values to the path there is a special syntax + + environment { + PATH+MAVEN = '/path/to/maven' + } + + +The ``PATH+`` syntax specifies +that the given value should be prepended to the ``PATH`` environment variable, where ```` is an arbitrary unique identifier, used to make the left hand side of the assignment unique. + +Lab 6.2: Environment (Scripted Syntax) +-------------------------------------- + +Create a new branch named lab-6.2 from branch lab-3.2 and change the contents of the Jenkinsfile to: + +```groovy +properties([ + buildDiscarder(logRotator(numToKeepStr: '5')) +]) + +timestamps() { + timeout(time: 10, unit: 'MINUTES') { + node { + stage('Greeting') { + withEnv(['GREETINGS_TO=Jenkins Techlab']) { + echo "Hello, ${env.GREETINGS_TO} !" + // also available as env variable to a process: + sh 'echo "Hello, $GREETINGS_TO !"' + } + } + } + } +} +``` + Lab 6.3: Predefined Environment Variables ----------------------------------------- diff --git a/labs/08_tools.md b/labs/08_tools.md index 6d49181..8be1f7c 100644 --- a/labs/08_tools.md +++ b/labs/08_tools.md @@ -6,16 +6,42 @@ As soon as you have more than a handful number of tools and versions it becomes That's why Jenkins provides a mechanism to provide the necessary tools for a build on the slaves it runs on. This lab shows how jobs can declare the tools they need. -Lab 8.1: Tools (Declarative Syntax) +Lab 8.1: Default Tools (Declarative Syntax) =================================== Declarative pipelines provide a ``tools`` section to declare which -tools a job requires. However, we are currently unable to use the Tools step because -it does not yet support custom tools (Custom Tool Plugin). -The problem is that the installed custom tool is not added to the path. -Until the problem is resolved, we must use the ``withEnv`` and ``tool`` steps. +tools a job requires. Jenkins per default supports the installation of the following tools: -In this example we use the custom tools jdk8_oracle and maven35. +* JDK +* Maven +* git +* Gradle +* Ant +* Docker + +Before a tool can be used in a job it needs to be added to the global tool configuration. + +Add a JDK: + +1. Go to Manage Jenkins > Global Tool Configuration +2. Under JDK click `Add JDK` +3. Under name enter `jdk8` +4. Check `Install automatically` +5. Under `Add Installer` select `Extract *.zip/*.tar.gz` + * Under `Download URL for binary archive` enter: "https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz" + * Under `Subdirectory of extracted archive` enter: "java-se-8u41-ri" +6. At the bottom of the page click `Apply` + +Add Maven: + +1. Go to Manage Jenkins > Global Tool Configuration +2. Under Maven click `Add Maven` +3. Under name enter `maven35` +4. Check `Install automatically` +5. Under `Install from Apache` select `3.5.0` +6. At the bottom of the page click `Save` + +Now we can use Java and Maven in our jobs. Create a new branch named ``lab-8.1`` from branch ``lab-3.1`` and change the contents of the ``Jenkinsfile`` to: @@ -27,16 +53,18 @@ pipeline { timeout(time: 10, unit: 'MINUTES') timestamps() // Requires the "Timestamper Plugin" } - environment{ - JAVA_HOME=tool('jdk8_oracle') - MAVEN_HOME=tool('maven35') - PATH="${env.JAVA_HOME}/bin:${env.MAVEN_HOME}/bin:${env.PATH}" + tools { + jdk 'jdk8' + maven 'maven35' } stages { stage('Build') { steps { + sh 'java -version' + sh 'javac -version' + sh 'mvn --version' } } @@ -44,52 +72,46 @@ pipeline { } ``` -The ``tool`` step returns the home directory of the installed tool. The ``PATH+`` syntax specifies -that the given value should be prepended to the ``PATH`` environment variable, where ```` is an arbitrary -unique identifier, used to make the left hand side of the assignment unique. +Inside the `tool{}` directive we define which tools are needed and in what version. The installed tools will be available because their bin directories are added to the ``PATH`` environment variable. The configured tools are downloaded when the job runs, directly onto the slaves it runs on. Note that tool installers are run for every build and therefore have to be efficient in case the tools are already installed. -Tools step example (not yet working) ------------------------------------- -As soon as the problem with the Custom Tool installation is fixed, this code will work. -```groovy -pipeline { - agent any // with hosted env use agent { label env.JOB_NAME.split('/')[0] } - options { - buildDiscarder(logRotator(numToKeepStr: '5')) - timeout(time: 10, unit: 'MINUTES') - timestamps() // Requires the "Timestamper Plugin" - } - tools { - 'com.cloudbees.jenkins.plugins.customtools.CustomTool' "jdk8_oracle" - 'com.cloudbees.jenkins.plugins.customtools.CustomTool' "maven35" +However we often need to use other tools not supported by default Jenkins (like rvm or nvm). In this case we have two options; the custom tool plugin and docker agents. + +Lab 8.1.1: Custom Tools (Plugin) +=================================== + +The custom tools plugin enables the installation of any tool to the agent node. We will use it to configure the `nvm` tools we will use in `lab-16`. + +1. Under Manage Jenkins > Global Tool Configuration click `Add Custom Tool` +2. Under name enter `nvm` +3. Check `Install automatically` +4. Under `Add Installer` select `Run shell command` + * Under `Command` enter: "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash" + * Under `Tool Home` enter: "/${HOME}/.nvm" + +The custom tool plugin does not support the `tool{}` directive but we can use the `tool()` step inside an `environment{}` directive to install the tool. The ``tool`` step returns the home directory of the installed tool. + + environment { + NVM_HOME = tool('nvm') } - stages { - stage('Build') { - steps { - sh 'java -version' - sh 'mvn --version' - } +A full example can be found in `lab-16`. + +Lab 8.1.2: Custom Tools (Docker Agent) +=================================== + +Jenkis can also use a container image as a build environment. In this case all the required tools are present in the image and the source files are mounted in the image. + + agent { + docker { + image 'ruby:2.7.1' } } -} -``` - -The ``tools`` step defines which tools are needed in which version. -The installed tools will be available because their bin directories are added to the ``PATH`` environment variable -Default tool installation example ---------------------------------- +We will use this method in `lab-15` -This example shows the configuration of a "normal" tool (jdk): -```groovy -tools { - jdk "jdk8" -} -``` Lab 8.2: Tools (Scripted Syntax) ================================ @@ -106,7 +128,7 @@ timestamps() { timeout(time: 10, unit: 'MINUTES') { node { // with hosted env use node(env.JOB_NAME.split('/')[0]) stage('Greeting') { - withEnv(["JAVA_HOME=${tool 'jdk8_oracle'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { + withEnv(["JAVA_HOME=${tool 'jdk8'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { sh "java -version" sh "mvn --version" } diff --git a/labs/09_artifacts.md b/labs/09_artifacts.md index 6d9e124..ae12b3b 100644 --- a/labs/09_artifacts.md +++ b/labs/09_artifacts.md @@ -29,10 +29,9 @@ pipeline { timeout(time: 10, unit: 'MINUTES') timestamps() // Requires the "Timestamper Plugin" } - environment{ - JAVA_HOME=tool('jdk8_oracle') - MAVEN_HOME=tool('maven35') - PATH="${env.JAVA_HOME}/bin:${env.MAVEN_HOME}/bin:${env.PATH}" + tools { + jdk 'jdk8' + maven 'maven35' } stages { stage('Build') { @@ -71,7 +70,7 @@ timestamps() { timeout(time: 10, unit: 'MINUTES') { node { // with hosted env use node(env.JOB_NAME.split('/')[0]) stage('Build') { - withEnv(["JAVA_HOME=${tool 'jdk8_oracle'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { + withEnv(["JAVA_HOME=${tool 'jdk8'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { checkout scm sh 'mvn -B -V -U -e clean verify -Dsurefire.useFile=false' archiveArtifacts 'target/*.?ar' diff --git a/labs/10_failures.md b/labs/10_failures.md index c672229..228bcf6 100644 --- a/labs/10_failures.md +++ b/labs/10_failures.md @@ -29,10 +29,9 @@ pipeline { timeout(time: 10, unit: 'MINUTES') timestamps() // Requires the "Timestamper Plugin" } - environment{ - JAVA_HOME=tool('jdk8_oracle') - MAVEN_HOME=tool('maven35') - PATH="${env.JAVA_HOME}/bin:${env.MAVEN_HOME}/bin:${env.PATH}" + tools { + jdk 'jdk8' + maven 'maven35' } stages { stage('Build') { @@ -84,7 +83,7 @@ try { node { // with hosted env use node(env.JOB_NAME.split('/')[0]) stage('Build') { try { - withEnv(["JAVA_HOME=${tool 'jdk8_oracle'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { + withEnv(["JAVA_HOME=${tool 'jdk8'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { checkout scm sh 'mvn -B -V -U -e clean verify -Dsurefire.useFile=false' archiveArtifacts 'target/*.?ar' diff --git a/labs/11_shared_libs.md b/labs/11_shared_libs.md index 0a3be02..c46710a 100644 --- a/labs/11_shared_libs.md +++ b/labs/11_shared_libs.md @@ -57,10 +57,9 @@ pipeline { timeout(time: 10, unit: 'MINUTES') timestamps() // Requires the "Timestamper Plugin" } - environment{ - JAVA_HOME=tool('jdk8_oracle') - MAVEN_HOME=tool('maven35') - PATH="${env.JAVA_HOME}/bin:${env.MAVEN_HOME}/bin:${env.PATH}" + tools { + jdk 'jdk8' + maven 'maven35' } stages { stage('Build') { diff --git a/labs/12_credentials.md b/labs/12_credentials.md index 73903f7..8a9e56a 100644 --- a/labs/12_credentials.md +++ b/labs/12_credentials.md @@ -25,15 +25,16 @@ pipeline { timestamps() // Requires the "Timestamper Plugin" } environment{ - JAVA_HOME=tool('jdk8_oracle') - MAVEN_HOME=tool('maven35') - PATH="${env.JAVA_HOME}/bin:${env.MAVEN_HOME}/bin:${env.PATH}" M2_SETTINGS = credentials('m2_settings') KNOWN_HOSTS = credentials('known_hosts') ARTIFACTORY = credentials('jenkins-artifactory') ARTIFACT = "${env.JOB_NAME.split('/')[0]}-hello" REPO_URL = 'https://artifactory.puzzle.ch/artifactory/ext-release-local' } + tools { + jdk 'jdk8' + maven 'maven35' + } stages { stage('Build') { steps { @@ -80,7 +81,7 @@ timestamps() { env.REPO_URL = 'https://artifactory.puzzle.ch/artifactory/ext-release-local' node { // with hosted env use node(env.JOB_NAME.split('/')[0]) withCredentials([file(credentialsId: 'm2_settings', variable: 'M2_SETTINGS'), usernameColonPassword(credentialsId: 'jenkins-artifactory', variable: 'ARTIFACTORY'), file(credentialsId: 'known_hosts', variable: 'KNOWN_HOSTS')]) { // Credentials Binding Plugin - withEnv(["JAVA_HOME=${tool 'jdk8_oracle'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { + withEnv(["JAVA_HOME=${tool 'jdk8'}", "PATH+MAVEN=${tool 'maven35'}/bin:${env.JAVA_HOME}/bin"]) { stage('Build') { checkout scm sh 'mvn -B -V -U -e clean verify -Dsurefire.useFile=false' diff --git a/labs/13_stages_locks_milestones.md b/labs/13_stages_locks_milestones.md index e2c4a52..9a4d81f 100644 --- a/labs/13_stages_locks_milestones.md +++ b/labs/13_stages_locks_milestones.md @@ -25,15 +25,15 @@ pipeline { timestamps() // Timestamper Plugin } environment{ - JAVA_HOME=tool('jdk8_oracle') - MAVEN_HOME=tool('maven35') - PATH="${env.JAVA_HOME}/bin:${env.MAVEN_HOME}/bin:${env.PATH}" M2_SETTINGS = credentials('m2_settings') KNOWN_HOSTS = credentials('known_hosts') ARTIFACTORY = credentials('jenkins-artifactory') ARTIFACT = "${env.JOB_NAME.split('/')[0]}-hello" REPO_URL = 'https://artifactory.puzzle.ch/artifactory/ext-release-local' - + } + tools { + jdk 'jdk8' + maven 'maven35' } stages { stage('Build') { diff --git a/labs/15_ruby.md b/labs/15_ruby.md index bfe0dd9..8a89b80 100644 --- a/labs/15_ruby.md +++ b/labs/15_ruby.md @@ -5,25 +5,22 @@ Lab 15.1: Install Ruby (Declarative Syntax) ------------------------------------------- ```groovy -@Library('jenkins-techlab-libraries') _ - pipeline { - agent any // with hosted env use agent { label env.JOB_NAME.split('/')[0] } + agent { + // with hosted env use agent { label env.JOB_NAME.split('/')[0] } + docker { + image 'ruby:2.7.1' + } + } options { buildDiscarder(logRotator(numToKeepStr: '5')) timeout(time: 10, unit: 'MINUTES') timestamps() // Timestamper Plugin } - environment { - RVM_HOME = tool('rvm') - } stages { stage('Build') { steps { sh """#!/bin/bash - source \${RVM_HOME}/scripts/rvm - rvm use --install 2.3.4 - gem list '^bundler\$' -i || gem install bundler ruby --version bundle --version """ diff --git a/labs/16_nodejs.md b/labs/16_nodejs.md index 58fbe4a..ece18da 100644 --- a/labs/16_nodejs.md +++ b/labs/16_nodejs.md @@ -2,15 +2,12 @@ Lab 16: Node.js =============== ```groovy -@Library('jenkins-techlab-libraries') _ - pipeline { agent any // with hosted env use agent { label env.JOB_NAME.split('/')[0] } options { buildDiscarder(logRotator(numToKeepStr: '5')) timeout(time: 10, unit: 'MINUTES') timestamps() // Timestamper Plugin - ansiColor('xterm') // AnsiColor Plugin } environment { NVM_HOME = tool('nvm')