You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BuildHelpers.py 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #coding=UTF-8
  2. ## Collection of helpers for Build scripts ##
  3. import sys, argparse, subprocess, platform
  4. from xml.etree import ElementTree
  5. from os.path import join, isdir, isfile, basename, exists
  6. from os import listdir, makedirs
  7. from shutil import copy, rmtree
  8. from glob import glob
  9. # Directory where the resulting war files are stored
  10. resultPath = join("result", "demos")
  11. if not exists(resultPath):
  12. makedirs(resultPath)
  13. elif not isdir(resultPath):
  14. print("Result path is not a directory.")
  15. sys.exit(1)
  16. args = None
  17. # Default argument parser
  18. parser = argparse.ArgumentParser(description="Automated staging validation")
  19. group = parser.add_mutually_exclusive_group(required=True)
  20. group.add_argument("--version", help="Vaadin version to use")
  21. parser.add_argument("--maven", help="Additional maven command line parameters", default=None)
  22. parser.add_argument("--fwRepo", help="Framework staging repository URL", default=None)
  23. parser.add_argument("--pluginRepo", help="Maven plugin repository URL", default=None)
  24. # Parse command line arguments <version>
  25. def parseArgs():
  26. # If no args, give help
  27. if len(sys.argv) == 1:
  28. args = parser.parse_args(["-h"])
  29. else:
  30. args = parser.parse_args()
  31. return args
  32. # Function for determining the path for an executable
  33. def getCommand(command):
  34. # This method uses .split("\n")[0] which basically chooses the first result where/which returns.
  35. # Fixes the case with multiple maven installations available on PATH
  36. if platform.system() == "Windows":
  37. try:
  38. return subprocess.check_output(["where", "%s.cmd" % (command)], universal_newlines=True).split("\n")[0]
  39. except:
  40. try:
  41. return subprocess.check_output(["where", "%s.bat" % (command)], universal_newlines=True).split("\n")[0]
  42. except:
  43. print("Unable to locate command %s with where. Is it in your PATH?" % (command))
  44. else:
  45. try:
  46. return subprocess.check_output(["which", command], universal_newlines=True).split("\n")[0]
  47. except:
  48. print("Unable to locate command %s with which. Is it in your PATH?" % (command))
  49. return None
  50. mavenCmd = getCommand("mvn")
  51. dockerCmd = getCommand("docker")
  52. # Get command line arguments. Parses arguments if needed.
  53. def getArgs():
  54. global args
  55. if args is None:
  56. args = parseArgs()
  57. return args
  58. # Maven Package and Validation
  59. def mavenValidate(artifactId, mvnCmd = mavenCmd, logFile = sys.stdout, version = None, mavenParams = None):
  60. if version is None:
  61. version = getArgs().version
  62. if mavenParams is None:
  63. mavenParams = getArgs().maven
  64. print("Do maven clean package validate")
  65. cmd = [mvnCmd]
  66. cmd.append("-Dvaadin.version=%s" % (version))
  67. # Enforcer does not always seem to take vaadin.version into account, skip until this can be resolved
  68. cmd.append("-Denforcer.skip=true")
  69. if mavenParams is not None:
  70. cmd.extend(mavenParams.strip('"').split(" "))
  71. cmd.extend(["clean", "package", "validate"])
  72. print("executing: %s" % (" ".join(cmd)))
  73. subprocess.check_call(cmd, cwd=join(resultPath, artifactId), stdout=logFile)
  74. # Collect .war files to given folder with given naming
  75. def copyWarFiles(artifactId, resultDir = resultPath, name = None):
  76. if name is None:
  77. name = artifactId
  78. copiedWars = []
  79. warFiles = glob(join(resultDir, artifactId, "target", "*.war"))
  80. warFiles.extend(glob(join(resultDir, artifactId, "*", "target", "*.war")))
  81. for warFile in warFiles:
  82. if len(warFiles) == 1:
  83. deployName = "%s.war" % (name)
  84. else:
  85. deployName = "%s-%d.war" % (name, warFiles.index(warFile))
  86. print("Copying .war file %s as %s to result folder" % (basename(warFile), deployName))
  87. copy(warFile, join(resultDir, deployName))
  88. copiedWars.append(join(resultDir, deployName))
  89. return copiedWars
  90. # Generates and modifies a maven pom file
  91. def generateArchetype(archetype, artifactId, repo, logFile, group="testpkg", archetypeGroup="com.vaadin"):
  92. # Generate the required command line for archetype generation
  93. args = getArgs()
  94. print("Parameters for archetype %s:" % (archetype))
  95. print("using version %s" % (args.version))
  96. cmd = [mavenCmd, "archetype:generate"]
  97. cmd.append("-DarchetypeGroupId=%s" % (archetypeGroup))
  98. cmd.append("-DarchetypeArtifactId=%s" % (archetype))
  99. cmd.append("-DarchetypeVersion=%s" % (args.version))
  100. if repo is not None:
  101. cmd.append("-DarchetypeRepository=%s" % repo)
  102. print("using repository %s" % (repo))
  103. else:
  104. print("using no repository")
  105. cmd.append("-DgroupId=%s" % (group))
  106. cmd.append("-DartifactId=%s" % (artifactId))
  107. cmd.append("-Dversion=1.0-SNAPSHOT")
  108. cmd.append("-DinteractiveMode=false")
  109. if hasattr(args, "maven") and args.maven is not None:
  110. cmd.extend(args.maven.strip('"').split(" "))
  111. # Generate pom.xml
  112. print("Generating archetype %s" % (archetype))
  113. subprocess.check_call(cmd, cwd=resultPath, stdout=logFile)
  114. # Add a repository of repoType to given repoNode with id and URL
  115. def addRepo(repoNode, repoType, id, url):
  116. newRepo = ElementTree.SubElement(repoNode, repoType)
  117. idElem = ElementTree.SubElement(newRepo, "id")
  118. idElem.text = id
  119. urlElem = ElementTree.SubElement(newRepo, "url")
  120. urlElem.text = url
  121. # Get a logfile for given artifact
  122. def getLogFile(artifact, resultDir = resultPath):
  123. return open(join(resultDir, "%s.log" % (artifact)), 'w')
  124. def removeDir(subdir):
  125. if '..' in subdir or '/' in subdir:
  126. # Dangerous relative paths.
  127. return
  128. rmtree(join(resultPath, subdir))
  129. def dockerWrap(imageVersion, imageName = "demo-validation"):
  130. dockerFileContent = """FROM jtomass/alpine-jre-bash:latest
  131. LABEL maintainer="FrameworkTeam"
  132. COPY ./*.war /var/lib/jetty/webapps/
  133. USER root
  134. RUN mkdir /opt
  135. RUN chown -R jetty:jetty /opt
  136. COPY ./index-generate.sh /opt/
  137. RUN chmod +x /opt/index-generate.sh
  138. USER jetty
  139. RUN /opt/index-generate.sh
  140. RUN mkdir -p /var/lib/jetty/webapps/root && \
  141. cp /opt/index.html /var/lib/jetty/webapps/root && \
  142. chmod 644 /var/lib/jetty/webapps/root/index.html
  143. EXPOSE 8080
  144. """
  145. indexGenerateScript = """#!/bin/ash
  146. wars="/var/lib/jetty/webapps"
  147. OUTPUT="/opt/index.html"
  148. echo "<UL>" > $OUTPUT
  149. cd $wars
  150. for war in `ls -1 *.war`; do
  151. nowar=`echo "$war" | sed -e 's/\(^.*\)\(.war$\)/\\1/'`
  152. echo "<LI><a href=\"/$nowar/\">$nowar</a></LI>" >> $OUTPUT
  153. done
  154. echo "</UL>" >> $OUTPUT
  155. """
  156. with open(join(resultPath, "Dockerfile"), "w") as dockerFile:
  157. dockerFile.write(dockerFileContent)
  158. with open(join(resultPath, "index-generate.sh"), "w") as indexScript:
  159. indexScript.write(indexGenerateScript)
  160. # build image
  161. cmd = [dockerCmd, "build", "-t", "%s:%s" % (imageName, imageVersion), resultPath]
  162. subprocess.check_call(cmd)
  163. # save to tgz
  164. cmd = [dockerCmd, "save", imageName]
  165. dockerSave = subprocess.Popen(cmd, stdout=subprocess.PIPE)
  166. subprocess.check_call(["gzip"], stdin=dockerSave.stdout, stdout=open(join(resultPath, "%s-%s.tgz" % (imageName, imageVersion)), "w"))
  167. dockerSave.wait()
  168. # delete from docker
  169. cmd = [dockerCmd, "rmi", "%s:%s" % (imageName, imageVersion)]
  170. subprocess.check_call(cmd)