SlideShare a Scribd company logo
Zen and-the-art-of-build-script-maintenance-skillsmatter
Zen and-the-art-of-build-script-maintenance-skillsmatter
Who is this guy, anyway?
John Ferguson Smart
Consultant, Trainer, Mentor, Author, Speaker
Specialities:
 Java, Groovy/Grails
 Software Development Lifecycle
 Agile stuff (CI, TDD, BDD,...)
 Open Source
Agenda
What are we discussing today?
What makes a good build script?
Smelly build scripts
Choosing your tools
Maven tips
Ant tips
Introduction
Quality build scripts - why bother
Maintenance costs
Learning curve
Turn-over
Portability
Automation
Build quality - quality builds
What makes a good build script?
Gold Standard
Portable
Reproducible
Standard
Maintainable
Build quality - quality builds
Gold Standard
Reference build process
Reference binaries
Build quality - quality builds
Portable
Runs anywhere
Runs on any OS
No local dependencies
 Environment-specific configurations
 Specially-installed software or databases
 ...
Build quality - quality builds
Reproducible
“Play it again, Sam”
Build quality - quality builds
Standard
Knowing what to expect
Build quality - quality builds
Maintainable
Think of the next dude
Smelly builds
 So 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
Paths
                                                                       ..
                                                                    1/




                                                                            URLs
Smelly builds




                                                                  9.
                                                               c-
                                                             gi
                                                          lo




                                                                                               1
                                                        eb




                                                                                            00



                                                                                                           Passwords
                                                     /w




                                                                                         :7
                                                                                      om
                                                   ea




                                                                                   .c
                                               /b




                                                                                me
                                              C:




                                                                             ac
                                                                          r.
                                                                       ve
                                                                    er
                                                                 ts
                                                              es                                               .>
                                                           /t                                              "..
                                                        :/                                             ger
                                                                                                  "ti
                                                     tp                                       rd=
                The hard coded build




                                                  ht                                     swo
                                                                                   pas
                                                                            tt"
                                                                       sco
                                                                  e="
                                                            nam
                                                      ser
                                                  n u
                                              <sv
                                                                                                                            />
                                                                                                                     M E }"
                                                                                                                S_HO
                                                                                                           JBOS
                                                                                                      env.
                                                                                               = "$ {
                                                                                       alue
                                                                                s" v




                                                                                                         Environment
                                                                        jbos
                                                                 dir.
                                                          me="




                                                                                                          variables
                                                   y na
                                              pert
                                       <pro
Smelly builds
The hard coded build

<target name="checkstyle">
                                           Hard-coded directories
  <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>
Smelly builds
    The hard coded build

    <target name="checkstyle">                Project-relative directory
<property name=”reports.checkstyle.dir”
      <delete dir="./reports" quiet="true" />
          value=”${basedir}/reports”/>
      <mkdir dir="./reports" />                         DRY
      <checkstyle config="./docs/sun_checks.xml">
<target name="checkstyle">
        <formatter type="xml" tofile="./reports/checkstyle.xml"/>
  <delete dir="${reports.checkstyle.dir}" quiet="true" />
  <mkdir<fileset dir="./src" includes="**/*.java"/>
         dir="${reports.checkstyle.dir}" />
      </checkstyle>
  <checkstyle config="./docs/sun_checks.xml">
    <formatter type="xml"
      <style in="./reports/checkstyle.xml"
                tofile="${reports.checkstyle.dir}/checkstyle.xml"/>
    <fileset out="./reports/checkstyle.html"
             dir="./src" includes="**/*.java"/>
             style="checkstyle.xsl"/>
  </checkstyle>

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

</target>
Smelly builds
    The hard coded build
<target name="war" >
  <war destfile="c:/tomcat/jakarta-tomcat-5.0.19/webapps/app.war"
       webxml="${src}/app.xml" basedir="${bin}" />
</target>


                  Hard-coded directories
Smelly builds
    The hard coded build
<property name="wardir"
          location="c:/tomcat/jakarta-tomcat-5.0.19/webapps"/>

<target name="war" >
  <war destfile="${wardir}" webxml="${src}/app.xml"
       basedir="${bin}" />
</target>
                  Still hard-coded
Smelly builds
   The hard coded build




<svn username="scott" password="tiger">
  <checkout url="http://subversion.acme.com/myapp/trunk"
            destPath="${subproject.dir}" />
</svn>

       Hard-coded username/password
Smelly builds
The hard coded build




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




                         Environment variable
Smelly builds
The OS-specific build


<exec command="grep "@" ${build.dir} | wc -l"
      outputproperty="token.count"/>
Smelly builds
The 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.254
  PING %NonExist% -n 1 -w 100 2>NUL | FIND "TTL=" >NUL
  ...
    pause.cmd
Smelly builds
The IDE-only build
Smelly builds
The Magic Machine build



                                         Directories

                           App servers


                Databases


       Configuration files


Environment variables


Installed software or tools
Smelly builds
The Magic Machine build


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

                                         Directories

                           App servers


                Databases


       Configuration files


Environment variables


Installed software or tools
Smelly builds
The Oral Tradition build
Smelly builds
The Nested Build

#! /bin/sh
ANT_HOME=/u01/app/tools/ant-1.7.1
...
$ANT_HOME/ant $1
project/tools/ant.sh
Smelly builds
   The Nested Build

<target name="build-subproject">
  <svn username="scott" password="tiger">
    <checkout url="http://subversion.acme.com/someproject/trunk"
              destPath="${subproject.dir}" />
  </svn>

  <ant dir="${subproject.dir}" target="build-all" />
</target>
build.xml
Smelly builds
The Messy Dependencies build
JAR files in the SCM
Unversioned JAR files
Unclear dependencies
Smelly builds
The DYI build
“Not invented here”
DYI dependencies
DYI deployments
DYI Maven releases
...
Smelly builds
The 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>
Smelly builds
The slow build
Choosing your tools
Flexibility verses Convention
What’s better: flexibility or standards?
It depends what you’re doing...
Choosing your tools
                                                                  Encourage/enforce

       Standards and Conventions              Support standards
                                                                      standards


                                                                                      3
Easy to read




                                                                                      2
                              Make up your
                              own standards




               No standards
Hard to read




Ad-hoc scripting                                      Standards and Conventions
Choosing your tools
         Flexibility and expressiveness
                                          3                      Do whatever you
  Easy to read



                                                                      want


                         2
                 Encourage/enforce
                     standards
  Hard to read




Makes you stick to conventions                Easy to do whatever you want
Choosing your tools
Flexibility verses Convention
Build Scripting Rule 1
    “A build script will tend to reflect the personality of
                        it’s developer”
Choosing your tools
Flexibility verses Convention
Build Scripting Rule 2
     “The more flexible a build script, the more likely it
             is to become unmaintainable”
Choosing your tools
Flexibility verses Convention
Flexibility is great for some jobs:
 Ad-hoc tasks
 Some deployment tasks
 “Out-of-the-box” stuff
Choosing your tools
Flexibility verses Convention
But too much flexibility is hard to maintain
Ant tips
Better Ant scripts
Consistent conventions
Declare your dependencies
Make it readable
Tidy up your mess
Avoid long scripts
Ant tips
Be consistent
Standardize target names
Document your public targets
Ant tips
Declare your dependencies
Use an Enterprise Repository Manager
Several tool choices:
 Maven Ant Tasks
 Ivy
Ant tips
 Using 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>
Ant tips
Make it readable
 Write a build script like your source code...
 Avoid long targets
 Avoid long build scripts
 Use descriptive target names
Ant tips
Tidy up your mess
Always define a ‘clean’ target.
Ant tips
Move to Maven ;-)
Maven tips
Better Maven scripts
Simple
Portable
Reproducible
Clean
Automated
Maven tips
Keep it simple
Use modules
Use an organization-level POM
Maven tips
Keep it portable
No hard-coding
Define sensible defaults for properties and profiles
Avoid resource filtering for production code
Maven tips
Keep it reproducible
Avoid external snapshots
Specify plugin versions
Use consistent environments
Maven tips
Consistent environments
Enforcing 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>
                                       Minimum Maven version
 	 <name>gameoflife</name>
 	 <prerequisites>
 	 	 <maven>2.2.1</maven>
 	 </prerequisites>
Maven tips
Consistent environments
Use 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
Maven tips
Enforcing consistency with the enforcer plugin
Maven version
JDK version
Snapshots
Plugin versions
OS
...
Maven tips
Enforce 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>                      Minimum Maven version
            <configuration>
              <rules>
                <requireMavenVersion>
                  <version>2.2.1</version>
                </requireMavenVersion>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>
Maven tips
Enforce the JDK version
All developers should be using the same JDKs
 Incompatible bytecode
 Different XML parsers
 Different Maven behaviour
Maven tips
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>                      Authorized JDK versions
            <configuration>
              <rules>
                <requireJavaVersion>
                  <version>[1.5.0,1.6.0)</version>
                </requireJavaVersion>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>
Maven tips
Specify your plugin versions
Undeclared version numbers are bad
 Inconsistent builds across different machines
 Non-repeatable builds
 Plugin changes can break the build
 Don’t use SNAPSHOT plugins either
Maven tips
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>               Plugin versions must be defined
            <configuration>
              <rules>
                <requirePluginVersions/>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>
Maven tips
Keep it clean
Keep tabs on your dependencies:
 What dependencies are you actually using?
 What dependencies do you really need?
Maven tips
Dependency list
What dependencies are you actually using?
 $ mvn dependency:list
 [INFO] Scanning for projects...        mvn dependency:list
 [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] ------------------------------------------------------------------------
Maven tips
Dependency tree
Where do they come from?
 $ mvn dependency:tree
 [INFO] Scanning for projects...       mvn dependency:tree
 [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] ------------------------------------------------------------------------
Maven tips
Dependencies in Eclipse
Eclipse has an equivalent screen
Maven tips
Dependency analyse
What dependencies do you really need?
 $ mvn dependency:analyze
 [INFO] Scanning for projects...     mvn dependency:analyse
 [INFO] Searching repository for plugin with prefix: 'dependency'.
 [INFO] ------------------------------------------------------------------------
 [INFO] Building babble-core
 [INFO]    task-segment: [dependency:analyze]
 [INFO] ------------------------------------------------------------------------
 [INFO] Preparing dependency:analyze
 ...                                                  Used but not declared
 [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
                                                       Declared but not used
 [INFO] ------------------------------------------------------------------------
Maven tips
Excluding dependencies
What if you don’t want a dependency?
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring</artifactId>
                                             Don’t include JMS
      <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>
Maven tips
  Standardizing versions
    Use dependencyManagement for consistency

<dependencyManagement>                       Parent pom
  <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>
        <dependencies>                                  Child pom
    </dependency>
          <dependency>
  </dependencies>
           !<groupId>mysql</groupId>
</dependencyManagement>
             <artifactId>mysql-connector-java</artifactId>
          </dependency>
        </dependencies>
Maven tips
Keep it automated
Plan your release strategy
Use a Repository Manager
Automatic snapshot deployments
Automated releases
Maven tips
Maven best practices for CI builds
Use batch mode (-B)
Always check or snapshot updates (-U)
Use a repository per project
Print test failures to stdout (-Dsurefire.useFile=false)
Maven tips
Know when to script it
Groovy or Ant scripting is easy in Maven
Call external scripts when appropriate
Maven tips
Know when to script it
It’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>
     ...
Maven tips
Know when to script it
It’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}"
      }
      ...
   }
 }
Java Power Tools Bootcamp
London - October 13-17 2010
Zen and-the-art-of-build-script-maintenance-skillsmatter

More Related Content

PDF
Implementing OpenID
David Recordon
 
PDF
Dave Folio
Dave Lilly
 
ZIP
FluidDB for Dummies
Nicholas Tollervey
 
PDF
30 Minute Expert1
Ben Wilkoff
 
PDF
FluidDB in a Nutshell
Nicholas Tollervey
 
PDF
Implementing OpenID
Uri Levanon
 
PDF
Egkekrimena sxedia comenius 2012
sfikasp
 
PDF
Using FluidDB with Django
Nicholas Tollervey
 
Implementing OpenID
David Recordon
 
Dave Folio
Dave Lilly
 
FluidDB for Dummies
Nicholas Tollervey
 
30 Minute Expert1
Ben Wilkoff
 
FluidDB in a Nutshell
Nicholas Tollervey
 
Implementing OpenID
Uri Levanon
 
Egkekrimena sxedia comenius 2012
sfikasp
 
Using FluidDB with Django
Nicholas Tollervey
 

Viewers also liked (20)

PDF
Ant_quick_guide
ducquoc_vn
 
PPTX
Jvm a brief introduction
Artem Shoobovych
 
PPT
Java Build Tools
­Avishek A
 
PDF
Architecting your Frontend
Ruben Teijeiro
 
PPTX
Gradle 2.Write once, builde everywhere
Strannik_2013
 
PDF
Angular.js
GDG Cali
 
PDF
Make Your Builds More Groovy
Paul King
 
PPTX
Apache maven 2 overview
Return on Intelligence
 
KEY
4장. Class Loader
김 한도
 
PPTX
Tutorial to develop build files using ANT
ravireddy76
 
PPTX
Apache maven 2 overview
Return on Intelligence
 
PPTX
Apache ant
koniik
 
PDF
Java Classloaders
Prateek Jain
 
PDF
Java Build Tool course in 2011
Ching Yi Chan
 
PPT
Apache Ant
hussulinux
 
ZIP
Automated Frontend Testing
Neil Crosby
 
PDF
Front-End Testing: Demystified
Seth McLaughlin
 
PPT
Apache Ant
Rajesh Kumar
 
KEY
Erlang vs. Java
Artan Cami
 
PDF
Manen Ant SVN
Sriskandarajah Suhothayan
 
Ant_quick_guide
ducquoc_vn
 
Jvm a brief introduction
Artem Shoobovych
 
Java Build Tools
­Avishek A
 
Architecting your Frontend
Ruben Teijeiro
 
Gradle 2.Write once, builde everywhere
Strannik_2013
 
Angular.js
GDG Cali
 
Make Your Builds More Groovy
Paul King
 
Apache maven 2 overview
Return on Intelligence
 
4장. Class Loader
김 한도
 
Tutorial to develop build files using ANT
ravireddy76
 
Apache maven 2 overview
Return on Intelligence
 
Apache ant
koniik
 
Java Classloaders
Prateek Jain
 
Java Build Tool course in 2011
Ching Yi Chan
 
Apache Ant
hussulinux
 
Automated Frontend Testing
Neil Crosby
 
Front-End Testing: Demystified
Seth McLaughlin
 
Apache Ant
Rajesh Kumar
 
Erlang vs. Java
Artan Cami
 
Ad

Similar to Zen and-the-art-of-build-script-maintenance-skillsmatter (20)

PDF
Zen and-the-art-of-build-script-maintenance
John Ferguson Smart Limited
 
PDF
ฝ่ายสวัสดิการ
ด.ช. แชมป์
 
PDF
The Future OS
Ed Parsons
 
PDF
Kiss the BRD Good-Bye
Patrick van Abbema, PMP, CBAP, CSP
 
KEY
CloudTunnel Atlanta Ruby Users Group October 2012
jmanuzak
 
PDF
Moodle 2.0 themes
Pieter van der Hijden
 
PDF
Diagonal paper
mrsdannikendall
 
PDF
Ed Burns @ FOWA 08
carsonsystems
 
PDF
Personas 2 0 (World Usability Day 2007)
Raphael De Robiano
 
PPTX
Srs
Nancy Munce
 
PPTX
Srs
Nancy Munce
 
PDF
Open Source Success: jQuery
jeresig
 
PDF
JecoGuides: how to in just 3 steps
Luca Francesco Garibaldo
 
PDF
Enhancing benefits from aquatic ecosystems: Nakambe sub-basin Case study
Water, food and livelihoods in River Basins: Basin Focal Projects
 
PDF
Alpha data sheet
CFN Services
 
PDF
The 21st Century Mapping Agency
Ed Parsons
 
PDF
Conversation Clusters: Grouping Conversation Through Human Computer Dialog
Tony Bergstrom
 
PDF
Designing learning spaces to meet the changing needs and expectations of stud...
Dan Munnerley
 
PDF
TPMC Portfolio Brochure July 2011
Emma Garrett
 
PDF
Matt copeland: a snapshot.
Matthew Copeland
 
Zen and-the-art-of-build-script-maintenance
John Ferguson Smart Limited
 
ฝ่ายสวัสดิการ
ด.ช. แชมป์
 
The Future OS
Ed Parsons
 
Kiss the BRD Good-Bye
Patrick van Abbema, PMP, CBAP, CSP
 
CloudTunnel Atlanta Ruby Users Group October 2012
jmanuzak
 
Moodle 2.0 themes
Pieter van der Hijden
 
Diagonal paper
mrsdannikendall
 
Ed Burns @ FOWA 08
carsonsystems
 
Personas 2 0 (World Usability Day 2007)
Raphael De Robiano
 
Open Source Success: jQuery
jeresig
 
JecoGuides: how to in just 3 steps
Luca Francesco Garibaldo
 
Enhancing benefits from aquatic ecosystems: Nakambe sub-basin Case study
Water, food and livelihoods in River Basins: Basin Focal Projects
 
Alpha data sheet
CFN Services
 
The 21st Century Mapping Agency
Ed Parsons
 
Conversation Clusters: Grouping Conversation Through Human Computer Dialog
Tony Bergstrom
 
Designing learning spaces to meet the changing needs and expectations of stud...
Dan Munnerley
 
TPMC Portfolio Brochure July 2011
Emma Garrett
 
Matt copeland: a snapshot.
Matthew Copeland
 
Ad

More from Skills Matter (20)

PDF
5 things cucumber is bad at by Richard Lawrence
Skills Matter
 
ODP
Patterns for slick database applications
Skills Matter
 
PDF
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Skills Matter
 
ODP
Oscar reiken jr on our success at manheim
Skills Matter
 
ODP
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Skills Matter
 
PDF
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Skills Matter
 
PDF
Cukeup nyc peter bell on getting started with cucumber.js
Skills Matter
 
PDF
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Skills Matter
 
ODP
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Skills Matter
 
ODP
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Skills Matter
 
PDF
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Skills Matter
 
PPTX
Dmitry mozorov on code quotations code as-data for f#
Skills Matter
 
PDF
A poet's guide_to_acceptance_testing
Skills Matter
 
PDF
Russ miles-cloudfoundry-deep-dive
Skills Matter
 
KEY
Serendipity-neo4j
Skills Matter
 
PDF
Simon Peyton Jones: Managing parallelism
Skills Matter
 
PDF
Plug 20110217
Skills Matter
 
PDF
Lug presentation
Skills Matter
 
PPT
I went to_a_communications_workshop_and_they_t
Skills Matter
 
PDF
Plug saiku
Skills Matter
 
5 things cucumber is bad at by Richard Lawrence
Skills Matter
 
Patterns for slick database applications
Skills Matter
 
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Skills Matter
 
Oscar reiken jr on our success at manheim
Skills Matter
 
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Skills Matter
 
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Skills Matter
 
Cukeup nyc peter bell on getting started with cucumber.js
Skills Matter
 
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Skills Matter
 
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Skills Matter
 
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Skills Matter
 
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Skills Matter
 
Dmitry mozorov on code quotations code as-data for f#
Skills Matter
 
A poet's guide_to_acceptance_testing
Skills Matter
 
Russ miles-cloudfoundry-deep-dive
Skills Matter
 
Serendipity-neo4j
Skills Matter
 
Simon Peyton Jones: Managing parallelism
Skills Matter
 
Plug 20110217
Skills Matter
 
Lug presentation
Skills Matter
 
I went to_a_communications_workshop_and_they_t
Skills Matter
 
Plug saiku
Skills Matter
 

Recently uploaded (20)

PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
Cloud-Migration-Best-Practices-A-Practical-Guide-to-AWS-Azure-and-Google-Clou...
Artjoker Software Development Company
 
PDF
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
PDF
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
codernjn73
 
PDF
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
A Day in the Life of Location Data - Turning Where into How.pdf
Precisely
 
PDF
REPORT: Heating appliances market in Poland 2024
SPIUG
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
PPTX
The-Ethical-Hackers-Imperative-Safeguarding-the-Digital-Frontier.pptx
sujalchauhan1305
 
PDF
How-Cloud-Computing-Impacts-Businesses-in-2025-and-Beyond.pdf
Artjoker Software Development Company
 
PDF
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Cloud-Migration-Best-Practices-A-Practical-Guide-to-AWS-Azure-and-Google-Clou...
Artjoker Software Development Company
 
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
codernjn73
 
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
A Day in the Life of Location Data - Turning Where into How.pdf
Precisely
 
REPORT: Heating appliances market in Poland 2024
SPIUG
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
The-Ethical-Hackers-Imperative-Safeguarding-the-Digital-Frontier.pptx
sujalchauhan1305
 
How-Cloud-Computing-Impacts-Businesses-in-2025-and-Beyond.pdf
Artjoker Software Development Company
 
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 

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

  • 3. Who is this guy, anyway? John Ferguson Smart Consultant, Trainer, Mentor, Author, Speaker Specialities: Java, Groovy/Grails Software Development Lifecycle Agile stuff (CI, TDD, BDD,...) Open Source
  • 4. Agenda What are we discussing today? What makes a good build script? Smelly build scripts Choosing your tools Maven tips Ant tips
  • 5. Introduction Quality build scripts - why bother Maintenance costs Learning curve Turn-over Portability Automation
  • 6. Build quality - quality builds What makes a good build script? Gold Standard Portable Reproducible Standard Maintainable
  • 7. Build quality - quality builds Gold Standard Reference build process Reference binaries
  • 8. Build quality - quality builds Portable Runs anywhere Runs on any OS No local dependencies Environment-specific configurations Specially-installed software or databases ...
  • 9. Build quality - quality builds Reproducible “Play it again, Sam”
  • 10. Build quality - quality builds Standard Knowing what to expect
  • 11. Build quality - quality builds Maintainable Think of the next dude
  • 12. Smelly builds So 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
  • 13. Paths .. 1/ URLs Smelly builds 9. c- gi lo 1 eb 00 Passwords /w :7 om ea .c /b me C: ac r. ve er ts es .> /t ".. :/ ger "ti tp rd= The hard coded build ht swo pas tt" sco e=" nam ser n u <sv /> M E }" S_HO JBOS env. = "$ { alue s" v Environment jbos dir. me=" variables y na pert <pro
  • 14. Smelly builds The hard coded build <target name="checkstyle"> Hard-coded directories <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>
  • 15. Smelly builds The hard coded build <target name="checkstyle"> Project-relative directory <property name=”reports.checkstyle.dir” <delete dir="./reports" quiet="true" /> value=”${basedir}/reports”/> <mkdir dir="./reports" /> DRY <checkstyle config="./docs/sun_checks.xml"> <target name="checkstyle"> <formatter type="xml" tofile="./reports/checkstyle.xml"/> <delete dir="${reports.checkstyle.dir}" quiet="true" /> <mkdir<fileset dir="./src" includes="**/*.java"/> dir="${reports.checkstyle.dir}" /> </checkstyle> <checkstyle config="./docs/sun_checks.xml"> <formatter type="xml" <style in="./reports/checkstyle.xml" tofile="${reports.checkstyle.dir}/checkstyle.xml"/> <fileset out="./reports/checkstyle.html" dir="./src" includes="**/*.java"/> style="checkstyle.xsl"/> </checkstyle> </target> <style in="${reports.checkstyle.dir}/checkstyle.xml" out="${reports.checkstyle.dir}/checkstyle.html" style="checkstyle.xsl"/> </target>
  • 16. Smelly builds The hard coded build <target name="war" > <war destfile="c:/tomcat/jakarta-tomcat-5.0.19/webapps/app.war" webxml="${src}/app.xml" basedir="${bin}" /> </target> Hard-coded directories
  • 17. Smelly builds The hard coded build <property name="wardir" location="c:/tomcat/jakarta-tomcat-5.0.19/webapps"/> <target name="war" > <war destfile="${wardir}" webxml="${src}/app.xml" basedir="${bin}" /> </target> Still hard-coded
  • 18. Smelly builds The hard coded build <svn username="scott" password="tiger"> <checkout url="http://subversion.acme.com/myapp/trunk" destPath="${subproject.dir}" /> </svn> Hard-coded username/password
  • 19. Smelly builds The hard coded build <property environment="env"/> <property name="dir.jboss" value="${env.JBOSS_HOME}"/> Environment variable
  • 20. Smelly builds The OS-specific build <exec command="grep "@" ${build.dir} | wc -l" outputproperty="token.count"/>
  • 21. Smelly builds The 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.254 PING %NonExist% -n 1 -w 100 2>NUL | FIND "TTL=" >NUL ... pause.cmd
  • 23. Smelly builds The Magic Machine build Directories App servers Databases Configuration files Environment variables Installed software or tools
  • 24. Smelly builds The Magic Machine build <proprerty weblogic.dir="/u01/app/bea/weblogic-9.1"/> Directories App servers Databases Configuration files Environment variables Installed software or tools
  • 25. Smelly builds The Oral Tradition build
  • 26. Smelly builds The Nested Build #! /bin/sh ANT_HOME=/u01/app/tools/ant-1.7.1 ... $ANT_HOME/ant $1 project/tools/ant.sh
  • 27. Smelly builds The Nested Build <target name="build-subproject"> <svn username="scott" password="tiger"> <checkout url="http://subversion.acme.com/someproject/trunk" destPath="${subproject.dir}" /> </svn> <ant dir="${subproject.dir}" target="build-all" /> </target> build.xml
  • 28. Smelly builds The Messy Dependencies build JAR files in the SCM Unversioned JAR files Unclear dependencies
  • 29. Smelly builds The DYI build “Not invented here” DYI dependencies DYI deployments DYI Maven releases ...
  • 30. Smelly builds The 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>
  • 32. Choosing your tools Flexibility verses Convention What’s better: flexibility or standards? It depends what you’re doing...
  • 33. Choosing your tools Encourage/enforce Standards and Conventions Support standards standards 3 Easy to read 2 Make up your own standards No standards Hard to read Ad-hoc scripting Standards and Conventions
  • 34. Choosing your tools Flexibility and expressiveness 3 Do whatever you Easy to read want 2 Encourage/enforce standards Hard to read Makes you stick to conventions Easy to do whatever you want
  • 35. Choosing your tools Flexibility verses Convention Build Scripting Rule 1 “A build script will tend to reflect the personality of it’s developer”
  • 36. Choosing your tools Flexibility verses Convention Build Scripting Rule 2 “The more flexible a build script, the more likely it is to become unmaintainable”
  • 37. Choosing your tools Flexibility verses Convention Flexibility is great for some jobs: Ad-hoc tasks Some deployment tasks “Out-of-the-box” stuff
  • 38. Choosing your tools Flexibility verses Convention But too much flexibility is hard to maintain
  • 39. Ant tips Better Ant scripts Consistent conventions Declare your dependencies Make it readable Tidy up your mess Avoid long scripts
  • 40. Ant tips Be consistent Standardize target names Document your public targets
  • 41. Ant tips Declare your dependencies Use an Enterprise Repository Manager Several tool choices: Maven Ant Tasks Ivy
  • 42. Ant tips Using 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>
  • 43. Ant tips Make it readable Write a build script like your source code... Avoid long targets Avoid long build scripts Use descriptive target names
  • 44. Ant tips Tidy up your mess Always define a ‘clean’ target.
  • 45. Ant tips Move to Maven ;-)
  • 46. Maven tips Better Maven scripts Simple Portable Reproducible Clean Automated
  • 47. Maven tips Keep it simple Use modules Use an organization-level POM
  • 48. Maven tips Keep it portable No hard-coding Define sensible defaults for properties and profiles Avoid resource filtering for production code
  • 49. Maven tips Keep it reproducible Avoid external snapshots Specify plugin versions Use consistent environments
  • 50. Maven tips Consistent environments Enforcing 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> Minimum Maven version <name>gameoflife</name> <prerequisites> <maven>2.2.1</maven> </prerequisites>
  • 51. Maven tips Consistent environments Use 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
  • 52. Maven tips Enforcing consistency with the enforcer plugin Maven version JDK version Snapshots Plugin versions OS ...
  • 53. Maven tips Enforce 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> Minimum Maven version <configuration> <rules> <requireMavenVersion> <version>2.2.1</version> </requireMavenVersion> </rules> </configuration> </execution> </executions> </plugin>
  • 54. Maven tips Enforce the JDK version All developers should be using the same JDKs Incompatible bytecode Different XML parsers Different Maven behaviour
  • 55. Maven tips 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> Authorized JDK versions <configuration> <rules> <requireJavaVersion> <version>[1.5.0,1.6.0)</version> </requireJavaVersion> </rules> </configuration> </execution> </executions> </plugin>
  • 56. Maven tips Specify your plugin versions Undeclared version numbers are bad Inconsistent builds across different machines Non-repeatable builds Plugin changes can break the build Don’t use SNAPSHOT plugins either
  • 57. Maven tips 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> Plugin versions must be defined <configuration> <rules> <requirePluginVersions/> </rules> </configuration> </execution> </executions> </plugin>
  • 58. Maven tips Keep it clean Keep tabs on your dependencies: What dependencies are you actually using? What dependencies do you really need?
  • 59. Maven tips Dependency list What dependencies are you actually using? $ mvn dependency:list [INFO] Scanning for projects... mvn dependency:list [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] ------------------------------------------------------------------------
  • 60. Maven tips Dependency tree Where do they come from? $ mvn dependency:tree [INFO] Scanning for projects... mvn dependency:tree [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] ------------------------------------------------------------------------
  • 61. Maven tips Dependencies in Eclipse Eclipse has an equivalent screen
  • 62. Maven tips Dependency analyse What dependencies do you really need? $ mvn dependency:analyze [INFO] Scanning for projects... mvn dependency:analyse [INFO] Searching repository for plugin with prefix: 'dependency'. [INFO] ------------------------------------------------------------------------ [INFO] Building babble-core [INFO] task-segment: [dependency:analyze] [INFO] ------------------------------------------------------------------------ [INFO] Preparing dependency:analyze ... Used but not declared [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 Declared but not used [INFO] ------------------------------------------------------------------------
  • 63. Maven tips Excluding dependencies What if you don’t want a dependency? <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> Don’t include JMS <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>
  • 64. Maven tips Standardizing versions Use dependencyManagement for consistency <dependencyManagement> Parent pom <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> <dependencies> Child pom </dependency> <dependency> </dependencies> !<groupId>mysql</groupId> </dependencyManagement> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies>
  • 65. Maven tips Keep it automated Plan your release strategy Use a Repository Manager Automatic snapshot deployments Automated releases
  • 66. Maven tips Maven best practices for CI builds Use batch mode (-B) Always check or snapshot updates (-U) Use a repository per project Print test failures to stdout (-Dsurefire.useFile=false)
  • 67. Maven tips Know when to script it Groovy or Ant scripting is easy in Maven Call external scripts when appropriate
  • 68. Maven tips Know when to script it It’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> ...
  • 69. Maven tips Know when to script it It’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}" } ... } }
  • 70. Java Power Tools Bootcamp London - October 13-17 2010