static bool MaybeOverrideLockToken([NotNull] SnapApps snapApps, [NotNull] ILog logger, [NotNull] string applicationId, string userInputLockToken, string optionName = "--lock-token") { if (snapApps == null) { throw new ArgumentNullException(nameof(snapApps)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (!string.IsNullOrWhiteSpace(applicationId)) { var lockTokenEnvironmentVariableName = $"SNAPX_{applicationId.ToUpperInvariant()}_LOCK_TOKEN"; var lockTokenEnvironmentVariableValue = Environment.GetEnvironmentVariable(lockTokenEnvironmentVariableName); if (!string.IsNullOrWhiteSpace(lockTokenEnvironmentVariableValue)) { snapApps.Generic.Token = lockTokenEnvironmentVariableValue; logger.Warn($"Lock token updated because of environment variable with name: {lockTokenEnvironmentVariableName}."); return(true); } } if (!string.IsNullOrWhiteSpace(userInputLockToken)) { snapApps.Generic.Token = userInputLockToken; logger.Warn($"Lock token updated because '{optionName}' option."); return(true); } return(false); }
internal static INuGetPackageSources BuildNugetSources([NotNull] this SnapApps snapApps, INuGetPackageSources nuGetPackageSources) { var allPackageSources = snapApps.Channels .SelectMany(x => { var packageSources = new List <PackageSource>(); var pushFeed = nuGetPackageSources.Items.SingleOrDefault(packageSource => packageSource.Name == x.PushFeed.Name); if (pushFeed != null) { packageSources.Add(pushFeed); } if (x.UpdateFeed is SnapsNugetFeed snapsNugetFeed) { var updateFeed = nuGetPackageSources.Items.SingleOrDefault(packageSource => packageSource.Name == snapsNugetFeed.Name); if (updateFeed != null) { packageSources.Add(updateFeed); } } return(packageSources); }) .DistinctBy(x => x.Name) .ToList(); return(!allPackageSources.Any() ? NuGetPackageSources.Empty : new NuGetPackageSources(nuGetPackageSources.Settings, allPackageSources)); }
public string ToSnapAppsYamlString([NotNull] SnapApps snapApps) { if (snapApps == null) { throw new ArgumentNullException(nameof(snapApps)); } return(YamlSerializerSnapApps.Serialize(snapApps)); }
internal static IEnumerable <SnapApp> BuildSnapApps([NotNull] this SnapApps snapApps, [NotNull] INuGetPackageSources nuGetPackageSources, [NotNull] ISnapFilesystem snapFilesystem) { foreach (var snapsApp in snapApps.Apps) { foreach (var snapsTarget in snapsApp.Targets) { yield return(snapApps.BuildSnapApp(snapsApp.Id, snapsTarget.Rid, nuGetPackageSources, snapFilesystem)); } } }
void AssertSnapApps(SnapApps snapAppsBefore, SnapApps snapAppsAfter, INuGetPackageSources nuGetPackageSources) { Assert.NotNull(snapAppsBefore); Assert.NotNull(snapAppsAfter); Assert.Equal(snapAppsBefore.Channels.Count, snapAppsAfter.Channels.Count); Assert.Equal(snapAppsBefore.Apps.Count, snapAppsAfter.Apps.Count); Assert.NotNull(snapAppsBefore.Generic); Assert.NotNull(snapAppsAfter.Generic); // Generic. Assert.Equal(snapAppsBefore.Generic.Nuspecs, snapAppsAfter.Generic.Nuspecs); Assert.Equal(snapAppsBefore.Generic.Packages, snapAppsAfter.Generic.Packages); // Channels. for (var index = 0; index < snapAppsBefore.Channels.Count; index++) { var lhsChannel = snapAppsBefore.Channels[index]; var rhsChannel = snapAppsAfter.Channels[index]; Assert.Equal(lhsChannel.Name, rhsChannel.Name); Assert.Equal(lhsChannel.PushFeed.Name, rhsChannel.PushFeed.Name); switch (lhsChannel.UpdateFeed) { case SnapsNugetFeed lhsSnapsNugetFeed: var rhsSnapsNugetFeed = (SnapsNugetFeed)rhsChannel.UpdateFeed; Assert.Equal(lhsSnapsNugetFeed.Name, rhsSnapsNugetFeed.Name); break; case SnapsHttpFeed lhsSnapsHttpFeed: var rhsSnapsHttpFeed = (SnapsHttpFeed)rhsChannel.UpdateFeed; Assert.Equal(lhsSnapsHttpFeed.Source, rhsSnapsHttpFeed.Source); break; default: throw new NotSupportedException($"Unsupported feed type: {lhsChannel.UpdateFeed?.GetType().Name}"); } } // Apps. var snapAppBefore = snapAppsBefore.BuildSnapApps(nuGetPackageSources, _snapFilesystem).ToList(); var snapAppAfter = snapAppsAfter.BuildSnapApps(nuGetPackageSources, _snapFilesystem).ToList(); Assert.Equal(snapAppBefore.Count, snapAppAfter.Count); for (var i = 0; i < snapAppsBefore.Apps.Count; i++) { AssertSnapApp(snapAppBefore[i], snapAppAfter[i]); } }
public async Task TestBuildSnapApp_Ignore_Non_Existant_Feeds() { await using var nugetTempDirectory = new DisposableDirectory(_baseFixture.WorkingDirectory, _fileSystem); var testChannel = new SnapChannel { Name = "test", PushFeed = new SnapNugetFeed { Name = Guid.NewGuid().ToString("N") }, UpdateFeed = new SnapNugetFeed { Name = Guid.NewGuid().ToString("N") }, Current = true }; var snapAppBefore = new SnapApp { Id = "demoapp", SuperVisorId = Guid.NewGuid().ToString(), Version = new SemanticVersion(1, 0, 0), Channels = new List <SnapChannel> { testChannel }, Target = new SnapTarget { Os = OSPlatform.Windows, Framework = "netcoreapp2.1", Rid = "win-x64", PersistentAssets = new List <string> { "subdirectory", "myjsonfile.json" } } }; var snapApps = new SnapApps(snapAppBefore); var snapAppAfter = snapApps.BuildSnapApp(snapAppBefore.Id, snapAppBefore.Target.Rid, snapAppBefore.BuildNugetSources(nugetTempDirectory), _fileSystem, false, false); Assert.NotNull(snapAppAfter); Assert.Single(snapAppAfter.Channels.Select(x => x.UpdateFeed is {}));
public async Task TestBuildSnapApp_Throws_If_Multiple_Nuget_Push_Feed_Names() { await using var nugetTempDirectory = new DisposableDirectory(_baseFixture.WorkingDirectory, _fileSystem); var nugetOrgFeed = new SnapNugetFeed { Name = "nuget.org", Source = new Uri(NuGetConstants.V3FeedUrl), ProtocolVersion = NuGetProtocolVersion.V3, Username = "******", Password = "******", ApiKey = "myapikey" }; var nugetOrgFeed2 = new SnapNugetFeed { Name = "nuget2.org", Source = new Uri(NuGetConstants.V3FeedUrl), ProtocolVersion = NuGetProtocolVersion.V3, Username = "******", Password = "******", ApiKey = "myapikey" }; var testChannel = new SnapChannel { Name = "test", PushFeed = nugetOrgFeed, UpdateFeed = nugetOrgFeed, Current = true }; var stagingChannel = new SnapChannel { Name = "staging", PushFeed = nugetOrgFeed2, UpdateFeed = nugetOrgFeed2 }; var productionChannel = new SnapChannel { Name = "production", PushFeed = nugetOrgFeed, UpdateFeed = nugetOrgFeed }; var snapAppBefore = new SnapApp { Id = "demoapp", SuperVisorId = Guid.NewGuid().ToString(), Version = new SemanticVersion(1, 0, 0), Channels = new List <SnapChannel> { testChannel, stagingChannel, productionChannel }, Target = new SnapTarget { Os = OSPlatform.Windows, Framework = "netcoreapp2.1", Rid = "win-x64", Shortcuts = new List <SnapShortcutLocation> { SnapShortcutLocation.Desktop, SnapShortcutLocation.Startup }, PersistentAssets = new List <string> { "subdirectory", "myjsonfile.json" } } }; var snapApps = new SnapApps(snapAppBefore); var ex = Assert.Throws <Exception>(() => snapApps.BuildSnapApp(snapAppBefore.Id, snapAppBefore.Target.Rid, snapAppBefore.BuildNugetSources(nugetTempDirectory), _fileSystem)); Assert.Equal($"Multiple nuget push feeds is not supported: nuget.org,nuget2.org. Application id: {snapAppBefore.Id}", ex.Message); }
public async Task TestBuildSnapApp() { await using var nugetTempDirectory = new DisposableDirectory(_baseFixture.WorkingDirectory, _fileSystem); var nugetOrgFeed = new SnapNugetFeed { Name = "nuget.org", Source = new Uri(NuGetConstants.V3FeedUrl), ProtocolVersion = NuGetProtocolVersion.V3, Username = "******", Password = "******", ApiKey = "myapikey" }; var updateFeedHttp = new SnapHttpFeed { Source = new Uri("https://mydynamicupdatefeed.com") }; var testChannel = new SnapChannel { Name = "test", PushFeed = nugetOrgFeed, UpdateFeed = nugetOrgFeed, Current = true }; var stagingChannel = new SnapChannel { Name = "staging", PushFeed = nugetOrgFeed, UpdateFeed = updateFeedHttp }; var productionChannel = new SnapChannel { Name = "production", PushFeed = nugetOrgFeed, UpdateFeed = nugetOrgFeed }; var snapAppBefore = new SnapApp { Id = "demoapp", MainExe = "demoapp", InstallDirectoryName = "demoapp", SuperVisorId = Guid.NewGuid().ToString(), Version = new SemanticVersion(1, 0, 0), Channels = new List <SnapChannel> { testChannel, stagingChannel, productionChannel }, Target = new SnapTarget { Os = OSPlatform.Windows, Framework = "netcoreapp2.1", Rid = "win-x64", Shortcuts = new List <SnapShortcutLocation> { SnapShortcutLocation.Desktop, SnapShortcutLocation.Startup }, PersistentAssets = new List <string> { "subdirectory", "myjsonfile.json" } } }; var snapApps = new SnapApps(snapAppBefore); var snapAppAfter = snapApps.BuildSnapApp(snapAppBefore.Id, snapAppBefore.Target.Rid, snapAppBefore.BuildNugetSources(nugetTempDirectory), _fileSystem); snapAppAfter.Version = snapAppBefore.Version.BumpMajor(); // Generic Assert.Equal(snapAppBefore.Id, snapAppAfter.Id); Assert.Equal(snapAppBefore.InstallDirectoryName, snapAppAfter.InstallDirectoryName); Assert.Equal(snapAppBefore.MainExe, snapAppAfter.MainExe); Assert.NotNull(snapAppAfter.MainExe); Assert.Equal(snapAppBefore.SuperVisorId, snapAppAfter.SuperVisorId); Assert.True(snapAppBefore.Version < snapAppAfter.Version); // Target Assert.NotNull(snapAppBefore.Target); Assert.NotNull(snapAppAfter.Target); Assert.Equal(snapAppBefore.Target.Os, snapAppAfter.Target.Os); Assert.Equal(snapAppBefore.Target.Rid, snapAppAfter.Target.Rid); Assert.NotNull(snapAppBefore.Target.Framework); Assert.NotNull(snapAppAfter.Target.Framework); Assert.Equal(snapAppBefore.Target.Framework, snapAppAfter.Target.Framework); Assert.Equal(snapAppBefore.Target.Rid, snapAppAfter.Target.Rid); Assert.Equal(snapAppBefore.Target.Shortcuts, snapAppAfter.Target.Shortcuts); Assert.Equal(snapAppBefore.Target.PersistentAssets, snapAppAfter.Target.PersistentAssets); // Channels Assert.Equal(snapAppBefore.Channels.Count, snapAppAfter.Channels.Count); for (var index = 0; index < snapAppAfter.Channels.Count; index++) { var lhsChannel = snapAppBefore.Channels[index]; var rhsChannel = snapAppAfter.Channels[index]; Assert.Equal(lhsChannel.Name, rhsChannel.Name); Assert.NotNull(lhsChannel.PushFeed); Assert.NotNull(rhsChannel.PushFeed); Assert.NotNull(lhsChannel.UpdateFeed); Assert.NotNull(rhsChannel.UpdateFeed); if (index == 0) { Assert.True(lhsChannel.Current); Assert.True(rhsChannel.Current); } else { Assert.False(lhsChannel.Current); Assert.False(rhsChannel.Current); } var lhsNugetPushFeed = lhsChannel.PushFeed; var rhsNugetPushFeed = rhsChannel.PushFeed; Assert.Equal(lhsNugetPushFeed.Name, rhsNugetPushFeed.Name); Assert.Equal(lhsNugetPushFeed.Source, rhsNugetPushFeed.Source); Assert.Equal(lhsNugetPushFeed.ProtocolVersion, rhsNugetPushFeed.ProtocolVersion); Assert.Equal(lhsNugetPushFeed.ApiKey, rhsNugetPushFeed.ApiKey); Assert.Equal(lhsNugetPushFeed.Username, rhsNugetPushFeed.Username); // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (lhsNugetPushFeed.IsPasswordEncryptionSupported()) { Assert.Equal(EncryptionUtility.DecryptString(lhsNugetPushFeed.Password), rhsNugetPushFeed.Password); } else { Assert.Equal(lhsNugetPushFeed.Password, rhsNugetPushFeed.Password); } var lhsUpdateFeed = lhsChannel.UpdateFeed; var rhsUpdateFeed = rhsChannel.UpdateFeed; switch (rhsUpdateFeed) { case SnapNugetFeed rhsNugetUpdateFeed: var lhsNugetUpdateFeed = (SnapNugetFeed)lhsUpdateFeed; Assert.Equal(lhsNugetUpdateFeed.Name, rhsNugetUpdateFeed.Name); Assert.Equal(lhsNugetUpdateFeed.Source, rhsNugetUpdateFeed.Source); Assert.Equal(lhsNugetUpdateFeed.ProtocolVersion, rhsNugetUpdateFeed.ProtocolVersion); Assert.Equal(lhsNugetUpdateFeed.ApiKey, rhsNugetUpdateFeed.ApiKey); Assert.Equal(lhsNugetUpdateFeed.Username, rhsNugetUpdateFeed.Username); Assert.Equal( lhsNugetUpdateFeed.IsPasswordEncryptionSupported() ? EncryptionUtility.DecryptString(lhsNugetUpdateFeed.Password) : lhsNugetUpdateFeed.Password, rhsNugetUpdateFeed.Password); break; case SnapHttpFeed rhsHttpUpdateFeed: var lhsHttpUpdateFeed = (SnapHttpFeed)lhsUpdateFeed; Assert.NotNull(lhsHttpUpdateFeed.Source); Assert.NotNull(rhsHttpUpdateFeed.Source); Assert.Equal(lhsHttpUpdateFeed.Source, rhsHttpUpdateFeed.Source); break; default: throw new NotSupportedException(rhsUpdateFeed.GetType().ToString()); } } }
internal static SnapApp BuildSnapApp([NotNull] this SnapApps snapApps, string id, [NotNull] string rid, [NotNull] INuGetPackageSources nuGetPackageSources, [NotNull] ISnapFilesystem snapFilesystem) { if (snapApps == null) { throw new ArgumentNullException(nameof(snapApps)); } if (rid == null) { throw new ArgumentNullException(nameof(rid)); } if (nuGetPackageSources == null) { throw new ArgumentNullException(nameof(nuGetPackageSources)); } if (snapFilesystem == null) { throw new ArgumentNullException(nameof(snapFilesystem)); } var snapApp = snapApps.Apps.SingleOrDefault(x => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase)); if (snapApp == null) { throw new Exception($"Unable to find snap with id: {id}"); } if (!Guid.TryParse(snapApp.SuperVisorId, out var superVisorId)) { throw new Exception("Unable to parse supervisor id. Please use a unique guid to identify your application."); } if (superVisorId == Guid.Empty) { throw new Exception("Supervisor id cannot be an empty guid."); } var snapAppUniqueRuntimeIdentifiers = snapApp.Targets.Select(x => x.Rid).ToList(); if (snapAppUniqueRuntimeIdentifiers.Distinct().Count() != snapApp.Targets.Count) { throw new Exception($"Target runtime identifiers (rids) must be unique: {string.Join(",", snapAppUniqueRuntimeIdentifiers)}. Snap id: {snapApp.Id}"); } var snapAppTarget = snapApp.Targets.SingleOrDefault(x => string.Equals(x.Rid, rid, StringComparison.OrdinalIgnoreCase)); if (snapAppTarget == null) { throw new Exception($"Unable to find target with rid: {rid}. Snap id: {snapApp.Id}"); } snapAppTarget.Installers = snapAppTarget.Installers.Distinct().ToList(); if (!snapAppTarget.Rid.IsRuntimeIdentifierValidSafe()) { throw new Exception($"Unsupported rid: {rid}. Snap id: {snapApp.Id}"); } if (!snapAppTarget.Framework.IsNetFrameworkValidSafe()) { throw new Exception($"Unknown .NET framework: {snapAppTarget.Framework}"); } var snapAppTargetUniqueShortcuts = snapAppTarget.Shortcuts.Select(x => x).ToList(); if (snapAppTargetUniqueShortcuts.Distinct().Count() != snapAppTarget.Shortcuts.Count) { throw new Exception($"Target shortcut locations must be unique: {string.Join(", ", snapAppTargetUniqueShortcuts)}. Snap id: {snapApp.Id}"); } var snapAppTargetUniqueInstallers = snapAppTarget.Installers.Select(x => x).ToList(); if (snapAppTargetUniqueInstallers.Distinct().Count() != snapAppTarget.Installers.Count) { throw new Exception($"Target installer types must be unique: {string.Join(", ", snapAppTargetUniqueInstallers)}. Snap id: {snapApp.Id}"); } if (snapAppTarget.Icon != null) { snapAppTarget.Icon = snapFilesystem.PathGetFullPath(snapAppTarget.Icon); if (!snapFilesystem.FileExists(snapAppTarget.Icon)) { throw new Exception($"Unable to find icon: {snapAppTarget.Icon}."); } } var snapAppUniqueChannels = snapApp.Channels.Distinct().ToList(); if (snapAppUniqueChannels.Count != snapApp.Channels.Count) { throw new Exception($"Channel list must be unique: {string.Join(",", snapApp.Channels)}. Snap id: {snapApp.Id}"); } var snapAppsDefaultChannel = snapApps.Channels.First(); var snapAppDefaultChannel = snapApp.Channels.First(); if (!string.Equals(snapAppsDefaultChannel.Name, snapAppDefaultChannel, StringComparison.Ordinal)) { throw new Exception($"Default channel must be {snapAppsDefaultChannel.Name}. Snap id: {snapApp.Id}"); } var snapAppAvailableChannels = snapApps.Channels.Where(rhs => snapApp.Channels.Any(lhs => lhs.Equals(rhs.Name, StringComparison.OrdinalIgnoreCase))).ToList(); if (!snapAppAvailableChannels.Any()) { throw new Exception($"Could not find any global channels. Channel list: {string.Join(",", snapAppUniqueChannels)}. Snap id: {snapApp.Id}"); } var snapFeeds = new List <SnapFeed>(); snapFeeds.AddRange(nuGetPackageSources.BuildSnapFeeds()); snapFeeds.AddRange(snapApps.Channels.Select(x => x.UpdateFeed).OfType <SnapsHttpFeed>().DistinctBy(x => x.Source).Select(x => new SnapHttpFeed(x))); var snapNugetFeeds = snapFeeds.Where(x => x is SnapNugetFeed).Cast <SnapNugetFeed>().ToList(); var snapHttpFeeds = snapFeeds.Where(x => x is SnapHttpFeed).Cast <SnapHttpFeed>().ToList(); var snapAppChannels = new List <SnapChannel>(); for (var i = 0; i < snapAppAvailableChannels.Count; i++) { var snapsChannel = snapAppAvailableChannels[i]; var pushFeed = snapNugetFeeds.SingleOrDefault(x => x.Name == snapsChannel.PushFeed.Name); if (pushFeed == null) { throw new Exception($"Unable to resolve push feed: {snapsChannel.PushFeed.Name}. Channel: {snapsChannel.Name}. Application id: {snapApp.Id}"); } SnapFeed updateFeed = null; switch (snapsChannel.UpdateFeed) { case SnapsNugetFeed snapsNugetFeed: updateFeed = snapNugetFeeds.SingleOrDefault(x => x.Name == snapsNugetFeed.Name); break; case SnapsHttpFeed snapsHttpFeed: updateFeed = snapHttpFeeds.SingleOrDefault(x => x.Source == snapsHttpFeed.Source); break; } if (updateFeed == null) { throw new Exception($"Unable to resolve update feed type: {snapsChannel.UpdateFeed?.GetType().Name}. Channel: {snapsChannel.Name}. Application id: {snapApp.Id}"); } var currentChannel = i == 0; // Default snap channel is always the first one defined. snapAppChannels.Add(new SnapChannel(snapsChannel.Name, currentChannel, pushFeed, updateFeed)); } var snapChannelNugetFeedNames = snapAppChannels.Select(x => x.PushFeed.Name).Distinct().ToList(); if (snapChannelNugetFeedNames.Count > 1) { throw new Exception($"Multiple nuget push feeds is not supported: {string.Join(",", snapChannelNugetFeedNames)}. Application id: {snapApp.Id}"); } if (snapAppTarget.PersistentAssets.Any(x => x.StartsWith("app-", StringComparison.OrdinalIgnoreCase))) { throw new Exception("Fatal error! A persistent asset starting with 'app-' was detected in manifest. This is a reserved keyword."); } return(new SnapApp { Id = snapApp.Id, SuperVisorId = superVisorId.ToString(), Channels = snapAppChannels, Target = new SnapTarget(snapAppTarget), Authors = snapApp.Nuspec.Authors, Description = snapApp.Nuspec.Description, ReleaseNotes = snapApp.Nuspec.ReleaseNotes, RepositoryUrl = snapApp.Nuspec.RepositoryUrl, RepositoryType = snapApp.Nuspec.RepositoryType }); }
public void TestBuildNugetSources_SnapApps() { var nugetOrgFeed = new SnapNugetFeed { Name = "nuget.org", Source = new Uri(NuGetConstants.V3FeedUrl) }; var nugetOrgMirrorFeed = new SnapNugetFeed { Name = "nuget.org (mirror)", Source = new Uri(NuGetConstants.V3FeedUrl) }; var snapApp = new SnapApp { Id = "demoapp", Version = new SemanticVersion(1, 0, 0), Channels = new List <SnapChannel> { new SnapChannel { UpdateFeed = nugetOrgFeed, PushFeed = nugetOrgFeed, Name = "test" }, new SnapChannel { UpdateFeed = nugetOrgFeed, PushFeed = nugetOrgFeed, Name = "staging" }, new SnapChannel { UpdateFeed = nugetOrgFeed, PushFeed = nugetOrgMirrorFeed, Name = "production" } }, Target = new SnapTarget { Os = OSPlatform.Windows, Rid = "win-x64", Framework = "netcoreapp2.1" } }; var snapApps = new SnapApps { Schema = 1, Channels = snapApp.Channels.Select(x => new SnapsChannel(x)).ToList(), Apps = new List <SnapsApp> { new SnapsApp(snapApp) }, Generic = new SnapAppsGeneric { Packages = "./packages" } }; var nugetPackageSources = snapApps.BuildNugetSources(new NuGetInMemoryPackageSources(_baseFixture.NugetTempDirectory, new List <PackageSource> { new PackageSource(nugetOrgFeed.Source.ToString(), nugetOrgFeed.Name), new PackageSource(nugetOrgMirrorFeed.Source.ToString(), nugetOrgMirrorFeed.Name) })); Assert.Equal(2, nugetPackageSources.Items.Count); var nugetOrgPackageSource = nugetPackageSources.Items.First(); Assert.Equal(nugetOrgPackageSource.Name, nugetOrgFeed.Name); var nugetOrgMirrorPackageSource = nugetPackageSources.Items.Skip(1).First(); Assert.Equal(nugetOrgMirrorPackageSource.Name, nugetOrgMirrorFeed.Name); }