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