flowey_lib_common/
download_gh_cli.rs1use crate::cache::CacheHit;
10use flowey::node::prelude::*;
11
12flowey_request! {
13 pub enum Request {
14 Version(String),
16 Get(WriteVar<PathBuf>),
18 }
19}
20
21new_flow_node!(struct Node);
22
23impl FlowNode for Node {
24 type Request = Request;
25
26 fn imports(ctx: &mut ImportCtx<'_>) {
27 ctx.import::<crate::install_dist_pkg::Node>();
28 ctx.import::<crate::cache::Node>();
29 }
30
31 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
32 let mut version = None;
33 let mut install_reqs = Vec::new();
34
35 for req in requests {
36 match req {
37 Request::Version(v) => same_across_all_reqs("Version", &mut version, v)?,
38 Request::Get(v) => install_reqs.push(v),
39 }
40 }
41
42 let version = version.ok_or(anyhow::anyhow!("Missing essential request: Version"))?;
43 let install_reqs = install_reqs;
44
45 if install_reqs.is_empty() {
48 return Ok(());
49 }
50
51 let gh_bin = ctx.platform().binary("gh");
52
53 let gh_arch = match ctx.arch() {
54 FlowArch::X86_64 => "amd64",
55 FlowArch::Aarch64 => "arm64",
56 arch => anyhow::bail!("unsupported architecture {arch}"),
57 };
58
59 let cache_dir = ctx.emit_rust_stepv("create gh cache dir", |_| {
60 |_| Ok(std::env::current_dir()?.absolute()?)
61 });
62
63 let cache_key = ReadVar::from_static(format!("gh-cli-{version}"));
64 let hitvar = ctx.reqv(|hitvar| crate::cache::Request {
65 label: "gh-cli".into(),
66 dir: cache_dir.clone(),
67 key: cache_key,
68 restore_keys: None,
69 hitvar,
70 });
71
72 ctx.emit_rust_step("installing gh", |ctx| {
73 let cache_dir = cache_dir.claim(ctx);
74 let hitvar = hitvar.claim(ctx);
75 let install_reqs = install_reqs.claim(ctx);
76 move |rt| {
77 let cache_dir = rt.read(cache_dir);
78
79 let cached = if matches!(rt.read(hitvar), CacheHit::Hit) {
80 let cached_bin = cache_dir.join(&gh_bin);
81 assert!(cached_bin.exists());
82 Some(cached_bin)
83 } else {
84 None
85 };
86
87 let path_to_gh = if let Some(cached) = cached {
88 cached
89 } else {
90 let sh = xshell::Shell::new()?;
91 match rt.platform() {
92 FlowPlatform::Windows => {
93 xshell::cmd!(sh, "curl --fail -L https://github.com/cli/cli/releases/download/v{version}/gh_{version}_windows_{gh_arch}.zip -o gh.zip").run()?;
94 xshell::cmd!(sh, "tar -xf gh.zip").run()?;
95 },
96 FlowPlatform::Linux(_) => {
97 xshell::cmd!(sh, "curl --fail -L https://github.com/cli/cli/releases/download/v{version}/gh_{version}_linux_{gh_arch}.tar.gz -o gh.tar.gz").run()?;
98 xshell::cmd!(sh, "tar -xf gh.tar.gz --strip-components=1").run()?;
99 },
100 FlowPlatform::MacOs => {
101 xshell::cmd!(sh, "curl --fail -L https://github.com/cli/cli/releases/download/v{version}/gh_{version}_macOS_{gh_arch}.zip -o gh.zip").run()?;
102 xshell::cmd!(sh, "tar -xf gh.zip --strip-components=1").run()?;
103 }
104 platform => anyhow::bail!("unsupported platform {platform}"),
105 };
106
107 let final_bin = cache_dir.join(&gh_bin);
109 fs_err::rename(format!("bin/{gh_bin}"), &final_bin)?;
110
111 final_bin.absolute()?
112 };
113
114 for var in install_reqs {
115 rt.write(var, &path_to_gh)
116 }
117
118 Ok(())
119 }
120 });
121
122 Ok(())
123 }
124}