Continous delivery with sbt

Preview:

Citation preview

CONTINOUS DELIVERYWITH SBT

JENKINS, DOCKER, GATLING AND MORECreated by Wojciech Pituła

DEPLOYMENT PIPELINE

BENEFITSRepeatable deploysHistory of deploysNo knowledge needed to deployFast rollback to previous version

RELEASE STAGE

COMMIT> ...

> sbt test

> ...

> git push

JENKINS POLL

SBT RELEASEproject/plugins.sbt

addSbtPlugin("com.github.gseitz" % "sbt­release" % "1.0.0")

shell> sbt release

jenkins

RELEASE PROCESSBUILD.SBT

import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._releaseProcess := Seq[ReleaseStep]( checkSnapshotDependencies, inquireVersions, runTest, setReleaseVersion, commitReleaseVersion, tagRelease, ReleaseStep(releaseStepTask(publish in Docker)), publishArtifacts, setNextVersion, commitNextVersion, pushChanges)

inquireVersionsReleaseStep(releaseStepTask(publish in Docker))publishArtifactspushChanges

RELEASE: INQUIRE VERSIONSVERSION.SBT

version in ThisBuild := "0.1.40­SNAPSHOT"

inquireVersionspublishArtifactsReleaseStep(releaseStepTask(publish in Docker))pushChanges

RELEASE: PUBLISH ARTIFACTSoptional

> sbt publish

inquireVersionspublishArtifactsReleaseStep(releaseStepTask(publish in Docker))pushChanges

BUILD.SBTpublishMavenStyle := truepublishArtifact in Test := falsepomIncludeRepository := _ => false publishTo := val nexus = "http://nexus.int.wp­sa.pl/" if (isSnapshot.value) Some("snapshots" at nexus + "content/repositories/snapshots" else Some("releases" at nexus + "content/repositories/releases")

RELEASE: DOCKERplugins.sbt

addSbtPlugin("com.typesafe.sbt" % "sbt­native­packager" % "1.0.3")

shell> sbt docker:publish

inquireVersionspublishArtifactsReleaseStep(releaseStepTask(publish in Docker))pushChanges

BUILD.SBTenablePlugins(JavaAppPackaging)dockerBaseImage := "java:8"dockerRepository := Some("hub.docker.grupawp.pl/itrd")

RELEASE: PUSHPush bumped version and tag to origin

inquireVersionspublishArtifactsReleaseStep(releaseStepTask(publish in Docker))pushChanges

SUCCESS

TRIGGER NEXT STEP

ADD RELEASED_VER PARAMETER

TRIGGER BUILD WITH PARAMS

DEPLOY TO DEV

DEPLOY BUILD

DEPLOY SCRIPT#!/usr/bin/env bashset ­xueAPP_VERSION=$1HOST=$2APP_NAME=ab­tests­serviceDOCKER_IMAGE=hub.docker.grupawp.pl/itrd/ab­tests­service:$APP_VERSIONshift 2RUN_OPTS=$@ssh ­t ­o StrictHostKeyChecking=no jenkins­ci@$HOST << EOF docker pull $DOCKER_IMAGE docker stop $APP_NAME docker rm $APP_NAME docker run ­­name $APP_NAME ­d ­p 8080:8080 $DOCKER_IMAGE $RUN_OPTSEOF# verify if docker is runningsleep 30ssh ­t ­o StrictHostKeyChecking=no jenkins­ci@$HOST 'RUNNING=docker inspect ­­format=" .State.Running " ab­tests­service; [[ $RUNNING == "true" ]]'

MACHINE SETUPANSIBLE PLAYBOOK

­­­­ hosts: all sudo: yes

tasks: ­ name: install docker­engine yum: name=docker­engine state=present

­ name: create jenkins user user: name=jenkins­ci groups=docker state=present shell=/bin/bash home=/opt/jenkins­ci createhome=yes

­ name: Set up authorized_keys for the deploy user authorized_key: user=jenkins­ci key=" item " with_file: ­ id_rsa.pub_noweci ­ id_rsa.pub

SUCCESS

TESTSTriggered automatically after deploy

GATLINGAn open-source load testing framework based on Scala,

Akka and Netty

High performanceReady-to-present HTML reportsScenario recorder and developer-friendly DSL

GATLING SCENARIOPut in src/it/scala

class AddAndDeleteSingleTestSimulation extends Simulation val httpConf = http.baseURL("some.url") val testScenario = scenario("AddAndGetSingleTest") .exec( http("PostNewTest") .post("some/endpoint") .header("Content­Type", "application/json") .body(StringBody("body")) .check(status.is(201)) ) .exec( http("GetCreatedTest") .get("some/endpoint") .check(status.is(200), jsonPath("$.testDef.name").is(testName)) ) .exec( http("DeleteCreatedTest")

PLUGINS.SBTaddSbtPlugin("io.gatling" % "gatling­sbt" % "2.1.5")

BUILD.SBTenablePlugins(GatlingPlugin)configs(IntegrationTest, GatlingIt)Defaults.itSettings

2015­09­09 12:38:33 +02:00, duration : 0 secondsGLOBAL DETAILS

> Global Information

Expand all groups | Collapse all groups

ASSERTIONS

Assertion

For all requests: count of failed requests is 0

STATISTICS

Executions Response Time (ms)

KO OK

0

1

Number of requestsNu

mber o

f Requests

t < 800 ms 800 ms < t < 1200ms

t > 1200 ms failed0

1

2

3

4

5

Indicators

addanddeletesingletestsimulation

Active Users

Requests / sec

Responses / sec

SUCCESS

DEPLOY TO PRODUCTIONExactly the same process like with DEV environment

TRIGGER MANUALLY

SUCCESS

DRAWBACKS AND PROBLEMSbinaries and config separationsmoke testsproduction db passworddata migration/schema updatesdeployment downtime

TRICKSbuild-name-setter