{"id":13463423,"url":"https://github.com/arangamani/jenkins_api_client","last_synced_at":"2025-04-29T18:48:31.268Z","repository":{"id":5061862,"uuid":"6223488","full_name":"arangamani/jenkins_api_client","owner":"arangamani","description":"Ruby Client libraries for communicating with Jenkins Remote Access API","archived":false,"fork":false,"pushed_at":"2025-01-11T01:42:20.000Z","size":6102,"stargazers_count":416,"open_issues_count":68,"forks_count":240,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-22T12:04:03.134Z","etag":null,"topics":["hacktoberfest","hacktoberfest2020","jenkins-api","jenkins-cli","jenkins-jobs","jenkins-server","ruby"],"latest_commit_sha":null,"homepage":"http://github.arangamani.net/jenkins_api_client/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"loicdescotte/MixTweets-AkkaStreams","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arangamani.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-10-15T07:57:41.000Z","updated_at":"2025-04-03T11:15:14.000Z","dependencies_parsed_at":"2024-01-13T17:55:49.637Z","dependency_job_id":"f17d23b3-4892-4cf8-aa39-304e6b324035","html_url":"https://github.com/arangamani/jenkins_api_client","commit_stats":{"total_commits":828,"total_committers":77,"mean_commits":"10.753246753246753","dds":0.5579710144927537,"last_synced_commit":"3fffb8b4c994f48fe388afc804cba12662c4d404"},"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arangamani%2Fjenkins_api_client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arangamani%2Fjenkins_api_client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arangamani%2Fjenkins_api_client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arangamani%2Fjenkins_api_client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arangamani","download_url":"https://codeload.github.com/arangamani/jenkins_api_client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250490570,"owners_count":21439169,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","hacktoberfest2020","jenkins-api","jenkins-cli","jenkins-jobs","jenkins-server","ruby"],"created_at":"2024-07-31T13:00:53.195Z","updated_at":"2025-04-29T18:48:31.247Z","avatar_url":"https://github.com/arangamani.png","language":"Ruby","funding_links":[],"categories":["Web Apps, Services \u0026 Interaction"],"sub_categories":["API Clients"],"readme":"Jenkins API Client\n==================\n\n[![Gem Version](http://img.shields.io/gem/v/jenkins_api_client.svg)][gem]\n[![Build Status](http://img.shields.io/travis/arangamani/jenkins_api_client.svg)][travis]\n[![Dependency Status](http://img.shields.io/gemnasium/arangamani/jenkins_api_client.svg)][gemnasium]\n[![Code Climate](http://img.shields.io/codeclimate/github/arangamani/jenkins_api_client.svg)][codeclimate]\n\n[gem]: https://rubygems.org/gems/jenkins_api_client\n[gemnasium]: https://gemnasium.com/arangamani/jenkins_api_client\n[codeclimate]: https://codeclimate.com/github/arangamani/jenkins_api_client\n\nCopyright \u0026copy; 2012-2017, Kannan Manickam [![endorse](http://api.coderwall.com/arangamani/endorsecount.png)](http://coderwall.com/arangamani)\n\nClient libraries for communicating with a Jenkins CI server and programatically managing jobs.\n\nOVERVIEW:\n---------\nThis project is a simple API client for interacting with Jenkins Continuous\nIntegration server. Jenkins provides three kinds of remote access API.\n1. XML API, 2. JSON API, and 3. Python API. This project aims at consuming the\nJSON API and provides some useful functions for controlling jobs on the Jenkins\nprogramatically. Even though Jenkins provides an awesome UI for controlling\njobs, it would be nice and helpful to have a programmable interface so we can\ndynamically and automatically manage jobs and other artifacts.\n\nDETAILS:\n--------\nThis project currently only provides functionality for the\n\u003ctt\u003ejobs, node, view, system, and build queue\u003c/tt\u003e interfaces.\n\nUSAGE:\n------\n\n### Installation\n\nInstall jenkins_api_client by \u003ctt\u003esudo gem install jenkins_api_client\u003c/tt\u003e.\nInclude this gem in your code as a require statement.\n\n    require 'jenkins_api_client'\n\n### Using with IRB\n\nIf you want to just play with it and not actually write a script, you\ncan just use the irb launcher script which is available in\n\u003ctt\u003escripts/login_with_irb.rb\u003c/tt\u003e. But make sure that you have your credentials\navailable in the correct location. By default the script assumes that you have\nyour credentials file in \u003ctt\u003e~/.jenkins_api_client/login.yml\u003c/tt\u003e. If you don't\nprefer this location and would like to use a different location, just modify\nthat script to point to the location where the credentials file exists.\n\n    ruby scripts/login_with_irb.rb\n\nYou will see that it entered IRB session and you can play with the API\nclient with the \u003ctt\u003e@client\u003c/tt\u003e object that it has returned.\n\n### Authentication\n\nSupplying credentials to the client is optional, as not all Jenkins instances\nrequire authentication. This project supports two types of password-based\nauthentication. You can just use the plain password by using \u003ctt\u003epassword\u003c/tt\u003e\nparameter. If you don't prefer leaving plain passwords in the credentials file,\nyou can encode your password in base64 format and use \u003ctt\u003epassword_base64\u003c/tt\u003e\nparameter to specify the password either in the arguments or in the credentials\nfile. To use the client without credentials, just leave out the\n\u003ctt\u003eusername\u003c/tt\u003e and \u003ctt\u003epassword\u003c/tt\u003e parameters. The \u003ctt\u003epassword\u003c/tt\u003e\nparameter is only required if \u003ctt\u003eusername\u003c/tt\u003e is specified.\n\n#### Using with Open ID\n\nIt is very simple to authenticate with a Jenkins server that has Open ID\nauthentication enabled. You will have to obtain your API token and use the API\ntoken as the password. To obtain the API token, go to your user configuration\npage and click 'Show API Token'. Use this token for the `password` parameter when\ninitializing the client.\n\n### Cross-site Scripting (XSS) and Crumb Support\n\nSupport for Jenkins crumbs has been added. These allow an application to\nuse the Jenkins API POST methods without requiring the 'Prevent Cross Site\nRequest Forgery exploits' to be disabled. The API will check in with the\nJenkins server to determine whether crumbs are enabled or not, and use them\nif appropriate.\n\n### SSL certificate verification\n\nWhen connecting over HTTPS, if the server's certificate is not trusted, the\nconnection will be aborted. To trust a certificate, specify the `ca_file`\nparameter when creating the client. The value should be a path to a PEM encoded\nfile containing the certificates.\n\n### Basic Usage\n\nAs discussed earlier, you can either specify all the credentials and server\ninformation as parameters to the Client or have a credentials file and just\nparse the yaml file and pass it in. The following call just passes the\ninformation as parameters\n\n```ruby\n@client = JenkinsApi::Client.new(\n  server_ip: '0.0.0.0',\n  username: 'somename', \n  password: 'secret password'\n)\n# The following call will return all jobs matching 'Testjob'\nputs @client.job.list(\"^Testjob\")\n```\n\nThe following example passes the YAML file contents. An example yaml file is\nlocated in \u003ctt\u003econfig/login.yml.example\u003c/tt\u003e.\n\n```ruby\n@client = JenkinsApi::Client.new(YAML.load_file(File.expand_path(\n  \"~/.jenkins_api_client/login.yml\", __FILE__)))\n# The following call lists all jobs\nputs @client.job.list_all\n```\n\n### Chaining and Building Jobs\n\nSometimes we want certain jobs to be added as downstream projects and run them\nsequentially. The following example will explain how this could be done.\n\n```ruby\nrequire 'jenkins_api_client'\n\n# We want to filter all jobs that start with 'test_job'\n# Just write a regex to match all the jobs that start with 'test_job'\njobs_to_filter = \"^test_job.*\"\n\n# Create an instance to jenkins_api_client\n@client = JenkinsApi::Client.new(YAML.load_file(File.expand_path(\n  \"~/.jenkins_api_client/login.yml\", __FILE__)))\n\n# Get a filtered list of jobs from the server\njobs = @client.job.list(jobs_to_filter)\n\n# Chain all the jobs with 'success' as the threshold\n# The chain method will return the jobs that is in the head of the sequence\n# This method will also remove any existing chaining\ninitial_jobs = @client.job.chain(jobs, 'success', [\"all\"])\n\n# Now that we have the initial job(s) we can build them\n# The build function returns a code from the API which should be 201 if\n# the build was successful, for Jenkins \u003e= v1.519\n# For versions older than v1.519, the success code is 302.\ncode = @client.job.build(initial_jobs[0])\nraise \"Could not build the job specified\" unless code == '201'\n```\n\nIn the above example, you might have noticed that the chain method returns an\narray instead of a single job. There is a reason behind it. In simple chain,\nsuch as the one in the example above, all jobs specified are chained one by\none. But in some cases they might not be dependent on the previous jobs and we\nmight want to run some jobs parallelly. We just have to specify that as a\nparameter.\n\nFor example: \u003ctt\u003eparallel = 3\u003c/tt\u003e in the parameter list to the \u003ctt\u003echain\u003c/tt\u003e\nmethod will take the first three jobs and chain them with the next three jobs\nand so forth till it reaches the end of the list.\n\nThere is another filter option you can specify for the method to take only\njobs that are in a particular state. In case if we want to build only jobs\nthat are failed or unstable, we can achieve that by passing in the states in\nthe third parameter. In the example above, we wanted to build all jobs. If we just\nwant to build failed and unstable jobs, just pass\n\u003ctt\u003e[\"failure\", \"unstable\"]\u003c/tt\u003e. Also if you pass in an empty array, it will\nassume that you want to consider all jobs and no filtering will be performed.\n\nThere is another parameter called \u003ctt\u003ethreshold\u003c/tt\u003e you can specify for the\nchaining and this is used to decide whether to move forward with the next job\nin the chain or not. A \u003ctt\u003esuccess\u003c/tt\u003e will move to the next job only if the\ncurrent build succeeds, \u003ctt\u003efailure\u003c/tt\u003e will move to the next job even if the\nbuild fails, and \u003ctt\u003eunstable\u003c/tt\u003e will move to the job even if the build is\nunstable.\n\nThe following call to the \u003ctt\u003echain\u003c/tt\u003e method will consider only failed and\nunstable jobs, chain then with 'failure' as the threshold, and also chain three\njobs in parallel.\n\n```ruby\ninitial_jobs = @client.job.chain(jobs, 'failure', [\"failure\", \"unstable\"], 3)\n# We will receive three jobs as a result and we can build them all\ninitial_jobs.each do |job|\n  code = @client.job.build(job)\n  raise \"Unable to build job: #{job}\" unless code == '201'\nend\n```\n\n### Configuring plugins\n\nGiven the abundance of plugins for Jenkins, we now provide a extensible way to \nset up jobs and configure their plugins. Right now, the gem ships with the hipchat\nplugin, with more plugins to follow in the future. \n\n```ruby\nhipchat_settings = JenkinsApi::Client::PluginSettings::Hipchat.new({\n  :room =\u003e '10000',\n  :start_notification =\u003e true,\n  :notify_success =\u003e true,\n  :notify_aborted =\u003e true,\n  :notify_not_built =\u003e true,\n  :notify_unstable =\u003e true,\n  :notify_failure =\u003e true,\n  :notify_back_to_normal =\u003e true,\n})\n\nclient = JenkinsApi::Client.new(\n  server_url: jenkins_server,\n  username: username,\n  password: password\n)\n\n# NOTE: plugins can be splatted so if you had another plugin it could be passed\n# to the new call below as another arg after hipchat\njob = JenkinsApi::Client::Job.new(client, hipchat)\n\n```\n\nWriting your own plugins is also straightforward. Inherit from the \nJenkinsApi::Client::PluginSettings::Base class and override the configure method.\nJenkins jobs are configured using xml so you just need to figure out where in the\nconfiguration to hook in your plugin settings.\n\nHere is an example of a plugin written to configure a job for workspace cleanup.  \n\n```ruby\nmodule JenkinsApi\n  class Client\n    module PluginSettings\n      class WorkspaceCleanup \u003c Base\n\n        # @option params [Boolean] :delete_dirs (false)\n        #   whether to also apply pattern on directories\n        # @option params [String] :cleanup_parameters\n        # @option params [String] :external_delete\n        def initialize(params={})\n          @params = params\n        end\n\n        # Create or Update a job with params given as a hash instead of the xml\n        # This gives some flexibility for creating/updating simple jobs so the\n        # user doesn't have to learn about handling xml.\n        #\n        # @param xml_doc [Nokogiri::XML::Document] xml document to be updated with \n        # the plugin configuration\n        #\n        # @return [Nokogiri::XML::Document]\n        def configure(xml_doc)\n          xml_doc.tap do |doc|\n            Nokogiri::XML::Builder.with(doc.at('buildWrappers')) do |build_wrappers|\n              build_wrappers.send('hudson.plugins.ws__cleanup.PreBuildCleanup') do |x|\n                x.deleteDirs @params.fetch(:delete_dirs) { false }\n                x.cleanupParameter @params.fetch(:cleanup_parameter) { '' }\n                x.externalDelete @params.fetch(:external_delete) { '' }\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n```\n\nCurrently, the skype plugin is still configured directly on the jenkins job. This will \nlikely be extracted into its own plugin in the near future, but we will maintain \nbackwards compatibility until after an official deprecation period.\n\n### Waiting for a build to start/Getting the build number\nNewer versions of Jenkins (starting with the 1.519 build) make it easier for\nan application to determine the build number for a 'build' request. (previously\nthere would be a degree of guesswork involved).  The new version actually\nreturns information allowing the jenkins_api_client to check the build queue\nfor the job and see if it has started yet (once it has started, the build-\nnumber is available.\n\nIf you wish to take advantage of this hands-off approach, the build method\nsupports an additional 'opts' hash that lets you specify how long you wish to\nwait for the build to start.\n\n#### Old Jenkins vs New Jenkins (1.519+)\n\n##### Old (v \u003c 1.519)\nThe 'opts' parameter will work with older versions of Jenkins with the following\ncaveats:\n* The 'cancel_on_build_start_timeout' option has no effect\n* The build_number is calculated by calling 'current_build_number' and adding\n  1 before the build is started.  This might break if there are multiple\n  entities running builds on the same job, or there are queued builds.\n\n##### New (v \u003e= 1.519)\n* All options work, and build number is accurately determined from queue\n  info.\n* The build trigger success code is now 201 (Created). Previously it was 302.\n\n#### Initiating a build and returning the build_number\n\n##### Minimum required\n```ruby\n# Minimum options required\nopts = {'build_start_timeout' =\u003e 30}\n@client.job.build(job_name, job_params || {}, opts)\n```\nThis method will block for up to 30 seconds, while waiting for the build to\nstart.  Instead of returning an http-status code, it will return the\nbuild_number, or if the build has not started will raise 'Timeout::Error'\nNote: to maintain legacy compatibility, passing 'true' will set the timeout\nto the default timeout specified when creating the @client.\n\n##### Auto cancel the queued-build on timeout\n```ruby\n# Wait for up to 30 seconds, attempt to cancel queued build\nopts = {'build_start_timeout' =\u003e 30,\n        'cancel_on_build_start_timeout' =\u003e true}\n@client.job.build(job_name, job_params || {}, opts)\n```\nThis method will block for up to 30 seconds, while waiting for the build to\nstart.  Instead of returning an http-status code, it will return the\nbuild_number, or if the build has not started will raise 'Timeout::Error'.\nPrior to raising the Timeout::Error, it will attempt to cancel the queued\nbuild - thus preventing it from starting.\n\n##### Getting some feedback while you're waiting\nThe opts parameter supports two values that can be assigned proc objects\n(which will be 'call'ed).  Both are optional, and will only be called if\nspecified in opts.\nThese are initially intended to assist with logging progress.\n\n* 'progress_proc' - called when job is initially queued, and periodically\n  thereafter.\n  * max_wait - the value of 'build_start_timeout'\n  * current_wait - how long we've been waiting so far\n  * poll_count - how many times we've polled the queue\n* 'completion_proc' - called just prior to return/Timeout::Error\n  * build_number - the build number assigned (or nil if timeout)\n  * cancelled - whether the build was cancelled (true if 'new' Jenkins\n    and it was able to cancel the build, false otherwise)\n\nTo use a class method, just specify 'instance.method(:method_name)', or\nuse a proc or lambda\n\n```ruby\n# Wait for up to 30 seconds, attempt to cancel queued build, progress\nopts = {'build_start_timeout' =\u003e 30,\n        'cancel_on_build_start_timeout' =\u003e true,\n        'poll_interval' =\u003e 2,      # 2 is actually the default :)\n        'progress_proc' =\u003e lambda {|max,curr,count| ... },\n        'completion_proc' =\u003e lambda {|build_number,cancelled| ... }}\n@client.job.build(job_name, job_params || {}, opts)\n```\n### Running Jenkins CLI\nTo running [Jenkins CLI](https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI)\n\n* authentication with username/password (deprecated)\n\n```ruby\n@client = JenkinsApi::Client.new(:server_ip =\u003e '127.0.0.1',\n         :username =\u003e 'somename', :password =\u003e 'secret password')\n# The following call will return the version of Jenkins instance\nputs @client.exec_cli(\"version\")\n```\n\n* authentication with public/private key file\nremember to upload the public key to:\n\n    `http://#{Server IP}:#{Server Port}/user/#{Username}/configure`\n\n```ruby\n@client = JenkinsApi::Client.new(:server_ip =\u003e '127.0.0.1',\n         :identity_file =\u003e '~/.ssh/id_rsa')\n# The following call will return the version of Jenkins instance\nputs @client.exec_cli(\"version\")\n```\n\nBefore you run the CLI, please make sure the following requirements are\nfulfilled:\n* JRE/JDK 6 (or above) is installed, and 'java' is on the $PATH environment\n  variable\n* The ```jenkins_api_client/java_deps/jenkins-cli.jar``` is required as the\n  client to run the CLI. You can retrieve the available commands via accessing\n  the URL: ```http://\u003cserver\u003e:\u003cport\u003e/cli```\n* (Optional) required if you run the Groovy Script through CLI; make sure\n  the *user* has the privilige to run script\n\n### Using with command line\nCommand line interface is supported only from version 0.2.0.\nSee help using \u003ctt\u003ejenkinscli help\u003c/tt\u003e\n\nThere are three ways for authentication using command line interface\n1. Passing all credentials and server information using command line parameters\n2. Passing the credentials file as the command line parameter\n3. Having the credentials file in the default location\n   \u003ctt\u003eHOME/.jenkins_api_client/login.yml\u003c/tt\u003e\n\n### Debug\n\nAs of v0.13.0, this debug parameter is removed. Use the logger instead. See the\nnext section for more information about this option.\n\n### Logger\n\nAs of v0.13.0, support for logger is introduced. Since it would be nice to have\nthe activities of the jenkins_api_client in a log file, this feature is\nimplemented using the Ruby's standard Logger class. For using this feature,\nthere are two new input arguments used during the initialization of Client.\n\n1. `:log_location` - This argument specifies the location for the log file. A\n   good location for linux based systems would be\n   '/var/log/jenkins_api_client.log'. The default for this values is STDOUT.\n   This will print the log messages on the console itself.\n2. `:log_level` - This argument specifies the level of messages to be logged.\n   It should be one of Logger::DEBUG (0), Logger::INFO (1), Logger::WARN (2),\n   Logger::ERROR (3), Logger::FATAL (4). It can be specified either using the\n   constants available in the Logger class or using these integers provided\n   here. The default for this argument is Logger::INFO (1)\n\nIf you want customization on the functionality Logger provides, such as leave n\nold log files, open the log file in append mode, create your own logger and\nthen set that in the client.\n\n#### Examples\n\n```ruby\n  @client = JenkinsApi::Client.new(...)\n  # Create a logger which ages logfile once it reaches a certain size. Leave 10\n  # “old log files” and each file is about 1,024,000 bytes.\n  @client.logger = Logger.new('foo.log', 10, 1024000)\n```\nPlease refer to [Ruby\nLogger](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html)\nfor more information.\n\n\n\nGem Development\n---------------\n\n### Updating java_deps/jenkins-cli.jar\n\nDownload the latest LTS \"Generic Java package (.war)\" `jenkins.war` from https://www.jenkins.io/download/, then:\n```\nmkdir tmp\ncd tmp\nmv ~/Downloads/jenkins.war .\njar -xvf jenkins.war\nmv WEB-INF/lib/cli-*.jar ../java_deps/jenkins-cli.jar\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farangamani%2Fjenkins_api_client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farangamani%2Fjenkins_api_client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farangamani%2Fjenkins_api_client/lists"}