Shared Libraries Fundamentals
Shared Libraries Fundamentals
Introduction to Shared Libraries
What are Shared Libraries?
Jenkins shared libraries are reusable collections of Groovy code that can be used by multiple Jenkins pipelines. They provide a way to share common pipeline logic across different projects and teams.
Benefits
- Code reusability
- Standardization
- Maintainability
- Version control
- Reduced duplication
- Centralized updates
Library Structure
Directory Layout
(root)
+- src/ # Groovy source files
| +- org/example/
| +- Utils.groovy # Common utility functions
+- vars/ # Global variables/functions
| +- standardBuild.groovy # Reusable pipeline step
| +- deploy.groovy # Deployment function
+- resources/ # Non-Groovy files
| +- scripts/
| +- deploy.sh # Shell scripts
+- tests/ # Test files
+- unit/
+- integration/
Component Types
1. Source Files (src/)
// src/org/example/Utils.groovy
package org.example
class Utils implements Serializable {
def script
Utils(script) {
this.script = script
}
def mvn(String goals) {
script.sh "mvn ${goals}"
}
def validateInput(Map config) {
if (!config.name) {
throw new IllegalArgumentException("'name' parameter is required")
}
}
}
2. Global Variables (vars/)
// vars/standardBuild.groovy
def call(Map config) {
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
def utils = new org.example.Utils(this)
utils.mvn('clean install')
}
}
}
}
}
}
3. Resources
# resources/scripts/deploy.sh
#!/bin/bash
ENV=$1
APP=$2
VERSION=$3
echo "Deploying $APP version $VERSION to $ENV"
# Deployment logic
Library Configuration
Global Library Configuration
// Jenkins Configuration
@Library('my-shared-library@master') _
// Pipeline usage
pipeline {
agent any
stages {
stage('Build') {
steps {
standardBuild()
}
}
}
}
Version Control Integration
// Multiple library versions
@Library([
'mylib@master',
'otherlib@1.0.0'
]) _
// Dynamic version selection
libraryResource('configs/deployment.yml')
Implementation Patterns
1. Simple Function
// vars/log.groovy
def info(message) {
echo "INFO: ${message}"
}
def warning(message) {
echo "WARNING: ${message}"
}
def error(message) {
echo "ERROR: ${message}"
}
2. Pipeline Step
// vars/dockerBuild.groovy
def call(String imageName, String version = 'latest') {
sh """
docker build -t ${imageName}:${version} .
docker push ${imageName}:${version}
"""
}
3. Complex Implementation
// vars/microservicePipeline.groovy
def call(Map config) {
pipeline {
agent {
kubernetes {
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.8.4
command:
- cat
tty: true
"""
}
}
stages {
stage('Build') {
steps {
container('maven') {
sh 'mvn clean package'
}
}
}
stage('Test') {
parallel {
stage('Unit Tests') {
steps {
container('maven') {
sh 'mvn test'
}
}
}
stage('Integration Tests') {
steps {
container('maven') {
sh 'mvn verify'
}
}
}
}
}
}
}
}
Security Considerations
Access Control
// Credential handling
withCredentials([
string(credentialsId: 'api-token', variable: 'TOKEN')
]) {
// Secure usage of credentials
}
Input Validation
def validateDeployConfig(config) {
required = ['environment', 'version', 'application']
required.each { param ->
if (!config.containsKey(param)) {
throw new IllegalArgumentException("Missing required parameter: ${param}")
}
}
}
Testing Strategy
Unit Tests
// tests/unit/UtilsTest.groovy
import org.example.Utils
import org.junit.Test
class UtilsTest {
@Test
void testValidateInput() {
def utils = new Utils()
try {
utils.validateInput([:]) // Should throw exception
assert false
} catch (IllegalArgumentException e) {
assert e.message == "'name' parameter is required"
}
}
}
Integration Tests
// tests/integration/PipelineTest.groovy
class PipelineTest extends BasePipelineTest {
@Test
void testStandardBuild() {
def script = loadScript("vars/standardBuild.groovy")
script.call([name: 'test-project'])
assertJobStatusSuccess()
assertCommandExecuted('mvn clean install')
}
}
Best Practices
Code Organization
- Keep functions focused and small
- Use meaningful names
- Implement proper error handling
- Add comprehensive documentation
- Follow consistent coding style
Version Control
- Use semantic versioning
- Maintain change log
- Tag releases
- Branch for features
- Review code changes
Hands-on Exercise
Exercise 1: Basic Library Implementation
- Create library structure
- Implement utility functions
- Add global variables
- Create test cases
- Configure in Jenkins
Exercise 2: Advanced Implementation
- Create complex pipeline step
- Implement security measures
- Add comprehensive tests
- Document the implementation
- Deploy and test
Assessment
Knowledge Check
- What is the purpose of shared libraries in Jenkins?
- How do you structure a shared library?
- What are the different types of library components?
- How do you implement security in shared libraries?
Practice Tasks
- Create a basic shared library
- Implement a complex pipeline step
- Add security measures
- Write comprehensive tests
Additional Resources
Documentation
Best Practices
- Follow coding standards
- Implement proper testing
- Maintain documentation
- Consider security aspects
Next Steps
- Review shared library concepts
- Practice implementation patterns
- Explore advanced features
- Study security considerations