flowey_lib_common/
publish_gh_release.rs1use flowey::node::prelude::*;
7
8flowey_request! {
9 pub struct Request(pub GhReleaseParams);
10}
11
12#[derive(Serialize, Deserialize)]
13pub struct GhReleaseParams<C = VarNotClaimed> {
14 pub repo_owner: String,
18 pub repo_name: String,
22 pub tag: ReadVar<String, C>,
24 pub title: ReadVar<String, C>,
26 pub files: ReadVar<Vec<(PathBuf, Option<String>)>, C>,
28 pub draft: bool,
30
31 pub done: WriteVar<SideEffect, C>,
32}
33
34impl GhReleaseParams {
35 pub fn claim(self, ctx: &mut StepCtx<'_>) -> GhReleaseParams<VarClaimed> {
36 let GhReleaseParams {
37 repo_owner,
38 repo_name,
39 tag,
40 title,
41 files,
42 draft,
43 done,
44 } = self;
45
46 GhReleaseParams {
47 repo_owner,
48 repo_name,
49 tag: tag.claim(ctx),
50 title: title.claim(ctx),
51 files: files.claim(ctx),
52 draft,
53 done: done.claim(ctx),
54 }
55 }
56}
57
58new_flow_node!(struct Node);
59
60impl FlowNode for Node {
61 type Request = Request;
62
63 fn imports(ctx: &mut ImportCtx<'_>) {
64 ctx.import::<crate::cache::Node>();
65 ctx.import::<crate::use_gh_cli::Node>();
66 }
67
68 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
69 if requests.is_empty() {
70 return Ok(());
71 }
72
73 let gh_cli = ctx.reqv(crate::use_gh_cli::Request::Get);
74
75 ctx.emit_rust_step("publish github releases", |ctx| {
76 let requests = requests
77 .into_iter()
78 .map(|r| r.0.claim(ctx))
79 .collect::<Vec<_>>();
80 let gh_cli = gh_cli.claim(ctx);
81
82 move |rt| {
83 let gh_cli = rt.read(gh_cli);
84
85 for req in requests {
86 let GhReleaseParams {
87 repo_owner,
88 repo_name,
89 tag,
90 title,
91 files,
92 draft,
93 done: _,
94 } = req;
95
96 let repo = format!("{repo_owner}/{repo_name}");
97 let tag = rt.read(tag);
98
99 let mut command = std::process::Command::new(&gh_cli);
104 command
105 .arg("release").arg("view").arg(&tag).arg("--repo").arg(&repo);
106 let mut child = command.spawn().context(
107 "failed to spawn gh cli"
108 )?;
109 let status = child.wait()?;
110
111 if status.success() {
113 log::info!("GitHub release with tag {tag} already exists in repo {repo}. Skipping...");
114 continue;
115 };
116
117 let title = rt.read(title);
118 let files = rt.read(files)
119 .into_iter()
120 .map(|(path, label)| {
121 let path = path.to_string_lossy().to_string();
122 if let Some(label) = label {
123 format!("{path}#{label}")
124 } else {
125 path
126 }
127 })
128 .collect::<Vec<_>>();
129 let draft = draft.then_some("--draft");
130
131 flowey::shell_cmd!(rt, "{gh_cli} release create --repo {repo} {tag} --title {title} --notes TODO {draft...} {files...}").run()?;
132 }
133
134 Ok(())
135 }
136 });
137
138 Ok(())
139 }
140}