Skip to content

Conversation

@dido18
Copy link
Contributor

@dido18 dido18 commented Nov 12, 2025

Motivation

Close #68

When a brick with required variables is added to an app created from scratch the operation fails.

This is because the FE (appLab) does not pass the required variables when the PUT /v1/apps/{appID}/bricks/{brickID} is called.

For example, the brick arduino:arduino_cloud has the ARDUINO_DEVICE_ID and ARDUINO_SECRET required.
When it is added to a scratch app, it fails silently.

Additionally, the issue does not occur when an app with a brick already added is cloned.
This is because when an app is cloned the backend does not check if the required variables are missing.

Change description

The following changes are

  1. When a brick is added to an app: DO NOT raise an error, BUT log a Warning and set the required variable as an empty string.
  2. When an app is started or restarted, for each brick in the ' app.yaml`, the following validation is performed:
    1. invalid if a required variable is omitted
    2. invalid if the brick ID is not found in the bricks index
    3. log a warning if a variable does not exist in the brick definition

Additional notes

  • Currently, the only brick that has required variables is arduino_cloud. Starting an app that uses the arduino_cloud without specifying the required variables ARDUINO_SECRET and ARDUINO_DEVICE_ID will raise an error.

Examples of errors

Example:
Given the following app-yaml, where the required ARDUINO_SECRET variable of arduino:arduino_cloud is missing:

name: hello
description: ""
ports: []
bricks:
- arduino:arduino_cloud: 
  variables:
      ARDUINO_DEVICE_ID: ""
icon: 😀

When an app is started

  • from arduino-app-cli
$ arduino-app-cli app start user:ciao
[ERROR] Variable "Arduino_secret" Is Required By Brick "Arduino:arduino_cloud"
  • from the FE:
variable "ARDUINO_SECRET" is required by brick "arduino:arduino_cloud" variable "ARDUINO_DEVICE_ID" is required by brick "arduino:arduino_cloud"

When an app is restarted

arduino@merola:/$ arduino-app-cli app restart user:ciao
[ERROR] Variable "Arduino_device_id" Is Required By Brick "Arduino:arduino_cloud"
Variable "Arduino_secret" Is Required By Brick "Arduino:arduino_cloud"
arduino@merola:/$

Additional Notes

Reviewer checklist

  • PR addresses a single concern.
  • PR title and description are properly filled.
  • Changes will be merged in main.
  • Changes are covered by tests.
  • Logging is meaningful in case of troubleshooting.

@dido18 dido18 changed the title fix(api): add brick allow empry required variable fix(api): allow empty required variable when a brick id added Nov 12, 2025
@dido18 dido18 changed the title fix(api): allow empty required variable when a brick id added fix(api): allow empty required variable when a brick is added Nov 12, 2025
@dido18 dido18 changed the title fix(api): allow empty required variable when a brick is added fix(api): allow missing required variable when a brick is added Nov 12, 2025
@dido18 dido18 marked this pull request as ready for review November 12, 2025 17:24
@per1234 per1234 added the bug Something isn't working label Nov 12, 2025
@dido18 dido18 requested a review from a team November 14, 2025 16:14
@dido18 dido18 changed the title fix(api): allow missing required variable when a brick is added fix(api): allow missing required variable when a brick is added + app validation Nov 14, 2025
@dido18 dido18 marked this pull request as draft November 17, 2025 08:49
@dido18
Copy link
Contributor Author

dido18 commented Nov 17, 2025

Running this script to test the validation of the example 0.5.0

set -o pipefail

base_path="/home/arduino/.local/share/arduino-app-cli/examples"

for dir in $(find "$base_path" -type d -name "sketch" ! -path "*/.cache/*"); do
    parent=$(basename "$(dirname "$dir")")
	echo "\033[32mTesting example: $parent\033[0m"

    if arduino-app-cli app start "examples:$parent"; then
		echo "\033[32mApp started successfully: examples:$parent\033[0m"
	else
		echo "\033[31mFailed to start app: examples:$parent\033[0m"
	fi
	arduino-app-cli app stop "examples:$parent"
	echo ""
done

@dido18 dido18 marked this pull request as ready for review November 17, 2025 10:18
@mirkoCrobu
Copy link
Contributor

mirkoCrobu commented Nov 17, 2025

When a brick is added to an app: DO NOT raise an error, BUT log a Warning and set the required variable as an empty string.

Doesn't this approach risk assigning a non-compatible value for a mandatory variable? What happens in this case?

The result is that the required variable is set as an empty string in the app.yaml (see the tests "do not fail if a mandatory variable is not present").

dido18 and others added 2 commits November 17, 2025 11:59
Comment on lines +15 to +17
if index == nil {
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would bricksindex required

Suggested change
if index == nil {
return nil
}

for appBrickVariableName := range appBrick.Variables {
_, exist := indexBrick.GetVariable(appBrickVariableName)
if !exist {
slog.Warn("variable is referenced but not declared in the brick configuration", "variable", appBrickVariableName, "brick", indexBrick.ID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add this todo for the future

Suggested change
slog.Warn("variable is referenced but not declared in the brick configuration", "variable", appBrickVariableName, "brick", indexBrick.ID)
TODO: we should return warnings
slog.Warn("variable is referenced but not declared in the brick configuration", "variable", appBrickVariableName, "brick", indexBrick.ID)

Comment on lines +455 to +461

err := app.ValidateBricks(appToStart.Descriptor, bricksIndex)
if err != nil {
yield(StreamMessage{error: err})
return
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this here. The check should be done only before starting and not before stopping

Comment on lines +27 to +66
filename: "all-required-app.yaml",
expectedError: nil,
},
{
name: "valid with missing bricks",
filename: "no-bricks-app.yaml",
expectedError: nil,
},
{
name: "valid with empty list of bricks",
filename: "empty-bricks-app.yaml",
expectedError: nil,
},
{
name: "valid if required variable is empty string",
filename: "empty-required-app.yaml",
expectedError: nil,
},
{
name: "invalid if required variable is omitted",
filename: "omitted-required-app.yaml",
expectedError: errors.Join(
errors.New("variable \"ARDUINO_DEVICE_ID\" is required by brick \"arduino:arduino_cloud\""),
errors.New("variable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
),
},
{
name: "invalid if a required variable among two is omitted",
filename: "omitted-mixed-required-app.yaml",
expectedError: errors.New("variable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
},
{
name: "invalid if brick id not found",
filename: "not-found-brick-app.yaml",
expectedError: errors.New("brick \"arduino:not_existing_brick\" not found"),
},
{
name: "log a warning if variable does not exist in the brick",
filename: "not-found-variable-app.yaml",
expectedError: nil,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, this test is very unreadable; the YAMLs are quite small, so it will be better to include them here instead of storing them in different files.


func TestValidateAppDescriptorBricks(t *testing.T) {
bricksIndex, err := bricksindex.GenerateBricksIndexFromFile(paths.New("testdata/validator"))
require.Nil(t, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
require.Nil(t, err)
require.NoError(t, err)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: it is not possible to add the Arduino Cloud brick into a newly created app

4 participants