package task
import (
"context"
"fmt"
"os"
"cuelang.org/go/cue"
"github.com/rs/zerolog/log"
"go.dagger.io/dagger/compiler"
"go.dagger.io/dagger/plancontext"
"go.dagger.io/dagger/solver"
)
func init() {
Register("ClientEnv", func() Task { return &clientEnvTask{} })
}
type clientEnvTask struct {
func (t clientEnvTask) Run(ctx context.Context, pctx *plancontext.Context, _ *solver.Solver, v *compiler.Value) (*compiler.Value, error) {
log.Ctx(ctx).Debug().Msg("loading environment variables")
fields, err := v.Fields()
if err != nil {
return nil, err
envs := make(map[string]interface{})
for _, field := range fields {
if field.Selector == cue.Str("$dagger") {
continue
envvar := field.Label()
val, err := t.getEnv(envvar, field.Value, pctx)
envs[envvar] = val
return compiler.NewValue().FillFields(envs)
func (t clientEnvTask) getEnv(envvar string, v *compiler.Value, pctx *plancontext.Context) (interface{}, error) {
env := os.Getenv(envvar)
if env == "" {
return nil, fmt.Errorf("environment variable %q not set", envvar)
// Resolve default in disjunction if a type hasn't been specified
val, _ := v.Default()
if plancontext.IsSecretValue(val) {
secret := pctx.Secrets.New(env)
return secret.MarshalCUE(), nil
if val.IsConcrete() {
return nil, fmt.Errorf("%s: unexpected concrete value, please use a type", envvar)
k := val.IncompleteKind()
if k == cue.StringKind {
return env, nil
return nil, fmt.Errorf("%s: unsupported type %q", envvar, k)