#Quick idea on slightly modified go sdk
1 messages · Page 1 of 1 (latest)
package main
import (
"context"
"fmt"
"strings"
)
func main() {
dag.Environment().
WithCommand(PublishAll{}).
WithCheck(UnitTest{}).
WithCheck(IntegTest{}).
WithShell(Dev{}).
Serve()
}
type PublishAll struct {
// The version of the server and client to publish
Version string
}
func (p *PublishAll) Command(ctx context.Context) (string, error) {
// First, publish the server
serverOutput, err := dag.DemoServer().Publish(ctx, version)
if err != nil {
return "", fmt.Errorf("failed to publish go server: %w", err)
}
// if that worked, publish the client app
clientOutput, err := dag.DemoClient().Publish(ctx, version)
if err != nil {
return "", fmt.Errorf("failed to publish python app: %w", err)
}
return strings.Join([]string{serverOutput, clientOutput}, "\n"), nil
}
func (p *PublishAll) Defaults() {
p.Version = "latest"
}
type UnitTest struct{}
func (UnitTest) Check(ctx context.Context) (*EnvironmentCheckResult, error) {
return dag.EnvironmentCheck().
WithSubcheck(dag.DemoClient().UnitTest()).
WithSubcheck(dag.DemoServer().UnitTest()).Result(), nil
}
type Dev struct{}
func (Dev) Shell(ctx context.Context) (*Container, error) {
clientApp := dag.DemoClient().ClientImage().Container()
return clientApp.
WithServiceBinding("server", dag.DemoServer().ServerImage().Container()).
WithEntrypoint([]string{"sh"}), nil
}
type IntegTest struct{}
func (IntegTest) Check(ctx context.Context) (*EnvironmentCheckResult, error) {
clientApp := dag.DemoClient().ClientImage().Container()
stdout, err := clientApp.
WithServiceBinding("server", dag.DemoServer().ServerImage().Container()).
WithExec(nil).
Stdout(ctx)
if err != nil {
return dag.EnvironmentCheckResult().WithOutput(err.Error()), nil
}
return dag.EnvironmentCheckResult().WithSuccess(true).WithOutput(stdout), nil
}
The improvements are:
- Parameters (for the entrypoints that support them) are now struct fields, which makes it very obvious + intuitive how to add doc strings to them without resorting to hacks where we attempt to parse
//commentsabove funcs and extract parameter-specific doc strings (go has no built-in support for that, but it does have built-in support for comments on struct fields) - A potentially nice+simple route to supporting default values in go (see the
Defaults()method attached toPublishAll) - The env
With*methods no longer have to accept typeany, which I have a fear could become a huge annoyance in the long run since it removes type safety from that part of the code. Instead they acceptinterface { ... }definitions and users get nice IDE errors if they do something wrong
Downsides:
- A little bit more verbose than just straight up funcs
- Accepting an interface rather than
anydoes sacrifice a bit of polymorphism (i.e. we can't makeerroroptional anymore), so that's a tradeoff rather than total improvement
Obviously we have way more on our plate so I'm not going to pursue this unless others think it's just clearly far and away better than the current state, but if you have any opinion beyond "meh" let me know @lunar pagoda @bright gust
I guess also, WithFunction will still have to accept any, no way of avoiding that
Interesting, I like some of the upside but personally prefer the current mode, it's really satisfying when you're able to chain together a bunch of client calls and not have an error return value. Feels more like scripting/composition
Another option for defaults could be expanding on the struct tag support here: https://github.com/sipsma/dagger/blob/ca5fc66308ed51b47d30eae655879eb0c787d6dc/universe/go/main.go#L27
Something like default:"123", which I've seen in some Go CLI option parsers like https://pkg.go.dev/github.com/jessevdk/go-flags