Jenkins for
PHP projects

Stephan Hochdörfer // 24.03.2016

About me


  • Stephan Hochdörfer
  • Head of Technology, bitExpert AG
    (Mannheim, Germany)
  • S.Hochdoerfer@bitExpert.de
  • @shochdoerfer

  • #PHP, #DevOps, #Automation
  • #phpugffm, #phpugmrn, #unKonf

Our story: Diversity

Back in the "old" days...

...and today: Jenkins

Jenkins Use Cases

  • Running continuous builds

  • Running nightly builds

  • Running integration tests

  • Triggering Satis builds

  • Gitlab builds

PHP Projects with Jenkins

Template for Jenkins Jobs

General Jenkins set-up

Jenkins Project Overview

Icon Config Management

Jenkins Job Icon Config

Config File Management

Jenkins Node Overview

Jenkins Node Config

Jenkins Node Environment

Continuous build




« [...] environments automatically rebuild the project whenever
changes are checked in - often several times a day -
and provide more immediate feedback » - Wikipedia

Our typical (PHP) toolchain




Composer, Phing, PHPUnit,

PHP_CodeSniffer, PDepend, PHPCPD

Project structure

/tmp/myproject
   |-build
   |---coverage
   |---logs
   |---pdepend
   |-docs
   |-src
   |---Vendor
   |-----MyProject
   |-tests
   |---Vendor
   |-----MyProject
   |-vendor
   |-web
   |-build.xml
   |-composer.json
   |-composer.lock
   |-phpdoc.dist.xml
   |-phpmd.xml
   |-phpunit.xml.dist

Basic Phing build.xml

<?xml version="1.0"?>
<project name="ci" default="ci:help" basedir=".">

    <target name="-ci:clean"
            depends="-init"
            hidden="true">

        <delete dir="${phing.dir}/build/logs" quiet="true" />
    </target>

    <target name="-ci:prepare"
            depends="-init, -ci:clean"
            hidden="true" >

        <mkdir dir="${phing.dir}/build/logs"/>
    </target>

    <target name="ci:build"
            depends="-init, -ci:prepare, ci:pdepend, ci:phpunit, 
            ci:phpcpd, ci:phpmd, ci:phpcs" />
</project>

Jenkins Job Config

Label Usage

Define Git repository

Polling vs. Push notifications

Polling vs. Push notifications

Polling vs. Push notifications

#!/bin/bash

# https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin
repo="https://gitlab.loc/customer-1/project-1.git"
curl -s -o /dev/null "https://jenkins.loc/jenkins/git/notifyCommit?url=${repo}" 2>&1

Environment configuration

Push config files to node

Validate composer.json

Installing dependencies

Running Phing

Installing npm dependencies

Running Grunt

Process the build results

Clover PHP Coverage Report

Email notifications

Email notifications

Trigger HHVM / PHP7 builds

Execute HHVM build

Trigger Satis build

Running nightly builds




« A nightly build is a neutral build that takes place automatically. These typically take place when no one is likely to be working in the office [...] » - Wikipedia

Security issues?




Check composer.lock file


$ php security-checker.phar security:check ./composer.lock
Security Check Report
~~~~~~~~~~~~~~~~~~~~~

Checked file: composer.lock


  [OK]
  0 packages have known vulnerabilities

Security Checker Phing task

Automate with Jenkins

Running integration tests




« [...] is the phase in software testing in which individual software modules are combined and tested as a group. » - Wikipedia

Running Phing

Running Grunt

Triggering Satis builds




Satis is a ultra-lightweight, static
file-based version of packagist.

Installing Satis

$ composer.phar create-project composer/satis --stability=dev
{
    "name": "bitExpert Satis repo",
    "homepage": "https://satis.loc",
    "repositories": [
        { "type": "vcs", "url": "/srv/repos/project-1.git" },
        { "type": "vcs", "url": "/srv/repos/project-2.git" }
    ],
    "require-all": true,
    "archive": {
        "directory": "dist",
        "format": "zip",
        "skip-dev": false
    }
}

Running Satis

$ php bin/satis build config.json web/
$ php bin/satis build config.json web/ customername/project1

Jenkins Satis Job Config

Define Job Param (Package)

Define Job Param (Recipient)

Running Satis build

Rewrite repo urls

Cleanup old files

Notify users after build

Running the build

Console output

Satis repository

Run Composer

$ composer.phar require customername/project1
Using version ^1.0 for customername/project1
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing customername/project1 (1.0.0)
    Downloading: 100%

Writing lock file
Generating autoload files

Gitlab builds

Gitlab Jenkins Webhook

Jenkins Gitlab Plugin Config

Jenkins Job Build Trigger

Gitlab Jenkins Webhook

Gitlab Commit Build running

Gitlab Commit Build result

Gitlab Merge Request

Gitlab Merge Request

Gitlab Merge Request

Jenkins Plugins Reference








Thank you! Questions?







Do not forget to rate the talk:
https://joind.in/talk/64f61