#dotnet

1 messages Β· Page 1 of 1 (latest)

bold pebble
#

Unofficial alpha-stage C# Dagger SDK is now on NuGet: https://www.nuget.org/packages/MaxPixel.Dagger.SDK

It works very well, but some syntax is prone to change before it's ironed out. The one major issue I've come across so far is Dagger queries that take more than 100 seconds trigger a default timeout on the GraphQL client, so fixing that is the next thing on my to-do list.

barren bay
fiery trellis
bold pebble
# barren bay Is this a packaging of the C# SDK from the dagger repo? Or from an unrelated rep...

Helder is right. I used its existing solution structure, but ultimately replaced the whole implementation as it was just a proof of concept and highly dissimilar to the other SDKs. This is a effectively a port of the NodeJS & Go SDKs. In fact, I'd like to port some of my subsequent fixes and improvements back in the other direction to improve the TypeScript SDK, in addition to proposing my C# implementation for official upstreaming once I've gone through all the necessary steps, fixed any issues, and of course earned community approval.

bold pebble
#

Right now, the test suite has near parity with the NodeJS one. With the exception of Zenith support (which I expect to add as well, if nobody else jumps in first).

bold pebble
#

Version 0.0.3 of my unofficial SDK upgrades to Dagger 0.9.8 and fixes the HTTP timeout.

Next on my to-do list is revising the generator to use the previous version of the C# SDK to perform the introspection, so that I can collapse the EngineConnection and Errors assemblies back into the DaggerSDK assembly.

barren bay
bold pebble
#

I have and I am!

I'm currently focused on some CI/CD infrastructure leaning very heavily into config-as-code & dotnet (Fedora CoreOS image with PowerShell, built with C# Dagger, deployed with F# Pulumi). Once that's running nicely I want to get the C# SDK set up with build + test + publish on push, and then move on to functions.

bright swift
#

Hi Everyone. I discovered Dagger at KubeCon. Our teams write code in C# .NET. So I think I've found the right place? Are there any 101 examples of using Dagger with C# available that I can help demo to my internal teams?

hot pumice
bold pebble
bright swift
bold pebble
#

That said, it's very analogous to the other sdks. If you take one of the many typescript examples from their documentation, paste it into a C# file, install the dagger SDK from nuget, and fix the syntax errors, you'll likely end up with a working pipeline.

bold pebble
#

I favor RHEL over Debian, so this is my standard build container:

Container buildContainer = dagger
    .Pipeline("Linux")
    .Container()
    .From("docker.io/almalinux:9.3-minimal")
    .WithExec(["ln", "-s", "microdnf", "/usr/bin/dnf"]);
buildContainer = buildContainer
    // Make RPM database ephemeral to container build process.
    .WithMountedDirectory("/var/lib/rpm", buildContainer.Directory("/var/lib/rpm"))
    // Mount semi-ephemeral package management caches.
    .WithMountedCache("/var/lib/dnf/repos", dagger.CacheVolume("var-lib-dnf-repos"), sharing: CacheSharingMode.LOCKED)
    .WithMountedCache("/var/cache/dnf", dagger.CacheVolume("var-cache-dnf"), sharing: CacheSharingMode.LOCKED)
    .WithMountedCache("/var/cache/yum", dagger.CacheVolume("var-cache-yum"), sharing: CacheSharingMode.LOCKED)
    // Create non-root user
    .WithCompoundExec
    (
        [
            InstallWithoutClean("shadow-utils"),
            ["useradd", "--create-home", "--home", "/home/rootless", "--shell", "/bin/bash", "--uid", "1000", "rootless"],
            ["dnf", "remove", "--assumeyes", "shadow-utils"],
            CleanAfterInstall
        ]
    )
    .WithWorkdir("/home/rootless")
    // Install build dependencies
    .Install("cargo", "glib2-devel")
    .WithoutMount("/var/lib/rpm")
    .WithoutMount("/var/lib/dnf/repos")
    .WithoutMount("/var/cache/dnf")
    .WithoutMount("/var/cache/yum")
    .WithUser("rootless");
#

I wanted to run czkawka on an ARM device recently so I had to build it myself.

dagger = dagger.Pipeline("Czkawka");
Host host = dagger.GetHost();
File buildArtifact = buildContainer
    .Pipeline("Czkawka")
    .WithMountedDirectory
    (
        "/home/rootless/app",
        host.Directory
        (
            CurrentDirectory,
            include: ["czkawka_cli", "czkawka_core", "czkawka_gui", "Cargo.lock", "*.toml"]
        ),
        owner: "rootless"
    )
    .WithWorkdir("/home/rootless/app")
    .WithEnvVariable("CARGO_INCREMENTAL", "0")
    .WithEnvVariable("RUSTFLAGS", "-C debuginfo=0")
    .WithExec(["cargo", "build", "--release", "--bin", "czkawka_cli"])
    .File("target/release/czkawka_cli");

await buildArtifact.Export($"{CurrentDirectory}/target/release/czkawka_cli");

This is a top-level Program.cs with a few using static at top e.g. to enable the use of CurrentDirectory as a complete expression.

bold pebble
#

Part of the deal with Dagger is that it doesn't prescribe a particular way of defining "targets" and dependencies between those targets, so you need to do that yourself. It's only a partial Make replacement.

Well, Dagger functions seem to intend to change that to some degree. But apart from the fact that I don't support them yet, it feels silly having my C# runtime start a container that contains another C# runtime. I haven't found anything I've needed to do to be so complex that getting something from Daggerverse felt like a more effective use of time than bashing something out in my known language in the same codebase, debuggable, tweakable. I haven't gotten around to using them in Node JS even, where they are supported.

That's partly because Node modules give a nice, concise way to write lazy-loaded singletons. Dagger caches everything heavily and re-evaluating complex graphs is trivial, so it shouldn't matter in a lot of cases, but there are times when it's nice to avoid re-evaluating not-dagger code when it's used in several places by some target. The best we can do in C# is use Lazy<>, and as a static member of a static class, as far as I've found. It's not quite as concise and scripty as the TypeScript equivalent. I'd like to learn F# sometime and see if that's a better fit. It's really not that much boilerplate, but it's enough to deter me from breaking up my pipelines into really tiny modules like I've done in Node.

Anyways, at least for the purpose of being able to say dagger run dotnet run This vs dagger run dotnet run That where This and That are both Dagger pipelines defined in the same csproj and maybe one depends on the other, I ended up using CommandDotNet on a more complex project. Add a new function Baz to a partial static class with a few lines to register that class with the library, boom, you can run that function by putting Baz at the end of the command-line.

#
partial class Targets
{
    static readonly Client _dagger = Client.Default;

    static int Main(string[] arguments)
    {
        string? pulumiStack = GetEnvironmentVariable("PULUMI_STACK");
        if (pulumiStack != null)
            arguments = [pulumiStack];
        return new AppRunner<Targets>().Run(arguments);
    }
}

This is how I integrate CommandDotNet (and Pulumi). Some of my targets are Pulumi, some are Dagger, some are a mix.

#

One more example for today, here's my pipeline for setting up a PXE environment for flashing custom CoreOS to some SBCs

Container sshContainer = _dagger
    .Container()
    .From("quay.io/fedora/fedora-minimal")
    .WithExec(["microdnf", "install", "-y", "openssh-clients"])
    .WithSSHAgent();

Task configureRouterTask = sshContainer
    .WithExec
    (
        ["ssh", "-vvv", $"-p{_ROUTER_SSH_PORT}", "admin@router.home.arpa", "tee /jffs/configs/dnsmasq.conf.add > /dev/null"],
        skipEntrypoint: true,
        stdin: $"""
        enable-tftp
        tftp-root=/tmp/mnt/usbdrive/tftp
        dhcp-match=set:ipxe,option:user-class,iPXE
        {
            string.Join
            (
                '\n',
                Device.All.Select
                (
                    device =>
                        $"""
                         dhcp-mac=set:{device.HostName},{device.Address}
                         dhcp-boot=tag:{device.HostName},{_http_url_base}{device.HostName}.ipxe
                         """
                )
            )
        }
        dhcp-boot=tag:!ipxe,ipxe.efi
        
        """
    )
    .WithExec(["ssh", $"-p{_ROUTER_SSH_PORT}", "admin@router.home.arpa", "service restart_dnsmasq"])
    .Sync();
#

Ah, and this is the WithSSHAgent extension method that's used in the above code snippet

public static Container WithSSHAgent(this Container self)
{
    string sshSocketPath = GetEnvironmentVariable("SSH_AUTH_SOCK")!;

    return self
        .WithMountedDirectory
        (
            "/root/.ssh",
            Client.Default.Directory()
                .WithFile
                (
                    "known_hosts",
                    Client.Default.GetHost().File($"{GetEnvironmentVariable("HOME")}/.ssh/known_hosts")
                )
        )
        .WithUnixSocket
        (
            sshSocketPath,
            Client.Default.GetHost().UnixSocket(sshSocketPath)
        )
        .WithEnvVariable("SSH_AUTH_SOCK", sshSocketPath);
}
shut spruce
# bold pebble Part of the deal with Dagger is that it doesn't prescribe a particular way of de...

I have experienced the same and went similar way with my Go tooling at work. We have multiple use cases of what we need to do and how to manipulate and transform data before we can run the pipeline for container builds. So my way of handling that is having custom CLI tool written in Go with Cobra package that does very specific things that would either be too verbose with other tools or incomplete. So similarly to you I usually end up writing my own stuff even though it can be found on Daggerverse because it naturally happens.

And since my developers all write code in .NET I would be very happy to be able to have the pipelines in .NET as well, I'm just not that proficient in both GraphQL and C# to figure out and maintain the SDK myself. So I can at least verbally express my support and excitement for your efforts.

bold pebble
shut spruce
#

I sure will, thank you

weak crow
#

does anyone have examples of building docker images in c# with dagger

weak crow
fiery trellis
weak crow
#

would you know of any demo ci'd projects that manage poetry?

fiery trellis
weak crow
#

yes. sorry I replied in the wrong channel.

#

I had my "ahah" moment with dagger last weekend and I think I am close to using it for everything once I get a few more of the details figured out

shut spruce
#

If there was official dotnet client I would actually use it for everything, I now use Go client but 90% of our codebase is dotnet. M-pixel's library is looking good but I cannot commit to use it in production

#

And my dotnet skills are nowhere near the proficiency needed to finish the SDK

hot pumice
coarse cove
#

Thanks, @hot pumice !

@shut spruce , it confuses me to refer to a Dagger .NET SDK since .NET is a framework and suite of tools, which includes three languages: C#, F#, and Visual Basic.

What I've seen in the channel here is that people want to write Dagger pipelines in C# and that the experimental SDK is for C#.

Will you please help me understand what I'm missing?

agile zinc
#

@coarse cove a Dagger .NET SDK would be written in one of the mentioned languages and compiled to IL assemblies: https://learn.microsoft.com/en-us/dotnet/standard/managed-code

All the .NET languages compile to IL which they can all then consume. You could even consume such assemblies with Powershell (if you really want to...)

So an SDK could be written in F# and still be utilized in a pipeline written in C#, and vice versa. Because most .NET application code is written in C# most developers would also write their Dagger pipeline in C#, hence why that is what is being asked for.

Regardless of the language choice the generated SDK would be a .NET SDK, though I'd say that even though it's possible to write an SDK in one language and use it in another, it's more feasible to structure an SDK well for C# by writing it in C#. The fact that it can be utilized in other languages I'd just think of as a bonus feature πŸ™‚

coarse cove
#

@barren bay , with Dagger functions, would it be easier to support an SDK for C# so that the maintainers aren't having to manage that interface layer to make that SDK cross-language?

hollow lantern
coarse cove
hollow lantern
#

Hi, I just write QueryBuilder which is the core part of the SDK to construct GraphQL query in codegen by porting from another SDK at https://github.com/dagger/dagger/pull/7208. I'm not the DotNet expert, hope that someone could help review.

GitHub

GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.

weak crow
#

is there a reference example of doing CI in c# I can refer to?

#

perhaps it needs to be written in python for now until the sdk is ready?

hollow lantern
#

C# is not ready yet. You may need to pick Go, Python, TS or Rust instead.

hollow lantern
deep marten
#

How and where would dagger fit if we are exploring nuke.build for .net. Would adding dagger on top of make any sense ?

hollow lantern
deep marten
#

Sorry do you mean dagger functions instead of module?

hollow lantern
deep marten
#

So you would have dagger module in typescript invoking a module containing .net sdk. I don’t think how this is possible because dagger doesn’t have any support for .net @barren bay ?

#

What if this dot net component is dockerized? Does that help in any way?

barren bay
deep marten
#

@barren bay is there a way to me to contribute to the dot net SDK and runtime ? I have a few .NET folks and a bunch of new energetic fresh grads who would like to help. They may just need some direction in how to get started contributing, tasks to complete, etc

#

also, might be able to sponsor the backlog if there is a way for the large universe of global dot net developer to contribute

barren bay
#

Absolutely, that would be amazing. There is a lot of demand for both dot net and Java, but we have limited core engineering resources so didn't find the cycles for it yet.

hollow lantern
#

Hi, @deep marten I believe we could do:

  1. Help reviewing https://github.com/dagger/dagger/pull/7208
  2. Help working on https://github.com/wingyplus/daggerverse/tree/main/dotnet-sdk

The reason I create on my own is the PR on (1) still in pending review process and I need fast iteration during development. If the PR on (1) can going forward, I can bring some changes in (2) to the upstream.

GitHub

In this PR try to modernize DotNet SDK by do the following:

Upgrade .net from 7 to 8.
Setup .editorconfig to make dotnet format works.
Rework on query builder by introduce QueryBuilder class and p...

GitHub

My Dagger modules. Contribute to wingyplus/daggerverse development by creating an account on GitHub.

frank bramble
#

@hollow lantern I've been a .NET dev for quite a long time. Wondering how I can help you out

#

A few things without looking too deep into it (maybe it's still not the right method) but ive found it hard to find the right docs for the SDK especially with the new functions approach.

  1. Roslyn Source Generators is a .NET Project type which supports writing code at compile time
  2. StrawberryShake being the popular GraphQL Client for the .NET ecosystem
  3. MSTest SDK (I think they're trying to condense the .NET Test SDK to have a holistic solution, a bit like how Golang just comes with what you need. so you dont need a Test SDK and a 3rd party unit tsting framework. You would simply use the base MS Test SDK Project
#

I was looking into starting playing aorund writing my own dotnet SDK but it makes no sense, it would take me weeks or months to even get it to where it's at now with how you have it

#

Need some handholding on "how to use this sdk" though. So far in my own code I managed to run the old undocumented method like dagger run dotnet run and see the port/token with some C# code, but i basically stopped there after finding this PR and the old experimental dotnet sdk.

hollow lantern
#

It’s require to run under dagger run because it’s supported only run through the session token. πŸ™‚

#

On the codegen part. I just use the string builder to construct the source code. I have been looking at the roslyn source generator but I didn’t understand how to generate the source from introspection. 😭

frank bramble
#

the introspection is a GraphQL response right?

#

I will clone your repo and play a bit

frank bramble
#

I think we would also benefit from the built in syntax tree formatting

#

unless this formatting is required for something else im not understanding yet

frank bramble
frank bramble
#

or dagger run dotnet build...

#

during build, make the source generator submit the graphql query

frank bramble
#

I butchered your solution though

#

i need to upload this so you can read how i did the changes :S

#

there was issue with source generator and the nuget package being used for some reason and source generators must target NetStandard2.0

#

so a bunch of c#12 stuff wont work without a couple of weird shims

#

so, dagger run dotnet run (get the introspection file), then when you do dotnet build, the roslyn source gen wil see the introspection.json file from the initial introspection query and then generate the types

#

<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> this is useful to see, otherwise its not output to disk usually

frank bramble
hollow lantern
# frank bramble during build, make the source generator submit the graphql query

We don't need to perform any request to fetch introspection type from Dagger Engine. Since I prior to make it support for Dagger Module as a first class citizen (library later), the engine will send introspection json into the module and use that to generate code, like https://github.com/dagger/dagger/blob/main/sdk/elixir/runtime/main.go#L71.

If we want to publish the SDK as a library to Nuget, I believe we fetch introspection from inside the module or use https://github.com/helderco/daggerverse/blob/main/codegen/main.go#L35 to use it for generate code.

GitHub

Application Delivery as Code that Runs Anywhere. Contribute to dagger/dagger development by creating an account on GitHub.

GitHub

My personal collection of Dagger modules. Contribute to helderco/daggerverse development by creating an account on GitHub.

hollow lantern
digital falcon
#

@frank bramble Good job, I see you got a lot further than I did, so just disregard my issue comment. πŸ™‚

frank bramble
#

can we dagger run pwsh the strawberry shake cli tool which generates code for a graphql api

frank bramble
#

We would take it even further and create Roslyn Analysers to make sure people use the SDK correctly

#

it's got as nice API to write custom rules and you are fed a code synxtax tree and then we can do some fun code that detects user code usage and says "please use X, dont use Y" or "dont chain X,X,X" if we find any limitations or things that would look like it would work in dagger, but actually wouldnt.

frank bramble
#

okay this isnt how i thought it would go

#

You have to write the GraphQL queries you want, then it generates the code for you based on that .graphql query file

hollow lantern
#

@digital falcon nice to see you. ^^

hollow lantern
frank bramble
#
$token = $env:DAGGER_SESSION_TOKEN
$bytes = [System.Text.Encoding]::UTF8.GetBytes("${token}:")
$base64 = [System.Convert]::ToBase64String($bytes)

write-host "http://127.0.0.1:$($env:DAGGER_SESSION_PORT)/ with --token $base64"

# dotnet graphql init http://127.0.0.1:$($env:DAGGER_SESSION_PORT)/query -x Accept=application/json --scheme Basic --token $base64 --clientName DaggerClient -p ./
#

thats the strawberry config setup

#

but its not how i thought it would go

#

looking at some other existing libraries out there, they dont look so fit for purpose with how we likely would want an SDK to suit the dagger style, likely want it aligned as much as possible with other SDks

#

so i think custom code generator is probably still the right way forward

frank bramble
#

i fixed the tests because i broke some code

#

but this is using the source gneerator version. So how does this look in the world of Dagger Functions?

#

Also, if we want nice Builder Pattern, We can use interfaces with the builder for the perfect interaction

frank bramble
#

@hollow lantern

#

haha, i found this

frank bramble
#

Why does this happen

#

this is one example, querry builder is used, a new immutable one is returned, but the following line is using the old one still, QueryBuilder

#
public Container WithEnvVariable(string name, string value, bool expand = false)
    {
        var arguments = ImmutableList<Argument>.Empty;
        arguments = arguments.Add(new Argument("name", new StringValue(name))).Add(new Argument("value", new StringValue(value)));
        var queryBuilder = QueryBuilder.Select("withEnvVariable", arguments);
        return new Container(QueryBuilder, GraphQLClient);
    }
#

should these all be new T(queryBuilder, Client) ?

#

I am thinking of something like this

hollow lantern
#

Ouch it’s something missing during refactoring on the afternoon somehow. Will fix that in around 1 hour. ><

frank bramble
#

okay so i am not wrong in understanding

#

I made fix on my "clone" of your repo

#

but actually i am finding behaviour is not how i am expecting 😦

#

this appears to work but then exec is empty. Even with my fix on queryBuilder

hollow lantern
#

Fixed.

frank bramble
#

found it

#

args is not being used πŸ˜„

#

line 447 need to pass args into list

#

I guess this is prototype, so many more variable need to be implemented

#

I think we should merge the Roslyn source generator into your one somehow or cleanup

digital falcon
#

Hi @hollow lantern and @frank bramble nice to see your progress. It would be nice if you were both working on a fork so that others could check it out and perhaps chip in. πŸ™‚

frank bramble
#

yeah..

#

Can we maybe get both the roslyn stuff I did and wingys stuff into a branch off the Dagger repo?

Issue is kind of like what Wingy was saying, he wants a fast prototype section

#

and so did i becuase i changed a lot

hollow lantern
#

I’m thinking about extracting the dotnet-sdk source out of my daggerverse repo so we can continue put it more forward. What do you think?

frank bramble
#

most of my stuff is just wingys code, except i modified some stuff:

  • netstandard had to add shims for new c# lang features (rwquired keyword) so i could keep how wingy had it
  • source generator which works on ctrl+shift+b
  • some fixes with the Querybuilder code
  • removed Nuget dependency on Pascal Casing
#

yeah, i thin its a good idea wingy

#

and i can make a PR to apply my changes on top?

#

i cant stop thinking about your nickname wingy, wingyplus sounds like copilot on steroids

digital falcon
#

Just do a fork each and merge with each other's once in a while.

hollow lantern
hollow lantern
frank bramble
#

okay so something I dont understand next

#

is it 'wrong' to include this introspection.json schema file?

frank bramble
hollow lantern
#

Because source generator needs it at compile time, right? I’m ok to include that file to the repo. πŸ‘

#

You can run dagger call introspect export β€”path=<path> from the root repo to generate introspection.json file for you.

digital falcon
#

Including or calling introspect depends on what we want to achieve.
Do we want a fixed client, based on the last time the include was updated?
Or do we want to generate the client based on the current Dagger version?

hollow lantern
#

The Dagger Module will pass the introspection json file during its generating code. So we can put it to the Dagger.SDK to use that for generating by SourceGenerator.

hollow lantern
#

Where is the source that Source Generator generated? I try to find it for debugging purpose.

hollow lantern
hollow lantern
frank bramble
#

woop nice

#

We can customise for debugging EmitCompiler, and in prod build of sdk, we can remove. For now i think its okay, this thing we can cleanup much later on, anything is possible

frank bramble
digital falcon
frank bramble
hollow lantern
hollow lantern
#

Documentation is working now. πŸ™‚

hollow lantern
frank bramble
#

this is awesome!

#

I love the way you build out the .NET project with the correct .net command line tools

hollow lantern
#

@frank bramble @digital falcon what a lint tool do you use to linting the csharp source file? Just want it to setup the CI.

frank bramble
#

I suggest we use what dotnet team use.

#

we can also enable csproj analysers

#

roslyn team probably have good one considering it's csharp compiler platform.

#

csproj we add EnableNETAnalyzers similar to emitCompilerGenerated

hollow lantern
#

Oh, it looks very easy. Thanks ❀️

frank bramble
#

I think we should steer clear of dotnet being the sdk name and use csharp. I've spoken to a member in a team who heavily uses f# in the finance business and kinda agree. if we don't build a magical all in one sdk that works for vb/fs/Cs it might be better to focus on csharp for dotnet.

#

I raised a issue on the github repo maybe it needs more discussion

hollow lantern
#

Yeah, let's discuss on the issue. πŸ‘

frank bramble
#
C:\Projects\pjmagee\dagger-dotnet-sdk\sdk [chores ≑ +0 ~1 -0 !]> dagger call introspect export --path ./Dagger.SDK/introspection.json
βœ” DotnetSdk.introspect: File! 2.4s
  βœ” Container.file(path: "/introspection.json"): File! 1.3s
    βœ” start dockerd --host=tcp://0.0.0.0:2375 --host=unix:///var/run/docker.sock --tls=false 1.6s
    ┃ ainerd.nri.v1
    ┃ time="2024-06-05T18:06:33.032716002Z" level=info msg="NRI interface is disabled by configuration."
    ┃ time="2024-06-05T18:06:33.032826453Z" level=info msg=serving... address=/var/run/docker/containerd/containerd-debu
    ┃ g.sock
    ┃ time="2024-06-05T18:06:33.032866276Z" level=info msg=serving... address=/var/run/docker/containerd/containerd.sock
    ┃ .ttrpc
    ┃ time="2024-06-05T18:06:33.032895978Z" level=info msg=serving... address=/var/run/docker/containerd/containerd.sock
    ┃
    ┃ time="2024-06-05T18:06:33.032927737Z" level=info msg="containerd successfully booted in 0.016144s"
    ┃ port is up: 10.87.0.93:2375
      βœ” 2375/tcp 1.3s
✘ File.export(path: "./Dagger.SDK/introspection.json"): Boolean! 0.0s
! unexpected closing recv msg: rpc error: code = Unknown desc = failed to chown synctarget dest file C:\Projects\pjmagee\dagger-dotnet-sdk\sdk\Dagger.SDK\introspection.json: chown C:\Projects\pjmagee\dagger-dotnet-sdk\sdk\Dagger.SDK\introspection.json: not supported by windows
  ✘ export file /introspection.json to host ./Dagger.SDK/introspection.json 0.0s
  ! unexpected closing recv msg: rpc error: code = Unknown desc = failed to chown synctarget dest file C:\Projects\pjmagee\dagger-dotnet-sdk\sdk\Dagger.SDK\introspection.json: chown C:\Projects\pjmagee\dagger-dotnet-sdk\sdk\Dagger.SDK\introspection.json: not supported by windows

Error: response from query: input: container.from.withoutEntrypoint.withServiceBinding.withEnvVariable.withExec.withExec.withNewFile.withExec.file.export resolve: unexpected closing recv msg: rpc error: code = Unknown desc = failed to chown synctarget dest file C:\Projects\pjmagee\dagger-dotnet-sdk\sdk\Dagger.SDK\introspection.json: chown C:\Projects\pjmagee\dagger-dotnet-sdk\sdk\Dagger.SDK\introspection.json: not supported by windows
#

for now i use WSL.

#

only found this because win deleted introspection.json πŸ˜„

hollow lantern
#

Oh, I never hit this issue because I use WSL too. πŸ˜‚

hollow lantern
hollow lantern
#

I feel like it gonna be a dagger script now. πŸ˜‚

What I do is building the sdk and then load the dll into Powershell. The Powershell is incredible, you can get autocomplete after load the SDK dll into the shell. O_O

1 issue I see is dagger run got crash when I'm using dagger run pwsh . 😦

And if we want to make it run anywhere, we might need to publish the SDK to Nuget, I guess.

#

☝️ The example above I use DAGGER_SESSION_TOKEN=<token> dagger listen to start the graphql server and set env manually because the SDK doesn't support auto provision engine. πŸ™‚

frank bramble
#

powershell plugin in vscode is good too

frank bramble
#

powershell supports publishing modules and it could depend on the .net dll somehow

#

Import-Module 'Dagger' something like this

hollow lantern
digital falcon
frank bramble
#

most .net would be familiar with nuget. I think since dagger sets up the sdk. we could configure the registry with some configuration if its better

#

ghcr isn't only for images?

hollow lantern
#

Oh I didnt realize ghcr already supported it.

frank bramble
#

same

frank bramble
#

@hollow lantern i did rebase and it works okay

#

The experience is weird tho, running test in ide not possible

#

thorugh the normal runner config anyway

hollow lantern
frank bramble
#

wonder if .NET TEst Adaptor is somehting we could look into

#

I know we have the dagger test idea

hollow lantern
# frank bramble thorugh the normal runner config anyway

I just find the way yesterday:

  1. Run DAGGER_SESSION_TOKEN=<token> dagger listen. It will listen on port 8080, I assume and you can replace <token> with any token you want.
  2. Set 2 env variables, first DAGGER_SESSION_TOKEN=<token> and second DAGGER_SESSION_PORT=8080.
  3. Run test << This step should works.
frank bramble
#

ohh

#

too many hidden cmd

#

πŸ˜›

hollow lantern
#

It is the secret command πŸ˜‚

hollow lantern
frank bramble
#

ITestExecutor could potentially wrap - i need to look into it later

hollow lantern
hollow lantern
#

Update for https://github.com/wingyplus/dagger-dotnet-sdk/pull/7. I just made a dagger functions works by fetch class information from reflection in potato module. πŸ˜„

And also update the module to use Dagger 0.11.7 to support a new module runtime api (introspection changed from string to File).

GitHub

GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.

digital falcon
#

Very cool!

barren bay
#

Looking good! I can tell you there's a lot of demand for a .net sdk, people are excited 😁

frank bramble
hollow lantern
hollow lantern
#

My potato is working now. T_T

hollow lantern
hollow lantern
#

@frank bramble @digital falcon I have kickstart the Dagger.SDK.Mod.SourceGenerator to generate necessary classes for dagger module. It would be nice if you could help me review the design on user code https://github.com/wingyplus/dagger-dotnet-sdk/pull/7/files#diff-e539ec19055ab375c2fd435120e273e4d5b2505c11b293f7c97cbfd00dcf4a8e and the source generator https://github.com/wingyplus/dagger-dotnet-sdk/pull/7/files#diff-b9ed2565e5b4a71fbae3029e2df3658368b45ead0091b39480bb9e3586ba5e66.

Please note that the potato module cannot run with dagger call and dagger functions for now, it's in the process of converting to source generator. T_T

And I also list the task that discover during implementing with reflection in the PR description. Feel free to ask if you have a questions. πŸ™

GitHub

Tasks

Every library in the SDK must be netstandard 2.0!
Generate necessary attributes and interfaces for user code.
Generate registration method to convert user code into Dagger.Module for regi...

frank bramble
#

sure. allow some time and I will take a look to give some comments

hollow lantern
#

@barren bay Is it valid to uses Dagger Cloud free access plan with dotnet-sdk repo?

barren bay
hollow lantern
#

Yes

barren bay
#

We were just talking about that actually. At the moment Dagger Cloud doesn't work great for open source projects, since you need an account to view the traces, and even then you can only see your own traces.

#

So it's not that we don't want you to use Dagger Cloud, it's just that only you will be able to see the traces

#

We are looking for a solution to that. In the meantime, of course you are welcome to use Dagger Cloud in that repo

hollow lantern
#

Thank you for the answer. Only me can view the traces is fine for now. πŸ™

frank bramble
#

@hollow lantern theres so many changes here

#

I think i need to pull the branch and run it to understand more

hollow lantern
# frank bramble <@105929805786001408> theres so many changes here

I didn’t realize that it’s big now. T T

By the way if you wanna try on that branch, I just make registering module in source generator version works. I do move the invoke method to the potato module to make it works, you can start reading from https://github.com/wingyplus/dagger-dotnet-sdk/pull/7/files#diff-1a5f09f4693df3e2f7cc839a1021b445756f6fd4309ec51808a3edb2471613bfR15.

GitHub

Tasks

Every library in the SDK must be netstandard 2.0!
Generate necessary attributes and interfaces for user code.
Generate registration method to convert user code into Dagger.Module for regi...

hollow lantern
#

This tool is very interesting https://nuke.build/docs/cicd/github-actions/

They can even support auto-generate GitHub workflow (other CIs are also supported) by using C# code.

Running on GitHub Actions will automatically enable custom theming for your build log output including collapsible groups for better structuring:

frank bramble
#

a few teams in my workplace are using this.

tiny crest
#

We are currently heavily using Nuke.Build, but would really like to migrate to dagger, but the lack of Windows containers support is preventing us as several major projects we build have windows dependency (WPF) πŸ˜’

frank bramble
# tiny crest We are currently heavily using Nuke.Build, but would really like to migrate to d...

if you have any netstandard libs or nugets internally, you may still be able to utilise some dagger. your main repo/project obviously needs the windows Agent but there is a possibility of maybe looking into individual components? There's also other benefits on dagger over builds and publishing containers. If you have any projects or pipelines in the company utilising any tooling, dagger could be useful there. Ive had a few use-cases where it's taking file inputs and dumping files as outputs - and now i can move that from gitlab to github easily.

tiny crest
#

The flexibility in movment between computing providers like GitHub Actions and Azure DevOps Pipelines is definitely something that attracts to dagger. And we do have some netstandard internal packages, but having ~80% net8.0-windows and .net 4.8 apps makes "diversification" into dagger quite a questionable idea from the stakeholders POV πŸ˜’

frank bramble
# tiny crest We are currently heavily using Nuke.Build, but would really like to migrate to d...

could your org look into this? https://avaloniaui.net/xpf

LinqPad is going full xplatform using this, and I've loved linqpad for over 10 years, but it ws only running on Windows, but its coming to mac soon and its going to stay as WPF

Avalonia UI

Avalonia XPF is a Cross-Platform fork of WPF, enabling WPF apps to run on Windows, macOS and Linux with little to no changes.

quasi meadow
#

Nuke question

hollow lantern
#

@barren bay @fiery trellis Hi, I would like to discuss about the DotNet SDK.

What do you think if we merge the https://github.com/wingyplus/dagger-dotnet-sdk into the dagger repository to replace the current dotnet implementation? At the current state, it can generate the sdk from introspection. The module support is still pending on https://github.com/wingyplus/dagger-dotnet-sdk/pull/7.

GitHub

Dagger DotNet SDK. Contribute to wingyplus/dagger-dotnet-sdk development by creating an account on GitHub.

GitHub

GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.

fiery trellis
#

If no one opposes, go for it (I mean in the community). What's the difference between your implementation and what's in our repo btw? Does it have a different DX?

hollow lantern
#

The current implementation has only graphql client. My implementation fork from the official and make the generate sdk part works.

fiery trellis
#

Oh, then what's been holding you on making a PR? 😁

#

When you have it, share the URL here to ping dotnet devs in the channel to help review. πŸ™

barren bay
#

Thank you @hollow lantern !

hollow lantern
hollow lantern
hollow lantern
frank bramble
digital falcon
#

Thanks for including me, though I do not feel that I contributed much. I will have a look at the PR and help what I can. πŸ™‚

frank bramble
#

@hollow lantern can dagger init sdk work from that PR?

#

i.e i want to see what it looks like when the '.dagger' is created from a fresh repo

#

and open visualstudio/rider/vscode

frank bramble
#

I want to be able to run dagger develop --sdk=github.com/wingyplus/dagger-dotnet-sdk/tree/main/dev dotnet but im struggling

hollow lantern
hollow lantern
#

@frank bramble Do you mind if squash those commits on that PR into a single commit? The commits is nearly 100 and make me hard to rebase. πŸ˜‚

hollow lantern
frank bramble
hollow lantern
#

I’m open a PR to implement CI pipeline for dotnet here https://github.com/dagger/dagger/pull/8762.

I found the problem that DotNet got hang during build on the CI. 😦 Found this similar issue on my Apple M1 machine as well.

Do you have any idea why it is hang?

GitHub

GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.

frank bramble
#

@hollow lantern I was playing around with roslyn syntax framework. and when trying to understand source gen I found a bug i think, I raised it on your repo, its about optional args and default values like bool? optional= true or string? dockerFile = "DockerFile" as part of function params.

Also thinking of Roslyn Syntax usage, i made a clone and did quick poc (but its not finished) - See how I am generating types using Syntax class, to create classes/parameters/arguments: https://github.com/pjmagee/DaggerSDK/blob/master/SourceGenerator/Dagger.Sdk.SourceGenerator/SchemaCodeGenerator.cs#L76
Example output (but i didnt handle the function implementation with builder + graphql client), but it shows you how it renders:

https://gist.github.com/pjmagee/a7936885d18695b1a5f4d24d05acf271

I was also thinking about partial class usage and partial function usage and wondering if we can have any benefits with partial? This is someitmes useful if we want a type created already, but have code generator 'extend' existing class with features.. not sure if this could be useful at the moment

Gist

Roslyn syntax . GitHub Gist: instantly share code, notes, and snippets.

GitHub

POC for Dagger .NET SDK. Contribute to pjmagee/DaggerSDK development by creating an account on GitHub.

frank bramble
hollow lantern
#

Roslyn syntax

frank bramble
#

@hollow lantern https://github.com/dagger/dagger/pull/9288, I did not implement all the roslyn code I showed above, i wanted to make smaller steps and fix existing sdk not work with 'Engine' clash, but added some smaller fixes in this as well

GitHub

renamed Engine to QueryExecutor due to clash with latest API. This aligns both QueryBuilder and QueryExecutor to be similar and related

update introspection.graphql, Looks to be some changes to t...

hollow lantern
bold pebble
# bold pebble **Unofficial alpha-stage** C# Dagger SDK is now on NuGet: https://www.nuget.org/...

Hey dotnet daggernauts. I wrote the SDK at the beginning of this channel (not the one that was recently replaced, but a fork of it that brought it mostly up to par with the other SDKs as of 9.7, pre-Modules, and never attempted to merge into upstream).

I'm sorry I haven't checked Discord in a long time. I see someone asked about how to use my SDK a long time ago and I wasn't around to help 😩

But... I'm glad to see that interest in Dagger + dotnet has increased.

In the intervening months, I actually have been using my SDK on a regular basis. But the recent introduction of interactive debugging was the push I needed to prioritize getting upgraded to the newer modules paradigm.

I did so over the past week. There's still some tidying up to be done, but I have pushed most of my progress so far. I'm sorry if it's annoying to anyone to hear that other work has been done in parallel. I didn't notice any of the work that had been done since the merge two months ago. Only that the implementation had been swapped out and added codegen, but that its codegen was still less robust than what I had earlier this year. But what's nice about open-source is that it's a missed opportunity at worst, constructive at best, and not a problem of any urgency for anyone. I hope my new work is well received.

I've made an effort to do things "the dot net way", and frankly I've had a lot of fun with it.

How far along am I with module support? I'd say about 95%. Hello world works. Calling other modules and returning a modified version of their output works. Chaining works. I can dagger call -m Pipelines nuget-server as-service up to run a local nuget server based on a C# Dagger pipeline. I can call a C# module from a Go module.

bold pebble
frank bramble
# bold pebble

Hey @bold pebble , thank you for this. I will watch this today soon

hollow lantern
bold pebble
#

Yes. The version in the video is the same as what's online right now.

hollow lantern
potent grove
hollow lantern
#

πŸ‘‹sorry for the late reply.

From the https://github.com/dagger/dagger/pull/8762

the introspection function is removed out of the dotnet dev module. If you want to generate code, change the directory to root dagger repository and run:

dagger call sdk dotnet generate export β€”path=.
GitHub

Add Dotnet to the SDK type and implements 3 functions, lint,
test and generate. Those functions are calling dotnet-sdk-dev
module that living inside sdk/dotnet/dev.
The custom dagger code in dev mo...

hollow lantern
#

I didn't realize that C# has an API to construct code until reading a code from @bold pebble fork. 🀩

hollow lantern
#

@frank bramble @bold pebble I'm opening an issue about Dagger Module here https://github.com/dagger/dagger/issues/9391. It would be a good starting place to discuss the good/bad parts and list action items together. πŸ™‚

GitHub

An engine to run your pipelines in containers. Contribute to dagger/dagger development by creating an account on GitHub.

bold pebble
#

I didn't realize that C# has an API to

bold pebble
#

The day has finally come. dagger init --sdk=https://github.com/m-pixel/dagger/sdk/dotnet/module@m-pixel-csharp is all you need to have a working C# module.

Of course, there's still a lot of work ahead. Surely some edge-cases that have yet to be discovered. Performance optimizations to be made (though it's already faster than the TypeScript SDK). But with that out of the way, I can start engaging more with the discussion about how to reconcile efforts without stressing about my deadline.

digital falcon
#

SDK

digital falcon
#

What is the state of things?
I got the SDK from @bold pebble working, but have not been able to do so with the one merged into the official repo.

bold pebble
#

State of two SDKs

frank bramble
#

@bold pebble - i think i noticed something, but would like your thoughts - when the module code is changed, i.e a change a function, id have thought that would be built by the dotnet sdk, but it looks like i need to 'build' the code locally, before it actually picks up the change. with the other sdks i dont think this is the case? i'd have thought pure code, no bin/obj output would ever be 'recognised'

bold pebble
frank bramble
#

would that include the Dagger.Generated.dll

#

have you come across something odd where the dagger function call returns this:

Name Description
get-hash-code -
to-string -

#

these arent defined in my dagger module at all, its somehow falling back to something else

#

I dont think the gitignore is doing what i want, i wouldnt commit those files either way, but i think locally - the bin is always being used until rebuilding is done before calling dagger

#

Another question out of curiousity, what do you see is the benefit of the modules being compiled dlls 'as a module'

#

so instead of reflection, the thunking can process the compiled binary so its readily usable or analysed by dagger functions?

bold pebble
#

I dont think the gitignore is doing what

bold pebble
#

One thing to clarify - Thunking is not a concept unique to my SDK. Go SDK does it roughly the same way. I assume that Java and most of the others would as well.

TypeScript is a bit different. It expects what I'll call the main() function of the program to be in the module source. I think that's a fragile design and undesirable, but for some languages it may be necessary. It's better to have a design where it's impossible to not have a main function that does what you think it does; a module shouldn't be able to change the implementation of e.g. parameter marshalling logic.

Even then, it wouldn't necessarily be incorrect to refer to TypeScript SDK's entrypoint as a thunk. It still does thunky things like looking up a function based on a string and arranging its input parameters.

One way to think of it is a plugin pattern.

What's unique is that I'm calling it "thunk", which I believe is the more accurate and specific term for what most of these SDKs are doing (and thus all of them should use that term). "Entrypoint" isn't technically incorrect but it's too vague and overloaded.

I'm not sure what you mean by "how many dlls". Only one assembly will be searched for functions to treat as Dagger functions. It can have as many dependencies as you want.

bold pebble
bold pebble
# frank bramble Another question out of curiousity, what do you see is the benefit of the module...

I'll answer that with a question (not being sassy, just illustrative): What do you see as the benefit of using apt get instead of compiling from source? Why does NuGet distribute DLL files instead of source code? Do you think it would be better, when you do docker run docker.io/alpine for it, instead of pulling a filesystem gzip as it currently does, to clone the alpine repo and construct that on your local system?

It ultimately just goes back to the general sofware architecture question of "where is it (dis)advantageous to cache?".

With C++ there are advantages to compiling from source instead of using ELFs, because there are dozens of compiler options that, if mismatched, can cause linking or runtime errors. That's why we have Nix. C as well, but to a lesser degree. If there were a Dagger C++ SDK, though, those flags could be standardized to enable binary distribution.

With JavaScript, Python, and other interpreted languages, it's sort of fundamentally impossible to have a difference between "the source" and "the build". There's more nuance to it than that with minification, but it's besides the point.

When it comes to C#, Java, and other JIT'd languages, with their excellent IL specs and robust reflection and dynamic dispatch systems, you basically lose all of the reasons to prefer source code over IL, as long as you're not planning to iterate on that source code yourself.

Dagger caches, yes, but not having to check the hash of a bunch of source files makes a difference, and cold start time negatively impacts the elasticity of a scalable build infrastructure. Reducing disk requirements is a good thing. Users of a C# module who are not themselves compiling C# projects in their Dagger engine would probably rather not have the 700MiB dotnet SDK that's required to build from source taking up space in their finite cache.

bold pebble
# frank bramble so instead of reflection, the thunking can process the compiled binary so its re...

Okay, last one, here we go... Yes, basically. I don't like how the current implementation requires invocation to reverse-engineer a bunch of stuff and figure out a lot of the same things that introspection had already figured out moments earlier (but in a different process). But it's kind of a necessary first step, I think it would be too hard to go straight for the ideal implementation without first having his one as reference.

In essence, I think it would be great if as much as possible were moved from Thunk to Primer. Imagine for example that Primer generates some code like this:

Invoke(string functionName, string objectTypeName, string objectJson, IReadOnlyDictionary<string, string> argumentsJson, JsonSerializer json)
{
    switch (objectTypeName) {
        case "MyModule":
            switch (functionName) {
                case "Foo":
                    DaggerReturn<Bar>(MyModule.Foo(json.Deserialize<int>(argumentsJson["blah"])));
                    break;
            }
            break;

        case "Bar":
            var subject = json.Deserialize<Bar>(objectJson);
            switch (functionName) { ... }
            break;
    }
}

Reflection is going to need to occur either way. But let's do it once. Right now, the invocation class figures out whether a return value is a Task that needs unwrapping or not every single time you invoke. I say let it figure that out once, and then generate a maximally optimized static thunk based on that information, and even link it against the user's module so that structs and primitives don't need to go through object boxing every time they pass between JSON and the module's internals.

hollow lantern
#

Sorry that I can't join a fun discussion. I'm a bit busy this week (and maybe next) to work on data engineer stuff and migrating ci/cd to dagger. 😒

frank bramble
#

I think im pretty much happy to try and push this alternative sdk in, and the one we have merged now which doesnt support modules...

  1. We split into another one as less developed, but i dont know why we would this
  2. we have it still in its current state in git history, so i dont think there is any foul play here if we can replace with what you have, i think its more developed - even when i wanted to introduce some more Roslyn you have already done these thingts
  3. i am happy to contribute and improve on yours once we get a merge in!!

Some other thoughts:

  1. Code style?? can we do something similiar as wingy put in like csharpier (we want it community maintained, who knows who'll be around later on)
  2. the infamous Async/Await naming - ive seen most of microsoft code using this suffix, can be eaiser to know what is await/awaited and also clearly defines the leafs (Stderr, stdout, exitCode) - What do we wanna do here??? ( I really like the additional 'boilerplate' but its always a contenious topic, maybe we need to throw in a microsoft code style ruleset)
  3. Documentation and maybe a few more examples (module init, and differences between the python/ts/go sdks)
  4. Couple of things which i had some conflicts on like cant name the class Module, or name it Dagger and a few edge cases - i wonder if a code analyser that is also part of the dagger sdk client dll (or inside that?) could highlight some of those things - the explicit interface implementation seems to be needed e.g void IJsonOnDeserialized.OnDeserialized() and just minor bits and bobs like this for the developer experience

5... any others??

potent grove
#

@frank bramble @bold pebble @hollow lantern

Thank you for all of your work on the dotnet experimental SDK. It's great to see all of the collaboration.

In the last few weeks, we've worked on clarifying the various levels of SDKs, and added a "Community SDK" level. This level requires a certain level of maintenance from SDK maintainers and has a docs requirement.

See announcement here:
https://dagger.io/blog/php-sdk
https://dagger.io/community-sdks

If any of you are interested in doing that for dotnet, please let me know! We'd be happy to move dotnet up.

If not, no worries! We are very thankful for all the work that you are already doing to keep dotnet experimental.

frank bramble
#

i think this is probably the next step after we can continue the discussions

frank bramble
#

#dotnet @bold pebble any thoughts on the above? would like to get your module merged in

bold pebble
#

@Patrick @M-Pixel @Win

bold pebble
#

@frank bramble automatic formatter for code style is definitely a must. I hope I can convince everyone to give "treat parentheses the same as curlies" an honest try. It creates a visual symmetry that I find makes codebases much easier to navigate with the eyes. But I realize it's unconventional and may prove unpopular.

#

So far I've stuck with not using Async suffixes. I think a primary reason they're used where they are in the dotnet framework is that they tend to be async versions of functions that are also available as non-async. The other Dagger SDKs don't use async suffix. Although I'm ambivalent enough that I wouldn't mind adding them if that seems to be what most users prefer.

bold pebble
hollow lantern
# bold pebble I created a board on GitHub to plan what merge-ready looks like: https://github....

Thanks for creating a board! I add one issue that I think it is very helpful during dev the SDK module https://github.com/M-Pixel/dagger/issues/20

GitHub

After help working on PHP SDK. We need integration tests in core/integration. Steps are: Add core/integration/module_dotnet_test.go. Add DotNetSuite type to the file. Add TestDotNet to the file. Ad...

hollow lantern
hollow lantern
#

@bold pebble @frank bramble Could we start from merge the codegen + client to the upstream first. I imagine the first PR to upstream (dagger/dagger) would be:

I also have an alternative plan in my mind. Convert our existing SDK codegen in the upstream to the CLI. So, porting the module part should not be hard?

And I have a questions:

  • Which project structure (upstream vs fork) is better for you?
  • Do we need to generate SDK code the repo like the others?

I can start looking on this next week if we have a conclusion. ✌️

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - dagger/dagger

hollow lantern
bold pebble
#

I don't think we want to use csharpier in a project that heavily leverages fluent APIs: https://github.com/belav/csharpier/issues/1512

Dotnet has code formatting built in, actually, and it's quite flexible. dotnet format. I started putting together a .editorconfig for this repo, and I think with a bit of extra scripting it could even be as thorough/invariable as gofmt (although it certainly isn't that way out of the box).

#

@hollow lantern regarding project structure, there are some GH issues from Dagger staff that raise concern about existing SDK structures, particularly overloaded terms like "SDK" and the need for disambiguation disambiguation. It turns out that some of the ways I deviated the SDK structure are informed by the same concerns, so while it differs a bit from the other SDKs, it is hypothetically going in "the right direction" for Dagger as a whole: https://github.com/dagger/dagger/issues/8424

Beyond using "client" instead of "SDK" and "module" instead of "runtime", there are other differences which stem from the architectural differences I explained above, which I attribute largely to dotnet's fundamental differences from Typescript (interpreted) and Go (non-IL).

GitHub

NoteThis is my own brainstorming epic, just putting it out there to allow me to reference it in discussions. It also provides an overview on the subject, allows for tracking and contributions to th...

#

"Do we need to generate [client source] code [into] the repo like the others?" is a good question. Thankfully Roslyn makes it as easy as calling compilationUnitSyntax.NormalizeWhitespace("\t", "\n").WriteTo(streamWriter). But I hope we can get away with not doing that, under the principle of "don't check-in derived artifacts to source control".

#

My fork is missing a "dev" module that runs tests. Sort of. I do have Pipelines which is for CI/CD tasks. It's a C# module instead of a Go one, which is... perhaps controversial.

For running tests, there are obvious impracticalities to that (unless it relies on the previous stable version). And so there's the question, if test running is implemented in a Go module, then should NuGet publishing and whatever else (code formatting) also be implemented in a Go module for consistency? Or we keep some separation for maximum csharpiness.

Either way, I think migrating your tests to the fork is the next step.

I've been preoccupied in my non-work hours with various chores for the past month. But I think I can make this upcoming Sunday a Dagger day.

hollow lantern
frank bramble
#

@bold pebble there's been a few updates to dagger since I last tried your version of the sdk. with the new addition of llm support the dagger community is really growing. I think a lot of people can really benefit if we can get all your hard work merged into the dagger repo πŸ™

bold pebble
#

I'm catching up today. Didn't have time for a while due to health issues. I had been working on code formatting, but honestly I think that can be bumped down to a post-merge task. Currently working on tests!

frank bramble
bold pebble
#

I've been chipping away at integrating with the Dagger repo's GHA setup (with the releaser module and top-level module's publish function). Trying to get a whole release cycle to work by pushing a tag. It successfully publishes the client library to NuGet at this point, and I'm working through some failures on the container publishes.

It's more difficult than it should be to diagnose because Dagger seems to "swallow" errors that occur in execs launched by modules. I'm hoping that's fixed in a newer version (I'm trying to get this all working on an old version so that I can use it to publish the libs for all the intermediate versions).

this trace for example fails when the Go module bootstrap calls a WithExec that returns a non zero exit code, but that WithExec simply doesn't exist in the trace. I can't navigate to it. I can't see its stdout or stderr. The closest thing that shows in the trace is the module function that calls the module function that runs the exec.

If you've got time to assist, this is probably the best starter issue on the board.
https://github.com/M-Pixel/dagger/issues/2

GitHub

This would be implemented in Primer, by changing the conditions that lead it to choose one return code versus another. Steps: Compile the dev module on your local machine Temporarily, locally, edit...

bold pebble
#

dagger init --sdk=https://github.com/m-pixel/dagger/sdk/dotnet/module@sdk/dotnet/v0.16.3: this works and it uses components that were built and published by GHA via Dagger's releaser module.

https://github.com/M-Pixel/dagger/issues/15 is now done. https://github.com/M-Pixel/dagger/issues/20 is next.

GitHub

After help working on PHP SDK. We need integration tests in core/integration. Steps are: Add core/integration/module_dotnet_test.go. Add DotNetSuite type to the file. Add TestDotNet to the file. Ad...

hollow lantern
#

@bold pebble is your fork rebased against the dagger main branch?

bold pebble
#

@M-Pixel is your fork rebased against

upbeat ermine
#

@bold pebble Is there some way to try your dotnet sdk version locally?

spiral bough
#

πŸ‘‹ In one of my PR I've got failures inside the .Net SDK. Basically the code generator not working anymore.
After some exploration, it looks like it's due to a missing case: a list of enum values (it also means it might be the first time this is added to the core API...)
I've found a fix, but to be honest I haven't done C# for almost 20 years, so I'm a bit rusty here...

If some with more knowledge than me on the .Net SDK could have a look at the commit and let me know if that looks OK, that would be appreciated πŸ™
https://github.com/dagger/dagger/pull/10584/commits/59dffb7f1785155caeea3970f9f76c05377d9aa2

I also added a describe function to the TypeRef it was to debug the type and understand it was a NON_NULL -> LIST -> NON_NULL -> ENUM, the full type reference wasn't displayed in the error message. I don't know if that's a good practice or not.
I'm also raising a new exception in case we fall down on an other type not handled as a list value, so that the error will be easier to understand.

hollow lantern
spiral bough
torn sedge
#

Hey hey - I just saw a talk by @weak owl and have experience with dotnet including working on www.nuke.build and energized to help. If there is anything I can do to assist moving dotnet forward into core - I am here and have some time/energy.

barren bay
#

@hollow lantern I have a question about the dotnet SDK πŸ™‚

hollow lantern
#

@Win I have a question about the dotnet

frank bramble
#
D:\Projects\pjmagee\my-dagger-csharp-module-test\dagger-hello-module> ls
D:\Projects\pjmagee\my-dagger-csharp-module-test\dagger-hello-module> dagger init --sdk=github.com/pjmagee/dagger/sdk/csharp/runtime@copilot/add-csharp-sdk --name=my-hello-module
β–Ά connect 0.6s

β—‹ moduleSource(refString: ".", disableFindUp: true, allowNotExists: true, requireKind: LOCAL_SOURCE): ModuleSource! 0.0s
β–Ά .configExists: Boolean! 0.0s

β–Ά ModuleSource.localContextDirectoryPath: String! 0.0s

β–Ά ModuleSource.sourceRootSubpath: String! 0.0s

βœ” ModuleSource.withName(name: "my-hello-module"): ModuleSource! 0.0s
βœ” .withSDK(source: "github.com/pjmagee/dagger/sdk/csharp/runtime@copilot/add-csharp-sdk"): ModuleSource! 4.6s
βœ” .withSourceSubpath(path: "."): ModuleSource! 0.0s
βœ” .withEngineVersion(version: "latest"): ModuleSource! 0.0s
β–Ά .generatedContextDirectory: Directory! 8.6s
β–Ά .export(path: "D:/Projects/pjmagee/my-dagger-csharp-module-test/dagger-hello-module"): String! 0.1s

18:55:10 WRN no LICENSE file found; generating one for you, feel free to change or remove license=Apache-2.0
Initialized module my-hello-module in D:\Projects\pjmagee\my-dagger-csharp-module-test\dagger-hello-module
D:\Projects\pjmagee\my-dagger-csharp-module-test\dagger-hello-module> cat .\Main.cs
using Dagger;
using static Dagger.Dagger;

namespace MyHelloModule;

/// <summary>
/// A generated module for MyHelloModule functions
///
/// This module has been generated via dagger init and serves as a reference to
/// basic module structure as you get started with Dagger.
///
/// Two functions have been pre-created. You can modify, delete, or add to them,
/// as needed. They demonstrate usage of arguments and return types using simple
/// echo and grep commands. The functions can be called from the dagger CLI or
/// from one of the SDKs.
///
/// The first line in this comment block is a short description line and the
/// rest is a long description with more detail on the module's purpose or usage,
/// if appropriate. All modules should have a short description.
/// </summary>
[DaggerObject]
public class MyHelloModule
{
    /// <summary>
    /// Returns a container that echoes whatever string argument is provided
    /// </summary>
    [DaggerFunction]
    public Container ContainerEcho(string stringArg)
    {
        return Dag
            .Container()
            .From("alpine:latest")
            .WithExec(new[] { "echo", stringArg });
    }

    /// <summary>
    /// Returns lines that match a pattern in the files of the provided Directory
    /// </summary>
    [DaggerFunction]
    public async Task<string> GrepDir(Directory directoryArg, string pattern)
    {
        return await Dag
            .Container()
            .From("alpine:latest")
            .WithMountedDirectory("/mnt", directoryArg)
            .WithWorkdir("/mnt")
            .WithExec(new[] { "grep", "-R", pattern, "." })
            .StdoutAsync();
    }
}
D:\Projects\pjmagee\my-dagger-csharp-module-test\dagger-hello-module> dagger functions
β–Ά connect 0.6s
β–Ά load module: . 4.7s

Name             Description
container-echo   -
grep-dir         -

With the help of Copilot

#

The generated code + sdk in this method is avoiding any package, i.e no C# nuget package, just bundle it all with the users Module project. I know the other sdks have libraries pulled from a package manager registry but this is good for iterating on

#

whe win has some time, I'll get him to look at it with me and see what he thinks

frank bramble
frank bramble
frank bramble
frank bramble
frank bramble
frank bramble
#

#dotnet any active dotnetters around?

#

I got copilot to review the SDK and write a report on .NET idiomatic ways of approaching an public API and to also compare against other existing SDKS

#

I'm wondering what thoughts are on optional usage of [Function] and [Field] and [Enum] and have these implicit. Or to only register all those within the modules namespace, so other types wouldnt be registered when pulled in. I like how clean/slim the go sdk is and its implicit how it handles it, and it would make the sdk less bloaty if we didn't need to use attributes

the report by copilot was actually pretty good, and some of it is really more opinionated than being wrong.

rigid heron
#

<@&1113692156289351723> (If you'll excuse a rare ping:) - an update from @frank bramble:

Hey, is anyone with c# experience able to help test my dagger c# sdk on my branch: i added experimental support for modules, fields, interfaces, xml documentation, and a c# nuget standalone client too, wanting some help/feedback
https://github.com/dagger/dagger/pull/11490

GitHub

Hi all,
This is a 2nd jab at doing a dotnet (C#) SDK. I didn&#39;t want to disrupt the existing experimental dotnet SDK. A few reasons:

other sdks are language specific, so &#39;csharp&amp...

frank bramble
#

C# code base, with a C# sdk

upbeat ermine
#

I've been coding dotnet for ages - but I don't know how to help in this matter. Just getting things rolling with the dotnet sdk has historically seems very hard with dagger

#

I would howeever love to see a dotnet SDK for dagger.

#

How do I test the sdk out?

frank bramble
#

hey, you can run dagger init --sdk=pjmagee/dagger/sdk/csharp@csharp/experimental

#

im also looking to think about nice/clean Analyzers e.g

frank bramble
#

I'm now thinking a bit more about final output/template organisation, making a new branch off the current one to play around a bit more and feel how restructuring vendoredsdk with nuget package and stuff feels like, also think it will align better with existing sdks

frank bramble
frank bramble
#

AHHH SO GOOD!

frank bramble
frank bramble
#

for anyone who knows .net well, this example should work from latest dagger cli - dagger -m github.com/pjmagee/daggerverse/aspnet-hello call serve up

This uses the experimental csharp sdk, builds the hello world aspnet starter template and serve it to you over port 5000. the project setup was about a total of 6 command line calls with the dotnet cli, some dagger functions to expose the aspnet default template and serve it to you. demonstrates also a base 'dotnet' module just to showcase it has dependency modules too. I think another example that might be good is maybe just running the dotnet cli tools in dagger and not having a project in the repo, could be another example πŸ™‚

frank bramble
upbeat ermine
#

@frank bramble I'm trying to make sens of what I'm seeing here, these are all daggervers modules right- but does this mean that the dotnet sdk actually works now or are these sort of tied to what exists in the sdk in your dagger git repo?

frank bramble
#

The csharp sdk used is on a fork branch of dagger

#

And these modules in my daggerverse are working as an sdk is actually just another dagger module. Dagger.json is pointing to cshark sdk gitref

#

Only 3 in my daggerverse are c#

upbeat ermine
#

So - if I would like to test the dotnet sdk on something I have local - how do I set that up?

frank bramble
#

Your own dagger cli will then make you a module using that sdk gitref

upbeat ermine
#

ooooh!

#

nice!

frank bramble
#

If you check that line in the dagger.json, that is produced and pointing to the fork of dagger with the csharp 'sdk/module runtime'

#

so long as your dagger module sdk source points to that, you are 'using' this fork/branch and can test it out

upbeat ermine
#

Allrighty! What's the status of getting that into the actual dagger repo?

frank bramble
#

lots of testing πŸ™‚

upbeat ermine
#

Then that's what we are gonna do!

frank bramble
#
GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

#

there are conventions/requirements for it to work:

  • Program.cs must remain, as this provides the hook
  • Main.cs can be renamed, but the main module class name must match the csproj name and also as defined in the dagger.json (snake-case to PascalCase rules)
  • the sdk/ folder is not a nuget, but this matches other sdks, 'vendored' sdk
upbeat ermine
#

Oh! This is so fresh you even use the .slnx solution files!

#

oh man, I gotta clone this locally and ahve a look. Nicely done!

frank bramble
#

i just thought of a new analyzer

#

i can probably ensure the users main module class name matches the dagger.json and if it doesnt, flag a compiler warning/error

upbeat ermine
#

yeah I saw that image above, very very nice indeed

frank bramble
#

I think a second leap, could be no reflection and a source generator. But honestly for now i think this is perfectly fine. Net10 is super performant and reflectionapi was optimized

#

Happy for any suggestions/ideas and contributions @upbeat ermine id love any help we can get

frank bramble
#

probably going to add .editorconfig as part of the template

upbeat ermine
#

These files, are they built in the initial dagger init --sdk=github.com/pjmagee/dagger/sdk/csharp@csharp/experimental-call?

  • Dagger.SDK.CodeFixes.dll
  • Dagger.SDK.Analyzers.dll
frank bramble
upbeat ermine
#

yeah, I was just - WHAT NUGETS ARE THESE?!!!??! πŸ™‚

#

Allright - so I have actually been able to use this thing with dotnet now! Very very nice. Juast being able to use Rider to write these scripts in csharp is AMAZE

#

Now I just gotta figure out how to get sourcecode from my local directory and build it

long tapir
#

@frank bramble Hey πŸ‘‹

I took a look at your PR that add the C# SDK with module support, that's a really nice job and I look forward to review it πŸ˜„
Little question: we already have a dotnet SDK in the dagger/dagger, is there a reason why you did a different SDK instead of extending the current one to add module support?

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - dagger/dagger

frank bramble
#

im still working on it, but one main difference is dotnet one was using source gen, but i found this difficult to work with and wanted to bring it more in same behaviour as other sdks with this vendored sdk approach (pulling src into a new module)

#

I had a vision also, if this becomes usable, it may be pulled out into a base dotnet sdk, and then we could have --sdk=fsharp --sdk=csharp (later on)

long tapir
#

I see, thanks for the explanation.
Ideally we should expose only 1 dotnet (or c#) SDK, so I think we need a plan for that.

frank bramble
#

100% agree

long tapir
#

Let me know when your PR is ready for review or if you have any question!
We'll try to see on dagger side how to handle that double SDK issue

frank bramble
#

I am mid-breaking so if you come into any issues @upbeat ermine i think its possible to add a commit hash in the source gitref - im trying to fix/add some extra analyzer around module naming tied to the dagger.json configuration, but maybe im adding too much complexity

#

I just know its something new comers will end up doing, and some analyzer might really save them some time if it can tell them

#

/mnt/d/Projects/pjmagee/dagger/sdk/csharp/examples/constructor-example/Main.cs(9,14): warning DAGGER012: At least one [Object] class must be named 'ConstructorExample' to match dagger.json module name 'constructor-example' and serve as the module root [/mnt/d/Projects/pjmagee/dagger/sdk/csharp/examples/constructor-example/ConstructorExample.csproj]

upbeat ermine
#

That type of DevEx will be very nice indeed!

#

Once I get back up in the saddle (I've been looking at Dagger since the CUE days) I'm really looking forward to showing this to my teams at work

frank bramble
#

I started watching the youtube videos during CUE days too πŸ˜„ and i was struggling to understand but i was so curious and interested

#

i think then i joined discord here around the time modules were introduced and the CUE sdk was removed

upbeat ermine
#

yeah same here, CUE was a whole different beast

#

I looked at Earthly too back then

#

To me there's just so much good stuff that could come with this. I run a smaller platform team and the possibilities of setting up dev environments and what not using this is just too good. we'll see if I get that far - but I have lots of ideas to test

frank bramble
#

its become more and more relevant too with AI, we need sandboxes more than ever

upbeat ermine
#

oh yeah, container-use was an absolute game changer for me

#

So, can I just ask. If I want to get sources ouf of the host system and into the build (sdk) container - how do I actually o that?

long tapir
frank bramble
upbeat ermine
#

So .WithMountedDirectory("/mnt", directoryArg) mounts a host directory directoryArginto /mnt?

frank bramble
#

yeah and i leave the default path as / (since its from dagger.json)

#

dagger.json is one dir above my .dagger folder

#

so that way it just pulls in all my csproj folders / slnx file

upbeat ermine
#

oh man, this works beautifully in Zed as well!

frank bramble
#

theres a design decision im split on

#

this is important before merged

#

its the suffix of Async

#

microsoft standards / libs recommend it as a convention, and its all over their own frameworks too. it also allows for understanding Task<T> return type, without being explisit, and promptsthe user to know about await calls.

#

But not all the sdks do it, and i know sdks, even in the contributor docs say design the sdk to how that language should feel.

upbeat ermine
#

yeah, I'm all pro the Async-suffix

frank bramble
#

nice okay, not just me πŸ˜„

upbeat ermine
#

hahaha

#

One way to do it is to add that to the analyzer. "Don't forget to await..." and so on

frank bramble
#

i think public made dagger functions should not include this in their function registration though, might want an analyzer to hint/suggest not defining public [Function] with Async unless its a private module

#

i love roslyn analyzers, they seriously help

upbeat ermine
upbeat ermine
#

yeah, he's got all the good stuff in there

#

haha! It builds my totally awesome weatherforecast api!

frank bramble
#

that makes me so happy man

upbeat ermine
#

This is fantastic work @frank bramble !

frank bramble
#

im sure we'll find some bugs or weird edge cases, but having some simple happy path usable examples is going to open our doorway to getting more c# lovers involved

upbeat ermine
#

mos def

#

I've just set up a super simple Aspire project. It doesent even have to be aspire - that's just how it went at this moment

#

I'm gonna make it publish as well

frank bramble
#

cd /mnt/d/Projects/pjmagee/dagger/sdk/csharp/src && dotnet test Dagger.SDK.Analyzers.Tests/Dagger.SDK.Analyzers.Tests.csproj --no-build
Dagger.SDK.Analyzers.Tests test net10.0 succeeded (3.8s)

Test summary: total: 84, failed: 0, succeeded: 84, skipped: 0, duration: 3.5s
Build succeeded in 4.2s

#

analyzer diagnostic tests πŸ™‚

frank bramble
#

he even poked solomon about "when is there going to be a c# sdk" πŸ˜‚

upbeat ermine
#

I met @barren bay last Kubecon EU (London) and I was like this dotnet SDK really has to happen. I had hopes for getting some of my own company time put into this - but I've been swamped with work so it didn't happen

#

Perhaps it will be done by Kubecon EU 2026 in amsterdam

#

!

frank bramble
#
  • to consider static functions
  • analyzers around ctor arguments + field names (i think we might have some funky behaviour here)
  • Analyzer to possibly remove unrequired async/await if we can return Task<T> instead (let the module runtime handle await)
  • Analyzer for returning an object that is not defined with [Object] correctly
  • possibly support for c# record (like how typescript sdk supports type if no functions are required.
  • test usage with dagger generate (havent done anything for this yet...)
frank bramble
upbeat ermine
frank bramble
#

@upbeat ermine whats your thoughts on the GlobalUsings.cs I added? I was thinking maybe even using Dagger; could be removed and add as a default global using, since these modules are very specific.

#

And the csproj removal of System.IO, since System.IO operations make far less sense to allow or even use within a dagger sandboxed environment

upbeat ermine
frank bramble
#

so far a starter template, its probably okay then. to some extent, there is personalisation/customisation allowed, so long as the sdk/ folder is generated and included in compilation, diagnostics, usings can all be modified after the module is created

upbeat ermine
#

yeah, I have to say I'm really looking forward to messing around with this a bit more tomorrow

#

Does the dotnet sdk in the main dagger repo actually work?

frank bramble
#

not in the same way, its more like a dagger client

#

There is one other which mpixel was also working on, its done quite differently to this one, his made use of thunking, compiled dlls as modules, also his runtime hook in was from implementing ISerialisable or something similiar to that if i remember, let me find it

frank bramble
#

I'll be out for a few days from tomorrow, back next week but if youre interesting in going one layer above from using to figuring out how dagger develop, template, tests run:

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

GitHub

An open-source runtime for composable workflows. Great for AI agents and CI/CD. - pjmagee/dagger

frank bramble
# long tapir Let me know when your PR is ready for review or if you have any question! We'll ...

I think its mostly ready, ive had some issues understanding DANG and i might not have all the right integration/tests configured, struggling a bit there but what I can say ive now tested

  • dagger init
  • dagger install of gha module and my own external module and code generate fine
  • added various attributes like other sdks, cache, function, object, field, interface, defaultPath, Ignore, Check
  • async/await functionality
  • very c#/dotnet specific functionality with roslyn analyzers/codefixes to help with the DX of using a c# sdk (essentially IDE/compiler warnings when using attributes wrong etc)
  • vendored sdk/ folder (like other sdks)
  • module runtime
  • draft published nuget package for 'non module version' - we'd need to figure out nuget publish api key / author permissions to nuget.org registry (like how you publish go/python/typescript package)

The current dotnet sdk is not this far in development and is slightly harder to use, plus does not support module runtime

Is there any stats for current dotnet sdk usage, what sort of risk do we have if we were to merge this in replacement of current one?

long tapir
upbeat ermine
#

And I can just say that so far, testing @frank bramble 's SDK has been a breeze!

frank bramble
#

😍

long tapir
frank bramble
#

also just added something missing, so i can mark experimental api functions

frank bramble
#

😍

long tapir
# frank bramble

Yeah there's no snippets of dotnet code in the doc website πŸ˜„

frank bramble
#

i think i might need to remove a feautre on the roslyn analyzers which seems clunky... i dont know why but its hard to know where the producing dagger.json file is placed. I had an analyzer that ensures the user kept the code name in sync with the module name in the json file. But seems like mixed results if using --source or not

#
D:\Projects\pjmagee\daggerverse\humanizer [main ≑]> dagger call number-to-ordinal-words --number=5 --culture="en"
βœ” connect 0.6s
βœ” load module: . 0.9s
βœ” parsing command line arguments 0.0s

βœ” textHumanizer: TextHumanizer! 0.0s
βœ” .numberToOrdinalWords(number: 5, culture: "en"): String! 1.0s

fifth

demonstrates a highly popular nuget library

https://github.com/pjmagee/daggerverse/blob/main/humanizer/Main.cs

GitHub

My Dagger Modules. Contribute to pjmagee/daggerverse development by creating an account on GitHub.

frank bramble
#

new csproj template

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="sdk/Dagger.SDK.props" Condition="Exists('sdk/Dagger.SDK.props')" />
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <RootNamespace>Test1</RootNamespace>
    <EnableDaggerAnalyzers>true</EnableDaggerAnalyzers>
    <!-- Add your custom properties here -->
  </PropertyGroup>

  <ItemGroup>
    <!-- Add your custom NuGet packages here -->
  </ItemGroup>

  <!-- Import SDK build logic AFTER user settings -->
  <Import Project="sdk/Dagger.SDK.targets" Condition="Exists('sdk/Dagger.SDK.targets')" />
</Project>

Idea behind this is dagger develop to not disrupt users csproj packages or customisation, but allow re-generated targets/props which might include mandatory nuget packages or config for the sdk/ folder

normal sentinel
#

@frank bramble I saw your PR and I was really hoping there was a C# sdk available. I'll look around and see what needs doing but if you know what's in the way perhaps I can start there.

frank bramble
#

It's extremely close to being usable and mergable even, though the main dagger branch has changed somewhat I would imagine its still usable now locally to test and try out

#

This shows examples of the SDK being used

#

There is 1 line of code in my PR which would need updating once merged and verified

frank bramble
#

@normal sentinel did you manage to take a look?

normal sentinel
barren bay
#

FYI dotnet enthusiasts: new dagger module, officially maintained, to analyze powershell scripts in an idiomatic way. We're switching to using that as part of our own CI cleanup

#

To use in any project:

dagger toolchain install github.com/dagger/PsScriptAnalyzer
dagger check
#

Or to try inline:

cd MYPROJECT/
dagger -m github.com/dagger/PsScriptAnalyzer check
hollow lantern
#

Nice !