Jenkins Lesson 8 – Freestyle Jobs | Dataplexa
Section I · Lesson 8

Freestyle Jobs

Every Jenkins engineer should build at least one Freestyle job — not because you'll use them forever, but because seeing one from the inside teaches you how Jenkins thinks. Let's build one from a blank screen to a passing build.

This lesson covers

Creating a Freestyle job → Configuring source control → Adding build steps → Reading build results → Understanding the six configuration sections

A Freestyle job is Jenkins at its most visual. Every setting lives in a form — dropdowns, checkboxes, text fields. No code, no files, no Groovy. You click your way to a working pipeline. That simplicity is exactly why it's the best starting point for understanding what Jenkins actually does under the hood, before the abstractions of Pipeline syntax take over.

Think of a Freestyle job as building flat-pack furniture with the instructions in front of you. Everything is visible, every step is explicit. Pipeline jobs are the same furniture assembled by someone who's done it a hundred times — faster, cleaner, but harder to follow if you've never seen the pieces.

The Six Sections of a Freestyle Job

When you open a Freestyle job's configuration page, Jenkins presents six collapsible sections — in this exact order. Every option you'll ever configure in a Freestyle job lives in one of these six buckets.

📝

1. General

Job description, display name, discard old builds, concurrent build settings. The basics.

📦

2. Source Code Management

Where Jenkins pulls your code from. Git repo URL, branch, credentials. This is the first real thing you configure.

3. Build Triggers

What starts the build — a schedule, a push to Git, another job finishing, or a manual click.

🏗️

4. Build Environment

Workspace cleanup, environment variables, SSH agent injection, abort if stuck. Pre-build housekeeping.

🔨

5. Build Steps

The actual commands that run — shell scripts, batch commands, Gradle tasks, Maven goals. This is where the work happens.

📬

6. Post-build Actions

What happens after — archive artifacts, send emails, trigger downstream jobs, publish test results.

Building the Job — Step by Step

Here's what the configuration form looks like when you wire up a real job. This mockup shows the three sections that matter most for a first build — SCM, Build Triggers, and Build Steps:

Jenkins — Configure: payment-service-build

📦 Source Code Management

Repository URL
https://github.com/acmecorp/payment-service.git
Credentials
github-deploy-key ▾
Branch
*/main

⚡ Build Triggers

🔨 Build Steps

# Execute shell
echo "Running tests for payment-service"
./gradlew clean test
echo "Build complete — exit code: $?"
+ Add build step

Creating a Freestyle Job via the CLI

The scenario:

You're a DevOps engineer at a retail startup. A developer has asked you to set up a Jenkins job that runs the test suite for the inventory-api service every time someone pushes to main. You want to create the job quickly using the CLI and an XML config file — no clicking through forms, no browser needed.

Tools used:

  • Jenkins config.xml — every Jenkins job is stored internally as an XML file called config.xml. You can create or update any job by sending a valid XML file to the Jenkins API. This is exactly the same format Jenkins uses internally to save jobs you configure via the UI.
  • curl -X POST — makes an HTTP POST request. We use this to send the XML config to Jenkins' createItem API endpoint, which creates a new job.
  • Content-Type: application/xml — this header tells Jenkins that the data we're sending is XML, not a form or JSON.
# Step 1: Create the job config XML file
# This defines a Freestyle job that checks out from Git and runs tests
cat > inventory-api-job.xml << 'EOF'


  
  Runs tests for the inventory-api service on every push to main

  
  
    10
  

  
  
    
      
        https://github.com/acmecorp/inventory-api.git
        github-deploy-key
      
    
    
      
      
        */main
      
    
  

  
  
    
      H/5 * * * *
    
  

  
  
    
      
        echo "Checking out inventory-api on $(date)"
        ./gradlew clean test
      
    
  

EOF

# Step 2: Send the XML to Jenkins to create the job
# --data-binary sends the file contents as the request body
curl \
  --user admin:your-api-token \
  -X POST \
  -H "Content-Type: application/xml" \
  --data-binary @inventory-api-job.xml \
  "http://jenkins-master-01:8080/createItem?name=inventory-api-test"

Where to practice: Run this against your local Docker Jenkins at http://localhost:8080. You'll need the Git plugin installed (it's included in Suggested Plugins from Lesson 6). After running the command, refresh your Jenkins dashboard — the new job appears immediately. Official Freestyle job docs at jenkins.io — Working with Projects.

  % Total    % Received % Xferd  Average Speed   Time    Total
                                 Dload  Upload   Total   Spent
100  1842    0     0  100  1842      0   6140  0:00:00 --:--:--  0:00:00

HTTP/1.1 200 OK
Date: Wed, 13 Mar 2024 09:22:14 GMT
X-Content-Type-Options: nosniff
Location: http://jenkins-master-01:8080/job/inventory-api-test/
Content-Length: 0
Server: Jetty(10.0.18)

What just happened?

  • HTTP/1.1 200 OK — the job was created successfully. Jenkins returns 200 for success, 400 if the XML is malformed, and 409 if a job with that name already exists.
  • Location: .../job/inventory-api-test/ — Jenkins tells you exactly where the new job lives. Paste that URL into your browser and you'll land directly on the job page.
  • Content-Length: 0 — the response body is empty, which is normal for a creation request. The success signal is the 200 status code, not the body.
  • The XML we sent is now stored as config.xml on the Jenkins master at /var/lib/jenkins/jobs/inventory-api-test/config.xml. That's the single source of truth for this job's configuration — the UI just reads and writes that file.
  • No browser required — creating jobs via the API means you can script job creation, store job configs in Git, and reproduce your entire Jenkins setup from code. This is the first step toward treating Jenkins configuration as code.

Triggering and Reading a Build

The scenario:

The job is created. Now you want to trigger it manually and immediately check whether it passed or failed — all without opening the browser. This is the workflow engineers use when scripting build automation or debugging from a remote terminal.

Tools used:

  • build (Jenkins CLI command) — triggers a job by name and optionally waits for it to finish before returning. The -s flag means "wait for the build to complete and print the result".
  • -v flag — verbose mode. Streams the console output to your terminal in real time while the build runs, exactly like watching it in the browser.
# Trigger the job and stream its console output to the terminal
# -s = wait for build to finish before returning
# -v = print the full console output while it runs
java -jar jenkins-cli.jar \
  -s http://jenkins-master-01:8080 \
  -auth admin:your-api-token \
  build inventory-api-test \
  -s -v

Where to practice: Download jenkins-cli.jar from http://localhost:8080/jnlpJars/jenkins-cli.jar if you haven't already. Then run this command from the same folder. You'll see the build output stream live in your terminal — the same output you'd see in the browser's Console Output page.

Started inventory-api-test #1
Started by user admin
Running as SYSTEM
Building in workspace /var/lib/jenkins/workspace/inventory-api-test
[inventory-api-test] $ /bin/sh -xe /tmp/jenkins3827456789.sh
+ echo 'Checking out inventory-api on Wed Mar 13 09:23:01 UTC 2024'
Checking out inventory-api on Wed Mar 13 09:23:01 UTC 2024
+ ./gradlew clean test
Downloading https://services.gradle.org/distributions/gradle-8.4-bin.zip

BUILD SUCCESSFUL in 54s
28 tests completed, 0 failed

Finished: SUCCESS

What just happened?

  • inventory-api-test #1 — this is the first build of this job. Jenkins numbers every build sequentially. If you run it again it will be #2, then #3. Build numbers never reset unless you manually delete them.
  • Running as SYSTEM — the build was triggered manually by an admin, so Jenkins runs it under the system account. Builds triggered by SCM polling run under a different context. This matters for permission-sensitive operations.
  • $ /bin/sh -xe /tmp/jenkins3827456789.sh — Jenkins writes your shell commands into a temporary script file and runs it. The -e flag means "exit immediately if any command fails" — which is how Jenkins knows to mark the build as FAILURE when a command returns a non-zero exit code.
  • Lines starting with + — these are the individual commands being executed, printed before their output. The -x in -xe causes this trace output. It's extremely useful for debugging — you can see exactly what ran.
  • 28 tests completed, 0 failed — this is Gradle's own output, not Jenkins'. Jenkins just captures and displays it. If any test had failed, Gradle would return exit code 1, Jenkins would catch that, and the build would finish as FAILURE.
  • Finished: SUCCESS — Jenkins' final verdict. The dashboard dot for this job will now be green.

The Limitation You'll Hit

Freestyle jobs store their entire configuration in the Jenkins UI — not in your code repository. That means if your Jenkins server dies, that job configuration is gone unless you backed it up. It also means your pipeline can't be reviewed in a pull request, and you can't see who changed what setting and when. This is the wall that pushes most teams toward Pipeline jobs — and why the next section of this course is entirely about Jenkinsfiles.

Teacher's Note

Build a Freestyle job once, understand every section, then move on. The real world runs on Pipelines.

Practice Questions

1. What is the name of the file Jenkins uses internally to store a job's full configuration?



2. In a Freestyle job, which configuration section contains the shell commands that actually run during the build?



3. What is the name of the Jenkins API endpoint used to create a new job by sending an XML config file?



Quiz

1. What does the -e flag in Jenkins' shell execution (/bin/sh -xe) do?


2. What is the biggest limitation of Freestyle jobs compared to Pipeline jobs?


3. In a Freestyle job, where would you configure Jenkins to send an email notification after the build finishes?


Up Next · Lesson 9

Build Lifecycle

What actually happens inside Jenkins from the moment a build triggers to the moment a result is recorded — every stage, every state, nothing skipped.