Skip to content

Instantly share code, notes, and snippets.

@jeremysells
Last active November 5, 2022 00:56
Show Gist options
  • Save jeremysells/5cbf14de49f2a3d5b3cf5713e767ce3f to your computer and use it in GitHub Desktop.
Save jeremysells/5cbf14de49f2a3d5b3cf5713e767ce3f to your computer and use it in GitHub Desktop.
Jenkins Example
REGISTRY_URI=registry.example.com
APPLICATION_DOCKER_FROM_IMAGE=ubuntu:18.04
APPLICATION_PHP_VERSION=7.2
APPLICATION_CODE=some-thing
APPLICATION_NAME=Some\ Thing
APPLICATION_DESCRIPTION=Some\ Thing\ Else
APPLICATION_VENDOR_NAME=Your\ Name
DATA_DIR=../some-thing-data
# Dev only.
# They are in here cause Python/Docker Compose has a bug when the date is an ENV in the docker-compose.yml
# I need to investiage/report
APPLICATION_VERSION=0.0.0
APPLICATION_VERSION_HASH=000000
APPLICATION_VERSION_STRING=v0.0.0
APPLICATION_BUILD_DATE=2000-01-01T01:00:00+00:00

About

Jenkinsfile examples

Notes

The Jenkinsfile.old_scripted probably should not be used. I think scriped pipelines are deprecated.

Use the Jenkinsfile.declarative with a multi branch pipeline.

Using Jenkins Docker Image (Building in Docker Containers In Jenkins Docker Container) This means any running container, will be run on the host!

When using in Jenkins Gitlab Plugin 1.5.8

If you are using docker in docker - you will need a symlink on the physical host. This is because the docker run are run on the host so when it goes to mount the folder its tells docker to mount the folder in the container, which does not exist on the host. e.g. (same as volume mount of Jenkins home data dir)

  • mkdir -p /var/lib/jenkins
  • ln -s /path/to/jenkins/folder/mount /var/lib/jenkins/.jenkins
#!/usr/bin/env groovy
def dataDirectory = './dynamic/docker-compose'
//---The CI itself------------------------------------------------------------
pipeline {
agent any
environment {
DATA_DIR = "$dataDirectory"
}
triggers {
gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All')
}
post {
success {
slackSend(message: "Jenkins Job successful (${env.JOB_NAME}#${env.BUILD_NUMBER}) - Url: ${env.BUILD_URL}")
updateGitlabCommitStatus(name: 'build', state: 'success')
}
failure {
slackSend(message: "Jenkins Job FAILED! (${env.JOB_NAME}#${env.BUILD_NUMBER}) - Url: ${env.BUILD_URL}")
slackSend(message: "Jenkins Job FAILED! (${env.JOB_NAME}#${env.BUILD_NUMBER}) - Url: ${env.BUILD_URL}", channel: "#notifications_bad")
updateGitlabCommitStatus(name: 'build', state: 'failed')
}
always {
// Cleanup any running/started containers
sh("docker-compose stop")
sh("docker-compose down")
sh("docker-compose kill")
sh("docker-compose rm")
//Ignore error "Error response from daemon: a prune operation is already running"
sh("docker network prune -f 2>/dev/null")
}
}
stages {
stage('Checkout') {
steps{
checkout scm
}
}
stage('Info') {
steps{
//Print out env information (handy for debugging/testing)
sh("env | sort")
sh("git branch -vv")
}
}
stage('Build') {
steps {
echo "To do - build"
}
}
stage('Test') {
steps {
// Copy dist config
sh("rm -f build/docker-compose/app/config/*.*")
sh("cp build/docker-compose/app/config/dist/*.* build/docker-compose/app/config/")
//Build the development container
sh("docker-compose build")
//Build the development container
sh("docker-compose run --no-deps --rm app ant ci-check")
}
}
// Gitlab PR?
// Not sure if this works after moving from scripted
stage('Feedback') {
when {
expression { env.gitlabMergeRequestId }
}
steps {
script {
//Add a comment that it passed
addGitLabMRComment(comment: 'Looks good to me!')
//Merge the PR?
//I work alone in this project, so use CI as my code reviewer and merge when its successful
acceptGitLabMR(mergeCommitMessage: 'Passed CI, so merging!')
}
}
}
// Package only if its master, develop, a tag (or a hotfix)
stage('Package') {
when {
anyOf {
branch 'develop'
branch 'master'
expression { env.gitlabTargetBranch && env.gitlabTargetBranch.contains('refs/tags/v') }
expression { env.gitlabBranch && env.gitlabBranch.contains('hotfix/') }
}
}
steps {
script {
//Build a production image (and push to registry)
sh("""
bash -c '
source .env;
DATA_DIR=$dataDirectory;
APPLICATION_VERSION=`git describe --tags --always HEAD | tail -c +2`;
APPLICATION_VERSION_STRING=`git describe --tags --always HEAD`;
APPLICATION_VERSION_HASH=`git rev-parse HEAD`;
APPLICATION_BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"`;
IMAGE_TAG_SPECIFIC="\${REGISTRY_URI}/\${APPLICATION_CODE}:\${APPLICATION_VERSION}";
IMAGE_TAG_LATEST="\${REGISTRY_URI}/\${APPLICATION_CODE}:latest";
docker build \
--tag "\${IMAGE_TAG_SPECIFIC}" \
--tag "\${IMAGE_TAG_LATEST}" \
--build-arg "APPLICATION_DOCKER_FROM_IMAGE=\${APPLICATION_DOCKER_FROM_IMAGE}" \
--build-arg "APPLICATION_CODE=\${APPLICATION_CODE}" \
--build-arg "APPLICATION_NAME=\${APPLICATION_NAME}" \
--build-arg "APPLICATION_DESCRIPTION=\${APPLICATION_DESCRIPTION}" \
--build-arg "APPLICATION_VENDOR_NAME=\${APPLICATION_VENDOR_NAME}" \
--build-arg "APPLICATION_VERSION=\${APPLICATION_VERSION}" \
--build-arg "APPLICATION_VERSION_HASH=\${APPLICATION_VERSION_HASH}" \
--build-arg "APPLICATION_VERSION_STRING=\${APPLICATION_VERSION_STRING}" \
--build-arg "APPLICATION_BUILD_DATE=\${APPLICATION_BUILD_DATE}" \
--build-arg "APPLICATION_PHP_VERSION=\${APPLICATION_PHP_VERSION}" \
--build-arg "APPLICATION_COMPOSER_INSTALL_FLAGS=--no-dev" \
--pull \
--file Dockerfile \
. \
&& docker push \${IMAGE_TAG_SPECIFIC} \
&& docker push \${IMAGE_TAG_LATEST}
'
"""
)
}
}
}
stage('Deploy') {
when {
anyOf {
branch 'develop'
branch 'master'
expression { env.gitlabTargetBranch && env.gitlabTargetBranch.contains('refs/tags/v') }
expression { env.gitlabBranch && env.gitlabBranch.contains('hotfix/') }
}
}
steps {
echo "To do - auto deploy here!"
}
}
}
}
#!/usr/bin/env groovy
//This probably should not be used. Use the Jenkinsfile.declarative
//---The CI itself------------------------------------------------------------
node() {
// Checks out the project
stage('Checkout') {
checkout scm
}
// Prints some debugging info
stage('Debug') {
//Print out env information (handy for debugging/testing)
sh(name: "Output env info for debugging",
script: "env | sort",
)
sh(name: "Output branch information for debugging",
script: "git branch -vv",
)
}
// Areas
gitlabBuilds(builds: ['Test', 'Feedback', 'Package']) {
// Test
stage('Test') {
gitlabCommitStatus("Test") {
// Custom
sh(name: "Copy dist files",
script: "rm -f build/docker-compose/app/config/*.* && cp build/docker-compose/app/config/dist/*.* build/docker-compose/app/config/",
)
//Build the development container
sh(name: "Docker Development Image - Build",
script: "docker-compose build",
)
//Build the development container
sh(name: "Ant build.xml ci-check in container",
script: "docker-compose run --no-deps --rm app ant ci-check",
)
//Make sure everything is down and cleanup
//old networks - '--rm' does not do this :( and the eventually fill up
sh(name: "Docker stop all and cleanup",
script: """
bash -c '
docker-compose stop \
&& docker-compose down \
&& docker-compose kill \
&& docker-compose rm \
&& docker network prune -f
'
"""
)
}
}
// If there is a merge request say that it passed
// Update anything with deployment version information (E.g. Continuous deployment)
stage('Feedback') {
gitlabCommitStatus("Feedback") {
// Gitlab PR?
if (env.gitlabMergeRequestId) {
//Add a comment that it passed
addGitLabMRComment(comment: 'Looks good to me!')
//Merge the PR? (not sure if this is right)
acceptGitLabMR(mergeCommitMessage: 'Passed CI, so merging!')
//Add echo
echo 'Is Gitlab merge request'
} else {
echo 'Skip, as is not a Gitlab merge request'
}
}
}
// Publish (build production, push image, deploy)
stage('Package') {
gitlabCommitStatus("Package") {
// Should we use continuous deployment / Push production image
if (env.gitlabTargetBranch.contains('refs/tags/v') || env.gitlabBranch.contains('hotfix/') || env.gitlabSourceBranch == 'develop' || env.BRANCH_NAME == 'develop') {
//Build an push production image to the registry
//Note: The tail below, trims the first 'v' off the version
sh( name: "Build Docker Image and Push",
script: """
bash -c '
source .env;
APPLICATION_VERSION=`git describe --tags --always HEAD | tail -c +2`;
APPLICATION_VERSION_STRING=`git describe --tags --always HEAD`;
APPLICATION_VERSION_HASH=`git rev-parse HEAD`;
APPLICATION_BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"`;
IMAGE_TAG_SPECIFIC="\${REGISTRY_URI}/\${APPLICATION_CODE}:\${APPLICATION_VERSION}";
IMAGE_TAG_LATEST="\${REGISTRY_URI}/\${APPLICATION_CODE}:latest";
docker build \
--tag "\${IMAGE_TAG_SPECIFIC}" \
--tag "\${IMAGE_TAG_LATEST}" \
--build-arg "APPLICATION_DOCKER_FROM_IMAGE=\${APPLICATION_DOCKER_FROM_IMAGE}" \
--build-arg "APPLICATION_CODE=\${APPLICATION_CODE}" \
--build-arg "APPLICATION_NAME=\${APPLICATION_NAME}" \
--build-arg "APPLICATION_DESCRIPTION=\${APPLICATION_DESCRIPTION}" \
--build-arg "APPLICATION_VENDOR_NAME=\${APPLICATION_VENDOR_NAME}" \
--build-arg "APPLICATION_VERSION=\${APPLICATION_VERSION}" \
--build-arg "APPLICATION_VERSION_HASH=\${APPLICATION_VERSION_HASH}" \
--build-arg "APPLICATION_VERSION_STRING=\${APPLICATION_VERSION_STRING}" \
--build-arg "APPLICATION_BUILD_DATE=\${APPLICATION_BUILD_DATE}" \
--build-arg "APPLICATION_PHP_VERSION=\${APPLICATION_PHP_VERSION}" \
--build-arg "APPLICATION_COMPOSER_INSTALL_FLAGS=--no-dev" \
--pull \
--file Dockerfile \
. \
&& docker push \${IMAGE_TAG_SPECIFIC} \
&& docker push \${IMAGE_TAG_LATEST}
'
"""
)
//We could do a push to a version application here. If only one was around :)
} else {
echo "Skip, as is not a production branch"
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment