8

¿Cómo puedo configurar compilaciones de aplicaciones Play y (personalizadas) Reproducir módulos en un sistema CI para que cuando la compilación de un módulo sea buena, la compilación instale los artefactos del módulo en un local repositorio y/o los despliega en un repositorio remoto, y las aplicaciones usan los artefactos en ese repositorio?Cómo usar Jugar con módulos personalizados y integración continua

La solución también debería funcionar bien para un desarrollador que esté trabajando localmente.

Estoy usando Jenkins, y corriendo en problemas de cualquier forma que trate de hacer esto.

Antes de exponer todos los problemas que he encontrado, esperaré, porque es laborioso, y tal vez alguien más pueda ofrecer cómo lo hacen.

Respuesta

6

Tengo una configuración en jenkins que funciona bien desde el desarrollo hasta la producción.

En primer lugar aquí es la configuración en el dependencies.yml para el repositorio módulo personalizado

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 este desarrolladores y la búsqueda Jenkins en primer lugar en el mismo repositorio para ver si un módulo está presente y si no, tiene que el repositorio de nexus para descargar el artefacto.

para construir mi módulo en Jenkins utilizo un script sh encargo como éste

#!/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 este script usted es capaz de empujar a su módulo de nexo en cada Jenkins construir. Esto no es realmente lo que hago. Yo uso el módulo de lanzamiento de jenkins para impulsarlo solo cuando construyo una versión. Para una liberación Tengo un script especial

#!/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" 

Este script poner una etiqueta en nuestro repositorio SVN, empuje el módulo de Nexus y actualizar dependencies.yml archivo.

Con esto jenkins puede construir una aplicación que depende de una versión local del módulo mientras no se lance y luego puede construir la aplicación descargando el módulo artifcat del repositorio nexus. Es lo mismo para los desarrolladores

+1

creo que esta técnica se va a hacer una diferencia en mi programa de instalación; Simplemente no he tenido tiempo de probarlo, y es por eso que aún no lo he aceptado. Pregunta de seguimiento: la configuración de repo localModules no parece que coincida con una configuración típica de Jenkins, donde los espacios de trabajo de construcción no están en directorios adyacentes. Estoy un poco confundido acerca de cómo las compilaciones de Jenkins recuperan dependencias para versiones dev (en lugar de versiones). – Ladlestein

+1

En jenkins, tengo solo un espacio de trabajo y todos mis directorios de módulos son adyacentes, ya que está en desarrollo. Si no, tienes que publicar tu artefacto en el nexo cada vez que construyes un módulo, con algún tipo de versión de instantáneas que será más tedioso de configurar y usar –

2

¡Escribí este pequeño juego! ¡Comando que básicamente hace lo mismo, pero se integra muy bien en 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 '~ ' 
Cuestiones relacionadas