|
| 1 | +import os |
| 2 | +import tarfile |
| 3 | +import urllib.request |
| 4 | +import zipfile |
| 5 | +import shutil |
| 6 | +import logging |
| 7 | +import subprocess |
| 8 | +from multiprocessing.pool import ThreadPool |
| 9 | +from itertools import repeat |
| 10 | + |
| 11 | +MICROSOFT_URL = "https://aka.ms/download-jdk/microsoft-jdk-21.0.1-" |
| 12 | +JRE_SUBFOLDER = "jdk-21.0.1+12" |
| 13 | +JDKS = { |
| 14 | + "windows-x64": "windows-x64.zip", |
| 15 | + "linux-x64": "linux-x64.tar.gz", |
| 16 | + "macos-x64": "macos-x64.tar.gz", |
| 17 | + "windows-aarch64": "windows-aarch64.zip", |
| 18 | + "linux-aarch64": "linux-aarch64.tar.gz", |
| 19 | + "macos-aarch64": "macos-aarch64.tar.gz", |
| 20 | +} |
| 21 | + |
| 22 | +# Specific to ergo-node .jap, collected with jdeps |
| 23 | +JLINK_MODULES = "java.base,java.compiler,java.desktop,java.management,java.naming,java.rmi,java.sql,jdk.unsupported" |
| 24 | + |
| 25 | +MAIN_JRE = os.environ.get("ERGO_RELEASE_PLATFORM") |
| 26 | +VERSION = os.environ.get("ERGO_RELEASE_TAG") |
| 27 | + |
| 28 | +JAR_FILENAME = f"ergo-{VERSION}.jar" |
| 29 | +SCRIPT_LOGO = f""" |
| 30 | +
|
| 31 | + .-*%@#+-. |
| 32 | + .-+#@@%*=-=*%@@#+-. |
| 33 | + +@@#+- :=*@@+ |
| 34 | + -@@: ......... :@@- |
| 35 | + .@@- #@@@@@@@% -@@: .@@@@@@@-:@@@@@%*. .+%@@@%+. .+%@@@%+. |
| 36 | + %@+ .*@@*. =@@. :@@:.... :@@:..+@@ =@@=. .=*= -@@=. .=@@= |
| 37 | + #@# .%@@= *@% :@@%%%%%.:@@+++%@# @@= .+++++ %@+ =@@ |
| 38 | + =@@. .*@@= .@@= :@@-:::: :@@+#@@- #@# .==*@@.#@# *@% |
| 39 | + *@% =@@@*+++= %@* :@@*****::@@. =@@: .#@@*+*%@% *@@*+*%@#. |
| 40 | + #@# +#######* *@% =======..== :== .-=++-. .-=+=-. |
| 41 | + %@*. .+@@. |
| 42 | + .#@@@#+-. .-+#@@%*: Node version: {VERSION} |
| 43 | + .-+#@@@#%@@#+-. |
| 44 | +
|
| 45 | +
|
| 46 | +""" |
| 47 | +def download_jdk(url): |
| 48 | + final_url = MICROSOFT_URL + url |
| 49 | + logging.warning(f"Downloading {final_url}") |
| 50 | + urllib.request.urlretrieve(final_url, url) |
| 51 | + |
| 52 | +def unarchive_jdk(filename, directory): |
| 53 | + logging.warning(f"Extracting {filename} into {directory}") |
| 54 | + if filename.endswith("tar.gz"): |
| 55 | + tar = tarfile.open(filename, "r:gz") |
| 56 | + tar.extractall(directory) |
| 57 | + tar.close() |
| 58 | + elif filename.endswith("zip"): |
| 59 | + with zipfile.ZipFile(filename, 'r') as zip_ref: |
| 60 | + zip_ref.extractall(directory) |
| 61 | + |
| 62 | +def create_jre(jlink, target_jre_dir, out_jre_dir): |
| 63 | + subprocess.run([ |
| 64 | + jlink, |
| 65 | + "--module-path", |
| 66 | + os.path.join(target_jre_dir, "jmods"), |
| 67 | + "--add-modules", |
| 68 | + JLINK_MODULES, |
| 69 | + "--strip-debug", |
| 70 | + "--compress", "2", |
| 71 | + "--no-header-files", |
| 72 | + "--no-man-pages", |
| 73 | + "--output", |
| 74 | + out_jre_dir |
| 75 | + ], check=True) |
| 76 | + |
| 77 | +def make_windows(target): |
| 78 | + app_dir = f"{target}/ergo-node" |
| 79 | + os.makedirs(app_dir, exist_ok=True) |
| 80 | + app_script = f""" |
| 81 | +Write-Host @" |
| 82 | +
|
| 83 | +{SCRIPT_LOGO} |
| 84 | +
|
| 85 | +"@ -ForegroundColor Red |
| 86 | +jre/bin/java -jar -Xmx4G {JAR_FILENAME} --mainnet -c ergo.conf |
| 87 | + """ |
| 88 | + with open(f"{app_dir}/ergo-node.ps1", "w") as f: |
| 89 | + f.write(app_script) |
| 90 | + |
| 91 | + shutil.copytree(f"{target}/jre", f"{app_dir}/jre") |
| 92 | + shutil.copyfile(JAR_FILENAME, f"{app_dir}/{JAR_FILENAME}") |
| 93 | + shutil.copyfile("ergo.conf", f"{app_dir}/ergo.conf") |
| 94 | + shutil.make_archive(f"release/ergo-node-{VERSION}-{target}", 'zip', app_dir) |
| 95 | + |
| 96 | +def make_linux(target): |
| 97 | + app_dir = f"{target}/ergo-node" |
| 98 | + os.makedirs(app_dir, exist_ok=True) |
| 99 | + |
| 100 | + app_script = f"""#!/bin/env sh |
| 101 | +echo '\033[0;31m' |
| 102 | +cat << EOF |
| 103 | + |
| 104 | +{SCRIPT_LOGO} |
| 105 | +
|
| 106 | +EOF |
| 107 | +echo '\033[0m' |
| 108 | +./jre/bin/java -jar -Xmx4G {JAR_FILENAME} --mainnet -c ergo.conf |
| 109 | +exit |
| 110 | + """ |
| 111 | + with open(f"{app_dir}/ergo-node.sh", "w") as f: |
| 112 | + f.write(app_script) |
| 113 | + os.chmod(f"{app_dir}/ergo-node.sh", 0o755) |
| 114 | + |
| 115 | + shutil.copytree(f"{target}/jre", f"{app_dir}/jre") |
| 116 | + shutil.copyfile(JAR_FILENAME, f"{app_dir}/{JAR_FILENAME}") |
| 117 | + shutil.copyfile("ergo.conf", f"{app_dir}/ergo.conf") |
| 118 | + with tarfile.open(f"release/ergo-node-{VERSION}-{target}.tar.gz", "w:gz") as tar: |
| 119 | + tar.add(app_dir) |
| 120 | + |
| 121 | +def make_macos(target): |
| 122 | + app_dir = f"{target}/ErgoNode.app" |
| 123 | + os.makedirs(app_dir, exist_ok=True) |
| 124 | + os.makedirs(f"{app_dir}/Contents/MacOS", exist_ok=True) |
| 125 | + os.makedirs(f"{app_dir}/Contents/Resources", exist_ok=True) |
| 126 | + |
| 127 | + info_plist = f"""<?xml version="1.0" encoding="UTF-8"?> |
| 128 | + <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 129 | + <plist version="1.0"> |
| 130 | + <dict> |
| 131 | + <key>CFBundleExecutable</key> |
| 132 | + <string>start.command</string> |
| 133 | + <key>CFBundleIdentifier</key> |
| 134 | + <string>org.ergoplatform.ergo-node</string> |
| 135 | + <key>CFBundleName</key> |
| 136 | + <string>Ergo Node</string> |
| 137 | + <key>CFBundleIconFile</key> |
| 138 | + <string>ergo.icns</string> |
| 139 | + <key>CFBundleVersion</key> |
| 140 | + <string>{VERSION}</string> |
| 141 | + </dict> |
| 142 | + </plist> |
| 143 | + """ |
| 144 | + with open(f"{app_dir}/Contents/info.plist", "w") as f: |
| 145 | + f.write(info_plist) |
| 146 | + |
| 147 | + app_script = f"""#!/bin/zsh |
| 148 | +SRC=$(cd "$(dirname "$0")"; pwd -P) |
| 149 | +echo '\033[0;31m' |
| 150 | +cat << EOF |
| 151 | +
|
| 152 | +{SCRIPT_LOGO} |
| 153 | +
|
| 154 | +EOF |
| 155 | +echo '\033[0m' |
| 156 | +$SRC/jre/bin/java -jar -Xmx4G $SRC/{JAR_FILENAME} --mainnet -c $SRC/ergo.conf |
| 157 | +
|
| 158 | +exit |
| 159 | + """ |
| 160 | + app_script_file = "ergo-node.sh" |
| 161 | + with open(f"{app_dir}/Contents/MacOS/{app_script_file}", "w") as f: |
| 162 | + f.write(app_script) |
| 163 | + |
| 164 | + # Require nested script for macos Terminal app to open |
| 165 | + start_command = f"""#!/bin/zsh |
| 166 | +MY_PATH=$(cd "$(dirname "$0")"; pwd -P) |
| 167 | +open -a Terminal $MY_PATH/{app_script_file} |
| 168 | + """ |
| 169 | + start_command_file = "start.command" |
| 170 | + with open(f"{app_dir}/Contents/MacOS/{start_command_file}", "w") as f: |
| 171 | + f.write(start_command) |
| 172 | + os.chmod(f"{app_dir}/Contents/MacOS/{app_script_file}", 0o755) |
| 173 | + os.chmod(f"{app_dir}/Contents/MacOS/{start_command_file}", 0o755) |
| 174 | + |
| 175 | + shutil.copytree(f"{target}/jre", f"{app_dir}/Contents/MacOS/jre") |
| 176 | + shutil.copyfile(JAR_FILENAME, f"{app_dir}/Contents/MacOS/{JAR_FILENAME}") |
| 177 | + shutil.copyfile("ergo.conf", f"{app_dir}/Contents/MacOS/ergo.conf") |
| 178 | + shutil.copyfile("ci/ergo.icns", f"{app_dir}/Contents/Resources/ergo.icns") |
| 179 | + |
| 180 | + with tarfile.open(f"release/ergo-node-{VERSION}-{target}.tar.gz", "w:gz") as tar: |
| 181 | + tar.add(app_dir) |
| 182 | + |
| 183 | +def process_download(entry): |
| 184 | + (os_type, filename) = entry |
| 185 | + download_jdk(filename) |
| 186 | + unarchive_jdk(filename, os_type) |
| 187 | + |
| 188 | +def process_jres(os_type, main_jre): |
| 189 | + logging.warning(f"Creating jre for {os_type}") |
| 190 | + if (os_type.startswith("macos")): |
| 191 | + create_jre(main_jre, os.path.join(os_type, JRE_SUBFOLDER, "Contents", "Home"), os_type + "/jre") |
| 192 | + make_macos(os_type) |
| 193 | + if (os_type.startswith("linux")): |
| 194 | + create_jre(main_jre, os.path.join(os_type, JRE_SUBFOLDER), os_type + "/jre") |
| 195 | + make_linux(os_type) |
| 196 | + if (os_type.startswith("windows")): |
| 197 | + create_jre(main_jre, os.path.join(os_type, JRE_SUBFOLDER), os_type + "/jre") |
| 198 | + make_windows(os_type) |
| 199 | + |
| 200 | +def get_main_jre(jre, subfolder) -> str: |
| 201 | + if (jre.startswith("windows")): |
| 202 | + return os.path.join(jre, subfolder, "bin", "jlink.exe") |
| 203 | + elif (jre.startswith("macos")): |
| 204 | + return os.path.join(jre, subfolder, "Contents", "Home", "bin", "jlink") |
| 205 | + else: #linux |
| 206 | + return os.path.join(jre, subfolder, "bin", "jlink") |
| 207 | + |
| 208 | +logging.warning(f"Starting release binaries for ergo-node") |
| 209 | + |
| 210 | +main_jre = get_main_jre(MAIN_JRE, JRE_SUBFOLDER) |
| 211 | +os.makedirs("release", exist_ok=True) |
| 212 | + |
| 213 | +ergo_conf = """ |
| 214 | +ergo { |
| 215 | + node { |
| 216 | + mining = false |
| 217 | + } |
| 218 | +} |
| 219 | +""" |
| 220 | +with open("ergo.conf", "w") as f: |
| 221 | + f.write(ergo_conf) |
| 222 | + |
| 223 | +with ThreadPool(JDKS.__len__()) as pool: |
| 224 | + pool.map(process_download, JDKS.items()) |
| 225 | + |
| 226 | +with ThreadPool(JDKS.__len__()) as pool: |
| 227 | + pool.starmap(process_jres, zip(JDKS.keys(), repeat(main_jre))) |
0 commit comments