Skip to content

Conversation

@mirkoCrobu
Copy link
Contributor

@mirkoCrobu mirkoCrobu commented Dec 29, 2025

Motivation

Change description

We should add a command and API endpoint (to be used by the App Lab), to export and import Arduino Apps.

The exported format should be the app folder structure, zipped as a single file
When exporting, remove .cache, secrets and data (or provide an option to keep or exclude data)
When importing, the structure and contents of the app must be validated first

Export

GET /api/v1/apps/{appId}/export?include_data=true

parameters:

Include_data : boolean, optional, default: false

Responses

200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="my_app.zip"

400 Bad Request

{
  "details": "The parameter 'include_data' must be a boolean.",
}

404 Not Found

{
  "details": "App with ID '12345' not found.",
}

500 Internal Server Error

{
  "details": "Failed to generate archive.",
}

Export rules

Always exclude:

  • .cache directory
  • secrets(to check)
  • data dir optional( based on the paramiter)

Implementation Details & Trade-offs about zip handling

In-Memory Processing (Buffer)

Pro

  • simple implementation
  • zip creation completes quickly
  • Content-Length can be calculated
  • easy error handling
  • ZIP always valid

Cons

  • RAM consumption depends on app size and number of concurrent requests
  • potential GC pressure on board if multiple exports run simultaneously
  • may not scale well for larger apps

Direct Stream Processing

Pro

  • constant and low memory usage
  • read files once, no temp files needed
  • safe for multiple concurrent requests

Cons
more complex implementation
error during streaming may result in a partially corrupted ZIP
Content-Length cannot be easily known in advance
may be slower than in-memory buffer if using compression

Temporary Zip on Disk

Pro

  • simple implementation
  • Content-Length can be calculated
  • low RAM usage
  • easy error handling
  • ZIP always valid

Cons

  • requires sufficient disk space
  • involves double I/O (write + read) → slower than pure in-memory for small apps

Import

POST /api/v1/apps/import

Headers
Content-Type: multipart/form-data

Body Parameters
file: Binary (The .zip file to upload). Required.

Responses

201 Created Import successful. Returns the id(same response as POST /v1/apps) of the newly created app.

{
  "id": "12345"
}

400 Bad Request (Validation Errors) The file is invalid, corrupt, or the directory structure is incorrect.

{
  "details": "Missing required file 'app.yaml' ."
}

409 Conflict An app with the same name already exists.

{
  "details": "App with ID '12345' already exists."
}

500 Internal Server Error

{
  "details": "Failed to process the archive."
}

Validation Rules

The server must validate the archive before finalizing the import.
If any check fails, the process aborts, and no files are written to the final app destination.
Verify that the file is a valid ZIP archive and check that the archive must contain essential folders:

  • app.yaml (content validation required)
  • sketch dir(content validation required)
  • python dir(content validation required)

Reuse the existing code for validation (also check [this]

// ValidateBricks checks that all bricks referenced in the given AppDescriptor exist in the provided BricksIndex,

Sanitization(after validation): we just import everithing is a valid zip

Drop any file that is not one of the following:

  • app.yaml
  • python dir
  • sketch dir

Implementation Details

  1. Stream to Disk: The incoming stream is saved to a temporary file (e.g., /tmp/upload_my_app.zip).
  2. validation step. If Invalid: Delete the temp files and return an error. If Valid: perform sanitization and extract files to the final destination (/ArduinoApps folder).
  3. Cleanup the temporary files.
  4. return response.

Point to discuss

  • Should support override in case of conflict? --> NEVER (With the current proposal, the user must manually delete the existing one before importing the new one) -> app folder e app name should be equal. two apps are identical if app folder names are identical and app.yaml names are equal
  • Should we set a size limit for the upload? -->not yet
  • Should perform security checks against viruses/malware?
  • Should set a timeout to prevent long uploads? -->not yet

TODO

  • check folder and name apps convention: folder name and app.yaml app name must be the same?

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.

@mirkoCrobu mirkoCrobu force-pushed the issue_647_import_export branch from a9dd57c to d636791 Compare December 30, 2025 08:59
@mirkoCrobu mirkoCrobu requested a review from a team December 30, 2025 14:08
@per1234 per1234 added the enhancement New feature or request label Jan 2, 2026
@mirkoCrobu mirkoCrobu self-assigned this Jan 7, 2026
@mirkoCrobu
Copy link
Contributor Author

mirkoCrobu commented Jan 12, 2026

test on board for import:

  1. Create app structure
    mkdir -p /tmp/manual_test/payload/python

  2. Create file app.yaml
    echo -e "name: Nome Display Originale\ndescription: my app" > /tmp/manual_test/payload/app.yaml

  3. Create file main.py
    echo "print('Hello from Manual Test')" > /tmp/manual_test/payload/python/main.py

  4. Create ZIP
    cd /tmp/manual_test/payload
    zip -r ../test_app.zip .
    cd ..

  5. Check the zip structure
    unzip -l test_app.zip

  6. send command

curl -v -X POST \
  -F "file=@/tmp/manual_test/test_app.zip" \
  -F 'options={"folder_name": "my-custom-folder-id"}' \
  http://localhost:8800/v1/apps/import
  1. Check the result with arduno-app-cli app list and manually into the ~/ArduinoApps folder

@mirkoCrobu mirkoCrobu requested a review from dido18 January 12, 2026 16:02
@mirkoCrobu mirkoCrobu requested a review from dido18 January 13, 2026 10:52
@mirkoCrobu mirkoCrobu requested a review from dido18 January 13, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants