From c3806bac008420db0366b2cb0112f04f47d6f2b5 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Sun, 19 Feb 2023 22:38:36 +0100 Subject: [PATCH] feat(sdk): add documentation strings --- crates/dagger-codegen/src/rust/functions.rs | 81 +++- .../src/rust/templates/object_tmpl.rs | 3 +- crates/dagger-sdk/src/gen.rs | 421 ++++++++++++++++++ 3 files changed, 499 insertions(+), 6 deletions(-) diff --git a/crates/dagger-codegen/src/rust/functions.rs b/crates/dagger-codegen/src/rust/functions.rs index 492210e..7cee7c7 100644 --- a/crates/dagger-codegen/src/rust/functions.rs +++ b/crates/dagger-codegen/src/rust/functions.rs @@ -64,9 +64,11 @@ pub fn format_function(funcs: &CommonFunctions, field: &FullTypeFields) -> Optio .pipe(|t| &t.type_ref) .pipe(|t| render_output_type(funcs, t)); - if let Some((args, true)) = args { + if let Some((args, desc, true)) = args { let required_args = format_required_function_args(funcs, field); Some(quote! { + $(field.description.pipe(|d| format_struct_comment(d))) + $(&desc) $(&signature)( $(required_args) ) -> $(output_type.as_ref()) { @@ -77,6 +79,8 @@ pub fn format_function(funcs: &CommonFunctions, field: &FullTypeFields) -> Optio $(render_execution(funcs, field)) } + $(field.description.pipe(|d| format_struct_comment(d))) + $(&desc) $(&signature)_opts$(lifecycle)( $args ) -> $(output_type) { @@ -90,8 +94,10 @@ pub fn format_function(funcs: &CommonFunctions, field: &FullTypeFields) -> Optio }) } else { Some(quote! { + $(field.description.pipe(|d| format_struct_comment(d))) + $(if let Some((_, desc, _)) = &args => $desc) $(signature)( - $(if let Some((args, _)) = args => $args) + $(if let Some((args, _, _)) = &args => $args) ) -> $(output_type) { let mut query = self.selection.select($(quoted(field.name.as_ref()))); @@ -268,7 +274,8 @@ fn format_function_args( funcs: &CommonFunctions, field: &FullTypeFields, lifecycle: Option<&rust::Tokens>, -) -> Option<(rust::Tokens, bool)> { +) -> Option<(rust::Tokens, rust::Tokens, bool)> { + let mut argument_description = Vec::new(); if let Some(args) = field.args.as_ref() { let args = args .into_iter() @@ -281,6 +288,18 @@ fn format_function_args( let t = funcs.format_input_type(&s.input_value.type_); let n = format_struct_name(&s.input_value.name); + if let Some(desc) = s.input_value.description.as_ref().and_then(|d| { + if d != "" { + Some(write_comment_line(&format!("* `{n}` - {}", d))) + } else { + None + } + }) { + argument_description.push(quote! { + $(desc) + }); + } + Some(quote! { $(n): $(t), }) @@ -294,15 +313,34 @@ fn format_function_args( }; if type_field_has_optional(field) { + let field_name = field_options_struct_name(field); + argument_description.push(quote! { + $(field_name.pipe(|_| write_comment_line(&format!("* `opt` - optional argument, see inner type for documentation, use _opts to use")))) + }); + + let description = quote! { + $(if argument_description.len() > 0 => $(format!("/// "))) + $(if argument_description.len() > 0 => $(format!("/// # Arguments"))) + $(if argument_description.len() > 0 => $(format!("/// "))) + $(for arg_desc in argument_description join ($['\r']) => $arg_desc) + }; + Some(( quote! { $(required_args) - opts: $(field_options_struct_name(field))$(lifecycle) + opts: $(field_name)$(lifecycle) }, + description, true, )) } else { - Some((required_args, false)) + let description = quote! { + $(if argument_description.len() > 0 => $(format!("/// "))) + $(if argument_description.len() > 0 => $(format!("/// # Arguments"))) + $(if argument_description.len() > 0 => $(format!("/// "))) + $(for arg_desc in argument_description join ($['\r']) => $arg_desc) + }; + Some((required_args, description, false)) } } else { None @@ -358,3 +396,36 @@ pub fn format_optional_args( .pipe(|t| render_optional_field_args(funcs, t)) .flatten() } + +pub fn write_comment_line(content: &str) -> Option { + let cnt = content.trim(); + if cnt == "" { + return None; + } + + let mut tokens = rust::Tokens::new(); + + for line in content.split('\n') { + tokens.append(format!("/// {}", line.trim())); + tokens.push(); + } + + Some(tokens) +} + +pub fn format_struct_comment(desc: &str) -> Option { + let lines = desc.trim().split("\n"); + + let formatted_lines = lines + .into_iter() + .map(write_comment_line) + .collect::>(); + + if formatted_lines.len() > 0 { + Some(quote! { + $(for line in formatted_lines join($['\r']) => $line) + }) + } else { + None + } +} diff --git a/crates/dagger-codegen/src/rust/templates/object_tmpl.rs b/crates/dagger-codegen/src/rust/templates/object_tmpl.rs index dc09a3a..c9a998d 100644 --- a/crates/dagger-codegen/src/rust/templates/object_tmpl.rs +++ b/crates/dagger-codegen/src/rust/templates/object_tmpl.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use crate::functions::{type_ref_is_optional, CommonFunctions}; use crate::rust::functions::{ field_options_struct_name, format_function, format_name, format_optional_args, - format_struct_name, + format_struct_comment, format_struct_name, }; use crate::utility::OptionExt; @@ -85,6 +85,7 @@ pub fn render_optional_field_args( contains_lifetime = true; } quote! { + $(a.description.pipe(|d| format_struct_comment(d))) #[builder(setter(into, strip_option))] pub $(format_struct_name(&a.name)): Option<$(type_)>, } diff --git a/crates/dagger-sdk/src/gen.rs b/crates/dagger-sdk/src/gen.rs index 92b0fc8..4c76fff 100644 --- a/crates/dagger-sdk/src/gen.rs +++ b/crates/dagger-sdk/src/gen.rs @@ -49,30 +49,43 @@ pub struct Container { #[derive(Builder, Debug, PartialEq)] pub struct ContainerBuildOpts<'a> { + /// Path to the Dockerfile to use. + /// Defaults to './Dockerfile'. #[builder(setter(into, strip_option))] pub dockerfile: Option<&'a str>, + /// Additional build arguments. #[builder(setter(into, strip_option))] pub build_args: Option>, + /// Target build stage to build. #[builder(setter(into, strip_option))] pub target: Option<&'a str>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerExecOpts<'a> { + /// Command to run instead of the container's default command. #[builder(setter(into, strip_option))] pub args: Option>, + /// Content to write to the command's standard input before closing. #[builder(setter(into, strip_option))] pub stdin: Option<&'a str>, + /// Redirect the command's standard output to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stdout: Option<&'a str>, + /// Redirect the command's standard error to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stderr: Option<&'a str>, + /// Provide dagger access to the executed command. + /// Do not use this option unless you trust the command being executed. + /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. #[builder(setter(into, strip_option))] pub experimental_privileged_nesting: Option, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerExportOpts { + /// Identifiers for other platform specific containers. + /// Used for multi-platform image. #[builder(setter(into, strip_option))] pub platform_variants: Option>, } @@ -85,6 +98,8 @@ pub struct ContainerPipelineOpts<'a> { #[derive(Builder, Debug, PartialEq)] pub struct ContainerPublishOpts { + /// Identifiers for other platform specific containers. + /// Used for multi-platform image. #[builder(setter(into, strip_option))] pub platform_variants: Option>, } @@ -105,12 +120,18 @@ pub struct ContainerWithDirectoryOpts<'a> { #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithExecOpts<'a> { + /// Content to write to the command's standard input before closing. #[builder(setter(into, strip_option))] pub stdin: Option<&'a str>, + /// Redirect the command's standard output to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stdout: Option<&'a str>, + /// Redirect the command's standard error to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stderr: Option<&'a str>, + /// Provide dagger access to the executed command. + /// Do not use this option unless you trust the command being executed. + /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. #[builder(setter(into, strip_option))] pub experimental_privileged_nesting: Option, } @@ -123,8 +144,10 @@ pub struct ContainerWithFileOpts { #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithMountedCacheOpts { + /// Directory to use as the cache volume's root. #[builder(setter(into, strip_option))] pub source: Option, + /// Sharing mode of the cache volume. #[builder(setter(into, strip_option))] pub sharing: Option, } @@ -138,6 +161,12 @@ pub struct ContainerWithNewFileOpts<'a> { } impl Container { + /// Initializes this container from a Dockerfile build, using the context, a dockerfile file path and some additional buildArgs. + /// + /// # Arguments + /// + /// * `context` - Directory context used by the Dockerfile. + /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn build( &self, context: DirectoryId, @@ -153,6 +182,12 @@ impl Container { } } + /// Initializes this container from a Dockerfile build, using the context, a dockerfile file path and some additional buildArgs. + /// + /// # Arguments + /// + /// * `context` - Directory context used by the Dockerfile. + /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn build_opts<'a>( &self, context: DirectoryId, @@ -177,6 +212,7 @@ impl Container { conn: self.conn.clone(), } } + /// Retrieves default arguments for future commands. pub async fn default_args( &self, ) -> eyre::Result> { @@ -184,6 +220,7 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Retrieves a directory at the given path. Mounts are included. pub fn directory( &self, path: impl Into, @@ -198,6 +235,7 @@ impl Container { conn: self.conn.clone(), } } + /// Retrieves entrypoint to be prepended to the arguments of all commands. pub async fn entrypoint( &self, ) -> eyre::Result> { @@ -205,6 +243,7 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Retrieves the value of the specified environment variable. pub async fn env_variable( &self, name: impl Into, @@ -215,6 +254,7 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Retrieves the list of environment variables passed to commands. pub fn env_variables( &self, ) -> Vec { @@ -226,6 +266,11 @@ impl Container { conn: self.conn.clone(), }] } + /// Retrieves this container after executing the specified command inside it. + /// + /// # Arguments + /// + /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn exec( &self, ) -> Container { @@ -238,6 +283,11 @@ impl Container { } } + /// Retrieves this container after executing the specified command inside it. + /// + /// # Arguments + /// + /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn exec_opts<'a>( &self, opts: ContainerExecOpts<'a> @@ -266,6 +316,8 @@ impl Container { conn: self.conn.clone(), } } + /// Exit code of the last executed command. Zero means success. + /// Null if no command has been executed. pub async fn exit_code( &self, ) -> eyre::Result { @@ -273,6 +325,14 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Writes the container as an OCI tarball to the destination file path on the host for the specified platformVariants. + /// Return true on success. + /// + /// # Arguments + /// + /// * `path` - Host's destination path. + /// Path can be relative to the engine's workdir or absolute. + /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub async fn export( &self, path: impl Into, @@ -284,6 +344,14 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Writes the container as an OCI tarball to the destination file path on the host for the specified platformVariants. + /// Return true on success. + /// + /// # Arguments + /// + /// * `path` - Host's destination path. + /// Path can be relative to the engine's workdir or absolute. + /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub async fn export_opts( &self, path: impl Into, @@ -298,6 +366,7 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Retrieves a file at the given path. Mounts are included. pub fn file( &self, path: impl Into, @@ -312,6 +381,12 @@ impl Container { conn: self.conn.clone(), } } + /// Initializes this container from the base image published at the given address. + /// + /// # Arguments + /// + /// * `address` - Image's address from its registry. + /// Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). pub fn from( &self, address: impl Into, @@ -326,6 +401,7 @@ impl Container { conn: self.conn.clone(), } } + /// Retrieves this container's root filesystem. Mounts are not included. pub fn fs( &self, ) -> Directory { @@ -337,6 +413,7 @@ impl Container { conn: self.conn.clone(), } } + /// A unique identifier for this container. pub async fn id( &self, ) -> eyre::Result { @@ -344,6 +421,7 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Retrieves the value of the specified label. pub async fn label( &self, name: impl Into, @@ -354,6 +432,7 @@ impl Container { query.execute(&graphql_client(&self.conn)).await } + /// Retrieves the list of labels passed to container. pub fn labels( &self, ) -> Vec