Tiltfile 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. # This Tiltfile contains the deployment and build config for the Wormhole devnet.
  2. #
  3. # We use Buildkit cache mounts and careful layering to avoid unnecessary rebuilds - almost
  4. # all source code changes result in small, incremental rebuilds. Dockerfiles are written such
  5. # that, for example, changing the contract source code won't cause Solana itself to be rebuilt.
  6. #
  7. load("ext://namespace", "namespace_create", "namespace_inject")
  8. load("ext://secret", "secret_yaml_generic")
  9. allow_k8s_contexts("ci")
  10. # Disable telemetry by default
  11. analytics_settings(False)
  12. # Runtime configuration
  13. config.define_bool("ci", False, "We are running in CI")
  14. config.define_string("num", False, "Number of guardian nodes to run")
  15. # You do not usually need to set this argument - this argument is for debugging only. If you do use a different
  16. # namespace, note that the "wormhole" namespace is hardcoded in tests and don't forget specifying the argument
  17. # when running "tilt down".
  18. #
  19. config.define_string("namespace", False, "Kubernetes namespace to use")
  20. # These arguments will enable writing Guardian events to a cloud BigTable instance.
  21. # Writing to a cloud BigTable is optional. These arguments are not required to run the devnet.
  22. config.define_string("gcpProject", False, "GCP project ID for BigTable persistence")
  23. config.define_string("bigTableKeyPath", False, "Path to BigTable json key file")
  24. cfg = config.parse()
  25. num_guardians = int(cfg.get("num", "5"))
  26. namespace = cfg.get("namespace", "wormhole")
  27. gcpProject = cfg.get("gcpProject", "local-dev")
  28. bigTableKeyPath = cfg.get("bigTableKeyPath", "./event_database/devnet_key.json")
  29. ci = cfg.get("ci", False)
  30. # namespace
  31. if not ci:
  32. namespace_create(namespace)
  33. def k8s_yaml_with_ns(objects):
  34. return k8s_yaml(namespace_inject(objects, namespace))
  35. # protos
  36. proto_deps = ["./proto", "./generate-protos.sh", "buf.yaml", "buf.gen.yaml"]
  37. local_resource(
  38. name = "proto-gen",
  39. deps = proto_deps,
  40. cmd = "./generate-protos.sh",
  41. )
  42. local_resource(
  43. name = "proto-gen-web",
  44. deps = proto_deps,
  45. resource_deps = ["proto-gen"],
  46. cmd = "./generate-protos-web.sh",
  47. )
  48. # bridge
  49. k8s_yaml_with_ns(
  50. secret_yaml_generic(
  51. "bridge-bigtable-key",
  52. from_file = "bigtable-key.json=" + bigTableKeyPath,
  53. ),
  54. )
  55. docker_build(
  56. ref = "guardiand-image",
  57. context = "node",
  58. dockerfile = "node/Dockerfile",
  59. )
  60. def build_bridge_yaml():
  61. bridge_yaml = read_yaml_stream("devnet/bridge.yaml")
  62. for obj in bridge_yaml:
  63. if obj["kind"] == "StatefulSet" and obj["metadata"]["name"] == "guardian":
  64. obj["spec"]["replicas"] = num_guardians
  65. container = obj["spec"]["template"]["spec"]["containers"][0]
  66. if container["name"] != "guardiand":
  67. fail("container 0 is not guardiand")
  68. container["command"] += ["--devNumGuardians", str(num_guardians)]
  69. container["command"] += ["--bigTableGCPProject", gcpProject]
  70. return encode_yaml_stream(bridge_yaml)
  71. k8s_yaml_with_ns(build_bridge_yaml())
  72. k8s_resource("guardian", resource_deps = ["proto-gen", "solana-devnet"], port_forwards = [
  73. port_forward(6060, name = "Debug/Status Server [:6060]"),
  74. port_forward(7070, name = "Public gRPC [:7070]"),
  75. port_forward(7071, name = "Public REST [:7071]"),
  76. ])
  77. docker_build(
  78. ref = "pyth",
  79. context = ".",
  80. dockerfile = "third_party/pyth/Dockerfile",
  81. )
  82. k8s_yaml_with_ns("./devnet/pyth.yaml")
  83. k8s_resource("pyth", resource_deps = ["solana-devnet"])
  84. # publicRPC proxy that allows grpc over http1, for local development
  85. k8s_yaml_with_ns("./devnet/envoy-proxy.yaml")
  86. k8s_resource(
  87. "envoy-proxy",
  88. resource_deps = ["guardian"],
  89. objects = ["envoy-proxy:ConfigMap"],
  90. port_forwards = [
  91. port_forward(8080, name = "gRPC proxy for guardian's publicRPC data [:8080]"),
  92. port_forward(9901, name = "gRPC proxy admin [:9901]"), # for proxy debugging
  93. ],
  94. )
  95. # solana client cli (used for devnet setup)
  96. docker_build(
  97. ref = "solana-client",
  98. context = ".",
  99. only = ["./proto", "./solana", "./ethereum", "./clients/token_bridge"],
  100. dockerfile = "Dockerfile.client",
  101. # Ignore target folders from local (non-container) development.
  102. ignore = ["./solana/target", "./solana/agent/target", "./solana/cli/target"],
  103. )
  104. # solana smart contract
  105. docker_build(
  106. ref = "solana-contract",
  107. context = "solana",
  108. dockerfile = "solana/Dockerfile",
  109. )
  110. # solana local devnet
  111. k8s_yaml_with_ns("devnet/solana-devnet.yaml")
  112. k8s_resource("solana-devnet", port_forwards = [
  113. port_forward(8899, name = "Solana RPC [:8899]"),
  114. port_forward(8900, name = "Solana WS [:8900]"),
  115. port_forward(9000, name = "Solana PubSub [:9000]"),
  116. ])
  117. # eth devnet
  118. docker_build(
  119. ref = "eth-node",
  120. context = "./ethereum",
  121. dockerfile = "./ethereum/Dockerfile",
  122. # ignore local node_modules (in case they're present)
  123. ignore = ["./ethereum/node_modules"],
  124. # sync external scripts for incremental development
  125. # (everything else needs to be restarted from scratch for determinism)
  126. #
  127. # This relies on --update-mode=exec to work properly with a non-root user.
  128. # https://github.com/tilt-dev/tilt/issues/3708
  129. live_update = [
  130. sync("./ethereum/src", "/home/node/app/src"),
  131. ],
  132. )
  133. k8s_yaml_with_ns("devnet/eth-devnet.yaml")
  134. k8s_resource("eth-devnet", port_forwards = [
  135. port_forward(8545, name = "Ganache RPC [:8545]"),
  136. ])
  137. # bigtable
  138. def build_cloud_function(container_name, go_func_name, path, builder):
  139. # Invokes Tilt's custom_build(), with a Pack command.
  140. # inspired by https://github.com/tilt-dev/tilt-extensions/tree/master/pack
  141. caching_ref = container_name + ":tilt-build-pack-caching"
  142. pack_build_cmd = " ".join([
  143. "./tools/bin/pack build",
  144. caching_ref,
  145. "--path " + path,
  146. "--builder " + builder,
  147. "--env " + "GOOGLE_FUNCTION_TARGET=%s" % go_func_name,
  148. "--env " + "GOOGLE_FUNCTION_SIGNATURE_TYPE=http",
  149. ])
  150. if ci:
  151. # inherit the DOCKER_HOST socket provided by custom_build.
  152. pack_build_cmd = pack_build_cmd + " --docker-host inherit"
  153. docker_tag_cmd = "docker tag " + caching_ref + " $EXPECTED_REF"
  154. custom_build(
  155. container_name,
  156. pack_build_cmd + " && " + docker_tag_cmd,
  157. [path],
  158. )
  159. build_cloud_function(
  160. container_name = "cloud-function-readrow",
  161. go_func_name = "ReadRow",
  162. path = "./event_database/cloud_functions",
  163. builder = "gcr.io/buildpacks/builder:v1",
  164. )
  165. k8s_yaml_with_ns("devnet/bigtable.yaml")
  166. k8s_resource("bigtable-emulator", port_forwards = [
  167. port_forward(8086, name = "BigTable clients [:8086]"),
  168. ])
  169. k8s_resource(
  170. "bigtable-readrow",
  171. resource_deps = ["proto-gen"],
  172. port_forwards = [port_forward(8090, name = "ReadRow [:8090]")],
  173. )
  174. # explorer web app
  175. docker_build(
  176. ref = "explorer",
  177. context = "./explorer",
  178. dockerfile = "./explorer/Dockerfile",
  179. ignore = ["./explorer/node_modules"],
  180. live_update = [
  181. sync("./explorer/src", "/home/node/app/src"),
  182. sync("./explorer/public", "/home/node/app/public"),
  183. ],
  184. )
  185. k8s_yaml_with_ns("devnet/explorer.yaml")
  186. k8s_resource(
  187. "explorer",
  188. resource_deps = ["proto-gen-web"],
  189. port_forwards = [
  190. port_forward(8001, name = "Explorer Web UI [:8001]"),
  191. ],
  192. )
  193. # terra devnet
  194. docker_build(
  195. ref = "terra-image",
  196. context = "./terra/devnet",
  197. dockerfile = "terra/devnet/Dockerfile",
  198. )
  199. docker_build(
  200. ref = "terra-contracts",
  201. context = "./terra",
  202. dockerfile = "./terra/Dockerfile",
  203. )
  204. k8s_yaml_with_ns("devnet/terra-devnet.yaml")
  205. k8s_resource(
  206. "terra-lcd",
  207. port_forwards = [port_forward(1317, name = "Terra LCD interface [:1317]")],
  208. )
  209. k8s_resource(
  210. "terra-terrad",
  211. port_forwards = [port_forward(26657, name = "Terra RPC [:26657]")],
  212. )
  213. k8s_resource(
  214. "terra-fcd",
  215. port_forwards = [port_forward(3060, name = "Terra FCD [:3060]")],
  216. )