diff --git a/source/ios/release/AdaptiveCards.framework.zip b/source/ios/release/AdaptiveCards.framework.zip deleted file mode 100644 index 47a2e6765e..0000000000 Binary files a/source/ios/release/AdaptiveCards.framework.zip and /dev/null differ diff --git a/source/ios/release/binary/AdaptiveCards.framework.zip b/source/ios/release/binary/AdaptiveCards.framework.zip deleted file mode 100644 index a97774557d..0000000000 Binary files a/source/ios/release/binary/AdaptiveCards.framework.zip and /dev/null differ diff --git a/source/ios/release/AdaptiveCards.podspec b/source/ios/tools/AdaptiveCards.podspec similarity index 100% rename from source/ios/release/AdaptiveCards.podspec rename to source/ios/tools/AdaptiveCards.podspec diff --git a/source/ios/tools/IOSFeed/IOSFeed.cs b/source/ios/tools/IOSFeed/IOSFeed.cs new file mode 100644 index 0000000000..d5060001e8 --- /dev/null +++ b/source/ios/tools/IOSFeed/IOSFeed.cs @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Storage; +using Microsoft.Azure.Storage.Blob; + +namespace AdaptiveCards.Tools.IOSFeed +{ + public static class Constants + { + public const string ConnectionStringPath = "source/ios/tools/IOSFeed/ConnectString.txt"; + public const string ContainerId = "adaptivecardsiosblobs"; + public const string FrameworkPath = "source/ios/AdaptiveCards/AdaptiveCards"; + public const string FrameworkName = "AdaptiveCards.framework.zip"; + public const string PodspecPath = "./source/ios/tools/"; + public const string TargetPodspecPath = "./source/ios/"; + public const string PodspecName = "AdaptiveCards.podspec"; + } + + /// + /// IOSFeed picks up ios artifact, sends to the Azure storage + /// and updates podspec for pod publication + /// + class IOSFeed + { + public static void Main() + { + try + { + // Run the examples asynchronously, wait for the results before proceeding + ProcessAsync().GetAwaiter().GetResult(); + } + catch (Exception ex) + { + Debug.WriteLine("Uploading taks failed with {0} exception", ex); + } + } + + private static async Task ProcessAsync() + { + string storageConnectionString; + + FileInfo fi = new FileInfo(Constants.ConnectionStringPath); + if (!fi.Exists) + { + throw new InvalidOperationException(Path.GetFileName(Constants.ConnectionStringPath) + " does not exist"); + } + + using (StreamReader sr = File.OpenText(Constants.ConnectionStringPath)) + { + storageConnectionString = sr.ReadToEnd(); + } + + // Check whether the connection string can be parsed. + if (!CloudStorageAccount.TryParse(storageConnectionString, out CloudStorageAccount storageAccount)) + { + throw new InvalidOperationException(Path.GetFileName(Constants.ConnectionStringPath) + " does not have valid connection string"); + } + else + { + // If the connection string is valid, proceed with operations against Blob + // storage here. + // Create the CloudBlobClient that represents the + // Blob storage endpoint for the storage account. + CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient(); + + CloudBlobContainer cloudBlobContainer = + cloudBlobClient.GetContainerReference(Constants.ContainerId); + await cloudBlobContainer.CreateIfNotExistsAsync(); + + // Set the permissions so the blobs are public. + BlobContainerPermissions permissions = new BlobContainerPermissions + { + PublicAccess = BlobContainerPublicAccessType.Blob + }; + + await cloudBlobContainer.SetPermissionsAsync(permissions); + + var sourceFile = Path.Combine(Constants.FrameworkPath, Constants.FrameworkName); + var blobGuid = Guid.NewGuid().ToString(); + var cloudFileName = blobGuid + Constants.FrameworkName; + + CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(cloudFileName); + + try + { + await cloudBlockBlob.UploadFromFileAsync(sourceFile); + + BlobContinuationToken blobContinuationToken = null; + do + { + var results = await cloudBlobContainer.ListBlobsSegmentedAsync(null, blobContinuationToken); + // Get the value of the continuation token returned by the listing call. + blobContinuationToken = results.ContinuationToken; + foreach (IListBlobItem item in results.Results) + { + var uriString = item.Uri.ToString(); + if (uriString.Contains(blobGuid)) + { + UpdatePodSpec(uriString); + } + } + } while (blobContinuationToken != null); + } + finally + { + // when exception happens, nothing is permanent except blob, so we delete it here, and allow the rest of the exception + // to follow the chain + cloudBlockBlob.DeleteIfExists(); + } + } + } + + private static void UpdatePodSpec(string uri) + { + var sourceFile = Path.Combine(Constants.PodspecPath, Constants.PodspecName); + var targetFile = Path.Combine(Constants.TargetPodspecPath, Constants.PodspecName); + + FileInfo fi = new FileInfo(sourceFile); + if (!fi.Exists) + { + throw new FileNotFoundException("missing file: " + Constants.PodspecName); + } + + // Open the stream and read it back. + using (StreamReader sr = File.OpenText(sourceFile)) + { + string s; + StringBuilder output = new StringBuilder(); + while ((s = sr.ReadLine()) != null) + { + if (s.Length != 0) + { + var splits = s.Split('='); + StringBuilder stringBuilderForEditedString = new StringBuilder(); + if (splits.Length > 0) + { + if (splits[0].Contains("spec.source", StringComparison.OrdinalIgnoreCase)) + { + stringBuilderForEditedString.Append(splits[0]).Append("= { :http => " + "'" + uri + "' }"); + } + else if (splits[0].Contains("spec.version", StringComparison.OrdinalIgnoreCase)) + { + var adaptiveVersion = Environment.GetEnvironmentVariable("ADCVERSION"); + stringBuilderForEditedString.Append(splits[0]).Append("= '" + adaptiveVersion + "'"); + } + else + { + stringBuilderForEditedString.Append(s); + } + } + + output.Append(stringBuilderForEditedString + "\n"); + } else + { + output.Append("\n"); + } + } + + File.WriteAllText(targetFile, output.ToString()); + } + } + } +} diff --git a/source/ios/tools/IOSFeed/IOSFeed.csproj b/source/ios/tools/IOSFeed/IOSFeed.csproj new file mode 100644 index 0000000000..21ff1029e7 --- /dev/null +++ b/source/ios/tools/IOSFeed/IOSFeed.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp2.1 + AdaptiveCards.Tools.IOSFeed + + + + + + + diff --git a/source/ios/tools/IOSFeed/IOSFeed.sln b/source/ios/tools/IOSFeed/IOSFeed.sln new file mode 100644 index 0000000000..b94e7a55ac --- /dev/null +++ b/source/ios/tools/IOSFeed/IOSFeed.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.705 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IOSFeed", "IOSFeed.csproj", "{953218C2-8A1A-44E3-96C6-DFF08D977D7C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {953218C2-8A1A-44E3-96C6-DFF08D977D7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {953218C2-8A1A-44E3-96C6-DFF08D977D7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {953218C2-8A1A-44E3-96C6-DFF08D977D7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {953218C2-8A1A-44E3-96C6-DFF08D977D7C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {060131CB-8F54-484E-BCDE-6AF526BB9762} + EndGlobalSection +EndGlobal