Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use Arduino CLI v1.1.0 #2571

Merged
merged 2 commits into from
Nov 21, 2024
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
2 changes: 1 addition & 1 deletion arduino-ide-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
],
"arduino": {
"arduino-cli": {
"version": "1.0.4"
"version": "1.1.0"
},
"arduino-fwuploader": {
"version": "2.4.1"
Expand Down
159 changes: 102 additions & 57 deletions arduino-ide-extension/scripts/generate-protocol.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
const { mkdirSync, promises: fs, rmSync } = require('node:fs');
const { exec } = require('./utils');
const { glob } = require('glob');
const { SemVer, gte, valid: validSemVer } = require('semver');
const { SemVer, gte, valid: validSemVer, gt } = require('semver');
// Use a node-protoc fork until apple arm32 is supported
// https://github.com/YePpHa/node-protoc/pull/10
const protoc = path.dirname(require('@pingghost/protoc/protoc'));
const repository = await fs.mkdtemp(path.join(os.tmpdir(), 'arduino-cli-'));

const { owner, repo, commitish } = (() => {
const pkg = require(path.join(__dirname, '..', 'package.json'));
Expand Down Expand Up @@ -57,11 +56,6 @@
return { owner, repo, commitish };
})();

const url = `https://github.com/${owner}/${repo}.git`;
console.log(`>>> Cloning repository from '${url}'...`);
exec('git', ['clone', url, repository], { logStdout: true });
console.log(`<<< Repository cloned.`);

const { platform } = process;
const resourcesFolder = path.join(
__dirname,
Expand All @@ -87,76 +81,127 @@
// - `git-snapshot` for local build executed via `task build`. We do not do this.
// - rest, we assume it is a valid semver and has the corresponding tagged code, we use the tag to generate the APIs from the `proto` files.
/*
{
"Application": "arduino-cli",
"VersionString": "nightly-20210126",
"Commit": "079bb6c6",
"Status": "alpha",
"Date": "2021-01-26T01:46:31Z"
}
*/
{
"Application": "arduino-cli",
"VersionString": "nightly-20210126",
"Commit": "079bb6c6",
"Status": "alpha",
"Date": "2021-01-26T01:46:31Z"
}
*/
const versionObject = JSON.parse(versionJson);
let version = versionObject.VersionString;
if (validSemVer(version)) {
// https://github.com/arduino/arduino-cli/pull/2374
if (gte(new SemVer(version, { loose: true }), new SemVer('0.35.0-rc.1'))) {
version = `v${version}`;
const version = versionObject.VersionString;

// Clone the repository and check out the tagged version
// Return folder with proto files
async function getProtoPath(forceCliVersion) {
const repository = await fs.mkdtemp(path.join(os.tmpdir(), 'arduino-cli-'));

const url = `https://github.com/${owner}/${repo}.git`;
console.log(`>>> Cloning repository from '${url}'...`);
exec('git', ['clone', url, repository], { logStdout: true });
console.log(`<<< Repository cloned.`);

let cliVersion = forceCliVersion || version;
if (validSemVer(cliVersion)) {
// https://github.com/arduino/arduino-cli/pull/2374
if (
gte(new SemVer(version, { loose: true }), new SemVer('0.35.0-rc.1'))
) {
cliVersion = `v${cliVersion}`;
}
console.log(`>>> Checking out tagged version: '${cliVersion}'...`);
exec('git', ['-C', repository, 'fetch', '--all', '--tags'], {
logStdout: true,
});
exec(
'git',
['-C', repository, 'checkout', `tags/${cliVersion}`, '-b', cliVersion],
{ logStdout: true }
);
console.log(`<<< Checked out tagged version: '${cliVersion}'.`);
} else if (forceCliVersion) {
console.log(`WARN: invalid semver: '${forceCliVersion}'.`);
// If the forced version is invalid, do not proceed with fallbacks.
return undefined;
} else if (commitish) {
console.log(
`>>> Checking out commitish from 'package.json': '${commitish}'...`
);
exec('git', ['-C', repository, 'checkout', commitish], {
logStdout: true,
});
console.log(
`<<< Checked out commitish from 'package.json': '${commitish}'.`
);
} else if (versionObject.Commit) {
console.log(
`>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`
);
exec('git', ['-C', repository, 'checkout', versionObject.Commit], {
logStdout: true,
});
console.log(
`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`
);
} else {
console.log(
`WARN: no 'git checkout'. Generating from the HEAD revision.`
);
}
console.log(`>>> Checking out tagged version: '${version}'...`);
exec('git', ['-C', repository, 'fetch', '--all', '--tags'], {
logStdout: true,
});
exec(
'git',
['-C', repository, 'checkout', `tags/${version}`, '-b', version],
{ logStdout: true }
);
console.log(`<<< Checked out tagged version: '${version}'.`);
} else if (commitish) {
console.log(
`>>> Checking out commitish from 'package.json': '${commitish}'...`
);
exec('git', ['-C', repository, 'checkout', commitish], { logStdout: true });
console.log(
`<<< Checked out commitish from 'package.json': '${commitish}'.`
);
} else if (versionObject.Commit) {
console.log(
`>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`
);
exec('git', ['-C', repository, 'checkout', versionObject.Commit], {
logStdout: true,
});
console.log(
`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`
);
} else {
console.log(`WARN: no 'git checkout'. Generating from the HEAD revision.`);

return path.join(repository, 'rpc');
}

const protoPath = await getProtoPath();

if (!protoPath) {
console.log(`Could not find the proto files folder.`);
process.exit(1);
}

console.log('>>> Generating TS/JS API from:');
exec('git', ['-C', repository, 'rev-parse', '--abbrev-ref', 'HEAD'], {
exec('git', ['-C', protoPath, 'rev-parse', '--abbrev-ref', 'HEAD'], {
logStdout: true,
});

const rpc = path.join(repository, 'rpc');
const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol');
// Must wipe the gen output folder. Otherwise, dangling service implementation remain in IDE2 code,
// although it has been removed from the proto file.
// For example, https://github.com/arduino/arduino-cli/commit/50a8bf5c3e61d5b661ccfcd6a055e82eeb510859.
rmSync(out, { recursive: true, maxRetries: 5, force: true });
mkdirSync(out, { recursive: true });

if (gt(new SemVer(version, { loose: true }), new SemVer('1.0.4'))) {
// Patch for https://github.com/arduino/arduino-cli/issues/2755
// Credit https://github.com/dankeboy36/ardunno-cli-gen/pull/9/commits/64a5ac89aae605249261c8ceff7255655ecfafca
// Download the 1.0.4 version and use the missing google/rpc/status.proto file.
console.log('<<< Generating missing google proto files');
const v104ProtoPath = await getProtoPath('1.0.4');
if (!v104ProtoPath) {
console.log(`Could not find the proto files folder for version 1.0.4.`);
process.exit(1);
}
await fs.cp(
path.join(v104ProtoPath, 'google'),
path.join(protoPath, 'google'),
{
recursive: true,
}
);
console.log(`>>> Generated missing google file`);
}

let protos = [];
try {
const matches = await glob('**/*.proto', { cwd: rpc });
protos = matches.map((filename) => path.join(rpc, filename));
const matches = await glob('**/*.proto', { cwd: protoPath });
protos = matches.map((filename) => path.join(protoPath, filename));
} catch (error) {
console.log(error.stack ?? error.message);
}

if (!protos || protos.length === 0) {
console.log(`Could not find any .proto files under ${rpc}.`);
console.log(`Could not find any .proto files under ${protoPath}.`);
process.exit(1);
}

Expand All @@ -167,7 +212,7 @@
`--js_out=import_style=commonjs,binary:${out}`,
`--grpc_out=generate_package_definition:${out}`,
'-I',
rpc,
protoPath,
...protos,
],
{ logStdout: true }
Expand All @@ -186,7 +231,7 @@
)}`,
`--ts_out=generate_package_definition:${out}`,
'-I',
rpc,
protoPath,
...protos,
],
{ logStdout: true }
Expand Down
4 changes: 2 additions & 2 deletions arduino-ide-extension/src/browser/contributions/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ export class Debug
): Promise<boolean> {
if (err instanceof Error) {
try {
const tempBuildPaths = await this.sketchesService.tempBuildPath(sketch);
return tempBuildPaths.some((tempBuildPath) =>
const buildPaths = await this.sketchesService.getBuildPath(sketch);
return buildPaths.some((tempBuildPath) =>
err.message.includes(tempBuildPath)
);
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,14 @@ export interface SketchesService {
/**
* This is the JS/TS re-implementation of [`GenBuildPath`](https://github.com/arduino/arduino-cli/blob/c0d4e4407d80aabad81142693513b3306759cfa6/arduino/sketch/sketch.go#L296-L306) of the CLI.
* Pass in a sketch and get the build temporary folder filesystem path calculated from the main sketch file location. Can be multiple ones. This method does not check the existence of the sketch.
* Since CLI v1.1.0 the default sketch folder is the os user cache dir. See https://github.com/arduino/arduino-cli/pull/2673/commits/d2ffeb06ca6360a211d5aa7ddd11505212ffb1b9
*
* The case sensitivity of the drive letter on Windows matters when the CLI calculates the MD5 hash of the temporary build folder.
* IDE2 does not know and does not want to rely on how the CLI treats the paths: with lowercase or uppercase drive letters.
* Hence, IDE2 has to provide multiple build paths on Windows. This hack will be obsolete when the CLI can provide error codes:
* https://github.com/arduino/arduino-cli/issues/1762.
*/
tempBuildPath(sketch: SketchRef): Promise<string[]>;
getBuildPath(sketch: SketchRef): Promise<string[]>;
}

export interface SketchRef {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

import * as grpc from "@grpc/grpc-js";
import * as cc_arduino_cli_commands_v1_commands_pb from "../../../../../cc/arduino/cli/commands/v1/commands_pb";
import * as google_rpc_status_pb from "../../../../../google/rpc/status_pb";
import * as cc_arduino_cli_commands_v1_common_pb from "../../../../../cc/arduino/cli/commands/v1/common_pb";
import * as cc_arduino_cli_commands_v1_board_pb from "../../../../../cc/arduino/cli/commands/v1/board_pb";
import * as cc_arduino_cli_commands_v1_common_pb from "../../../../../cc/arduino/cli/commands/v1/common_pb";
import * as cc_arduino_cli_commands_v1_compile_pb from "../../../../../cc/arduino/cli/commands/v1/compile_pb";
import * as cc_arduino_cli_commands_v1_core_pb from "../../../../../cc/arduino/cli/commands/v1/core_pb";
import * as cc_arduino_cli_commands_v1_debug_pb from "../../../../../cc/arduino/cli/commands/v1/debug_pb";
import * as cc_arduino_cli_commands_v1_monitor_pb from "../../../../../cc/arduino/cli/commands/v1/monitor_pb";
import * as cc_arduino_cli_commands_v1_upload_pb from "../../../../../cc/arduino/cli/commands/v1/upload_pb";
import * as cc_arduino_cli_commands_v1_lib_pb from "../../../../../cc/arduino/cli/commands/v1/lib_pb";
import * as cc_arduino_cli_commands_v1_monitor_pb from "../../../../../cc/arduino/cli/commands/v1/monitor_pb";
import * as cc_arduino_cli_commands_v1_settings_pb from "../../../../../cc/arduino/cli/commands/v1/settings_pb";
import * as cc_arduino_cli_commands_v1_upload_pb from "../../../../../cc/arduino/cli/commands/v1/upload_pb";
import * as google_rpc_status_pb from "../../../../../google/rpc/status_pb";

interface IArduinoCoreServiceService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {
create: IArduinoCoreServiceService_ICreate;
Expand Down
Loading
Loading