diff --git a/scripts/publish.py b/scripts/publish.py new file mode 100644 index 000000000..b8c35604d --- /dev/null +++ b/scripts/publish.py @@ -0,0 +1,123 @@ +#! /bin/python3 + +# This is a script for publishing the wasmer crates to crates.io. +# It should be run in the root of wasmer like `python3 scripts/publish.py`. + +# install dependencies: +# pip3 install toposort + +import argparse +import os +import re +import subprocess +import time + +from typing import Optional +from toposort import toposort_flatten + + +# TODO find this automatically +target_version = "1.0.0-alpha01.1" + +# TODO generate this by parsing toml files +dep_graph = { + "wasmer-types": set([]), + "wasmer-vm": set(["wasmer-types"]), + "wasmer-compiler": set(["wasmer-vm", "wasmer-types"]), + "wasmer-object": set(["wasmer-types", "wasmer-compiler"]), + "wasmer-engine": set(["wasmer-types", "wasmer-vm", "wasmer-compiler"]), + "wasmer-compiler-singlepass": set(["wasmer-types", "wasmer-vm", "wasmer-compiler"]), + "wasmer-compiler-cranelift": set(["wasmer-types", "wasmer-vm", "wasmer-compiler"]), + "wasmer-compiler-llvm": set(["wasmer-types", "wasmer-vm", "wasmer-compiler"]), + "wasmer-engine-jit": set(["wasmer-types", "wasmer-vm", "wasmer-compiler", "wasmer-engine"]), + "wasmer-engine-native": set(["wasmer-types", "wasmer-vm", "wasmer-compiler", "wasmer-engine", + "wasmer-object"]), + "wasmer": set(["wasmer-vm", "wasmer-compiler-singlepass", "wasmer-compiler-cranelift", + "wasmer-compiler-llvm", "wasmer-compiler", "wasmer-engine", "wasmer-engine-jit", + "wasmer-engine-native", "wasmer-types"]), + "wasmer-cache": set(["wasmer"]), + "wasmer-wasi": set(["wasmer"]), + "wasmer-wasi-experimental-io-devices": set(["wasmer-wasi"]), + "wasmer-emscripten": set(["wasmer"]), +} + +# where each crate is located in `lib` +# this can also be generated from the toml files +location = { + "wasmer-types": "wasmer-types", + "wasmer-vm": "vm", + "wasmer-compiler": "compiler", + "wasmer-object": "object", + "wasmer-engine": "engine", + "wasmer-compiler-singlepass": "compiler-singlepass", + "wasmer-compiler-cranelift": "compiler-cranelift", + "wasmer-compiler-llvm": "compiler-llvm", + "wasmer-engine": "engine", + "wasmer-engine-jit": "engine-jit", + "wasmer-engine-native": "engine-native", + "wasmer-cache": "cache", + "wasmer": "api", + "wasmer-wasi": "wasi", + "wasmer-emscripten": "emscripten", + "wasmer-wasi-experimental-io-devices": "wasi-experimental-io-devices", +} + +dry_run = False + +def get_latest_version_for_crate(crate_name: str) -> Optional[str]: + output = subprocess.run(["cargo", "search", crate_name], capture_output=True) + rexp_src = '^{} = "([^"]+)"'.format(crate_name) + prog = re.compile(rexp_src) + haystack = output.stdout.decode("utf-8") + for line in haystack.splitlines(): + result = prog.match(line) + if result: + return result.group(1) + +def is_crate_already_published(crate_name: str) -> bool: + found_string = get_latest_version_for_crate(crate_name) + if found_string is None: + return False + + return target_version == found_string + +# TODO: add dry run mode +def publish_crate(crate: str): + os.chdir("lib/{}".format(location[crate])) + + global dry_run + if dry_run: + print("In dry-run: not publishing crate `{}`".format(crate)) + else: + output = subprocess.run(["cargo", "publish"]) + + os.chdir("../..") + +def main(): + parser = argparse.ArgumentParser(description='Publish the Wasmer crates to crates.io') + parser.add_argument('--dry-run', default=False, action='store_true', + help='Run the script without actually publishing anything to crates.io') + args = vars(parser.parse_args()) + + global dry_run + dry_run = args['dry_run'] + + # get the order to publish the crates in + order = list(toposort_flatten(dep_graph, sort=True)) + + for crate in order: + print("Publishing `{}`...".format(crate)) + if not is_crate_already_published(crate): + publish_crate(crate) + else: + print("`{}` was already published!".format(crate)) + continue + # sleep for 10 seconds between crates to ensure the crates.io index has time to update + # this can be optimized with knowledge of our dep graph via toposort; we can even publish + # crates in parallel; however this is out of scope for the first version of this script + print("Sleeping for 10 seconds to allow the `crates.io` index to update...") + time.sleep(10) + + +if __name__ == "__main__": + main()