Skip to content

fix(compile): install vendor cores from the VPP's board manager URL - #1001

Merged
thiagoralves merged 4 commits into
developmentfrom
fix/vpp-board-manager-url
Aug 10, 2026
Merged

fix(compile): install vendor cores from the VPP's board manager URL#1001
thiagoralves merged 4 commits into
developmentfrom
fix/vpp-board-manager-url

Conversation

@thiagoralves

@thiagoralves thiagoralves commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Problem

Selecting an IndustrialShields board failed the build outright:

Installing Arduino core...
Arduino core install failed: Arduino CLI process exited with code 7
Invalid argument passed: Platform 'industrialshields:esp32' not found

The VPP declares target.boardManagerUrl, and BoardInfoResolver already
resolved it onto BoardBuildInfo.boardManagerUrl — then it was dropped on the
floor. resolveBoardSelection did not copy it onto boardEntry,
InstallArduinoCoreArgs had no field to carry it, and handleCoreInstallation
spawned core install without --additional-urls. Every vendor board index
shipped in a VPP was dead data.

It went unnoticed because every other VPP targets a core that is either built
into arduino-cli (arduino:avr, arduino:samd, arduino:mbed_edge) or
hardcoded in the editor's ARDUINO_DATA list (esp32, STM32, rp2040, FACTS).
IndustrialShields is the first VPP core in neither.

Changes

  • InstallArduinoCoreArgs gains boardManagerUrl; the pipeline forwards it
    from boardEntry, and resolveBoardSelection populates it.
  • handleCoreInstallation accepts the URL and passes --additional-urls to
    core install.
  • handleCoreUpdateIndex takes the URL and is now actually called — it was
    dead code. core install --additional-urls alone is not enough: the CLI
    resolves the platform against its cached index. The refresh is best-effort,
    so a network blip there cannot mask the real install error.
  • The arduino-cli config was written with { flag: 'wx' } and skipped on
    EEXIST, making it effectively write-once — any URL added to ARDUINO_DATA
    never reached an existing install. Missing URLs are now merged into the
    existing file, preserving user-added entries and other settings.

Vendors now ship their board index in the VPP instead of needing a patch to the
editor's hardcoded list.

Verification

Against the real bundled arduino-cli:

BEFORE (no --additional-urls):   (no match)
AFTER  (with --additional-urls): industrialshields:esp32     2.7.1
                                 industrialshields:avr       1.2.1
                                 industrialshields-wis:esp32 2.0.1

Confirmed end-to-end by the reporter: the IndustrialShields VPP now compiles.

Tests

7 new cases — index-refresh-before-install ordering, --additional-urls with
and without a pinned core version, the no-URL regression case, refresh-failure
tolerance, plus pipeline and resolver forwarding. Suite goes 542 -> 549.

Checked they are not vacuous: reverting the two source hunks fails 3 of them.

Paired with openplc-web (shared-core parity).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for installing Arduino cores from vendor board-manager indexes.
    • Vendor index URLs are used during core discovery and installation, including pinned versions.
    • Existing CLI configuration preserves user settings while adding missing supported indexes.
    • Installation continues with a warning if an index refresh fails.
  • Bug Fixes

    • Improved support for vendor-specific Arduino boards.
    • Invalid board-manager URLs are safely ignored without affecting other manifest data.
  • Tests

    • Added regression coverage for vendor URLs, configuration updates, validation, and installation fallback behavior.

A VPP that declares `target.boardManagerUrl` could not be compiled when
its core lives outside arduino-cli's built-in index. Selecting an
IndustrialShields board failed with:

    Invalid argument passed: Platform 'industrialshields:esp32' not found
    Arduino CLI process exited with code 7

The URL was resolved onto `BoardBuildInfo.boardManagerUrl` and then
dropped: `resolveBoardSelection` did not copy it onto `boardEntry`,
`InstallArduinoCoreArgs` had no field to carry it, and
`handleCoreInstallation` spawned `core install` without
`--additional-urls`. Vendor indexes shipped in VPPs were dead data.

It went unnoticed because every other VPP targets a core that is either
built into arduino-cli (arduino:avr, arduino:samd, arduino:mbed_edge) or
hardcoded in the editor's `ARDUINO_DATA` (esp32, STM32, rp2040, FACTS).
IndustrialShields is the first VPP core in neither list.

Changes:

- `InstallArduinoCoreArgs` gains `boardManagerUrl`, forwarded from
  `boardEntry` by the pipeline and populated by `resolveBoardSelection`.
- `handleCoreInstallation` accepts the URL and passes `--additional-urls`
  to `core install`.
- `handleCoreUpdateIndex` takes the URL too and is now actually called -
  it was dead code. `core install --additional-urls` alone is not enough,
  because the CLI resolves the platform against its cached index. The
  refresh is best-effort: a network failure there must not mask the real
  install error.
- The arduino-cli config was written with `{ flag: 'wx' }` and skipped on
  EEXIST, so any URL added to `ARDUINO_DATA` never reached an existing
  install. Missing URLs are now merged into the existing file, preserving
  user-added entries and other settings.

Vendors now ship their board index in the VPP instead of needing a patch
to the editor's hardcoded list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change validates vendor Arduino board-manager URLs, reconciles them into Arduino CLI configuration, propagates them through board resolution and compilation, and uses them for index refresh and core installation. Tests cover valid and invalid URLs, propagation, pinned installs, and refresh failures.

Changes

Vendor board-manager support

Layer / File(s) Summary
Board-manager URL manifest validation
src/middleware/shared/ports/package-manifest-schema.ts, src/middleware/shared/ports/__tests__/package-manifest-schema.test.ts
Manifest targets accept valid HTTPS board-manager URLs. Installed manifests remove invalid URLs while preserving other device fields.
Arduino CLI configuration reconciliation
src/backend/editor/services/user-service/index.ts
Existing Arduino CLI YAML is read and updated with missing shipped URLs without overwriting existing settings.
Board-manager URL propagation
src/middleware/shared/ports/compiler-platform-port.ts, src/backend/shared/compile/pipeline.ts, src/backend/shared/compile/steps/resolve-board-selection.ts, src/backend/shared/compile/__tests__/*, src/backend/editor/compiler/editor-compiler-platform-port.ts
boardManagerUrl is added to installation metadata and propagated from board resolution to installArduinoCore.
Vendor core index refresh and installation
src/backend/editor/compiler/compiler-module.ts, src/backend/editor/compiler/__tests__/handle-core-installation.test.ts
Arduino CLI receives --additional-urls for index refresh and core installation. Refresh failures are logged, and installation continues.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BoardSelection
  participant CompilePipeline
  participant EditorCompilerPlatformPort
  participant CompilerModule
  participant ArduinoCLI

  BoardSelection->>CompilePipeline: Resolve board with boardManagerUrl
  CompilePipeline->>EditorCompilerPlatformPort: Pass boardManagerUrl
  EditorCompilerPlatformPort->>CompilerModule: Start core installation
  CompilerModule->>ArduinoCLI: Refresh index with --additional-urls
  CompilerModule->>ArduinoCLI: Install core with --additional-urls
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: vmleroy

Poem

A rabbit checks each URL with care,
Then passes it through the compiler.
The index refreshes; the core installs.
YAML settings remain in place.
If refresh fails, a warning appears.
The bunny continues the build.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes installing vendor Arduino cores from a VPP board manager URL.
Description check ✅ Passed The description clearly documents the problem, implementation, verification, and tests, but it omits the repository’s DOD checklist and reference sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/vpp-board-manager-url

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/backend/editor/compiler/compiler-module.ts (1)

961-984: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject when the index-refresh process cannot start.

Line 961 creates a promise that only settles on close. If spawn emits error, such as for a missing binary or permission failure, handleCoreUpdateIndex stays pending. The try/catch at Line 1031 cannot continue to core installation.

Add an error listener that rejects the promise. Add a test that emits error.

Proposed fix
       executeCommand.stderr?.on('data', (data: Buffer) => {
         stderrData += data.toString()
       })
+      executeCommand.once('error', reject)
       executeCommand.on('close', (code) => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/editor/compiler/compiler-module.ts` around lines 961 - 984,
Update the promise in handleCoreUpdateIndex around executeCommand to listen for
the child process error event and reject with that error, while preserving the
existing close handling. Add or update a test for handleCoreUpdateIndex that
emits an error from the spawned process and verifies the promise rejects so core
installation can continue through the existing try/catch.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/backend/editor/compiler/compiler-module.ts`:
- Around line 1029-1057: Validate device.target.boardManagerUrl during manifest
loading via PackageManifestSchema, accepting only HTTPS URLs whose path ends in
.json and rejecting local or file schemes and other invalid values. Ensure
invalid values cannot reach handleCoreUpdateIndex or the Arduino core install
command, while preserving the existing behavior for valid URLs.

In `@src/backend/editor/services/user-service/index.ts`:
- Around line 174-195: Update the Arduino CLI configuration update logic around
the additional_urls anchor to recognize valid inline empty sequences such as
`additional_urls: []`, then insert missing shipped URLs while preserving valid
YAML formatting. Keep the existing multiline handling unchanged, and add a
regression test covering an `additional_urls: []` configuration.

In `@src/backend/shared/compile/__tests__/resolve-board-selection.test.ts`:
- Around line 256-283: Remove the unnecessary as unknown as PackageManifest
assertion from the manifest fixture in
src/backend/shared/compile/__tests__/resolve-board-selection.test.ts:256-283 and
construct a type-compatible fixture directly. In
src/backend/editor/compiler/__tests__/handle-core-installation.test.ts:143-147,
replace unchecked assertion casts in the mocked module and fixture helpers with
properly typed mocks or object shapes, covering the referenced cast sites.

---

Outside diff comments:
In `@src/backend/editor/compiler/compiler-module.ts`:
- Around line 961-984: Update the promise in handleCoreUpdateIndex around
executeCommand to listen for the child process error event and reject with that
error, while preserving the existing close handling. Add or update a test for
handleCoreUpdateIndex that emits an error from the spawned process and verifies
the promise rejects so core installation can continue through the existing
try/catch.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 50a5a388-9025-44bd-8e9b-92d403dea99e

📥 Commits

Reviewing files that changed from the base of the PR and between e5fbc33 and 291aded.

📒 Files selected for processing (9)
  • src/backend/editor/compiler/__tests__/handle-core-installation.test.ts
  • src/backend/editor/compiler/compiler-module.ts
  • src/backend/editor/compiler/editor-compiler-platform-port.ts
  • src/backend/editor/services/user-service/index.ts
  • src/backend/shared/compile/__tests__/pipeline.test.ts
  • src/backend/shared/compile/__tests__/resolve-board-selection.test.ts
  • src/backend/shared/compile/pipeline.ts
  • src/backend/shared/compile/steps/resolve-board-selection.ts
  • src/middleware/shared/ports/compiler-platform-port.ts

Comment thread src/backend/editor/compiler/compiler-module.ts
Comment thread src/backend/editor/services/user-service/index.ts
Comment thread src/backend/shared/compile/__tests__/resolve-board-selection.test.ts Outdated
@Gustavohsdp

Copy link
Copy Markdown
Contributor

Review — the fix is right; one red CI check and two things to decide

Reviewed together with the web counterpart Autonomy-Logic/openplc-web#660 — the 5 shared files are byte-identical between the repos. Every finding below is on this (editor) side; the web PR carries none of its own.

The diagnosis is precise and checkable: the URL was resolved onto BoardBuildInfo.boardManagerUrl and then dropped in three separate places (resolveBoardSelection didn't copy it, InstallArduinoCoreArgs had no field, handleCoreInstallation never passed --additional-urls). And the explanation for why nobody hit it — every other VPP targets a core that is either built into arduino-cli or hardcoded in ARDUINO_DATA, IndustrialShields being the first in neither — holds up.

The security question this kind of change demands, and the answer. --additional-urls makes arduino-cli fetch a third-party index and install a board package, and board packages carry toolchain executables that later builds run. I traced the trust chain, and it closes:

  • REQUIRE_SIGNATURE refuses every unsigned import, and the check runs before any manifest field is used as a path or any HAL/plugin is compiled, failing closed. So the URL only reaches the CLI from a manifest signed by a key in TRUSTED_PACKAGE_KEYS.
  • The URL is passed as an array argument (spawn(binary, ['core','install',coreRef,'--additional-urls',url,…])) — no shell, no injection.

One ordering detail that's easy to get wrong and is right here: the "already installed and no pinned version" short-circuit returns before the index refresh, so an offline user with the core present still compiles without touching the network.

Verification: 5/5 shared files byte-identical (git hash-object); 71 tests green on the editor side (handle-core-installation, pipeline, resolve-board-selection), 10 on web.


🔴 format / Format Check is failing on the editor PR

The CI log names exactly one file, and it's one this PR touches:

[warn] src/backend/editor/services/user-service/index.ts
[warn] Code style issues found in the above file.
##[error]Process completed with exit code 1

It's the const missing = shipped.map(…).filter(…) chain, which fits on one line. npx prettier --write src/backend/editor/services/user-service/index.ts clears it.

(My local prettier flagged additional files, including .h/.cpp under resources/sources/Baremetal/ that this PR never touches — a version mismatch on my side. I went by the CI log, which is the authority.)


🟡 1 — additional_urls: [] isn't handled, and that's a hole in this fix itself

user-service/index.ts:184 anchors on /^(\s*)additional_urls:\s*$/m, which requires the key alone on its line. A perfectly valid config written as additional_urls: [] doesn't match, so the method logs a warning and adds nothing.

Why it needs fixing. additional_urls: [] is the shape arduino-cli config init produces — so for any user whose config came from the CLI rather than from an older editor build, the second bug this PR fixes (the write-once config) stays exactly as broken as before. The symptom is also the quiet kind: a warning in the console and a build that still fails with "Platform not found".

Suggested fix. yaml is already a dependency of this repo, so parse → modify → stringify needs no new dependency and removes the whole class of shapes the regex can't see (inline sequences, comments after the key, a quoted key, and so on). A regression test for additional_urls: [] pins it.

Related, from my side: existing.includes(url) is a substring test against the whole file, so a URL that is a prefix of another one, or that appears in a comment, counts as already present and is skipped.

Worth saying what's right here too: the merge is insert-only — it never rewrites the file — and the no-anchor case warns instead of guessing. The risk isn't corrupting someone's config; it's silently not fixing it.


🟡 2 — boardManagerUrl reaches the subprocess with no format or scheme validation

CodeRabbit asked for validation at manifest load and I agree. The angle worth making explicit, because it's what carries the request even with mandatory signing: the signature vouches for the manifest, not for what the URL serves. arduino-cli's package checksums live inside the index it downloads, so a plaintext http:// index is MITM-able and the board package that lands is whatever the attacker's index points at.

Why it's cheap and consistent. package-manifest-schema.ts just gained format validation for the version floors, with the comment "a field a gate reads should not reach it as unknown" — and boardManagerUrl is a field a subprocess argument reads, currently not declared in the schema at all (it rides through .passthrough()). Declaring it as an https-only URL follows the decision already made in that same file days ago.

Impact if left. With signing enforced the practical exposure today is small — but the constraint that makes it small lives in a different repo's key material, while the URL is consumed here with no local guard. Requiring https:// costs one schema line.


What's good

  • handleCoreUpdateIndex was dead code and is now actually called, with the right reason recorded: core install --additional-urls alone isn't enough because the CLI resolves the platform against its cached index. That's the kind of detail you only learn after hitting exit 7.
  • The refresh is best-effort with the rationale stated — a network blip there must not mask the real install error. Correct call on error ordering.
  • Before/after evidence against the real bundled arduino-cli ((no match)industrialshields:esp32 2.7.1), plus end-to-end confirmation from the reporter. For a hotfix, that's the validation that counts.
  • A second bug found on the way: the config written with { flag: 'wx' } and EEXIST swallowed was effectively write-once, so any URL added to ARDUINO_DATA after a user's first launch never reached them and the only remedy was deleting the file by hand.
  • The 10 new cases cover the edges that matter — refresh-before-install ordering, --additional-urls with and without a pinned version, the no-URL regression, and refresh-failure tolerance. Not façade tests.
  • The web side is a genuine no-opinstallArduinoCore returns { ok: true } because the compile service already ships the libraries — so the five shared files are pure plumbing (+117/−0, zero deletions) purely to keep the surface identical.

Verdict

The 🔴 is one command. I'd want 🟡 1 before merge — not for theoretical robustness, but because additional_urls: [] is what arduino-cli config init writes, so there are real users for whom this fix wouldn't work. 🟡 2 is cheap hardening that lines up with the schema decision already taken in that file.

Nothing on the web side needs changing: it carries no findings of its own. Once the editor lands, merge the pair in short sequence — shared-surface plumbing shouldn't sit half-merged, since each repo's sync gate only tolerates divergence while an open PR exists in the other.

Review assisted by Claude Code.

Addresses the review on #1001.

- **Format Check.** `prettier --write` on `user-service/index.ts`; the CI log
  named exactly that file and it was the one statement flagged.

- **`boardManagerUrl` is now validated before it can reach the subprocess.**
  It rides through `PackageManifestSchema` on `.passthrough()` today, so it is
  typed in `types.ts` but entirely unchecked at runtime — and it becomes an
  `--additional-urls` argument to arduino-cli, which downloads a board package
  full of toolchain executables that later builds run.

  Signing a VPP vouches for the manifest, not for what the URL serves:
  arduino-cli's package checksums live INSIDE the index it fetches, so a
  plaintext index can be intercepted and the package that lands replaced.
  Requiring https closes that. Only the scheme is constrained — arduino-cli
  reads compressed indexes (.json.gz, .zip, .bz2) too, so pinning the path
  suffix would refuse valid vendors for no security gain.

  This follows the decision already recorded in this file for the version
  floors: a field a gate reads should not reach it as `unknown`.

  Strict where the artefact enters, tolerant where we only read what is
  already on disk — the same split the floors use, and for the same reason. A
  package installed before this constraint existed has its URL dropped with a
  warning rather than its whole manifest rejected, which would make every
  board it provides vanish from the board lookup on an upgrade the user never
  asked for. Dropping the field leaves it exactly as capable as it was before
  vendor indexes existed.

  openplc-packages carries the matching `"pattern": "^https://"`, so a package
  refused here cannot be built there either.

- **Dropped an unnecessary `as unknown as PackageManifest`** in
  `resolve-board-selection.test.ts`. Verified genuinely redundant: the file
  typechecks without it. The remaining casts CodeRabbit flagged in
  `handle-core-installation.test.ts` are pre-existing jest scaffolding and
  that file's established fixture pattern; diverging from it there would make
  the file less consistent, not more.

Tests: 13 new covering the accepted/refused URL shapes, the compressed-index
case, and the drop-not-reject behaviour on the installed-read path.

All 12 packages in openplc-packages still validate — every boardManagerUrl in
the repo is already https.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thiagoralves

Copy link
Copy Markdown
Contributor Author

Review addressed — pushed in 326e97a3a

🔴 Format Check — fixed. prettier --write on user-service/index.ts; it was the one const missing = … chain the CI log named. I also ran prettier across every file this branch touches, so it should go green.

🟡 1 — additional_urls: [] — valid, and fixed in #1002 rather than here. That PR replaces the regex with the yaml Document API (the suggested parse/modify/stringify), which also fixes the existing.includes(url) substring problem. Not duplicated here because #1002 deletes this code; patching it now would only conflict with the work that removes it. Detail in the resolved thread.

🟡 2 — boardManagerUrl unvalidated — fixed. Now declared in PackageManifestSchema and required to be https, with the matching "pattern": "^https://" in openplc-packages (Autonomy-Logic/openplc-packages#31) so authoring-time and install-time rules stay aligned. Detail in the resolved thread.


On the CodeRabbit finding outside the diff — handleCoreUpdateIndex not rejecting on spawn error

Technically valid, not fixing here. The promise settles only on close, so an error (missing or non-executable binary) leaves it pending and the try/catch cannot fall through.

Two reasons to keep it out of this PR:

  • It is pre-existing and systemic, not introduced here. compiler-module.ts has 5 spawn sites and only 1 attaches an error listener. handleCoreInstallation — untouched by this PR and called on every build — has exactly the same gap.
  • The practical difference is close to nil. The only trigger is the bundled arduino-cli being missing or non-executable, and in that case handleCoreInstallation hangs moments later regardless. Fixing one wrapper and not the other four would read as coverage that isn't there.

It deserves a small dedicated PR that adds once('error', reject) to all five with a test each. Happy to open it — say the word.

CodeRabbit as unknown as casts

Half fixed: the PackageManifest cast was genuinely redundant and is gone. The handle-core-installation.test.ts ones are pre-existing jest scaffolding and that file's established fixture pattern — reasoning in the resolved thread.

Docstring coverage 0.00%

Noise. The changed files are densely commented with JSDoc block comments; whatever the checker counts, it isn't finding them. Every other pre-merge check passes.


Verification

  • Editor: 6087 tests passing, typecheck / lint / prettier clean.
  • Web (migrate(step-7): DevicePort adapter implementation #660): mirrored, all 7 shared files byte-identical, 1474 → 1487 passing; the 19 pre-existing failures on development are unchanged and unrelated (baselined before and after).
  • openplc-packages: all 12 packages still validate — every boardManagerUrl in the repo is already https, so the new constraint breaks nothing.

Merge order

This PR → #660 (shortly after, the sync gate only tolerates divergence while the counterpart PR is open) → #1002 / openplc-web#661 → openplc-packages#31.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/middleware/shared/ports/package-manifest-schema.ts`:
- Line 214: Remove the unnecessary type assertion from value.devices in the
devices mapping expression, relying on the existing Array.isArray narrowing
while keeping device: unknown and the rest of the guard unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d25a377-57fd-469a-916e-fc6ed703102a

📥 Commits

Reviewing files that changed from the base of the PR and between 291aded and 326e97a.

📒 Files selected for processing (4)
  • src/backend/editor/services/user-service/index.ts
  • src/backend/shared/compile/__tests__/resolve-board-selection.test.ts
  • src/middleware/shared/ports/__tests__/package-manifest-schema.test.ts
  • src/middleware/shared/ports/package-manifest-schema.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/backend/editor/services/user-service/index.ts
  • src/backend/shared/compile/tests/resolve-board-selection.test.ts

Comment thread src/middleware/shared/ports/package-manifest-schema.ts Outdated
thiagoralves and others added 2 commits August 10, 2026 13:10
`Array.isArray(value.devices)` already makes `.map` available, and annotating
the callback parameter as `unknown` is what preserves the runtime element
checking — the `as unknown[]` cast added nothing. tsc and eslint are both
clean without it.

Raised by CodeRabbit on #1001.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/backend/editor/compiler/compiler-module.ts (1)

1045-1058: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse #executeArduinoCliCommand for the install spawn.

#executeArduinoCliCommand already appends the .exe suffix on Windows and spawns the binary. handleCoreInstallation repeats that logic at Lines 1045-1050. The same duplication exists in handleCoreUpdateIndex, handleLibraryInstallation, and handleLibraryUpdateIndex. Reuse of the private helper removes four copies of the platform check.

♻️ Proposed refactor for the install spawn
-    let binaryPath = this.arduinoCliBinaryPath
-
-    if (CompilerModule.HOST_PLATFORM === 'win32') {
-      // INFO: On Windows, we need to add the .exe extension to the binary path.
-      binaryPath += '.exe'
-    }
     return new Promise<MethodsResult<string | Buffer>>((resolve, reject) => {
-      const executeCommand = spawn(binaryPath, [
+      const executeCommand = this.#executeArduinoCliCommand([
         'core',
         'install',
         coreRef,
         ...(boardManagerUrl ? ['--additional-urls', boardManagerUrl] : []),
         ...this.arduinoCliBaseParameters,
       ])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/editor/compiler/compiler-module.ts` around lines 1045 - 1058,
Update handleCoreInstallation to invoke the existing `#executeArduinoCliCommand`
helper for the core install arguments instead of constructing binaryPath and
spawning directly. Apply the same reuse in handleCoreUpdateIndex,
handleLibraryInstallation, and handleLibraryUpdateIndex, removing their
duplicated Windows .exe handling while preserving each command’s existing
arguments and result behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/backend/editor/compiler/compiler-module.ts`:
- Around line 1045-1058: Update handleCoreInstallation to invoke the existing
`#executeArduinoCliCommand` helper for the core install arguments instead of
constructing binaryPath and spawning directly. Apply the same reuse in
handleCoreUpdateIndex, handleLibraryInstallation, and handleLibraryUpdateIndex,
removing their duplicated Windows .exe handling while preserving each command’s
existing arguments and result behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b6443c9e-ec15-470b-9bfd-c71d8672cb4a

📥 Commits

Reviewing files that changed from the base of the PR and between 326e97a and 94c28eb.

📒 Files selected for processing (2)
  • src/backend/editor/compiler/compiler-module.ts
  • src/middleware/shared/ports/package-manifest-schema.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/middleware/shared/ports/package-manifest-schema.ts

@Gustavohsdp Gustavohsdp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved

CI is green on both PRs and two of the three review items landed.

Fixed:

  • Format Check — green (326e97a3a).
  • boardManagerUrl validation — done properly, and the docblock records the reasoning better than my comment did: "The signature on a VPP vouches for the manifest, not for what the URL serves. arduino-cli's package checksums live INSIDE the index it fetches", plus the note that this field goes further than a gate because it becomes a subprocess argument that downloads toolchain executables. 87 lines of new tests with it.

Still open — carried, not resolved:

  • additional_urls: [] is not handled. user-service/index.ts:182 still anchors on /^(\s*)additional_urls:\s*$/m, and there's no yaml import. A config written as additional_urls: [] — which is what arduino-cli config init produces — still takes the warn-and-do-nothing path, so for those users the write-once config bug this PR also set out to fix stays as it was. It's not a regression and it doesn't block the IndustrialShields fix, which is why I'm not holding the approval for it; yaml is already a dependency here if someone wants to close it in a follow-up.

Everything I verified for the main fix still stands: the trust chain closes (REQUIRE_SIGNATURE refuses unsigned imports before any field is used; the URL is passed as an array argument, no shell), the already-installed short-circuit runs before the index refresh so offline builds keep working, and the shared surface is byte-identical across the two repos.

Merge the pair in short sequence — the sync gate in each repo only tolerates divergence while an open PR exists in the other.

Review assisted by Claude Code.

@thiagoralves
thiagoralves merged commit 6e7584c into development Aug 10, 2026
14 checks passed
@thiagoralves
thiagoralves deleted the fix/vpp-board-manager-url branch August 10, 2026 20:37
thiagoralves added a commit that referenced this pull request Aug 11, 2026
Resolves the expected conflict in `#checkIfArduinoCliConfigExists`, where
#1001 (now on development) and this branch both rewrote the same method.

Took this branch's version: `reconcileArduinoCliConfig` is a superset of the
regex #1001 introduced — it backfills missing board-manager URLs *and* retires
the obsolete `output.no_color`, using the `yaml` Document API rather than
anchored regexes. That also settles the review finding on #1001 that the regex
could not see `additional_urls: []`, the shape `arduino-cli config init`
writes, along with the `existing.includes(url)` whole-file substring match.

The doc comment is merged rather than replaced, so the board-manager-URL
rationale from #1001 survives alongside the no_color one.

Everything else auto-merged. #1001's boardManagerUrl schema validation and
pipeline plumbing are intact; so is this branch's console work.

Editor suite: 6386 passing, typecheck / lint / prettier clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants