Add support for Gitea (#134)

* Add NuGet package

* Add Gitea support

* Add OS option

* Add Gitea test

Add test for release check

---------

Co-authored-by: Caelan Sayler <git@caesay.com>
This commit is contained in:
Remco Fischer
2024-06-27 22:21:13 +02:00
committed by GitHub
parent ad7ce6a75a
commit 8950b2138b
13 changed files with 766 additions and 25 deletions

View File

@@ -0,0 +1,188 @@
using System.Net;
using System.Text;
using Gitea.Net.Api;
using Gitea.Net.Client;
using Gitea.Net.Model;
using Microsoft.Extensions.Logging;
using Velopack.NuGet;
using Velopack.Packaging;
using Velopack.Packaging.Exceptions;
using Velopack.Sources;
namespace Velopack.Deployment;
public class GiteaDownloadOptions : RepositoryOptions
{
public bool Prerelease { get; set; }
public string RepoUrl { get; set; }
public string Token { get; set; }
///// <summary>
///// Example https://gitea.com
///// </summary>
//public string ServerUrl { get; set; }
//public int ServerPort { get; set; }
}
public class GiteaUploadOptions : GiteaDownloadOptions
{
public bool Publish { get; set; }
public string ReleaseName { get; set; }
public string TagName { get; set; }
public string TargetCommitish { get; set; }
public bool Merge { get; set; }
}
public class GiteaRepository : SourceRepository<GiteaDownloadOptions, GiteaSource>, IRepositoryCanUpload<GiteaUploadOptions>
{
public GiteaRepository(ILogger logger) : base(logger)
{
}
public override GiteaSource CreateSource(GiteaDownloadOptions options)
{
return new GiteaSource(options.RepoUrl, options.Token, options.Prerelease);
}
public static (string owner, string repo) GetOwnerAndRepo(string repoUrl)
{
var repoUri = new Uri(repoUrl);
var repoParts = repoUri.AbsolutePath.Trim('/').Split('/');
if (repoParts.Length != 2)
throw new Exception($"Invalid Gitea URL, '{repoUri.AbsolutePath}' should be in the format 'owner/repo'");
var repoOwner = repoParts[0];
var repoName = repoParts[1];
return (repoOwner, repoName);
}
public async Task UploadMissingAssetsAsync(GiteaUploadOptions options)
{
var (repoOwner, repoName) = GetOwnerAndRepo(options.RepoUrl);
var helper = new ReleaseEntryHelper(options.ReleaseDir.FullName, options.Channel, Log, options.TargetOs);
var build = BuildAssets.Read(options.ReleaseDir.FullName, options.Channel);
var latest = helper.GetLatestFullRelease();
var latestPath = Path.Combine(options.ReleaseDir.FullName, latest.FileName);
var releaseNotes = new ZipPackage(latestPath).ReleaseNotes;
var semVer = options.TagName ?? latest.Version.ToString();
var releaseName = string.IsNullOrWhiteSpace(options.ReleaseName) ? semVer.ToString() : options.ReleaseName;
// Setup Gitea config
Configuration config = new Configuration();
// Example: http://www.Gitea.com/api/v1
var uri = new Uri(options.RepoUrl);
var baseUri = uri.GetLeftPart(System.UriPartial.Authority);
config.BasePath = baseUri + "/api/v1";
Log.Info($"Preparing to upload {build.Files.Count} asset(s) to Gitea");
// Set token if provided
if (!string.IsNullOrWhiteSpace(options.Token)) {
config.ApiKey.Add("token", options.Token);
}
var apiInstance = new RepositoryApi(config);
// Get all releases
// Get repository info for total releases
List<Release> existingReleases = null;
ApiResponse<Repository> repositoryInfo = await apiInstance.RepoGetWithHttpInfoAsync(repoOwner, repoName);
if (repositoryInfo != null && repositoryInfo.StatusCode == HttpStatusCode.OK) {
// Get all releases
var allReleases = await apiInstance.RepoListReleasesWithHttpInfoAsync(repoOwner, repoName, page: 1, limit: (int) repositoryInfo.Data.ReleaseCounter);
existingReleases = allReleases.Data;
if (allReleases != null && allReleases.StatusCode == HttpStatusCode.OK && allReleases.Data.Any(r => r.Name == releaseName)) {
throw new UserInfoException($"There is already an existing release named '{releaseName}'. Please delete this release or provide a new release name.");
}
} else {
throw new UserInfoException("Could not get all releases from server");
}
if (!options.Merge) {
if (existingReleases.Any(r => r.TagName == semVer.ToString())) {
throw new UserInfoException($"There is already an existing release tagged '{semVer}'. Please delete this release or provide a new version number.");
}
if (existingReleases.Any(r => r.Name == releaseName)) {
throw new UserInfoException($"There is already an existing release named '{releaseName}'. Please delete this release or provide a new release name.");
}
}
// create or retrieve github release
var release = existingReleases.FirstOrDefault(r => r.TagName == semVer.ToString())
?? existingReleases.FirstOrDefault(r => r.Name == releaseName); ;
if (release != null) {
if (release.TagName != semVer.ToString())
throw new UserInfoException($"Found existing release matched by name ({release.Name} [{release.TagName}]), but tag name does not match ({semVer}).");
Log.Info($"Found existing release ({release.Name} [{release.TagName}]). Merge flag is enabled.");
} else {
var newReleaseReq = new CreateReleaseOption(
body: releaseNotes,
draft: true,
prerelease: options.Prerelease,
name: string.IsNullOrWhiteSpace(options.ReleaseName) ? semVer.ToString() : options.ReleaseName,
targetCommitish: options.TargetCommitish,
tagName: semVer.ToString()
);
Log.Info($"Creating draft release titled '{newReleaseReq.Name}'");
release = await apiInstance.RepoCreateReleaseAsync(repoOwner, repoName, newReleaseReq);
}
// check if there is an existing releasesFile to merge
var releasesFileName = Utility.GetVeloReleaseIndexName(options.Channel);
var releaseAsset = release.Assets.FirstOrDefault(a => a.Name == releasesFileName);
if (releaseAsset != null) {
throw new UserInfoException($"There is already a remote asset named '{releasesFileName}', and merging release files on Gitea is not supported.");
}
// upload all assets (incl packages)
foreach (var a in build.Files) {
await RetryAsync(() => UploadFileAsAsset(apiInstance, release, repoOwner, repoName, a), $"Uploading asset '{Path.GetFileName(a)}'..");
}
var feed = new VelopackAssetFeed {
Assets = build.GetReleaseEntries().ToArray(),
};
var json = ReleaseEntryHelper.GetAssetFeedJson(feed);
await RetryAsync(async () => {
await apiInstance.RepoCreateReleaseAttachmentAsync(repoOwner, repoName, release.Id, releasesFileName, new MemoryStream(Encoding.UTF8.GetBytes(json)));
}, "Uploading " + releasesFileName);
if (options.Channel == ReleaseEntryHelper.GetDefaultChannel(RuntimeOs.Windows)) {
var legacyReleasesContent = ReleaseEntryHelper.GetLegacyMigrationReleaseFeedString(feed);
var legacyReleasesBytes = Encoding.UTF8.GetBytes(legacyReleasesContent);
await RetryAsync(async () => {
await apiInstance.RepoCreateReleaseAttachmentAsync(repoOwner, repoName, release.Id, "RELEASES", new MemoryStream(legacyReleasesBytes));
}, "Uploading legacy RELEASES (compatibility)");
}
// convert draft to full release
if (options.Publish) {
if (release.Draft) {
Log.Info("Converting draft to full published release.");
var body = new EditReleaseOption(
release.Body,
false, // Draft
release.Name,
release.Prerelease,
release.TagName,
release.TargetCommitish
);
Release result = await apiInstance.RepoEditReleaseAsync(repoOwner, repoName, release.Id, body);
} else {
Log.Info("Skipping publish, release is already not a draft.");
}
}
}
private async Task UploadFileAsAsset(RepositoryApi client, Release release, string repoOwner, string repoName, string filePath)
{
using var stream = File.OpenRead(filePath);
// Create a release attachment
await client.RepoCreateReleaseAttachmentAsync(repoOwner, repoName, release.Id, Path.GetFileName(filePath), stream);
}
}

View File

@@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="AWSSDK.S3" Version="3.7.308.8" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.20.0" />
<PackageReference Include="Gitea.Net.API" Version="1.0.0" />
<PackageReference Include="Octokit" Version="11.0.1" />
</ItemGroup>

View File

@@ -21,6 +21,19 @@
"System.Text.Json": "4.7.2"
}
},
"Gitea.Net.API": {
"type": "Direct",
"requested": "[1.0.0, )",
"resolved": "1.0.0",
"contentHash": "5ZhKnsZfIjJ/aFeZFibi1VY8oOam0rQFf30A5gqxM5F3yoxpr1qHxeks10hvdgerGFMHSXgV8FDvtTHM4OA3Qw==",
"dependencies": {
"JsonSubTypes": "2.0.1",
"Microsoft.AspNetCore.SystemWebAdapters": "1.3.0",
"Newtonsoft.Json": "13.0.3",
"Polly": "8.4.0",
"RestSharp": "111.2.0"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
@@ -72,16 +85,40 @@
"System.IO.Hashing": "6.0.0"
}
},
"JsonSubTypes": {
"type": "Transitive",
"resolved": "2.0.1",
"contentHash": "1Po+Ypf0SjCeEKx5+C89Nb5OgTcqNvfS3uTI46MUM+KEp6Rq/M0h+vVsTUt/6DFRwZMTpsAJM4yJrZmEObVANA==",
"dependencies": {
"Newtonsoft.Json": "13.0.1"
}
},
"Markdig": {
"type": "Transitive",
"resolved": "0.37.0",
"contentHash": "biiu4MTPFjW55qw6v5Aphtj0MjDLJ14x8ndZwkJUHIeqvaSGKeqhLY7S7Vu/S3k7/c9KwhhnaCDP9hdFNUhcNA=="
},
"Microsoft.AspNetCore.SystemWebAdapters": {
"type": "Transitive",
"resolved": "1.3.0",
"contentHash": "1gomLUkk2dfZbznBAPb/HCZzlA+7QNKb08v5GzPh/tqhkUaKZHR8PHh0vmJlZGAj8vnvNLnzpfIwwCdq/9BHWQ==",
"dependencies": {
"System.Runtime.Caching": "6.0.0"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
},
"Microsoft.Bcl.TimeProvider": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "f5Kr5JepAbiGo7uDmhgvMqhntwxqXNn6/IpTBSSI4cuHhgnJGrLxFRhMjVpRkLPp6zJXO0/G0l3j9p9zSJxa+w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "6.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
@@ -144,11 +181,42 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.Win32.SystemEvents": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"NuGet.Versioning": {
"type": "Transitive",
"resolved": "6.10.0",
"contentHash": "ytTA08tgZWo/Pbk333hnzQfiMyyynkkwMt4GyC5T0bzExYYSRNrkwv4jT8jmWr5LUOYsumEZvXdoven2SA7YZw=="
},
"Polly": {
"type": "Transitive",
"resolved": "8.4.0",
"contentHash": "z2EeUutuy49jBQyZ5s2FUuTCGx3GCzJ0cJ2HbjWwks94TsC6bKTtAHKBkMZOa/DyYRl5yIX7MshvMTWl1J6RNg==",
"dependencies": {
"Polly.Core": "8.4.0"
}
},
"Polly.Core": {
"type": "Transitive",
"resolved": "8.4.0",
"contentHash": "3AZxuP//pxOeBo9tQs7/tz4Z5TTbu4BYfjpaXZD0JYKJo98ngN9TMUz1nybh4k0ykWkMBpGZALV/AmVIE3ew7A==",
"dependencies": {
"Microsoft.Bcl.TimeProvider": "8.0.0"
}
},
"RestSharp": {
"type": "Transitive",
"resolved": "111.2.0",
"contentHash": "OkWr6AGM0zirdkRpxVOxXMWx9OHEIWrDzrpx1XIx5KyvTcmtjJVsKBscVkYTcFerhj5w5Bny7boRIV4a0ENGaQ=="
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
@@ -283,6 +351,15 @@
"System.Threading.Tasks": "4.3.0"
}
},
"System.Configuration.ConfigurationManager": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==",
"dependencies": {
"System.Security.Cryptography.ProtectedData": "6.0.0",
"System.Security.Permissions": "6.0.0"
}
},
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -311,6 +388,14 @@
"System.Runtime": "4.3.0"
}
},
"System.Drawing.Common": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==",
"dependencies": {
"Microsoft.Win32.SystemEvents": "6.0.0"
}
},
"System.Globalization": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -506,6 +591,14 @@
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.Caching": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "E0e03kUp5X2k+UAoVl6efmI7uU7JRBWi5EIdlQ7cr0NpBGjHG4fWII35PgsBY9T4fJQ8E4QPsL0rKksU9gcL5A==",
"dependencies": {
"System.Configuration.ConfigurationManager": "6.0.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -555,6 +648,11 @@
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ=="
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -669,8 +767,8 @@
},
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q=="
"resolved": "6.0.0",
"contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ=="
},
"System.Security.Cryptography.X509Certificates": {
"type": "Transitive",
@@ -704,6 +802,15 @@
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Permissions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==",
"dependencies": {
"System.Security.AccessControl": "6.0.0",
"System.Windows.Extensions": "6.0.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -748,6 +855,14 @@
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
},
"System.Windows.Extensions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==",
"dependencies": {
"System.Drawing.Common": "6.0.0"
}
},
"velopack": {
"type": "Project",
"dependencies": {

View File

@@ -0,0 +1,19 @@
namespace Velopack.Vpk.Commands.Deployment;
public abstract class GiteaBaseCommand : OutputCommand
{
public string RepoUrl { get; private set; }
public string Token { get; private set; }
protected GiteaBaseCommand(string name, string description)
: base(name, description)
{
var repoUrl = AddOption<Uri>((v) => RepoUrl = v.ToAbsoluteOrNull(), "--repoUrl")
.SetDescription("Full url to the gitea repository (eg. 'https://gitea.com/myname/myrepo').")
.SetRequired()
.MustBeValidHttpUri();
AddOption<string>((v) => Token = v, "--token")
.SetDescription("OAuth token to use as login credentials.");
}
}

View File

@@ -0,0 +1,12 @@
namespace Velopack.Vpk.Commands.Deployment;
public class GiteaDownloadCommand : GiteaBaseCommand
{
public bool Prerelease { get; private set; }
public GiteaDownloadCommand()
: base("gitea", "Download latest release from Gitea repository.")
{
AddOption<bool>((v) => Prerelease = v, "--pre")
.SetDescription("Get latest pre-release instead of stable.");
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Velopack.Vpk.Commands.Deployment;
public class GiteaUploadCommand : GiteaBaseCommand
{
public bool Publish { get; private set; }
public string ReleaseName { get; private set; }
public string TagName { get; private set; }
public string TargetCommitish { get; private set; }
public bool Prerelease { get; private set; }
public bool Merge { get; private set; }
public GiteaUploadCommand()
: base("gitea", "Upload releases to a Gitea repository.")
{
AddOption<bool>((v) => Publish = v, "--publish")
.SetDescription("Create and publish instead of leaving as draft.");
AddOption<bool>((v) => Prerelease = v, "--pre")
.SetDescription("Create as pre-release instead of stable.");
AddOption<bool>((v) => Merge = v, "--merge")
.SetDescription("Allow merging this upload with an existing release.");
AddOption<string>((v) => ReleaseName = v, "--releaseName")
.SetDescription("A custom name for the release.")
.SetArgumentHelpName("NAME");
AddOption<string>((v) => TagName = v, "--tag")
.SetDescription("A custom tag for the release.")
.SetArgumentHelpName("NAME");
AddOption<string>((v) => TargetCommitish = v, "--targetCommitish")
.SetDescription("A commitish value for tag (branch or commit SHA).")
.SetArgumentHelpName("NAME");
ReleaseDirectoryOption.SetRequired();
ReleaseDirectoryOption.MustNotBeEmpty();
}
}

View File

@@ -22,6 +22,8 @@ public static partial class OptionMapper
public static partial OsxBundleOptions ToOptions(this OsxBundleCommand cmd);
public static partial GitHubDownloadOptions ToOptions(this GitHubDownloadCommand cmd);
public static partial GitHubUploadOptions ToOptions(this GitHubUploadCommand cmd);
public static partial GiteaDownloadOptions ToOptions(this GiteaDownloadCommand cmd);
public static partial GiteaUploadOptions ToOptions(this GiteaUploadCommand cmd);
public static partial HttpDownloadOptions ToOptions(this HttpDownloadCommand cmd);
public static partial LocalDownloadOptions ToOptions(this LocalDownloadCommand cmd);
public static partial LocalUploadOptions ToOptions(this LocalUploadCommand cmd);

View File

@@ -132,6 +132,7 @@ public class Program
var downloadCommand = new CliCommand("download", "Download's the latest release from a remote update source.");
downloadCommand.AddRepositoryDownload<GitHubDownloadCommand, GitHubRepository, GitHubDownloadOptions>(provider);
downloadCommand.AddRepositoryDownload<GiteaDownloadCommand, GiteaRepository, GiteaDownloadOptions>(provider);
downloadCommand.AddRepositoryDownload<S3DownloadCommand, S3Repository, S3DownloadOptions>(provider);
downloadCommand.AddRepositoryDownload<AzureDownloadCommand, AzureRepository, AzureDownloadOptions>(provider);
downloadCommand.AddRepositoryDownload<LocalDownloadCommand, LocalRepository, LocalDownloadOptions>(provider);
@@ -140,6 +141,7 @@ public class Program
var uploadCommand = new CliCommand("upload", "Upload local package(s) to a remote update source.");
uploadCommand.AddRepositoryUpload<GitHubUploadCommand, GitHubRepository, GitHubUploadOptions>(provider);
uploadCommand.AddRepositoryUpload<GiteaUploadCommand, GiteaRepository, GiteaUploadOptions>(provider);
uploadCommand.AddRepositoryUpload<S3UploadCommand, S3Repository, S3UploadOptions>(provider);
uploadCommand.AddRepositoryUpload<AzureUploadCommand, AzureRepository, AzureUploadOptions>(provider);
uploadCommand.AddRepositoryUpload<LocalUploadCommand, LocalRepository, LocalUploadOptions>(provider);

View File

@@ -218,16 +218,52 @@
"resolved": "2.17.3",
"contentHash": "BFKpnrs3yKH/jo1yewQdvLKMkEaxE6Wj3Lu5LHRNJfcAdOQ9YiY4dfQ5+5kz6ji1E/Xcxy5ta+qqKGA6KiVQMw=="
},
"Gitea.Net.API": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "5ZhKnsZfIjJ/aFeZFibi1VY8oOam0rQFf30A5gqxM5F3yoxpr1qHxeks10hvdgerGFMHSXgV8FDvtTHM4OA3Qw==",
"dependencies": {
"JsonSubTypes": "2.0.1",
"Microsoft.AspNetCore.SystemWebAdapters": "1.3.0",
"Newtonsoft.Json": "13.0.3",
"Polly": "8.4.0",
"RestSharp": "111.2.0"
}
},
"JsonSubTypes": {
"type": "Transitive",
"resolved": "2.0.1",
"contentHash": "1Po+Ypf0SjCeEKx5+C89Nb5OgTcqNvfS3uTI46MUM+KEp6Rq/M0h+vVsTUt/6DFRwZMTpsAJM4yJrZmEObVANA==",
"dependencies": {
"Newtonsoft.Json": "13.0.1"
}
},
"Markdig": {
"type": "Transitive",
"resolved": "0.37.0",
"contentHash": "biiu4MTPFjW55qw6v5Aphtj0MjDLJ14x8ndZwkJUHIeqvaSGKeqhLY7S7Vu/S3k7/c9KwhhnaCDP9hdFNUhcNA=="
},
"Microsoft.AspNetCore.SystemWebAdapters": {
"type": "Transitive",
"resolved": "1.3.0",
"contentHash": "1gomLUkk2dfZbznBAPb/HCZzlA+7QNKb08v5GzPh/tqhkUaKZHR8PHh0vmJlZGAj8vnvNLnzpfIwwCdq/9BHWQ==",
"dependencies": {
"System.Runtime.Caching": "6.0.0"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
},
"Microsoft.Bcl.TimeProvider": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "f5Kr5JepAbiGo7uDmhgvMqhntwxqXNn6/IpTBSSI4cuHhgnJGrLxFRhMjVpRkLPp6zJXO0/G0l3j9p9zSJxa+w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "6.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
@@ -543,6 +579,11 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.Win32.SystemEvents": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
@@ -591,6 +632,27 @@
"resolved": "11.0.1",
"contentHash": "fpwF/DxMJyGS+pIXDKQozx0wCIpOfG8VDr10ls+m9Gn9Lz8GslhhApxkKD9JCNO60HRUeMJsedsAS24gCjTD7Q=="
},
"Polly": {
"type": "Transitive",
"resolved": "8.4.0",
"contentHash": "z2EeUutuy49jBQyZ5s2FUuTCGx3GCzJ0cJ2HbjWwks94TsC6bKTtAHKBkMZOa/DyYRl5yIX7MshvMTWl1J6RNg==",
"dependencies": {
"Polly.Core": "8.4.0"
}
},
"Polly.Core": {
"type": "Transitive",
"resolved": "8.4.0",
"contentHash": "3AZxuP//pxOeBo9tQs7/tz4Z5TTbu4BYfjpaXZD0JYKJo98ngN9TMUz1nybh4k0ykWkMBpGZALV/AmVIE3ew7A==",
"dependencies": {
"Microsoft.Bcl.TimeProvider": "8.0.0"
}
},
"RestSharp": {
"type": "Transitive",
"resolved": "111.2.0",
"contentHash": "OkWr6AGM0zirdkRpxVOxXMWx9OHEIWrDzrpx1XIx5KyvTcmtjJVsKBscVkYTcFerhj5w5Bny7boRIV4a0ENGaQ=="
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
@@ -753,6 +815,15 @@
"System.Threading.Tasks": "4.3.0"
}
},
"System.Configuration.ConfigurationManager": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==",
"dependencies": {
"System.Security.Cryptography.ProtectedData": "6.0.0",
"System.Security.Permissions": "6.0.0"
}
},
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -786,6 +857,14 @@
"System.Runtime": "4.3.0"
}
},
"System.Drawing.Common": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==",
"dependencies": {
"Microsoft.Win32.SystemEvents": "6.0.0"
}
},
"System.Formats.Asn1": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -991,6 +1070,14 @@
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.Caching": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "E0e03kUp5X2k+UAoVl6efmI7uU7JRBWi5EIdlQ7cr0NpBGjHG4fWII35PgsBY9T4fJQ8E4QPsL0rKksU9gcL5A==",
"dependencies": {
"System.Configuration.ConfigurationManager": "6.0.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -1040,6 +1127,11 @@
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ=="
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1162,8 +1254,8 @@
},
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q=="
"resolved": "6.0.0",
"contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ=="
},
"System.Security.Cryptography.X509Certificates": {
"type": "Transitive",
@@ -1197,6 +1289,15 @@
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Permissions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==",
"dependencies": {
"System.Security.AccessControl": "6.0.0",
"System.Windows.Extensions": "6.0.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1256,6 +1357,14 @@
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
},
"System.Windows.Extensions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==",
"dependencies": {
"System.Drawing.Common": "6.0.0"
}
},
"velopack": {
"type": "Project",
"dependencies": {
@@ -1268,6 +1377,7 @@
"dependencies": {
"AWSSDK.S3": "[3.7.308.8, )",
"Azure.Storage.Blobs": "[12.20.0, )",
"Gitea.Net.API": "[1.0.0, )",
"Octokit": "[11.0.1, )",
"Velopack.Packaging": "[1.0.0, )"
}
@@ -1523,11 +1633,39 @@
"resolved": "2.17.3",
"contentHash": "BFKpnrs3yKH/jo1yewQdvLKMkEaxE6Wj3Lu5LHRNJfcAdOQ9YiY4dfQ5+5kz6ji1E/Xcxy5ta+qqKGA6KiVQMw=="
},
"Gitea.Net.API": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "5ZhKnsZfIjJ/aFeZFibi1VY8oOam0rQFf30A5gqxM5F3yoxpr1qHxeks10hvdgerGFMHSXgV8FDvtTHM4OA3Qw==",
"dependencies": {
"JsonSubTypes": "2.0.1",
"Microsoft.AspNetCore.SystemWebAdapters": "1.3.0",
"Newtonsoft.Json": "13.0.3",
"Polly": "8.4.0",
"RestSharp": "111.2.0"
}
},
"JsonSubTypes": {
"type": "Transitive",
"resolved": "2.0.1",
"contentHash": "1Po+Ypf0SjCeEKx5+C89Nb5OgTcqNvfS3uTI46MUM+KEp6Rq/M0h+vVsTUt/6DFRwZMTpsAJM4yJrZmEObVANA==",
"dependencies": {
"Newtonsoft.Json": "13.0.1"
}
},
"Markdig": {
"type": "Transitive",
"resolved": "0.37.0",
"contentHash": "biiu4MTPFjW55qw6v5Aphtj0MjDLJ14x8ndZwkJUHIeqvaSGKeqhLY7S7Vu/S3k7/c9KwhhnaCDP9hdFNUhcNA=="
},
"Microsoft.AspNetCore.SystemWebAdapters": {
"type": "Transitive",
"resolved": "1.3.0",
"contentHash": "1gomLUkk2dfZbznBAPb/HCZzlA+7QNKb08v5GzPh/tqhkUaKZHR8PHh0vmJlZGAj8vnvNLnzpfIwwCdq/9BHWQ==",
"dependencies": {
"System.Runtime.Caching": "6.0.0"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -1843,6 +1981,11 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.Win32.SystemEvents": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
@@ -1891,6 +2034,24 @@
"resolved": "11.0.1",
"contentHash": "fpwF/DxMJyGS+pIXDKQozx0wCIpOfG8VDr10ls+m9Gn9Lz8GslhhApxkKD9JCNO60HRUeMJsedsAS24gCjTD7Q=="
},
"Polly": {
"type": "Transitive",
"resolved": "8.4.0",
"contentHash": "z2EeUutuy49jBQyZ5s2FUuTCGx3GCzJ0cJ2HbjWwks94TsC6bKTtAHKBkMZOa/DyYRl5yIX7MshvMTWl1J6RNg==",
"dependencies": {
"Polly.Core": "8.4.0"
}
},
"Polly.Core": {
"type": "Transitive",
"resolved": "8.4.0",
"contentHash": "3AZxuP//pxOeBo9tQs7/tz4Z5TTbu4BYfjpaXZD0JYKJo98ngN9TMUz1nybh4k0ykWkMBpGZALV/AmVIE3ew7A=="
},
"RestSharp": {
"type": "Transitive",
"resolved": "111.2.0",
"contentHash": "OkWr6AGM0zirdkRpxVOxXMWx9OHEIWrDzrpx1XIx5KyvTcmtjJVsKBscVkYTcFerhj5w5Bny7boRIV4a0ENGaQ=="
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
@@ -2053,6 +2214,15 @@
"System.Threading.Tasks": "4.3.0"
}
},
"System.Configuration.ConfigurationManager": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==",
"dependencies": {
"System.Security.Cryptography.ProtectedData": "6.0.0",
"System.Security.Permissions": "6.0.0"
}
},
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -2083,6 +2253,14 @@
"System.Runtime": "4.3.0"
}
},
"System.Drawing.Common": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==",
"dependencies": {
"Microsoft.Win32.SystemEvents": "6.0.0"
}
},
"System.Formats.Asn1": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -2283,6 +2461,14 @@
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.Caching": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "E0e03kUp5X2k+UAoVl6efmI7uU7JRBWi5EIdlQ7cr0NpBGjHG4fWII35PgsBY9T4fJQ8E4QPsL0rKksU9gcL5A==",
"dependencies": {
"System.Configuration.ConfigurationManager": "6.0.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "5.0.0",
@@ -2332,6 +2518,11 @@
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ=="
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -2454,8 +2645,8 @@
},
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q=="
"resolved": "6.0.0",
"contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ=="
},
"System.Security.Cryptography.X509Certificates": {
"type": "Transitive",
@@ -2489,6 +2680,15 @@
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Permissions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==",
"dependencies": {
"System.Security.AccessControl": "6.0.0",
"System.Windows.Extensions": "6.0.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -2544,6 +2744,14 @@
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
},
"System.Windows.Extensions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==",
"dependencies": {
"System.Drawing.Common": "6.0.0"
}
},
"velopack": {
"type": "Project",
"dependencies": {
@@ -2556,6 +2764,7 @@
"dependencies": {
"AWSSDK.S3": "[3.7.308.8, )",
"Azure.Storage.Blobs": "[12.20.0, )",
"Gitea.Net.API": "[1.0.0, )",
"Octokit": "[11.0.1, )",
"Velopack.Packaging": "[1.0.0, )"
}

View File

@@ -28,6 +28,7 @@ namespace Velopack.Json
[JsonSerializable(typeof(List<GithubRelease>))]
[JsonSerializable(typeof(List<GitlabRelease>))]
[JsonSerializable(typeof(List<GiteaRelease>))]
[JsonSerializable(typeof(VelopackAssetFeed))]
[JsonSerializable(typeof(VelopackFlowReleaseAsset[]))]
#if NET8_0_OR_GREATER
@@ -60,6 +61,11 @@ namespace Velopack.Json
return JsonSerializer.Deserialize(json, Context.ListGithubRelease);
}
public static List<GiteaRelease>? DeserializeGiteaReleaseList(string json)
{
return JsonSerializer.Deserialize(json, Context.ListGiteaRelease);
}
public static List<GitlabRelease>? DeserializeGitlabReleaseList(string json)
{
return JsonSerializer.Deserialize(json, Context.ListGitlabRelease);
@@ -119,6 +125,11 @@ namespace Velopack.Json
return JsonConvert.DeserializeObject<List<GithubRelease>>(json, Options);
}
public static List<GiteaRelease>? DeserializeGiteaReleaseList(string json)
{
return JsonConvert.DeserializeObject<List<GiteaRelease>>(json, Options);
}
public static List<GitlabRelease>? DeserializeGitlabReleaseList(string json)
{
return JsonConvert.DeserializeObject<List<GitlabRelease>>(json, Options);

View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Velopack.Json;
namespace Velopack.Sources
{
/// <summary> Describes a Gitea release, including attached assets. </summary>
public class GiteaRelease
{
/// <summary> The name of this release. </summary>
[JsonPropertyName("name")]
public string? Name { get; set; }
/// <summary> True if this release is a prerelease. </summary>
[JsonPropertyName("prerelease")]
public bool Prerelease { get; set; }
/// <summary> The date which this release was published publicly. </summary>
[JsonPropertyName("published_at")]
public DateTime? PublishedAt { get; set; }
/// <summary> A list of assets (files) uploaded to this release. </summary>
[JsonPropertyName("assets")]
public GiteaReleaseAsset[] Assets { get; set; } = new GiteaReleaseAsset[0];
}
/// <summary> Describes a asset (file) uploaded to a Gitea release. </summary>
public class GiteaReleaseAsset
{
/// <summary>
/// The asset URL for this release asset. Requests to this URL will use API
/// quota and return JSON unless the 'Accept' header is "application/octet-stream".
/// </summary>
[JsonPropertyName("url")]
public string? Url { get; set; }
/// <summary>
/// The browser URL for this release asset. This does not use API quota,
/// however this URL only works for public repositories. If downloading
/// assets from a private repository, the <see cref="Url"/> property must
/// be used with an appropriate access token.
/// </summary>
[JsonPropertyName("browser_download_url")]
public string? BrowserDownloadUrl { get; set; }
/// <summary> The name of this release asset. </summary>
[JsonPropertyName("name")]
public string? Name { get; set; }
}
/// <summary>
/// Retrieves available releases from a Gitea repository.
/// </summary>
public class GiteaSource : GitBase<GiteaRelease>
{
/// <inheritdoc cref="GiteaSource" />
/// <param name="repoUrl">
/// The URL of the Gitea repository to download releases from
/// (e.g. https://Gitea.com/myuser/myrepo)
/// </param>
/// <param name="accessToken">
/// The Gitea access token to use with the request to download releases.
/// If left empty, the Gitea rate limit for unauthenticated requests allows
/// for up to 60 requests per hour, limited by IP address.
/// </param>
/// <param name="prerelease">
/// If true, pre-releases will be also be searched / downloaded. If false, only
/// stable releases will be considered.
/// </param>
/// <param name="downloader">
/// The file downloader used to perform HTTP requests.
/// </param>
public GiteaSource(string repoUrl, string? accessToken, bool prerelease, IFileDownloader? downloader = null)
: base(repoUrl, accessToken, prerelease, downloader)
{
}
/// <summary>
/// The authorization token used in the request.
/// Overwrite it to token
/// </summary>
protected override string? Authorization => string.IsNullOrWhiteSpace(AccessToken) ? null : "token " + AccessToken;
/// <inheritdoc />
protected override async Task<GiteaRelease[]> GetReleases(bool includePrereleases)
{
// https://gitea.com/api/swagger#/repository/repoListReleases
// https://docs.gitea.com/api/1.22/#tag/repository/operation/repoListReleases
const int perPage = 10;
const int page = 1;
var releasesPath = $"repos{RepoUri.AbsolutePath}/releases?limit={perPage}&page={page}&draft=false";
var baseUri = GetApiBaseUrl(RepoUri);
var getReleasesUri = new Uri(baseUri, releasesPath);
var response = await Downloader.DownloadString(getReleasesUri.ToString(), Authorization, "application/json").ConfigureAwait(false);
var releases = CompiledJson.DeserializeGiteaReleaseList(response);
if (releases == null) return new GiteaRelease[0];
return releases.OrderByDescending(d => d.PublishedAt).Where(x => includePrereleases || !x.Prerelease).ToArray();
}
/// <inheritdoc />
protected override string GetAssetUrlFromName(GiteaRelease release, string assetName)
{
if (release.Assets == null || release.Assets.Count() == 0) {
throw new ArgumentException($"No assets found in Gitea Release '{release.Name}'.");
}
IEnumerable<GiteaReleaseAsset> allReleasesFiles = release.Assets.Where(a => a.Name?.Equals(assetName, StringComparison.InvariantCultureIgnoreCase) == true);
if (allReleasesFiles == null || allReleasesFiles.Count() == 0) {
throw new ArgumentException($"Could not find asset called '{assetName}' in Gitea Release '{release.Name}'.");
}
var asset = allReleasesFiles.First();
if (asset.BrowserDownloadUrl != null) {
return asset.BrowserDownloadUrl;
} else {
throw new ArgumentException("Could not find a valid asset url for the specified asset.");
}
}
/// <summary>
/// Given a repository URL (e.g. https://Gitea.com/myuser/myrepo) this function
/// returns the API base for performing requests. (eg. "https://api.Gitea.com/"
/// or http://internal.Gitea.server.local/api/v1)
/// </summary>
/// <param name="repoUrl"></param>
/// <returns></returns>
protected virtual Uri GetApiBaseUrl(Uri repoUrl)
{
Uri baseAddress = new Uri(string.Format("{0}{1}{2}/api/v1/", repoUrl.Scheme, Uri.SchemeDelimiter, repoUrl.Host));
// above ^^ notice the end slashes for the baseAddress, explained here: http://stackoverflow.com/a/23438417/162694
return baseAddress;
}
}
}

View File

@@ -8,15 +8,6 @@
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net462": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
@@ -50,11 +41,6 @@
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.NETFramework.ReferenceAssemblies.net462": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
@@ -159,9 +145,9 @@
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.1, )",
"resolved": "8.0.1",
"contentHash": "ADdJXuKNjwZDfBmybMnpvwd5CK3gp92WkWqqeQhW4W+q4MO3Qaa9QyW2DcFLAvCDMcCWxT5hRXqGdv13oon7nA=="
"requested": "[8.0.6, )",
"resolved": "8.0.6",
"contentHash": "E+lDylsTeP4ZiDmnEkiJ5wobnGaIJzFhOgZppznJCb69UZgbh6G3cfv1pnLDLLBx6JAgl0kAlnINDeT3uCuczQ=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",

View File

@@ -389,7 +389,6 @@ public class UpdateManagerTests
Assert.True(new SemanticVersion(1, 0, 1) == info.TargetFullRelease.Version);
Assert.Equal(0, info.DeltasToTarget.Count());
}
[Fact(Skip = "Consumes API Quota")]
public void CheckGithubWithNonExistingChannel()
{
@@ -402,7 +401,20 @@ public class UpdateManagerTests
var um = new UpdateManager(source, opt, logger, locator);
Assert.Throws<ArgumentException>(() => um.CheckForUpdates());
}
[Fact(Skip = "Consumes API Quota")]
public void CheckGitea()
{
// https://github.com/caesay/SquirrelCustomLauncherTestApp
using var logger = _output.BuildLoggerFor<UpdateManagerTests>();
using var _1 = Utility.GetTempDirectory(out var tempPath);
var locator = new TestVelopackLocator("MyCoolApp", "1.0.0", tempPath, logger);
var source = new GiteaSource("https://gitea.com/remco1271/VeloPackTest", null, false);
var um = new UpdateManager(source, null, logger, locator);
var info = um.CheckForUpdates();
Assert.NotNull(info);
Assert.True(new SemanticVersion(1, 0, 1) == info.TargetFullRelease.Version);
Assert.Equal(0, info.DeltasToTarget.Count());
}
[Fact]
public void CheckFromEmptyFileSource()
{