docker-build.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #!/usr/bin/env python3
  2. from os import environ, makedirs, chdir, listdir, rename
  3. from os.path import isdir, exists
  4. from subprocess import call, check_call
  5. from shutil import *
  6. from multiprocessing import cpu_count
  7. from datetime import datetime
  8. from sys import stdout
  9. site = environ['GLUON_SITE']
  10. release = environ['GLUON_RELEASE']
  11. branch = environ['GLUON_BRANCH']
  12. broken = environ['GLUON_BROKEN']
  13. home = '/usr/src/build'
  14. gluondir = '%s/gluon' % home
  15. outdir = '%s/output/%s' % (home, release)
  16. logdir = '%s/log' % outdir
  17. siteconf = '/usr/src/site.conf'
  18. sitemk = '/usr/src/site.mk'
  19. i18ndir = '/usr/src/i18n'
  20. factorydir = '%s/images/factory' % outdir
  21. sysupdir = '%s/images/sysupgrade' % outdir
  22. modulesdir = '%s/modules' % outdir
  23. makedirs(factorydir)
  24. makedirs(sysupdir)
  25. makedirs(modulesdir)
  26. makedirs(logdir)
  27. start = datetime.now()
  28. def format_duration(d):
  29. s = d.total_seconds()
  30. return '%.2dh%.2dm%06.3fs' % (s//3600, (s//60)%60, s%60)
  31. # Clone Gluon
  32. if isdir(gluondir):
  33. rmtree(gluondir)
  34. print('Cloning Gluon... ', end=''); stdout.flush()
  35. with open('%s/git.log' % logdir, 'w') as log:
  36. check_call('git clone https://github.com/freifunk-gluon/gluon.git %s -b "%s"' % (gluondir, environ['GLUON_TAG']), stdout=log, stderr=log, shell=True)
  37. print('OK'); stdout.flush()
  38. # Add site configuration
  39. sitedir = '%s/site' % gluondir
  40. makedirs(sitedir)
  41. copy(siteconf, sitedir)
  42. copy(sitemk, sitedir)
  43. copytree(i18ndir, '%s/i18n' % sitedir)
  44. # Prepare
  45. chdir(gluondir)
  46. print('Updating other repositories... ', end=''); stdout.flush()
  47. with open('%s/update.log' % logdir, 'w') as log:
  48. check_call('make update V=s', stdout=log, stderr=log, shell=True)
  49. print('OK'); stdout.flush()
  50. # Choose targets to build
  51. if 'GLUON_TARGETS' in environ:
  52. targets = environ['GLUON_TARGETS'].split()
  53. else:
  54. targets = [f for f in listdir('targets') if isdir('targets/%s' % f)]
  55. # Build
  56. for target in targets:
  57. print('You can copy the log file from the container using: docker cp %s:%s/%s_stderr.log <destination>'% (environ['HOSTNAME'], logdir, target)); stdout.flush()
  58. print('Building for target %s... ' % target, end=''); stdout.flush()
  59. arch, variant = target.split('-')
  60. target_start = datetime.now()
  61. with open('%s/%s_stdout.log' % (logdir, target), 'w') as logout, open('%s/%s_stderr.log' % (logdir, target), 'w') as logerr:
  62. rc = call('make -j %s GLUON_BRANCH=%s BROKEN=%s GLUON_TARGET=%s V=s' % (cpu_count()+1, branch, broken, target), stdout=logout, stderr=logerr, shell=True)
  63. duration = format_duration(datetime.now() - target_start)
  64. if rc == 0:
  65. print('OK in', duration)
  66. # Create manifest
  67. print('Creating manifest... ', end=''); stdout.flush()
  68. with open('%s/%s_manifest.log' % (logdir, target), 'w') as log:
  69. rc = call('make manifest GLUON_BRANCH=%s BROKEN=%s GLUON_TARGET=%s V=s' % (branch, broken, target), stdout=log, stderr=log, shell=True)
  70. if rc == 0:
  71. rename('output/images/sysupgrade/%s.manifest' % branch, 'output/images/sysupgrade/%s.%s.manifest' % (target, branch))
  72. print('OK')
  73. else:
  74. print('FAILED')
  75. stdout.flush()
  76. # Move images to output
  77. for f in listdir('output/images/factory'):
  78. rename('output/images/factory/%s' % f, '%s/%s' % (factorydir, f))
  79. for f in listdir('output/images/sysupgrade'):
  80. rename('output/images/sysupgrade/%s' % f, '%s/%s' % (sysupdir, f))
  81. # Move modules to output
  82. # Since lede modules are optional for some targets
  83. modulesbuilddir = 'output/packages/gluon-%s-%s/%s/%s' % (site, release, arch, variant)
  84. if exists(modulesbuilddir):
  85. try:
  86. makedirs('%s/%s' % (modulesdir, arch))
  87. except FileExistsError:
  88. pass
  89. variantdir = '%s/%s/%s' % (modulesdir, arch, variant)
  90. rename('output/packages/gluon-%s-%s/%s/%s' % (site, release, arch, variant), variantdir)
  91. # Checksum modules
  92. print('Creating SHA512 sums for modules... ', end=''); stdout.flush()
  93. chdir(variantdir)
  94. check_call('sha512sum * > sha512sum.txt', shell=True)
  95. chdir(gluondir)
  96. else:
  97. print('No modules found for target %s....OK' % target)
  98. else:
  99. print('FAILED after', duration)
  100. # Clean up
  101. chdir(gluondir)
  102. print('Cleaning up...', end=''); stdout.flush()
  103. with open('%s/%s_cleanup.log' % (logdir, target), 'w') as log:
  104. print('Cleaning up...', end=''); stdout.flush()
  105. with open('%s/%s_cleanup.log' % (logdir, target), 'w') as log:
  106. # rc = call('make dirclean V=s', stdout=log, stderr=log, shell=True) # clean all
  107. rc = call('make clean GLUON_TARGET=%s V=s' % (target), stdout=log, stderr=log, shell=True) # clean target specific
  108. if rc == 0:
  109. print('OK')
  110. else:
  111. print('FAILED')
  112. stdout.flush()
  113. print('Creating SHA512 sums for images... ', end=''); stdout.flush()
  114. for d in (factorydir, sysupdir):
  115. chdir(d)
  116. check_call('sha512sum * > sha512sum.txt', shell=True)
  117. print('OK')
  118. print('''
  119. BUILD FINISHED in %s
  120. You can copy the resulting images from the container using:
  121. docker cp %s:/usr/src/build/output <destination>
  122. '''% (format_duration(datetime.now() - start), environ['HOSTNAME']))