8

Come posso creare build di app Play e moduli di riproduzione personalizzati in un sistema di elementi di configurazione in modo che quando la build di un modulo è buona, la build installa gli elementi del modulo in un locale repository e/o li distribuisce a un repository remoto e le app utilizzano le risorse in quel repository?Come utilizzare Riproduci con moduli personalizzati e integrazione continua

La soluzione dovrebbe funzionare anche per uno sviluppatore che lavora localmente.

Sto usando Jenkins e mi trovo nei guai in qualunque modo provo a farlo.

Prima di approfondire tutti i problemi che ho riscontrato, aspetterò, perché è laborioso, e forse qualcun altro può offrire come lo fanno.

risposta

6

Ho una configurazione in jenkins che funziona bene da dev in produzione.

Prima qui è la configurazione nel dependencies.yml per il repository modulo personalizzato

repositories: 
    - modules: 
     type: chain 
     using: 
      - localModules: 
       type: local 
       descriptor: "${application.path}/../[module]/conf/dependencies.yml" 
       artifact: "${application.path}/../[module]" 
      - repoModules: 
       type: http 
       artifact: "http://mynexus/nexus/content/repositories/releases/com/myorg/[module]/[revision]/[module]-[revision].zip" 
     contains: 
      - com.myorg -> * 

Con questo gli sviluppatori e la ricerca Jenkins in primo luogo nello stesso repository per vedere se un modulo è presente e se non, avuto modo di il repository nexus per scaricare l'artefatto.

per costruire il mio modulo Jenkins Io uso uno script sh personalizzato come questo

#!/bin/bash 
APPLICATION="myModule" 
PLAY_PATH="/usr/local/play" 
set –xe 

$PLAY_PATH/play deps --sync 
$PLAY_PATH/play build-module --require 1.2.3 
VERSION=`grep self conf/dependencies.yml | sed "s/.*$APPLICATION //"` 
echo "Sending $APPLICATION-$VERSION.zip to nexus repository" 
curl --request POST --user user:passwd http://mynexus/nexus/content/repositories/releases/com/myorg/$APPLICATION/$VERSION/$APPLICATION-$VERSION.zip -F "[email protected]/$APPLICATION-$VERSION.zip" --verbose 

Con questo script si è in grado di spingere il modulo per Nexus su ogni Jenkins costruire. Questo non è esattamente quello che faccio. Io uso il modulo di rilascio di jenkins per spingerlo solo quando creo un rilascio. Per un rilascio Ho uno script speciale

#!/bin/bash 
APPLICATION="myModule" 
PLAY_PATH="/usr/local/play" 
set –xe 

if [ -z "$RELEASE_VERSION" ] 
then 
    echo "Parameter RELEASE_VERSION is mandatory" 
    exit 1 
fi 
if [ -z "$DEVELOPMENT_VERSION" ] 
then 
    echo "Parameter DEVELOPMENT_VERSION is mandatory" 
    exit 1 
fi 
echo "Release version : $RELEASE_VERSION" 
echo "Development version : $DEVELOPMENT_VERSION" 
VERSION=`grep self conf/dependencies.yml | sed "s/.*$APPLICATION //"` 
if [ "$RELEASE_VERSION" != "$VERSION" ] 
then 
    echo "Release version $RELEASE_VERSION and play version $VERSION in dependencies.yml does not match : release failed" 
    exit 1 
fi 
REVISION=`svnversion .` 
echo "Tag svn repository in revision $REVISION with version $VERSION" 
svn copy -m "Version $VERSION" -r $REVISION http://mysvn/myRepo/$APPLICATION/trunk/ http://mysvn/myRepo/$APPLICATION/tags/$VERSION 
echo "svn tag applied" 
echo "Sending $APPLICATION-$VERSION.zip to nexus repository" 
curl --request POST --user user:passwd http://mynexus/nexus/content/repositories/releases/com/myorg/$APPLICATION/$VERSION/$APPLICATION-$VERSION.zip -F "[email protected]/$APPLICATION-$VERSION.zip" --verbose 
echo "$APPLICATION-$VERSION.zip sent to nexus repository" 
echo "Update module to version $DEVELOPMENT_VERSION" 
sed -i "s/self\(.*\)$VERSION/self\1$DEVELOPMENT_VERSION/g" conf/dependencies.yml 
svn commit -m "Version $DEVELOPMENT_VERSION" conf/dependencies.yml 
svn update 
echo "Version $DEVELOPMENT_VERSION créée" 

Questo script messo un tag nel nostro repository svn, spingere il modulo a Nexus e aggiornare dependencies.yml file.

Con questo jenkins è possibile creare un'app che dipende da una versione locale del modulo mentre non è rilasciata e successivamente è possibile creare l'app scaricando il modulo artifcat dal repository nexus. È la stessa cosa per gli sviluppatori

+1

penso che questa tecnica sta andando a fare la differenza nel mio setup; Non ho ancora avuto il tempo di provarlo, ed è per questo che non l'ho ancora accettato. Domanda di follow-up: la configurazione del repository di localModules non sembra corrispondere a una tipica configurazione di Jenkins, in cui le aree di lavoro di generazione non sono nelle directory adiacenti. Sono un po 'confuso da dove le tue build di Jenkins recuperano le dipendenze per le versioni dev (in opposizione al rilascio). – Ladlestein

+1

In jenkins ho solo uno spazio di lavoro e tutte le directory dei miei moduli sono adiacenti così come lo sono in dev. In caso contrario, devi pubblicare il tuo artefatto in nexus ogni volta che crei un modulo, con una sorta di versione di istantanee che sarà più noiosa da configurare e utilizzare –

2

Ho scritto questo giochino! Comanda che fondamentalmente fa la stessa cosa, ma si integra piacevolmente in Play!

http://www.playframework.org/community/snippets/25

from play.utils import * 
from poster.encode import multipart_encode 
from poster.streaminghttp import register_openers 
import urllib 
import urllib2 
import yaml 

COMMANDS = ['nexus-commit',] 

HELP = { 
    'nexus-commit': 'push built module to nexus' 
} 

def execute(**kargs): 
    app = kargs.get("app") 
    args = kargs.get("args") 
    play_env = kargs.get("env") 

    print '~ ' 
    print '~ Commiting to nexus server' 
    print '~ ' 

    app.check() 
    nexus = app.readConf('nexus.server.url') 
    user = app.readConf('nexus.server.user') 
    password = app.readConf('nexus.server.password') 

    if nexus: 
     print '~ Found nexus repository : %s' % nexus 
    else: 
     print '~ No nexus server configured' 
     print '~ Set up the following on your application.conf:' 
     print '~ nexus.server.url' 
     print '~ nexus.server.user' 
     print '~ nexus.server.password' 
     sys.exit(0) 

    #Getting module version from dependencies file 
    deps_file = os.path.join(app.path, 'conf', 'dependencies.yml') 
    if os.path.exists(deps_file): 
     f = open(deps_file) 
     deps = yaml.load(f.read()) 
     #Is this a Play~ module? 
     if "self" in deps: 
      d = deps["self"].split(" ") 
      module_version = d.pop() 
      app_name = d.pop() 
     else: 
      app_name = app.name() 
      print '~ This is not a Play module' 
      module_version = app.readConf('application.version') 
      if not module_version: 
       print '~ ' 
       print '~ No application.version found in application.conf file' 
       print '~ ' 
       module_version = raw_input('~ Provide version number to be pushed to Nexus:') 
     f.close 

    if module_version: 
     print '~ Module version : %s' % module_version 
     print '~ ' 
    else: 
     print '~ No module version configured.' 
     print '~ Configure your dependencies file properly' 
     sys.exit(0) 

    dist_dir = os.path.join(app.path, 'dist') 

    #Only interested on .zip files 
    for root, dirs, files in os.walk(dist_dir): 
     files = [ fi for fi in files if fi.endswith(".zip") ] 

    #Loop over all found files 
    if len(files) >0: 
     for file in files: 
      if "-a" in args: 
       #We won't ask the user if he wants to commit 
       resp = "Y" 
      else: 
       resp = raw_input('~ Do you want to post %s to nexus? (Y/N) ' % file) 
      if resp == 'Y': 
       url = '%s/%s/%s-SNAPSHOT/%s-%s-SNAPSHOT.zip' % (nexus, app_name, module_version, app_name, module_version) 
       print '~ ' 
       print '~ Sending %s to %s' % (file, url) 

       try: 
        data = open(os.path.join(dist_dir, file), 'rb') 
       except: 
        print '~ Error: could not open file %s for reading' % file 
        continue 

       openers = register_openers() 
       #post data to Nexus using configured credentials 
       passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 
       passman.add_password(None, url, user, password) 
       authhandler = urllib2.HTTPBasicAuthHandler(passman) 
       openers.add_handler(authhandler) 
       openers.add_handler(urllib2.HTTPHandler(debuglevel=1)) 
       datagen, headers = multipart_encode({"file": data}) 
       request = urllib2.Request(url, datagen, headers) 

       try: 
        print urllib2.urlopen(request).read() 
        print '~ File correctly sent' 
       except urllib2.HTTPError, err: 
        print '~ Error: Nexus replied with -- %s' % err 

      else: 
       print '~ ' 
       print '~ Skiping %s' % file 
    else: 
     print '~ ' 
     print '~ No module build found.' 
     print '~ Try "play build-module" command first' 
     print '~ ' 
Problemi correlati