Tiltfile 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. # Runtime configuration
  10. config.define_string("num", False, "Number of guardian nodes to run")
  11. # You do not usually need to set this argument - this argument is for debugging only. If you do use a different
  12. # namespace, note that the "wormhole" namespace is hardcoded in tests and don't forget specifying the argument
  13. # when running "tilt down".
  14. #
  15. config.define_string("namespace", False, "Kubernetes namespace to use")
  16. # These arguments will enable writing Guardian events to a BigTable instance.
  17. # Writing to BigTable is optional. These arguments are not required to run the devnet.
  18. config.define_bool("bigTablePersistence", False, "Enable forwarding guardian events to BigTable")
  19. config.define_string("gcpProject", False, "GCP project ID for BigTable persistence")
  20. config.define_string("bigTableKeyPath", False, "Path to BigTable json key file")
  21. cfg = config.parse()
  22. num_guardians = int(cfg.get("num", "5"))
  23. namespace = cfg.get("namespace", "wormhole")
  24. bigTablePersistence = cfg.get("bigTablePersistence", False)
  25. gcpProject = cfg.get("gcpProject", None)
  26. bigTableKeyPath = cfg.get("bigTableKeyPath", "./bigtable-writer.json")
  27. # namespace
  28. namespace_create(namespace)
  29. def k8s_yaml_with_ns(objects):
  30. return k8s_yaml(namespace_inject(objects, namespace))
  31. # protos
  32. proto_deps = ["./proto", "./generate-protos.sh", "buf.yaml", "buf.gen.yaml"]
  33. local_resource(
  34. name = "proto-gen",
  35. deps = proto_deps,
  36. cmd = "./generate-protos.sh",
  37. )
  38. local_resource(
  39. name = "proto-gen-web",
  40. deps = proto_deps,
  41. resource_deps = ["proto-gen"],
  42. cmd = "./generate-protos-web.sh",
  43. )
  44. # bridge
  45. if bigTablePersistence:
  46. k8s_yaml_with_ns(
  47. secret_yaml_generic(
  48. "bridge-bigtable-key",
  49. from_file = "bigtable-key.json=" + bigTableKeyPath
  50. )
  51. )
  52. docker_build(
  53. ref = "guardiand-image",
  54. context = "bridge",
  55. dockerfile = "bridge/Dockerfile",
  56. )
  57. def build_bridge_yaml():
  58. bridge_yaml = read_yaml_stream("devnet/bridge.yaml")
  59. for obj in bridge_yaml:
  60. if obj["kind"] == "StatefulSet" and obj["metadata"]["name"] == "guardian":
  61. obj["spec"]["replicas"] = num_guardians
  62. container = obj["spec"]["template"]["spec"]["containers"][0]
  63. if container["name"] != "guardiand":
  64. fail("container 0 is not guardiand")
  65. container["command"] += ["--devNumGuardians", str(num_guardians)]
  66. if bigTablePersistence:
  67. container["command"] += [
  68. "--bigTablePersistenceEnabled",
  69. "--bigTableGCPProject",
  70. gcpProject
  71. ]
  72. return encode_yaml_stream(bridge_yaml)
  73. k8s_yaml_with_ns(build_bridge_yaml())
  74. k8s_resource("guardian", resource_deps = ["proto-gen", "solana-devnet"], port_forwards = [
  75. port_forward(6060, name = "Debug/Status Server [:6060]"),
  76. port_forward(7070, name = "Public gRPC [:7070]"),
  77. port_forward(7071, name = "Public REST [:7071]"),
  78. ])
  79. # publicRPC proxy that allows grpc over http1, for local development
  80. k8s_yaml_with_ns("./devnet/envoy-proxy.yaml")
  81. k8s_resource(
  82. "envoy-proxy",
  83. resource_deps = ["guardian"],
  84. objects = ["envoy-proxy:ConfigMap:wormhole"],
  85. port_forwards = [
  86. port_forward(8080, name = "gRPC proxy for guardian's publicRPC data [:8080]"),
  87. port_forward(9901, name = "gRPC proxy admin [:9901]"), # for proxy debugging
  88. ],
  89. )
  90. # solana client cli (used for devnet setup)
  91. docker_build(
  92. ref = "solana-client",
  93. context = ".",
  94. only = ["./proto", "./solana", "./ethereum", "./clients/token_bridge"],
  95. dockerfile = "Dockerfile.client",
  96. # Ignore target folders from local (non-container) development.
  97. ignore = ["./solana/target", "./solana/agent/target", "./solana/cli/target"],
  98. )
  99. # solana smart contract
  100. docker_build(
  101. ref = "solana-contract",
  102. context = "solana",
  103. dockerfile = "solana/Dockerfile",
  104. )
  105. # solana local devnet
  106. k8s_yaml_with_ns("devnet/solana-devnet.yaml")
  107. k8s_resource("solana-devnet", port_forwards = [
  108. port_forward(8899, name = "Solana RPC [:8899]"),
  109. port_forward(8900, name = "Solana WS [:8900]"),
  110. port_forward(9000, name = "Solana PubSub [:9000]"),
  111. ])
  112. # eth devnet
  113. docker_build(
  114. ref = "eth-node",
  115. context = "./ethereum",
  116. dockerfile = "./ethereum/Dockerfile",
  117. # ignore local node_modules (in case they're present)
  118. ignore = ["./ethereum/node_modules"],
  119. # sync external scripts for incremental development
  120. # (everything else needs to be restarted from scratch for determinism)
  121. #
  122. # This relies on --update-mode=exec to work properly with a non-root user.
  123. # https://github.com/tilt-dev/tilt/issues/3708
  124. live_update = [
  125. sync("./ethereum/src", "/home/node/app/src"),
  126. ],
  127. )
  128. k8s_yaml_with_ns("devnet/eth-devnet.yaml")
  129. k8s_resource("eth-devnet", port_forwards = [
  130. port_forward(8545, name = "Ganache RPC [:8545]"),
  131. ])
  132. # explorer web app
  133. docker_build(
  134. ref = "explorer",
  135. context = "./explorer",
  136. dockerfile = "./explorer/Dockerfile",
  137. ignore = ["./explorer/node_modules"],
  138. live_update = [
  139. sync("./explorer/src", "/home/node/app/src"),
  140. sync("./explorer/public", "/home/node/app/public"),
  141. ],
  142. )
  143. k8s_yaml_with_ns("devnet/explorer.yaml")
  144. k8s_resource(
  145. "explorer",
  146. resource_deps = ["envoy-proxy", "proto-gen-web"],
  147. port_forwards = [
  148. port_forward(8001, name = "Explorer Web UI [:8001]"),
  149. ],
  150. )
  151. # terra devnet
  152. docker_build(
  153. ref = "terra-image",
  154. context = "./terra/devnet",
  155. dockerfile = "terra/devnet/Dockerfile",
  156. )
  157. docker_build(
  158. ref = "terra-contracts",
  159. context = "./terra",
  160. dockerfile = "./terra/Dockerfile",
  161. )
  162. k8s_yaml_with_ns("devnet/terra-devnet.yaml")
  163. k8s_resource(
  164. "terra-lcd",
  165. port_forwards = [port_forward(1317, name = "Terra LCD interface [:1317]")],
  166. )
  167. k8s_resource(
  168. "terra-terrad",
  169. port_forwards = [port_forward(26657, name = "Terra RPC [:26657]")],
  170. )
  171. k8s_resource(
  172. "terra-fcd",
  173. port_forwards = [port_forward(3060, name = "Terra FCD [:3060]")],
  174. )