Menu
About me Kontakt

Jenkinsfile - what is it and how to create one? Useful if you are using Jenkins (video, 35 minutes)

In TechWorld with Nana's latest video, the topic of Jenkins Files is thoroughly explored, along with their significance in continuous integration processes. A Jenkins File serves as a means to define job configurations and builds within Jenkins using code. Instead of configuring jobs via a user interface, users can create a 'Jenkins File' in their repository, representing a shift towards infrastructure as code. In this presentation, Nana details the foundational steps to creating a Jenkins File in your repository, as well as the basic syntax that accompanies it. She highlights critical elements such as the necessity for both scripted and declarative pipeline styles, each catering to varying levels of programming expertise.

To summarize, the scripted pipeline represents the original syntax for Jenkins Files, utilizing the Groovy language. Conversely, the declarative pipeline introduces a predefined structure, making it easier for those unfamiliar with Groovy to navigate. Nana elaborates on mandatory attributes that must be contained within a Jenkins File, like the agent and stages. These components are essential to understanding how pipelines function, organizing the various stages of building, testing, and deploying applications in a seamless manner.

Nana delves into the importance of conditions and expressions within this context, emphasizing their role in determining which stages execute based on build status or branch, thus enhancing the flexibility of the CI/CD process. The concepts she introduces, such as post conditions and parameters, showcase advanced capabilities in logical expression. Moreover, Nana draws attention to the utilization of environmental variables and how they can be leveraged within Groovy scripts, significantly enriching the dynamics of Jenkins Files.

Towards the end, Nana ventures into the intriguing topic of utilizing external scripts within Jenkins. She elucidates the advantages of this approach, such as modularity and simplified management of complex scripts. Summarizing the video, she encourages viewers to subscribe to her channel and invites them to ask questions in the comment section, enhancing community engagement.

At the time of writing this article, the video has garnered 856187 views and 15709 likes, indicating its educational value and the interest it has sparked within the IT community. The mention of these statistics underscores the importance of the topics explored by TechWorld with Nana and how they benefit many individuals in their pathways to learning programming and continuous integration.

Toggle timeline summary

  • 00:00 Introduction to Jenkins file and its purpose.
  • 00:11 Explanation of Jenkins file as a means to create and configure jobs.
  • 00:33 Jenkins file as pipeline as code; it can be scripted or declarative.
  • 00:51 Demonstration using a demo project to create a Jenkins file.
  • 01:13 Basic syntax of Jenkins file and required attributes.
  • 01:33 Comparison between scripted and declarative pipeline syntax.
  • 03:41 The importance of stages in a Jenkins pipeline.
  • 04:09 Example of defining multiple stages such as build, test, and deploy.
  • 05:04 Writing simple echo commands for testing within the Jenkins file.
  • 05:40 Creating a new build in Jenkins and configuring it.
  • 07:26 Explaining how Jenkins detects the Jenkins file in branches.
  • 08:44 Definition and purpose of post conditions after pipeline stages.
  • 10:19 Using 'when' expressions to conditionally run stages.
  • 12:42 Overview of environmental variables in Jenkins files.
  • 13:47 Defining custom environmental variables.
  • 21:52 Defining tools required for various projects in Jenkins file.
  • 22:32 Using parameters to pass configurations to the build.
  • 27:31 Utilizing external scripts for cleaner Jenkins file configuration.
  • 33:02 Importing and using external Groovy scripts in Jenkins file.
  • 34:48 Closing remarks and invitation for questions.

Transcription

In this video, I'm going to show you what Jenkins file is, how to create it and what the syntax looks like. So what is Jenkins file? If you're familiar with Jenkins, usually you would create new jobs or new builds and you would configure them. So basically what Jenkins file is that instead of you creating and configuring jobs on the Jenkins user interface, you would write a file or you would script that build and its configuration in a file. So Jenkins file is pipeline as a code. It's a scripted pipeline, which is part of this whole infrastructure as a code concept. And so respectively, you would create Jenkins file in your repository with your code. So I have this demo project here that I'm going to use to demonstrate Jenkins file and configure a build with it. The first step is to create Jenkins file in your repository. So I'm going to create a new file in my dev branch and call it Jenkins file. So code is where your Jenkins file lives. Now, how do you create a Jenkins file? How does syntax look like? And this is the most basic Jenkins file that basically does nothing. But this is the basic syntax. But here I'm going to explain you the required attributes for Jenkins file. So the first thing is that Jenkins file can be written as a scripted pipeline or a declarative pipeline. So the scripted pipeline was the first syntax of Jenkins file. So what it is, is basically it allows to write the whole configuration of the Jenkins file using groovy script. So the only structure that you have there is this here. And inside of this is basically groovy script. And you can write the whole configuration here in a flexible manner as you wish. So there is no predefined structure there. However, for people who didn't know or doesn't know groovy syntax or who hasn't worked with groovy is a little bit difficult to start with. That's why as a recent addition, they actually added declarative pipeline syntax for Jenkins file, which is easier to get started with. It has, of course, it's not as powerful as the scripted pipeline because here you're not limited in any way, but it's easier to get started with because you have a predefined structure. So this what you see here is basically pre given structure that you have to follow. But again, you don't have to think about how to script all this. So you just fill in the gaps. So what we saw here, the note definition is basically same as these two lines here. So in a declarative pipeline, you declare that you're writing a pipeline and agent any basically means that this build is going to run on any available Jenkins agent. An agent can be a note. It could be an executor on that note, whatever. And this is more relevant when you have a Jenkins cluster, so to say, with master and slaves where you have Windows nodes and Linux nodes, et cetera. But here for a beginning for base, we just say agent any. So we'll just run with the next available agent. And as I said, these two are equivalent to this one here. And they are required attributes. You always have to use them. The next required attribute is stages. And this is where the whole work actually happens. So you have different stages of that pipeline. And inside the stages, you define stage name and you can define as many stages as you want. Usually you have something like this. So you have a build stage to get rid of this one. Actually, you have a build stage, maybe you have a test stage and then you have a deploy stage. Like this, you can have additional ones, like, for example, you might have a checkout state stage here and I don't know, cleanup stage afterwards, whatever. And as you see inside the stage, you have the steps. And here goes the script that actually executes some command on the Jenkins server or Jenkins agent. So, for example, if you're building a JavaScript application, all the NPM install, NPM build, et cetera, scripts will go here like this. If you're running tests or for Java backend, all the text execution scripts will be here and the deployment script will be here. So right now, let's just write simple echo commands to kind of test this. So here we're going to say building the application. And here we're going to say testing the application. And here we are deploying the application. And this is a valid Jenkins file and this should work already. So let's actually. OK, so I have the Jenkins file and that just basically echoes some stuff. And now let's see how to actually use that in Jenkins pipeline. So the second step will be to go to Jenkins to create a new build. And I have to log in. And I'm going to call it my app pipeline. And I'm going to create a multi branch pipeline. And here is the configuration where I select the repository that I want to build. So I'm going to configure the repository. Credentials, if you don't know how credentials work in Jenkins, I have a separate video about that, what scopes of credentials there are in Jenkins, how to create them and use them, et cetera. And that would be it. So basically, this is my configuration. And here I can specify which branches I want to build. So I'm going to leave it at all the branches and let's see what happens. So here you see that it just basically went through all the branches that I have master dev. I have some test branches there and it scanned all the branches for Jenkins file and it only found in his file in Dev branch because that's where I created it. And it built their branch. And let's see that actually. So I'm going to create a new branch. I'm going to let's see that actually see that branch was built by Jenkins file and the stages that we defined in the Jenkins file are this one here. So we said built, test and deploy. And to each one of them, you can see this echo command that we define. So building the application, testing the application, et cetera. So the first step here, which is declarative checking out SCM basically comes from this configuration here. So this implicitly defines the first stage of the pipeline, which is checking out the code. And the second question is why or how is it configured that my pipeline looks for Jenkins file in those projects? And that configuration is right here. Build configuration, which is default. I didn't set it or I didn't configure it by default. It looks for file called Jenkins file. And this is the path in the project. And I have Jenkins file in the root directory. So I didn't change any of this. So this is all you need to do in order to configure a pipeline to build from Jenkins file. The rest of the configuration of individual steps of built pipeline will be done in the Jenkins file itself. So let's go back to the Jenkins file and how can we see what attributes we can use to configure different parts of the build. So this is the basic syntax where we have the base construct inside the stages where we defined three different stages. So another thing you can do with Jenkins file is that at the end of it, you can define post attribute. So what it does is it takes attribute. So what it does is basically executes some kind of logic or some kind of scripts after all the stages are done. And inside the post, there are different conditions that you can execute your scripts on. So, for example, if I say always in the post condition, it means that this script or this logic, whatever is in there will be executed always, no matter if the build failed or if it succeeded or whatever happened, this will be always executed. And this could be something like sending an email out to the team about the build condition, because you want to know whether it failed or succeeded or whatever happened. Another condition is success. So you will execute a script here that all is only relevant if the build succeeded. And you have the same thing with failure. So you can define all the different conditions in the post block. And there are a couple of more. But to generalize in the post block, you basically define expressions of either build status or build status change. So, for example, if the last bill change and now it's green again, you can use that condition as well here. So now it's actually switched to the editor so that we can see the highlighting as well. And let's continue from here. Another thing you can do in Jenkins file, which is very useful, is define expressions or conditionals for each stage. So, for example, you only want to run the tests on development branch built. You don't want to run tests for feature branch bill or any other bills. What you can do here is inside the stage block, you can define so-called when expressions. So when should this stage execute? And the syntax for that is like this. And inside you have expression block. And here you find basically your Boolean expressions and the branch name or the current the active branch name in the build is always available in Jenkins file through an environmental variable that Jenkins provides it. Environmental variable is called branch name and that is just available. Or you can also write like this and that is basically just available for you out of the box and you can use it to check what the current branch that's building is. So if I want to check that it's a branch, I can do like this and this stage will only execute or this part of the stage will only execute if the current branch is deaf. If not, it's just going to skip. And the same way like you would do in expressions, you can also add or or end expressions here. So you can say, I want to run this stage if it's a deaf built or if it's a master built, let's say you can do it like this or another applicable use case for when expressions is, for example, you only want to build your application if their code changes made in the project. So, for example, in the build step, I can do something like if it's a deaf and code changes equals true. And this could be a variable that you define yourself at the beginning, let's say outside the pipeline. And that basically has logic where it gets it changes or something like this. So basically, this will be a groovy script that checks whether there has been any changes made in the code and sets the value of this boolean. So let's clear all this up again. And talk about environmental variables in Jenkins file, which is which is very important concept. So as I just showed, Jenkins provides some environmental variables out of the box for you to use them in Jenkins file like current branch name. But there are some other stuff that you might need for the logic. For example, you want to know which build number the current build has so you can use it in your versioning or some other stuff. So how do you know what variables you have available from Jenkins? The location where you can find that, which I find pretty practical, is in your Jenkins. There's a URL in bars, HTML that basically provides you with the list of all the environmental variables and you can use them in your Jenkins file. This is the one that we used. And also you have descriptions for each one of those that you want to use. But in addition to the ones that Jenkins provides, you can define your own environmental variables. And this is also a common practice. So let's see how to do that. In Jenkins file, there is an attribute called environment. And whatever environmental variables you define here will be available for all the stages that you have in the pipeline. So, for example, if you need a version in many different stages in your pipeline, you would define that version here. Let's actually go and do that. So version and let's just say whatever. Usually you would calculate the version like you would extract it from your code. But I'm just going to write it like this. And the way that you can use that environmental variable in your script is like this. So let's see. Building version. You. And you also see the syntax highlighting that this is interpreted as a variable and important thing to note here is that if I copy that and I put this in single quotes, this is what happens. And this is a syntax of groovy. If you want the variable to be interpreted as a variable in a string, you have to enclose it in double quotes, something to be aware. But otherwise, if you have a simple string, you can use either another practical example of using environmental variable can be credentials. So, for example, you have a stage that deploys your newly built application to a development server, let's say. And for that stage, you need credentials of the development server to connect to it and to copy the newly built artifact. So you would define credentials in Jenkins. As I said, I have a separate video where I explain how credentials work in Jenkins, different scopes, et cetera. So once you have defined credentials in Jenkins, you can use that in Jenkins file. And one way to do that is in your environment block, you would say server credentials and you would extract the credentials from Jenkins. And let's see how that works. So this is method or function that binds the credentials that are defined in Jenkins to your environmental variable. And that is actually a separate plugin that you have to install in Jenkins. It's called credentials binding plugin, which makes it possible to use Jenkins credentials inside the Jenkins file. And as a parameter, it takes the ID or reference of the credentials in Jenkins. So let's go back to Jenkins and see our credentials. So this is a global scope. And if I add here a credential, let's say username and password, I don't know, let's just say server user password, whatever. And this is the idea of the reference. Let's call it server credentials. And if I create this, I will be able to use that credential inside the Jenkins file using that reference or the ID that I provided. And now I can use that environmental variable in the stage the same way as your version. Again, I have to enclose it in double quotes and. Like this, and obviously, you're not going to be using that credentials in a string. It would be a shell script. So the same way you can provide it inside there. Now, if you need that credentials only in one stage, it actually makes sense to read it from Jenkins in that stage as well. So another way to do that is instead of defining that in environment block, and this is the syntax of rappers, so to say, you can directly define it here. So let me delete that instead. What you can do is use with credentials rapper. And that takes as a parameter and object, this is object syntax in Ruby, and that object will be username password. And that is basically a function that lets me get password and username of that credentials individually. So I pass it inside the object and as parameters here, I can provide credentials ID, which is the same as here. And the reason why I can use username password is because the type of credential that I created. So the server user here is of type username and password. That's why I can use it here. And after the idea of credentials, I can get my username and I can store it into a variable name that I want. So I'm going to call it user and variable and I can store it into password. So what this will do is take the username and store it into variable. I want to call user and same with password. OK, so now inside this block with credentials, I can use user and password variables. So if I have a shell script here, some script, I can like, I don't know, copy the artifact to some place. I can use my username and password like this. So a user and password. So this will be the script, some commands, some actual shell commands and username and password variables inside the script. And as I said, you have to have these two plugins in Jenkins. Let's actually go and see those two plugins. So I have credentials plugin that allows me to create credentials inside Jenkins UI and I have credentials binding plugin that allows me to use those credentials in my Jenkins file through environmental variables. Let's clean all that up. And other useful thing that you can use in your file is tools attribute. So what tools does is basically provides you with built tools for your projects. So if you have a front and back end application, you would have some built tools configured for that. Could be Maven, Gradle or some other tool that you use. And obviously, when you're building an application, you want to have those tools available. So, for example, in build, you would run something like Maven install or Gradle build, whatever. And you need to have those tools available. And one way to have those tools available is through these tools attribute. And there are three tools right now that Jenkins file supports. That's Gradle, Maven and JDK. If you need yarn or NPM, for example, you have to do it in another way. If you want to have a complete overview of how tools work and how you can use any built tool in your Jenkins file from your Jenkins configuration. I have made a separate video on that where I explain the whole thing in detail so you can check it out. But here I'm just going to show you how tools attribute works and the way you can define the tools here is using the name that is supported. So as I said, Gradle and JDK. And next to the tool, you have to provide the name of the tool and that has to be pre-configured or pre-installed in Jenkins. And the way that you can check that is in global tool configuration. And Maven is, I believe, in most of the recent versions, pre-installed and pre-configured. So you have that. And that is the name. So name of the installation that you have to provide in your Jenkins file using quotes. So this definition here will make Maven comments available in all the stages. And again, if you want to know exactly how to add new tools here and how to use them in Jenkins file, then you can go and check out the other video that I made. Another thing that could also be helpful in pipelines is parameters. So maybe you have some external configuration that you want to provide to your build to change some behavior. An example could be that you have a build that deploys your application to a staging server, let's say, and you want to be able to select which version of the application you want to deploy. So here in parameters, you will define the selection and the way you can write that is like this. So you have the type first of the parameter and inside you provide the name of the parameter. That's how it's going to be displayed. Say, call it version. You can provide default value. I'm just going to be blank and you can add the description so that other people also know or maybe you later know what that parameter is meant for. So it's a version to deploy on prod. There are different types of parameters support. For example, instead of string, you can have a choice. Which is called a version, so instead of having to enter input a version name, you can have predefined choices of different versions that you can actually choose from. And here you say choices and let's say. Like this. And this will also have a subscription that's blank for now. And you also have some other types like boolean. And this could be, for example, you want to skip a certain stage on some builds and you can do that here. So let's say you say execute test parameter default value will be true and description. Let's leave it here so we can delete one of those two. So now we've defined the parameters and we can actually see in practice how they're displayed in Jenkins built. And now you can use these parameters in any of your stages, which is pretty straightforward. You remember the one expression that we used? So parameters are suitable usage for expressions. So, for example, here we want to define that whenever expression. So in the one expression, we can use the parameters so we can say that if execute test parameter is set to true, only then we're going to run tests. If not, we're going to skip that. So this step will only execute if execute tests. That's and this is how you can use the parameters if execute test is true. So you can write it either like this or you can just leave that equals true out and this will work as well. So if params execute test is set to true, this is going to execute. If you set it to false, this will be skipped. And the version we can use deployed, let's say double quotes deploying version like this. And let's actually execute this Jenkins file to see how it looks like in Jenkins. So I'm going to copy that and edit my Jenkins file and the check. So params, this is missing here. So I have to say params version. And again, you can write it with all caps or camel case. It's up to you. And I'm going to commit that. And let's execute that on Jenkins. So now let's see where I see my parameters. So in pipeline view, I don't see any configuration. But if I go into the branch, they've now here instead of built, I see button called build with parameters. So before, if you don't have any parameters set, then it will just say built. So I'm going to click that and I'm going to see both of the parameters listed here so I can choose a version here from the list. So let me just say one, two, zero, and I'm going to uncheck execute tests. And if I build that, let's see. So the tests should be skipped because we unchecked it. And let's see what the deploy stage says. Deploying version one to zero. So that's how parameters work. So these parameters that we defined in Jenkins file apply to all the branches. So you can use that individually in every branch when building. Now, another very useful and interesting thing is using external scripts in Jenkins. So imagine a scenario where you have all these pipeline steps where you build front end and you run tests and you build backend and you build Docker image out of it and you push it to repository, et cetera. So you have many different stages. And then inside of the stages, you have a lot of logic and the logic is mainly groovy scripts. Right. And very soon your Jenkins file can get loaded with external scripts. You could have shell scripts or you may have cradle scripts that execute different stuff. So often it's a good idea to clean up Jenkins file and put all these scripts, so to say, in its own file. And the way that you can use it is create a separate cradle script and extract all the cradle scripts into that external file. And let's actually do that till now on these examples that I showed you, I have used just very simple echo comments. But Jenkins file basically supports groovy script so you can write much more powerful logic using groovy. And the way you can do that is using script blocks. So instead of just putting this echo simple commands in the step section, you would define script here and here you can write normal cradle so you can define variables and you can define functions and do all other stuff and call cradle functions, et cetera. So what we're going to do now is we're going to extract those simple echo commands to a cradle script just to see how to do that. So I have this groovy script here that just defines one function, just echo something very simple and return. This is important because otherwise you can't import it in Jenkins file. So how do I import and use that groovy function in Jenkins file? So I'm going to go ahead and create an init section or init stage here in which I'm going to load that groovy script. And in order to load that, I need a script block because it's going to be groovy command. And I'm going to say groovy or GB, whatever, and load script dot groovy. And I want to make this a variable that holds the imported groovy script, so to say, globally available so that I can use it in all my stages. I'm going to define that actually outside here. And assign the whole groovy script there. So the one that I exported was so this should be a function name. So I'm going to call it built up. And the way I can use that function now in my Jenkins file is using that variable that holds the script. And instead of this year, I can replace this echo statement. But again, I need to do that in script because otherwise it's not executed because it's groovy syntax. So the variable name and the function name and the function name. Very simple. And let me actually export all of those. So I'm going to create a new function. I'm going to call it test app and copy that here. And I'm going to do a third one, which is deploy app. And again, I'm going to copy the whole thing here. And I need to put them in script. So this is going to be test and this is going to be deploy. And one thing you may already noticed here is that the echo command with version parameter should be params version. Actually, I put that in deploy app in the groovy script. So basically, all the environmental variables that you have accessible here through parameters attribute or environment attribute or out of the box available from Jenkins, you can use all of them in groovy. So you have access to them inside your script. So you don't have to configure anything for that. So now we have exported each stage of functionality to groovy script. So whenever, for example, your logic of building the application changes and you have some complex logic here, for example, in build application, you may want to extract the version from your palm file or from your file or maybe some other place. And you have to build a new version construct depending on how you version your application. So all that logic will live in groovy script and Jenkins file will have more slim and simple structure. What you can also extract groovy is your expression. So basically everything that is groovy scripts you can extract to the external script. So it's actually execute the now and see how it works. So I'm going to edit the Jenkins file. And I'm also going to add that groovy script to my project. I called it script groovy. OK, so now if I scan my branch, see the logs. And let's see this building and it was successful. So one thing that is very practical in pipeline is in the branch specific built where you have the history. If I go, for example, in one of those, I have this replay button that is a very practical way of testing out changes in Jenkins file without having to commit that. So I can actually make the changes right here so I can add another echo and I can run the build again. So now that I've committed that extra script that I have, let's go to the last build here. And if I do replay, I see not only my Jenkins file, but also that script. So I can actually change or I can adjust both and test the changes right here. So if I wanted to say. Changes and run that. I can see that your echo and that's how you configure and use external groovy script in Jenkins file. Thanks for watching the video. I hope it was helpful. And if it was, don't forget to like it. If you want to be notified whenever a new video comes out, then subscribe to my channel. If you have any questions, if something wasn't clear in the video, please post them in the comment section below and I will try to answer them. So thank you and see you in the next video.