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.

275 lines
8.0KB

  1. import sys
  2. import os
  3. import glob
  4. import json
  5. import time
  6. import re
  7. import tempfile
  8. import random
  9. import common
  10. import update_modulargrid
  11. import update_cache
  12. TOOLCHAIN_DIR = "../toolchain-v2"
  13. PACKAGES_DIR = "../packages"
  14. MANIFESTS_DIR = "manifests"
  15. RACK_SYSTEM_DIR = "../Rack2"
  16. RACK_USER_DIR = "$HOME/.Rack2"
  17. SCREENSHOTS_DIR = os.path.join(RACK_USER_DIR, "screenshots")
  18. PLUGIN_DIR = os.path.join(RACK_USER_DIR, "plugins-lin-x64")
  19. FILES_DIR = "../files/packages"
  20. BUILD_MAC_ARM64_ONLY = False
  21. def package_exists(slug, version, os_, cpu):
  22. if os.path.isfile(os.path.join(PACKAGES_DIR, f"{slug}-{version}-{os_}-{cpu}.vcvplugin")):
  23. return True
  24. if cpu == 'x64':
  25. if os.path.isfile(os.path.join(PACKAGES_DIR, f"{slug}-{version}-{os_}.vcvplugin")):
  26. return True
  27. return False
  28. # Get missing Mac ARM64 slugs
  29. def print_missing_mac_arm64():
  30. emails = set()
  31. for manifest_path in glob.glob("manifests/*.json"):
  32. with open(manifest_path, "r") as f:
  33. manifest = json.load(f)
  34. slug = manifest['slug']
  35. version = manifest['version']
  36. author = manifest['author']
  37. license = manifest.get('license', "")
  38. email = manifest.get('authorEmail', "")
  39. if not package_exists(slug, version, 'mac', 'x64'):
  40. continue
  41. if package_exists(slug, version, 'mac', 'arm64'):
  42. continue
  43. print(f"{slug} {version}\t\t{email}\t\t{license}")
  44. # print_missing_mac_arm64()
  45. # exit(0)
  46. # Update git before continuing
  47. if not BUILD_MAC_ARM64_ONLY:
  48. common.system("git pull")
  49. common.system("git submodule sync --recursive --quiet")
  50. common.system("git submodule update --init --recursive")
  51. plugin_paths = sys.argv[1:]
  52. # Default to all repos, so all out-of-date repos are built
  53. if not plugin_paths:
  54. plugin_paths = glob.glob("repos/*")
  55. # Randomize repo order
  56. plugin_paths = random.sample(plugin_paths, len(plugin_paths))
  57. manifest_versions = {}
  58. for plugin_path in plugin_paths:
  59. plugin_path = os.path.abspath(plugin_path)
  60. (plugin_basename, plugin_ext) = os.path.splitext(os.path.basename(plugin_path))
  61. # Get manifest
  62. # Source dir
  63. if os.path.isdir(plugin_path):
  64. manifest_filename = os.path.join(plugin_path, "plugin.json")
  65. try:
  66. # Read manifest
  67. with open(manifest_filename, "r") as f:
  68. manifest = json.load(f)
  69. except IOError:
  70. # Skip plugins without plugin.json
  71. continue
  72. slug = manifest['slug']
  73. version = manifest['version']
  74. # Plugin package
  75. elif plugin_ext == ".vcvplugin":
  76. m = re.match(r'^(.*)-(\d\..*?)-(.*?)-(.*?)$', plugin_basename)
  77. if not m:
  78. raise Exception(f"Filename {plugin_path} invalid format")
  79. slug = m[1]
  80. version = m[2]
  81. os_ = m[3]
  82. cpu = m[4]
  83. # Extract ZIP to temp dir
  84. try:
  85. tempdir = tempfile.mkdtemp()
  86. common.system(f'zstd -d < "{plugin_path}" | tar -x -C "{tempdir}"')
  87. # Read manifest
  88. manifest_filename = os.path.join(tempdir, slug, "plugin.json")
  89. with open(manifest_filename) as f:
  90. manifest = json.load(f)
  91. if manifest['slug'] != slug:
  92. raise Exception(f"Manifest slug {manifest['slug']} does not match filename slug {slug}")
  93. if manifest['version'] != version:
  94. raise Exception(f"Manifest version {manifest['version']} does not match filename version {version}")
  95. finally:
  96. common.system(f'rm -rf "{tempdir}"')
  97. else:
  98. raise Exception(f"Plugin {plugin_path} is not a valid format")
  99. # Slug blacklist
  100. # if slug == 'questionablemodules':
  101. # continue
  102. # Get library manifest
  103. library_manifest_filename = os.path.join(MANIFESTS_DIR, f"{slug}.json")
  104. library_manifest = None
  105. try:
  106. with open(library_manifest_filename, "r") as f:
  107. library_manifest = json.load(f)
  108. except IOError:
  109. # Warn if manifest is new
  110. print(f"Manifest {slug} is new, press enter to approve.")
  111. if input() != '':
  112. continue
  113. pass
  114. # Source dir
  115. if os.path.isdir(plugin_path):
  116. # Check library manifest version
  117. if library_manifest and version == library_manifest['version']:
  118. # Build only if library manifest is out of date
  119. if not BUILD_MAC_ARM64_ONLY:
  120. continue
  121. else:
  122. # Build Mac ARM64 only if library manifest is up to date
  123. if BUILD_MAC_ARM64_ONLY:
  124. continue
  125. # Build repo
  126. if BUILD_MAC_ARM64_ONLY:
  127. if package_exists(slug, version, 'mac', 'arm64'):
  128. print(f"{slug} {version} Mac ARM64 package already exists")
  129. continue
  130. if not package_exists(slug, version, 'mac', 'x64'):
  131. print(f"{slug} {version} Mac x64 doesn't exist, not building")
  132. continue
  133. print()
  134. print(f"Building {slug}")
  135. try:
  136. # Clean repo
  137. common.system(f'cd "{TOOLCHAIN_DIR}" && make plugin-build-clean')
  138. # Build repo for each arch
  139. common.system(f'cd "{TOOLCHAIN_DIR}" && make -j2 plugin-build-mac-arm64 PLUGIN_DIR="{plugin_path}"')
  140. if not BUILD_MAC_ARM64_ONLY:
  141. common.system(f'cd "{TOOLCHAIN_DIR}" && make -j2 plugin-build-mac-x64 PLUGIN_DIR="{plugin_path}"')
  142. common.system(f'cd "{TOOLCHAIN_DIR}" && make -j2 plugin-build-win-x64 PLUGIN_DIR="{plugin_path}"')
  143. common.system(f'cd "{TOOLCHAIN_DIR}" && make -j2 plugin-build-lin-x64 PLUGIN_DIR="{plugin_path}"')
  144. # Copy package to packages dir
  145. common.system(f'cp -v "{TOOLCHAIN_DIR}"/plugin-build/* "{PACKAGES_DIR}"/')
  146. # Copy Mac ARM64 package to files dir for testing
  147. common.system(f'cp -v "{TOOLCHAIN_DIR}"/plugin-build/*-mac-arm64.vcvplugin "{FILES_DIR}"/')
  148. # Install Linux package for testing
  149. if not BUILD_MAC_ARM64_ONLY:
  150. common.system(f'cp -v "{TOOLCHAIN_DIR}"/plugin-build/*-lin-x64.vcvplugin "{PLUGIN_DIR}"/')
  151. except Exception as e:
  152. print(e)
  153. print(f"{slug} build failed")
  154. input()
  155. continue
  156. finally:
  157. common.system(f'cd "{TOOLCHAIN_DIR}" && make plugin-build-clean')
  158. # Open plugin issue thread
  159. if not BUILD_MAC_ARM64_ONLY:
  160. os.system(f"xdg-open 'https://github.com/VCVRack/library/issues?q=is%3Aissue+in%3Atitle+{slug}' &")
  161. # Plugin package
  162. elif plugin_ext == ".vcvplugin":
  163. # Review manifest for errors
  164. print(json.dumps(manifest, indent=" "))
  165. print("Press enter to approve manifest")
  166. input()
  167. # Copy package
  168. common.system(f'cp "{plugin_path}" "{PACKAGES_DIR}/"')
  169. # Update file timestamp
  170. package_filename = os.path.basename(plugin_path)
  171. common.system(f'touch "{PACKAGES_DIR}/{package_filename}"')
  172. # Copy Mac ARM64 package to files dir for testing
  173. if os_ == 'mac' and cpu == 'arm64':
  174. common.system(f'cp -v "{plugin_path}" "{FILES_DIR}"/')
  175. # Install Linux package for testing
  176. if os_ == 'lin':
  177. common.system(f'cp "{plugin_path}" "{PLUGIN_DIR}/"')
  178. # Copy manifest
  179. if not BUILD_MAC_ARM64_ONLY:
  180. with open(library_manifest_filename, "w") as f:
  181. json.dump(manifest, f, indent=" ")
  182. if not BUILD_MAC_ARM64_ONLY:
  183. # Delete screenshot cache
  184. screenshots_dir = os.path.join(SCREENSHOTS_DIR, slug)
  185. common.system(f'rm -rf "{screenshots_dir}"')
  186. manifest_versions[slug] = version
  187. manifest_versions_str = ", ".join(map(lambda pair: pair[0] + " to " + pair[1], manifest_versions.items()))
  188. if BUILD_MAC_ARM64_ONLY:
  189. print()
  190. print(f"Test plugins on Mac ARM64 and press enter if approved: {manifest_versions_str}")
  191. input()
  192. common.system("cd ../packages && make upload")
  193. exit(0)
  194. if not manifest_versions:
  195. print("Nothing to build")
  196. exit(0)
  197. update_cache.update()
  198. update_modulargrid.update()
  199. # Upload data
  200. print()
  201. print(f"Press enter to launch Rack and test the following packages: {manifest_versions_str}")
  202. input()
  203. try:
  204. common.system(f"cd {RACK_SYSTEM_DIR} && ./Rack")
  205. common.system(f"cd {RACK_USER_DIR} && grep 'warn' log.txt || true")
  206. except:
  207. print(f"Rack failed! Enter to continue if desired")
  208. print(f"Press enter to generate screenshots, upload packages, upload screenshots, and commit/push the library repo.")
  209. input()
  210. # Generate screenshots
  211. try:
  212. common.system(f"cd {RACK_SYSTEM_DIR} && ./Rack -t 4")
  213. except:
  214. print(f"Rack failed! Enter to continue if desired")
  215. common.system("cd ../screenshots && make -j$(nproc)")
  216. # Commit git repo
  217. common.system("git add manifests")
  218. common.system("git add manifests-cache.json ModularGrid-VCVLibrary.json")
  219. common.system(f"git commit -m 'Update manifest {manifest_versions_str}'")
  220. # Upload packages
  221. common.system("cd ../packages && make upload")
  222. # Upload screenshots
  223. common.system("cd ../screenshots && make upload")
  224. # Push git repo
  225. common.system("git push")
  226. print()
  227. print(f"Updated {manifest_versions_str}")