Para comenzar la implementación de dicho sistema declaré las siguientes clases: GitHubRelease, GitHubAsset y GitHubAuthor las cuales servirán para representar información de una release, un asset y un author/uploader. Y por último declaré una clase con nombre GitHubUtil en donde declaré varias funciones sincrónicas y asincrónicas para implementar las siguientes funcionalidades: obtener todas las releases de un repositorio, obtener la última release, obtener una release con versión específica, y comprobar si existe una versión más reciente (para actualizar nuestro programa).
Estoy seguro que les servirá para sus aplicaciones de código abierto y le podrán sacar varias utilidades con diferentes fines que se ajusten a sus necesidades...
Aquí lo tienen todo:
Código
Imports System Imports System.Collections.Generic Imports System.Collections.ObjectModel Imports System.Collections.Specialized Imports System.ComponentModel Imports System.IO Imports System.Net Imports System.Net.Mime Imports System.Runtime.Serialization.Json Imports System.Text Imports System.Threading Imports System.Threading.Tasks Imports System.Web Imports System.Xml
GitHubRelease.vb
Código
''' <summary> ''' Represents a release on GitHub. ''' </summary> ''' <seealso href="https://github.com"/> Public NotInheritable Class GitHubRelease ''' <summary> ''' Gets the GitHub's unique identifier for this release. ''' </summary> Public ReadOnly Property Id As String ''' <summary> ''' Gets the release name. ''' </summary> Public ReadOnly Property Name As String ''' <summary> ''' Gets the release tag name. ''' </summary> Public ReadOnly Property TagName As String ''' ---------------------------------------------------------------------------------------------------- ''' <summary> ''' Gets the release version. ''' </summary> ''' ---------------------------------------------------------------------------------------------------- ''' <remarks> ''' The version is derived from <see cref="GitHubRelease.TagName"/>, which should follow semantic versioning guidelines. ''' <para></para> ''' See for more info about semantic versioning: ''' <para></para> ''' <see href="https://semver.org/"/> ''' <para></para> ''' <see href="https://help.github.com/articles/about-releases/"/> ''' <para></para> ''' <see href="https://git-scm.com/book/en/v2/Git-Basics-Tagging"/> ''' </remarks> ''' ---------------------------------------------------------------------------------------------------- Public ReadOnly Property Version As Version Get ' Remove prefixes and suffixes from tagname, like: "v1.0", "1.0-alpha" or "1.0-beta". Dim str As String = Me.TagName.ToLower(). Trim("abcdefghijklmnopqrstuvwxyz !·$%&/()=?\|@#~'^*¨;:,.{}[]+".ToArray()) Dim result As Version = Nothing Version.TryParse(str, result) Return result End Get End Property ''' <summary> ''' Gets the body, in MarkDown format. ''' </summary> Public ReadOnly Property Body As String ''' <summary> ''' Gets the commition target. ''' </summary> Public ReadOnly Property TargetCommitish As String ''' <summary> ''' Gets an <see cref="Uri"/> that points to the release page. ''' </summary> Public ReadOnly Property UriRelease As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the assets page of this release. ''' </summary> Public ReadOnly Property UriAssets As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the tarball of this release. ''' </summary> Public ReadOnly Property UriTarball As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the zipball of this release. ''' </summary> Public ReadOnly Property UriZipball As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the release page for a web-browser. ''' </summary> Public ReadOnly Property UriHtml As Uri ''' <summary> ''' Gets a value that determine whether this release is a draft. ''' </summary> Public ReadOnly Property IsDraft As Boolean ''' <summary> ''' Gets a value that determine whether this release is a pre-release. ''' </summary> Public ReadOnly Property IsPreRelease As Boolean ''' <summary> ''' Gets the creation datetime. ''' </summary> Public ReadOnly Property DateCreated As Date ''' <summary> ''' Gets the published datetime. ''' </summary> Public ReadOnly Property DatePublished As Date ''' <summary> ''' Gets the author of this release. ''' </summary> Public ReadOnly Property Author As GitHubAuthor ''' <summary> ''' Gets the assets of this release. ''' </summary> Public ReadOnly Property Assets As ReadOnlyCollection(Of GitHubAsset) ''' <summary> ''' Prevents a default instance of the <see cref="GitHubRelease"/> class from being created. ''' </summary> Private Sub New() End Sub ''' <summary> ''' Initializes a new instance of the <see cref="GitHubRelease"/> class. ''' </summary> ''' <param name="xml"> ''' An <see cref="XElement"/> that contains the fields to parse. ''' <para></para> ''' See: <see href="https://api.github.com/repos/{user}/{repo}/releases"/> ''' </param> Public Sub New(ByVal xml As XElement) Me.Id = xml.<id>.Value Me.Name = xml.<name>.Value Me.TagName = xml.<tag_name>.Value Me.Body = xml.<body>.Value Me.TargetCommitish = xml.<target_commitish>.Value Me.UriRelease = New Uri(xml.<url>.Value, UriKind.Absolute) Me.UriAssets = New Uri(xml.<assets_url>.Value, UriKind.Absolute) Me.UriHtml = New Uri(xml.<html_url>.Value, UriKind.Absolute) Me.UriTarball = New Uri(xml.<tarball_url>.Value, UriKind.Absolute) Me.UriZipball = New Uri(xml.<zipball_url>.Value, UriKind.Absolute) Me.IsDraft = xml.<draft>.Value Me.IsPreRelease = xml.<prerelease>.Value Me.DateCreated = Date.Parse(xml.<created_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat) Me.DatePublished = Date.Parse(xml.<published_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat) Me.Author = New GitHubAuthor(xml.<author>.SingleOrDefault()) Dim elements As IEnumerable(Of XElement) = xml.<assets>.<item> For Each element As XElement In elements Dim asset As New GitHubAsset(element) assets.Add(asset) Next Me.Assets = New ReadOnlyCollection(Of GitHubAsset)(assets) End Sub ''' <summary> ''' Returns a <see cref="String"/> that represents this release. ''' </summary> ''' <returns> ''' A <see cref="String"/> that represents this release. ''' </returns> Public Overrides Function ToString() As String Dim kvPairs As New NameValueCollection(EqualityComparer(Of String).Default) From { {NameOf(Me.Id), Me.Id}, {NameOf(Me.TagName), Me.TagName}, {NameOf(Me.Name), Me.Name}, {NameOf(Me.TargetCommitish), Me.TargetCommitish}, {NameOf(Me.IsDraft), Me.IsDraft}, {NameOf(Me.IsPreRelease), Me.IsPreRelease}, {NameOf(Me.DateCreated), Me.DateCreated.ToString("MM/dd/yyyy HH:mm:ss")}, {NameOf(Me.DatePublished), Me.DatePublished.ToString("MM/dd/yyyy HH:mm:ss")}, {NameOf(Me.UriHtml), Me.UriHtml.AbsoluteUri} } Return String.Format("{{{0}}}", String.Join(", ", (From key In kvPairs.AllKeys, value In kvPairs.GetValues(key) Select String.Format("{0}={1}", key, value)))) End Function ''' <summary> ''' Implements the operator <>. ''' </summary> ''' <param name="release1"> ''' The first <see cref="GitHubRelease"/>. ''' </param> ''' <param name="release2"> ''' The second <see cref="GitHubRelease"/>. ''' </param> ''' <returns> ''' The result of the operator. ''' </returns> Public Shared Operator <>(ByVal release1 As GitHubRelease, ByVal release2 As GitHubRelease) As Boolean Return (release1.Id <> release2.Id) End Operator ''' <summary> ''' Implements the operator =. ''' </summary> ''' <param name="release1"> ''' The first <see cref="GitHubRelease"/>. ''' </param> ''' <param name="release2"> ''' The second <see cref="GitHubRelease"/>. ''' </param> ''' <returns> ''' The result of the operator. ''' </returns> Public Shared Operator =(ByVal release1 As GitHubRelease, ByVal release2 As GitHubRelease) As Boolean Return (release1.Id = release2.Id) End Operator End Class
GitHubAsset.vb
Código
''' <summary> ''' Represents an asset of a release on GitHub. ''' </summary> ''' <seealso href="https://github.com"/> Public NotInheritable Class GitHubAsset ''' <summary> ''' Gets the GitHub's unique identifier for this asset. ''' </summary> Public ReadOnly Property Id As String ''' <summary> ''' Gets the name of this asset. ''' </summary> Public ReadOnly Property Name As String ''' <summary> ''' Gets the label of this asset. ''' </summary> Public ReadOnly Property Label As String ''' <summary> ''' Gets the state of this asset. ''' </summary> Public ReadOnly Property State As String ''' <summary> ''' Gets the size of this asset, in bytes. ''' </summary> Public ReadOnly Property Size As Long ''' <summary> ''' Gets a value indicating how many times this asset was downloaded. ''' </summary> Public ReadOnly Property DownloadCount As Integer ''' <summary> ''' Gets the content-type of this asset. ''' </summary> Public ReadOnly Property ContentType As ContentType ''' <summary> ''' Gets an <see cref="Uri"/> that points to the page of this asset. ''' </summary> Public ReadOnly Property UriAsset As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the download page of this asset. ''' </summary> Public ReadOnly Property UriDownload As Uri ''' <summary> ''' Gets the creation datetime. ''' </summary> Public ReadOnly Property DateCreated As Date ''' <summary> ''' Gets the uploaded datetime. ''' </summary> Public ReadOnly Property DateUploaded As Date ''' <summary> ''' Gets the uploader of this asset. ''' </summary> Public ReadOnly Property Uploader As GitHubAuthor ''' <summary> ''' Prevents a default instance of the <see cref="GitHubAsset"/> class from being created. ''' </summary> Private Sub New() End Sub ''' <summary> ''' Initializes a new instance of the <see cref="GitHubAsset"/> class. ''' </summary> ''' <param name="xml"> ''' An <see cref="XElement"/> that contains the fields to parse. ''' <para></para> ''' See: <see href="https://api.github.com/repos/{user}/{repo}/releases"/> ''' </param> Public Sub New(ByVal xml As XElement) Me.Id = xml.<id>.Value Me.Name = xml.<name>.Value Me.Label = xml.<label>.Value Me.State = xml.<state>.Value Me.Size = xml.<size>.Value Me.ContentType = New ContentType(xml.<content_type>.Value) Me.DownloadCount = xml.<download_count>.Value Me.DateCreated = Date.Parse(xml.<created_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat) Me.DateUploaded = Date.Parse(xml.<updated_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat) Me.UriAsset = New Uri(xml.<url>.Value, UriKind.Absolute) Me.UriDownload = New Uri(xml.<browser_download_url>.Value, UriKind.Absolute) Me.Uploader = New GitHubAuthor(xml.<uploader>.Single()) End Sub ''' <summary> ''' Returns a <see cref="String"/> that represents this asset. ''' </summary> ''' <returns> ''' A <see cref="String"/> that represents this asset. ''' </returns> Public Overrides Function ToString() As String Dim kvPairs As New NameValueCollection(EqualityComparer(Of String).Default) From { {NameOf(Me.Id), Me.Id}, {NameOf(Me.Name), Me.Name}, {NameOf(Me.Label), Me.Label}, {NameOf(Me.State), Me.State}, {NameOf(Me.Size), Me.Size}, {NameOf(Me.ContentType), Me.ContentType.ToString()}, {NameOf(Me.DownloadCount), Me.DownloadCount}, {NameOf(Me.DateCreated), Me.DateCreated.ToString("MM/dd/yyyy HH:mm:ss")}, {NameOf(Me.DateUploaded), Me.DateUploaded.ToString("MM/dd/yyyy HH:mm:ss")}, {NameOf(Me.UriDownload), Me.UriDownload.AbsoluteUri} } Return String.Format("{{{0}}}", String.Join(", ", (From key In kvPairs.AllKeys, value In kvPairs.GetValues(key) Select String.Format("{0}={1}", key, value)))) End Function ''' <summary> ''' Implements the operator <>. ''' </summary> ''' <param name="asset1"> ''' The first <see cref="GitHubAsset"/>. ''' </param> ''' <param name="asset2"> ''' The second <see cref="GitHubAsset"/>. ''' </param> ''' <returns> ''' The result of the operator. ''' </returns> Public Shared Operator <>(ByVal asset1 As GitHubAsset, ByVal asset2 As GitHubAsset) As Boolean Return (asset1.Id <> asset2.Id) End Operator ''' <summary> ''' Implements the operator =. ''' </summary> ''' <param name="asset1"> ''' The first <see cref="GitHubAsset"/>. ''' </param> ''' <param name="asset2"> ''' The second <see cref="GitHubAsset"/>. ''' </param> ''' <returns> ''' The result of the operator. ''' </returns> Public Shared Operator =(ByVal asset1 As GitHubAsset, ByVal asset2 As GitHubAsset) As Boolean Return (asset1.Id = asset2.Id) End Operator End Class
GitHubAuthor.vb
Código
''' <summary> ''' Represents the author of a release or the uploader of an asset on GitHub. ''' </summary> ''' <seealso href="https://github.com"/> Public NotInheritable Class GitHubAuthor ''' <summary> ''' Gets the GitHub's unique identifier for this author. ''' </summary> Public ReadOnly Property Id As String ''' <summary> ''' Gets the author name. ''' </summary> Public ReadOnly Property Name As String ''' <summary> ''' Gets the type of user. ''' </summary> Public ReadOnly Property [Type] As String ''' <summary> ''' Gets a value that determine whether this author is a site administrator. ''' </summary> Public ReadOnly Property IsSiteAdministrator As Boolean ''' <summary> ''' Gets the unique identifier of the Gravatar. ''' <para></para> ''' See for more info: <see href="https://gravatar.com/"/> ''' </summary> Public ReadOnly Property GravatarId As String ''' <summary> ''' Gets an <see cref="Uri"/> that points to the author page. ''' </summary> Public ReadOnly Property UriAuthor As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the avatar page of this author. ''' </summary> Public ReadOnly Property UriAvatar As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the followers page of this author. ''' </summary> Public ReadOnly Property UriFollowers As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the subscriptions page of this author. ''' </summary> Public ReadOnly Property UriSubscriptions As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the organizations page of this author. ''' </summary> Public ReadOnly Property UriOrganizations As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the repositories page of this author. ''' </summary> Public ReadOnly Property UriRepositories As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the received events page of this author. ''' </summary> Public ReadOnly Property UriReceivedEvents As Uri ''' <summary> ''' Gets an <see cref="Uri"/> that points to the author page for a web-browser. ''' </summary> Public ReadOnly Property UriHtml As Uri ''' <summary> ''' Prevents a default instance of the <see cref="GitHubAuthor"/> class from being created. ''' </summary> Private Sub New() End Sub ''' <summary> ''' Initializes a new instance of the <see cref="GitHubAuthor"/> class. ''' </summary> ''' <param name="xml"> ''' An <see cref="XElement"/> that contains the fields to parse. ''' <para></para> ''' See: <see href="https://api.github.com/repos/{user}/{repo}/releases"/> ''' </param> Public Sub New(ByVal xml As XElement) Me.Id = xml.<id>.Value Me.Name = xml.<login>.Value Me.Type = xml.<type>.Value Me.IsSiteAdministrator = xml.<site_admin>.Value Me.GravatarId = xml.<gravatar_id>.Value Me.UriAuthor = New Uri(xml.<url>.Value, UriKind.Absolute) Me.UriAvatar = New Uri(xml.<avatar_url>.Value, UriKind.Absolute) Me.UriSubscriptions = New Uri(xml.<subscriptions_url>.Value, UriKind.Absolute) Me.UriOrganizations = New Uri(xml.<organizations_url>.Value, UriKind.Absolute) Me.UriRepositories = New Uri(xml.<repos_url>.Value, UriKind.Absolute) Me.UriReceivedEvents = New Uri(xml.<received_events_url>.Value, UriKind.Absolute) Me.UriHtml = New Uri(xml.<html_url>.Value, UriKind.Absolute) End Sub ''' <summary> ''' Returns a <see cref="String"/> that represents this author. ''' </summary> ''' <returns> ''' A <see cref="String"/> that represents this author. ''' </returns> Public Overrides Function ToString() As String Dim kvPairs As New NameValueCollection(EqualityComparer(Of String).Default) From { {NameOf(Me.Id), Me.Id}, {NameOf(Me.Name), Me.Name}, {NameOf(Me.Type), Me.Type}, {NameOf(Me.IsSiteAdministrator), Me.IsSiteAdministrator}, {NameOf(Me.UriHtml), Me.UriHtml.AbsoluteUri} } Return String.Format("{{{0}}}", String.Join(", ", (From key In kvPairs.AllKeys, value In kvPairs.GetValues(key) Select String.Format("{0}={1}", key, value)))) End Function ''' <summary> ''' Implements the operator <>. ''' </summary> ''' <param name="author1"> ''' The first <see cref="GitHubAuthor"/>. ''' </param> ''' <param name="author2"> ''' The second <see cref="GitHubAuthor"/>. ''' </param> ''' <returns> ''' The result of the operator. ''' </returns> Public Shared Operator <>(ByVal author1 As GitHubAuthor, ByVal author2 As GitHubAuthor) As Boolean Return (author1.Id <> author2.Id) End Operator ''' <summary> ''' Implements the operator =. ''' </summary> ''' <param name="author1"> ''' The first <see cref="GitHubAuthor"/>. ''' </param> ''' <param name="author2"> ''' The second <see cref="GitHubAuthor"/>. ''' </param> ''' <returns> ''' The result of the operator. ''' </returns> Public Shared Operator =(ByVal author1 As GitHubAuthor, ByVal author2 As GitHubAuthor) As Boolean Return (author1.Id = author2.Id) End Operator End Class
GitHubUtil.vb
Código
Public NotInheritable Class GitHubUtil #Region " Constructors " ''' <summary> ''' Prevents a default instance of the <see cref="GitHubUtil"/> class from being created. ''' </summary> Private Sub New() End Sub #End Region #Region " Public Methods " ''' <summary> ''' Asynchronously gets the releases from the specified repository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <returns> ''' A <see cref="Task(Of ReadOnlyCollection(Of GitHubRelease))"/> containing the releases. ''' </returns> ''' <exception cref="HttpException"> ''' JSON validation error. ''' </exception> Public Shared Async Function GetReleasesAsync(ByVal userName As String, ByVal repositoryName As String) As Task(Of ReadOnlyCollection(Of GitHubRelease)) Dim uri As New Uri(String.Format("https://api.github.com/repos/{0}/{1}/releases", userName, repositoryName), UriKind.Absolute) Dim request As HttpWebRequest = DirectCast(WebRequest.Create(uri), HttpWebRequest) request.UserAgent = userName Using response As WebResponse = Await request.GetResponseAsync(), sr As New StreamReader(response.GetResponseStream()), xmlReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(sr.BaseStream, Encoding.UTF8, New XmlDictionaryReaderQuotas, Nothing) Dim xml As XElement = XElement.Load(xmlReader) If (xml.IsEmpty) Then Dim errMsg As String = String.Format("JSON validation error. ""{0}""", uri.ToString()) Throw New HttpException(HttpStatusCode.NotFound, errMsg) End If Dim elements As IEnumerable(Of XElement) = xml.<item> For Each element As XElement In elements Dim release As New GitHubRelease(element) releases.Add(release) Next Return New ReadOnlyCollection(Of GitHubRelease)(releases) End Using End Function ''' <summary> ''' Gets the releases from the specified repository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <returns> ''' A <see cref="ReadOnlyCollection(Of GitHubRelease)"/> collection containing the releases. ''' </returns> Public Shared Function GetReleases(ByVal userName As String, ByVal repositoryName As String) As ReadOnlyCollection(Of GitHubRelease) Dim t As Task(Of ReadOnlyCollection(Of GitHubRelease)) = Task.Run(Function() GitHubUtil.GetReleases(userName, repositoryName)) t.Wait(Timeout.Infinite) Return t.Result End Function ''' <summary> ''' Asynchronously gets a release that matches the specified version from the specified repository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <param name="version"> ''' The version of the release. ''' </param> ''' <returns> ''' The resulting <see cref="GitHubRelease"/>. ''' </returns> Public Shared Async Function GetReleaseAsync(ByVal userName As String, ByVal repositoryName As String, ByVal version As Version) As Task(Of GitHubRelease) Return (From release As GitHubRelease In Await GetReleasesAsync(userName, repositoryName) Where release.Version = version). DefaultIfEmpty(Nothing). SingleOrDefault() End Function ''' <summary> ''' Gets a release that matches the specified version from the specified repository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <param name="version"> ''' The version of the release. ''' </param> ''' <returns> ''' The resulting <see cref="GitHubRelease"/>. ''' </returns> Public Shared Function GetRelease(ByVal userName As String, ByVal repositoryName As String, ByVal version As Version) As GitHubRelease Dim t As Task(Of GitHubRelease) = Task.Run(Function() GitHubUtil.GetRelease(userName, repositoryName, version)) t.Wait(Timeout.Infinite) Return t.Result End Function ''' <summary> ''' Asynchronously gets the latest release from the specified repository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <returns> ''' The resulting <see cref="GitHubRelease"/>. ''' </returns> ''' <exception cref="HttpException"> ''' JSON validation error. ''' </exception> Public Shared Async Function GetLatestReleaseAsync(ByVal userName As String, ByVal repositoryName As String) As Task(Of GitHubRelease) Dim uri As New Uri(String.Format("https://api.github.com/repos/{0}/{1}/releases/latest", userName, repositoryName), UriKind.Absolute) Dim request As HttpWebRequest = WebRequest.Create(uri) request.UserAgent = userName Using response As WebResponse = Await request.GetResponseAsync(), sr As New StreamReader(response.GetResponseStream()), xmlReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(sr.BaseStream, Encoding.UTF8, New XmlDictionaryReaderQuotas, Nothing) Dim xml As XElement = XElement.Load(xmlReader) If (xml.IsEmpty) Then Dim errMsg As String = String.Format("JSON validation error. ""{0}""", uri.ToString()) Throw New HttpException(HttpStatusCode.NotFound, errMsg) End If Return New GitHubRelease(xml) End Using End Function ''' <summary> ''' Gets the latest release from the specified repository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <returns> ''' The resulting <see cref="GitHubRelease"/>. ''' </returns> Public Shared Function GetLatestRelease(ByVal userName As String, ByVal repositoryName As String) As GitHubRelease Dim t As Task(Of GitHubRelease) = Task.Run(Function() GitHubUtil.GetLatestReleaseAsync(userName, repositoryName)) t.Wait(Timeout.Infinite) Return t.Result End Function ''' <summary> ''' Asynchronously gets a value that determine whether exists a new version available of the specified reository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <param name="currentVersion"> ''' The current version. ''' </param> ''' <returns> ''' <see langword="True"/> if exists a new version available on GitHub; otherwise, <see langword="False"/>. ''' </returns> Public Shared Async Function IsUpdateAvailableAsync(ByVal userName As String, ByVal repositoryName As String, ByVal currentVersion As Version) As Task(Of Boolean) Dim latestRelease As GitHubRelease = Await GitHubUtil.GetLatestReleaseAsync(userName, repositoryName) Return (latestRelease.Version > currentVersion) End Function ''' <summary> ''' Gets a value that determine whether exists a new version available of the specified reository on GitHub. ''' </summary> ''' <param name="userName"> ''' The user name. ''' </param> ''' <param name="repositoryName"> ''' The repository name. ''' </param> ''' <param name="currentVersion"> ''' The current version. ''' </param> ''' <returns> ''' <see langword="True"/> if exists a new version available on GitHub; otherwise, <see langword="False"/>. ''' </returns> Public Shared Function IsUpdateAvailable(ByVal userName As String, ByVal repositoryName As String, ByVal currentVersion As Version) As Boolean Dim t As Task(Of Boolean) = Task.Run(Function() GitHubUtil.IsUpdateAvailableAsync(userName, repositoryName, currentVersion)) t.Wait(Timeout.Infinite) Return t.Result End Function #End Region End Class