{"id":1819,"date":"2026-10-29T09:35:13","date_gmt":"2026-10-29T09:35:13","guid":{"rendered":"https:\/\/devopsschool.org\/blog\/?p=1819"},"modified":"2026-10-29T09:35:15","modified_gmt":"2026-10-29T09:35:15","slug":"jenkins-for-students-how-to-automate-software-builds-and-tests","status":"publish","type":"post","link":"https:\/\/devopsschool.org\/blog\/jenkins-for-students-how-to-automate-software-builds-and-tests\/","title":{"rendered":"Jenkins for Students: How to Automate Software Builds and Tests"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"572\" src=\"https:\/\/devopsschool.org\/blog\/wp-content\/uploads\/2026\/10\/image-22.png\" alt=\"\" class=\"wp-image-1820\" srcset=\"https:\/\/devopsschool.org\/blog\/wp-content\/uploads\/2026\/10\/image-22.png 1024w, https:\/\/devopsschool.org\/blog\/wp-content\/uploads\/2026\/10\/image-22-300x168.png 300w, https:\/\/devopsschool.org\/blog\/wp-content\/uploads\/2026\/10\/image-22-768x429.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every developer remembers the anxiety of working on a group programming project where everyone\u2019s code worked fine on their personal laptop, but everything shattered into cryptic errors once merged together the night before submission. One teammate used an outdated Java version, another modified an interface without telling anyone, and a third forgot to commit a critical dependency.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Software engineering teams in the tech industry face this exact challenge every day, but on a massive scale. To solve it, engineering organizations rely on automated, repeatable processes that build, test, and validate software every single time an engineer pushes a code change. Instead of guessing whether an application compiles or passes its test suite, teams use automated continuous feedback loops. At the center of this industry-standard practice sits <strong>Jenkins<\/strong>, an open-source automation server that powers modern Continuous Integration and Continuous Delivery (CI\/CD) workflows. For university students, recent graduates, and aspiring engineers learning through educational platforms like <strong>DevOpsSchool<\/strong>, mastering Jenkins bridges the gap between writing simple code assignments and understanding real-world software delivery pipelines. Learning <strong>Jenkins for students<\/strong> is not merely about clicking buttons on a dashboard; it provides foundational insight into build automation, regression testing, pipeline design, configuration management, and the collaborative operational culture known as DevOps. By learning to automate builds and tests early in your academic journey, you develop the disciplined habits top software engineering teams expect from junior hires.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. What Is Jenkins?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins is a self-contained, open-source automation server designed to coordinate and automate tasks throughout the software development lifecycle. Written in Java, it acts as an orchestration engine that watches your code repositories for updates, triggers execution routines, runs test suites, packages binary distributions, and reports the status back to the engineering team.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Manual vs. Automated Builds<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To understand why Jenkins is essential, consider the contrast between manual and automated workflows:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Aspect<\/strong><\/td><td><strong>Manual Build Process<\/strong><\/td><td><strong>Automated Build Process (Jenkins)<\/strong><\/td><\/tr><\/thead><tbody><tr><td><strong>Execution Trigger<\/strong><\/td><td>Developer manually types commands in a local terminal<\/td><td>Automatically triggered by a Git push, pull request, or schedule<\/td><\/tr><tr><td><strong>Environment Consistency<\/strong><\/td><td>Highly variable; depends on local machine state and configurations<\/td><td>Standardized across reproducible build environments<\/td><\/tr><tr><td><strong>Test Verification<\/strong><\/td><td>Easily skipped, forgotten, or executed incompletely<\/td><td>Enforced automatically before code is accepted or packaged<\/td><\/tr><tr><td><strong>Feedback Loop<\/strong><\/td><td>Slow; bugs often discovered days or weeks later<\/td><td>Fast; failures reported within minutes of a code push<\/td><\/tr><tr><td><strong>Human Effort<\/strong><\/td><td>Repetitive, prone to human error, and time-consuming<\/td><td>&#8220;Set and forget&#8221; pipeline definition executed automatically<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">How Jenkins Supports CI\/CD<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins fundamentally supports two stages of modern software delivery:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>Continuous Integration (CI):<\/strong> Developers integrate their code into a shared repository frequently\u2014often multiple times a day. Jenkins verifies each check-in by automatically building the application and running automated tests. This detects bugs early and pinpoints the exact commit that introduced a defect.<\/li>\n\n\n\n<li><strong>Continuous Delivery (CD):<\/strong> Once the build and test stages pass, Jenkins can automatically stage the packaged application for release or deploy it directly to staging or production environments.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">The Role of an Orchestrator<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A common misconception among beginners is that Jenkins compiles your code or executes unit tests natively. In reality, <strong>Jenkins is an orchestrator, not a compiler.<\/strong> Jenkins does not inherently know how to compile Java, package Python, or transpile TypeScript.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, Jenkins coordinates specialized tools and plugins. It uses a Version Control System (VCS) like Git to fetch code, hands the code over to a build tool like Apache Maven or Gradle to compile and test it, runs test runners like JUnit, and parses the resulting test reports to determine if the pipeline passed or failed. Jenkins provides the environment, schedules the tasks, records the output, and signals success or failure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Understanding Builds, Automated Tests, and CI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before configuring an automated server, you must understand the core concepts behind the lifecycle of an automated run.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>+---------------+      Git Push      +--------------------+\n|   Developer   | -----------------&gt; |  Code Repository   |\n| (Local Code)  |                    |      (GitHub)      |\n+---------------+                    +--------------------+\n                                               |\n                                        Webhook Event\n                                               v\n+---------------------------------------------------------+\n|                    Jenkins Controller                   |\n|                                                         |\n|  +----------------+   +----------------+   +---------+  |\n|  | 1. Checkout Git|--&gt;| 2. Maven Build |--&gt;| 3. Test |  |\n|  +----------------+   +----------------+   +---------+  |\n|                                                 |       |\n|                                            JUnit XML    |\n|                                                 v       |\n|  +----------------+                       +----------+  |\n|  | Fast Feedback  |&lt;----------------------| 4. Report|  |\n|  | (Pass \/ Fail)  |                       +----------+  |\n|  +----------------+                                     |\n+---------------------------------------------------------+\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">What Is a Software Build?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A software build transforms source code files written by humans into executable machine code, bytecode, or deployable software packages (such as <code>.jar<\/code>, <code>.war<\/code>, or <code>.zip<\/code> files).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A build process includes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Dependency Management:<\/strong> Downloading and linking external libraries, frameworks, and packages specified by the project (for example, via Maven&#8217;s <code>pom.xml<\/code> or Node&#8217;s <code class=\"\">package.json<\/code>).<\/li>\n\n\n\n<li><strong>Compilation:<\/strong> Converting human-readable source code into machine-executable formats while verifying syntax and interface contracts.<\/li>\n\n\n\n<li><strong>Resource Processing:<\/strong> Copying and formatting static assets, configuration files, and properties.<\/li>\n\n\n\n<li><strong>Packaging:<\/strong> Assembling the compiled code and resources into an archive ready for execution or distribution.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">The Testing Pyramid<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Automated testing evaluates software behavior against expected outcomes without requiring human testers to click through an application manually. Automated tests fall into three primary categories:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Unit Tests:<\/strong> These verify the smallest testable parts of an application\u2014such as a single function, class, or method\u2014in complete isolation from databases, networks, or file systems. They execute in milliseconds and should make up the majority of your test suite.<\/li>\n\n\n\n<li><strong>Integration Tests:<\/strong> These verify that distinct components, modules, or services function correctly together (for example, verifying that an authentication class interacts properly with a test database).<\/li>\n\n\n\n<li><strong>End-to-End (E2E) \/ System Tests:<\/strong> These exercise the entire application flow from start to finish, mimicking real user journeys through user interfaces or public API endpoints.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">The Cost of Build and Test Failures<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In a manual setup, if a developer breaks a calculation inside a core helper function, that defect might go unnoticed until another teammate pulls the changes days later\u2014or worse, after the software is handed to a customer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Continuous Integration enforces <strong>early feedback<\/strong>. Suppose a student updates a discount calculation in an e-commerce class:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>The student commits and pushes the code change to Git.<\/li>\n\n\n\n<li>Jenkins detects the push and immediately starts an automated build.<\/li>\n\n\n\n<li>Jenkins invokes the build tool to run all unit tests.<\/li>\n\n\n\n<li>An existing test checks: <code>calculateDiscount(100, 0.20)<\/code> and expects <code>80<\/code>. The new code returns <code>20<\/code>.<\/li>\n\n\n\n<li>The test runner registers an assertion error and terminates with an exit code indicating failure.<\/li>\n\n\n\n<li>Jenkins halts the pipeline, marks the build as <strong>Failed (Red)<\/strong>, and notifies the developer within minutes.<\/li>\n\n\n\n<li>The developer reviews the test failure output, fixes the logic error, pushes the correction, and Jenkins turns <strong>Healthy (Green)<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">4. How Jenkins Works: Architecture and Core Components<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins uses a distributed, modular architecture capable of scaling from a single laptop to thousands of servers across enterprise data centers.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <code>                    +---------------------------------------+\n                     |          Jenkins Controller           |\n                     |  - Web UI &amp; HTTP Dashboard            |\n                     |  - Configuration &amp; Plugin Engine      |\n                     |  - Build Job Scheduler                |\n                     |  - Credentials Vault                  |\n                     +---------------------------------------+\n                                  \/            \\\n                      Work Request \/              \\ Work Request\n                                  \/                \\\n                                 v                  v\n                 +----------------------+    +----------------------+\n                 |     Agent Node 1     |    |     Agent Node 2     |\n                 |  (Build Environment) |    |  (Build Environment) |\n                 |  - Git, JDK, Maven   |    |  - Docker, Python    |\n                 |  - Executes Tasks    |    |  - Executes Tasks    |\n                 +----------------------+    +----------------------+\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Core Components<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Controller (formerly Master):<\/strong> The brain of the Jenkins installation. The controller provides the web UI, manages plugins, schedules build jobs, stores job definitions and build history, handles credentials, and assigns work tasks.<\/li>\n\n\n\n<li><strong>Agents (formerly Slaves):<\/strong> Worker machines or containers that connect to the controller and carry out the physical execution of build steps. Agents keep heavy compilation tasks off the controller. In small learning environments, Jenkins provides a <strong>built-in node<\/strong> directly on the controller to run jobs locally. However, production environments assign workloads to isolated agents for security and performance.<\/li>\n\n\n\n<li><strong>Jobs and Pipelines:<\/strong> A <em>job<\/em> (or item) is any automated task sequence managed by Jenkins. A <em>pipeline<\/em> is an advanced, user-defined model of a continuous delivery path, structured into sequential stages such as Build, Test, and Deploy.<\/li>\n\n\n\n<li><strong>Workspaces:<\/strong> An isolated directory on the file system of the machine executing the build. Jenkins creates a workspace for each job, checks out your project&#8217;s source code into it, runs tools against it, and cleans it up when instructed.<\/li>\n\n\n\n<li><strong>Plugins:<\/strong> Jenkins is built on an extensible plugin system. The base installation has minimal features; plugins provide integration with tools like Git, GitHub, Docker, Maven, Slack, and JUnit reporting.<\/li>\n\n\n\n<li><strong>Build History and Console Output:<\/strong> Every time a job runs, Jenkins creates an immutable historical record labeled with a sequential build number (<code>#1<\/code>, <code>#2<\/code>, <code>#3<\/code>). Jenkins captures the full terminal standard output (<code>stdout<\/code>) and standard error (<code>stderr<\/code>) logs, allowing you to debug exactly what happened during execution.<\/li>\n\n\n\n<li><strong>Credentials Management:<\/strong> A centralized, encrypted vault inside Jenkins that lets you store API keys, SSH private keys, and passwords. Jobs reference these secrets securely via IDs without ever hardcoding sensitive tokens into your project source code.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">5. Setting Up Jenkins for Learning<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To learn Jenkins step by step, you need a local sandbox environment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">System Requirements<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before beginning, confirm your machine meets these basic requirements:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Operating System:<\/strong> Linux (Ubuntu\/Debian, CentOS\/RHEL), macOS, or Windows 10\/11 (with WSL2 recommended).<\/li>\n\n\n\n<li><strong>Memory (RAM):<\/strong> Minimum 2 GB to 4 GB allocated for Jenkins and your build tools.<\/li>\n\n\n\n<li><strong>Disk Space:<\/strong> At least 10 GB free for Jenkins, runtime logs, dependencies, and local git clones.<\/li>\n\n\n\n<li><strong>Runtime:<\/strong> A supported Java Development Kit (JDK) or Java Runtime Environment (JRE). Modern versions of Jenkins require <strong>Java 17 or Java 21<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Setup Methods: Native vs. Docker<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Students typically choose between two setups:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>Docker Container (Recommended for Students):<\/strong> Running Jenkins inside an official container isolates the automation server from your local operating system, avoids dependency conflicts, and allows you to tear down and recreate environments in seconds.<\/li>\n\n\n\n<li><strong>Native Host Installation:<\/strong> Installing Java and the Jenkins package directly on your operating system using package managers (<code>apt<\/code>, <code>brew<\/code>, or native installers).<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Method A: Running Jenkins via Docker<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you have Docker Desktop installed, run this command in your terminal:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -d \\\n  --name jenkins-learning \\\n  -p 8080:8080 \\\n  -p 50000:50000 \\\n  -v jenkins_home:\/var\/jenkins_home \\\n  jenkins\/jenkins:lts-jdk17\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>-p 8080:8080<\/code>: Exposes the Jenkins web dashboard on port <code>8080<\/code>.<\/li>\n\n\n\n<li><code>-p 50000:50000<\/code>: Allows external Jenkins agents to communicate with the controller.<\/li>\n\n\n\n<li><code>-v jenkins_home:...<\/code>: Mounts a persistent Docker volume so your pipeline configurations, job history, and plugin settings survive container restarts.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Method B: Native Installation on Ubuntu\/Debian Linux<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For a native install on Linux, verify that Java 17 is present:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Update repositories and install OpenJDK 17\nsudo apt-get update\nsudo apt-get install -y openjdk-17-jdk\n\n# Verify Java version\njava -version\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, add the official Jenkins Debian repository key, register the repository sources list, update your packages, and install Jenkins:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo wget -O \/usr\/share\/keyrings\/jenkins-keyring.asc \\\n  https:&#047;&#047;pkg.jenkins.io\/debian-stable\/jenkins.io-2023.key\n\necho \"deb &#091;signed-by=\/usr\/share\/keyrings\/jenkins-keyring.asc] \\\n  https:\/\/pkg.jenkins.io\/debian-stable binary\/\" | sudo tee \\\n  \/etc\/apt\/sources.list.d\/jenkins.list &gt; \/dev\/null\n\nsudo apt-get update\nsudo apt-get install -y jenkins\n\n# Enable and start the Jenkins service\nsudo systemctl enable jenkins\nsudo systemctl start jenkins\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Initial Administrator Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once Jenkins starts, complete the setup wizard:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Open a browser and navigate to <code>http:\/\/localhost:8080<\/code>.<\/li>\n\n\n\n<li><strong>Unlock Jenkins:<\/strong> The browser displays a screen asking for an initial administrator password.\n<ul class=\"wp-block-list\">\n<li>If running natively on Linux:Bash<code>sudo cat \/var\/lib\/jenkins\/secrets\/initialAdminPassword<\/code><\/li>\n\n\n\n<li>If running via Docker:Bash<code>docker exec jenkins-learning cat \/var\/jenkins_home\/secrets\/initialAdminPassword<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Copy the 32-character alphanumeric string, paste it into the setup screen, and click <strong>Continue<\/strong>.<\/li>\n\n\n\n<li><strong>Customize Jenkins:<\/strong> Click <strong>Install suggested plugins<\/strong>. This installs the default plugins for Git, Pipeline support, credentials, and common dashboard utilities.<\/li>\n\n\n\n<li><strong>Create First Admin User:<\/strong> Fill out the form with a username, password, full name, and email address (for example, <code>studentadmin<\/code>). Avoid relying on the temporary <code>admin<\/code> account.<\/li>\n\n\n\n<li><strong>Instance Configuration:<\/strong> Confirm the default URL (<code>http:\/\/localhost:8080<\/code>) and select <strong>Save and Finish<\/strong>. Your Jenkins dashboard is ready.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">6. Prepare a Sample Application for Automation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To understand <strong>Jenkins build automation<\/strong>, you need an application project to build and test. We will use a standard Java application configured with Apache Maven.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Standard Maven Project Directory Structure<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Maven relies on a standard directory layout. Create this structure locally on your workstation or in a new Git repository:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Plaintext<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>simple-java-app\/\n\u251c\u2500\u2500 pom.xml\n\u2514\u2500\u2500 src\n    \u251c\u2500\u2500 main\n    \u2502   \u2514\u2500\u2500 java\n    \u2502       \u2514\u2500\u2500 com\n    \u2502           \u2514\u2500\u2500 devopsschool\n    \u2502               \u2514\u2500\u2500 Calculator.java\n    \u2514\u2500\u2500 test\n        \u2514\u2500\u2500 java\n            \u2514\u2500\u2500 com\n                \u2514\u2500\u2500 devopsschool\n                    \u2514\u2500\u2500 CalculatorTest.java\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>pom.xml<\/code>: The Project Object Model file containing project configuration, dependencies, and build plugins.<\/li>\n\n\n\n<li><code>src\/main\/java<\/code>: Stores your application&#8217;s production source code.<\/li>\n\n\n\n<li><code>src\/test\/java<\/code>: Stores automated test suites, such as unit tests.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">1. The Build Configuration (<code>pom.xml<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This minimal <code>pom.xml<\/code> configures a Java project with the modern JUnit 5 (Jupiter) testing framework and the Maven Surefire plugin for running tests:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">XML<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"\n         xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 \n         https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n\n    &lt;groupId&gt;com.devopsschool&lt;\/groupId&gt;\n    &lt;artifactId&gt;simple-java-app&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.0&lt;\/version&gt;\n    &lt;packaging&gt;jar&lt;\/packaging&gt;\n\n    &lt;properties&gt;\n        &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;\n        &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;\n        &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;\n        &lt;junit.version&gt;5.10.2&lt;\/junit.version&gt;\n    &lt;\/properties&gt;\n\n    &lt;dependencies&gt;\n        &lt;!-- JUnit Jupiter API &amp; Test Engine --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.junit.jupiter&lt;\/groupId&gt;\n            &lt;artifactId&gt;junit-jupiter&lt;\/artifactId&gt;\n            &lt;version&gt;${junit.version}&lt;\/version&gt;\n            &lt;scope&gt;test&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n\n    &lt;build&gt;\n        &lt;plugins&gt;\n            &lt;!-- Maven Surefire Plugin to execute tests during the build lifecycle --&gt;\n            &lt;plugin&gt;\n                &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\n                &lt;artifactId&gt;maven-surefire-plugin&lt;\/artifactId&gt;\n                &lt;version&gt;3.2.5&lt;\/version&gt;\n            &lt;\/plugin&gt;\n        &lt;\/plugins&gt;\n    &lt;\/build&gt;\n&lt;\/project&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. The Application Code (<code>Calculator.java<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Place this file in <code>src\/main\/java\/com\/devopsschool\/Calculator.java<\/code>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.devopsschool;\n\npublic class Calculator {\n\n    public int add(int a, int b) {\n        return a + b;\n    }\n\n    public int subtract(int a, int b) {\n        return a - b;\n    }\n\n    public int multiply(int a, int b) {\n        return a * b;\n    }\n\n    public double divide(int a, int b) {\n        if (b == 0) {\n            throw new IllegalArgumentException(\"Division by zero is not allowed.\");\n        }\n        return (double) a \/ b;\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. The Unit Test Suite (<code>CalculatorTest.java<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Place this file in <code>src\/test\/java\/com\/devopsschool\/CalculatorTest.java<\/code>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.devopsschool;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.DisplayName;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class CalculatorTest {\n\n    private Calculator calculator;\n\n    @BeforeEach\n    void setUp() {\n        calculator = new Calculator();\n    }\n\n    @Test\n    @DisplayName(\"Test addition of two integers\")\n    void testAdd() {\n        assertEquals(15, calculator.add(10, 5), \"10 + 5 should equal 15\");\n    }\n\n    @Test\n    @DisplayName(\"Test subtraction of two integers\")\n    void testSubtract() {\n        assertEquals(5, calculator.subtract(10, 5), \"10 - 5 should equal 5\");\n    }\n\n    @Test\n    @DisplayName(\"Test division by zero throws exception\")\n    void testDivideByZero() {\n        assertThrows(IllegalArgumentException.class, () -&gt; {\n            calculator.divide(10, 0);\n        }, \"Dividing by zero must throw IllegalArgumentException\");\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Initialize a local Git repository, commit these files, and push them to a Git hosting provider such as GitHub, GitLab, or Gitea:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git init\ngit add .\ngit commit -m \"Initial commit of student calculator project with unit tests\"\ngit branch -M main\n# Add your remote and push\n# git remote add origin https:\/\/github.com\/&lt;your-username&gt;\/simple-java-app.git\n# git push -u origin main\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">7. Create Your First Jenkins Job<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before jumping into code-based pipelines, it helps to understand what a Jenkins job looks like under the hood.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Freestyle Jobs vs. Pipeline Jobs<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When creating a job in Jenkins, you will see several options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Freestyle Project:<\/strong> The legacy, UI-driven way to configure builds in Jenkins. You configure Git repositories, shell commands, and post-build actions using forms and dropdown menus in the browser. While easy for beginners to understand, Freestyle jobs cannot be version-controlled, reviewed, or easily migrated.<\/li>\n\n\n\n<li><strong>Pipeline Project:<\/strong> The modern, production-standard approach. The entire workflow is written as code using a domain-specific language (DSL) and stored directly in your Git repository alongside your application code.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Exploring a Basic Freestyle Build (Walkthrough)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To understand how Jenkins interacts with tools on the underlying host, create a temporary Freestyle job:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>On the Jenkins dashboard, click <strong>New Item<\/strong>.<\/li>\n\n\n\n<li>Enter the name <code>my-first-freestyle-job<\/code>, select <strong>Freestyle project<\/strong>, and click <strong>OK<\/strong>.<\/li>\n\n\n\n<li>Under <strong>General<\/strong>, add a short description: <em>Testing basic shell execution<\/em>.<\/li>\n\n\n\n<li>Scroll to the <strong>Build Steps<\/strong> section, click <strong>Add build step<\/strong>, and select <strong>Execute shell<\/strong> (or <em>Execute Windows batch command<\/em> if running natively on Windows).<\/li>\n\n\n\n<li>Enter a simple command:Bash<code>echo \"Running build on agent: $(hostname)\" echo \"Current workspace directory: $(pwd)\" java -version<\/code><\/li>\n\n\n\n<li>Click <strong>Save<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Running the Job and Inspecting Output<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>On the left navigation sidebar of your new job, click <strong>Build Now<\/strong>.<\/li>\n\n\n\n<li>Notice that a new item appears in the <strong>Build History<\/strong> box: <code>#1<\/code>.<\/li>\n\n\n\n<li>Click the <code>#1<\/code> link, then select <strong>Console Output<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Plaintext<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Started by user studentadmin\nRunning as SYSTEM\nBuilding in workspace \/var\/jenkins_home\/workspace\/my-first-freestyle-job\n&#091;my-first-freestyle-job] $ \/bin\/sh -xe \/tmp\/jenkins847291048293.sh\n+ echo 'Running build on agent: jenkins-learning'\nRunning build on agent: jenkins-learning\n+ echo 'Current workspace directory: \/var\/jenkins_home\/workspace\/my-first-freestyle-job'\nCurrent workspace directory: \/var\/jenkins_home\/workspace\/my-first-freestyle-job\n+ java -version\nopenjdk version \"17.0.10\" 2024-01-16\nOpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7)\nOpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode)\nFinished: SUCCESS\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The console output shows every command executed by Jenkins, along with its standard output, standard error, and exit status. An exit code of <code>0<\/code> results in <code>Finished: SUCCESS<\/code> (represented by a <strong>blue<\/strong> or <strong>green<\/strong> ball depending on your UI theme). Any non-zero exit code stops execution and marks the job as <code>Finished: FAILURE<\/code> (<strong>red<\/strong> ball).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">8. Build a Jenkins Pipeline Using a Jenkinsfile<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Freestyle jobs work for quick experiments, but modern DevOps relies on <strong>Pipeline as Code<\/strong>. By defining your build, test, and release logic in a text file named <code>Jenkinsfile<\/code> and committing it to your Git repository, your automation pipeline is versioned, reviewed, and audited just like your application code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Declarative vs. Scripted Pipelines<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins supports two pipeline syntaxes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Declarative Pipeline:<\/strong> A structured, opinionated format with clear syntax blocks (<code>pipeline<\/code>, <code>agent<\/code>, <code>stages<\/code>, <code>steps<\/code>). It is easy to read, catches configuration errors early, and is the industry-standard syntax for nearly all modern CI pipelines.<\/li>\n\n\n\n<li><strong>Scripted Pipeline:<\/strong> An older, Groovy-based programming style that offers full programmatic flexibility at the cost of higher complexity and maintenance overhead.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">As a student, focus on mastering <strong>Declarative Pipelines<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Anatomy of a Jenkinsfile<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a practical, production-ready <code>Jenkinsfile<\/code> for our Java and Maven project:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Groovy<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pipeline {\n    agent any\n\n    tools {\n        \/\/ References a Maven installation configured in Global Tool Configuration\n        maven 'Maven-3.9'\n        \/\/ References a JDK installation configured in Global Tool Configuration\n        jdk 'JDK-17'\n    }\n\n    options {\n        \/\/ Automatically stop the build if it takes longer than 20 minutes\n        timeout(time: 20, unit: 'MINUTES')\n        \/\/ Print timestamps in the console output for easier debugging\n        timestamps()\n    }\n\n    stages {\n        stage('Checkout') {\n            steps {\n                echo 'Checking out source code from Git repository...'\n                checkout scm\n            }\n        }\n\n        stage('Compile &amp; Package') {\n            steps {\n                echo 'Compiling source files and packaging JAR...'\n                \/\/ Run Maven compile while skipping tests during this initial compilation stage\n                sh 'mvn clean compile'\n            }\n        }\n\n        stage('Run Automated Tests') {\n            steps {\n                echo 'Executing automated unit tests via Maven Surefire...'\n                \/\/ Executes tests and compiles the JAR artifact\n                sh 'mvn test'\n            }\n        }\n\n        stage('Archive Artifacts') {\n            steps {\n                echo 'Archiving built application packages...'\n                \/\/ Package the application into a target\/*.jar file\n                sh 'mvn package -DskipTests=true'\n                \/\/ Store the resulting binary within Jenkins build records\n                archiveArtifacts artifacts: 'target\/*.jar', fingerprint: true, allowEmptyArchive: false\n            }\n        }\n    }\n\n    post {\n        always {\n            echo 'Collecting test execution results...'\n            \/\/ Parse JUnit XML files produced by the Maven Surefire plugin\n            junit 'target\/surefire-reports\/*.xml'\n        }\n        success {\n            echo 'Pipeline completed successfully! All stages and tests passed.'\n        }\n        failure {\n            echo 'Pipeline failed! Investigate the console output and test reports above.'\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Explaining the Pipeline Sections<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>pipeline<\/code>:<\/strong> The root container that tells Jenkins to parse the block as a Declarative Pipeline.<\/li>\n\n\n\n<li><strong><code>agent any<\/code>:<\/strong> Tells Jenkins to run this pipeline on any available executor node or agent.<\/li>\n\n\n\n<li><strong><code>tools<\/code>:<\/strong> Informs Jenkins which pre-configured compilers or build tools to automatically inject into the operating system <code>PATH<\/code> for this build.<\/li>\n\n\n\n<li><strong><code>stages<\/code>:<\/strong> Houses the sequence of tasks that describe your software delivery lifecycle.<\/li>\n\n\n\n<li><strong><code>stage('Name')<\/code>:<\/strong> A distinct logical segment of the pipeline. In the Jenkins UI, each stage renders as an independent column, showing you exactly how long each phase took and whether it succeeded or failed.<\/li>\n\n\n\n<li><strong><code>steps<\/code>:<\/strong> The actual commands executed within a stage (such as running shell commands with <code>sh<\/code>, or batch scripts with <code>bat<\/code>).<\/li>\n\n\n\n<li><strong><code>post<\/code>:<\/strong> Executes steps conditionally after all stages finish:\n<ul class=\"wp-block-list\">\n<li><code>always<\/code>: Runs regardless of the build outcome (ideal for collecting test reports or cleaning temporary directories).<\/li>\n\n\n\n<li><code>success<\/code>: Runs only if every stage finished without error.<\/li>\n\n\n\n<li><code>failure<\/code>: Runs if any stage or test suite threw an error (ideal for sending alerts).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Setting Up the Pipeline Job in Jenkins<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>On the Jenkins home screen, click <strong>New Item<\/strong>.<\/li>\n\n\n\n<li>Enter the name <code>calculator-ci-pipeline<\/code>, select <strong>Pipeline<\/strong>, and click <strong>OK<\/strong>.<\/li>\n\n\n\n<li>Under the <strong>Pipeline<\/strong> configuration tab at the bottom:\n<ul class=\"wp-block-list\">\n<li>Change <strong>Definition<\/strong> to <strong>Pipeline script from SCM<\/strong>.<\/li>\n\n\n\n<li>Under <strong>SCM<\/strong>, select <strong>Git<\/strong>.<\/li>\n\n\n\n<li>Enter your <strong>Repository URL<\/strong> (e.g., your GitHub repository URL).<\/li>\n\n\n\n<li>Under <strong>Branches to build<\/strong>, specify <code>*\/main<\/code>.<\/li>\n\n\n\n<li>Under <strong>Script Path<\/strong>, ensure it reads <code>Jenkinsfile<\/code>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Click <strong>Save<\/strong>.<\/li>\n\n\n\n<li>Click <strong>Build Now<\/strong>. Jenkins will clone your Git repository, locate the <code>Jenkinsfile<\/code> in the project root, parse its instructions, and execute each stage.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">9. Automating Tests with Jenkins<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Automated testing is the primary safety net of Continuous Integration. Without testing, a CI pipeline is just an automated compiler that packages broken code faster.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Maven and Surefire Produce Test Data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When Jenkins runs the command <code>mvn test<\/code>, the Maven lifecycle invokes the <strong>Maven Surefire Plugin<\/strong>. Surefire discovers all test classes ending in <code>Test<\/code> or <code>TestCase<\/code> under <code>src\/test\/java<\/code>, runs each test method, and writes the results to standardized XML files in the <code>target\/surefire-reports\/<\/code> directory:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Plaintext<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>target\/surefire-reports\/\n\u251c\u2500\u2500 TEST-com.devopsschool.CalculatorTest.xml\n\u2514\u2500\u2500 com.devopsschool.CalculatorTest.txt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Inside <code>TEST-com.devopsschool.CalculatorTest.xml<\/code>, Surefire writes structured data detailing the execution:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">XML<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;testsuite name=\"com.devopsschool.CalculatorTest\" tests=\"3\" skipped=\"0\" failures=\"0\" errors=\"0\" time=\"0.045\"&gt;\n  &lt;testcase name=\"testAdd()\" classname=\"com.devopsschool.CalculatorTest\" time=\"0.021\"\/&gt;\n  &lt;testcase name=\"testSubtract()\" classname=\"com.devopsschool.CalculatorTest\" time=\"0.003\"\/&gt;\n  &lt;testcase name=\"testDivideByZero()\" classname=\"com.devopsschool.CalculatorTest\" time=\"0.004\"\/&gt;\n&lt;\/testsuite&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Publishing Test Results in Jenkins<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>post<\/code> block in our <code>Jenkinsfile<\/code> includes this instruction:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Groovy<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>junit 'target\/surefire-reports\/*.xml'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This step uses the Jenkins JUnit plugin to parse the XML output files. Instead of requiring developers to dig through thousands of lines of terminal logs to find why a build failed, Jenkins generates an interactive graphical <strong>Test Result<\/strong> dashboard directly on the job\u2019s page.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The dashboard displays:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Total Tests Executed:<\/strong> The total number of individual assertions evaluated.<\/li>\n\n\n\n<li><strong>Failures and Errors:<\/strong> The exact test methods that failed, complete with stack traces, expected vs. actual values, and code line numbers.<\/li>\n\n\n\n<li><strong>Test Duration:<\/strong> How long individual tests took to complete, helping you spot performance regressions.<\/li>\n\n\n\n<li><strong>Test Trends:<\/strong> An interactive historical graph charting passing, failing, and skipped tests over time across all builds.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">What Happens When a Test Fails?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To see this in action, imagine a developer changes the <code>add<\/code> method in <code>Calculator.java<\/code> to an incorrect implementation:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public int add(int a, int b) {\n    return a + b + 1; \/\/ Intentional logic bug\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When this change is pushed to Git and Jenkins executes <code>mvn test<\/code>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Plaintext<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#091;INFO] Running com.devopsschool.CalculatorTest\n&#091;ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.052 s &lt;&lt;&lt; FAILURE! -- in com.devopsschool.CalculatorTest\n&#091;ERROR] com.devopsschool.CalculatorTest.testAdd -- Time elapsed: 0.022 s &lt;&lt;&lt; FAILURE!\norg.opentest4j.AssertionFailedError: 10 + 5 should equal 15 ==&gt; expected: &lt;15&gt; but was: &lt;16&gt;\n\tat org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)\n\tat org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)\n\tat org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)\n\tat com.devopsschool.CalculatorTest.testAdd(CalculatorTest.java:21)\n<\/code><\/pre>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Maven detects an assertion failure and exits with status code <code>1<\/code>.<\/li>\n\n\n\n<li>Jenkins notices the non-zero exit code and halts pipeline execution before reaching the <code>Archive Artifacts<\/code> stage. This prevents a broken application package from ever being created.<\/li>\n\n\n\n<li>The <code>post<\/code> block activates, executing the <code>junit<\/code> step, which captures the failure details from the Surefire XML report.<\/li>\n\n\n\n<li>The build is marked as <strong>UNSTABLE<\/strong> or <strong>FAILED<\/strong> (Red).<\/li>\n\n\n\n<li>The Jenkins UI highlights the exact failure: <code class=\"\">com.devopsschool.CalculatorTest.testAdd - expected &lt;15&gt; but was &lt;16&gt;<\/code>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">10. Triggering Builds Automatically<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Manually clicking <strong>Build Now<\/strong> is helpful while writing and testing your pipeline, but true Continuous Integration requires builds to run automatically whenever code changes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>+------------------+         Git Push          +---------------------+\n| Student commits  | ------------------------&gt; | GitHub Repository   |\n| code on laptop   |                           +---------------------+\n+------------------+                                      |\n                                             Webhook HTTP POST request\n                                                          v\n                                               +---------------------+\n                                               | Jenkins Controller  |\n                                               | (Starts Pipeline)   |\n                                               +---------------------+\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins supports several build triggers:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Webhooks (Industry Best Practice)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A <strong>Webhook<\/strong> is an automated HTTP <code>POST<\/code> payload sent from your Git host (such as GitHub or GitLab) to Jenkins whenever an event occurs\u2014such as a developer pushing a commit or opening a pull request.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>How it works:<\/strong> When you push code, GitHub immediately calls <code>http:\/\/&lt;your-jenkins-ip&gt;:8080\/github-webhook\/<\/code>. Jenkins receives the notification, determines which job monitors that repository and branch, and starts the build immediately.<\/li>\n\n\n\n<li><strong>Network Requirement:<\/strong> The Git host must be able to reach your Jenkins server over the network. If you are running Jenkins locally on <code>localhost<\/code> behind a home router, GitHub cannot reach it directly without an HTTP tunnel (such as ngrok) or a public IP address.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Polling SCM (Beginner Fallback)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If your Jenkins installation is running on a local private network or laptop without public internet ingress, you can use <strong>Poll SCM<\/strong>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>How it works:<\/strong> Jenkins periodically checks your remote Git repository on a schedule (defined using Cron syntax) to see if any new commits have appeared. If new commits exist, Jenkins triggers a build; if not, it does nothing.<\/li>\n\n\n\n<li><strong>Configuration:<\/strong> Inside your <code>Jenkinsfile<\/code>, add a triggers block:<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Groovy<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pipeline {\n    agent any\n    triggers {\n        \/\/ Poll the Git repository every 15 minutes for changes\n        pollSCM('H\/15 * * * *')\n    }\n    \/\/ ... stages continue below\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><em>The <code>H<\/code> symbol stands for &#8220;Hash&#8221; and spreads out the polling load across your Jenkins controller to avoid sudden spikes in activity.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Scheduled Builds<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Some builds do not need to run on every commit. For example, long-running end-to-end test suites or performance benchmarks can be scheduled to run during off-peak hours:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Groovy<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>triggers {\n    \/\/ Run every night at midnight\n    cron('H 0 * * *')\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">11. Understanding Build Failures and Troubleshooting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Encountering errors is an unavoidable part of engineering. Knowing how to diagnose and resolve build failures will save you hours of frustration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a quick-reference troubleshooting matrix for common beginner issues:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Symptom \/ Error Message<\/strong><\/td><td><strong>Root Cause<\/strong><\/td><td><strong>Where to Look<\/strong><\/td><td><strong>Practical Fix<\/strong><\/td><\/tr><\/thead><tbody><tr><td><code>mvn: command not found<\/code> or <code>java: not found<\/code><\/td><td>The tool is not installed, or its executable directory is missing from the system <code>PATH<\/code>.<\/td><td>Console Output &amp; System Configuration<\/td><td>Configure the tool in <strong>Manage Jenkins &gt; Tools<\/strong>, or use the <code>tools<\/code> directive in your <code>Jenkinsfile<\/code>.<\/td><\/tr><tr><td><code>Fatal: Authentication failed for 'https:\/\/...'<\/code><\/td><td>Jenkins lacks valid credentials to access a private Git repository.<\/td><td>Job Configuration &amp; Credentials Vault<\/td><td>Add an SSH key or Personal Access Token in <strong>Manage Jenkins &gt; Credentials<\/strong>, and link it to the SCM configuration.<\/td><\/tr><tr><td><code>Non-resolvable parent POM<\/code> or <code>Could not resolve dependencies<\/code><\/td><td>Maven cannot reach the internet to download dependencies, or repository proxy settings are incorrect.<\/td><td>Console Output (<code>mvn<\/code> logs)<\/td><td>Verify your network connection, inspect DNS inside your Docker container, or configure Maven&#8217;s <code>settings.xml<\/code> file with proper proxy settings.<\/td><\/tr><tr><td><code>Compilation failure: [ERROR] cannot find symbol<\/code><\/td><td>Syntax error, missing import, or a Java language version mismatch.<\/td><td>Console Output (Compiler section)<\/td><td>Check that your local JDK version matches the compiler target defined in <code>pom.xml<\/code> and Jenkins tool settings.<\/td><\/tr><tr><td><code>FAILURE: There are test failures<\/code><\/td><td>One or more unit tests failed their assertions.<\/td><td><strong>Test Result<\/strong> tab on the Build page<\/td><td>Click into the failed test in the Jenkins UI to view the stack trace and pinpoint the logic error in your code.<\/td><\/tr><tr><td><code>Recording test results... No test report files were found<\/code><\/td><td>The path specified in the <code>junit<\/code> step does not match where Maven generated the XML reports.<\/td><td>Pipeline <code>post<\/code> block &amp; Workspace filesystem<\/td><td>Confirm that the pattern <code>target\/surefire-reports\/*.xml<\/code> matches your project layout. Ensure the test stage actually ran.<\/td><\/tr><tr><td><code>Permission denied<\/code> when creating directories<\/td><td>The user account running Jenkins (<code>jenkins<\/code>) does not own the workspace folder on the host machine.<\/td><td>Controller host file permissions<\/td><td>Run <code>chown -R jenkins:jenkins \/var\/jenkins_home<\/code> on the host machine hosting your storage volumes.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">12. Jenkins Best Practices for Students<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Following these simple best practices will keep your pipelines reliable, readable, and easy to maintain:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Treat Pipelines as Code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Always define your build instructions in a version-controlled <code>Jenkinsfile<\/code> rather than using the Jenkins UI to configure Freestyle jobs. Your pipeline definitions should be reviewed, tested, and tracked in version control right alongside your application code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Never Hardcode Secrets<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Never commit passwords, database credentials, API tokens, or private keys directly into a repository or <code>Jenkinsfile<\/code>. Use Jenkins&#8217; built-in Credentials Provider and access secrets securely within your pipeline:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Groovy<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>environment {\n    API_KEY = credentials('my-secret-api-token')\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Fail Fast<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Order your pipeline stages logically. Run fast, lightweight tasks first (such as static linting, compilation, and unit tests) before triggering slower, resource-intensive operations (such as end-to-end UI tests or container builds). If a simple unit test fails, there is no reason to spend twenty minutes building a Docker image.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Keep Build Environments Clean and Disposable<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid manually installing software packages inside an active build workspace. Rely on versioned tools, package managers, or containerized execution nodes. If an agent machine is destroyed, your pipeline should run smoothly on a brand-new agent without manual intervention.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Keep Test Suites Deterministic<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Flaky tests\u2014tests that pass on one run and fail on the next without any code changes\u2014erode trust in your CI\/CD pipeline. Tests should be isolated, avoid external network dependencies, clean up after themselves, and produce predictable results every time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">13. Extending the Pipeline Beyond Builds and Tests<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once your basic build-and-test pipeline is running smoothly, you can expand it with additional automated checks used in professional software delivery.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>+-----------+   +----------+   +----------+   +---------------+   +------------+\n|  Compile  |--&gt;|   Unit   |--&gt;| Quality  |--&gt;| Build &amp; Push  |--&gt;| Deploy to  |\n|  Package  |   |  Tests   |   | Analysis |   | Docker Image  |   | Staging VM |\n+-----------+   +----------+   +----------+   +---------------+   +------------+\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">1. Static Code Analysis and Quality Gates<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Integrate tools like <strong>SonarQube<\/strong> or <strong>SpotBugs<\/strong> to inspect your source code for bugs, anti-patterns, and vulnerabilities without running it. You can define a Quality Gate that halts the pipeline if code coverage drops below an agreed threshold (e.g., 80%).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Dependency Vulnerability Scanning<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use security plugins such as <strong>OWASP Dependency-Check<\/strong> or <strong>Snyk<\/strong> to scan your project dependencies (<code>pom.xml<\/code>) against national vulnerability databases, alerting you to known security vulnerabilities in third-party libraries.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Containerization with Docker<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Extend your pipeline to package your application into an immutable Docker image and publish it to an artifact registry such as Docker Hub:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Groovy<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>stage('Build Docker Image') {\n    steps {\n        script {\n            dockerImage = docker.build(\"myusername\/simple-java-app:${env.BUILD_NUMBER}\")\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Automated Deployment<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add a deployment stage that transfers your packaged artifacts to a cloud server, testing environment, or staging Kubernetes cluster whenever a build on your <code>main<\/code> branch succeeds.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Automated Notifications<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Configure the <code>post<\/code> block to send notifications to Discord, Slack, or email channels, letting your team know immediately when a build succeeds or requires attention.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">14. A Mini Project: Build and Test Automation from Start to Finish<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Put your new knowledge into practice with this step-by-step hands-on exercise.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <code>      PROJECT ROADMAP\nStep 1: Write Java code &amp; JUnit tests\n                 |\nStep 2: Commit &amp; push to your Git repo\n                 |\nStep 3: Point Jenkins to your repository\n                 |\nStep 4: Run the pipeline &amp; see Green\n                 |\nStep 5: Introduce an intentional bug\n                 |\nStep 6: Watch Jenkins catch the failure\n                 |\nStep 7: Fix the bug &amp; restore to Green\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Create the Project<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new directory named <code>student-ci-demo<\/code> containing the <code>pom.xml<\/code>, <code>Calculator.java<\/code>, and <code>CalculatorTest.java<\/code> files detailed in <strong>Section 6<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Add the Jenkinsfile<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a file named <code>Jenkinsfile<\/code> in the root of your project directory using the Declarative Pipeline code from <strong>Section 8<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Push to Git<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Initialize Git, commit your project files, create a new repository on your preferred Git host, and push your commits to the <code>main<\/code> branch:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git init\ngit add .\ngit commit -m \"feat: complete initial project setup with pipeline\"\ngit branch -M main\ngit remote add origin &lt;your-git-repo-url&gt;\ngit push -u origin main\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Configure Jenkins<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Open Jenkins at <code>http:\/\/localhost:8080<\/code>.<\/li>\n\n\n\n<li>Click <strong>New Item<\/strong>, choose <strong>Pipeline<\/strong>, and name it <code>student-mini-project<\/code>.<\/li>\n\n\n\n<li>In the configuration under <strong>Pipeline<\/strong>, set <strong>Definition<\/strong> to <strong>Pipeline script from SCM<\/strong>.<\/li>\n\n\n\n<li>Set <strong>SCM<\/strong> to <strong>Git<\/strong>, provide your repository URL, and set the branch to <code>*\/main<\/code>.<\/li>\n\n\n\n<li>Click <strong>Save<\/strong>, then click <strong>Build Now<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Verify the Passing Build<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Watch the <strong>Stage View<\/strong> dashboard. The stages\u2014<em>Checkout<\/em>, <em>Compile &amp; Package<\/em>, <em>Run Automated Tests<\/em>, and <em>Archive Artifacts<\/em>\u2014will turn green one by one.<\/li>\n\n\n\n<li>Click into the build, select <strong>Test Result<\/strong>, and confirm that <strong>3 tests ran with 0 failures<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Break a Test Intentionally<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Simulate a developer error. Open <code>Calculator.java<\/code> and modify the <code>subtract<\/code> method:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public int subtract(int a, int b) {\n    return a - b - 10; \/\/ Intentional defect\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Commit and push this change to your repository:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git commit -am \"refactor: tweak subtraction logic\"\ngit push origin main\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 7: Observe the Failure<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Return to Jenkins and click <strong>Build Now<\/strong> (or wait for your webhook or polling trigger to run).<\/li>\n\n\n\n<li>The pipeline will stop at the <strong>Run Automated Tests<\/strong> stage, turning <strong>Red<\/strong>.<\/li>\n\n\n\n<li>Click the failed build number, open the <strong>Test Result<\/strong> page, and review the error:Plaintext<code>CalculatorTest.testSubtract: expected: &lt;5&gt; but was: &lt;-5&gt;<\/code><\/li>\n\n\n\n<li>Notice that the <em>Archive Artifacts<\/em> stage was skipped completely, preventing a broken application binary from being created.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Step 8: Fix and Verify<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Correct the calculation in <code>Calculator.java<\/code>, commit the fix, and push it to Git. Run the pipeline one more time to see your pipeline return to a clean, passing <strong>Green<\/strong> state.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">15. Frequently Asked Questions (FAQ)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">What is Jenkins used for?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins is an open-source automation server used primarily to implement Continuous Integration (CI) and Continuous Delivery (CD). It automates repetitive tasks throughout the software lifecycle, including code checkout, compilation, unit and integration testing, code analysis, packaging, and deployment to hosting environments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is Jenkins suitable for beginners?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. While Jenkins offers powerful features for enterprise use, its core concepts\u2014automating builds, running commands, and displaying test results\u2014are straightforward to learn. Starting with a basic Declarative Pipeline on a single project is an approachable, hands-on way for students to learn CI\/CD fundamentals.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the difference between a Jenkins job and a Jenkins pipeline?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A <em>Jenkins job<\/em> is a broad term for any automated task configured in Jenkins, historically set up via the graphical UI (such as a Freestyle job). A <em>Jenkins pipeline<\/em> is a modern, code-based workflow that models your entire build, test, and release process as code using a <code>Jenkinsfile<\/code>, which can be checked into version control alongside your project.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is a Jenkinsfile?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>Jenkinsfile<\/code> is a text configuration file stored in the root of your source code repository that defines your Jenkins pipeline. Written using Declarative or Scripted pipeline syntax, it models the build, test, and deployment stages as code, ensuring your automation workflow is versioned and tracked alongside your application code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How does Jenkins automate software testing?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Jenkins executes test commands through build tools or test runners (such as <code>mvn test<\/code> for Java, <code>npm test<\/code> for JavaScript, or <code>pytest<\/code> for Python). Jenkins captures the test results, parses generated XML report files (like JUnit XML), marks builds as passed or failed based on test outcomes, and generates visual trend reports on the dashboard.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does Jenkins require Java?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. The Jenkins controller itself is written in Java and requires a supported Java runtime (typically OpenJDK 17 or 21) to execute. However, this does not limit what Jenkins can build; it can build and test software written in any programming language.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can Jenkins build applications written in different programming languages?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Jenkins is language-agnostic. By installing the relevant tools, compilers, and plugins\u2014or by running build steps inside Docker containers\u2014Jenkins can automate projects written in Python, Node.js, Go, C++, C#, Rust, Ruby, or any other programming language.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What happens when a Jenkins test fails?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When an automated test fails, the test runner exits with a non-zero exit status. Jenkins detects this exit code, halts the pipeline to prevent broken code from advancing to packaging or deployment, flags the build as Failed (Red) or Unstable (Yellow), highlights the failing assertions on the dashboard, and notifies the team.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is Jenkins free to use?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Jenkins is open-source software released under the MIT License. It is completely free to download, install, modify, and use for personal, academic, or commercial projects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What should students learn after creating their first Jenkins pipeline?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">After mastering basic build and test automation, students should explore:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Running build agents dynamically inside <strong>Docker containers<\/strong>.<\/li>\n\n\n\n<li>Static code analysis and security auditing with <strong>SonarQube<\/strong>.<\/li>\n\n\n\n<li>Managing pull requests automatically using <strong>GitHub\/GitLab webhooks<\/strong>.<\/li>\n\n\n\n<li>Deploying applications to cloud infrastructure or container orchestration platforms like <strong>Kubernetes<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">16. Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mastering Jenkins transforms software development from an error-prone manual chore into a reliable, professional engineering discipline. By learning how to configure declarative pipelines, automate builds with Maven, and let automated test suites catch regressions early, students gain direct experience with the continuous integration workflows used across top tech teams. Building confidence in DevOps starts with these small, consistent experiments\u2014setting up a local server, intentionally breaking tests to learn how Jenkins handles failure, and gradually extending your pipeline with new tools. As you integrate automation into your academic assignments and personal projects, you not only eliminate late-night integration headaches but also develop the practical, job-ready CI\/CD skills essential for a successful career in software delivery.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction Every developer remembers the anxiety of working on a group programming project where everyone\u2019s code worked fine on their personal laptop, but everything shattered into cryptic errors once&hellip;<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1819","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/posts\/1819","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/comments?post=1819"}],"version-history":[{"count":1,"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/posts\/1819\/revisions"}],"predecessor-version":[{"id":1821,"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/posts\/1819\/revisions\/1821"}],"wp:attachment":[{"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/media?parent=1819"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/categories?post=1819"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devopsschool.org\/blog\/wp-json\/wp\/v2\/tags?post=1819"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}