Hi Team,
I am aware that the Package Manager support private packages in the form of custom private repositories. In this approach, the user will not know that if there is a new package unless you communicate to them.
- Is there a mechanism to serve a notification to the user that there is an update to a custom package?
- Is there a mechanism to auto install a the latest version of a custom package on a users machine?
We have setup our own delivery pipeline that does this across the firm. But I’d be in favor of moving to a McNeel supported alternative if it exists.
We used to use this code to check for Updates and request customers to upgrade, it is based on previous forum code.
Since Rhino 8 we find customers always have Install Updates checked on package manager so it doesn’t get as much use as in Rhino 7.
This is great as it reduces the support burden of old versions!
You’d have to swap logging / settings approach to use this code.
/// <summary>
/// Use Rhino's Yak package manger to see if there are updates for ProductName
/// <see curl="https://discourse.mcneel.com/t/installing-yak-packages-via-rhinocommon/119454"/>
/// </summary>
internal static class UpdateChecker {
private const string Product = "ProductName";
internal static async void CheckForUpdates(bool silent = true) {
var logger = Serilog.Log.Logger;
var settings = ProductNamePlugin.Instance.Model.Settings;
bool allowPreRelease = settings.UseVersionBeta || settings.UseVersionDEV;
try {
var yak = GetYakClient();
// find out what is installed
var installedVer = GetInstalledVersion(yak);
if (installedVer == null ) {
logger.RWarning(nameof(UpdateChecker), $"Unable to find installed version of {Product}", "Install ProductName via Rhino's Package Manager.");
return;
}
// get newest available package
Version[] versions = await yak.Version.GetAll(Product);
versions = versions.Where(v => v.Distributions.Any(d => d.IsCompatible())
&& (!v.Prerelease || allowPreRelease)
&& (!v.Number.Contains("dev") || settings.UseVersionDEV)
&& (!v.Number.Contains("beta") || settings.UseVersionBeta)).ToArray();
var latest = versions.OrderBy(v => VersionNumber.TryParse(v.Number, out var ver) ? ver : null).LastOrDefault();
if ( latest == null || !VersionNumber.TryParse(latest.Number, out var latestVer)) {
logger.RWarning(nameof(UpdateChecker), $"Unable to find any compatible version of {Product}.",Remedies.DevReport);
return;
}
// make a comparison
if (latestVer.CompareTo(installedVer) > 0) {
logger.RInfo(nameof(UpdateChecker), "An update to Version {updateVersion} is available.", "Please use the Rhino Package Manager to upgrade", latestVer.ToNormalisedString());
} else {
if (!silent) {
logger.RInfo(nameof(UpdateChecker), "You are running the latest version of {product} {latestVersion}", "Check back later for new versions.", Product,
latestVer.ToNormalisedString());
}
}
} catch (Exception e) {
logger.RError(nameof(UpdateChecker), "Failed to check for updates.", Remedies.DevReport, e);
}
}
/// <summary>
/// Semantic Version number e.g. 1.2.3-beta
/// </summary>
public static string GetInstalledVersion() {
VersionNumber version = GetInstalledVersion(GetYakClient());
return version?.ToNormalisedString();
}
private static VersionNumber GetInstalledVersion(YakClient yak) {
var installedProduct = yak.List().FirstOrDefault(p => p.Name == Product);
return installedProduct != null && VersionNumber.TryParse(installedProduct.Version, out var installedVer) ? installedVer : null;
}
private static YakClient GetYakClient() {
// init yak client and set package install folder for this version of rhino
// product header value is included in user-agent for requests to yak.rhino3d.com (for analytics only)
var yak = new YakClient(Rhino.ApplicationSettings.PackageManagerSettings.Sources.Split(';').Select(s => PackageRepositoryFactory.Create(s, new ProductHeaderValue(Product))).ToArray()) {
PackageFolder = Rhino.Runtime.HostUtils.AutoInstallPlugInFolder(true) // user
};
return yak;
}
/// <summary>
///
/// </summary>
/// <param name="currentVersion"></param>
/// <param name="highestRunVersion"></param>
/// <returns> -ve if current lower than higher </returns>
public static int CompareVersions(string currentVersion, string highestRunVersion) =>
VersionNumber.TryParse(currentVersion, out var a) &&
VersionNumber.TryParse(highestRunVersion, out var b)
? a.CompareTo(b)
: 0;
}
2 Likes
Thanks David. We are doing something similar already. I am curious to know if McNeel has plans to support the features I mentioned in the original post.