The most powerful CI/CD ever.
Simple at the shallow end (see Jenkins in Docker in one command).
Non-trivial at the advanced end (auto-scaling on Kubernetes, Jenkins Plugins, Groovy Shared Library programming).
At least intermediate level Groovy programming is mandatory once you start using Shared Libraries between pipelines, or even code snippets in the administration Script Console.
- Jenkinsfile - Scripted vs Declarative pipelines
- Quick Jenkins in Docker and SysAdmin Scripts
- Jenkins CLI
- Jenkins Shell Scripts
- Jenkins Plugins
- Jenkins Jobs auto-saved to Git
- Jenkins Groovy
- Jenkins Shared Libraries (Groovy)
- Jenkins API
- Desktop Menu Notifications
- Jenkins on Docker in one command
- Jenkins Slaves on Bare Metal / VMs
- Jenkins on Kubernetes
- Google Auth SSO
- Azure AD auth SSO
- CloudBees
- Jenkins X
- Tips
- Troubleshooting
- Other Resources
- newer
- adds SCM Checkout stage by default
- can Restart from Stage (not available in Scripted Pipelines)
- def variable outside of pipeline block
- use script block to get the mutation variable benefits of scripted pipeline
- older
- can use Groovy programming code like in shared libraries
$JENKINS_URL/pipeline-syntax/
Get the default initial admin password quickly from Docker or Kubernetes by running:
jenkins_password.sh
Download:
wget "$JENKINS_URL/jnlpJars/jenkins-cli.jar"
Run:
java -jar jenkins-cli.jar help
jenkins_cli.sh
does this automatically and its --help
tells you what sorts of environment variables you need for auth and
connectivity which the jar is not good at.
Scripts for common Jenkins operations using the Jenkins CLI and API:
HariSekhon/DevOps-Bash-tools
jenkins/
directory.
Plugins are the greatest strength and weakness of Jenkins, depending on how you look at it.
Jenkins has all of the power but also the complexity of managing the extensions, additional configuration and plugin upgrades.
To get a list of plugins on an existing Jenkins server, one per line:
java -jar jenkins-cli.jar -s "$JENKINS_URL" list-plugins | awk '{print $1}' | sort
See here for a great list of plugins that I've used in production across companies:
HariSekhon/Kubernetes - jenkins/base/values.yaml
Waits for builds to finish:
$JENKINS_URL/safeRestart
Doesn't wait for builds to finish:
$JENKINS_URL/restart
Auto-backport Jenkins job XML configurations to Git for tracking, diffing and reloading in case of disaster recovery.
Groovy shared library function:
jenkinsJobsDownloadConfigurations.groovy
or script it yourself by calling one of these scripts and then Git committing the downloaded XMLs:
jenkins_jobs_download_configs.sh
jenkins_jobs_download_configs_cli.sh
Inspired by Rancid which I was using 2010-2013 to back up my Cisco & Juniper network configurations to Subversion and later Git (I hacked the code to support the latter). I've written similarly functional code Git backport code for other systems like IBM BigInsights, Datameer etc. (DevOps-Perl-tools repo).
Groovy is the language of Jenkins, and it is awesome.
If you want to do anything advanced in Jenkins, you need to know Groovy.
You can paste Groovy code snippets into the Script Console in Jenkins, which is located at:
$JENKINS_URL/script
Some *.groovy
scripts are mixed in between the shell scripts
here.
HariSekhon/Jenkins repo.
Functions should either follow java reverse fqdn naming convention or more simple flat vars/funcName.groovy
.
Filename must be camelCase or lowercase to work.
Configure the Jenkins Shared Library repo containing the Groovy code in the global System Configuration and give it a name for easy referencing:
Configure Jenkins
-> Configure System
-> Global Pipeline Libraries
-> Add - give a NAME and point it to Git repo where var/ content is
Then in Jenkinsfile
reference the named configured repo
@Library('NAME@branchOrTag') _
@branch/tag
suffix is required, otherwise gets ERROR: No version specified for library NAME
Trailing underscore _
is required to import all functions, otherwise syntax error from next token:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 3: unexpected token: pipeline @ line 3, column 1.
pipeline {
Or using the pipeline-github-lib plugin you can use a dynamic repo via URL path to a public git repo - this is useful for development pointing to a dev repo / branch:
@Library('github.com/harisekhon/jenkins@master') _
Then call functions at top level of Jenkinsfile
if inserting a whole Pipeline,
or within a steps{}
section if inserting normal functions.
funcName("param1", "param2")
Don't use external shell scripts or similar as they have to be in the source repo, not the shared library repo,
so you can't actually share such external scripts among different builds in different repos without checking them out
from another git repo as a separate step in the Jenkinsfile
pipeline because otherwise the script won't be found.
See jenkins_api.sh
/api/json
/job/$job/api/json
curl "$JENKINS_URL/job/test%20ok/api/json?pretty=true"
- CCMenu - Mac OSX menu watcher
- BuildNotify - for Linux
Provides the /cc.xml/
endpoint for notification tools above.
https://plugins.jenkins.io/cctray-xml/
Then put this in your CCMenu or similar tool:
<JENKINS_URL>/cc.xml/
From the DevOps-Bash-tools repo:
jenkins/jenkins.sh
-
boots Jenkins in Docker
-
installs plugins
-
prints admin creds to stdout
-
creates a Pipeline build job for the local repo
-
executes the build job
-
automatically opens the Jenkins UI on Mac, or prints the url on Linux
-
Uses docker-compose/jenkins.yml
- can optionally edit config to:
- use
JAVA_OPTS
to tweak heap size - mount
/var/jenkins_home
to local machine for persistence
- use
- can optionally edit config to:
- Manage Jenkins
- Nodes
- New Node
- use ssh-slaves plugin to automatically deploy agents via pre-distributed SSH keys on the servers
- New Node
- Nodes
Note: don't commit the JCasC security googleOAuth2
section to Git as it contains the clientId
and clientSecret
.
Just delete the security local
so that it doesn't overwrite and revert to local authentication.
Instructions are in this README.md.
In Azure AD UI:
App Registrations
New Registration
- Overview - get the
Application (client) ID
andDirectory (tenant) ID
Authentication
- set
Redirect URI
to behttps://$JENKINS_URL/securityRealm/finishLogin
substituting your real jenkins url - tick
ID tokens
- set
API Permissions
Azure Active Directory Graph
Directory.Read.All (Delegated)
Directory.Read.All (Application)
User.Read.All (Delegated)
Microsoft Graph
Directory.Read.All (Delegated)
Directory.Read.All (Application)
User.Read (Delegated)
User.Read.All (Application)
- if you have perms click
Grant admin consent for MyCompany
before this will work to be able to read groups, requires AAD Admin permission
Certificates & Secrets
->New client secret
(copy and paste to Jenkins)Manifest
-> change"groupMembershipClaims": null
to "groupMembershipClaims": "SecurityGroup"
, which combined with the Authentication ID tokens sends the group info in the token (it still won't show up in the Jenkins user info, but it works and gets rid of the lack of permissions to retrieve group error)
- Overview - get the
In Jenkins UI:
Manage Jenkins
Configure Global Security
Azure Active Directory
(deprecated plugin, so this might be different in saml plugin now)- enter
application client id
,directory tenant id
andsecret
- click
Verify
- enter
Authorization
Azure Matrix-based security
- grant perms to your user/group (should autocomplete if above AAD steps were done right)
- (not to be confused with the old Matrix-based security bullet point, although both seem to work but only the Azure one gives you autocomplete of groups, while the latter simply needs the group name to match, the azure plugin can differentiate between Outlook365 groups and Security groups)
Save
- grant perms to your user/group (should autocomplete if above AAD steps were done right)
- Go back to base Jenkins URL to do AAD login, ignore error pages not from starting point
- If you find yourself locked out, follow tradition password reset or JCasC password reset
Managed hosted Jenkins control plane - commercial proprietary management layer.
Runs Jenkins controllers and agents on your own Kubernetes.
The real problem this solves is 'Islands of Jenkins' since there is a limit to the vertical scalability of the Jenkins server leading to provincial team oriented Jenkins installations which is a management and governance hassle for larger enterprises.
Licensed by number of users, not build minutes since that is run locally.
https://docs.cloudbees.com/docs/cloudbees-ci/latest/feature-definition
Roughly $1k per user + VAT, depending on whether 8x5 or 24x7 support. Prices are always subject to change, negotiation and scale.
See Jenkins on Kubernetes - CloudBees section
See Jenkins on Kubernetes - Jenkins X section
- Use Plugins - they're awesome
- uninstall ones you're not using to save RAM
- Standardize your Jenkins agents via automation
- config management for Bare Meta / VMs
- preferably Jenkins on Kubernetes dynamically spawning agents from pod template
- Don't run builds on Jenkins server since builds will contend for important server resources needed for job
coordination
- Builds on server that's only for trivial small setups, PoCs, local docker testing etc.
- Jenkins server is a vertical scaling bottleneck
- Can cause inconsistencies between builds on agents vs server
- Speed up builds via caching
- Docker layer caching
- Incremental code builds
- Integrate with other tools (usually via plugins):
- Sonar, Jira, Gerrit, Allure
- Artifactory / Nexus
- Slack for notifications
- Use Jenkins LTS releases for stability
- Test your plugin upgrades on a dev/test instance first as they can break anything on Jenkins
- High number of Pipeline Jobs and frequent build executions will degrade Jenkins server performance
- past roughly 150 jobs depending on your execution frequency you'll probably need to split to another Jenkins server
- The resulting 'Islands of Jenkins' multiple UI servers is where CloudBees sells to enterprise a management control plane single pane of glass
On a traditional Jenkins install (not using the Kubernetes helm chart, see Kubernetes section for that):
SSH to the jenkins server and run:
sed -i 's|<useSecurity>true</useSecurity>|<useSecurity>false</useSecurity>|' "$JENKINS_HOME/config.xml"
Check it worked:
grep -i useSecurity "$JENKINS_HOME/config.xml"
Then restart Jenkins, access it without auth, update the admin password, undo the config change, and restart again.
Execute in Script Console at $JENKINS_URL/script
:
org.jenkinsci.plugins.durabletask.BourneShellScript.LAUNCH_DIAGNOSTICS=true
https://www.slideshare.net/andrewbayer/7-habits-of-highly-effective-jenkins-users
Ported from private Knowledge Base page 2013+