【Jenkins】Blue Ocean REST API でパイプライン情報を取得する

CI/CD

はじめに

こんにちは株式会社TIELECのタカシユウトです。この記事ではJenkinsのBlue Ocean REST APIについて紹介します。Blue Ocean REST APIは、Blue Ocean UIで表示される情報をプログラムから取得するためのAPIです。

Blue Ocean REST API

https://github.com/jenkinsci/blueocean-plugin/tree/master/blueocean-rest

最後にBlue Ocean REST APIについての紹介です。 こちらはJenkinsのBlue Oceanのプラグインを入れことにより使えるようになります。

エンドポイントはJenkinsのURLの後ろに/blue/restをつけたものになります。

usersearchなど様々なエンドポイントがありそうですがよく使いそうなのはとorganizationsになりそうです。

Jenkinsのジョブの情報などを取得する際もorganizationsを使って確認していきます。

では実際に確認していきましょう。 /blue/rest/organizations http://jenkins.tielec.blog:8080/blue/rest/organizations/

[ 
   { 
      "_class":"io.jenkins.blueocean.service.embedded.rest.OrganizationImpl",
      "_links":{ 
         "pipelines":{ 
            "_class":"io.jenkins.blueocean.rest.hal.Link",
            "href":"/blue/rest/organizations/jenkins/pipelines/"
         },
         "self":{ 
            "_class":"io.jenkins.blueocean.rest.hal.Link",
            "href":"/blue/rest/organizations/jenkins/"
         },
         "user":{ 
            "_class":"io.jenkins.blueocean.rest.hal.Link",
            "href":"/blue/rest/organizations/jenkins/user/"
         },
         "users":{ 
            "_class":"io.jenkins.blueocean.rest.hal.Link",
            "href":"/blue/rest/organizations/jenkins/users/"
         }
      },
      "displayName":"Jenkins",
      "name":"jenkins"
   }
]

エンドポイントの情報が見れています。

今回もジョブの情報を見るところまでやっていきたいので、pipelinesを開いてみます。

パイプラインの情報を取得する

Jsonをクリックで展開します

{
  "_class": "io.jenkins.blueocean.service.embedded.rest.PipelineFolderImpl",
  "_links": {
    "self": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/"
    },
    "scm": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/scm/"
    },
    "actions": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/actions/"
    },
    "runs": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/runs/"
    },
    "trends": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/trends/"
    },
    "queue": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/queue/"
    }
  },
  "actions": [],
  "disabled": false,
  "displayName": "decrative-pipeline",
  "fullDisplayName": "decrative-pipeline",
  "fullName": "decrative-pipeline",
  "name": "decrative-pipeline",
  "organization": "jenkins",
  "parameters": null,
  "permissions": {
    "create": false,
    "configure": false,
    "read": true,
    "start": true,
    "stop": false
  },
  "numberOfFolders": 0,
  "numberOfPipelines": 25,
  "pipelineFolderNames": [
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null
  ]
}

フォルダの名称等はわかりましたが、piplineの一覧みたいな情報は取れませんでした。


ジョブの詳細を取得

ジョブの詳細を取得する場合はさらにURLの後ろにジョブ名を追加します。 http://jenkins.tielec.blog:8080/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/03_write_file/


{
  "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineImpl",
  "_links": {
    "self": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
    },
    "scm": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/scm/"
    },
    "actions": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/actions/"
    },
    "runs": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/"
    },
    "trends": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/trends/"
    },
    "queue": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/queue/"
    }
  },
  "actions": [],
  "disabled": false,
  "displayName": "03_write_file",
  "estimatedDurationInMillis": 18597,
  "fullDisplayName": "decrative-pipeline/03_write_file",
  "fullName": "decrative-pipeline/03_write_file",
  "latestRun": {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineImpl$PipelineRunSummary",
    "_links": {
      "prevRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/"
      },
      "parent": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
      },
      "tests": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/tests/"
      },
      "log": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/log/"
      },
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/"
      },
      "blueTestSummary": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/blueTestSummary/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/actions/"
      },
      "changeSet": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/changeSet/"
      },
      "artifacts": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/artifacts/"
      }
    },
    "actions": [],
    "artifactsZipFile": null,
    "causeOfBlockage": null,
    "causes": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Started by upstream project "decrative-pipeline/08_parallel_step" build number 9",
        "upstreamBuild": 9,
        "upstreamProject": "decrative-pipeline/08_parallel_step",
        "upstreamUrl": "job/decrative-pipeline/job/08_parallel_step/"
      }
    ],
    "description": null,
    "durationInMillis": 47339,
    "enQueueTime": "2019-08-30T12:43:06.337+0900",
    "endTime": "2019-08-30T12:43:53.687+0900",
    "estimatedDurationInMillis": 18597,
    "id": "17",
    "name": null,
    "organization": "jenkins",
    "pipeline": "03_write_file",
    "replayable": true,
    "result": "SUCCESS",
    "runSummary": "stable",
    "startTime": "2019-08-30T12:43:06.348+0900",
    "state": "FINISHED",
    "type": "WorkflowRun",
    "changeSet": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.ChangeSetResource",
        "_links": {
          "self": {
            "_class": "io.jenkins.blueocean.rest.hal.Link",
            "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/changeSet/2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f/"
          }
        },
        "affectedPaths": [
          "pipeline/decrative-pipeline/pipeline_19_random_kitten_generator.groovy"
        ],
        "author": {
          "_class": "io.jenkins.blueocean.service.embedded.rest.UserImpl",
          "_links": {
            "favorites": {
              "_class": "io.jenkins.blueocean.rest.hal.Link",
              "href": "/blue/rest/users/noreply/favorites/"
            },
            "self": {
              "_class": "io.jenkins.blueocean.rest.hal.Link",
              "href": "/blue/rest/users/noreply/"
            }
          },
          "avatar": null,
          "email": null,
          "fullName": "noreply",
          "id": "noreply",
          "permission": null
        },
        "checkoutCount": 0,
        "commitId": "2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f",
        "issues": [],
        "msg": "Update pipeline_19_random_kitten_generator.groovy",
        "timestamp": "2019-08-10T19:11:25.000+0900",
        "url": "https://github.com/sakamaki-y123/jenkins-continuous-delivery/commit/2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f"
      }
    ]
  },
  "name": "03_write_file",
  "organization": "jenkins",
  "parameters": [
    {
      "_class": "hudson.model.TextParameterDefinition",
      "defaultParameterValue": {
        "_class": "hudson.model.StringParameterValue",
        "name": "OUTPUT_TEXT",
        "value": ""
      },
      "description": "",
      "name": "OUTPUT_TEXT",
      "type": "TextParameterDefinition"
    }
  ],
  "permissions": {
    "create": false,
    "configure": false,
    "read": true,
    "start": true,
    "stop": false
  },
  "weatherScore": 100
}

ジョブの開始時間、終了時間、ステータス、チェンジセットなど様々な情報が取れています。 Pipeline REST APIよりも一回の情報量は多いですね。ビルド履歴に関しては取れていません。


ビルド履歴を取得する

ビルド履歴を取得するエンドポイントはrunsになります。 取得してみます。 http://jenkins.tielec.blog:8080/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/03_write_file/runs/

Jsonをクリックで展開します

[
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineRunImpl",
    "_links": {
      "prevRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/"
      },
      "parent": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
      },
      "tests": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/tests/"
      },
      "nodes": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/nodes/"
      },
      "log": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/log/"
      },
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/"
      },
      "blueTestSummary": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/blueTestSummary/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/actions/"
      },
      "steps": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/"
      },
      "changeSet": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/changeSet/"
      },
      "artifacts": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/artifacts/"
      }
    },
    "actions": [],
    "artifactsZipFile": null,
    "causeOfBlockage": null,
    "causes": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Started by upstream project "decrative-pipeline/08_parallel_step" build number 9",
        "upstreamBuild": 9,
        "upstreamProject": "decrative-pipeline/08_parallel_step",
        "upstreamUrl": "job/decrative-pipeline/job/08_parallel_step/"
      }
    ],
    "description": null,
    "durationInMillis": 47339,
    "enQueueTime": "2019-08-30T12:43:06.337+0900",
    "endTime": "2019-08-30T12:43:53.687+0900",
    "estimatedDurationInMillis": 18597,
    "id": "17",
    "name": null,
    "organization": "jenkins",
    "pipeline": "03_write_file",
    "replayable": true,
    "result": "SUCCESS",
    "runSummary": "stable",
    "startTime": "2019-08-30T12:43:06.348+0900",
    "state": "FINISHED",
    "type": "WorkflowRun",
    "changeSet": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.ChangeSetResource",
        "_links": {
          "self": {
            "_class": "io.jenkins.blueocean.rest.hal.Link",
            "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/changeSet/2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f/"
          }
        },
        "affectedPaths": [
          "pipeline/decrative-pipeline/pipeline_19_random_kitten_generator.groovy"
        ],
        "author": {
          "_class": "io.jenkins.blueocean.service.embedded.rest.UserImpl",
          "_links": {
            "favorites": {
              "_class": "io.jenkins.blueocean.rest.hal.Link",
              "href": "/blue/rest/users/noreply/favorites/"
            },
            "self": {
              "_class": "io.jenkins.blueocean.rest.hal.Link",
              "href": "/blue/rest/users/noreply/"
            }
          },
          "avatar": null,
          "email": null,
          "fullName": "noreply",
          "id": "noreply",
          "permission": null
        },
        "checkoutCount": 0,
        "commitId": "2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f",
        "issues": [],
        "msg": "Update pipeline_19_random_kitten_generator.groovy",
        "timestamp": "2019-08-10T19:11:25.000+0900",
        "url": "https://github.com/sakamaki-y123/jenkins-continuous-delivery/commit/2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f"
      }
    ],
    "branch": null,
    "commitId": null,
    "commitUrl": null,
    "pullRequest": null
  },
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineRunImpl",
    "_links": {
      "prevRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/"
      },
      "parent": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
      },
      "tests": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/tests/"
      },
      "nodes": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/nodes/"
      },
      "log": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/log/"
      },
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/"
      },
      "blueTestSummary": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/blueTestSummary/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/actions/"
      },
      "steps": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/steps/"
      },
      "changeSet": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/changeSet/"
      },
      "artifacts": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/artifacts/"
      },
      "nextRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/"
      }
    },
    "actions": [],
    "artifactsZipFile": null,
    "causeOfBlockage": null,
    "causes": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Started by upstream project "decrative-pipeline/08_parallel_step" build number 8",
        "upstreamBuild": 8,
        "upstreamProject": "decrative-pipeline/08_parallel_step",
        "upstreamUrl": "job/decrative-pipeline/job/08_parallel_step/"
      }
    ],
    "description": null,
    "durationInMillis": 6335,
    "enQueueTime": "2019-05-10T14:41:05.305+0900",
    "endTime": "2019-05-10T14:41:11.660+0900",
    "estimatedDurationInMillis": 18597,
    "id": "16",
    "name": null,
    "organization": "jenkins",
    "pipeline": "03_write_file",
    "replayable": true,
    "result": "SUCCESS",
    "runSummary": "stable",
    "startTime": "2019-05-10T14:41:05.325+0900",
    "state": "FINISHED",
    "type": "WorkflowRun",
    "changeSet": [],
    "branch": null,
    "commitId": null,
    "commitUrl": null,
    "pullRequest": null
  },
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineRunImpl",
    "_links": {
      "prevRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/"
      },
      "parent": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
      },
      "tests": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/tests/"
      },
      "nodes": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/nodes/"
      },
      "log": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/log/"
      },
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/"
      },
      "blueTestSummary": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/blueTestSummary/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/actions/"
      },
      "steps": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/steps/"
      },
      "changeSet": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/changeSet/"
      },
      "artifacts": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/artifacts/"
      },
      "nextRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/"
      }
    },
    "actions": [],
    "artifactsZipFile": null,
    "causeOfBlockage": null,
    "causes": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Started by user anonymous",
        "userId": null,
        "userName": "anonymous"
      },
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Restarted from build #14, stage write file"
      }
    ],
    "description": null,
    "durationInMillis": 2117,
    "enQueueTime": "2019-04-05T14:34:10.771+0900",
    "endTime": "2019-04-05T14:34:12.894+0900",
    "estimatedDurationInMillis": 18597,
    "id": "15",
    "name": null,
    "organization": "jenkins",
    "pipeline": "03_write_file",
    "replayable": true,
    "result": "SUCCESS",
    "runSummary": "stable",
    "startTime": "2019-04-05T14:34:10.777+0900",
    "state": "FINISHED",
    "type": "WorkflowRun",
    "changeSet": [],
    "branch": null,
    "commitId": null,
    "commitUrl": null,
    "pullRequest": null
  },
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineRunImpl",
    "_links": {
      "prevRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/"
      },
      "parent": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
      },
      "tests": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/tests/"
      },
      "nodes": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/nodes/"
      },
      "log": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/log/"
      },
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/"
      },
      "blueTestSummary": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/blueTestSummary/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/actions/"
      },
      "steps": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/steps/"
      },
      "changeSet": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/changeSet/"
      },
      "artifacts": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/artifacts/"
      },
      "nextRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/15/"
      }
    },
    "actions": [],
    "artifactsZipFile": null,
    "causeOfBlockage": null,
    "causes": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Started by user anonymous",
        "userId": null,
        "userName": "anonymous"
      }
    ],
    "description": null,
    "durationInMillis": 6006,
    "enQueueTime": "2019-04-05T14:33:09.167+0900",
    "endTime": "2019-04-05T14:33:15.175+0900",
    "estimatedDurationInMillis": 18597,
    "id": "14",
    "name": null,
    "organization": "jenkins",
    "pipeline": "03_write_file",
    "replayable": true,
    "result": "SUCCESS",
    "runSummary": "stable",
    "startTime": "2019-04-05T14:33:09.169+0900",
    "state": "FINISHED",
    "type": "WorkflowRun",
    "changeSet": [],
    "branch": null,
    "commitId": null,
    "commitUrl": null,
    "pullRequest": null
  },
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineRunImpl",
    "_links": {
      "parent": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
      },
      "tests": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/tests/"
      },
      "nodes": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/nodes/"
      },
      "log": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/log/"
      },
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/"
      },
      "blueTestSummary": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/blueTestSummary/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/actions/"
      },
      "steps": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/steps/"
      },
      "changeSet": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/changeSet/"
      },
      "artifacts": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/13/artifacts/"
      },
      "nextRun": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/14/"
      }
    },
    "actions": [],
    "artifactsZipFile": null,
    "causeOfBlockage": null,
    "causes": [
      {
        "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
        "shortDescription": "Started by user anonymous",
        "userId": null,
        "userName": "anonymous"
      }
    ],
    "description": null,
    "durationInMillis": 6035,
    "enQueueTime": "2019-03-13T23:14:12.526+0900",
    "endTime": "2019-03-13T23:14:18.565+0900",
    "estimatedDurationInMillis": 18597,
    "id": "13",
    "name": null,
    "organization": "jenkins",
    "pipeline": "03_write_file",
    "replayable": true,
    "result": "SUCCESS",
    "runSummary": "stable",
    "startTime": "2019-03-13T23:14:12.530+0900",
    "state": "FINISHED",
    "type": "WorkflowRun",
    "changeSet": [],
    "branch": null,
    "commitId": null,
    "commitUrl": null,
    "pullRequest": null
  }
]

こちらもかなり細かく情報が取れています。


最後にビルド結果を見てみます。 ビルド結果はrunsの後ろにビルド番号を追加すると取得できます。 http://jenkins.tielec.blog:8080/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/03_write_file/runs/17

Jsonをクリックで展開します

{
  "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineRunImpl",
  "_links": {
    "prevRun": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/16/"
    },
    "parent": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/"
    },
    "tests": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/tests/"
    },
    "nodes": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/nodes/"
    },
    "log": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/log/"
    },
    "self": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/"
    },
    "blueTestSummary": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/blueTestSummary/"
    },
    "actions": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/actions/"
    },
    "steps": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/"
    },
    "changeSet": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/changeSet/"
    },
    "artifacts": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/artifacts/"
    }
  },
  "actions": [],
  "artifactsZipFile": null,
  "causeOfBlockage": null,
  "causes": [
    {
      "_class": "io.jenkins.blueocean.service.embedded.rest.AbstractRunImpl$BlueCauseImpl",
      "shortDescription": "Started by upstream project "decrative-pipeline/08_parallel_step" build number 9",
      "upstreamBuild": 9,
      "upstreamProject": "decrative-pipeline/08_parallel_step",
      "upstreamUrl": "job/decrative-pipeline/job/08_parallel_step/"
    }
  ],
  "description": null,
  "durationInMillis": 47339,
  "enQueueTime": "2019-08-30T12:43:06.337+0900",
  "endTime": "2019-08-30T12:43:53.687+0900",
  "estimatedDurationInMillis": 18597,
  "id": "17",
  "name": null,
  "organization": "jenkins",
  "pipeline": "03_write_file",
  "replayable": true,
  "result": "SUCCESS",
  "runSummary": "stable",
  "startTime": "2019-08-30T12:43:06.348+0900",
  "state": "FINISHED",
  "type": "WorkflowRun",
  "changeSet": [
    {
      "_class": "io.jenkins.blueocean.service.embedded.rest.ChangeSetResource",
      "_links": {
        "self": {
          "_class": "io.jenkins.blueocean.rest.hal.Link",
          "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/changeSet/2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f/"
        }
      },
      "affectedPaths": [
        "pipeline/decrative-pipeline/pipeline_19_random_kitten_generator.groovy"
      ],
      "author": {
        "_class": "io.jenkins.blueocean.service.embedded.rest.UserImpl",
        "_links": {
          "favorites": {
            "_class": "io.jenkins.blueocean.rest.hal.Link",
            "href": "/blue/rest/users/noreply/favorites/"
          },
          "self": {
            "_class": "io.jenkins.blueocean.rest.hal.Link",
            "href": "/blue/rest/users/noreply/"
          }
        },
        "avatar": null,
        "email": null,
        "fullName": "noreply",
        "id": "noreply",
        "permission": null
      },
      "checkoutCount": 0,
      "commitId": "2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f",
      "issues": [],
      "msg": "Update pipeline_19_random_kitten_generator.groovy",
      "timestamp": "2019-08-10T19:11:25.000+0900",
      "url": "https://github.com/sakamaki-y123/jenkins-continuous-delivery/commit/2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f"
    }
  ],
  "branch": null,
  "commitId": null,
  "commitUrl": null,
  "pullRequest": null
}

ここでの情報は先ほどまで出てきた情報とあまり変わりがありませんが、logstepsといったエンドポイントが扱えることがわかります。


stepsの内容を確認してみます。 http://jenkins.tielec.blog:8080/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/03_write_file/runs/17/steps


[
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineStepImpl",
    "_links": {
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/7/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/7/actions/"
      }
    },
    "actions": [
      {
        "_class": "org.jenkinsci.plugins.workflow.support.actions.LogStorageAction",
        "_links": {
          "self": {
            "_class": "io.jenkins.blueocean.rest.hal.Link",
            "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/7/log/"
          }
        },
        "urlName": "log"
      }
    ],
    "displayDescription": null,
    "displayName": "Check out from version control",
    "durationInMillis": 2420,
    "id": "7",
    "input": null,
    "result": "SUCCESS",
    "startTime": "2019-08-30T12:43:50.731+0900",
    "state": "FINISHED",
    "type": "STEP"
  },
  {
    "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineStepImpl",
    "_links": {
      "self": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/14/"
      },
      "actions": {
        "_class": "io.jenkins.blueocean.rest.hal.Link",
        "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/14/actions/"
      }
    },
    "actions": [
      {
        "_class": "org.jenkinsci.plugins.workflow.support.actions.LogStorageAction",
        "_links": {
          "self": {
            "_class": "io.jenkins.blueocean.rest.hal.Link",
            "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/14/log/"
          }
        },
        "urlName": "log"
      }
    ],
    "displayDescription": "output.txt",
    "displayName": "Write file to workspace",
    "durationInMillis": 4,
    "id": "14",
    "input": null,
    "result": "SUCCESS",
    "startTime": "2019-08-30T12:43:53.230+0900",
    "state": "FINISHED",
    "type": "STEP"
  }
]

Pipelineで実行されているstepごとの実行時間が取得できています。ここまでの情報はPipeline REST APIでは取れなかったと思います。


stepにはIDが振られておりさらに掘り下げて確認することができます。

http://jenkins.tielec.blog:8080/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/03_write_file/runs/17/steps/7/

{
  "_class": "io.jenkins.blueocean.rest.impl.pipeline.PipelineStepImpl",
  "_links": {
    "self": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/7/"
    },
    "actions": {
      "_class": "io.jenkins.blueocean.rest.hal.Link",
      "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/7/actions/"
    }
  },
  "actions": [
    {
      "_class": "org.jenkinsci.plugins.workflow.support.actions.LogStorageAction",
      "_links": {
        "self": {
          "_class": "io.jenkins.blueocean.rest.hal.Link",
          "href": "/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/pipelines/03_write_file/runs/17/steps/7/log/"
        }
      },
      "urlName": "log"
    }
  ],
  "displayDescription": null,
  "displayName": "Check out from version control",
  "durationInMillis": 2420,
  "id": "7",
  "input": null,
  "result": "SUCCESS",
  "startTime": "2019-08-30T12:43:50.731+0900",
  "state": "FINISHED",
  "type": "STEP"
}

さらにlogのエンドポイントがあるので、ステップごとのログが取得できそうです。


ステップのログを確認してみます。 http://jenkins.tielec.blog:8080/blue/rest/organizations/jenkins/pipelines/decrative-pipeline/03_write_file/runs/17/steps/7/log


No credentials specified
Cloning the remote Git repository
Cloning repository https://github.com/sakamaki-y123/jenkins-continuous-delivery.git
 > git init /var/lib/jenkins/workspace/decrative-pipeline/03_write_file # timeout=10
Fetching upstream changes from https://github.com/sakamaki-y123/jenkins-continuous-delivery.git
 > git --version # timeout=10
 > git fetch --tags --progress https://github.com/sakamaki-y123/jenkins-continuous-delivery.git +refs/heads/*:refs/remotes/origin/*
 > git config remote.origin.url https://github.com/sakamaki-y123/jenkins-continuous-delivery.git # timeout=10
 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git config remote.origin.url https://github.com/sakamaki-y123/jenkins-continuous-delivery.git # timeout=10
Fetching upstream changes from https://github.com/sakamaki-y123/jenkins-continuous-delivery.git
 > git fetch --tags --progress https://github.com/sakamaki-y123/jenkins-continuous-delivery.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision 2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f (refs/remotes/origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 2ae5f87662481e3cedaf98b9b6faa64e4e8e0a7f
Commit message: "Update pipeline_19_random_kitten_generator.groovy"

BlueOceanで確認できるログが取得できました。

まとめ

APIを使うとJenkinsの情報を色々取得することができます。 この記事では以下の3種類のAPIを紹介しました。

  1. Remote access API
  2. Pipeline REST API
  3. Blue Ocean REST API

それぞれのAPIで取得できる情報の粒度がだいぶ違うので用途に合わせて使い分けることができればやれることの幅が広がると思います。

Remote access API を使って全体的な大まかな情報を取得、Pipeline REST API を使って細かな情報の取得。 さらにpipelineのステップごとの情報といったより細かな情報を取得するときは Blue Ocean REST APIと使い分けるのがポイントだと思いました。

3つのAPIは取れる情報が重複する部分もありますが、そのAPIでしか取れない情報もあるので色々と眺めてみると面白いのでなないでしょうか?

Pipeline には readJSON という便利なステップがあるので、組み合わせて使うと色々と情報の加工ができると思います。また、pythonやほかの言語を使っていろいろとジョブの分析をしたりといったことができそうです。

まとめ

この記事では、JenkinsのAPIを使ってジョブの情報を取得する方法について紹介しました。APIを活用することで、Jenkinsの情報をプログラムから取得したり、自動化を進めることができます。

おすすめ書籍

[

[改訂第3版]Jenkins実践入門 ――ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

[

Jenkins

[

サーバ/インフラエンジニアの基本がこれ1冊でしっかり身につく本

コメント

タイトルとURLをコピーしました