Compare commits

...

21 Commits

Author SHA1 Message Date
c3a43d1a80 fix: make sure tests have a command to execute 2023-03-13 20:59:25 +01:00
01f807b150 fix: remove unused imports 2023-03-13 20:47:23 +01:00
cbdac7fef5 refactor: remove export and instead use exitcode 2023-03-13 20:46:53 +01:00
1f26415759 refactor: move issues to actual tests and refactor 2023-03-13 20:44:56 +01:00
471caf276b fix: add support for String as well 2023-03-13 20:33:24 +01:00
e3579a35e0 refactor: move issues to another folder 2023-03-13 20:27:05 +01:00
5bc517e68f fix: add public tuple field and into func 2023-03-13 20:26:13 +01:00
deda62253e replication(issue-30): initial issue 2023-03-13 20:12:58 +01:00
Renovate Bot
44fa0240f8 fix(deps): update rust crate futures to 0.3.27 2023-03-11 18:21:37 +01:00
62de24153a docs: add basic contributing 2023-03-10 23:49:26 +01:00
9513bb5653 docs: add architecture 2023-03-10 23:46:12 +01:00
6b43d5bc36 fix: proper readme 2023-03-10 23:44:36 +01:00
f390eac29f Release dagger-core v0.2.8, dagger-sdk v0.2.16 2023-03-10 23:40:02 +01:00
e642778d90 chore: fix tasks 2023-03-10 23:39:23 +01:00
7133bfae95 feat: with dagger-engine v.0.4.0 2023-03-10 23:27:15 +01:00
41b20b6268 feat: bump version 2023-03-10 23:27:15 +01:00
13b7805e7e docs(sdk): fix missing await in connect 2023-02-25 02:42:34 +01:00
4381af0295 feat: add tests to sdk 2023-02-25 02:33:30 +01:00
5f9b3a19c0 feat: set internal warnings as errors 2023-02-25 02:01:13 +01:00
f9e7af931d feat: introduce tests again 2023-02-25 01:47:57 +01:00
ecca036bc6 fix(sdk): fix builder pattern to actually work with default values
In previous versions the builder pattern required all values to be set.
This has not been fixed, so that default values are allowed.
2023-02-25 01:47:57 +01:00
28 changed files with 624 additions and 194 deletions

12
ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,12 @@
# Architecture
- `.` Root project mainly used for generating the CLI, which in turn is used to
bootstrap the code generation from `dagger`
- `crates/dagger-core` Contains all base types used during actual usage. This is
where the primary logic lives in which the user interacts (\*disclaimer: most
stuff haven't moved in here yet.)
- `crates/dagger-sdk` Contains the actual sdk in which the user interacts,
`dagger-core` is reexported through this API as well.
- `crates/dagger-codegen` This is the bulk of the work, it takes the input
graphql and spits out the API in which the user interacts, this is heavily
inspired by other `dagger-sdk's`. It primarily turns graphql into rust code.

11
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,11 @@
# Contributing
The sdk is still quite young, so feel free to either:
- Refactor
- Document
- Improve the code
Feel free to ping me on discord @Hermansen#4325, or just create an issue if
there is a missing feature, or you'd like some mentorship in getting into the
code

40
Cargo.lock generated
View File

@@ -260,7 +260,7 @@ dependencies = [
[[package]]
name = "dagger-core"
version = "0.2.7"
version = "0.2.8"
dependencies = [
"clap",
"dirs",
@@ -309,7 +309,7 @@ dependencies = [
[[package]]
name = "dagger-sdk"
version = "0.2.15"
version = "0.2.16"
dependencies = [
"base64",
"dagger-core",
@@ -537,9 +537,9 @@ dependencies = [
[[package]]
name = "futures"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
dependencies = [
"futures-channel",
"futures-core",
@@ -552,9 +552,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
dependencies = [
"futures-core",
"futures-sink",
@@ -562,15 +562,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
[[package]]
name = "futures-executor"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
dependencies = [
"futures-core",
"futures-task",
@@ -579,15 +579,15 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
[[package]]
name = "futures-macro"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
dependencies = [
"proc-macro2",
"quote",
@@ -596,21 +596,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
[[package]]
name = "futures-task"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
[[package]]
name = "futures-util"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
dependencies = [
"futures-channel",
"futures-core",

View File

@@ -20,7 +20,7 @@ members = [
[dependencies]
dagger-codegen = { path = "crates/dagger-codegen", version = "^0.2.5" }
dagger-core = { path = "crates/dagger-core", version = "^0.2.7" }
dagger-core = { path = "crates/dagger-core", version = "^0.2.8" }
clap = "4.1.6"
dirs = "4.0.0"

43
Makefile.toml Normal file
View File

@@ -0,0 +1,43 @@
[tasks.codegen]
command = "cargo"
args = ["run", "-p", "ci", "--", "codegen"]
workspace = false
[tasks.build]
command = "cargo"
args = ["run", "-p", "ci", "--", "ci"]
dependencies = ["codegen"]
workspace = false
[tasks.fmt]
command = "cargo"
args = ["fmt", "--all"]
workspace = false
[tasks.fix]
command = "cargo"
args = ["fix", "--workspace", "--allow-dirty"]
dependencies = ["fmt"]
workspace = false
[tasks.release_crate]
command = "cargo"
args = [
"smart-release",
"--allow-fully-generated-changelogs",
"--update-crates-index",
"dagger-sdk",
]
dependencies = ["codegen", "fix"]
workspace = false
[tasks.release_crate_commit]
command = "cargo"
args = [
"smart-release",
"-e",
"--allow-fully-generated-changelogs",
"--update-crates-index",
"dagger-sdk",
]
workspace = false

View File

@@ -1,40 +0,0 @@
# dagger-rs
A dagger sdk written in rust for rust.
# Usage
See [dagger-sdk](./crates/dagger-sdk/README.md)
### Status
- [x] dagger cli downloader
- [x] dagger network session
- [x] graphql rust codegen (User API)
- [x] Scalars
- [x] Enums
- [x] Input
- [x] Objects
- [x] Implement context and querier
- [x] Marshaller
- [x] Querier
- [x] Context
- [x] Deserializer for nested response (bind)
- [x] Add codegen to hook into querier
- [x] fix build / release cycle
- [x] general api stabilisation
- [x] document usage
- [x] make async variant
## Architecture
- `.` Root project mainly used for generating the CLI, which in turn is used to
bootstrap the code generation from `dagger`
- `crates/dagger-core` Contains all base types used during actual usage. This is
where the primary logic lives in which the user interacts (\*disclaimer: most
stuff haven't moved in here yet.)
- `crates/dagger-sdk` Contains the actual sdk in which the user interacts,
`dagger-core` is reexported through this API as well.
- `crates/dagger-codegen` This is the bulk of the work, it takes the input
graphql and spits out the API in which the user interacts, this is heavily
inspired by other `dagger-sdk's`. It primarily turns graphql into rust code.

1
README.md Symbolic link
View File

@@ -0,0 +1 @@
crates/dagger-sdk/README.md

View File

@@ -8,6 +8,6 @@ edition = "2021"
[dependencies]
clap = "4.1.6"
color-eyre = "0.6.2"
dagger-sdk = { path = "../crates/dagger-sdk/", version = "^0.2.15" }
dagger-sdk = { path = "../crates/dagger-sdk/", version = "^0.2.16" }
eyre = "0.6.8"
tokio = { version = "1.25.0", features = ["full"] }

View File

@@ -1,5 +1,6 @@
use std::sync::Arc;
use clap::ArgMatches;
use dagger_sdk::{Container, HostDirectoryOpts, Query};
#[tokio::main]
@@ -10,6 +11,7 @@ async fn main() -> eyre::Result<()> {
.subcommand_required(true)
.subcommand(clap::Command::new("pr"))
.subcommand(clap::Command::new("release"))
.subcommand(clap::Command::new("codegen"))
.get_matches();
let client = dagger_sdk::connect().await?;
@@ -20,6 +22,7 @@ async fn main() -> eyre::Result<()> {
return validate_pr(client, base).await;
}
Some(("release", subm)) => return release(client, subm).await,
Some(("codegen", subm)) => return run_codegen(client, subm).await,
Some(_) => {
panic!("invalid subcommand selected!")
}
@@ -29,6 +32,42 @@ 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!["cargo", "fmt", "--all"])
.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> {
let src_dir = client.host().directory_opts(
".",
@@ -87,14 +126,14 @@ async fn get_dependencies(client: Arc<Query>) -> eyre::Result<Container> {
);
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 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
.container()
.from("rust:latest")
.from("rustlang/rust:nightly")
.with_workdir("app")
.with_exec(vec!["apt-get", "update"])
.with_exec(vec!["apt-get", "install", "--yes", "libpq-dev", "wget"])
@@ -110,7 +149,7 @@ async fn get_dependencies(client: Arc<Query>) -> eyre::Result<Container> {
"/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(
"AWS_ACCESS_KEY_ID",
std::env::var("AWS_ACCESS_KEY_ID").unwrap_or("".into()),
@@ -152,8 +191,7 @@ async fn get_dependencies(client: Arc<Query>) -> eyre::Result<Container> {
"--recipe-path",
"recipe.json",
])
.with_mounted_cache("/app/", cache_cargo_deps.id().await?)
.with_mounted_directory("/app/", src_dir.id().await?)
.with_directory("/app/", src_dir.id().await?)
.with_exec(vec!["cargo", "build", "--all", "--release"]);
return Ok(builder_start);
@@ -165,8 +203,21 @@ async fn select_base_image(client: Arc<Query>) -> eyre::Result<Container> {
src_dir
}
async fn validate_pr(_client: Arc<Query>, container: Container) -> eyre::Result<()> {
//let container = container.with_exec(vec!["cargo", "test", "--all"], None);
async fn validate_pr(client: Arc<Query>, container: Container) -> eyre::Result<()> {
let exit = container.exit_code().await?;
if exit != 0 {
eyre::bail!("container failed with non-zero exit code");
}
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 = container
.with_mounted_file("/usr/bin/docker", docker_cli.id().await?)
.with_unix_socket("/var/run/docker.sock", socket.id().await?)
.with_exec(vec!["cargo", "test", "--all"]);
let exit = container.exit_code().await?;
if exit != 0 {

View File

@@ -11,7 +11,7 @@ publish = true
[dependencies]
convert_case = "0.6.0"
dagger-core = { path = "../dagger-core", version = "^0.2.7" }
dagger-core = { path = "../dagger-core", version = "^0.2.8" }
eyre = "0.6.8"
genco = "0.17.3"

View File

@@ -153,6 +153,7 @@ impl From<&TypeRef> for Scalar {
}
}
#[allow(dead_code)]
pub fn get_type_from_name<'t>(types: &'t [FullType], name: &'t str) -> Option<&'t FullType> {
types
.into_iter()
@@ -258,6 +259,7 @@ pub fn input_values_has_optionals(input_values: &[&InputValue]) -> bool {
> 0
}
#[allow(dead_code)]
pub fn input_values_is_empty(input_values: &[InputValue]) -> bool {
input_values.len() > 0
}

View File

@@ -1,3 +1,5 @@
#![deny(warnings)]
mod functions;
mod generator;
pub mod rust;

View File

@@ -86,7 +86,7 @@ pub fn render_optional_field_args(
}
quote! {
$(a.description.pipe(|d| format_struct_comment(d)))
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub $(format_struct_name(&a.name)): Option<$(type_)>,
}
});

View File

@@ -11,6 +11,18 @@ pub fn render_scalar(t: &FullType) -> eyre::Result<rust::Tokens> {
Ok(quote! {
#[derive($serialize, $deserialize, PartialEq, Debug, Clone)]
pub struct $(t.name.pipe(|n|format_name(n)))(String);
pub struct $(t.name.pipe(|n|format_name(n)))(pub String);
impl Into<$(t.name.pipe(|n| format_name(n)))> for &str {
fn into(self) -> $(t.name.pipe(|n| format_name(n))) {
$(t.name.pipe(|n| format_name(n)))(self.to_string())
}
}
impl Into<$(t.name.pipe(|n| format_name(n)))> for String {
fn into(self) -> $(t.name.pipe(|n| format_name(n))) {
$(t.name.pipe(|n| format_name(n)))(self.clone())
}
}
})
}

View File

@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## v0.2.8 (2023-03-10)
### New Features
- <csr-id-41b20b6268db9d8defe333694e4d3ec019d7c923/> bump version
- <csr-id-5f9b3a19c0ab6988bc335b020052074f3f101305/> set internal warnings as errors
- <csr-id-f9e7af931d94fbedacf74f5da9a2f71b1992324b/> introduce tests again
### Bug Fixes
- <csr-id-ecca036bc644fee93fbcb69bf6da9f29169e473e/> fix builder pattern to actually work with default values
In previous versions the builder pattern required all values to be set.
This has not been fixed, so that default values are allowed.
### Commit Statistics
<csr-read-only-do-not-edit/>
- 4 commits contributed to the release over the course of 13 calendar days.
- 13 days passed between releases.
- 4 commits were understood as [conventional](https://www.conventionalcommits.org).
- 0 issues like '(#ID)' were seen in commit messages
### Commit Details
<csr-read-only-do-not-edit/>
<details><summary>view details</summary>
* **Uncategorized**
- bump version ([`41b20b6`](https://github.com/kjuulh/dagger-rs/commit/41b20b6268db9d8defe333694e4d3ec019d7c923))
- set internal warnings as errors ([`5f9b3a1`](https://github.com/kjuulh/dagger-rs/commit/5f9b3a19c0ab6988bc335b020052074f3f101305))
- introduce tests again ([`f9e7af9`](https://github.com/kjuulh/dagger-rs/commit/f9e7af931d94fbedacf74f5da9a2f71b1992324b))
- fix builder pattern to actually work with default values ([`ecca036`](https://github.com/kjuulh/dagger-rs/commit/ecca036bc644fee93fbcb69bf6da9f29169e473e))
</details>
## v0.2.7 (2023-02-24)
### New Features
@@ -15,7 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<csr-read-only-do-not-edit/>
- 1 commit contributed to the release.
- 2 commits contributed to the release.
- 4 days passed between releases.
- 1 commit was understood as [conventional](https://www.conventionalcommits.org).
- 0 issues like '(#ID)' were seen in commit messages
@@ -27,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<details><summary>view details</summary>
* **Uncategorized**
- Release dagger-core v0.2.7, dagger-sdk v0.2.15 ([`6a9a560`](https://github.com/kjuulh/dagger-rs/commit/6a9a560cdca097abf23371d44599a2f1b726ae7f))
- update to dagger-v0.3.13 ([`3e8ca8d`](https://github.com/kjuulh/dagger-rs/commit/3e8ca8d86eafdc1f9d5e8b69f14fb60509549e0f))
</details>

View File

@@ -1,6 +1,6 @@
[package]
name = "dagger-core"
version = "0.2.7"
version = "0.2.8"
edition = "2021"
readme = "README.md"
license-file = "LICENSE.MIT"

View File

@@ -1,6 +1,6 @@
use std::{
fs::File,
io::{copy, Read, Write},
io::{copy, Write},
os::unix::prelude::PermissionsExt,
path::PathBuf,
};
@@ -27,6 +27,7 @@ impl Platform {
let normalize_arch = match arch.as_str() {
"x86_64" => "amd64",
"aarch" => "arm64",
"aarch64" => "arm64",
arch => arch,
};
@@ -138,6 +139,10 @@ impl Downloader {
if let Ok(entry) = file {
let path = entry.path();
if path != cli_bin_path {
println!(
"deleting client: path: {:?} vs cli_bin_path: {:?}",
path, cli_bin_path
);
std::fs::remove_file(path)?;
}
}
@@ -200,8 +205,6 @@ impl Downloader {
hasher.update(&bytes);
let res = hasher.finalize();
println!("{}", hex::encode(&res));
if archive_url.ends_with(".zip") {
// TODO: Nothing for now
todo!()
@@ -220,8 +223,6 @@ impl Downloader {
let mut entry = entry?;
let path = entry.path()?;
println!("path: {:?}", path);
if path.ends_with("dagger") {
copy(&mut entry, output)?;

View File

@@ -1,3 +1,4 @@
use crate::DAGGER_ENGINE_VERSION;
use crate::{
cli_session::CliSession, config::Config, connect_params::ConnectParams, downloader::Downloader,
};
@@ -10,7 +11,9 @@ impl Engine {
}
async fn from_cli(&self, cfg: &Config) -> eyre::Result<(ConnectParams, tokio::process::Child)> {
let cli = Downloader::new("0.3.13".into())?.get_cli().await?;
let cli = Downloader::new(DAGGER_ENGINE_VERSION.into())?
.get_cli()
.await?;
let cli_session = CliSession::new();
@@ -25,28 +28,3 @@ impl Engine {
self.from_cli(cfg).await
}
}
#[cfg(test)]
mod tests {
use crate::{config::Config, connect_params::ConnectParams};
use super::Engine;
// TODO: these tests potentially have a race condition
#[tokio::test]
async fn engine_can_start() {
let engine = Engine::new();
let params = engine
.start(&Config::new(None, None, None, None))
.await
.unwrap();
assert_ne!(
params.0,
ConnectParams {
port: 123,
session_token: "123".into()
}
)
}
}

View File

@@ -241,6 +241,7 @@ pub struct SchemaTypes {
pub full_type: FullType,
}
#[allow(dead_code)]
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SchemaDirectivesArgs {
@@ -257,6 +258,7 @@ pub struct SchemaDirectives {
pub args: Option<Vec<Option<SchemaDirectivesArgs>>>,
}
#[allow(dead_code)]
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Schema {

View File

@@ -1,3 +1,7 @@
#![deny(warnings)]
pub const DAGGER_ENGINE_VERSION: &'static str = "0.4.0";
pub mod cli_session;
pub mod config;
pub mod connect_params;

View File

@@ -12,13 +12,3 @@ pub async fn get_schema() -> eyre::Result<IntrospectionResponse> {
Ok(schema)
}
#[cfg(test)]
mod tests {
use super::get_schema;
#[tokio::test]
async fn can_get_schema() {
let _ = get_schema().await.unwrap();
}
}

View File

@@ -6,6 +6,52 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## v0.2.16 (2023-03-10)
### Chore
- <csr-id-e642778d9028726dfb07217814e15ad1dd3b83f2/> fix tasks
### Documentation
- <csr-id-13b7805e7e6fcf47e0a1318adcc25b4ab773a3c9/> fix missing await in connect
### New Features
- <csr-id-7133bfae9508bc5977548e373c49342a1248d6e4/> with dagger-engine v.0.4.0
- <csr-id-4381af029521c2cbac9325278d261db79a994657/> add tests to sdk
- <csr-id-5f9b3a19c0ab6988bc335b020052074f3f101305/> set internal warnings as errors
### Bug Fixes
- <csr-id-ecca036bc644fee93fbcb69bf6da9f29169e473e/> fix builder pattern to actually work with default values
In previous versions the builder pattern required all values to be set.
This has not been fixed, so that default values are allowed.
### Commit Statistics
<csr-read-only-do-not-edit/>
- 6 commits contributed to the release over the course of 13 calendar days.
- 13 days passed between releases.
- 6 commits were understood as [conventional](https://www.conventionalcommits.org).
- 0 issues like '(#ID)' were seen in commit messages
### Commit Details
<csr-read-only-do-not-edit/>
<details><summary>view details</summary>
* **Uncategorized**
- fix tasks ([`e642778`](https://github.com/kjuulh/dagger-rs/commit/e642778d9028726dfb07217814e15ad1dd3b83f2))
- with dagger-engine v.0.4.0 ([`7133bfa`](https://github.com/kjuulh/dagger-rs/commit/7133bfae9508bc5977548e373c49342a1248d6e4))
- fix missing await in connect ([`13b7805`](https://github.com/kjuulh/dagger-rs/commit/13b7805e7e6fcf47e0a1318adcc25b4ab773a3c9))
- add tests to sdk ([`4381af0`](https://github.com/kjuulh/dagger-rs/commit/4381af029521c2cbac9325278d261db79a994657))
- set internal warnings as errors ([`5f9b3a1`](https://github.com/kjuulh/dagger-rs/commit/5f9b3a19c0ab6988bc335b020052074f3f101305))
- fix builder pattern to actually work with default values ([`ecca036`](https://github.com/kjuulh/dagger-rs/commit/ecca036bc644fee93fbcb69bf6da9f29169e473e))
</details>
## v0.2.15 (2023-02-24)
### New Features
@@ -20,7 +66,7 @@ and this project adheres to
<csr-read-only-do-not-edit/>
- 2 commits contributed to the release.
- 3 commits contributed to the release.
- 2 days passed between releases.
- 2 commits were understood as [conventional](https://www.conventionalcommits.org).
- 0 issues like '(#ID)' were seen in commit messages
@@ -32,6 +78,7 @@ and this project adheres to
<details><summary>view details</summary>
* **Uncategorized**
- Release dagger-core v0.2.7, dagger-sdk v0.2.15 ([`6a9a560`](https://github.com/kjuulh/dagger-rs/commit/6a9a560cdca097abf23371d44599a2f1b726ae7f))
- set deserialize on enums as well ([`e578b0e`](https://github.com/kjuulh/dagger-rs/commit/e578b0e371e13bc30ada793b7cd6ebe75ba83a07))
- update to dagger-v0.3.13 ([`3e8ca8d`](https://github.com/kjuulh/dagger-rs/commit/3e8ca8d86eafdc1f9d5e8b69f14fb60509549e0f))
</details>

View File

@@ -1,6 +1,6 @@
[package]
name = "dagger-sdk"
version = "0.2.15"
version = "0.2.16"
edition = "2021"
readme = "README.md"
license-file = "LICENSE.MIT"
@@ -11,11 +11,11 @@ publish = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dagger-core = { path = "../dagger-core", version = "^0.2.7" }
dagger-core = { path = "../dagger-core", version = "^0.2.8" }
base64 = "0.21.0"
eyre = "0.6.8"
futures = "0.3.26"
futures = "0.3.27"
gql_client = "1.0.7"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"

View File

@@ -27,7 +27,7 @@ cargo add dagger-sdk
```rust
#[tokio::main]
async fn main() -> eyre::Result<()> {
let client = dagger_sdk::connect()?;
let client = dagger_sdk::connect().await?;
let version = client
.container()
@@ -46,9 +46,3 @@ And run it like a normal application:
```bash
cargo run
```
### Disclaimer
You are free to use something else than `tokio`, I haven't tested it with
anything else, but it should work with any other runtime. We don't rely on it
specifically. That might change in the future though.

View File

@@ -7,24 +7,113 @@ use std::sync::Arc;
use tokio::process::Child;
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct CacheId(String);
pub struct CacheId(pub String);
impl Into<CacheId> for &str {
fn into(self) -> CacheId {
CacheId(self.to_string())
}
}
impl Into<CacheId> for String {
fn into(self) -> CacheId {
CacheId(self.clone())
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct ContainerId(String);
pub struct ContainerId(pub String);
impl Into<ContainerId> for &str {
fn into(self) -> ContainerId {
ContainerId(self.to_string())
}
}
impl Into<ContainerId> for String {
fn into(self) -> ContainerId {
ContainerId(self.clone())
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct DirectoryId(String);
pub struct DirectoryId(pub String);
impl Into<DirectoryId> for &str {
fn into(self) -> DirectoryId {
DirectoryId(self.to_string())
}
}
impl Into<DirectoryId> for String {
fn into(self) -> DirectoryId {
DirectoryId(self.clone())
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct FileId(String);
pub struct FileId(pub String);
impl Into<FileId> for &str {
fn into(self) -> FileId {
FileId(self.to_string())
}
}
impl Into<FileId> for String {
fn into(self) -> FileId {
FileId(self.clone())
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Platform(String);
pub struct Platform(pub String);
impl Into<Platform> for &str {
fn into(self) -> Platform {
Platform(self.to_string())
}
}
impl Into<Platform> for String {
fn into(self) -> Platform {
Platform(self.clone())
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct SecretId(String);
pub struct SecretId(pub String);
impl Into<SecretId> for &str {
fn into(self) -> SecretId {
SecretId(self.to_string())
}
}
impl Into<SecretId> for String {
fn into(self) -> SecretId {
SecretId(self.clone())
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct SocketId(String);
pub struct SocketId(pub String);
impl Into<SocketId> for &str {
fn into(self) -> SocketId {
SocketId(self.to_string())
}
}
impl Into<SocketId> for String {
fn into(self) -> SocketId {
SocketId(self.clone())
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct BuildArg {
pub name: String,
pub value: String,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct PipelineLabel {
pub value: String,
pub name: String,
}
#[derive(Debug, Clone)]
pub struct CacheVolume {
pub proc: Arc<Child>,
@@ -50,134 +139,144 @@ pub struct Container {
pub struct ContainerBuildOpts<'a> {
/// Path to the Dockerfile to use.
/// Default: './Dockerfile'.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub dockerfile: Option<&'a str>,
/// Additional build arguments.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub build_args: Option<Vec<BuildArg>>,
/// Target build stage to build.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub target: Option<&'a str>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerEndpointOpts<'a> {
/// The exposed port number for the endpoint
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub port: Option<isize>,
/// Return a URL with the given scheme, eg. http for http://
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub scheme: Option<&'a str>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerExecOpts<'a> {
/// Command to run instead of the container's default command (e.g., ["run", "main.go"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub args: Option<Vec<&'a str>>,
/// Content to write to the command's standard input before closing (e.g., "Hello world").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub stdin: Option<&'a str>,
/// Redirect the command's standard output to a file in the container (e.g., "/tmp/stdout").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub redirect_stdout: Option<&'a str>,
/// Redirect the command's standard error to a file in the container (e.g., "/tmp/stderr").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
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))]
#[builder(setter(into, strip_option), default)]
pub experimental_privileged_nesting: Option<bool>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerExportOpts {
/// Identifiers for other platform specific containers.
/// Used for multi-platform image.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub platform_variants: Option<Vec<ContainerId>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerPipelineOpts<'a> {
#[builder(setter(into, strip_option))]
/// Pipeline description.
#[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>,
/// Pipeline labels.
#[builder(setter(into, strip_option), default)]
pub labels: Option<Vec<PipelineLabel>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerPublishOpts {
/// Identifiers for other platform specific containers.
/// Used for multi-platform image.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub platform_variants: Option<Vec<ContainerId>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithDefaultArgsOpts<'a> {
/// Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub args: Option<Vec<&'a str>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithDirectoryOpts<'a> {
/// Patterns to exclude in the written directory (e.g., ["node_modules/**", ".gitignore", ".git/"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub exclude: Option<Vec<&'a str>>,
/// Patterns to include in the written directory (e.g., ["*.go", "go.mod", "go.sum"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub include: Option<Vec<&'a str>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithExecOpts<'a> {
/// Content to write to the command's standard input before closing (e.g., "Hello world").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub stdin: Option<&'a str>,
/// Redirect the command's standard output to a file in the container (e.g., "/tmp/stdout").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub redirect_stdout: Option<&'a str>,
/// Redirect the command's standard error to a file in the container (e.g., "/tmp/stderr").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub redirect_stderr: Option<&'a str>,
/// Provides 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))]
#[builder(setter(into, strip_option), default)]
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)]
pub struct ContainerWithExposedPortOpts<'a> {
/// Transport layer network protocol
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub protocol: Option<NetworkProtocol>,
/// Optional port description
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithFileOpts {
/// Permission given to the copied file (e.g., 0600).
/// Default: 0644.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub permissions: Option<isize>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithMountedCacheOpts {
/// Identifier of the directory to use as the cache volume's root.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub source: Option<DirectoryId>,
/// Sharing mode of the cache volume.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub sharing: Option<CacheSharingMode>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithNewFileOpts<'a> {
/// Content of the file to write (e.g., "Hello world!").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub contents: Option<&'a str>,
/// Permission given to the written file (e.g., 0600).
/// Default: 0644.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub permissions: Option<isize>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct ContainerWithoutExposedPortOpts {
/// Port protocol to unexpose
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub protocol: Option<NetworkProtocol>,
}
@@ -252,6 +351,7 @@ impl 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 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
///
@@ -265,6 +365,7 @@ impl 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 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
///
@@ -358,7 +459,7 @@ impl Container {
};
}
/// 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> {
let query = self.selection.select("exitCode");
@@ -404,7 +505,8 @@ impl Container {
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> {
let query = self.selection.select("exposedPorts");
@@ -460,6 +562,7 @@ impl 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> {
let query = self.selection.select("hostname");
@@ -505,6 +608,7 @@ impl Container {
///
/// # Arguments
///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline(&self, name: impl Into<String>) -> Container {
let mut query = self.selection.select("pipeline");
@@ -522,6 +626,7 @@ impl Container {
///
/// # Arguments
///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline_opts<'a>(
&self,
@@ -534,6 +639,9 @@ impl Container {
if let Some(description) = opts.description {
query = query.arg("description", description);
}
if let Some(labels) = opts.labels {
query = query.arg("labels", labels);
}
return Container {
proc: self.proc.clone(),
@@ -600,14 +708,14 @@ impl Container {
};
}
/// 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> {
let query = self.selection.select("stderr");
query.execute(&graphql_client(&self.conn)).await
}
/// 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> {
let query = self.selection.select("stdout");
@@ -796,6 +904,9 @@ impl Container {
experimental_privileged_nesting,
);
}
if let Some(insecure_root_capabilities) = opts.insecure_root_capabilities {
query = query.arg("insecureRootCapabilities", insecure_root_capabilities);
}
return Container {
proc: self.proc.clone(),
@@ -807,6 +918,7 @@ impl Container {
/// Exposed ports serve two purposes:
/// - For health checks and introspection, when running services
/// - For setting the EXPOSE OCI field when publishing the container
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
///
/// # Arguments
///
@@ -828,6 +940,7 @@ impl Container {
/// Exposed ports serve two purposes:
/// - For health checks and introspection, when running services
/// - For setting the EXPOSE OCI field when publishing the container
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
///
/// # Arguments
///
@@ -1159,6 +1272,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.
/// 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.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
///
/// # Arguments
///
@@ -1247,6 +1361,7 @@ impl Container {
};
}
/// Unexpose a previously exposed port.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
///
/// # Arguments
///
@@ -1265,6 +1380,7 @@ impl Container {
}
/// Unexpose a previously exposed port.
/// Currently experimental; set _EXPERIMENTAL_DAGGER_SERVICES_DNS=0 to disable.
///
/// # Arguments
///
@@ -1371,57 +1487,61 @@ pub struct Directory {
pub struct DirectoryDockerBuildOpts<'a> {
/// Path to the Dockerfile to use (e.g., "frontend.Dockerfile").
/// Defaults: './Dockerfile'.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub dockerfile: Option<&'a str>,
/// The platform to build.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub platform: Option<Platform>,
/// Build arguments to use in the build.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub build_args: Option<Vec<BuildArg>>,
/// Target build stage to build.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub target: Option<&'a str>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct DirectoryEntriesOpts<'a> {
/// Location of the directory to look at (e.g., "/src").
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub path: Option<&'a str>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct DirectoryPipelineOpts<'a> {
#[builder(setter(into, strip_option))]
/// Pipeline description.
#[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>,
/// Pipeline labels.
#[builder(setter(into, strip_option), default)]
pub labels: Option<Vec<PipelineLabel>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct DirectoryWithDirectoryOpts<'a> {
/// Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub exclude: Option<Vec<&'a str>>,
/// Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub include: Option<Vec<&'a str>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct DirectoryWithFileOpts {
/// Permission given to the copied file (e.g., 0600).
/// Default: 0644.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub permissions: Option<isize>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct DirectoryWithNewDirectoryOpts {
/// Permission granted to the created directory (e.g., 0777).
/// Default: 0755.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub permissions: Option<isize>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct DirectoryWithNewFileOpts {
/// Permission given to the copied file (e.g., 0600).
/// Default: 0644.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub permissions: Option<isize>,
}
@@ -1574,10 +1694,11 @@ impl Directory {
conn: self.conn.clone(),
};
}
/// Creates a named sub-pipeline.
/// Creates a named sub-pipeline
///
/// # Arguments
///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline(&self, name: impl Into<String>) -> Directory {
let mut query = self.selection.select("pipeline");
@@ -1591,10 +1712,11 @@ impl Directory {
};
}
/// Creates a named sub-pipeline.
/// Creates a named sub-pipeline
///
/// # Arguments
///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline_opts<'a>(
&self,
@@ -1607,6 +1729,9 @@ impl Directory {
if let Some(description) = opts.description {
query = query.arg("description", description);
}
if let Some(labels) = opts.labels {
query = query.arg("labels", labels);
}
return Directory {
proc: self.proc.clone(),
@@ -1948,9 +2073,9 @@ pub struct GitRef {
#[derive(Builder, Debug, PartialEq)]
pub struct GitRefTreeOpts<'a> {
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub ssh_known_hosts: Option<&'a str>,
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub ssh_auth_socket: Option<SocketId>,
}
@@ -2077,19 +2202,19 @@ pub struct Host {
#[derive(Builder, Debug, PartialEq)]
pub struct HostDirectoryOpts<'a> {
/// Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub exclude: Option<Vec<&'a str>>,
/// Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub include: Option<Vec<&'a str>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct HostWorkdirOpts<'a> {
/// Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub exclude: Option<Vec<&'a str>>,
/// Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]).
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub include: Option<Vec<&'a str>>,
}
@@ -2343,39 +2468,43 @@ pub struct Query {
#[derive(Builder, Debug, PartialEq)]
pub struct QueryContainerOpts {
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub id: Option<ContainerId>,
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub platform: Option<Platform>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct QueryDirectoryOpts {
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub id: Option<DirectoryId>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct QueryGitOpts {
/// Set to true to keep .git directory.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub keep_git_dir: Option<bool>,
/// A service which must be started before the repo is fetched.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub experimental_service_host: Option<ContainerId>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct QueryHttpOpts {
/// A service which must be started before the URL is fetched.
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub experimental_service_host: Option<ContainerId>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct QueryPipelineOpts<'a> {
#[builder(setter(into, strip_option))]
/// Pipeline description.
#[builder(setter(into, strip_option), default)]
pub description: Option<&'a str>,
/// Pipeline labels.
#[builder(setter(into, strip_option), default)]
pub labels: Option<Vec<PipelineLabel>>,
}
#[derive(Builder, Debug, PartialEq)]
pub struct QuerySocketOpts {
#[builder(setter(into, strip_option))]
#[builder(setter(into, strip_option), default)]
pub id: Option<SocketId>,
}
@@ -2582,10 +2711,11 @@ impl Query {
conn: self.conn.clone(),
};
}
/// Creates a named sub-pipeline
/// Creates a named sub-pipeline.
///
/// # Arguments
///
/// * `name` - Pipeline name.
/// * `opt` - optional argument, see inner type for documentation, use <func>_opts to use
pub fn pipeline(&self, name: impl Into<String>) -> Query {
let mut query = self.selection.select("pipeline");
@@ -2599,10 +2729,11 @@ impl Query {
};
}
/// Creates a named sub-pipeline
/// Creates a named sub-pipeline.
///
/// # Arguments
///
/// * `name` - Pipeline name.
/// * `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 {
let mut query = self.selection.select("pipeline");
@@ -2611,6 +2742,9 @@ impl Query {
if let Some(description) = opts.description {
query = query.arg("description", description);
}
if let Some(labels) = opts.labels {
query = query.arg("labels", labels);
}
return Query {
proc: self.proc.clone(),

View File

@@ -1,3 +1,5 @@
#![deny(warnings)]
mod client;
mod gen;
mod querybuilder;

View File

@@ -0,0 +1,47 @@
use dagger_sdk::{QueryContainerOpts, QueryContainerOptsBuilder};
static PLATFORMS: [&str; 2] = ["linux/arm64", "linux/x86_64"];
#[tokio::test]
async fn test_issue_30_alt() -> eyre::Result<()> {
let client = dagger_sdk::connect().await?;
for platform in PLATFORMS {
let ref_ = client
.container_opts(QueryContainerOpts {
id: None,
platform: Some(platform.to_string().into()),
})
.from("alpine")
.with_exec(vec!["echo", "'hello'"])
.exit_code()
.await?;
println!("published image to: {:#?}", ref_);
}
Ok(())
}
#[tokio::test]
async fn test_issue_30() -> eyre::Result<()> {
let client = dagger_sdk::connect().await?;
for platform in PLATFORMS {
let ref_ = client
.container_opts(
QueryContainerOptsBuilder::default()
.platform(platform)
.build()
.unwrap(),
)
.from("alpine")
.with_exec(vec!["echo", "'hello'"])
.exit_code()
.await?;
println!("published image to: {:#?}", ref_);
}
Ok(())
}

View File

@@ -0,0 +1 @@
mod iss_30;

View File

@@ -1,4 +1,7 @@
mod issues;
use dagger_sdk::{connect, ContainerExecOptsBuilder};
use pretty_assertions::assert_eq;
#[tokio::test]
async fn test_example_container() {
@@ -19,3 +22,99 @@ async fn test_example_container() {
assert_eq!(out, "3.16.2\n".to_string())
}
#[tokio::test]
async fn test_directory() {
let c = connect().await.unwrap();
let contents = c
.directory()
.with_new_file("/hello.txt", "world")
.file("/hello.txt")
.contents()
.await
.unwrap();
assert_eq!("world", contents)
}
#[tokio::test]
async fn test_git() {
let c = connect().await.unwrap();
let tree = c.git("github.com/dagger/dagger").branch("main").tree();
let _ = tree
.entries()
.await
.unwrap()
.iter()
.find(|f| f.as_str() == "README.md")
.unwrap();
let readme_file = tree.file("README.md");
let readme = readme_file.contents().await.unwrap();
assert_eq!(true, readme.find("Dagger").is_some());
let readme_id = readme_file.id().await.unwrap();
let other_readme = c.file(readme_id).contents().await.unwrap();
assert_eq!(readme, other_readme);
}
#[tokio::test]
async fn test_container() {
let client = connect().await.unwrap();
let alpine = client.container().from("alpine:3.16.2");
let contents = alpine
.fs()
.file("/etc/alpine-release")
.contents()
.await
.unwrap();
assert_eq!(contents, "3.16.2\n".to_string());
let out = alpine
.exec_opts(
ContainerExecOptsBuilder::default()
.args(vec!["cat", "/etc/alpine-release"])
.build()
.unwrap(),
)
.stdout()
.await
.unwrap();
assert_eq!(out, "3.16.2\n".to_string());
let id = alpine.id().await.unwrap();
let contents = client
.container_opts(dagger_sdk::QueryContainerOpts {
id: Some(id),
platform: None,
})
.fs()
.file("/etc/alpine-release")
.contents()
.await
.unwrap();
assert_eq!(contents, "3.16.2\n".to_string());
}
#[tokio::test]
async fn test_err_message() {
let client = connect().await.unwrap();
let alpine = client.container().from("fake.invalid:latest").id().await;
assert_eq!(alpine.is_err(), true);
let err = alpine.expect_err("Tests expect err");
let error_msg = r#"
GQLClient Error: Look at json field for more details
Message: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
"#;
assert_eq!(err.to_string().as_str(), error_msg);
}