Example #1
0
        public void GivenShippingAssets()
        {
            BuildModel expectedBuildModel = GetBuildModel();
            PushMetadataToBuildAssetRegistry pushMetadata = GetPushMetadata();

            PackageArtifactModel packageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", "false" },
                },
                Id      = shippingAssetData.Name,
                Version = shippingAssetData.Version
            };

            expectedBuildModel.Artifacts =
                new ArtifactSet
            {
                Packages = new List <PackageArtifactModel> {
                    packageArtifact
                }
            };

            BuildModel actualModel = pushMetadata.CreateMergedManifestBuildModel(
                ImmutableList.Create(shippingAssetData), manifestBuildData);

            actualModel.Should().BeEquivalentTo(expectedBuildModel);
        }
Example #2
0
        public void GivenAssetWithoutVersion()
        {
            BuildModel expectedBuildModel = GetBuildModel();
            PushMetadataToBuildAssetRegistry pushMetadata = GetPushMetadata();

            PackageArtifactModel packageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", "true" },
                    { "Id", assetDataWithoutVersion.Name },
                    { "Version", null }
                }
            };

            expectedBuildModel.Artifacts =
                new ArtifactSet
            {
                Packages = new List <PackageArtifactModel> {
                    packageArtifact
                }
            };

            BuildModel actualModel = pushMetadata.CreateMergedManifestBuildModel(
                ImmutableList.Create(assetDataWithoutVersion), manifestBuildData);

            actualModel.Should().BeEquivalentTo(expectedBuildModel);
        }
Example #3
0
        private ITaskItem ConvertToPackageInfoItem(PackageArtifactModel identity)
        {
            var metadata = new Dictionary <string, string>
            {
                [NuGetPackageInfoId]      = identity.Id,
                [NuGetPackageInfoVersion] = identity.Version.ToString()
            };

            return(new TaskItem(identity.ToString(), metadata));
        }
Example #4
0
        public void PackageArtifactModelEquals_ReturnsFalseWhenObjectsAreDifferentTypes()
        {
            PackageArtifactModel packageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", true.ToString().ToLower() },
                },
                Id      = "AssetName",
                Version = null
            };

            Assert.False(packageArtifact.Equals("thisIsNotAPackageArtifact!"));
        }
        OrchestratedFeedPackageVersion(string packageId)
        {
            return(infos => infos
                   .Select(info =>
            {
                PackageArtifactModel match = info.GetBlobFeed()?.Artifacts.Packages
                                             .FirstOrDefault(p => p.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase));

                if (match != null)
                {
                    return new DependencyReplacement(match.Version, new[] { info });
                }

                return null;
            })
                   .FirstOrDefault(r => r != null));
        }
Example #6
0
        public void GivenSomeAssetsInBlobSetAndSomeNot()
        {
            BuildModel expectedBuildModel = GetBuildModel();
            PushMetadataToBuildAssetRegistry pushMetadata = GetPushMetadata();

            AssetData dataInBlobSet = pushMetadata.GetManifestAsAsset(ImmutableList.Create(nonShippingAssetData), "thisIsALocation", "thisIsTheManifestFileName");

            PackageArtifactModel shippingPackageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", "false" },
                },
                Id      = shippingAssetData.Name,
                Version = shippingAssetData.Version
            };

            BlobArtifactModel blobArtifactModel = new BlobArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", "true" }
                },
                Id = dataInBlobSet.Name
            };

            expectedBuildModel.Artifacts =
                new ArtifactSet
            {
                Packages = new List <PackageArtifactModel> {
                    shippingPackageArtifact
                },
                Blobs = new List <BlobArtifactModel> {
                    blobArtifactModel
                }
            };

            BuildModel actualModel = pushMetadata.CreateMergedManifestBuildModel(
                ImmutableList.Create(dataInBlobSet, shippingAssetData), manifestBuildData);

            actualModel.Should().BeEquivalentTo(expectedBuildModel);
        }
        private Task <int> PublishWithNugetAsync(FeedConfig feedConfig, PackageArtifactModel package)
        {
            var packageFullPath = $"{PackageAssetsBasePath}{Path.DirectorySeparatorChar}{package.Id}.{package.Version}.nupkg";

            var tcs = new TaskCompletionSource <int>();

            Log.LogMessage($"Publishing package {packageFullPath} to target feed {feedConfig.TargetFeedURL} with nuget.exe push");

            var process = new Process
            {
                StartInfo = new ProcessStartInfo()
                {
                    FileName               = NugetPath,
                    Arguments              = $"push -Source {feedConfig.TargetFeedURL} -apikey {feedConfig.FeedKey} {packageFullPath}",
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    CreateNoWindow         = true
                },
                EnableRaisingEvents = true
            };

            process.Exited += (sender, args) =>
            {
                tcs.SetResult(process.ExitCode);
                if (process.ExitCode != 0)
                {
                    Log.LogError($"Nuget push failed with exit code {process.ExitCode}. Standard error output: {process.StandardError.ReadToEnd()}");
                }
                else
                {
                    Log.LogMessage($"Successfully published package {packageFullPath} to {feedConfig.TargetFeedURL}");
                }
                process.Dispose();
            };

            process.Start();

            return(tcs.Task);
        }
Example #8
0
        public void PackageArtifactModelEquals_ReturnsTrueWhenMatchingAttributesAreNull()
        {
            PackageArtifactModel packageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", true.ToString().ToLower() },
                },
                Id      = "AssetName",
                Version = null
            };

            PackageArtifactModel otherPackageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", true.ToString().ToLower() },
                },
                Id      = "AssetName",
                Version = null
            };

            Assert.True(packageArtifact.Equals(otherPackageArtifact));
        }
Example #9
0
        public void PackageArtifactModelEquals_ReturnsFalseWhenTwoObjectsDoNotHaveMatchingAttributes()
        {
            PackageArtifactModel packageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "Shipping", true.ToString().ToLower() },
                },
                Id      = "AssetName",
                Version = "AssetVersion"
            };

            PackageArtifactModel otherPackageArtifact = new PackageArtifactModel
            {
                Attributes = new Dictionary <string, string>
                {
                    { "NonShipping", true.ToString().ToLower() },
                },
                Id      = "AssetName",
                Version = "AssetVersion"
            };

            Assert.False(packageArtifact.Equals(otherPackageArtifact));
        }
Example #10
0
 private ITaskItem CreateItem(PackageArtifactModel model)
 {
     return(new TaskItem("Package", ArtifactMetadata(model.ToXml(), model.Attributes)));
 }
        /// <summary>
        ///     Push a single package to the azure devops nuget feed.
        /// </summary>
        /// <param name="feedConfig">Feed</param>
        /// <param name="packageToPublish">Package to push</param>
        /// <returns>Task</returns>
        /// <remarks>
        ///     This method attempts to take the most efficient path to push the package.
        ///     There are two cases:
        ///         - The package does not exist, and is pushed normally
        ///         - The package exists, and its contents may or may not be equivalent.
        ///     The second case is is by far the most common. So, we first attempt to push the package normally using nuget.exe.
        ///     If this fails, this could mean any number of things (like failed auth). But in normal circumstances, this might
        ///     mean the package already exists. This either means that we are attempting to push the same package, or attemtping to push
        ///     a different package with the same id and version. The second case is an error, as azure devops feeds are immutable, the former
        ///     is simply a case where we should continue onward.
        /// </remarks>
        private async Task PushNugetPackageAsync(FeedConfig feedConfig, HttpClient client, PackageArtifactModel packageToPublish,
                                                 string feedAccount, string feedVisibility, string feedName)
        {
            Log.LogMessage(MessageImportance.High, $"Pushing package '{packageToPublish.Id}' to feed {feedConfig.TargetFeedURL}");

            PackageAssetsBasePath = PackageAssetsBasePath.TrimEnd(
                Path.DirectorySeparatorChar,
                Path.AltDirectorySeparatorChar)
                                    + Path.DirectorySeparatorChar;

            string localPackageLocation = $"{PackageAssetsBasePath}{packageToPublish.Id}.{packageToPublish.Version}.nupkg";

            if (!File.Exists(localPackageLocation))
            {
                Log.LogError($"Could not locate '{packageToPublish.Id}.{packageToPublish.Version}' at '{localPackageLocation}'");
                return;
            }

            try
            {
                // The feed key when pushing to AzDo feeds is "AzureDevOps" (works with the credential helper).
                int result = await StartProcessAsync(NugetPath, $"push \"{localPackageLocation}\" -Source \"{feedConfig.TargetFeedURL}\" -NonInteractive -ApiKey AzureDevOps");

                if (result != 0)
                {
                    Log.LogMessage(MessageImportance.Low, $"Failed to push {localPackageLocation}, attempting to determine whether the package already exists on the feed with the same content.");

                    try
                    {
                        string packageContentUrl = $"https://pkgs.dev.azure.com/{feedAccount}/{feedVisibility}_apis/packaging/feeds/{feedName}/nuget/packages/{packageToPublish.Id}/versions/{packageToPublish.Version}/content";

                        if (await IsLocalPackageIdenticalToFeedPackage(localPackageLocation, packageContentUrl, client))
                        {
                            Log.LogMessage(MessageImportance.Normal, $"Package '{packageToPublish.Id}@{packageToPublish.Version}' already exists on '{feedConfig.TargetFeedURL}' but has the same content. Skipping.");
                        }
                        else
                        {
                            Log.LogError($"Package '{packageToPublish.Id}@{packageToPublish.Version}' already exists on '{feedConfig.TargetFeedURL}' with different content.");
                        }

                        return;
                    }
                    catch (Exception e)
                    {
                        // This is an error. It means we were unable to push using nuget, and then could not access to the package otherwise.
                        Log.LogWarning($"Failed to determine whether an existing package on the feed has the same content as '{localPackageLocation}': {e.Message}");
                    }

                    Log.LogError($"Failed to push '{packageToPublish.Id}@{packageToPublish.Version}'. Result code '{result}'.");
                }
            }
            catch (Exception e)
            {
                Log.LogError($"Unexpected exception pushing package '{packageToPublish.Id}@{packageToPublish.Version}': {e.Message}");
            }
        }