-
Notifications
You must be signed in to change notification settings - Fork 247
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
Plugin update badger #1577
Plugin update badger #1577
Conversation
Signed-off-by: itowlson <[email protected]>
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.
A couple of minor nits but I'm also having trouble understanding some of the logic. A few inline comments would help.
let base_dir = dirs::cache_dir() | ||
.or_else(|| dirs::home_dir().map(|p| p.join(".spin"))) | ||
.ok_or_else(|| anyhow!("Unable to get local data directory or home directory"))?; |
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.
It feels like there is some logic here that ought to be extracted into spin-common
.
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 only thing in cache/spin
other than the notifications record seems to be the OCI registry cache... I can move this into common if we want but I'm reluctant to mess with the OCI cache code (especially as part of this PR). Subsequent refactoring maybe?
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 think this should reuse default_data_dir
from data_dir.rs
. Otherwise it will also mess up any colocation of data for package managers
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.
@kate-goldenring note this is under I see this was addressed in the top-level comments.dirs::cache_dir
, not data_dir
.
@itowlson I had this in the back of my mind when I suggested spin_common::spin_dirs
over in #1584 (comment) 🤷 Either way I'm fine with punting for now.
Thanks for the feedback - I added a bunch of comments that hopefully clarify things, but of course please let me know if it's still cryptic. |
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 implementation is looking great. Just a few clarifying questions
src/commands/external.rs
Outdated
@@ -68,6 +75,7 @@ pub async fn execute_external_subcommand( | |||
} | |||
plugin_installer.run().await?; | |||
} | |||
None // No update badgering needed if we just installed 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.
None // No update badgering needed if we just installed it! | |
None // No update badgering needed if we just updated and installed it! |
src/commands/external.rs
Outdated
terminal::info!("This plugin can be upgraded.", "Version {to} is available,"); | ||
eprintln!("but may not be backward compatible with your current plugin."); | ||
eprintln!("To upgrade, run `{}`.", to.upgrade_command()); |
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.
Curious. What is the reason for the combination of logging and eprintln? Is it for color?
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.
Logging is used for errors, and eprintln/terminal
for user output. We don't want to display errors by default (this is meant to be a silent, unintrusive process), so we log those at info
. terminal
is used when we want colour highlighting, eprintln
for continuation lines that don't want additional colouring.
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.
crates/plugins/src/badger/mod.rs
Outdated
// | ||
// The reason for the Precomputed/Deferred dance is to handle the two cases of: | ||
// 1. There's no point waiting and doing the calculations because we _know_ we have a decision (or an error). | ||
// 2. There's a point to waiting because there _might_ be an upgrade, so we want to give the backgroeund |
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.
// 2. There's a point to waiting because there _might_ be an upgrade, so we want to give the backgroeund | |
// 2. There's a point to waiting because there _might_ be an upgrade, so we want to give the background |
let (eligible_manifests, questionable_manifests) = if self.current_version.major == 0 { | ||
(vec![], considerable_manifests) | ||
} else { |
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.
Given that none of our plugins are v1.0, this badger will always throw "but may not be backward compatible with your current plugin", even if updating a patch version. For example, if i run spin cloud --help
with cloud 0.1.0
installed, I get:
This plugin can be upgraded. Version 0.1.1 is available,
but may not be backward compatible with your current plugin.
According to semver, it should be backwards compat
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 thought semver had an exception for major version 0? If it doesn't, we've been doing it wrong... grin
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.
Indeed you are right: "
Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable."
I guess my point is, are we concerned with every badger saying "may not be compatible". I guess this is a given, but i do think for our plugins it would be worth visiting what it would take to see them to 1.0
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.
Yes, and this perhaps comes back to the discussion we had about stability vs maturity - it would be great to try to get our plugins to 1.x even if they are not fully mature, so that we can at least send meaningful signals about interface stability and compatibility. But the risk then is we have to do too many major revs in the early months...
let highest_questionable_manifest = questionable_manifests | ||
.into_iter() | ||
.max_by_key(|pv| pv.version.clone()); | ||
|
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.
According to the definition of Both
being that the questionable is higher than the elgible, do we need a check here of whether highest_questionable_manifest > highest_eligible_manifest
and if false set highest_questionable_manifest
to None
?
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.
considerable_manifests
contains only manifests whose version is >= current version. If HEV exists then its major version is == current major version. If HQV exists, its major version is != current major version. But since HQV major must be >= current major version, this means HQV major > current major. And since current major == HEV major, if both exist then HQV major > HEV major.
I can add a comment explaining this if it would be useful.
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.
just cackled 🤣 thank you for laying all this out! I don't think we need to comment it
let base_dir = dirs::cache_dir() | ||
.or_else(|| dirs::home_dir().map(|p| p.join(".spin"))) | ||
.ok_or_else(|| anyhow!("Unable to get local data directory or home directory"))?; |
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 think this should reuse default_data_dir
from data_dir.rs
. Otherwise it will also mess up any colocation of data for package managers
// There is a potential race condition here if someone runs two plugins at | ||
// the same time. As this is unlikely, and the worst outcome is that a user | ||
// misses a badger or gets a double badger, let's not worry about it for now. |
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.
won't the PR to prevent simultaneous updates help with this too?
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.
Sadly, no - the potential race here is the load-save cycle for the notification records themselves.
@kate-goldenring for some reason I can't reply to the comment on lines 44-46
I chose |
c369712
to
a769322
Compare
@itowlson that seems like a reasonable distinction to me. I am just thinking of when people uninstall Spin we have multiple directories that need cleanup but registry uses it anyways so SGTM |
#[macro_export] | ||
macro_rules! info { | ||
($highlight:expr, $($arg:tt)*) => {{ | ||
$crate::ceprint!($crate::colors::bold_cyan(), $highlight); |
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.
Not sure how I feel about step!
going to stdout while error!
and info!
go to stderr. For text processing tools the distinction is clear to me: stdout is for "data" that you might be piping to another command, while stderr is for stuff that is only for human consumption. It isn't obvious how/if that distinction applies here.
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 sent the update badger to stderr because I explicitly didn't want it mixed up with plugin output that might be getting consumed by a program (e.g. a plugin that outputs JSON). I can be more explicit and call this einfo!
or something if you prefer - that might also make it clear the follow-up lines should use eprintln
not println
. Let me know if you want me to make that or a similar change.
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.
Ah yes that makes perfect sense for 🦡. einfo
would make sense to me, especially to help differentiate from step
.
|
||
const BADGER_TIMEOUT_DAYS: i64 = 14; | ||
|
||
// How the checker works: |
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.
Thanks, very helpful!
Signed-off-by: itowlson <[email protected]>
a769322
to
1afc07c
Compare
@lann added a comment on the error swallowing, and changed to |
Merge away! |
Fixes #1543.