Ravindra BagaleCourses & study guides मराठी

Chapter 31: Backup, Configuration as Code and Jenkins Operations

31.7 REST and CLI that start a job

Why: the problem

Suppose we are on the Ola team. A release tool must start the badge-api deploy job after a ticket is approved. Nobody should click in Jenkins at night. Jenkins has a REST API and a CLI. With an API token and the right permission, a script can start a job with parameters, wait, and read the result.

What we will build

You will start a parameterised job from curl, from the Jenkins CLI jar, and from a small Python script, then wait for the result.

What: every term in plain English

  • REST API — HTTP URLs that let programs talk to Jenkins.
  • API token — A per-user token used instead of a password. Made on your user page.
  • Crumb — A CSRF protection value. API tokens usually do not need it.
  • buildWithParameters — The URL that starts a job with parameters.
  • Queue item — Where a build waits before it starts. Its URL leads to the build number.
  • jenkins-cli.jar — The Jenkins command line client.
Make a token Store it for this shell Check who you are Start the job Find the build number Wait for the result Same with the CLI
REST trigger: token, POST, queue, build number, result

How: step by step

  1. Make a token

    User menu > Security > API Token > Add new token
    

    What it does: Copy it once into a secret store or env var.

    Output

    (token shown once)
    
  2. Store it for this shell

    read -rs JENKINS_TOKEN && export JENKINS_TOKEN
    

    What it does: Not in history, not in files.

    Output

    (no output)
    
  3. Check who you are

    curl -s -u ravi:$JENKINS_TOKEN localhost:8080/me/api/json | jq -r .id
    

    What it does: The token works.

    Output

    ravi
    
  4. Start the job

    curl -s -i -X POST -u ravi:$JENKINS_TOKEN "localhost:8080/job/badge-deploy/buildWithParameters?ENV=staging&VERSION=1.4.2" | grep -i location
    

    What it does: Returns a queue URL.

    Output

    Location: http://localhost:8080/queue/item/912/
    
  5. Find the build number

    curl -s -u ravi:$JENKINS_TOKEN localhost:8080/queue/item/912/api/json | jq .executable.number
    

    What it does: Once started, the queue item points to the build.

    Output

    57
    
  6. Wait for the result

    curl -s -u ravi:$JENKINS_TOKEN localhost:8080/job/badge-deploy/57/api/json | jq -r ".building, .result"
    

    What it does: building false and result SUCCESS means done.

    Output

    false
    SUCCESS
    
  7. Same with the CLI

    java -jar jenkins-cli.jar -s http://localhost:8080/ -auth ravi:$JENKINS_TOKEN build badge-deploy -p ENV=staging -p VERSION=1.4.2 -s -v | tail -2
    

    What it does: -s waits, -v prints the console.

    Output

    Finished: SUCCESS
    Completed badge-deploy #58 : SUCCESS
    

Example 1: Bash with curl: start, wait, and exit with the build result

Stack. bash, curl, jq

Goal. Bash with curl: start, wait, and exit with the build result.

trigger.sh

#!/usr/bin/env bash
# trigger.sh ENV VERSION - start badge-deploy and wait for it
set -euo pipefail
J=http://localhost:8080; JOB=badge-deploy; AUTH="ravi:${JENKINS_TOKEN:?set JENKINS_TOKEN}"
Q=$(curl -s -i -X POST -u "$AUTH" "$J/job/$JOB/buildWithParameters?ENV=$1&VERSION=$2" | awk -F": " "/^[Ll]ocation/{print \$2}" | tr -d "\r")
until N=$(curl -s -u "$AUTH" "${Q}api/json" | jq -er .executable.number); do sleep 3; done
echo "started #$N"
while [ "$(curl -s -u "$AUTH" "$J/job/$JOB/$N/api/json" | jq -r .building)" = true ]; do sleep 10; done
R=$(curl -s -u "$AUTH" "$J/job/$JOB/$N/api/json" | jq -r .result)
echo "result $R"; [ "$R" = SUCCESS ]

What each line does

  • ${JENKINS_TOKEN:?...} — Stops if the token is not set.
  • Location header — The queue item URL.
  • jq -er .executable.number — Fails until the build has started.
  • [ "$R" = SUCCESS ] — Script exit code follows the build result.

Green output

$ bash trigger.sh staging 1.4.2
started #57
result SUCCESS

Expected result. Any tool that runs a script can now start the deploy.

Example 2: Python: the same flow with requests, for release tools written in Python

Stack. Python 3.12, requests

Goal. Python: the same flow with requests, for release tools written in Python.

trigger.py

# trigger.py - start a Jenkins job and wait (python3 trigger.py staging 1.4.2)
import os, sys, time, requests
J = "http://localhost:8080"; JOB = "badge-deploy"
auth = ("ravi", os.environ["JENKINS_TOKEN"])
r = requests.post(f"{J}/job/{JOB}/buildWithParameters",
                  params={"ENV": sys.argv[1], "VERSION": sys.argv[2]}, auth=auth, timeout=10)
r.raise_for_status()
queue = r.headers["Location"]
while True:
    item = requests.get(queue + "api/json", auth=auth, timeout=10).json()
    if item.get("executable"): break
    time.sleep(3)
n = item["executable"]["number"]; print("started", n)
while True:
    b = requests.get(f"{J}/job/{JOB}/{n}/api/json", auth=auth, timeout=10).json()
    if not b["building"]: break
    time.sleep(10)
print("result", b["result"]); sys.exit(0 if b["result"] == "SUCCESS" else 1)

What each line does

  • os.environ["JENKINS_TOKEN"] — The token comes from the environment.
  • raise_for_status() — Stop on 401 or 404.
  • headers["Location"] — Queue URL.
  • sys.exit(...) — Exit code for the calling tool.

Green output

$ python3 trigger.py staging 1.4.2
started 58
result SUCCESS

Expected result. Same result from Python.

Example 3: Jenkins CLI: a short command for admins with the CLI jar

Stack. Java 17, jenkins-cli.jar

Goal. Jenkins CLI: a short command for admins with the CLI jar.

commands

curl -s -O localhost:8080/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s http://localhost:8080/ -auth ravi:$JENKINS_TOKEN who-am-i
java -jar jenkins-cli.jar -s http://localhost:8080/ -auth ravi:$JENKINS_TOKEN list-jobs | head -3
java -jar jenkins-cli.jar -s http://localhost:8080/ -auth ravi:$JENKINS_TOKEN build badge-deploy -p ENV=staging -p VERSION=1.4.2 -s -v

What each line does

  • jnlpJars/jenkins-cli.jar — The jar matches your Jenkins version.
  • -auth user:token — Logs in with the token.
  • -s — Wait for the build.
  • -v — Print the console output.

Green output

Authenticated as: ravi
badge-api
badge-deploy
smoke-test
Completed badge-deploy #59 : SUCCESS

Expected result. The CLI is handy for admins; scripts usually use REST.

Example 4: Start a job and wait for its result from a script

Stack. Jenkins REST

Goal. Start a job and wait for its result from a script.

trigger-wait.sh

#!/usr/bin/env bash
set -euo pipefail
J=http://localhost:8080/job/release-tool
loc=$(curl -si -u "admin:$JENKINS_TOKEN" -X POST "$J/buildWithParameters?VERSION=1.4.2" | awk '/^Location:/{print $2}' | tr -d '\r')
until num=$(curl -s -u "admin:$JENKINS_TOKEN" "${loc}api/json" | jq -er '.executable.number'); do sleep 2; done
until [ "$(curl -s -u "admin:$JENKINS_TOKEN" "$J/$num/api/json" | jq -r .building)" = false ]; do sleep 5; done
curl -s -u "admin:$JENKINS_TOKEN" "$J/$num/api/json" | jq -r '"build \(.number): \(.result)"' 

What each line does

  • Location header — Points to the queue item.
  • executable.number — The build number once it starts.
  • building false — The build finished.

Green output

build 57: SUCCESS

Expected result. The release tool knows the real result, not just that it clicked Build.

Verify: did it work?

  1. See the builds

    curl -s -u ravi:$JENKINS_TOKEN "localhost:8080/job/badge-deploy/api/json?tree=builds[number,result]{0,3}" | jq -c .builds
    

    What it does: Three newest builds.

    Output

    [{"number":59,"result":"SUCCESS"},{"number":58,"result":"SUCCESS"},{"number":57,"result":"SUCCESS"}]
    
  2. See parameters used

    curl -s -u ravi:$JENKINS_TOKEN localhost:8080/job/badge-deploy/59/api/json | jq -c "[.actions[]|select(.parameters)|.parameters[]|{name,value}]"
    

    What it does: Proves what was asked.

    Output

    [{"name":"ENV","value":"staging"},{"name":"VERSION","value":"1.4.2"}]
    
  3. See who started it

    curl -s -u ravi:$JENKINS_TOKEN localhost:8080/job/badge-deploy/59/api/json | jq -r ".actions[]|select(.causes)|.causes[0].shortDescription"
    

    What it does: Audit trail.

    Output

    Started by user ravi
    

When it is red 1

HTTP/1.1 401 Unauthorized

Cause. Wrong user or token.

Fix, step by step

  1. Check the user id, not the display name.
  2. Make a new token if needed.

When it is red 2

HTTP/1.1 403 No valid crumb was included in the request

Cause. Password used instead of a token, or an old setup.

Fix, step by step

  1. Use an API token.
  2. Or fetch a crumb from /crumbIssuer/api/json in the same session.

When it is red 3

HTTP/1.1 400 Nothing is submitted

Cause. Job has parameters but you called /build without them.

Fix, step by step

  1. Use /buildWithParameters.

When it is red 4

HTTP 403 No valid crumb was included in the request

Cause. Using a password instead of an API token.

Fix, step by step

  1. Create an API token for the user.
  2. Use admin:TOKEN in curl.

Cleanup

  1. Revoke the lab token

    User menu > Security > API Token > Revoke
    

    What it does: Old tokens are a risk.

    Output

    Token revoked
    

Practice tasks

Easy Call /me

Why: Check your token.

What to do: curl /me/api/json.

How:
  1. Use -u user:token.

Check: Your id prints.

Medium Use tree filter

Why: Smaller answers.

What to do: Fetch only number and result.

How:
  1. Add ?tree=number,result

Check: Short JSON.

Hard Limit the bot user

Why: Least privilege.

What to do: Make a user that can only build badge-deploy.

How:
  1. Use Role-based or Matrix authorization.

Check: It cannot configure jobs.

Easy Say REST and CLI triggers in two lines

Why: If you can say it simply, you understand it.

What to do: Write two short lines about REST and CLI triggers for a fresher.

How:
  1. Write the problem.
  2. Write the command or file you use.

Check: A fresher understands it.

Easy Start a fresh lab Jenkins

Why: Practice needs a throwaway Jenkins.

What to do: Run Jenkins LTS in Docker with a named volume.

How:
  1. docker volume create jenkins_home
  2. docker run -d --name jenkins -p 8080:8080 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk17
  3. docker logs jenkins | grep -A2 "initialAdminPassword"

Check: The Jenkins login page opens on localhost:8080.

Medium Do it on the second setup

Why: The idea must work on VM, Docker and Kubernetes.

What to do: Repeat this lesson on a different setup than the one you used.

How:
  1. Pick Docker if you used a VM, or kind if you used Docker.
  2. Run the same steps.

Check: Same result on the second setup.

Medium Break it on purpose

Why: You must know the red output by face.

What to do: Cause one error from "When it is red" and fix it.

How:
  1. Follow the error section.
  2. Write down the exact message.

Check: You fixed it using the steps.

Medium Write a runbook page

Why: At 2 a.m. nobody remembers.

What to do: Write a one-page runbook for this lesson.

How:
  1. Title, when to use, steps, how to check.

Check: A teammate can follow it alone.

Hard Explain it like an interview

Why: Interviewers want real stories.

What to do: Record a 60 second answer.

How:
  1. Problem, command, one error you hit.

Check: Your answer has a real command and a real error.

Hard Draw the flow top to bottom

Why: A drawing shows the order.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at the trigger, end at the check.

Check: Each box matches a real step you ran.

Homework: try at home

Try at home

At home, write trigger.sh for your lab job and make it exit 1 when the build fails, then use it from another Jenkins job.

Recap

  • Use API tokens, never passwords, for scripts.
  • buildWithParameters returns a queue URL.
  • The queue item gives the build number.
  • Poll the build until building is false.
  • Give bot users only the rights they need.

FAQ

Can I trigger without a user?

Use a bot user with a token and minimal rights.

What is a remote build token?

An old per-job token. Prefer user API tokens.

Can I get logs by API?

Yes, /consoleText or /logText/progressiveText.

Is the CLI over SSH?

It can be, but HTTP with -auth is simpler.

How do I stop a build?

POST /job/NAME/N/stop.

Should the token belong to a person?

No. Use a service user with only Build rights on that job.

Interview questions

  1. How do you trigger Jenkins from another system?

    POST to buildWithParameters with a bot user API token, follow the queue item, poll the result.

  2. What is a crumb?

    CSRF token for browser-style requests.

  3. How do you secure API access?

    Bot users, tokens in secret stores, least privilege, revoke old tokens.

  4. How do you read results?

    /job/NAME/N/api/json result field.

  5. CLI vs REST?

    CLI is handy for admins; REST is easiest for tools.

Quick quiz

Q1. Which URL starts a job with parameters?

/job/NAME/buildWithParameters.

Q2. What do you use instead of a password?

An API token.

Q3. Where do you find the build number?

The queue item executable.number.

Q4. What does CLI -s do?

Waits for the build.

Q5. Where should the token live?

In an env var or secret store.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards