flowey_lib_hvlite/_jobs/
consolidate_and_publish_gh_pages.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Consolidate various pre-built HTML artifacts (guide, docs, etc...), and glue
5//! them together into a single HTML bundle which can be published to
6//! `openvmm.dev` via gh pages.
7
8use crate::build_guide::GuideOutput;
9use crate::build_rustdoc::RustdocOutput;
10use flowey::node::prelude::*;
11
12flowey_request! {
13    pub struct Params {
14        pub rustdoc_linux: ReadVar<RustdocOutput>,
15        pub rustdoc_windows: ReadVar<RustdocOutput>,
16        pub guide: ReadVar<GuideOutput>,
17        pub output: WriteVar<GhPagesOutput>,
18    }
19}
20
21#[derive(Serialize, Deserialize)]
22pub struct GhPagesOutput {
23    pub gh_pages: PathBuf,
24}
25
26impl Artifact for GhPagesOutput {}
27
28new_simple_flow_node!(struct Node);
29
30impl SimpleFlowNode for Node {
31    type Request = Params;
32
33    fn imports(ctx: &mut ImportCtx<'_>) {
34        ctx.import::<flowey_lib_common::copy_to_artifact_dir::Node>();
35        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
36    }
37
38    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
39        let Params {
40            rustdoc_linux,
41            rustdoc_windows,
42            guide: rendered_guide,
43            output,
44        } = request;
45
46        let repo = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
47
48        let consolidated_html = ctx.emit_rust_stepv("generate consolidated gh pages html", |ctx| {
49            let rendered_guide = rendered_guide.claim(ctx);
50            let rustdoc_windows = rustdoc_windows.claim(ctx);
51            let rustdoc_linux = rustdoc_linux.claim(ctx);
52            let repo = repo.claim(ctx);
53            |rt| {
54                let rendered_guide = rt.read(rendered_guide);
55                let rustdoc_windows = rt.read(rustdoc_windows);
56                let rustdoc_linux = rt.read(rustdoc_linux);
57                let repo = rt.read(repo);
58
59                let consolidated_html = std::env::current_dir()?.join("out").absolute()?;
60                fs_err::create_dir(&consolidated_html)?;
61
62                // DEVNOTE: Please try to keep this top-level structure stable!
63                //
64                // As the project grows, its quite likely more external websites
65                // will be linking to specific pages under `openvmm.dev`. Lets
66                // do our best to avoid linkrot, and if we are moving things
67                // around, lets make sure to add appropriate redirects whenever
68                // we can.
69
70                // Make the OpenVMM Guide accessible under `openvmm.dev/guide/`
71                flowey_lib_common::_util::copy_dir_all(
72                    rendered_guide.guide,
73                    consolidated_html.join("guide"),
74                )?;
75
76                // Make rustdocs accessible under `openvmm.dev/rustdoc/{platform}`
77                flowey_lib_common::_util::copy_dir_all(
78                    rustdoc_windows.docs,
79                    consolidated_html.join("rustdoc/windows"),
80                )?;
81                flowey_lib_common::_util::copy_dir_all(
82                    rustdoc_linux.docs,
83                    consolidated_html.join("rustdoc/linux"),
84                )?;
85
86                // Make petri logview available under `openvmm.dev/test-results/`
87                flowey_lib_common::_util::copy_dir_all(
88                    repo.join("petri/logview"),
89                    consolidated_html.join("test-results"),
90                )?;
91
92                // Make petri logview available under
93                // `openvmm.dev/test-results-new/` Will move to `test-results`
94                // after getting usage feedback.
95                flowey_lib_common::_util::copy_dir_all(
96                    repo.join("petri/logview_new/dist"),
97                    consolidated_html.join("test-results-new"),
98                )?;
99
100                // as we do not currently have any form of "landing page",
101                // redirect `openvmm.dev` to `openvmm.dev/guide`
102                fs_err::write(consolidated_html.join("index.html"), REDIRECT)?;
103
104                Ok(consolidated_html)
105            }
106        });
107
108        let consolidated_html = if matches!(ctx.backend(), FlowBackend::Github) {
109            let did_upload = ctx
110                .emit_gh_step("Upload pages artifact", "actions/upload-pages-artifact@v3")
111                .with(
112                    "path",
113                    consolidated_html.map(ctx, |x| x.display().to_string()),
114                )
115                .finish(ctx);
116
117            let did_deploy = ctx
118                .emit_gh_step("Deploy to GitHub Pages", "actions/deploy-pages@v4")
119                .requires_permission(GhPermission::IdToken, GhPermissionValue::Write)
120                .requires_permission(GhPermission::Pages, GhPermissionValue::Write)
121                .run_after(did_upload)
122                .finish(ctx);
123
124            consolidated_html.depending_on(ctx, &did_deploy)
125        } else {
126            consolidated_html
127        };
128
129        consolidated_html.write_into(ctx, output, |p| GhPagesOutput { gh_pages: p });
130        Ok(())
131    }
132}
133
134const REDIRECT: &str = r#"
135<!DOCTYPE html>
136<html>
137<head>
138    <title>Redirecting...</title>
139    <link rel="canonical" href="/guide"/>
140    <meta charset="utf-8"/>
141    <meta http-equiv="refresh" content="0; url=/guide">
142</head>
143<body>
144    <p>If you are not redirected automatically, follow this <a href="/guide">link to openvmm.dev/guide</a>.</p>
145</body>
146</html>
147"#;