Zen and-the-art-of-build-script-maintenance-skillsmatter

71
ZEN and the art of Build Script Maintenance An Inquiry into Build Automation Quality

Transcript of Zen and-the-art-of-build-script-maintenance-skillsmatter

Page 1: Zen and-the-art-of-build-script-maintenance-skillsmatter

ZENand the art of

Build Script Maintenance

An Inquiry into Build Automation Quality

Page 2: Zen and-the-art-of-build-script-maintenance-skillsmatter

John Ferguson SmartWakaleo Consulting

Web: http://www.wakaleo.comEmail: [email protected]: wakaleo

Page 3: Zen and-the-art-of-build-script-maintenance-skillsmatter

Who is this guy, anyway?John Ferguson SmartConsultant, Trainer, Mentor, Author, Speaker

Specialities:

Java, Groovy/Grails

Software Development Lifecycle

Agile stuff (CI, TDD, BDD,...)

Open Source

Page 4: Zen and-the-art-of-build-script-maintenance-skillsmatter

AgendaWhat are we discussing today?What makes a good build script?

Smelly build scripts

Choosing your tools

Maven tips

Ant tips

Page 5: Zen and-the-art-of-build-script-maintenance-skillsmatter

IntroductionQuality build scripts - why botherMaintenance costs

Learning curve

Turn-over

Portability

Automation

Page 6: Zen and-the-art-of-build-script-maintenance-skillsmatter

Build quality - quality buildsWhat makes a good build script?Gold Standard

Portable

Reproducible

Standard

Maintainable

Page 7: Zen and-the-art-of-build-script-maintenance-skillsmatter

Build quality - quality buildsGold StandardReference build process

Reference binaries

Page 8: Zen and-the-art-of-build-script-maintenance-skillsmatter

Build quality - quality buildsPortableRuns anywhere

Runs on any OS

No local dependencies

Environment-specific configurations

Specially-installed software or databases

...

Page 9: Zen and-the-art-of-build-script-maintenance-skillsmatter

Build quality - quality buildsReproducible“Play it again, Sam”

Page 10: Zen and-the-art-of-build-script-maintenance-skillsmatter

Build quality - quality buildsStandardKnowing what to expect

Page 11: Zen and-the-art-of-build-script-maintenance-skillsmatter

Build quality - quality buildsMaintainableThink of the next dude

Page 12: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsSo what makes a poor build script?

1) The hard coded build

2) The OS-specific build

3) The IDE-only build

4) The Magic Machine build

5) The Oral Tradition build

6) The Nested build

7) The Messy Dependencies build

8) The DYI build

9) The untrustworthy build

10) The slow build

Page 13: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe hard coded build

C:/bea/weblogic-9.1/..

Paths

http://testserver.acme.com:7001

URLs

<svn username="scott" password="tiger"...>Passwords

<property name="dir.jboss" value="${env.JBOSS_HOME}"/>

Environment variables

Page 14: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe hard coded build

<target name="checkstyle">

<delete dir="./reports" quiet="true" /> <mkdir dir="./reports" /> <checkstyle config="./docs/sun_checks.xml"> <formatter type="xml" tofile="./reports/checkstyle.xml"/> <fileset dir="./src" includes="**/*.java"/> </checkstyle>

<style in="./reports/checkstyle.xml" out="./reports/checkstyle.html" style="checkstyle.xsl"/>

</target>

Hard-coded directories

Page 15: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe hard coded build

<target name="checkstyle">

<delete dir="./reports" quiet="true" /> <mkdir dir="./reports" /> <checkstyle config="./docs/sun_checks.xml"> <formatter type="xml" tofile="./reports/checkstyle.xml"/> <fileset dir="./src" includes="**/*.java"/> </checkstyle>

<style in="./reports/checkstyle.xml" out="./reports/checkstyle.html" style="checkstyle.xsl"/>

</target>

<property name=”reports.checkstyle.dir” value=”${basedir}/reports”/>

<target name="checkstyle"> <delete dir="${reports.checkstyle.dir}" quiet="true" /> <mkdir dir="${reports.checkstyle.dir}" /> <checkstyle config="./docs/sun_checks.xml"> <formatter type="xml" tofile="${reports.checkstyle.dir}/checkstyle.xml"/> <fileset dir="./src" includes="**/*.java"/> </checkstyle>

<style in="${reports.checkstyle.dir}/checkstyle.xml" out="${reports.checkstyle.dir}/checkstyle.html" style="checkstyle.xsl"/>

</target>

Project-relative directory

DRY

Page 19: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe hard coded build

<property environment="env"/><property name="dir.jboss" value="${env.JBOSS_HOME}"/>

Environment variable

Page 20: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe OS-specific build

<exec command="grep \"@\" ${build.dir} | wc -l" outputproperty="token.count"/>

Page 21: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe OS-specific build

...CALL PAUSE.CMD...

build.cmd

...:: Check for a non-existent IP address:: Note: this causes a small extra delay!IF NOT DEFINED NonExist SET NonExist=10.255.255.254PING %NonExist% -n 1 -w 100 2>NUL | FIND "TTL=" >NUL...

pause.cmd

Page 22: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe IDE-only build

Page 23: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe Magic Machine build

Directories

App servers

Databases

Configuration files

Environment variables

Installed software or tools

Page 24: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe Magic Machine build

Directories

App servers

Databases

Configuration files

Environment variables

Installed software or tools

<proprerty weblogic.dir="/u01/app/bea/weblogic-9.1"/>

Page 25: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe Oral Tradition build

Page 26: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe Nested Build

#! /bin/shANT_HOME=/u01/app/tools/ant-1.7.1...$ANT_HOME/ant $1project/tools/ant.sh

Page 28: Zen and-the-art-of-build-script-maintenance-skillsmatter

The Messy Dependencies buildJAR files in the SCM

Unversioned JAR files

Unclear dependencies

Smelly builds

Page 29: Zen and-the-art-of-build-script-maintenance-skillsmatter

The DYI build“Not invented here”

DYI dependencies

DYI deployments

DYI Maven releases

...

Smelly builds

Page 30: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe untrustworthy build<junit fork="yes" haltonfailure="false" dir="${basedir}"> <classpath refid="test.class.path" /> <classpath refid="project.class.path"/> <formatter type="plain" usefile="true" /> <formatter type="xml" usefile="true" /> <batchtest fork="yes" todir="${logs.junit.dir}"> <fileset dir="${test.unit.dir}"> <patternset refid="test.sources.pattern"/> </fileset> </batchtest></junit>

Page 31: Zen and-the-art-of-build-script-maintenance-skillsmatter

Smelly buildsThe slow build

Page 32: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsFlexibility verses ConventionWhat’s better: flexibility or standards?

It depends what you’re doing...

Page 33: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsStandards and Conventions

No standards

Make up your own standards

Support standards

Encourage/enforce standards

Standards and ConventionsAd-hoc scripting

Eas

y to

rea

dH

ard

to

rea

d

23

Page 34: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsFlexibility and expressiveness

Eas

y to

rea

dH

ard

to

rea

d

Easy to do whatever you wantMakes you stick to conventions

3

Encourage/enforce standards

Do whatever you want

2

Page 35: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsFlexibility verses ConventionBuild Scripting Rule 1

“A build script will tend to reflect the personality of it’s developer”

Page 36: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsFlexibility verses ConventionBuild Scripting Rule 2

“The more flexible a build script, the more likely it is to become unmaintainable”

Page 37: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsFlexibility verses ConventionFlexibility is great for some jobs:

Ad-hoc tasks

Some deployment tasks

“Out-of-the-box” stuff

Page 38: Zen and-the-art-of-build-script-maintenance-skillsmatter

Choosing your toolsFlexibility verses ConventionBut too much flexibility is hard to maintain

Page 39: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsBetter Ant scriptsConsistent conventions

Declare your dependencies

Make it readable

Tidy up your mess

Avoid long scripts

Page 40: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsBe consistent

Standardize target names

Document your public targets

Page 41: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsDeclare your dependencies

Use an Enterprise Repository Manager

Several tool choices:

Maven Ant Tasks

Ivy

Page 42: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsUsing the Maven Ant Tasks

Declare dependencies

Deploy to a Maven Enterprise Repository

<artifact:dependencies pathId="dependency.classpath"> <dependency groupId="junit" artifactId="junit" version="3.8.2" scope="test"/> <dependency groupId="javax.servlet" artifactId="servlet-api" version="2.4" scope="provided"/></artifact:dependencies>

Page 43: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsMake it readable

Write a build script like your source code...

Avoid long targets

Avoid long build scripts

Use descriptive target names

Page 44: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsTidy up your mess

Always define a ‘clean’ target.

Page 45: Zen and-the-art-of-build-script-maintenance-skillsmatter

Ant tipsMove to Maven ;-)

Page 46: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsBetter Maven scriptsSimple

Portable

Reproducible

Clean

Automated

Page 47: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKeep it simpleUse modules

Use an organization-level POM

Page 48: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKeep it portableNo hard-coding

Define sensible defaults for properties and profiles

Avoid resource filtering for production code

Page 49: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKeep it reproducibleAvoid external snapshots

Specify plugin versions

Use consistent environments

Page 50: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsConsistent environmentsEnforcing a minimum Maven version

<?xml version="1.0"?><project...> <modelVersion>4.0.0</modelVersion> <groupId>com.ciwithhudson.gameoflife</groupId> <artifactId>gameoflife</artifactId> <version>0.0.1-SNAPSHOT</version> <name>gameoflife</name> <prerequisites> <maven>2.2.1</maven> </prerequisites>

Minimum Maven version

Page 51: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsConsistent environmentsUse the same version of Maven

Use a “standard” Maven installation across the organization

Use a global settings.xml file

Store a copy in SCM

Enforce a minimum Maven version in your projects

Page 52: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsEnforcing consistency with the enforcer pluginMaven version

JDK version

Snapshots

Plugin versions

OS

...

Page 53: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsEnforce the Maven version

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.0-beta-1</version> <executions> <execution> <id>enforce-maven-version</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireMavenVersion> <version>2.2.1</version> </requireMavenVersion> </rules> </configuration> </execution> </executions> </plugin>

Minimum Maven version

Page 54: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsEnforce the JDK versionAll developers should be using the same JDKs

Incompatible bytecode

Different XML parsers

Different Maven behaviour

Page 55: Zen and-the-art-of-build-script-maintenance-skillsmatter

Enforce the JDK version

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.0-beta-1</version> <executions> <execution> <id>enforce-jdk-version</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireJavaVersion> <version>[1.5.0,1.6.0)</version> </requireJavaVersion> </rules> </configuration> </execution> </executions> </plugin>

Maven tips

Authorized JDK versions

Page 56: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsSpecify your plugin versionsUndeclared version numbers are bad

Inconsistent builds across different machines

Non-repeatable builds

Plugin changes can break the build

Don’t use SNAPSHOT plugins either

Page 57: Zen and-the-art-of-build-script-maintenance-skillsmatter

Specify your plugin versions

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.0-beta-1</version> <executions> <execution> <id>enforce-versions</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requirePluginVersions/> </rules> </configuration> </execution> </executions> </plugin>

Maven tips

Plugin versions must be defined

Page 58: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKeep it cleanKeep tabs on your dependencies:

What dependencies are you actually using?

What dependencies do you really need?

Page 59: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsDependency list What dependencies are you actually using?$ mvn dependency:list[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'dependency'.[INFO] ------------------------------------------------------------------------[INFO] Building babble-core[INFO] task-segment: [dependency:list][INFO] ------------------------------------------------------------------------[INFO] [dependency:list][INFO] [INFO] The following files have been resolved:[INFO] antlr:antlr:jar:2.7.6:compile...[INFO] commons-collections:commons-collections:jar:2.1.1:compile[INFO] commons-logging:commons-logging:jar:1.0.4:compile[INFO] dom4j:dom4j:jar:1.6.1:compile[INFO] javax.persistence:persistence-api:jar:1.0:compile[INFO] javax.transaction:jta:jar:1.0.1B:compile[INFO] junit:junit:jar:4.5:test[INFO] net.sf.ehcache:ehcache:jar:1.2:compile[INFO] org.hamcrest:hamcrest-all:jar:1.1:compile[INFO] org.hibernate:hibernate:jar:3.2.0.ga:compile[INFO] org.hibernate:hibernate-annotations:jar:3.2.0.ga:compile[INFO] [INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESSFUL[INFO] ------------------------------------------------------------------------

mvn dependency:list

Page 60: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsDependency tree Where do they come from?$ mvn dependency:tree[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'dependency'.[INFO] ------------------------------------------------------------------------[INFO] Building babble-core[INFO] task-segment: [dependency:tree][INFO] ------------------------------------------------------------------------[INFO] [dependency:tree][INFO] com.sonatype.training:babble-core:jar:1.0-SNAPSHOT[INFO] +- org.hibernate:hibernate:jar:3.2.0.ga:compile[INFO] | +- net.sf.ehcache:ehcache:jar:1.2:compile[INFO] | +- javax.transaction:jta:jar:1.0.1B:compile[INFO] | +- commons-logging:commons-logging:jar:1.0.4:compile[INFO] | +- asm:asm-attrs:jar:1.5.3:compile[INFO] | +- dom4j:dom4j:jar:1.6.1:compile[INFO] | +- antlr:antlr:jar:2.7.6:compile[INFO] | +- cglib:cglib:jar:2.1_3:compile[INFO] | +- asm:asm:jar:1.5.3:compile[INFO] | \- commons-collections:commons-collections:jar:2.1.1:compile[INFO] +- org.hibernate:hibernate-annotations:jar:3.2.0.ga:compile[INFO] | \- javax.persistence:persistence-api:jar:1.0:compile[INFO] +- junit:junit:jar:4.5:test[INFO] \- org.hamcrest:hamcrest-all:jar:1.1:compile[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESSFUL[INFO] ------------------------------------------------------------------------

mvn dependency:tree

Page 61: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsDependencies in EclipseEclipse has an equivalent screen

Page 62: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsDependency analyse What dependencies do you really need?$ mvn dependency:analyze[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'dependency'.[INFO] ------------------------------------------------------------------------[INFO] Building babble-core[INFO] task-segment: [dependency:analyze][INFO] ------------------------------------------------------------------------[INFO] Preparing dependency:analyze...[INFO] [dependency:analyze][WARNING] Used undeclared dependencies found:[WARNING] javax.persistence:persistence-api:jar:1.0:compile[WARNING] Unused declared dependencies found:[WARNING] org.hibernate:hibernate-annotations:jar:3.2.0.ga:compile[WARNING] org.hibernate:hibernate:jar:3.2.0.ga:compile[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESSFUL[INFO] ------------------------------------------------------------------------

mvn dependency:analyse

Used but not declared

Declared but not used

Page 63: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsExcluding dependenciesWhat if you don’t want a dependency? <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>2.5.5</version> <exclusions> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms<artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jms_1.1_spec</artifact> <version>1.1</version> </dependency> <dependencies>

Don’t include JMS

Page 64: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsStandardizing versionsUse dependencyManagement for consistency

<dependencyManagement> <dependencies> <dependency> ! <groupId>mysql</groupId> ! <artifactId>mysql-connector-java</artifactId> ! <version>5.1.6</version> </dependency> <dependency> ! <groupId>postgres</groupId> ! <artifactId>postgres</artifactId> ! <version>7.3.2</version> </dependency> </dependencies></dependencyManagement>

<dependencies> <dependency> !<groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency></dependencies>

Parent pom

Child pom

Page 65: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKeep it automatedPlan your release strategy

Use a Repository Manager

Automatic snapshot deployments

Automated releases

Page 66: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsMaven best practices for CI buildsUse batch mode (-B)

Always check or snapshot updates (-U)

Use a repository per project

Print test failures to stdout (-Dsurefire.useFile=false)

Page 67: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKnow when to script itGroovy or Ant scripting is easy in Maven

Call external scripts when appropriate

Page 68: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKnow when to script itIt’s pretty easy in Maven 2...<project> <build> <plugins> <plugin> <groupId>org.codehaus.groovy.maven</groupId> <artifactId>gmaven-plugin</artifactId> <version>1.0-rc-5</version> <executions> <execution> <phase>compile</phase> <goals> <goal>execute</goal> </goals> <configuration> <source> println "Hi there I’m compiling ${project.name}" </source> </configuration> </execution> </executions> </plugin> </plugins> </build> ...

Page 69: Zen and-the-art-of-build-script-maintenance-skillsmatter

Maven tipsKnow when to script itIt’s even easier in Maven 3...project { build { $execute(id: 'compilation-script', phase: 'compile') { println "Hi there I’m compiling ${project.name}" } $execute(id: 'validation-script', phase: 'validate') { println "Hi there I’m validating ${project.name}" } ... }}

Page 70: Zen and-the-art-of-build-script-maintenance-skillsmatter

Want to learn more?

Java Power Tools BootcampLondon - October 13-17 2010

Page 71: Zen and-the-art-of-build-script-maintenance-skillsmatter

Thank You

John Ferguson SmartWakaleo Consulting

Web: http://www.wakaleo.comEmail: [email protected]: wakaleo