Bu örnekte, Jenkins pipeline aşamalarını GitHub depomuza göre manuel olarak çalıştıracağız. Jenkins'de bir testi tetiklediğimizde, Jenkins GitHub'a SSH ile bağlanacak ve GitHub deposunda bulunan Jenkinsfile içinde listelenen tüm pipeline aşamalarını çalıştıracak.


Akış


Jenkins GitHub'dan docker uygulamamızı çeker, containerleri kurar, containerler içinde tüm testleri çalıştırır, containerleri durdurur ve docker artıklarını ortadan kaldırır. Hepsi bu kadar!


Ön şartlar


Jenkins sunucusu GitHub SSH entegrasyonu


Jenkins sunucusunun SSH anahtarının GitHub deposuna eklendiğinden emin olun. Jenkins UI'ye giriş yaptıktan sonra aşağıdakileri uygulayın.


  1. Sol taraftaki "Credentials" linkini tıklayın.

  2. Önce "Jenkins/Global", daha sonrada "Add credentials" linkini tıklayın.

  3. "Kind" bölümünden "SSH Username and private key" seçeneğini seçin.

  4. "Username" bölümüne bir isim belirleyin (örneğin: GitHub-inanzzz).

  5. "Enter directly" radio butonuna tıklayın ve daha sonra ~/.ssh/id_rsa.pub dosyasının içeriğini text alanına yapıştırın.

  6. Kaydedip çıkın.

Jenkins kullanıcısının "docker" komutlarını çalıştırması


Öncelikle, "docker" ve "docker-compose" öğelerinin Jenkins sunucusunda yüklü olduğundan emin olun. Bununla birlikte jenkins kullanıcısının $ docker ... ve $ docker-compose ... CLI komutlarını çalıştırabilmesini sağlayın. Terminalde $ sudo usermod -aG docker $USER ve $ sudo usermod -aG docker jenkins komutlarını çalıştırın. Değişikliklerin etkili olması için Jenkins sunucusunu yeniden başlatmanız gerekecek. Not: Jenkins sunucusuna jenkins kullanıcısı olarak bağlanmak için $ sudo -i -u jenkins komutunu kullanabilirsiniz.


"Pipeline" projesinin kurumu


Jenkins'in ana sayfasında "New Item" linkine tıklayıp "Test" isminde yeni bir item yaratın ve sonraki sayfadan "Pipeline" seçeneğini seçin.


  1. "Pipeline" bölümünden "Pipeline script from SCM" seçeneğini seçin.

  2. SCM olarak "Git" seçin.

  3. "Repository URL" için https://github.com/inanzzz/game linkini kullanın.

  4. "Credentials" bölümünden GitHub-inanzzz seçeneğini seçin.

  5. İsteğe bağlı olarak */master*/develop olarak değiştirin.

  6. "Script path" bölümüne ci/pipeline/branch/develop/Jenkinsfile yazın.

  7. Kaydedip çıkın.

Uygulama yapısı


.
├── ci
│ └── pipeline
│ └── branch
│ └── develop
│ └── Jenkinsfile
├── composer.json
├── docker
│ └── ci
│ ├── docker-compose.yml
│ ├── .env
│ ├── Makefile
│ └── php
│ └── Dockerfile
├── src
│ └── Football.php
└── tests
└── FootballTest.php

Dosyalar


Jenkinsfile


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'
}
}
}
}

composer.json


{
"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
}
}

docker-compose.yml


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

.env


COMPOSE_PROJECT_NAME=game

Makefile


Bu dosyayı yaratmamızın nedeni, Jenkins Pipeline eklentisinin $ docker-composer ... komutlarını çalıştıramamasıdır.


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

Dockerfile


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

Test


"Build Now" linkine tıklarsanız, ilk build başarıyla çalıştırılmalı ve konsol çıktısı aşağıdakine benzemelidir.


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