public static List <UpdateInfo> GetLatestUpdateInfos() { if (!IsConnectedToInternet) { throw new UpdateNoInternetException(); } List <UpdateInfo> updateInfos = new List <UpdateInfo>(); HttpWebRequest request = WebRequest.CreateHttp(_updateUrl); request.UserAgent = _userAgent; request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore); request.Timeout = TimeoutMS; using (XmlReader reader = XmlReader.Create(request.GetResponse().GetResponseStream())) { while (reader.Read()) { if (reader.IsStartElement()) { if (reader.Name == "update") { string version = reader.GetAttribute("version"); string url = reader.GetAttribute("url"); ReleaseChannel releaseChannel = (ReleaseChannel)Enum.Parse(typeof(ReleaseChannel), reader.GetAttribute("channel")); updateInfos.Add(new UpdateInfo(version, url, releaseChannel)); } } } } return(updateInfos); }
/// <summary> /// Given a ReleaseChannel and a keyName, attempt to load the corresponding ChannelInfo objecvt /// </summary> /// <param name="releaseChannel">The ReleaseChannel being queried</param> /// <param name="channelInfo">Returns the ChannelInfo here</param> /// <param name="gitHubWrapper">An optional wrapper to the GitHub data</param> /// <param name="keyName">An optional override of the key to use when reading the ChannelInfo data</param> /// <param name="exceptionReporter">An optional IExceptionReporter if you want exception details</param> /// <returns>true if we found data</returns> public static bool TryGetChannelInfo(ReleaseChannel releaseChannel, out ChannelInfo channelInfo, IGitHubWrapper gitHubWrapper, string keyName = "default", IExceptionReporter exceptionReporter = null) { try { IGitHubWrapper wrapper = gitHubWrapper ?? new GitHubWrapper(exceptionReporter); using (Stream stream = new MemoryStream()) { wrapper.LoadChannelInfoIntoStream(releaseChannel, stream); channelInfo = GetChannelFromStream(stream, keyName); return(true); } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception e) { if (exceptionReporter != null) { exceptionReporter.ReportException(e); } } #pragma warning restore CA1031 // Do not catch general exception types // Default values channelInfo = null; return(false); }
public void ReleaseChannel_CanBeOverriddenInConstructor() { const ReleaseChannel testReleaseChannel = ReleaseChannel.Insider; IAutoUpdate update = BuildAutoUpdate(releaseChannel: testReleaseChannel); Assert.AreEqual(testReleaseChannel.ToString(), update.ReleaseChannel); }
public async override Task <string> Resolve(ReleaseChannel channel, Product product, CancellationToken token = new CancellationToken()) { string level = GetLevel(channel); string productId = GetProductId(product); var uri = new Uri(Url + level); Boots.Logger.WriteLine($"Querying {uri}"); var response = await httpClient.GetAsync(uri, token); response.EnsureSuccessStatusCode(); var document = new XmlDocument(); using (var stream = await response.Content.ReadAsStreamAsync()) { token.ThrowIfCancellationRequested(); document.Load(stream); var node = document.SelectSingleNode($"/UpdateInfo/Application[@id='{productId}']/Update/@url"); if (node == null) { throw new XmlException($"Did not find {product}, at channel {channel}"); } string url = node.InnerText; if (string.IsNullOrEmpty(url)) { throw new XmlException($"Did not find {product}, at channel {channel}"); } // Just let this throw if it is an invalid Uri new Uri(url); return(url); } }
static void SetChannelAndProduct(Bootstrapper boots, string product, ReleaseChannel channel) { if (!string.IsNullOrEmpty(product)) { boots.Channel = channel; boots.Product = Enum.Parse <Product> (product.Replace(".", "")); } }
/// <summary> /// Unit testable ctor - allows dependency injection for testing /// </summary> /// <param name="releaseChannelProvider">Provides the client's current release channel</param> /// <param name="installedVersionProvider">Method that provides the installed version string</param> /// <param name="channelInfoProvider">Method that provides a (potentially invalid) ChannelInfo</param> internal AutoUpdate(Func <ReleaseChannel> releaseChannelProvider, Func <string> installedVersionProvider, IChannelInfoProvider channelInfoProvider) { _strongReleaseChannel = releaseChannelProvider(); _installedVersionProvider = installedVersionProvider; _channelInfoProvider = channelInfoProvider; ReleaseChannel = _strongReleaseChannel.ToString(); _initTask = Task.Run(() => InitializeWithTimer()); }
public override string ToString() { StringBuilder sb = new StringBuilder(); sb.AppendLine(string.Format("{0} is your current version", CurrentVersion)); sb.AppendLine(string.Format("{0} is the latest {1}", LatestVersion, ReleaseChannel.GetDescription())); sb.AppendLine(string.Format("{1} was last updated on {0}", Date.ToLongDateString(), ReleaseChannel.GetDescription())); return(sb.ToString()); }
public static TelemetryEvent ForReleaseChannelChangeConsidered(ReleaseChannel oldChannel, ReleaseChannel newChannel) { return(new TelemetryEvent(TelemetryAction.ReleaseChannel_ChangeConsidered, new Dictionary <TelemetryProperty, string> { { TelemetryProperty.ReleaseChannel, oldChannel.ToString() }, { TelemetryProperty.ReleaseChannelConsidered, newChannel.ToString() }, })); }
public async Task Resolve(Type type, ReleaseChannel channel, Product product) { var resolver = (UrlResolver)Activator.CreateInstance(type, new Bootstrapper()); var url = await resolver.Resolve(channel, product); var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); }
public static async Task Boots(this ICakeContext context, Product product, ReleaseChannel channel = ReleaseChannel.Stable) { var boots = new Bootstrapper { Channel = channel, Product = product, Logger = new CakeWriter(context) }; await boots.Install(); }
/// <summary> /// Installs a different version in response to a channel change /// </summary> /// <param name="newChannel">The new channel to use</param> public static void ChangeChannel(ReleaseChannel newChannel) { if (ChannelInfoUtilities.TryGetChannelInfo(newChannel, out ChannelInfo channelInfo, null) && channelInfo.IsValid) { DownloadAndInstall(new Uri(channelInfo.InstallAsset), newChannel); return; } throw new ArgumentException("Unable to get channel information", nameof(newChannel)); }
private Uri GetChannelSpecificUri(ReleaseChannel releaseChannel) { // Check for special cases, otherwise use production value switch (releaseChannel) { case ReleaseChannel.Insider: return(_insiderConfigFileUri); case ReleaseChannel.Canary: return(_canaryConfigFileUri); } return(_productionConfigFileUri); }
public void UpdateOptionAsync_ReleaseChannelIsOverridden_UsesCorrectChannel() { const ReleaseChannel testReleaseChannel = ReleaseChannel.Canary; Mock <IChannelInfoProvider> providerMock = BuildChannelInfoProvider(testReleaseChannel, OptionalUpgradeChannelInfo); AutoUpdate update = BuildAutoUpdate(releaseChannel: testReleaseChannel, channelProvider: providerMock.Object); Assert.AreEqual(AutoUpdateOption.OptionalUpgrade, update.UpdateOptionAsync.Result); Assert.AreEqual(TestInstalledVersion, update.InstalledVersion.ToString()); Assert.AreEqual(OptionalUpgradeChannelInfo.CurrentVersion, update.CurrentChannelVersion); Assert.AreEqual(OptionalUpgradeChannelInfo.MinimumVersion, update.MinimumChannelVersion); Assert.AreEqual(OptionalUpgradeChannelInfo.ReleaseNotesAsset, update.ReleaseNotesUri.ToString()); providerMock.VerifyAll(); }
private IEnumerable <ReleaseMeta> ExpandAllReleases(ReleaseChannel channel) { foreach (var release in channel.Releases) { var isLatest = channel.LatestSdk == release.Sdk.Version; yield return(new ReleaseMeta { ChannelVersion = channel.ChannelVersion, SupportPhase = isLatest ? (SupportPhases?)channel.SupportPhase : null, Version = release.Sdk.Version }); } }
/// <summary> /// Installs a different version in response to a channel change /// </summary> /// <param name="newChannel">The new channel to use</param> public static void ChangeChannel(ReleaseChannel newChannel) { if (ChannelInfoUtilities.TryGetChannelInfo(newChannel, out ChannelInfo channelInfo, null) && channelInfo.IsValid) { DownloadAndInstall(new Uri(channelInfo.InstallAsset), newChannel); return; } #pragma warning disable CA1303 // Do not pass literals as localized parameters throw new ArgumentException("Unable to get channel information", nameof(newChannel)); #pragma warning restore CA1303 // Do not pass literals as localized parameters }
public async override Task <string> Resolve(ReleaseChannel channel, Product product, CancellationToken token = new CancellationToken()) { Uri uri = GetUri(channel); string channelId = GetChannelId(channel); string productId = GetProductId(product); Boots.Logger.WriteLine($"Querying {uri}"); var response = await httpClient.GetAsync(uri, token); response.EnsureSuccessStatusCode(); string?payloadManifestUrl; using (var stream = await response.Content.ReadAsStreamAsync()) { token.ThrowIfCancellationRequested(); var manifest = await JsonSerializer.DeserializeAsync <VSManifest> (stream, cancellationToken : token); var channelItem = manifest.channelItems?.FirstOrDefault(c => c.id == channelId); if (channelItem == null) { throw new InvalidOperationException($"Did not find '{channelId}' at: {uri}"); } payloadManifestUrl = channelItem.payloads?.Select(p => p.url)?.FirstOrDefault(); if (string.IsNullOrEmpty(payloadManifestUrl)) { throw new InvalidOperationException($"Did not find manifest url for '{channelId}' at: {uri}"); } } uri = new Uri(payloadManifestUrl); Boots.Logger.WriteLine($"Querying {uri}"); response = await httpClient.GetAsync(uri, token); response.EnsureSuccessStatusCode(); using (var stream = await response.Content.ReadAsStreamAsync()) { token.ThrowIfCancellationRequested(); var payload = await JsonSerializer.DeserializeAsync <VSPayloadManifest> (stream, cancellationToken : token); var url = payload.packages?.FirstOrDefault(p => p.id == productId)?.payloads?.Select(p => p.url).FirstOrDefault(); // NOTE: workaround NRT in netstandard2.0 if (url == null || url == "") { throw new InvalidOperationException($"Did not find payload url for '{productId}' at: {uri}"); } // Just let this throw if it is an invalid Uri new Uri(url); return(url); } }
string GetChannelId(ReleaseChannel channel) { switch (channel) { case ReleaseChannel.Stable: return("Microsoft.VisualStudio.Manifests.VisualStudio"); case ReleaseChannel.Preview: return("Microsoft.VisualStudio.Manifests.VisualStudioPreview"); default: throw new NotImplementedException($"Unexpected value for release: {channel}");; } }
Uri GetUri(ReleaseChannel channel) { switch (channel) { case ReleaseChannel.Stable: return(new Uri(ReleaseUrl)); case ReleaseChannel.Preview: return(new Uri(PreviewUrl)); default: throw new NotImplementedException($"Unexpected value for {nameof (ReleaseChannel)}: {channel}");; } }
string GetLevel(ReleaseChannel channel) { switch (channel) { case ReleaseChannel.Stable: return("Stable"); case ReleaseChannel.Preview: return("Beta"); default: throw new NotImplementedException($"Unexpected value for release: {channel}"); } }
public override int GetHashCode() { int hash = 1; if (ReleaseChannel != global::Yandex.Cloud.K8S.V1.ReleaseChannel.Unspecified) { hash ^= ReleaseChannel.GetHashCode(); } hash ^= versions_.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } return(hash); }
public UpdateInfo(string version, string url, ReleaseChannel releaseChannel) { if (string.IsNullOrWhiteSpace(version)) { throw new ArgumentNullException(nameof(version)); } if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentNullException(nameof(url)); } Version = version.Trim(); Url = url.Trim(); ReleaseChannel = releaseChannel; }
public InstallerInfo(string version, string url, ReleaseChannel releaseChannel) { if (string.IsNullOrWhiteSpace(version)) { throw new ArgumentNullException("version"); } if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentNullException("url"); } Version = version.Trim(); Url = url.Trim(); ReleaseChannel = releaseChannel; }
// Wrap the ctor to give us a single place for adding dependency injection parameters private static AutoUpdate BuildAutoUpdate(ReleaseChannel releaseChannel = ReleaseChannel.Production, string testInstalledVersion = null, IChannelInfoProvider channelProvider = null) { return(new AutoUpdate(() => releaseChannel, () => testInstalledVersion ?? TestInstalledVersion, channelProvider ?? InertChannelInfoProvider)); }
// Constructor public CharonAPI(ReleaseChannel channel) { // Set gateway url _gatewayUrl = gatewayUrls[channel]; }
public static void UpdateCheck(bool confirmUpdate, bool showUpToDate) { try { IsCheckingforUpdate = true; List <UpdateInfo> updateInfos = GetLatestUpdateInfos(); ReleaseChannel targetReleaseChannel = GetReleaseChannel(); ulong maxVersion = LongVersion(AppVM.FullVersion); UpdateInfo latestVersion = null; bool updateAvailable = false; foreach (UpdateInfo updateInfo in updateInfos) { if (updateInfo.ReleaseChannel == targetReleaseChannel) { ulong installerVersion = LongVersion(updateInfo.Version); if (installerVersion > maxVersion) { updateAvailable = true; latestVersion = updateInfo; maxVersion = installerVersion; } } } LastUpdateCheck = DateTime.Now; if (updateAvailable) { if (confirmUpdate) { string message = string.Format(Strings.ChordiousUpdateAvailableUpdateNowMessageFormat, latestVersion.Version); AppVM.AppView.DoOnUIThread(() => { Messenger.Default.Send(new ConfirmationMessage(message, (confirmed) => { try { if (confirmed) { Messenger.Default.Send(new LaunchUrlMessage(latestVersion.Url)); } } catch (Exception ex) { ExceptionUtils.HandleException(new UpdateException(ex)); } })); }); } else { AppVM.AppView.DoOnUIThread(() => { Messenger.Default.Send(new LaunchUrlMessage(latestVersion.Url)); }); } } else { if (showUpToDate) { AppVM.AppView.DoOnUIThread(() => { Messenger.Default.Send(new ChordiousMessage(Strings.ChordiousUpdateNotAvailableMessage)); }); } } } catch (Exception ex) { ExceptionUtils.HandleException(new UpdateException(ex)); } finally { IsCheckingforUpdate = false; } }
/// <summary> /// Implements <see cref="IChannelInfoProvider.TryGetChannelInfo(string, out ChannelInfo)"/> /// </summary> public bool TryGetChannelInfo(ReleaseChannel releaseChannel, out ChannelInfo channelInfo) { return(ChannelInfoUtilities.TryGetChannelInfo(releaseChannel, out channelInfo, _gitHubWrapper, exceptionReporter: _exceptionReporter)); }
public async Task NotImplemented(Type type, ReleaseChannel channel, Product product) { var resolver = (UrlResolver)Activator.CreateInstance(type, new Bootstrapper()); await Assert.ThrowsAsync <NotImplementedException> (() => resolver.Resolve(channel, product)); }
/// <summary> /// Implements <see cref="IGitHubWrapper.LoadChannelInfoIntoStream(string, Stream)(Uri, Stream)"/> /// </summary> public void LoadChannelInfoIntoStream(ReleaseChannel releaseChannel, Stream stream) { GitHubClient.LoadUriContentsIntoStream(GetChannelSpecificUri(releaseChannel), stream, _timeout); }
public static void UpdateCheck(bool confirmUpdate, bool showUpToDate) { try { IsCheckingforUpdate = true; List <UpdateInfo> updateInfos = GetLatestUpdateInfos(); ReleaseChannel targetReleaseChannel = GetReleaseChannel(); ulong maxVersion = LongVersion(AppVM.FullVersion); UpdateInfo latestVersion = null; bool updateAvailable = false; foreach (UpdateInfo updateInfo in updateInfos) { if (updateInfo.ReleaseChannel == targetReleaseChannel) { ulong updateVersion = LongVersion(updateInfo.Version); if (updateVersion > maxVersion) { updateAvailable = true; latestVersion = updateInfo; maxVersion = updateVersion; } } } if (updateAvailable) { if (confirmUpdate) { string message = string.Format("Mzinga v{0} is available. Would you like to update now?", latestVersion.Version); AppVM.DoOnUIThread(() => { Messenger.Default.Send(new ConfirmationMessage(message, (confirmed) => { try { if (confirmed) { Messenger.Default.Send(new LaunchUrlMessage(latestVersion.Url)); } } catch (Exception ex) { ExceptionUtils.HandleException(new UpdateException(ex)); } })); }); } else { AppVM.DoOnUIThread(() => { Messenger.Default.Send(new LaunchUrlMessage(latestVersion.Url)); }); } } else { if (showUpToDate) { AppVM.DoOnUIThread(() => { Messenger.Default.Send(new InformationMessage("Mzinga is up-to-date.")); }); } } } catch (WebException ex) { if (ex.Status == WebExceptionStatus.Timeout) { TimeoutMS = (int)Math.Min(TimeoutMS * 1.5, MaxTimeoutMS); } if (showUpToDate) { ExceptionUtils.HandleException(new UpdateException(ex)); } } catch (Exception ex) { ExceptionUtils.HandleException(new UpdateException(ex)); } finally { IsCheckingforUpdate = false; } }
public static void UpdateCheck(bool confirmUpdate, bool showUpToDate) { try { IsCheckingforUpdate = true; List <InstallerInfo> installerInfos = GetLatestInstallerInfos(); ReleaseChannel targetReleaseChannel = GetReleaseChannel(); ulong maxVersion = LongVersion(AppViewModel.FullVersion); InstallerInfo latestVersion = null; bool updateAvailable = false; foreach (InstallerInfo installerInfo in installerInfos) { if (installerInfo.ReleaseChannel == targetReleaseChannel) { ulong installerVersion = LongVersion(installerInfo.Version); if (installerVersion > maxVersion) { updateAvailable = true; latestVersion = installerInfo; maxVersion = installerVersion; } } } SetLastUpdateCheck(DateTime.Now); if (updateAvailable) { if (confirmUpdate) { string message = string.Format("Mzinga v{0} is available. Would you like to update now?", latestVersion.Version); AppVM.DoOnUIThread(() => { Messenger.Default.Send(new ConfirmationMessage(message, (confirmed) => { try { if (confirmed) { Update(latestVersion); } } catch (Exception ex) { ExceptionUtils.HandleException(new UpdateException(ex)); } })); }); } else { Update(latestVersion); } } else { if (showUpToDate) { AppVM.DoOnUIThread(() => { Messenger.Default.Send(new InformationMessage("Mzinga is up-to-date.")); }); } } } catch (Exception ex) { ExceptionUtils.HandleException(new UpdateException(ex)); } finally { IsCheckingforUpdate = false; } }