gojenkins wraps the Jenkins REST API in idiomatic Go calls
Jenkins API Client in Go. Looking for maintainers to move this project forward.
At a glance
- What is it?
- gojenkins is a Go client for the Jenkins API that covers builds, nodes, queue, folders, views, users and API tokens. It saves you from hand-writing Jenkins calls, but several of its own examples are stale and creating jobs still means hand-writing XML.
- Who is it for?
- Pick gojenkins if your Go service has to read build results, drive nodes or manage API tokens without writing Jenkins requests by hand, and you can live with polling and with hand-written job XML. Step away if you need modern Jenkins plugin features, Kerberos login, or a library whose examples still match its own API.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is not Jenkins, it is the shape of the Jenkins API
Jenkins is a widely used open source continuous integration system, and its HTTP API is wide, uneven and full of XML. Gojenkins exists to put a typed layer over that surface so that a Go program can treat a job, a build, a node or a queue item as an object instead of a bag of status codes. The repository description is blunt about its future: it is looking for maintainers to move this project forward. The library itself is not a server, a plugin or a wrapper around the Jenkins UI. It is a client, so the Jenkins instance stays where it is and your code talks to it over HTTP.
The alternative to gojenkins is not a competing library so much as the raw approach: call the Jenkins REST endpoints yourself, parse the XML or JSON by hand, and handle authentication on every request. The difference in approach is that gojenkins gives you a requester object that holds the base URL, the credentials and the TLS configuration, plus methods that already know the Jenkins URL layout, so the call sites in your code read as operations rather than as HTTP plumbing. The price is that you inherit the library's opinions, its polling model and its occasional rough edges.
CreateJenkins puts credentials and TLS in one place
Every example in the documentation starts the same way, by building a client object. The first argument is an http.Client, and passing nil is legal: by default gojenkins uses http.DefaultClient when no client is passed into CreateJenkins(). The remaining arguments are the server URL and, optionally, a user name and password, so authentication state is not repeated per call.
The library also has a place for the awkward deployment reality of a self-signed certificate. The requester exposes a CACert field, and the documented pattern is to read the certificate file and assign it before making calls. Where a company already runs its own HTTP stack, you can pass a fully configured client, for instance one carrying your own SSL settings, and the library will use that instead.
The installation step is the ordinary Go one, and the module is published under the same path as the import:
go get github.com/bndr/gojenkinsAfter that, a first connection is short. You create the client, call Init, and the returned error tells you whether the server answered:
ctx := context.Background()
jenkins := gojenkins.CreateJenkins(nil, "http://localhost:8080/", "admin", "admin")
// Provide CA certificate if server is using self-signed certificate
// caCert, _ := ioutil.ReadFile("/tmp/ca.crt")
// jenkins.Requester.CACert = caCert
_, err := jenkins.Init(ctx)Freshness comes from polling, and one polling example does not compile
Jenkins has no push channel for build state, so the library models freshness with explicit polling. A build is queried on demand, and the documentation is clear that to always get fresh data you use the .Poll() method. The documented wait loop is a sleep followed by a poll:
// Wait for build to finish
for build.IsRunning(ctx) {
time.Sleep(5000 * time.Millisecond)
build.Poll(ctx)
}Two things follow from that snippet. First, the interval is hard coded in your code, so the polling rate is your problem rather than the library's, which is good for cost control and bad for latency. Second, the loop shape means you can be looking at a state that changed between polls.
There is a real defect in the same part of the documentation. Under the heading about fresh data, the example calls job.Poll() with no context argument, then calls build.getBuild(ctx, 1) with a lower case method name and a context. Elsewhere the public method is GetBuild, and the node example polls with a context. As written that snippet does not match the API the rest of the documentation uses. Copy it literally and you will fight the compiler. Treat the polling example as a sketch and the GetBuild and Poll methods with a context as the real contract.
Creating a job means writing Jenkins XML yourself
The library is strong on reading and on lifecycle actions. It can query nodes and start, stop or take them offline, query and manipulate jobs, fetch plugins, builds, artifacts and fingerprints, validate artifact fingerprints, read the current queue and cancel tasks, and create and delete users.
The weak point is creation. To put a job inside a folder, the documented flow builds a config string containing raw Jenkins XML and hands it to CreateJobInFolder:
pFolder, err := jenkins.CreateFolder(ctx, "parentFolder")
if err != nil {
panic(err)
}job, err := jenkins.CreateJobInFolder(ctx, configString, "jobInFolder", pFolder.GetName(), cFolder.GetName())
if err != nil {
panic(err)
}The configString in the documentation is a literal project element with NullSCM and empty builders and publishers. So the library moves the HTTP problem out of your way but leaves the Jenkins domain problem in front of you: you must know the schema the installed Jenkins version expects, and the sample is deliberately minimal. A pipeline job, a matrix job or a job with a real SCM needs different XML, and the documentation does not describe how to generate it. If your use case is creating many varied jobs, expect to write that XML layer yourself or use a different tool.
API token handling is the most useful part of the surface
For automation that runs on a schedule, the token API is the reason to pick this library. You generate a token for a user, point the requester at the new secret, and revoke it afterwards. The pattern is short and complete:
// Create a token for admin user
token, err := jenkins.GenerateAPIToken(ctx, "TestToken")
if err != nil {
log.Fatal(err)
}// Revoke all tokens for admin user
err = jenkins.RevokeAllAPITokens(ctx)
if err != nil {
log.Fatal(err)
}The same section shows how to swap the client over to the new credential, by assigning token.Value to the password field of the requester's BasicAuth, and how to revoke a single token through the token object. That flow is what makes short lived credentials possible for CI jobs.
User management sits next to it, with CreateUser taking a name, a password, a full name and an email address, and a Delete method on the returned user. The documentation also notes that you can delete a user that gojenkins did not create, calling DeleteUser with the name directly. Note that this call, unlike its neighbours, takes no context argument, which is a small inconsistency in an otherwise context-first API. Anything that touches users or tokens is administrative, so scope the account you use and the lifetime of the tokens accordingly.
The Dockerfile names the plugins the client expects
The repository ships a Dockerfile, and it is short enough to be the fastest way to understand the dependency surface:
FROM jenkins/jenkins:lts
RUN /usr/local/bin/install-plugins.sh cloudbees-folder ssh-slaves credentials ssh-credentials docker-commonsTwo things follow. The project targets the LTS line of Jenkins, so a client test run is expected against a current long term support image rather than an arbitrary old release. And the plugin set is a requirements list in disguise: cloudbees-folder is what the folder feature needs, credentials and ssh-credentials back the credential and slave features, and docker-commons is there for Docker based nodes. If you plan to exercise the folder or node paths of the client, that plugin list is the set to install on your own instance.
There is also a command line front end. The documentation sends CLI users into the cli directory and builds it with make, which produces a jenkinsctl binary alongside the library:
$ cd cli/jenkinsctl
$ makeThe documented way to exercise the client is likewise a single command:
go testAn active tree with a long gap between releases
The repository is not archived and the last push was on 2026-10-07, so the code is still being worked on. The release history, however, is uneven. There is a v1.0.1 from 2019-11-25, a v1.1.0 from 2021-03-16, and a v1.2.0 from 2025-12-15, which leaves a gap of more than four years between the first two tags and a further gap of almost five years before the most recent one. With no release notes attached to the tags and no changelog in the tree, the practical upgrade signal is the commit history rather than a version note.
The module definition is short and pins a recent Go baseline:
module github.com/bndr/gojenkins
go 1.21
require (
github.com/stretchr/testify v1.11.1
golang.org/x/net v0.25.0
)The declared TODO list names two gaps: Kerberos authentication, which matters for organisations that centralise credentials in Active Directory, and a rewrite of some or all iterators with channels, which would make stream consumption easier than the current pull style calls. The licence is Apache-2.0, which is permissive and carries the usual notice obligations if you redistribute the code; what it means for your own deployment is a question for a qualified adviser. The two direct dependencies are modest, so the supply chain surface is small.
Editorial conclusion
Pick gojenkins if your Go service has to read build results, drive nodes or manage API tokens without writing Jenkins requests by hand, and you can live with polling and with hand-written job XML. Step away if you need modern Jenkins plugin features, Kerberos login, or a library whose examples still match its own API. Before you adopt it, run go test, open the godoc reference for the methods you need, and confirm that the v1.2.0 tag still matches the Jenkins version you run.
Frequently asked questions
How do I install gojenkins for a Go project?
The documented installation is a single go get of the module path github.com/bndr/gojenkins, which is also the import path used in every example.
How do I check that a Jenkins build finished successfully from Go?
Get the job, get the build, and read its result, which is compared against the SUCCESS string in the documentation example. For a running build you wait in a loop that sleeps for 5000 milliseconds and then calls Poll on the build.
Can gojenkins create jobs inside folders?
Yes. You create a parent folder with CreateFolder, then call CreateJobInFolder with a config string, the job name and the parent and child folder names. The config string is raw Jenkins XML that you have to supply yourself.
Does gojenkins support Kerberos authentication?
Not yet. Kerberos authentication appears on the TODO list of the project, while the documented authentication options are user name and password, an API token, and your own http.Client.
Which Jenkins plugins does the client need?
The Dockerfile in the repository installs cloudbees-folder, ssh-slaves, credentials, ssh-credentials and docker-commons on top of the jenkins/jenkins:lts image. The cloudbees-folder plugin in particular is what the folder features build on.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bndr-gojenkins)Was this useful?