Skip to content
Back to skills

Jenkins Api

ASecurity

Integrates with the Jenkins REST API via python-jenkins and JenkinsAPI

  • 4 stars
  • 0 votes
  • 0 copies
  • 6 views
  • Added June 12, 2026
devopspythonrustgonodedockerkubernetesgitapidatabaseci/cd

Works with

  • cli
  • api

Security analysis

A100/100

Scanned June 12, 2026

npx -y skills add paulpas/agent-skill-router --skill jenkins-api --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Jenkins Api?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Jenkins Api
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-jenkins-api/badge)](https://www.skillsdirectory.com/skills/paulpas-jenkins-api)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---




name: jenkins-api
description: Integrates with the Jenkins REST API via python-jenkins and JenkinsAPI
  to manage jobs, builds, pipelines, credentials, plugins, nodes, and folder organization.
license: MIT
compatibility: opencode
metadata:
  version: "1.0.0"
  domain: coding
  triggers: jenkins api, python-jenkins, jenkinsapi, jenkins job, jenkins pipeline,
    jenkins build, jenkins plugin, jenkins credentials
  archetypes:
  - tactical
  - generation
  anti_triggers:
  - brainstorming
  - vague ideation
  - code golf
  - over-engineering
  response_profile:
    verbosity: low
    directive_strength: high
    abstraction_level: operational
  role: implementation
  scope: implementation
  output-format: code
  content-types:
  - code
  - guidance
  - do-dont
  - examples
  related-skills: coding-github-api, coding-gitlab-api, coding-circleci-api




---




# Jenkins API & python-jenkins Integration

Integrates with the Jenkins REST API using `python-jenkins` and `JenkinsAPI` libraries to automate jobs, builds, pipelines, credentials, plugins, nodes, folders, and system configuration.

## TL;DR for Code Generation

- [ ] Use `python-jenkins` (`jenkins.Jenkins`) for server administration (jobs, plugins, nodes, credentials)
- [ ] Use `JenkinsAPI` (`jenkinsapi.jenkins.Jenkins`) for build-centric workflows (artifacts, revisions, blocking)
- [ ] Authenticate with username + API token (not password) — tokens are generated in the Jenkins user profile
- [ ] Use the `tree` query parameter to filter API responses and reduce payload size
- [ ] Set a reasonable timeout (>=30s) for all Jenkins connections
- [ ] Handle `jenkins.JenkinsException` for auth failures and `requests.exceptions.ConnectionError` for connection issues

---

## When to Use

Use this skill when:

- Automating job creation, configuration, and deletion across Jenkins instances
- Building CI/CD pipelines that trigger builds and collect artifacts programmatically
- Managing Jenkins credentials, nodes, and plugin installations at scale
- Implementing build monitoring dashboards or metric collection pipelines
- Migrating jobs between Jenkins instances or upgrading plugin configurations
- Automating folder structure and view organization for large Jenkins deployments

---

## When NOT to Use

Avoid this skill for:

- Writing Jenkins Pipeline DSL (use the Jenkinsfile `pipeline {}` syntax and Groovy scripting)
- Configuring Jenkins as code at scale (use the Jenkins Configuration as Code (JCasC) plugin with YAML)
- Container orchestration (use `coding-kubernetes-api` or `coding-docker-api`)

---

## Core Workflow

1. **Connect to Jenkins** — Create a `jenkins.Jenkins(url, username, password_or_token)` instance. Use API tokens, not account passwords. **Checkpoint:** Call `server.get_version()` or `server.get_whoami()` to verify the connection and credentials.

2. **Inspect Server State** — Use `server.get_jobs()`, `server.get_plugins()`, `server.get_nodes()` to understand the current state. **Checkpoint:** Filter with `depth=2` or the `tree` parameter to limit response size on large instances.

3. **Manage Jobs** — Use `server.create_job(name, config_xml)`, `server.copy_job(from_name, to_name)`, `server.build_job(name, parameters)`. Job configurations use Jenkins XML format. **Checkpoint:** Verify the job appears in `server.get_jobs()` with the expected color/status.

4. **Monitor Builds** — Use `server.get_build_info(name, number)`, `server.get_build_console_output(name, number)`, or the JenkinsAPI `job.get_last_build()` method. **Checkpoint:** Check `build['result']` for SUCCESS, FAILURE, UNSTABLE, or ABORTED.

5. **Process Results** — Extract artifacts with `server.get_build_info()`'s artifacts list, console output with `get_build_console_output()`, and test results through the REST API. **Checkpoint:** Verify artifact URLs are accessible via the Jenkins web UI.

---

## Implementation Patterns

### Pattern 1: Job Management with python-jenkins

```python
import os
import xml.etree.ElementTree as ET
import jenkins
from jenkins import JenkinsException


def create_maven_job(
    job_name: str,
    git_repo_url: str,
    maven_goals: str = "clean package",
    branch: str = "*/main",
) -> dict:
    """Create a Jenkins Maven job with Git SCM configuration.

    Args:
        job_name: Name for the new Jenkins job.
        git_repo_url: Git repository URL.
        maven_goals: Maven goals to execute.
        branch: Branch specifier.

    Returns:
        Dict with job name and creation status.

    Raises:
        JenkinsException: If connection or job creation fails.
    """
    server = jenkins.Jenkins(
        os.environ["JENKINS_URL"],
        username=os.environ["JENKINS_USERNAME"],
        password=os.environ["JENKINS_API_TOKEN"],
        timeout=30,
    )

    # Build the config XML programmatically
    project = ET.Element("project")
    ET.SubElement(project, "description").text = f"Auto-created job: {job_name}"

    scm = ET.SubElement(project, "scm", attrib={"class": "hudson.plugins.git.GitSCM"})
    user_remote_configs = ET.SubElement(scm, "userRemoteConfigs")
    remote_config = ET.SubElement(user_remote_configs, "hudson.plugins.git.UserRemoteConfig")
    ET.SubElement(remote_config, "url").text = git_repo_url
    branches = ET.SubElement(scm, "branches")
    branch_spec = ET.SubElement(branches, "hudson.plugins.git.BranchSpec")
    ET.SubElement(branch_spec, "name").text = branch

    builders = ET.SubElement(project, "builders")
    maven = ET.SubElement(
        builders,
        "hudson.tasks.Maven",
        attrib={"mavenName": "Maven 3"},
    )
    ET.SubElement(maven, "targets").text = maven_goals

    config_xml = ET.tostring(project, encoding="unicode")

    try:
        server.create_job(job_name, config_xml)
    except JenkinsException as exc:
        if "already exists" in str(exc):
            # Job exists — reconfigure it
            server.reconfig_job(job_name, config_xml)
            return {"job_name": job_name, "status": "reconfigured"}
        raise RuntimeError(
            f"Failed to create Jenkins job '{job_name}': {exc}"
        ) from exc

    return {"job_name": job_name, "status": "created"}
```

### Pattern 2: Build Trigger and Artifact Collection

```python
import os
import time
import jenkins
from jenkins import JenkinsException
import requests


def trigger_build_and_wait(
    job_name: str,
    parameters: dict | None = None,
    poll_interval: int = 10,
    timeout: int = 1800,
) -> dict:
    """Trigger a Jenkins build and wait for completion.

    Args:
        job_name: Name of the Jenkins job.
        parameters: Build parameters for parameterized jobs.
        poll_interval: Seconds between build status checks.
        timeout: Maximum seconds to wait.

    Returns:
        Dict with build number, result, and console output.

    Raises:
        TimeoutError: If the build does not complete in time.
        JenkinsException: If the Jenkins server returns an error.
    """
    server = jenkins.Jenkins(
        os.environ["JENKINS_URL"],
        username=os.environ["JENKINS_USERNAME"],
        password=os.environ["JENKINS_API_TOKEN"],
        timeout=30,
    )

    # Trigger the build
    next_build_number = server.get_job_info(job_name)["nextBuildNumber"]
    server.build_job(job_name, parameters=parameters or {})

    # Poll for completion
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        try:
            build_info = server.get_build_info(job_name, next_build_number)
        except JenkinsException:
            # Build info may not be available immediately
            time.sleep(poll_interval)
            continue

        if build_info.get("building", True):
            time.sleep(poll_interval)
            continue

        # Build is complete — collect results
        console_output = server.get_build_console_output(job_name, next_build_number)
        return {
            "job_name": job_name,
            "build_number": next_build_number,
            "result": build_info["result"],
            "duration_ms": build_info.get("duration", 0),
            "console_output": console_output,
            "url": build_info["url"],
        }

    raise TimeoutError(
        f"Build {job_name}#{next_build_number} did not complete within {timeout}s."
    )
```

### Pattern 3: Plugin Management and Node Operations

```python
import os
import jenkins
from jenkins import JenkinsException


def install_plugins_and_create_node(
    plugins: list[str],
    node_name: str,
    node_remote_fs: str = "/home/jenkins",
    num_executors: int = 2,
    labels: str = "linux docker",
) -> dict:
    """Install Jenkins plugins and create a new permanent agent node.

    Args:
        plugins: List of plugin short names to install.
        node_name: Name for the new node.
        node_remote_fs: Remote root directory on the node.
        num_executors: Number of concurrent executors.
        labels: Space-separated label list.

    Returns:
        Dict with installation status and node info.
    """
    server = jenkins.Jenkins(
        os.environ["JENKINS_URL"],
        username=os.environ["JENKINS_USERNAME"],
        password=os.environ["JENKINS_API_TOKEN"],
        timeout=60,
    )

    # Install plugins
    plugin_results: dict[str, str] = {}
    for plugin in plugins:
        try:
            if server.get_plugin_info(plugin):
                plugin_results[plugin] = "already_installed"
                continue
        except JenkinsException:
            pass

        try:
            server.install_plugin(plugin)
            plugin_results[plugin] = "installing"
        except JenkinsException as exc:
            plugin_results[plugin] = f"failed: {exc}"

    # Create a permanent agent node
    try:
        server.create_node(
            name=node_name,
            num_executors=num_executors,
            remote_fs=node_remote_fs,
            labels=labels,
        )
        node_status = "created"
    except JenkinsException as exc:
        if "already exists" in str(exc):
            node_status = "already_exists"
        else:
            node_status = f"failed: {exc}"

    return {
        "plugin_results": plugin_results,
        "node": {"name": node_name, "status": node_status},
    }
```

### BAD vs GOOD: Jenkins API Error Handling

```python
# ❌ BAD — no timeout, no version check, password instead of token
def connect_bad(url, user, password):
    server = jenkins.Jenkins(url, user, password)
    return server  # May hang or silently fail auth!

# ✅ GOOD — typed, with timeout, version verification, and token auth
def connect_good(
    url: str,
    username: str,
    api_token: str,
    timeout: int = 30,
) -> jenkins.Jenkins:
    """Connect to a Jenkins server and verify credentials.

    Args:
        url: Full URL to Jenkins server (e.g., "https://jenkins.example.com").
        username: Jenkins username.
        api_token: Jenkins API token (from user profile).
        timeout: Connection and read timeout in seconds.

    Returns:
        Authenticated Jenkins server instance.

    Raises:
        RuntimeError: If connection or authentication fails.
    """
    if not url or not username or not api_token:
        raise ValueError("Jenkins URL, username, and API token are required.")

    server = jenkins.Jenkins(url, username, api_token, timeout=timeout)
    try:
        version = server.get_version()
        user_info = server.get_whoami()
    except JenkinsException as exc:
        raise RuntimeError(
            f"Failed to connect or authenticate to Jenkins at '{url}': {exc}"
        ) from exc

    print(f"Connected to Jenkins v{version} as '{user_info.get('fullName', 'unknown')}'")
    return server
```

## MUST DO

- Use API tokens (generated in Jenkins user profile) instead of account passwords
- Set a timeout >= 30 seconds on all `jenkins.Jenkins` connections
- Use the `tree` query parameter to filter API responses — `?tree=jobs[name,url,color]` reduces payloads significantly
- Poll build status with appropriate intervals (10s minimum) to avoid overwhelming the server
- Use `server.get_whoami()` to verify authentication immediately after connecting
- Check `build['result']` is not None — a running build returns `result: None`

## MUST NOT DO

- Never use account passwords for Jenkins API access — always generate and use API tokens
- Do not make API calls without setting a timeout — Jenkins can hang on unresponsive instances
- Avoid polling builds more frequently than every 10 seconds — use webhooks for real-time updates
- Never hardcode Jenkins URLs or credentials in source code — use environment variables
- Do not assume `get_build_info` returns immediately after `build_job` — builds may be queued
- Never delete jobs or nodes without verifying the correct name and confirming no active builds

---

## Constraints

### MUST DO
- Implement structured error responses with consistent format: {error_code, message, details, request_id}
- Add rate limiting per client/API key with configurable burst and sustained limits using a token bucket algorithm
- Validate all incoming requests against a schema before processing — reject malformed input with clear error messages
- Include correlation/request IDs in all log entries for end-to-end request tracing across service boundaries

### MUST NOT DO
- Do not expose internal implementation details, stack traces, or database queries in error responses
- Avoid accepting unbounded request bodies — set maximum payload sizes and timeout limits
- Never trust client-supplied authentication tokens without validation (signature verification, expiration check)
- Do not log request/response bodies containing PII, API keys, or other sensitive data


## Live References

- [python-jenkins Documentation](https://python-jenkins.readthedocs.io/en/latest/)
- [python-jenkins GitHub Repository](https://opendev.org/jjb/python-jenkins)
- [JenkinsAPI on PyPI](https://pypi.org/project/jenkinsapi/)
- [JenkinsAPI Documentation](http://pycontribs.github.io/jenkinsapi/)
- [Jenkins REST API Reference](https://www.jenkins.io/doc/book/using/remote-access-api/)
- [Jenkins API Token Authentication](https://www.jenkins.io/blog/2018/07/02/new-api-token-system/)
- [Jenkins Job DSL API](https://jenkinsci.github.io/job-dsl-plugin/)

## Related Skills

| Skill | Purpose |
|---|---|
| `coding-github-api` | GitHub API for triggering Jenkins builds via webhooks |
| `coding-gitlab-api` | GitLab CI/CD as an alternative to Jenkins pipelines |
| `coding-circleci-api` | CircleCI API as a cloud-native CI/CD alternative |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.