From 5aaa8f61c46f1d7c7545947aecb28809f0414e4b Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Wed, 27 Mar 2024 21:58:47 +0000 Subject: [PATCH] Fix azure tests --- src/Velopack.Deployment/AzureRepository.cs | 27 ++++++++++++++----- src/Velopack.Deployment/S3Repository.cs | 14 ++++++---- src/Velopack.Deployment/_ObjectRepository.cs | 21 +++++---------- .../Commands/Deployment/AzureBaseCommand.cs | 19 ++++++++----- src/Velopack/packages.lock.json | 6 ++++- .../AzureDeploymentTests.cs | 23 ++++++++-------- 6 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/Velopack.Deployment/AzureRepository.cs b/src/Velopack.Deployment/AzureRepository.cs index 4a3053c3..e6163991 100644 --- a/src/Velopack.Deployment/AzureRepository.cs +++ b/src/Velopack.Deployment/AzureRepository.cs @@ -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 GetObjectBytes(BlobServiceClient client, string container, string key) { return await RetryAsyncRet(async () => { - 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(); + 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}..."); } diff --git a/src/Velopack.Deployment/S3Repository.cs b/src/Velopack.Deployment/S3Repository.cs index 5f35af7f..0e1fee00 100644 --- a/src/Velopack.Deployment/S3Repository.cs +++ b/src/Velopack.Deployment/S3Repository.cs @@ -57,12 +57,16 @@ public class S3Repository : ObjectRepository GetObjectBytes(AmazonS3Client client, string container, string key) { return await RetryAsyncRet(async () => { - var ms = new MemoryStream(); - using (var obj = await client.GetObjectAsync(container, key)) - using (var stream = obj.ResponseStream) { - await stream.CopyToAsync(ms); + 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; } - return ms.ToArray(); }, $"Downloading {key}..."); } diff --git a/src/Velopack.Deployment/_ObjectRepository.cs b/src/Velopack.Deployment/_ObjectRepository.cs index b57976be..5b400e18 100644 --- a/src/Velopack.Deployment/_ObjectRepository.cs +++ b/src/Velopack.Deployment/_ObjectRepository.cs @@ -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 : DownRepository, IRepositoryCanUpload where TDown : RepositoryOptions, IObjectDownloadOptions where TUp : IObjectUploadOptions, TDown @@ -45,14 +40,11 @@ public abstract class ObjectRepository : DownRepository { - try { - var bytes = await GetObjectBytes(client, options.ContainerName, releasesName); - return VelopackAssetFeed.FromJson(Encoding.UTF8.GetString(bytes)); - } catch (ObjectNotFoundException) { - return new VelopackAssetFeed(); - } - }, $"Fetching {releasesName}..."); + var bytes = await GetObjectBytes(client, options.ContainerName, releasesName); + if (bytes == null || bytes.Length == 0) { + return new VelopackAssetFeed(); + } + return VelopackAssetFeed.FromJson(Encoding.UTF8.GetString(bytes)); } public async Task UploadMissingAssetsAsync(TUp options) @@ -112,8 +104,7 @@ public abstract class ObjectRepository : DownRepository 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); } } diff --git a/src/Velopack.Vpk/Commands/Deployment/AzureBaseCommand.cs b/src/Velopack.Vpk/Commands/Deployment/AzureBaseCommand.cs index 137591a0..c3dc92c7 100644 --- a/src/Velopack.Vpk/Commands/Deployment/AzureBaseCommand.cs +++ b/src/Velopack.Vpk/Commands/Deployment/AzureBaseCommand.cs @@ -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((v) => Key = v, "--key") + var key = AddOption((v) => Key = v, "--key") .SetDescription("Account secret key") - .SetArgumentHelpName("KEY") - .SetRequired(); + .SetArgumentHelpName("KEY"); + + var sas = AddOption((v) => SasToken = v, "--sas") + .SetDescription("Shared access signature token (not the url)") + .SetArgumentHelpName("TOKEN"); AddOption((v) => ContainerName = v, "--container") .SetDescription("Azure container name") @@ -29,9 +34,11 @@ public class AzureBaseCommand : OutputCommand .SetRequired(); AddOption((v) => Endpoint = v.ToAbsoluteOrNull(), "--endpoint") - .SetDescription("Service url (eg. https://.blob.core.windows.net)") + .SetDescription("Service url (eg. https://.blob.core.windows.net)") .SetArgumentHelpName("URL") - .MustBeValidHttpUri() - .SetRequired(); + .MustBeValidHttpUri(); + + this.AtLeastOneRequired(sas, key); + this.AreMutuallyExclusive(sas, key); } } diff --git a/src/Velopack/packages.lock.json b/src/Velopack/packages.lock.json index 3cc2ecd3..d267f317 100644 --- a/src/Velopack/packages.lock.json +++ b/src/Velopack/packages.lock.json @@ -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": {} } } \ No newline at end of file diff --git a/test/Velopack.Packaging.Tests/AzureDeploymentTests.cs b/test/Velopack.Packaging.Tests/AzureDeploymentTests.cs index b0b2b077..c2d9a71a 100644 --- a/test/Velopack.Packaging.Tests/AzureDeploymentTests.cs +++ b/test/Velopack.Packaging.Tests/AzureDeploymentTests.cs @@ -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(); 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.");