20/02/2019 - DOCKER, GIT, JENKINS
In this example we are going to manually run Jenkins pipeline stages against our GitHub repository. When we trigger a build in Jenkins, it will connect to GitHub via SSH and run all the stages listed in the Jenkinsfile which is also stored in the GitHub repository.
Jenkins pulls our dockerised GitHub repository, builds containers, runs all tests in containers, stops containers and clears docker artifacts. That's all!
Make sure that the SSH key of Jenkins server is added to GitHub repository. Login to Jenkins UI and do the following.
GitHub-inanzzz
) for "Username" option.~/.ssh/id_rsa.pub
file into the textarea.First of all make sure that the "docker" and "docker-compose" are installed on the Jenkins server. In addition to that, make sure that the jenkins
user can execute $ docker ...
and $ docker-compose ...
CLI commands. Run $ sudo usermod -aG docker $USER
and $ sudo usermod -aG docker jenkins
commands. You will need to restart the Jenkins server to let the changes take affect. Note: You can use $ sudo -i -u jenkins
command to login as jenkins
user on Jenkins server.
In Jenkins's main page, click "New Item" link to create a new item called "Test" and then select "Pipeline" option in the following page.
https://github.com/inanzzz/game
for "Repository URL".GitHub-inanzzz
from "Credentials".*/master
to */develop
.ci/pipeline/branch/develop/Jenkinsfile
to "Script path".If you click "Build Now" link, it should successfuly run the first build and the console output should look like below.
.
├── ci
│ └── pipeline
│ └── branch
│ └── develop
│ └── Jenkinsfile
├── composer.json
├── docker
│ └── ci
│ ├── docker-compose.yml
│ ├── .env
│ ├── Makefile
│ └── php
│ └── Dockerfile
├── src
│ └── Football.php
└── tests
└── FootballTest.php
pipeline {
agent any
options {
skipDefaultCheckout(true)
}
stages {
stage('Checkout SCM') {
steps {
echo '> Checking out the source control ...'
checkout scm
}
}
stage('Git Pull') {
steps {
echo '> Pulling the code from GitHub repository ...'
sh 'git remote update && git checkout develop && git pull origin develop'
}
}
stage('Docker Up') {
steps {
echo '> Building the docker containers ...'
sh 'cd docker && cd ci && make build'
}
}
stage('Composer Install') {
steps {
echo '> Building the application within the container ...'
sh 'cd docker && cd ci && make composer'
}
}
stage('Test') {
steps {
echo '> Running the application tests ...'
sh 'cd docker && cd ci && make test'
}
}
}
}
{
"name": "inanzzz/game",
"require": {
"php": ">=7.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.13",
"phpstan/phpstan": "^0.11.2",
"phpunit/phpunit": "^7.3"
},
"autoload": {
"psr-4": {
"App\\": "src/",
"App\\Tests\\": "tests/"
}
},
"config": {
"sort-packages": true
}
}
version: '3'
services:
php:
build:
context: php
container_name: '${COMPOSE_PROJECT_NAME}_php'
hostname: '${COMPOSE_PROJECT_NAME}-php'
env_file:
- .env
volumes:
- ../../:/app:consistent
working_dir: /app
COMPOSE_PROJECT_NAME=game
The reason why we have this file is because the Jenkins Pipeline plugin doesn't run $ docker-composer ...
commands.
CONTAINER := game_php
build:
@docker-compose up -d
composer:
@docker exec -i $(CONTAINER) composer install
test:
@docker exec -i $(CONTAINER) vendor/bin/php-cs-fixer fix src --rules=@PSR2 --using-cache=no --dry-run --verbose --diff
@docker exec -i $(CONTAINER) vendor/bin/phpunit tests
@docker exec -i $(CONTAINER) vendor/bin/phpstan analyse src tests --no-progress --level=max
@make -s down
down:
@docker-compose down --volumes
@make -s clean
clean:
@docker system prune --volumes --force
FROM php:7.2-cli-alpine
RUN apk update \
&& apk add --no-cache $PHPIZE_DEPS \
bash \
git \
zip \
unzip
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN rm -rf /var/cache/apk/*
CMD tail -f /dev/null
If you click "Build Now" link, it should successfuly run the first build and the console output should look like below.
Started by user root
Obtained ci/pipeline/branch/develop/Jenkinsfile from git https://github.com/inanzzz/game
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/game
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Checkout SCM)
[Pipeline] echo
> Checking out the source control ...
[Pipeline] checkout
using credential 1a41495c-ad85
> git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
> git config remote.origin.url https://github.com/inanzzz/game # timeout=10
Fetching upstream changes from https://github.com/inanzzz/game
> git --version # timeout=10
using GIT_SSH to set credentials
> git fetch --tags --progress https://github.com/inanzzz/game +refs/heads/*:refs/remotes/origin/*
> git rev-parse refs/remotes/origin/develop^{commit} # timeout=10
> git rev-parse refs/remotes/origin/origin/develop^{commit} # timeout=10
Checking out Revision 139991 (refs/remotes/origin/develop)
> git config core.sparsecheckout # timeout=10
> git checkout -f 139991
Commit message: "Format"
> git rev-list --no-walk 86e9d7 # timeout=10
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Git Pull)
[Pipeline] echo
> Pulling the code from GitHub repository ...
[Pipeline] sh
+ git remote update
Fetching origin
+ git checkout develop
Previous HEAD position was 139991f... Format
Switched to branch 'develop'
Your branch and 'origin/develop' have diverged,
and have 10 and 1 different commit each, respectively.
(use "git pull" to merge the remote branch into yours)
+ git pull origin develop
From https://github.com/inanzzz/game
* branch develop -> FETCH_HEAD
Merge made by the 'recursive' strategy.
ci/pipeline/branch/develop/Jenkinsfile | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Docker Up)
[Pipeline] echo
> Building the docker containers ...
[Pipeline] sh
+ cd docker
+ cd ci
+ make build
Creating network "game_default" with the default driver
Creating game_php ...
[1A[2K
Creating game_php ... [32mdone[0m
[1B[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Composer Install)
[Pipeline] echo
> Building the application within the container ...
[Pipeline] sh
+ cd docker
+ cd ci
+ make composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] echo
> Running the application tests ...
[Pipeline] sh
+ cd docker
+ cd ci
+ make test
php-cs-fixer
phpunit
phpstan
Loaded config default.
.
Legend: ?-unknown, I-invalid file syntax, file ignored, S-Skipped, .-no changes, F-fixed, E-error
Checked all files in 0.008 seconds, 10.000 MB memory used
PHPUnit 7.5.4 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 18 ms, Memory: 4.00MB
OK (1 test, 1 assertion)
[OK] No errors
Stopping game_php ...
[1A[2K
Stopping game_php ... [32mdone[0m
[1BRemoving game_php ...
[1A[2K
Removing game_php ... [32mdone[0m
[1BRemoving network game_default
Total reclaimed space: 0B
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS