Fix azure tests

This commit is contained in:
Caelan Sayler
2024-03-27 21:58:47 +00:00
parent 2acfab1e8c
commit 5aaa8f61c4
6 changed files with 65 additions and 45 deletions

View File

@@ -13,6 +13,8 @@ public class AzureDownloadOptions : RepositoryOptions, IObjectDownloadOptions
public string Endpoint { get; set; }
public string ContainerName { get; set; }
public string SasToken { get; set; }
}
public class AzureUploadOptions : AzureDownloadOptions, IObjectUploadOptions
@@ -28,7 +30,16 @@ public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploa
protected override BlobServiceClient CreateClient(AzureDownloadOptions options)
{
return new BlobServiceClient(new Uri(options.Endpoint), new StorageSharedKeyCredential(options.Account, options.Key));
var serviceUrl = options.Endpoint ?? "https://" + options.Account + ".blob.core.windows.net";
if (options.Endpoint == null) {
Log.Info($"Endpoint not specified, default to: {serviceUrl}");
}
if (!String.IsNullOrEmpty(options.SasToken)) {
return new BlobServiceClient(new Uri(serviceUrl), new Azure.AzureSasCredential(options.SasToken));
}
return new BlobServiceClient(new Uri(serviceUrl), new StorageSharedKeyCredential(options.Account, options.Key));
}
protected override async Task DeleteObject(BlobServiceClient client, string container, string key)
@@ -42,11 +53,15 @@ public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploa
protected override async Task<byte[]> GetObjectBytes(BlobServiceClient client, string container, string key)
{
return await RetryAsyncRet(async () => {
try {
var containerClient = client.GetBlobContainerClient(container);
var obj = containerClient.GetBlobClient(key);
var ms = new MemoryStream();
using var response = await obj.DownloadToAsync(ms, CancellationToken.None);
return ms.ToArray();
} catch (Azure.RequestFailedException ex) when (ex.Status == 404) {
return null;
}
}, $"Downloading {key}...");
}

View File

@@ -57,12 +57,16 @@ public class S3Repository : ObjectRepository<S3DownloadOptions, S3UploadOptions,
protected override async Task<byte[]> GetObjectBytes(AmazonS3Client client, string container, string key)
{
return await RetryAsyncRet(async () => {
try {
var ms = new MemoryStream();
using (var obj = await client.GetObjectAsync(container, key))
using (var stream = obj.ResponseStream) {
await stream.CopyToAsync(ms);
}
return ms.ToArray();
} catch (AmazonS3Exception ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) {
return null;
}
}, $"Downloading {key}...");
}

View File

@@ -14,11 +14,6 @@ public interface IObjectDownloadOptions
string ContainerName { get; set; }
}
public class ObjectNotFoundException : Exception
{
public ObjectNotFoundException(string message) : base(message) { }
}
public abstract class ObjectRepository<TDown, TUp, TClient> : DownRepository<TDown>, IRepositoryCanUpload<TUp>
where TDown : RepositoryOptions, IObjectDownloadOptions
where TUp : IObjectUploadOptions, TDown
@@ -45,14 +40,11 @@ public abstract class ObjectRepository<TDown, TUp, TClient> : DownRepository<TDo
{
var releasesName = Utility.GetVeloReleaseIndexName(options.Channel);
var client = CreateClient(options);
return await RetryAsyncRet(async () => {
try {
var bytes = await GetObjectBytes(client, options.ContainerName, releasesName);
return VelopackAssetFeed.FromJson(Encoding.UTF8.GetString(bytes));
} catch (ObjectNotFoundException) {
if (bytes == null || bytes.Length == 0) {
return new VelopackAssetFeed();
}
}, $"Fetching {releasesName}...");
return VelopackAssetFeed.FromJson(Encoding.UTF8.GetString(bytes));
}
public async Task UploadMissingAssetsAsync(TUp options)
@@ -112,8 +104,7 @@ public abstract class ObjectRepository<TDown, TUp, TClient> : DownRepository<TDo
if (toDelete.Length > 0) {
Log.Info($"Retention policy about to delete {toDelete.Length} releases...");
foreach (var del in toDelete) {
//var metadata = await client.GetObjectMetadataAsync(options.Bucket, del.FileName);
await RetryAsync(() => DeleteObject(client, options.ContainerName, del.FileName), "Deleting " + del.FileName);
await DeleteObject(client, options.ContainerName, del.FileName);
}
}

View File

@@ -10,6 +10,8 @@ public class AzureBaseCommand : OutputCommand
public string ContainerName { get; private set; }
public string SasToken { get; private set; }
protected AzureBaseCommand(string name, string description)
: base(name, description)
{
@@ -18,10 +20,13 @@ public class AzureBaseCommand : OutputCommand
.SetArgumentHelpName("ACCOUNT")
.SetRequired();
AddOption<string>((v) => Key = v, "--key")
var key = AddOption<string>((v) => Key = v, "--key")
.SetDescription("Account secret key")
.SetArgumentHelpName("KEY")
.SetRequired();
.SetArgumentHelpName("KEY");
var sas = AddOption<string>((v) => SasToken = v, "--sas")
.SetDescription("Shared access signature token (not the url)")
.SetArgumentHelpName("TOKEN");
AddOption<string>((v) => ContainerName = v, "--container")
.SetDescription("Azure container name")
@@ -29,9 +34,11 @@ public class AzureBaseCommand : OutputCommand
.SetRequired();
AddOption<Uri>((v) => Endpoint = v.ToAbsoluteOrNull(), "--endpoint")
.SetDescription("Service url (eg. https://<storage-account-name>.blob.core.windows.net)")
.SetDescription("Service url (eg. https://<account-name>.blob.core.windows.net)")
.SetArgumentHelpName("URL")
.MustBeValidHttpUri()
.SetRequired();
.MustBeValidHttpUri();
this.AtLeastOneRequired(sas, key);
this.AreMutuallyExclusive(sas, key);
}
}

View File

@@ -61,6 +61,7 @@
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
},
".NETFramework,Version=v4.6.2/win-x64": {},
".NETFramework,Version=v4.8": {
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Direct",
@@ -107,6 +108,7 @@
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
},
".NETFramework,Version=v4.8/win-x64": {},
"net6.0": {
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Direct",
@@ -147,6 +149,7 @@
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
},
"net6.0/win-x64": {},
"net8.0": {
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Direct",
@@ -194,6 +197,7 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
}
},
"net8.0/win-x64": {}
}
}

View File

@@ -6,10 +6,10 @@ namespace Velopack.Packaging.Tests;
public class AzureDeploymentTests
{
public readonly static string B2_KEYID = "xstg";
public readonly static string B2_SECRET = Environment.GetEnvironmentVariable("VELOPACK_AZ_TEST_TOKEN");
public readonly static string B2_BUCKET = "test-releases";
public readonly static string B2_ENDPOINT = "xstg.blob.core.windows.net";
public readonly static string AZ_ACCOUNT = "velopacktest";
public readonly static string AZ_KEY = Environment.GetEnvironmentVariable("VELOPACK_AZ_TEST_TOKEN");
public readonly static string AZ_CONTAINER = "test1";
public readonly static string AZ_ENDPOINT = "velopacktest.blob.core.windows.net";
private readonly ITestOutputHelper _output;
@@ -21,7 +21,7 @@ public class AzureDeploymentTests
[SkippableFact]
public void CanDeployToAzure()
{
Skip.If(String.IsNullOrWhiteSpace(B2_SECRET), "VELOPACK_AZ_TEST_TOKEN is not set.");
Skip.If(String.IsNullOrWhiteSpace(AZ_KEY), "VELOPACK_AZ_TEST_TOKEN is not set.");
using var logger = _output.BuildLoggerFor<S3DeploymentTests>();
using var _1 = Utility.GetTempDirectory(out var releaseDir);
@@ -30,7 +30,7 @@ public class AzureDeploymentTests
: "ci-" + VelopackRuntimeInfo.SystemOs.GetOsShortName();
// get latest version, and increment patch by one
var updateUrl = $"https://{B2_ENDPOINT}/{B2_BUCKET}";
var updateUrl = $"https://{AZ_ENDPOINT}/{AZ_CONTAINER}";
var source = new SimpleWebSource(updateUrl);
VelopackAssetFeed feed = new VelopackAssetFeed();
try {
@@ -47,18 +47,17 @@ public class AzureDeploymentTests
var repo = new AzureRepository(logger);
var options = new AzureUploadOptions {
ReleaseDir = new DirectoryInfo(releaseDir),
ContainerName = B2_BUCKET,
ContainerName = AZ_CONTAINER,
Channel = channel,
Endpoint = "https://" + B2_ENDPOINT,
Account = B2_KEYID,
Key = B2_SECRET,
Account = AZ_ACCOUNT,
Key = AZ_KEY,
KeepMaxReleases = 4,
};
// download latest version and create delta
repo.DownloadLatestFullPackageAsync(options).GetAwaiterResult();
var id = "B2TestApp";
TestApp.PackTestApp(id, newVer.ToFullString(), $"b2-{DateTime.UtcNow.ToLongDateString()}", releaseDir, logger, channel: channel);
var id = "AZTestApp";
TestApp.PackTestApp(id, newVer.ToFullString(), $"az-{DateTime.UtcNow.ToLongDateString()}", releaseDir, logger, channel: channel);
if (latest != null) {
// check delta was created
Assert.True(Directory.EnumerateFiles(releaseDir, "*-delta.nupkg").Any(), "No delta package was created.");