-
-
Notifications
You must be signed in to change notification settings - Fork 406
Add first set of profile
commands
#2917
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
base: master
Are you sure you want to change the base?
Add first set of profile
commands
#2917
Conversation
profile
commandprofile
commands
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2917 +/- ##
==========================================
- Coverage 67.83% 67.82% -0.02%
==========================================
Files 238 248 +10
Lines 22442 22854 +412
==========================================
+ Hits 15223 15500 +277
- Misses 6016 6128 +112
- Partials 1203 1226 +23
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
It creates a `sketch.yaml` file at the provided path. A new profile can be added to the file by providing a profile name and FQBN.
ab96ed6
to
8a41c13
Compare
It adds one or multiple libraries to the specified profile.
8a41c13
to
d3d7a59
Compare
It removes a library from the specified profile.
67c9a2c
to
f98bf7d
Compare
If the project file contains only one profile, it is automatically set as default, otherwise the `--default` flag can be used. Library operations are automatically executed on the default profile.
Sets the default profile to the provided existing profile.
896841b
to
a2c86ef
Compare
It dumps the content of the project file.
Hello, this is great 🔥 Maybe you want to consider adding and removing multiple libs (later cores) with a single request. I do not know how it performs, but when a user interface wants to initialize a profile from a set of libraries and cores, one request would be better than multiple ones. Update: I checked the changes only from the point of the proto API as a client. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job! 🚀
We have a bug in the long standing:
arduino-cli/internal/arduino/sketch/profiles.go
Lines 166 to 167 in 55f86b5
res += p.Platforms.AsYaml() | |
res += p.Libraries.AsYaml() |
arduino-cli profile init --profile Uno_profile -b arduino:avr:uno /tmp/sk
cat /tmp/sk/sketch.yaml
profiles:
Uno_profile:
fqbn: arduino:avr:uno
platforms:
- platform: arduino:avr (1.8.6)
libraries:
default_profile: c
You can see here that it produces libraries:
without []
, this is an invalid yaml.
Basically we have to check if the items == 0, then we either skip that property or we set libraries: []
.
I'm afraid it could also happen for the platforms
so I'd put that check there too.
|
||
// GRPCStatus converts the error into a *status.Status | ||
func (e *DuplicateProfileError) GRPCStatus() *status.Status { | ||
return status.New(codes.NotFound, e.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return status.New(codes.NotFound, e.Error()) | |
return status.New(codes.AlreadyExists, e.Error()) |
message ProfileDumpRequest { | ||
// Absolute path to Sketch folder. | ||
string sketch_path = 1; | ||
// The format of the dump. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// The format of the dump. | |
// The format of the dump (default is "json", allowed values are "json", and "yaml"). |
To be consistent with also the Configuation operation, I'd set a default value to json
switch req.GetDumpFormat() { | ||
case "yaml": | ||
return &rpc.ProfileDumpResponse{EncodedProfile: sk.Project.AsYaml()}, nil | ||
case "json": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case "json": | |
case "", "json": |
Let's allow a default value if the DumpFormat is not specified to be json
. This is consistent with what we're doing with Settings api
} | ||
|
||
newProfile := &sketch.Profile{Name: req.GetProfileName(), FQBN: req.GetFqbn()} | ||
// TODO: what to do with the PlatformIndexURL? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have some kind of internal API that we can use to retrieve platform <-> index URL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc: @cmaglie
Example: "" + | ||
" # " + i18n.Tr("Creates or updates the sketch project file in the current directory.") + "\n" + | ||
" " + os.Args[0] + " profile init\n" + | ||
" " + os.Args[0] + " config init --profile Uno_profile -b arduino:avr:uno", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
" " + os.Args[0] + " config init --profile Uno_profile -b arduino:avr:uno", | |
" " + os.Args[0] + " profile init --profile uno_profile -b arduino:avr:uno", |
if err != nil { | ||
feedback.Fatal(i18n.Tr("Cannot set %s as default profile: %v", profileName, err), feedback.ErrGeneric) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | |
feedback.Print(i18n.Tr("Default profile set to: %s", profileName)) | |
} |
sketchPath := paths.New(req.GetSketchPath()) | ||
projectFilePath, err := sketchPath.Join("sketch.yaml").Abs() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Returns an error if the main file is missing from the sketch so there is no need to check if the path exists | ||
sk, err := sketch.New(sketchPath) | ||
if err != nil { | ||
return nil, err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sketchPath := paths.New(req.GetSketchPath()) | |
projectFilePath, err := sketchPath.Join("sketch.yaml").Abs() | |
if err != nil { | |
return nil, err | |
} | |
// Returns an error if the main file is missing from the sketch so there is no need to check if the path exists | |
sk, err := sketch.New(sketchPath) | |
if err != nil { | |
return nil, err | |
} | |
sketchPath := paths.New(req.GetSketchPath()) | |
projectFilePath, err := sketchPath.Join("sketch.yaml").Abs() | |
if err != nil { | |
return nil, err | |
} | |
// Returns an error if the main file is missing from the sketch so there is no need to check if the path exists | |
sk, err := sketch.New(sketchPath) | |
if err != nil { | |
return nil, err | |
} |
Can you please move this snippet of code under a private function? Something like checkProfilePreconditions
.
And call that in all the new function you have created under commands
. I've noticed that you do this same check for al of them
if !projectFilePath.Exist() { | ||
err := projectFilePath.WriteFile([]byte("profiles:\n")) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the GRPC api, is possible to endup with a project file containing an invalid yaml:
profiles:
This can happen if: the path doesn't exists and the ProfileName is empty
if !projectFilePath.Exist() { | |
err := projectFilePath.WriteFile([]byte("profiles:\n")) | |
if err != nil { | |
return nil, err | |
} | |
} | |
if !projectFilePath.Exist() && req.GetProfileName() == ""{ | |
// return error | |
return nil, error | |
} | |
if !projectFilePath.Exist() { | |
err := projectFilePath.WriteFile([]byte("profiles:\n")) | |
if err != nil { | |
return nil, err | |
} | |
} |
require.FileExists(t, projectFile.String()) | ||
fileContent, err := projectFile.ReadFile() | ||
require.NoError(t, err) | ||
require.Equal(t, "profiles:\n Uno:\n fqbn: arduino:avr:uno\n platforms:\n - platform: arduino:avr (1.8.6)\n libraries:\n\ndefault_profile: Uno\n", string(fileContent)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
libraries:\n
this is not a valid yaml it should be libraries:[]\n
In the Review comment you can find where to fix it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel that the design of the profile dump
command is inappropriate. This command is actually printing the data of the entire sketch project file, not the build profile data alone. Although the primary usage of the sketch project file is currently for defining build profiles, it is not limited to this purpose and there is a good chance that it will be used for additional things unrelated to build profiles as time goes on.
The profile dump
command should be a tool for printing the data from a build profile.
If you want a tool for printing the sketch project file, that should go somewhere else, such as under the sketch
command (e.g., sketch project dump
), not under the profile
command.
If the user doesn't specify a profile ID, it should print the default build profile from the sketch project file. An --all
flag could be added to cause it to print all build profiles present in the sketch project file.
Short: i18n.Tr("Dumps the project file."), | ||
Long: i18n.Tr("Dumps the project file."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: i18n.Tr("Dumps the project file."), | |
Long: i18n.Tr("Dumps the project file."), | |
Short: i18n.Tr("Print the sketch project file."), | |
Long: i18n.Tr("Print the data from the sketch project file."), |
- Use "print" instead of "dump"
- I think the term "dump" is ambiguous (the user might interpret it as meaning "delete")
- The use of the term "dump" doesn't add anything of documentary value since this is already in the command name.
- This aligns with the documentation for
config dump
.
- Use the established convention of the "imperative mood" (i.e., "print" instead of "prints")
- Use the full standard term "sketch project file"
- "Project file" is ambiguous as this could be interpreted as meaning the sketch code file.
- Be a bit more informative in the "long" description.
Short: i18n.Tr("Creates or updates the sketch project file."), | ||
Long: i18n.Tr("Creates or updates the sketch project file."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: i18n.Tr("Creates or updates the sketch project file."), | |
Long: i18n.Tr("Creates or updates the sketch project file."), | |
Short: i18n.Tr("Create or update the sketch project file."), | |
Long: i18n.Tr("Create or update the sketch project file."), |
Use the established convention of the "imperative mood".
Short: i18n.Tr("Profile commands about libraries."), | ||
Long: i18n.Tr("Profile commands about libraries."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: i18n.Tr("Profile commands about libraries."), | |
Long: i18n.Tr("Profile commands about libraries."), | |
Short: i18n.Tr("Commands related to build profile libraries."), | |
Long: i18n.Tr("Commands related to the library dependencies of build profiles."), |
- Make the descriptions more informative.
- Use full standard term "build profile".
Short: i18n.Tr("Arduino profile operations."), | ||
Long: i18n.Tr("Arduino profile operations."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: i18n.Tr("Arduino profile operations."), | |
Long: i18n.Tr("Arduino profile operations."), | |
Short: i18n.Tr("Build profile operations."), | |
Long: i18n.Tr("Build profile operations."), |
- Remove the superfluous "Arduino"
- Use the full standard term "build profile"
Short: i18n.Tr("Sets the default profile."), | ||
Long: i18n.Tr("Sets the default profile."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: i18n.Tr("Sets the default profile."), | |
Long: i18n.Tr("Sets the default profile."), | |
Short: i18n.Tr("Set the default build profile."), | |
Long: i18n.Tr("Set the default build profile."), |
- Use the full standard term "build profile"
- Use the established convention of the "imperative mood".
}, | ||
} | ||
|
||
setDefaultCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file.")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setDefaultCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file.")) | |
setDefaultCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the sketch project file.")) |
Use the full standard term "sketch project file"
// Create the project file and add a profile to it. | ||
rpc InitProfile(InitProfileRequest) returns (InitProfileResponse) {} | ||
|
||
// Add a library to the profile. | ||
rpc ProfileLibAdd(ProfileLibAddRequest) returns (ProfileLibAddResponse) {} | ||
|
||
// Remove a library from the profile. | ||
rpc ProfileLibRemove(ProfileLibRemoveRequest) returns (ProfileLibRemoveResponse) {} | ||
|
||
// Set the default profile. | ||
rpc ProfileSetDefault(ProfileSetDefaultRequest) returns (ProfileSetDefaultResponse) {} | ||
|
||
// Dump the project file. | ||
rpc ProfileDump(ProfileDumpRequest) returns (ProfileDumpResponse) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Create the project file and add a profile to it. | |
rpc InitProfile(InitProfileRequest) returns (InitProfileResponse) {} | |
// Add a library to the profile. | |
rpc ProfileLibAdd(ProfileLibAddRequest) returns (ProfileLibAddResponse) {} | |
// Remove a library from the profile. | |
rpc ProfileLibRemove(ProfileLibRemoveRequest) returns (ProfileLibRemoveResponse) {} | |
// Set the default profile. | |
rpc ProfileSetDefault(ProfileSetDefaultRequest) returns (ProfileSetDefaultResponse) {} | |
// Dump the project file. | |
rpc ProfileDump(ProfileDumpRequest) returns (ProfileDumpResponse) {} | |
// Create the sketch project file and add a build profile to it. | |
rpc InitProfile(InitProfileRequest) returns (InitProfileResponse) {} | |
// Add a library to the build profile. | |
rpc ProfileLibAdd(ProfileLibAddRequest) returns (ProfileLibAddResponse) {} | |
// Remove a library from the build profile. | |
rpc ProfileLibRemove(ProfileLibRemoveRequest) returns (ProfileLibRemoveResponse) {} | |
// Set the default build profile. | |
rpc ProfileSetDefault(ProfileSetDefaultRequest) returns (ProfileSetDefaultResponse) {} | |
// Dump the sketch project file. | |
rpc ProfileDump(ProfileDumpRequest) returns (ProfileDumpResponse) {} |
}, | ||
} | ||
|
||
addCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file.")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file.")) | |
addCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the sketch project file.")) |
}, | ||
} | ||
|
||
removeCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file.")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removeCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the project file.")) | |
removeCommand.Flags().StringVar(&destDir, "dest-dir", "", i18n.Tr("Location of the sketch project file.")) |
Please check if the PR fulfills these requirements
See how to contribute
before creating one)
our contributing guidelines
UPGRADING.md
has been updated with a migration guide (for breaking changes)configuration.schema.json
updated if new parameters are added.What kind of change does this PR introduce?
Code enhancement
What is the current behavior?
Operations on the
sketch.yaml
project file must be done manually.What is the new behavior?
First set of
profile
commands:profile init [<PATH>] [-m <PROFILE_NAME -b <FQBN>] [--default]
creates asketch.yaml
file at the provided path. By default it creates the file in the current directory. A new profile can be added to the file by providing a profile name and FQBN (mandatory). The platform is detected automatically. If there is only one profile, it is automatically set as the default profile, otherwise the flag--default
must be used. The command fails in the following cases:profile lib add <LIB_NAME@LIB_VERSION> [-m <PROFILE_NAME] [--dest-dir <PATH>]
adds a library to the provided profile or to the default one. By default it checks for thesketch.yaml
file in the current directory.profile lib remove <LIB_NAME> [-m <PROFILE_NAME] [--dest-dir <PATH>]
removes a library from the provided profile or from the default one. By default it checks for thesketch.yaml
file in the current directory.profile set-default <PROFILE_NAME> [--dest-dir <PATH>]
sets the default profile to an existing profile. By default it checks for thesketch.yaml
file in the current directory.profile dump [<PATH>]
dumps the content of thesketch.yaml
file. It supports theyaml
andjson
formats.Does this PR introduce a breaking change, and is titled accordingly?
Other information