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