flowey_lib_common/
download_gh_artifact.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Download a github release artifact
5
6use flowey::node::prelude::*;
7
8flowey_request! {
9    pub struct Request {
10        /// First component of a github repo path
11        ///
12        /// e.g: the "foo" in "github.com/foo/bar"
13        pub repo_owner: String,
14        /// Second component of a github repo path
15        ///
16        /// e.g: the "bar" in "github.com/foo/bar"
17        pub repo_name: String,
18        /// Specific artifact to download.
19        pub file_name: String,
20        /// Path to downloaded artifact.
21        pub path: WriteVar<PathBuf>,
22        /// The Github actions run id to download artifacts from
23        pub run_id: ReadVar<String>,
24        /// Github token to authenticate with
25        pub gh_token: ReadVar<String>,
26    }
27}
28
29new_simple_flow_node!(struct Node);
30
31impl SimpleFlowNode for Node {
32    type Request = Request;
33
34    fn imports(ctx: &mut ImportCtx<'_>) {
35        ctx.import::<crate::cache::Node>();
36        ctx.import::<crate::use_gh_cli::Node>();
37    }
38
39    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40        let Request {
41            repo_owner,
42            repo_name,
43            file_name,
44            path,
45            run_id,
46            gh_token,
47        } = request;
48
49        ctx.req(crate::use_gh_cli::Request::WithAuth(
50            crate::use_gh_cli::GhCliAuth::AuthToken(gh_token),
51        ));
52        let gh_cli = ctx.reqv(crate::use_gh_cli::Request::Get);
53
54        ctx.emit_rust_step("download artifacts from github actions run", |ctx| {
55            let gh_cli = gh_cli.claim(ctx);
56            let run_id = run_id.claim(ctx);
57            let path = path.claim(ctx);
58            move |rt| {
59                let sh = xshell::Shell::new()?;
60                let gh_cli = rt.read(gh_cli);
61                let run_id = rt.read(run_id);
62
63                let path_end = format!("{repo_owner}/{repo_name}/{run_id}");
64                let out_dir = std::env::current_dir()?.absolute()?.join(path_end);
65                fs_err::create_dir_all(&out_dir)?;
66                sh.change_dir(&out_dir);
67
68                xshell::cmd!(sh, "{gh_cli} run download {run_id} -R {repo_owner}/{repo_name} --pattern {file_name}").run()?;
69
70                if !out_dir.join(file_name).exists() {
71                    anyhow::bail!("Failed to download artifact");
72                }
73
74                rt.write(path, &out_dir);
75                Ok(())
76            }
77        });
78
79        Ok(())
80    }
81}