Skip to content

Commit 3708460

Browse files
committed
fix: enhance brick validation to collect all errors and add new test cases for validation scenarios
1 parent 38b49bc commit 3708460

File tree

5 files changed

+33
-10
lines changed

5 files changed

+33
-10
lines changed

internal/orchestrator/app/parser.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,35 +140,41 @@ func (a *AppDescriptor) IsValid() error {
140140
}
141141

142142
// ValidateBricks checks that all bricks referenced in the given AppDescriptor exist in the provided BricksIndex,
143-
// and that all required variables for each brick are present and valid. It returns an error if any brick is missing,
144-
// if any variable referenced by the app does not exist in the corresponding brick, or if any required variable is missing.
143+
// and that all required variables for each brick are present and valid. It collects and returns all validation
144+
// errors found, allowing the caller to see all issues at once rather than stopping at the first error.
145145
// If the index is nil, validation is skipped and nil is returned.
146146
func (a *AppDescriptor) ValidateBricks(index *bricksindex.BricksIndex) error {
147147
if index == nil {
148148
return nil
149149
}
150+
151+
var allErrors error
152+
150153
for _, appBrick := range a.Bricks {
151154
indexBrick, found := index.FindBrickByID(appBrick.ID)
152155
if !found {
153-
return fmt.Errorf("brick %q not found", appBrick.ID)
156+
allErrors = errors.Join(allErrors, fmt.Errorf("brick %q not found", appBrick.ID))
157+
continue // Skip further validation for this brick since it doesn't exist
154158
}
155159

160+
// Check that all app variables exist in brick definition
156161
for appBrickName := range appBrick.Variables {
157162
_, exist := indexBrick.GetVariable(appBrickName)
158163
if !exist {
159-
return fmt.Errorf("variable %q does not exist on brick %q", appBrickName, indexBrick.ID)
164+
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q does not exist on brick %q", appBrickName, indexBrick.ID))
160165
}
161166
}
162167

168+
// Check that all required brick variables are provided by app
163169
for _, indexBrickVariable := range indexBrick.Variables {
164170
if indexBrickVariable.IsRequired() {
165171
if _, exist := appBrick.Variables[indexBrickVariable.Name]; !exist {
166-
return fmt.Errorf("variable %q is required by brick %q", indexBrickVariable.Name, indexBrick.ID)
172+
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q is required by brick %q", indexBrickVariable.Name, indexBrick.ID))
167173
}
168174
}
169175
}
170176
}
171-
return nil
177+
return allErrors
172178
}
173179

174180
func isSingleEmoji(s string) bool {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: App ok
2+
description: App ok
3+
bricks:
4+
- arduino:arduino_cloud:
5+
variables:
6+
ARDUINO_DEVICE_ID: "my-device-id"
7+
ARDUINO_SECRET: "my-secret"
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
name: App no existing brick
22
description: App no existing brick
33
bricks:
4-
- arduino:not_existing_brick
4+
- arduino:not_existing_brick:
5+
variables:
6+
ARDUINO_DEVICE_ID: "my-device-id"
7+
ARDUINO_SECRET: "LAKDJ"

internal/orchestrator/app/testdata/validator/not-found-variable-app.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ description: App with non existing variable
33
bricks:
44
- arduino:arduino_cloud:
55
variables:
6-
NOT_EXISTING_VARIABLE: "this-is-a-not-existing-variable-for-the-brick"
6+
NOT_EXISTING_VARIABLE: "this-is-a-not-existing-variable-for-the-brick"
7+
ARDUINO_DEVICE_ID: "my-device-id"
8+
ARDUINO_SECRET: "my-secret"

internal/orchestrator/app/validator_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ func TestValidateAppDescriptorBricks(t *testing.T) {
2222
filename string
2323
expectedErr *string
2424
}{
25+
{
26+
name: "valid with all required filled",
27+
filename: "all-required-app.yaml",
28+
expectedErr: nil,
29+
},
2530
{
2631
name: "valid with missing bricks",
2732
filename: "no-bricks-app.yaml",
@@ -40,7 +45,7 @@ func TestValidateAppDescriptorBricks(t *testing.T) {
4045
{
4146
name: "invalid if required variable is omitted",
4247
filename: "omitted-required-app.yaml",
43-
expectedErr: f.Ptr("variable \"ARDUINO_DEVICE_ID\" is required by brick \"arduino:arduino_cloud\""),
48+
expectedErr: f.Ptr("variable \"ARDUINO_DEVICE_ID\" is required by brick \"arduino:arduino_cloud\"\nvariable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
4449
},
4550
{
4651
name: "invalid if a required variable among two is omitted",
@@ -53,7 +58,7 @@ func TestValidateAppDescriptorBricks(t *testing.T) {
5358
expectedErr: f.Ptr("brick \"arduino:not_existing_brick\" not found"),
5459
},
5560
{
56-
name: "invalid variable does not exist in the brick",
61+
name: "invalid if variable does not exist in the brick",
5762
filename: "not-found-variable-app.yaml",
5863
expectedErr: f.Ptr("variable \"NOT_EXISTING_VARIABLE\" does not exist on brick \"arduino:arduino_cloud\""),
5964
},

0 commit comments

Comments
 (0)