feat: with dagger-engine v.0.4.0

This commit is contained in:
Kasper Juul Hermansen 2023-03-10 23:16:35 +01:00
parent 04934e8293
commit 08c9c741df
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
4 changed files with 107 additions and 16 deletions

4
Makefile.toml Normal file
View File

@ -0,0 +1,4 @@
[tasks.codegen]
command = "cargo"
args = ["run", "-p", "ci", "--", "codegen"]
workspace = false

View File

@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use clap::ArgMatches;
use dagger_sdk::{Container, HostDirectoryOpts, Query}; use dagger_sdk::{Container, HostDirectoryOpts, Query};
#[tokio::main] #[tokio::main]
@ -10,6 +11,7 @@ async fn main() -> eyre::Result<()> {
.subcommand_required(true) .subcommand_required(true)
.subcommand(clap::Command::new("pr")) .subcommand(clap::Command::new("pr"))
.subcommand(clap::Command::new("release")) .subcommand(clap::Command::new("release"))
.subcommand(clap::Command::new("codegen"))
.get_matches(); .get_matches();
let client = dagger_sdk::connect().await?; let client = dagger_sdk::connect().await?;
@ -20,6 +22,7 @@ async fn main() -> eyre::Result<()> {
return validate_pr(client, base).await; return validate_pr(client, base).await;
} }
Some(("release", subm)) => return release(client, subm).await, Some(("release", subm)) => return release(client, subm).await,
Some(("codegen", subm)) => return run_codegen(client, subm).await,
Some(_) => { Some(_) => {
panic!("invalid subcommand selected!") panic!("invalid subcommand selected!")
} }
@ -29,6 +32,41 @@ async fn main() -> eyre::Result<()> {
} }
} }
async fn run_codegen(client: Arc<Query>, _subm: &ArgMatches) -> eyre::Result<()> {
let docker_cli = client
.container()
.from("docker:cli")
.file("/usr/local/bin/docker");
let socket = client.host().unix_socket("/var/run/docker.sock");
let container = get_dependencies(client).await?;
let generated_image = container
.with_exec(vec!["mkdir", "-p", "/mnt/output"])
.with_mounted_file("/usr/bin/docker", docker_cli.id().await?)
.with_unix_socket("/var/run/docker.sock", socket.id().await?)
.with_exec(vec![
"cargo",
"run",
"--",
"generate",
"--output",
"crates/dagger-sdk/gen.rs",
])
.with_exec(vec!["cargo", "fmt", "--all"])
.with_exec(vec!["cargo", "fix", "--workspace", "--allow-dirty"])
.with_exec(vec!["mv", "crates/dagger-sdk/gen.rs", "/mnt/output/gen.rs"]);
let _ = generated_image.exit_code().await?;
generated_image
.file("/mnt/output/gen.rs")
.export("crates/dagger-sdk/src/gen.rs")
.await?;
Ok(())
}
async fn release(client: Arc<Query>, _subm: &clap::ArgMatches) -> Result<(), color_eyre::Report> { async fn release(client: Arc<Query>, _subm: &clap::ArgMatches) -> Result<(), color_eyre::Report> {
let src_dir = client.host().directory_opts( let src_dir = client.host().directory_opts(
".", ".",
@ -87,14 +125,14 @@ async fn get_dependencies(client: Arc<Query>) -> eyre::Result<Container> {
); );
let cache_cargo_index_dir = client.cache_volume("cargo_index"); let cache_cargo_index_dir = client.cache_volume("cargo_index");
let cache_cargo_deps = client.cache_volume("cargo_deps"); let _cache_cargo_deps = client.cache_volume("cargo_deps");
let cache_cargo_bin = client.cache_volume("cargo_bin_cache"); let cache_cargo_bin = client.cache_volume("cargo_bin_cache");
let minio_url = "https://github.com/mozilla/sccache/releases/download/v0.3.3/sccache-v0.3.3-x86_64-unknown-linux-musl.tar.gz"; let minio_url = "https://github.com/mozilla/sccache/releases/download/v0.3.3/sccache-v0.3.3-x86_64-unknown-linux-musl.tar.gz";
let base_image = client let base_image = client
.container() .container()
.from("rust:latest") .from("rustlang/rust:nightly")
.with_workdir("app") .with_workdir("app")
.with_exec(vec!["apt-get", "update"]) .with_exec(vec!["apt-get", "update"])
.with_exec(vec!["apt-get", "install", "--yes", "libpq-dev", "wget"]) .with_exec(vec!["apt-get", "install", "--yes", "libpq-dev", "wget"])
@ -110,7 +148,7 @@ async fn get_dependencies(client: Arc<Query>) -> eyre::Result<Container> {
"/usr/local/bin/sccache", "/usr/local/bin/sccache",
]) ])
.with_exec(vec!["chmod", "+x", "/usr/local/bin/sccache"]) .with_exec(vec!["chmod", "+x", "/usr/local/bin/sccache"])
.with_env_variable("RUSTC_WRAPPER", "/usr/local/bin/sccache") //.with_env_variable("RUSTC_WRAPPER", "/usr/local/bin/sccache")
.with_env_variable( .with_env_variable(
"AWS_ACCESS_KEY_ID", "AWS_ACCESS_KEY_ID",
std::env::var("AWS_ACCESS_KEY_ID").unwrap_or("".into()), std::env::var("AWS_ACCESS_KEY_ID").unwrap_or("".into()),
@ -152,8 +190,7 @@ async fn get_dependencies(client: Arc<Query>) -> eyre::Result<Container> {
"--recipe-path", "--recipe-path",
"recipe.json", "recipe.json",
]) ])
.with_mounted_cache("/app/", cache_cargo_deps.id().await?) .with_directory("/app/", src_dir.id().await?)
.with_mounted_directory("/app/", src_dir.id().await?)
.with_exec(vec!["cargo", "build", "--all", "--release"]); .with_exec(vec!["cargo", "build", "--all", "--release"]);
return Ok(builder_start); return Ok(builder_start);

View File

@ -25,6 +25,11 @@ pub struct BuildArg {
pub name: String, pub name: String,
pub value: String, pub value: String,
} }
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct PipelineLabel {
pub value: String,
pub name: String,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CacheVolume { pub struct CacheVolume {
pub proc: Arc<Child>, pub proc: Arc<Child>,
@ -97,8 +102,12 @@ pub struct ContainerExportOpts {
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct ContainerPipelineOpts<'a> { pub struct ContainerPipelineOpts<'a> {
/// Pipeline description.
#[builder(setter(into, strip_option), default)] #[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>, pub description: Option<&'a str>,
/// Pipeline labels.
#[builder(setter(into, strip_option), default)]
pub labels: Option<Vec<PipelineLabel>>,
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct ContainerPublishOpts { pub struct ContainerPublishOpts {
@ -138,6 +147,12 @@ pub struct ContainerWithExecOpts<'a> {
/// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM.
#[builder(setter(into, strip_option), default)] #[builder(setter(into, strip_option), default)]
pub experimental_privileged_nesting: Option<bool>, pub experimental_privileged_nesting: Option<bool>,
/// Execute the command with all root capabilities. This is similar to running a command
/// with "sudo" or executing `docker run` with the `--privileged` flag. Containerization
/// does not provide any security guarantees when using this option. It should only be used
/// when absolutely necessary and only with trusted commands.
#[builder(setter(into, strip_option), default)]
pub insecure_root_capabilities: Option<bool>,
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithExposedPortOpts<'a> { pub struct ContainerWithExposedPortOpts<'a> {
@ -252,6 +267,7 @@ impl Container {
/// Retrieves an endpoint that clients can use to reach this container. /// Retrieves an endpoint that clients can use to reach this container.
/// If no port is specified, the first exposed port is used. If none exist an error is returned. /// If no port is specified, the first exposed port is used. If none exist an error is returned.
/// If a scheme is specified, a URL is returned. Otherwise, a host:port pair is returned. /// If a scheme is specified, a URL is returned. Otherwise, a host:port pair is returned.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -265,6 +281,7 @@ impl Container {
/// Retrieves an endpoint that clients can use to reach this container. /// Retrieves an endpoint that clients can use to reach this container.
/// If no port is specified, the first exposed port is used. If none exist an error is returned. /// If no port is specified, the first exposed port is used. If none exist an error is returned.
/// If a scheme is specified, a URL is returned. Otherwise, a host:port pair is returned. /// If a scheme is specified, a URL is returned. Otherwise, a host:port pair is returned.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -358,7 +375,7 @@ impl Container {
}; };
} }
/// Exit code of the last executed command. Zero means success. /// Exit code of the last executed command. Zero means success.
/// Null if no command has been executed. /// Errors if no command has been executed.
pub async fn exit_code(&self) -> eyre::Result<isize> { pub async fn exit_code(&self) -> eyre::Result<isize> {
let query = self.selection.select("exitCode"); let query = self.selection.select("exitCode");
@ -404,7 +421,8 @@ impl Container {
query.execute(&graphql_client(&self.conn)).await query.execute(&graphql_client(&self.conn)).await
} }
/// Retrieves the list of exposed ports /// Retrieves the list of exposed ports.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
pub fn exposed_ports(&self) -> Vec<Port> { pub fn exposed_ports(&self) -> Vec<Port> {
let query = self.selection.select("exposedPorts"); let query = self.selection.select("exposedPorts");
@ -460,6 +478,7 @@ impl Container {
}; };
} }
/// Retrieves a hostname which can be used by clients to reach this container. /// Retrieves a hostname which can be used by clients to reach this container.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
pub async fn hostname(&self) -> eyre::Result<String> { pub async fn hostname(&self) -> eyre::Result<String> {
let query = self.selection.select("hostname"); let query = self.selection.select("hostname");
@ -505,6 +524,7 @@ impl Container {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use /// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline(&self, name: impl Into<String>) -> Container { pub fn pipeline(&self, name: impl Into<String>) -> Container {
let mut query = self.selection.select("pipeline"); let mut query = self.selection.select("pipeline");
@ -522,6 +542,7 @@ impl Container {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use /// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline_opts<'a>( pub fn pipeline_opts<'a>(
&self, &self,
@ -534,6 +555,9 @@ impl Container {
if let Some(description) = opts.description { if let Some(description) = opts.description {
query = query.arg("description", description); query = query.arg("description", description);
} }
if let Some(labels) = opts.labels {
query = query.arg("labels", labels);
}
return Container { return Container {
proc: self.proc.clone(), proc: self.proc.clone(),
@ -600,14 +624,14 @@ impl Container {
}; };
} }
/// The error stream of the last executed command. /// The error stream of the last executed command.
/// Null if no command has been executed. /// Errors if no command has been executed.
pub async fn stderr(&self) -> eyre::Result<String> { pub async fn stderr(&self) -> eyre::Result<String> {
let query = self.selection.select("stderr"); let query = self.selection.select("stderr");
query.execute(&graphql_client(&self.conn)).await query.execute(&graphql_client(&self.conn)).await
} }
/// The output stream of the last executed command. /// The output stream of the last executed command.
/// Null if no command has been executed. /// Errors if no command has been executed.
pub async fn stdout(&self) -> eyre::Result<String> { pub async fn stdout(&self) -> eyre::Result<String> {
let query = self.selection.select("stdout"); let query = self.selection.select("stdout");
@ -796,6 +820,9 @@ impl Container {
experimental_privileged_nesting, experimental_privileged_nesting,
); );
} }
if let Some(insecure_root_capabilities) = opts.insecure_root_capabilities {
query = query.arg("insecureRootCapabilities", insecure_root_capabilities);
}
return Container { return Container {
proc: self.proc.clone(), proc: self.proc.clone(),
@ -807,6 +834,7 @@ impl Container {
/// Exposed ports serve two purposes: /// Exposed ports serve two purposes:
/// - For health checks and introspection, when running services /// - For health checks and introspection, when running services
/// - For setting the EXPOSE OCI field when publishing the container /// - For setting the EXPOSE OCI field when publishing the container
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -828,6 +856,7 @@ impl Container {
/// Exposed ports serve two purposes: /// Exposed ports serve two purposes:
/// - For health checks and introspection, when running services /// - For health checks and introspection, when running services
/// - For setting the EXPOSE OCI field when publishing the container /// - For setting the EXPOSE OCI field when publishing the container
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -1159,6 +1188,7 @@ impl Container {
/// Establish a runtime dependency on a service. The service will be started automatically when needed and detached when it is no longer needed. /// Establish a runtime dependency on a service. The service will be started automatically when needed and detached when it is no longer needed.
/// The service will be reachable from the container via the provided hostname alias. /// The service will be reachable from the container via the provided hostname alias.
/// The service dependency will also convey to any files or directories produced by the container. /// The service dependency will also convey to any files or directories produced by the container.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -1247,6 +1277,7 @@ impl Container {
}; };
} }
/// Unexpose a previously exposed port. /// Unexpose a previously exposed port.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -1265,6 +1296,7 @@ impl Container {
} }
/// Unexpose a previously exposed port. /// Unexpose a previously exposed port.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -1391,8 +1423,12 @@ pub struct DirectoryEntriesOpts<'a> {
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct DirectoryPipelineOpts<'a> { pub struct DirectoryPipelineOpts<'a> {
/// Pipeline description.
#[builder(setter(into, strip_option), default)] #[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>, pub description: Option<&'a str>,
/// Pipeline labels.
#[builder(setter(into, strip_option), default)]
pub labels: Option<Vec<PipelineLabel>>,
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct DirectoryWithDirectoryOpts<'a> { pub struct DirectoryWithDirectoryOpts<'a> {
@ -1574,10 +1610,11 @@ impl Directory {
conn: self.conn.clone(), conn: self.conn.clone(),
}; };
} }
/// Creates a named sub-pipeline. /// Creates a named sub-pipeline
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use /// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline(&self, name: impl Into<String>) -> Directory { pub fn pipeline(&self, name: impl Into<String>) -> Directory {
let mut query = self.selection.select("pipeline"); let mut query = self.selection.select("pipeline");
@ -1591,10 +1628,11 @@ impl Directory {
}; };
} }
/// Creates a named sub-pipeline. /// Creates a named sub-pipeline
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use /// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline_opts<'a>( pub fn pipeline_opts<'a>(
&self, &self,
@ -1607,6 +1645,9 @@ impl Directory {
if let Some(description) = opts.description { if let Some(description) = opts.description {
query = query.arg("description", description); query = query.arg("description", description);
} }
if let Some(labels) = opts.labels {
query = query.arg("labels", labels);
}
return Directory { return Directory {
proc: self.proc.clone(), proc: self.proc.clone(),
@ -2370,8 +2411,12 @@ pub struct QueryHttpOpts {
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct QueryPipelineOpts<'a> { pub struct QueryPipelineOpts<'a> {
/// Pipeline description.
#[builder(setter(into, strip_option), default)] #[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>, pub description: Option<&'a str>,
/// Pipeline labels.
#[builder(setter(into, strip_option), default)]
pub labels: Option<Vec<PipelineLabel>>,
} }
#[derive(Builder, Debug, PartialEq)] #[derive(Builder, Debug, PartialEq)]
pub struct QuerySocketOpts { pub struct QuerySocketOpts {
@ -2582,10 +2627,11 @@ impl Query {
conn: self.conn.clone(), conn: self.conn.clone(),
}; };
} }
/// Creates a named sub-pipeline /// Creates a named sub-pipeline.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use /// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline(&self, name: impl Into<String>) -> Query { pub fn pipeline(&self, name: impl Into<String>) -> Query {
let mut query = self.selection.select("pipeline"); let mut query = self.selection.select("pipeline");
@ -2599,10 +2645,11 @@ impl Query {
}; };
} }
/// Creates a named sub-pipeline /// Creates a named sub-pipeline.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use /// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline_opts<'a>(&self, name: impl Into<String>, opts: QueryPipelineOpts<'a>) -> Query { pub fn pipeline_opts<'a>(&self, name: impl Into<String>, opts: QueryPipelineOpts<'a>) -> Query {
let mut query = self.selection.select("pipeline"); let mut query = self.selection.select("pipeline");
@ -2611,6 +2658,9 @@ impl Query {
if let Some(description) = opts.description { if let Some(description) = opts.description {
query = query.arg("description", description); query = query.arg("description", description);
} }
if let Some(labels) = opts.labels {
query = query.arg("labels", labels);
}
return Query { return Query {
proc: self.proc.clone(), proc: self.proc.clone(),
@ -2714,12 +2764,12 @@ impl Socket {
} }
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub enum CacheSharingMode { pub enum CacheSharingMode {
LOCKED,
SHARED, SHARED,
PRIVATE, PRIVATE,
LOCKED,
} }
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub enum NetworkProtocol { pub enum NetworkProtocol {
UDP,
TCP, TCP,
UDP,
} }

View File

@ -1,4 +1,4 @@
use dagger_sdk::{connect, ContainerExecOpts, ContainerExecOptsBuilder}; use dagger_sdk::{connect, ContainerExecOptsBuilder};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
#[tokio::test] #[tokio::test]