Skip to main content

Jenkins

Our Jenkins integration allows you to import jobs, builds, and users from your Jenkins environment into Port, according to your mapping and definitions.

Common use cases

  • Map jobs, builds, and users in your Jenkins environment.
  • Watch for object changes (create/update/delete) in real-time, and automatically apply the changes to your entities in Port.

Prerequisites

To install the integration, you need a Kubernetes cluster that the integration's container chart will be deployed to.

Please make sure that you have kubectl and helm installed on your machine, and that your kubectl CLI is connected to the Kubernetes cluster where you plan to install the integration.

Troubleshooting

If you are having trouble installing this integration, please refer to these troubleshooting steps.

To generate a token for authenticating the Jenkins API calls:

  1. In the Jenkins banner frame, click your user name to open the user menu.
  2. Navigate to Your Username > Configure > API Token.
  3. Click Add new Token.
  4. Click Generate.
  5. Copy the API token that is generated to use as the JENKINS_TOKEN.

Installation

Choose one of the following installation methods:

Using this installation option means that the integration will be able to update Port in real time using webhooks.

This table summarizes the available parameters for the installation. Set them as you wish in the script below, then copy it and run it in your terminal:

ParameterDescriptionRequired
port.clientIdYour port client id (Get the credentials)
port.clientSecretYour port client secret (Get the credentials)
integration.identifierChange the identifier to describe your integration
integration.typeThe integration type
integration.eventListener.typeThe event listener type
integration.secrets.jenkinsUserThe Jenkins username
integration.secrets.jenkinsTokenThe Jenkins password or token
integration.config.jenkinsHostThe Jenkins host
integration.config.appHostThe host of the Port Ocean app. Used to set up the integration endpoint as the target for webhooks created in Jenkins
scheduledResyncIntervalThe number of minutes between each resync
initializePortResourcesDefault true, When set to true the integration will create default blueprints and the port App config Mapping

helm repo add --force-update port-labs https://port-labs.github.io/helm-charts
helm upgrade --install my-jenkins-integration port-labs/port-ocean \
--set port.clientId="PORT_CLIENT_ID" \
--set port.clientSecret="PORT_CLIENT_SECRET" \
--set initializePortResources=true \
--set scheduledResyncInterval=120 \
--set integration.identifier="my-jenkins-integration" \
--set integration.type="jenkins" \
--set integration.eventListener.type="POLLING" \
--set integration.secrets.jenkinsUser="JENKINS_USER" \
--set integration.secrets.jenkinsToken="JENKINS_TOKEN" \
--set integration.config.jenkinsHost="JENKINS_HOST"
Advanced integration configuration

For advanced configuration such as proxies or self-signed certificates, click here.

Ingesting Jenkins objects

The Jenkins integration uses a YAML configuration to describe the process of loading data into the developer portal.

Here is an example snippet from the config which demonstrates the process for getting job data from Jenkins:

createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: job
selector:
query: "true"
port:
entity:
mappings:
identifier: .url | split("://")[1] | sub("^.*?/"; "") | gsub("%20"; "-") | gsub("/"; "-") | .[:-1]
title: .fullName
blueprint: '"jenkinsJob"'
properties:
jobName: .name
url: .url
jobStatus: '{"notbuilt": "created", "blue": "passing", "red": "failing"}[.color]'
timestamp: .time

The integration makes use of the JQ JSON processor to select, modify, concatenate, transform and perform other operations on existing fields and values from Jenkins's API events.

Configuration structure

The integration configuration determines which resources will be queried from Jenkins, and which entities and properties will be created in Port.

  • The root key of the integration configuration is the resources key:

    resources:
    - kind: job
    selector:
    ...
  • The kind key is a specifier for a Jenkins object:

      resources:
    - kind: job
    selector:
    ...
  • The selector and the query keys allow you to filter which objects of the specified kind will be ingested into your software catalog:

    resources:
    - kind: job
    selector:
    query: "true" # JQ boolean expression. If evaluated to false - this object will be skipped.
    port:
  • The port, entity and the mappings keys are used to map the Jenkins object fields to Port entities. To create multiple mappings of the same kind, you can add another item in the resources array;

    resources:
    - kind: job
    selector:
    query: "true"
    port:
    entity:
    mappings: # Mappings between one Jenkins object to a Port entity. Each value is a JQ query.
    identifier: .url | split("://")[1] | sub("^.*?/"; "") | gsub("%20"; "-") | gsub("/"; "-") | .[:-1]
    title: .fullName
    blueprint: '"jenkinsJob"'
    properties:
    jobName: .name
    url: .url
    jobStatus: '{"notbuilt": "created", "blue": "passing", "red": "failing"}[.color]'
    timestamp: .time
    - kind: job # In this instance job is mapped again with a different filter
    selector:
    query: '.name == "MyJobName"'
    port:
    entity:
    mappings: ...
    Blueprint key

    Note the value of the blueprint key - if you want to use a hardcoded string, you need to encapsulate it in 2 sets of quotes, for example use a pair of single-quotes (') and then another pair of double-quotes (")

Ingest data into Port

To ingest Jenkins objects using the integration configuration, you can follow the steps below:

  1. Go to the DevPortal Builder page.
  2. Select a blueprint you want to ingest using Jenkins.
  3. Choose the Ingest Data option from the menu.
  4. Select Jenkins under the CI/CD category.
  5. Modify the configuration according to your needs.
  6. Click Resync.

Examples

Examples of blueprints and the relevant integration configurations:

Job

Job blueprint
{
"identifier": "jenkinsJob",
"description": "This blueprint represents a job in Jenkins",
"title": "Jenkins Job",
"icon": "Jenkins",
"schema": {
"properties": {
"jobName": {
"type": "string",
"title": "Job Name"
},
"jobStatus": {
"type": "string",
"title": "Job Status",
"enum": [
"created",
"unknown",
"passing",
"failing"
],
"enumColors": {
"passing": "green",
"created": "darkGray",
"failing": "red",
"unknown": "orange"
}
},
"timestamp": {
"type": "string",
"format": "date-time",
"title": "Timestamp",
"description": "Last updated timestamp of the job"
},
"url": {
"type": "string",
"title": "Project URL"
},
"parentJob": {
"type": "object",
"title": "Parent Job"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: job
selector:
query: "true"
port:
entity:
mappings:
identifier: .url | split("://")[1] | sub("^.*?/"; "") | gsub("%20"; "-") | gsub("/"; "-") | .[:-1]
title: .fullName
blueprint: '"jenkinsJob"'
properties:
jobName: .name
url: .url
jobStatus: '{"notbuilt": "created", "blue": "passing", "red": "failing"}[.color]'
timestamp: .time
parentJob: .__parentJob

Build

Build blueprint
{
"identifier": "jenkinsBuild",
"description": "This blueprint represents a build event from Jenkins",
"title": "Jenkins Build",
"icon": "Jenkins",
"schema": {
"properties": {
"buildStatus": {
"type": "string",
"title": "Build Status",
"enum": [
"SUCCESS",
"FAILURE",
"UNSTABLE"
],
"enumColors": {
"SUCCESS": "green",
"FAILURE": "red",
"UNSTABLE": "yellow"
}
},
"buildUrl": {
"type": "string",
"title": "Build URL",
"description": "URL to the build"
},
"timestamp": {
"type": "string",
"format": "date-time",
"title": "Timestamp",
"description": "Last updated timestamp of the build"
},
"buildDuration": {
"type": "number",
"title": "Build Duration",
"description": "Duration of the build"
}
},
"required": []
},
"mirrorProperties": {
"previousBuildStatus": {
"title": "Previous Build Status",
"path": "previousBuild.buildStatus"
}
},
"calculationProperties": {},
"relations": {
"parentJob": {
"title": "Jenkins Job",
"target": "jenkinsJob",
"required": false,
"many": false
},
"previousBuild": {
"title": "Previous Build",
"target": "jenkinsBuild",
"required": false,
"many": false
}
}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: build
selector:
query: "true"
port:
entity:
mappings:
identifier: .url | split("://")[1] | sub("^.*?/"; "") | gsub("%20"; "-") | gsub("/"; "-") | .[:-1]
title: .displayName
blueprint: '"jenkinsBuild"'
properties:
buildStatus: .result
buildUrl: .url
buildDuration: .duration
timestamp: '.timestamp / 1000 | todate'
relations:
parentJob: .url | split("://")[1] | sub("^.*?/"; "") | gsub("%20"; "-") | gsub("/"; "-") | .[:-1] | gsub("-[0-9]+$"; "")
previousBuild: .previousBuild.url | split("://")[1] | sub("^.*?/"; "") | gsub("%20"; "-") | gsub("/"; "-") | .[:-1]

User

User blueprint
{
"identifier": "jenkinsUser",
"description": "This blueprint represents a jenkins user",
"title": "Jenkins User",
"icon": "Jenkins",
"schema": {
"properties": {
"url": {
"type": "string",
"title": "URL",
"format": "url"
},
"lastUpdateTime": {
"type": "string",
"format": "date-time",
"title": "Last Update",
"description": "Last updated timestamp of the user"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: user
selector:
query: "true"
port:
entity:
mappings:
identifier: .user.id
title: .user.fullName
blueprint: '"jenkinsUser"'
properties:
url: .user.absoluteUrl
lastUpdateTime: if .lastChange then (.lastChange/1000) else now end | strftime("%Y-%m-%dT%H:%M:%SZ")