Tiltfile 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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 = "tilt docker build -- --target go-export -f Dockerfile.proto -o type=local,dest=node .",
  41. env = {"DOCKER_BUILDKIT": "1"},
  42. )
  43. local_resource(
  44. name = "proto-gen-web",
  45. deps = proto_deps,
  46. resource_deps = ["proto-gen"],
  47. cmd = "tilt docker build -- --target node-export -f Dockerfile.proto -o type=local,dest=. .",
  48. env = {"DOCKER_BUILDKIT": "1"},
  49. )
  50. # wasm
  51. local_resource(
  52. name = "wasm-gen",
  53. deps = ["solana"],
  54. dir = "solana",
  55. cmd = "tilt docker build -- -f Dockerfile.wasm -o type=local,dest=.. .",
  56. env = {"DOCKER_BUILDKIT": "1"},
  57. )
  58. # node
  59. k8s_yaml_with_ns(
  60. secret_yaml_generic(
  61. "bridge-bigtable-key",
  62. from_file = "bigtable-key.json=" + bigTableKeyPath,
  63. ),
  64. )
  65. docker_build(
  66. ref = "guardiand-image",
  67. context = "node",
  68. dockerfile = "node/Dockerfile",
  69. )
  70. def build_node_yaml():
  71. node_yaml = read_yaml_stream("devnet/node.yaml")
  72. for obj in node_yaml:
  73. if obj["kind"] == "StatefulSet" and obj["metadata"]["name"] == "guardian":
  74. obj["spec"]["replicas"] = num_guardians
  75. container = obj["spec"]["template"]["spec"]["containers"][0]
  76. if container["name"] != "guardiand":
  77. fail("container 0 is not guardiand")
  78. container["command"] += ["--devNumGuardians", str(num_guardians)]
  79. container["command"] += ["--bigTableGCPProject", gcpProject]
  80. return encode_yaml_stream(node_yaml)
  81. k8s_yaml_with_ns(build_node_yaml())
  82. k8s_resource("guardian", resource_deps = ["proto-gen", "solana-devnet"], port_forwards = [
  83. port_forward(6060, name = "Debug/Status Server [:6060]"),
  84. port_forward(7070, name = "Public gRPC [:7070]"),
  85. port_forward(7071, name = "Public REST [:7071]"),
  86. ])
  87. docker_build(
  88. ref = "pyth",
  89. context = ".",
  90. dockerfile = "third_party/pyth/Dockerfile.pyth",
  91. )
  92. k8s_yaml_with_ns("./devnet/pyth.yaml")
  93. k8s_resource("pyth", resource_deps = ["solana-devnet"])
  94. # publicRPC proxy that allows grpc over http1, for local development
  95. k8s_yaml_with_ns("./devnet/envoy-proxy.yaml")
  96. k8s_resource(
  97. "envoy-proxy",
  98. resource_deps = ["guardian"],
  99. objects = ["envoy-proxy:ConfigMap"],
  100. port_forwards = [
  101. port_forward(8080, name = "gRPC proxy for guardian's publicRPC data [:8080]"),
  102. port_forward(9901, name = "gRPC proxy admin [:9901]"), # for proxy debugging
  103. ],
  104. )
  105. # solana client cli (used for devnet setup)
  106. docker_build(
  107. ref = "bridge-client",
  108. context = ".",
  109. only = ["./proto", "./solana", "./ethereum", "./clients"],
  110. dockerfile = "Dockerfile.client",
  111. # Ignore target folders from local (non-container) development.
  112. ignore = ["./solana/*/target"],
  113. )
  114. # solana smart contract
  115. docker_build(
  116. ref = "solana-contract",
  117. context = "solana",
  118. dockerfile = "solana/Dockerfile",
  119. )
  120. # solana local devnet
  121. k8s_yaml_with_ns("devnet/solana-devnet.yaml")
  122. k8s_resource(
  123. "solana-devnet",
  124. resource_deps = ["wasm-gen"],
  125. port_forwards = [
  126. port_forward(8899, name = "Solana RPC [:8899]"),
  127. port_forward(8900, name = "Solana WS [:8900]"),
  128. port_forward(9000, name = "Solana PubSub [:9000]"),
  129. ],
  130. )
  131. # pyth2wormhole client
  132. docker_build(
  133. ref = "p2w-client",
  134. context = ".",
  135. only = ["./solana", "./third_party"],
  136. dockerfile = "./third_party/pyth/Dockerfile.p2w-client",
  137. # Ignore target folders from local (non-container) development.
  138. ignore = ["./solana/*/target"],
  139. )
  140. k8s_yaml_with_ns("devnet/p2w-client.yaml")
  141. k8s_resource("p2w-client",
  142. resource_deps=["solana-devnet", "pyth"],
  143. port_forwards=[]
  144. )
  145. # eth devnet
  146. docker_build(
  147. ref = "eth-node",
  148. context = "./ethereum",
  149. dockerfile = "./ethereum/Dockerfile",
  150. # ignore local node_modules (in case they're present)
  151. ignore = ["./ethereum/node_modules"],
  152. # sync external scripts for incremental development
  153. # (everything else needs to be restarted from scratch for determinism)
  154. #
  155. # This relies on --update-mode=exec to work properly with a non-root user.
  156. # https://github.com/tilt-dev/tilt/issues/3708
  157. live_update = [
  158. sync("./ethereum/src", "/home/node/app/src"),
  159. ],
  160. )
  161. k8s_yaml_with_ns("devnet/eth-devnet.yaml")
  162. k8s_resource("eth-devnet", port_forwards = [
  163. port_forward(8545, name = "Ganache RPC [:8545]"),
  164. ])
  165. # bigtable
  166. def build_cloud_function(container_name, go_func_name, path, builder):
  167. # Invokes Tilt's custom_build(), with a Pack command.
  168. # inspired by https://github.com/tilt-dev/tilt-extensions/tree/master/pack
  169. caching_ref = container_name + ":tilt-build-pack-caching"
  170. pack_build_cmd = " ".join([
  171. "./tools/bin/pack build",
  172. caching_ref,
  173. "--path " + path,
  174. "--builder " + builder,
  175. "--env " + "GOOGLE_FUNCTION_TARGET=%s" % go_func_name,
  176. "--env " + "GOOGLE_FUNCTION_SIGNATURE_TYPE=http",
  177. ])
  178. if ci:
  179. # inherit the DOCKER_HOST socket provided by custom_build.
  180. pack_build_cmd = pack_build_cmd + " --docker-host inherit"
  181. docker_tag_cmd = "docker tag " + caching_ref + " $EXPECTED_REF"
  182. custom_build(
  183. container_name,
  184. pack_build_cmd + " && " + docker_tag_cmd,
  185. [path],
  186. )
  187. build_cloud_function(
  188. container_name = "cloud-function-readrow",
  189. go_func_name = "ReadRow",
  190. path = "./event_database/cloud_functions",
  191. builder = "gcr.io/buildpacks/builder:v1",
  192. )
  193. local_resource(
  194. name = "pack-bin",
  195. cmd = "go build -mod=readonly -o bin/pack github.com/buildpacks/pack/cmd/pack",
  196. dir = "tools",
  197. )
  198. k8s_yaml_with_ns("devnet/bigtable.yaml")
  199. k8s_resource("bigtable-emulator", port_forwards = [
  200. port_forward(8086, name = "BigTable clients [:8086]"),
  201. ])
  202. k8s_resource(
  203. "bigtable-readrow",
  204. resource_deps = ["proto-gen"],
  205. port_forwards = [port_forward(8090, name = "ReadRow [:8090]")],
  206. )
  207. # explorer web app
  208. docker_build(
  209. ref = "explorer",
  210. context = "./explorer",
  211. dockerfile = "./explorer/Dockerfile",
  212. ignore = ["./explorer/node_modules"],
  213. live_update = [
  214. sync("./explorer/src", "/home/node/app/src"),
  215. sync("./explorer/public", "/home/node/app/public"),
  216. ],
  217. )
  218. k8s_yaml_with_ns("devnet/explorer.yaml")
  219. k8s_resource(
  220. "explorer",
  221. resource_deps = ["proto-gen-web"],
  222. port_forwards = [
  223. port_forward(8001, name = "Explorer Web UI [:8001]"),
  224. ],
  225. )
  226. # terra devnet
  227. docker_build(
  228. ref = "terra-image",
  229. context = "./terra/devnet",
  230. dockerfile = "terra/devnet/Dockerfile",
  231. )
  232. docker_build(
  233. ref = "terra-contracts",
  234. context = "./terra",
  235. dockerfile = "./terra/Dockerfile",
  236. )
  237. k8s_yaml_with_ns("devnet/terra-devnet.yaml")
  238. k8s_resource(
  239. "terra-lcd",
  240. port_forwards = [port_forward(1317, name = "Terra LCD interface [:1317]")],
  241. )
  242. k8s_resource(
  243. "terra-terrad",
  244. port_forwards = [port_forward(26657, name = "Terra RPC [:26657]")],
  245. )
  246. k8s_resource(
  247. "terra-fcd",
  248. port_forwards = [port_forward(3060, name = "Terra FCD [:3060]")],
  249. )