private static BuildModel CreateModel(IEnumerable <BlobArtifactModel> blobArtifacts, IEnumerable <PackageArtifactModel> packageArtifacts, string manifestBuildId, string[] manifestBuildData, string manifestRepoName, string manifestBranch, string manifestCommit, bool isStableBuild, PublishingInfraVersion publishingVersion, TaskLoggingHelper log, SigningInformationModel signingInformationModel = null) { var attributes = MSBuildListSplitter.GetNamedProperties(manifestBuildData); if (!ManifestBuildDataHasLocationInformation(attributes)) { log.LogError($"Missing 'location' property from ManifestBuildData"); } BuildModel buildModel = new BuildModel( new BuildIdentity { Attributes = attributes, Name = manifestRepoName, BuildId = manifestBuildId, Branch = manifestBranch, Commit = manifestCommit, IsStable = isStableBuild.ToString(), PublishingVersion = publishingVersion }); buildModel.Artifacts.Blobs.AddRange(blobArtifacts); buildModel.Artifacts.Packages.AddRange(packageArtifacts); buildModel.SigningInformation = signingInformationModel; return(buildModel); }
/// <summary> /// Create a build manifest for packages, blobs, and associated signing information /// </summary> /// <param name="log">MSBuild log helper</param> /// <param name="blobArtifacts">Collection of blobs</param> /// <param name="packageArtifacts">Collection of packages</param> /// <param name="assetManifestPath">Asset manifest file that should be written</param> /// <param name="manifestRepoName">Repository name</param> /// <param name="manifestBuildId">Azure devops build id</param> /// <param name="manifestBranch">Name of the branch that was built</param> /// <param name="manifestCommit">Commit that was built</param> /// <param name="manifestBuildData">Additional build data properties</param> /// <param name="isStableBuild">True if the build is stable, false otherwise.</param> /// <param name="publishingVersion">Publishing version in use.</param> /// <param name="isReleaseOnlyPackageVersion">True if this repo uses release-only package versions</param> /// <param name="signingInformationModel">Signing information.</param> public static void CreateBuildManifest(TaskLoggingHelper log, IEnumerable <BlobArtifactModel> blobArtifacts, IEnumerable <PackageArtifactModel> packageArtifacts, string assetManifestPath, string manifestRepoName, string manifestBuildId, string manifestBranch, string manifestCommit, string[] manifestBuildData, bool isStableBuild, PublishingInfraVersion publishingVersion, bool isReleaseOnlyPackageVersion, SigningInformationModel signingInformationModel = null) { CreateModel( blobArtifacts, packageArtifacts, manifestBuildId, manifestBuildData, manifestRepoName, manifestBranch, manifestCommit, isStableBuild, publishingVersion, isReleaseOnlyPackageVersion, log, signingInformationModel: signingInformationModel) .WriteAsXml(assetManifestPath, log); }
/// <summary> /// Create a build manifest for packages, blobs, and associated signing information /// </summary> /// <param name="log">MSBuild log helper</param> /// <param name="blobArtifacts">Collection of blobs</param> /// <param name="packageArtifacts">Collection of packages</param> /// <param name="assetManifestPath">Asset manifest file that should be written</param> /// <param name="manifestRepoName">Repository name</param> /// <param name="manifestBuildId">Azure devops build id</param> /// <param name="manifestBranch">Name of the branch that was built</param> /// <param name="manifestCommit">Commit that was built</param> /// <param name="manifestBuildData">Additional build data properties</param> /// <param name="isStableBuild">True if the build is stable, false otherwise.</param> /// <param name="publishingVersion">Publishing version in use.</param> /// <param name="isReleaseOnlyPackageVersion">True if this repo uses release-only package versions</param> /// <param name="signingInformationModel">Signing information.</param> public void CreateBuildManifest( IEnumerable <BlobArtifactModel> blobArtifacts, IEnumerable <PackageArtifactModel> packageArtifacts, string assetManifestPath, string manifestRepoName, string manifestBuildId, string manifestBranch, string manifestCommit, string[] manifestBuildData, bool isStableBuild, PublishingInfraVersion publishingVersion, bool isReleaseOnlyPackageVersion, SigningInformationModel signingInformationModel = null) { BuildModel model = CreateModel( blobArtifacts, packageArtifacts, manifestBuildId, manifestBuildData, manifestRepoName, manifestBranch, manifestCommit, isStableBuild, publishingVersion, isReleaseOnlyPackageVersion, signingInformationModel: signingInformationModel); _log.LogMessage(MessageImportance.High, $"Writing build manifest file '{assetManifestPath}'..."); _fileSystem.WriteToFile(assetManifestPath, model.ToXml().ToString(SaveOptions.DisableFormatting)); }
[InlineData(typeof(ArgumentException), "", "bar")] // Can't be empty public void ManifestModelToXmlValidatesFileExtensionSignInfos(Type exceptionType, params string[] infos) { if (infos.Length % 2 != 0) { throw new ArgumentException(); } List <FileExtensionSignInfoModel> models = new List <FileExtensionSignInfoModel>(); // Include is first arg, cert name is second // InlineData can't pass tuple types so using this instead. for (int i = 0; i < infos.Length / 2; i++) { models.Add(new FileExtensionSignInfoModel() { Include = infos[i * 2], CertificateName = infos[i * 2 + 1] }); } SigningInformationModel signInfo = new SigningInformationModel() { FileExtensionSignInfo = models }; VerifyToXml(exceptionType, signInfo); }
[InlineData(null, "MyStrongName", "aaaaaaaaaaaaaaab", "Mycert", "MyStrongName", "aaaaaaaaaaaaaaaa", "Mycert2")] // No conflict public void ManifestModelToXmlValidatesStrongNameSignInfo(Type exceptionType, params string[] infos) { if (infos.Length % 3 != 0) { throw new ArgumentException(); } List <StrongNameSignInfoModel> models = new List <StrongNameSignInfoModel>(); for (int i = 0; i < infos.Length / 3; i++) { models.Add(new StrongNameSignInfoModel() { Include = infos[i * 3], PublicKeyToken = infos[i * 3 + 1], CertificateName = infos[i * 3 + 2] }); } SigningInformationModel signInfo = new SigningInformationModel() { StrongNameSignInfo = models }; VerifyToXml(exceptionType, signInfo); }
public void ManifestModelToXmlValidatesCertificateSignInfo(Type exceptionType, params string[] infos) { if (infos.Length % 2 != 0) { throw new ArgumentException(); } List <CertificatesSignInfoModel> models = new List <CertificatesSignInfoModel>(); for (int i = 0; i < infos.Length / 2; i++) { models.Add(new CertificatesSignInfoModel() { Include = infos[i * 2], DualSigningAllowed = bool.Parse(infos[i * 2 + 1]) }); } SigningInformationModel signInfo = new SigningInformationModel() { CertificatesSignInfo = models }; VerifyToXml(exceptionType, signInfo); }
public void ValidateSymreaderFileSignInfos() { List <FileSignInfoModel> models = new List <FileSignInfoModel>(); models.Add(new FileSignInfoModel() { Include = "Microsoft.DiaSymReader.dll", CertificateName = "MicrosoftWin8WinBlue", TargetFramework = ".NETFramework,Version=v2.0", PublicKeyToken = "31bf3856ad364e35", }); models.Add(new FileSignInfoModel() { Include = "Microsoft.DiaSymReader.dll", CertificateName = "Microsoft101240624", // lgtm [cs/common-default-passwords] Safe, these are certificate names TargetFramework = ".NETStandard,Version=v1.1", PublicKeyToken = "31bf3856ad364e35", }); SigningInformationModel signInfo = new SigningInformationModel() { FileSignInfo = models }; signInfo.ToXml().Should().NotBeNull(); }
public void ManifestModelToXmlValidatesFileSignInfos(Type exceptionType, params string[] infos) { if (infos.Length % 4 != 0) { throw new ArgumentException(); } List <FileSignInfoModel> models = new List <FileSignInfoModel>(); for (int i = 0; i < infos.Length / 4; i++) { models.Add(new FileSignInfoModel() { Include = infos[i * 4], CertificateName = infos[i * 4 + 1], TargetFramework = infos[i * 4 + 2], PublicKeyToken = infos[i * 4 + 3], }); } SigningInformationModel signInfo = new SigningInformationModel() { FileSignInfo = models }; VerifyToXml(exceptionType, signInfo); }
private static void VerifyToXml(Type expectedExceptionType, SigningInformationModel signInfo) { if (expectedExceptionType != null) { Action act = () => signInfo.ToXml(); act.Should().Throw <Exception>().And.Should().BeOfType(expectedExceptionType); } else { signInfo.ToXml().Should().NotBeNull(); } }
private static void VerifyFromXml(Type expectedExceptionType, StringBuilder builder) { if (expectedExceptionType != null) { Action act = () => SigningInformationModel.Parse(XElement.Parse(builder.ToString())); act.Should().Throw <Exception>().And.Should().BeOfType(expectedExceptionType); } else { SigningInformationModel.Parse(XElement.Parse(builder.ToString())).Should().NotBeNull(); } }
public override bool Execute() { try { Log.LogMessage(MessageImportance.High, "Performing push to Azure DevOps artifacts storage."); if (!string.IsNullOrWhiteSpace(AssetsTemporaryDirectory)) { Log.LogMessage(MessageImportance.High, $"It's no longer necessary to specify a value for the {nameof(AssetsTemporaryDirectory)} property. " + $"Please consider patching your code to not use it."); } if (ItemsToPush == null) { Log.LogError($"No items to push. Please check ItemGroup ItemsToPush."); } else { IEnumerable <BlobArtifactModel> blobArtifacts = Enumerable.Empty <BlobArtifactModel>(); IEnumerable <PackageArtifactModel> packageArtifacts = Enumerable.Empty <PackageArtifactModel>(); var itemsToPushNoExcludes = ItemsToPush. Where(i => !string.Equals(i.GetMetadata("ExcludeFromManifest"), "true", StringComparison.OrdinalIgnoreCase)); if (PublishFlatContainer) { // Act as if %(PublishFlatContainer) were true for all items. blobArtifacts = itemsToPushNoExcludes .Select(BuildManifestUtil.CreateBlobArtifactModel); foreach (var blobItem in itemsToPushNoExcludes) { if (!File.Exists(blobItem.ItemSpec)) { Log.LogError($"Could not find file {blobItem.ItemSpec}."); continue; } Log.LogMessage(MessageImportance.High, $"##vso[artifact.upload containerfolder=BlobArtifacts;artifactname=BlobArtifacts]{blobItem.ItemSpec}"); } } else { ITaskItem[] symbolItems = itemsToPushNoExcludes .Where(i => i.ItemSpec.Contains("symbols.nupkg")) .Select(i => { string fileName = Path.GetFileName(i.ItemSpec); i.SetMetadata("RelativeBlobPath", $"{BuildManifestUtil.AssetsVirtualDir}symbols/{fileName}"); return(i); }) .ToArray(); var blobItems = itemsToPushNoExcludes .Where(i => { var isFlatString = i.GetMetadata("PublishFlatContainer"); if (!string.IsNullOrEmpty(isFlatString) && bool.TryParse(isFlatString, out var isFlat)) { return(isFlat); } return(false); }) .Union(symbolItems) .ToArray(); ITaskItem[] packageItems = itemsToPushNoExcludes .Except(blobItems) .ToArray(); foreach (var packagePath in packageItems) { if (!File.Exists(packagePath.ItemSpec)) { Log.LogError($"Could not find file {packagePath.ItemSpec}."); continue; } Log.LogMessage(MessageImportance.High, $"##vso[artifact.upload containerfolder=PackageArtifacts;artifactname=PackageArtifacts]{packagePath.ItemSpec}"); } foreach (var blobItem in blobItems) { if (!File.Exists(blobItem.ItemSpec)) { Log.LogError($"Could not find file {blobItem.ItemSpec}."); continue; } Log.LogMessage(MessageImportance.High, $"##vso[artifact.upload containerfolder=BlobArtifacts;artifactname=BlobArtifacts]{blobItem.ItemSpec}"); } packageArtifacts = packageItems.Select(BuildManifestUtil.CreatePackageArtifactModel); blobArtifacts = blobItems.Select(BuildManifestUtil.CreateBlobArtifactModel).Where(blob => blob != null); } PublishingInfraVersion targetPublishingVersion = PublishingInfraVersion.Latest; if (!string.IsNullOrEmpty(PublishingVersion)) { if (!Enum.TryParse(PublishingVersion, ignoreCase: true, out targetPublishingVersion)) { Log.LogError($"Could not parse publishing infra version '{PublishingVersion}'"); } } SigningInformationModel signingInformationModel = BuildManifestUtil.CreateSigningInformationModelFromItems(AzureDevOpsCollectionUri, AzureDevOpsProject, AzureDevOpsBuildId, ItemsToSign, StrongNameSignInfo, FileSignInfo, FileExtensionSignInfo); BuildManifestUtil.CreateBuildManifest(Log, blobArtifacts, packageArtifacts, AssetManifestPath, ManifestRepoUri, ManifestBuildId, ManifestBranch, ManifestCommit, ManifestBuildData, IsStableBuild, targetPublishingVersion, signingInformationModel: signingInformationModel); Log.LogMessage(MessageImportance.High, $"##vso[artifact.upload containerfolder=AssetManifests;artifactname=AssetManifests]{AssetManifestPath}"); } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }