tracel_xtask/commands/
doc.rs

1use anyhow::Ok;
2use strum::IntoEnumIterator;
3
4use crate::{
5    commands::WARN_IGNORED_ONLY_ARGS,
6    endgroup, group,
7    prelude::{Context, Environment},
8    utils::{
9        process::{run_process_for_package, run_process_for_workspace},
10        workspace::{get_workspace_members, WorkspaceMember, WorkspaceMemberType},
11    },
12};
13
14use super::Target;
15
16#[tracel_xtask_macros::declare_command_args(Target, DocSubCommand)]
17pub struct DocCmdArgs {}
18
19pub fn handle_command(args: DocCmdArgs, _env: Environment, _ctx: Context) -> anyhow::Result<()> {
20    if args.target == Target::Workspace && !args.only.is_empty() {
21        warn!("{WARN_IGNORED_ONLY_ARGS}");
22    }
23    match args.get_command() {
24        DocSubCommand::Build => run_documentation_build(&args.target, &args.exclude, &args.only),
25        DocSubCommand::Tests => run_documentation(&args.target, &args.exclude, &args.only),
26    }
27}
28
29fn run_documentation_build(
30    target: &Target,
31    excluded: &Vec<String>,
32    only: &Vec<String>,
33) -> anyhow::Result<()> {
34    match target {
35        Target::Workspace => {
36            group!("Build Workspace documentation");
37            run_process_for_workspace(
38                "cargo",
39                &["doc", "--workspace", "--no-deps", "--color=always"],
40                excluded,
41                None,
42                None,
43                "Workspace documentation build failed",
44                None,
45                None,
46            )?;
47            endgroup!();
48        }
49        Target::Crates | Target::Examples => {
50            let members = match target {
51                Target::Crates => get_workspace_members(WorkspaceMemberType::Crate),
52                Target::Examples => get_workspace_members(WorkspaceMemberType::Example),
53                _ => unreachable!(),
54            };
55
56            for member in members {
57                group!("Doc Build: {}", member.name);
58                run_process_for_package(
59                    "cargo",
60                    &member.name,
61                    &["doc", "-p", &member.name, "--no-deps", "--color=always"],
62                    excluded,
63                    only,
64                    &format!("Format check execution failed for {}", &member.name),
65                    None,
66                    None,
67                )?;
68                endgroup!();
69            }
70        }
71        Target::AllPackages => {
72            Target::iter()
73                .filter(|t| *t != Target::AllPackages && *t != Target::Workspace)
74                .try_for_each(|t| run_documentation_build(&t, excluded, only))?;
75        }
76    }
77    Ok(())
78}
79
80pub(crate) fn run_documentation(
81    target: &Target,
82    excluded: &[String],
83    only: &[String],
84) -> anyhow::Result<()> {
85    match target {
86        Target::Workspace => {
87            group!("Workspace Documentation Tests");
88            run_process_for_workspace(
89                "cargo",
90                &["test", "--workspace", "--doc", "--color", "always"],
91                excluded,
92                Some(r"Doc-tests (\w+)"),
93                Some("Doc Tests"),
94                "Workspace documentation test failed",
95                None,
96                None,
97            )?;
98            endgroup!();
99        }
100        Target::Crates | Target::Examples => {
101            let members = match target {
102                Target::Crates => get_workspace_members(WorkspaceMemberType::Crate),
103                Target::Examples => get_workspace_members(WorkspaceMemberType::Example),
104                _ => unreachable!(),
105            };
106
107            for member in members {
108                run_doc_test(&member, excluded, only)?;
109            }
110        }
111        Target::AllPackages => {
112            Target::iter()
113                .filter(|t| *t != Target::AllPackages && *t != Target::Workspace)
114                .try_for_each(|t| run_documentation(&t, excluded, only))?;
115        }
116    }
117    Ok(())
118}
119
120fn run_doc_test(
121    member: &WorkspaceMember,
122    excluded: &[String],
123    only: &[String],
124) -> Result<(), anyhow::Error> {
125    group!("Doc Tests: {}", member.name);
126    run_process_for_package(
127        "cargo",
128        &member.name,
129        &["test", "--doc", "-p", &member.name],
130        excluded,
131        only,
132        &format!(
133            "Failed to execute documentation test for '{}'",
134            &member.name
135        ),
136        Some("no library targets found"),
137        Some(&format!(
138            "No library found to test documentation for in the crate '{}'",
139            &member.name
140        )),
141    )?;
142    endgroup!();
143    Ok(())
144}