Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions core/dotenv/dotenv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,32 @@ func TestAllExpansion(t *testing.T) {
"SPECIAL": "!@#$%^&*()",
},
},
{
name: "JSON array must be protected with quotes",
environ: []string{
`no_quotes=["ga", "bu", "zo", "meu", 42]`,
`single_quotes='["ga", "bu", "zo", "meu", 42]'`,
`double_quotes="[\"ga\", \"bu\", \"zo\", \"meu\", 42]"`,
},
want: map[string]string{
`no_quotes`: `[ga, bu, zo, meu, 42]`,
`single_quotes`: `["ga", "bu", "zo", "meu", 42]`,
`double_quotes`: `["ga", "bu", "zo", "meu", 42]`,
},
},
{
name: "JSON object must be protected with quotes",
environ: []string{
`no_quotes={"name": "John Wick", "age": 58, "occupation": "assassin"}`,
`single_quotes='{"name": "John Wick", "age": 58, "occupation": "assassin"}'`,
`double_quotes="{\"name\": \"John Wick\", \"age\": 58, \"occupation\": \"assassin\"}"`,
},
want: map[string]string{
`no_quotes`: `{name: John Wick, age: 58, occupation: assassin}`,
`single_quotes`: `{"name": "John Wick", "age": 58, "occupation": "assassin"}`,
`double_quotes`: `{"name": "John Wick", "age": 58, "occupation": "assassin"}`,
},
},
}

for _, tt := range tests {
Expand Down
17 changes: 17 additions & 0 deletions core/integration/envfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,23 @@ func (EnvFileSuite) TestEvalMatch(ctx context.Context, t *testctx.T) {
"single_quoted_var": `"hello, nice '$animal'"`,
},
},

{
name: "JSON array must be protected with quotes",
vars: map[string]string{
`no_quotes`: `["ga", "bu", "zo", "meu", 42]`,
`single_quotes`: `'["ga", "bu", "zo", "meu", 42]'`,
`double_quotes`: `"[\"ga\", \"bu\", \"zo\", \"meu\", 42]"`,
},
},
{
name: "JSON object must be protected with quotes",
vars: map[string]string{
`no_quotes`: `{"name": "John Wick", "age": 58, "occupation": "assassin"}`,
`single_quotes`: `'{"name": "John Wick", "age": 58, "occupation": "assassin"}'`,
`double_quotes`: `"{\"name\": \"John Wick\", \"age\": 58, \"occupation\": \"assassin\"}"`,
},
},
}

for _, tt := range tests {
Expand Down
12 changes: 12 additions & 0 deletions core/integration/testdata/modules/go/defaults/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ func New(
password *dagger.Secret,
// +optional
file *dagger.File,
// +optional
// +ignore=["*", "!**/*.txt", "!**/*.md"]
docs *dagger.Directory,
) *Defaults {
return &Defaults{
Greeting: greeting,
Dir: dir,
Password: password,
File: file,
Docs: docs,
}
}

Expand All @@ -30,6 +34,7 @@ type Defaults struct {
Dir *dagger.Directory
File *dagger.File
Password *dagger.Secret
Docs *dagger.Directory
}

func (m *Defaults) Message(
Expand All @@ -48,6 +53,13 @@ func (m *Defaults) Ls(ctx context.Context, dir *dagger.Directory) ([]string, err
return dir.Entries(ctx)
}

// List the contents of text files in a directory (with an ignore applied)
func (m *Defaults) LsText(ctx context.Context,
// +ignore=["**", "!**/*.txt", "!**/*.md"]
dir *dagger.Directory) ([]string, error) {
return dir.Entries(ctx)
}

// Capitalize a string
func (m *Defaults) Capitalize(s string) string {
return strings.ToUpper(s)
Expand Down
37 changes: 37 additions & 0 deletions core/integration/user_defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,43 @@ func (UserDefaultsSuite) TestDependencies(ctx context.Context, t *testctx.T) {
require.Equal(t, "hello, world!!!!", output, "User defaults should apply to nested dependencies")
}

func (UserDefaultsSuite) TestOptionalDirectoryWithIgnore(ctx context.Context, t *testctx.T) {
c := connect(ctx, t)
docs := dag.Directory().
WithNewFile("README.md", "Thank you for reading me. The end.").
WithNewFile("Makefile", "lol")
output, err := nestedDaggerContainer(t, c, "go", "defaults").
WithDirectory("/foo/mydocs", docs).
WithWorkdir("defaults").
WithNewFile(".env", `docs=/foo/mydocs`).
WithExec([]string{"dagger", "call", "docs", "entries"}, nestedExec).
Stdout(ctx)
require.NoError(t, err)
require.Equal(t, "README.md\n", output)
}

func (UserDefaultsSuite) TestRequiredDirectoryWithIgnore(ctx context.Context, t *testctx.T) {
c := connect(ctx, t)
docs := dag.Directory().
WithNewFile("README.md", "Thank you for reading me. The end.").
WithNewFile("Makefile", "lol")
controlOutput, err := nestedDaggerContainer(t, c, "go", "defaults").
WithDirectory("/foo/mydocs", docs).
WithWorkdir("defaults").
WithExec([]string{"dagger", "call", "ls-text", "--dir=/foo/mydocs"}, nestedExec).
Stdout(ctx)
require.NoError(t, err)
require.Equal(t, "README.md\n", controlOutput, "control - if this fails, something else is wrong")
output, err := nestedDaggerContainer(t, c, "go", "defaults").
WithDirectory("/foo/mydocs", docs).
WithWorkdir("defaults").
WithNewFile(".env", `lsText_dir=/foo/mydocs`).
WithExec([]string{"dagger", "call", "ls-text"}, nestedExec).
Stdout(ctx)
require.NoError(t, err)
require.Equal(t, "README.md\n", output)
}

var nestedExec = dagger.ContainerWithExecOpts{ExperimentalPrivilegedNesting: true}

func (UserDefaultsSuite) TestConstructorOptional(ctx context.Context, t *testctx.T) {
Expand Down
13 changes: 11 additions & 2 deletions core/modfunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1044,8 +1044,11 @@ func (fn *ModuleFunction) loadContextualArg(
}

func (fn *ModuleFunction) applyIgnoreOnDir(ctx context.Context, dag *dagql.Server, arg *FunctionArg, value any) (any, error) {
if arg.TypeDef.Kind != TypeDefKindObject || arg.TypeDef.AsObject.Value.Name != "Directory" {
return nil, fmt.Errorf("argument %q must be of type Directory to apply ignore pattern: [%s]", arg.OriginalName, strings.Join(arg.Ignore, ","))
if kind := arg.TypeDef.Kind; kind != TypeDefKindObject {
return nil, fmt.Errorf("[kind=%v] argument %q must be of type Directory to apply ignore pattern: [%s]", kind, arg.OriginalName, strings.Join(arg.Ignore, ","))
}
if objName := arg.TypeDef.AsObject.Value.Name; objName != "Directory" {
return nil, fmt.Errorf("[ObjName=%v] argument %q must be of type Directory to apply ignore pattern: [%s]", objName, arg.OriginalName, strings.Join(arg.Ignore, ","))
}

if dag == nil {
Expand Down Expand Up @@ -1085,6 +1088,12 @@ func (fn *ModuleFunction) applyIgnoreOnDir(ctx context.Context, dag *dagql.Serve
return applyIgnore(value)
case dagql.ID[*Directory]:
return applyIgnore(value)
case dagql.Optional[dagql.IDType]:
id := value.Value
if dirid, ok := id.(dagql.ID[*Directory]); ok {
return applyIgnore(dirid)
}
return nil, fmt.Errorf("not a directory id: %#v", id)
default:
return nil, fmt.Errorf("argument %q must be of type Directory to apply ignore pattern ([%s]) but type is %#v", arg.OriginalName, strings.Join(arg.Ignore, ", "), value)
}
Expand Down