Upload checksums for installation artifacts (#4191)
The checksums are SHA-512 hashes, which users can use to verify file integrity and authenticity.
This commit is contained in:
parent
3e1eb008e2
commit
3ae14ab618
11 changed files with 402 additions and 200 deletions
|
@ -1,7 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildThisFileDirectory)/publish/FinishBuild.targets" />
|
||||||
<Import Project="$(MSBuildThisFileDirectory)/publish/PublishContent.targets" />
|
<Import Project="$(MSBuildThisFileDirectory)/publish/PublishContent.targets" />
|
||||||
<Import Project="$(MSBuildThisFileDirectory)/publish/Microsoft.DotNet.Cli.Badge.targets" />
|
<Import Project="$(MSBuildThisFileDirectory)/publish/Microsoft.DotNet.Cli.Badge.targets" />
|
||||||
|
<Import Project="$(MSBuildThisFileDirectory)/publish/Microsoft.DotNet.Cli.Checksum.targets" />
|
||||||
|
|
||||||
<!-- PUBLISH_TO_AZURE_BLOB env variable set by CI -->
|
<!-- PUBLISH_TO_AZURE_BLOB env variable set by CI -->
|
||||||
<Target Name="Publish"
|
<Target Name="Publish"
|
||||||
|
@ -16,26 +18,22 @@
|
||||||
DependsOnTargets="SetupAzureBlobInformation;
|
DependsOnTargets="SetupAzureBlobInformation;
|
||||||
GenerateVersionBadge;
|
GenerateVersionBadge;
|
||||||
GatherItemsForPattern;
|
GatherItemsForPattern;
|
||||||
UploadToAzure;
|
GenerateChecksums;
|
||||||
|
UploadArtifactsToAzure;
|
||||||
|
UploadChecksumsToAzure;
|
||||||
PublishDebFilesToDebianRepo;
|
PublishDebFilesToDebianRepo;
|
||||||
PublishCliVersionBadge" />
|
PublishCliVersionBadge" />
|
||||||
|
|
||||||
<Target Name="FinishBuild">
|
|
||||||
<FinalizeBuild AccountName="$(CloudDropAccountName)"
|
|
||||||
AccountKey="$(CloudDropAccessToken)"
|
|
||||||
NugetVersion="$(NugetVersion)"
|
|
||||||
Channel="$(Channel)"
|
|
||||||
CommitHash="$(CommitHash)"
|
|
||||||
BranchName="$(BranchName)" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="SetupAzureBlobInformation">
|
<Target Name="SetupAzureBlobInformation">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Sdk</Product>
|
<Product>Sdk</Product>
|
||||||
<ContainerName>$(STORAGE_CONTAINER)</ContainerName>
|
<ArtifactContainerName>$(ARTIFACT_STORAGE_CONTAINER)</ArtifactContainerName>
|
||||||
<CloudDropAccessToken>$(STORAGE_KEY)</CloudDropAccessToken>
|
<ArtifactCloudDropAccessToken>$(ARTIFACT_STORAGE_KEY)</ArtifactCloudDropAccessToken>
|
||||||
<CloudDropAccountName>$(STORAGE_ACCOUNT)</CloudDropAccountName>
|
<ArtifactCloudDropAccountName>$(ARTIFACT_STORAGE_ACCOUNT)</ArtifactCloudDropAccountName>
|
||||||
<DotnetBlobRootUrl>https://$(CloudDropAccountName).blob.core.windows.net/$(ContainerName)</DotnetBlobRootUrl>
|
<DotnetBlobRootUrl>https://$(ArtifactCloudDropAccountName).blob.core.windows.net/$(ArtifactContainerName)</DotnetBlobRootUrl>
|
||||||
|
<ChecksumContainerName>$(CHECKSUM_STORAGE_CONTAINER)</ChecksumContainerName>
|
||||||
|
<ChecksumCloudDropAccessToken>$(CHECKSUM_STORAGE_KEY)</ChecksumCloudDropAccessToken>
|
||||||
|
<ChecksumCloudDropAccountName>$(CHECKSUM_STORAGE_ACCOUNT)</ChecksumCloudDropAccountName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
@ -94,16 +92,16 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<UploadToAzure
|
<UploadToAzure
|
||||||
AccountKey="$(CloudDropAccessToken)"
|
AccountKey="$(ArtifactCloudDropAccessToken)"
|
||||||
AccountName="$(CloudDropAccountName)"
|
AccountName="$(ArtifactCloudDropAccountName)"
|
||||||
ContainerName="$(ContainerName)"
|
ContainerName="$(ArtifactContainerName)"
|
||||||
Items="@(CliVersionBadgeToUpload)"
|
Items="@(CliVersionBadgeToUpload)"
|
||||||
Overwrite="$(OverwriteOnPublish)" />
|
Overwrite="$(OverwriteOnPublish)" />
|
||||||
|
|
||||||
<SetBlobPropertiesBasedOnFileType
|
<SetBlobPropertiesBasedOnFileType
|
||||||
AccountKey="$(CloudDropAccessToken)"
|
AccountKey="$(ArtifactCloudDropAccessToken)"
|
||||||
AccountName="$(CloudDropAccountName)"
|
AccountName="$(ArtifactCloudDropAccountName)"
|
||||||
ContainerName="$(ContainerName)"
|
ContainerName="$(ArtifactContainerName)"
|
||||||
Items="@(CliVersionBadgeToUpload)" />
|
Items="@(CliVersionBadgeToUpload)" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
|
@ -2,7 +2,10 @@
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="14.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<UsingTask TaskName="AddMetadataIsPE" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="AddMetadataIsPE" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="ChangeEntryPointLibraryName" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="ChangeEntryPointLibraryName" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
<UsingTask TaskName="CheckIfAllBuildsHavePublished" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="ChMod" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="ChMod" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
<UsingTask TaskName="CopyBlobsToLatest" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
<UsingTask TaskName="CreateAzureContainer" AssemblyFile="$(CLIBuildDll)"/>
|
||||||
<UsingTask TaskName="Crossgen" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="Crossgen" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="DotNetBuild" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="DotNetBuild" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="DotNetNew" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="DotNetNew" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
@ -11,8 +14,8 @@
|
||||||
<UsingTask TaskName="DotNetRestore" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="DotNetRestore" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="DotNetTest" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="DotNetTest" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="DownloadFile" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="DownloadFile" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="FinalizeBuild" AssemblyFile="$(CLIBuildDll)" />
|
|
||||||
<UsingTask TaskName="GenerateBuildVersionInfo" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="GenerateBuildVersionInfo" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
<UsingTask TaskName="GenerateChecksums" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="GenerateGuidFromName" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="GenerateGuidFromName" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="GetCommitHash" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="GetCommitHash" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="GetCurrentRuntimeInformation" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="GetCurrentRuntimeInformation" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
@ -23,7 +26,7 @@
|
||||||
<UsingTask TaskName="SetEnvVar" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="SetEnvVar" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="TarGzFileCreateFromDirectory" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="TarGzFileCreateFromDirectory" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="TarGzFileExtractToDirectory" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="TarGzFileExtractToDirectory" AssemblyFile="$(CLIBuildDll)" />
|
||||||
<UsingTask TaskName="CreateAzureContainer" AssemblyFile="$(CLIBuildDll)"/>
|
<UsingTask TaskName="UpdateVersionsRepo" AssemblyFile="$(CLIBuildDll)"/>
|
||||||
<UsingTask TaskName="UploadToAzure" AssemblyFile="$(CLIBuildDll)"/>
|
<UsingTask TaskName="UploadToAzure" AssemblyFile="$(CLIBuildDll)"/>
|
||||||
<UsingTask TaskName="ZipFileCreateFromDirectory" AssemblyFile="$(CLIBuildDll)"/>
|
<UsingTask TaskName="ZipFileCreateFromDirectory" AssemblyFile="$(CLIBuildDll)"/>
|
||||||
<UsingTask TaskName="ZipFileExtractToDirectory" AssemblyFile="$(CLIBuildDll)"/>
|
<UsingTask TaskName="ZipFileExtractToDirectory" AssemblyFile="$(CLIBuildDll)"/>
|
||||||
|
|
34
build/publish/FinishBuild.targets
Normal file
34
build/publish/FinishBuild.targets
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="FinishBuild"
|
||||||
|
DependsOnTargets="CheckIfAllBuildsHavePublished;
|
||||||
|
FinalizeBuild" />
|
||||||
|
|
||||||
|
<Target Name="CheckIfAllBuildsHavePublished">
|
||||||
|
<CheckIfAllBuildsHavePublished AccountKey="$(ArtifactCloudDropAccessToken)"
|
||||||
|
AccountName="$(ArtifactCloudDropAccountName)"
|
||||||
|
ContainerName="$(ArtifactContainerName)"
|
||||||
|
NugetVersion="$(NugetVersion)">
|
||||||
|
<Output TaskParameter="HaveAllBuildsPublished" PropertyName="HaveAllBuildsPublished" />
|
||||||
|
</CheckIfAllBuildsHavePublished>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="FinalizeBuild"
|
||||||
|
Condition=" '$(HaveAllBuildsPublished)' == 'True' ">
|
||||||
|
<CopyBlobsToLatest AccountName="$(ArtifactCloudDropAccountName)"
|
||||||
|
AccountKey="$(ArtifactCloudDropAccessToken)"
|
||||||
|
ContainerName="$(ArtifactContainerName)"
|
||||||
|
NugetVersion="$(NugetVersion)"
|
||||||
|
Channel="$(Channel)"
|
||||||
|
CommitHash="$(CommitHash)" />
|
||||||
|
|
||||||
|
<CopyBlobsToLatest AccountName="$(ChecksumCloudDropAccountName)"
|
||||||
|
AccountKey="$(ChecksumCloudDropAccessToken)"
|
||||||
|
ContainerName="$(ChecksumContainerName)"
|
||||||
|
NugetVersion="$(NugetVersion)"
|
||||||
|
Channel="$(Channel)"
|
||||||
|
CommitHash="$(CommitHash)" />
|
||||||
|
|
||||||
|
<UpdateVersionsRepo BranchName="$(BranchName)" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
21
build/publish/Microsoft.DotNet.Cli.Checksum.targets
Normal file
21
build/publish/Microsoft.DotNet.Cli.Checksum.targets
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="GenerateChecksums"
|
||||||
|
DependsOnTargets="Init;
|
||||||
|
InitializeChecksumItemGroup;"
|
||||||
|
Inputs="@(ArtifactsForGeneratingChecksums)"
|
||||||
|
Outputs="%(ArtifactsForGeneratingChecksums.DestinationPath)">
|
||||||
|
<GenerateChecksums Items="@(ArtifactsForGeneratingChecksums)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="InitializeChecksumItemGroup"
|
||||||
|
DependsOnTargets="Init;
|
||||||
|
GatherItemsForPattern">
|
||||||
|
<ItemGroup>
|
||||||
|
<ArtifactsForGeneratingChecksums Include="@(ForPublishing)">
|
||||||
|
<DestinationPath>%(ForPublishing.FullPath).sha</DestinationPath>
|
||||||
|
<RelativeBlobPath>%(ForPublishing.RelativeBlobPath).sha</RelativeBlobPath>
|
||||||
|
</ArtifactsForGeneratingChecksums>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
|
@ -19,23 +19,42 @@
|
||||||
<Error Condition="'@(ForPublishing)' == ''" Text="No items were found matching pattern '$(PublishPattern)'." />
|
<Error Condition="'@(ForPublishing)' == ''" Text="No items were found matching pattern '$(PublishPattern)'." />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<!-- publishes items to blob storage in Azure -->
|
<!-- publishes artifacts to blob storage in Azure -->
|
||||||
<Target Name="UploadToAzure" DependsOnTargets="GatherItemsForPattern">
|
<Target Name="UploadArtifactsToAzure" DependsOnTargets="GatherItemsForPattern">
|
||||||
<Error Condition="'$(ContainerName)' == ''" Text="Missing property ContainerName." />
|
<Error Condition="'$(ArtifactContainerName)' == ''" Text="Missing property ArtifactContainerName." />
|
||||||
<Error Condition="'$(CloudDropAccountName)' == ''" Text="Missing property CloudDropAccountName." />
|
<Error Condition="'$(ArtifactCloudDropAccountName)' == ''" Text="Missing property ArtifactCloudDropAccountName." />
|
||||||
<Error Condition="'$(CloudDropAccessToken)' == ''" Text="Missing property CloudDropAccessToken." />
|
<Error Condition="'$(ArtifactCloudDropAccessToken)' == ''" Text="Missing property ArtifactCloudDropAccessToken." />
|
||||||
<!-- create the container if it doesn't exist -->
|
<!-- create the container if it doesn't exist -->
|
||||||
<CreateAzureContainer
|
<CreateAzureContainer
|
||||||
AccountKey="$(CloudDropAccessToken)"
|
AccountKey="$(ArtifactCloudDropAccessToken)"
|
||||||
AccountName="$(CloudDropAccountName)"
|
AccountName="$(ArtifactCloudDropAccountName)"
|
||||||
ContainerName="$(ContainerName)" />
|
ContainerName="$(ArtifactContainerName)" />
|
||||||
<!-- now upload the items -->
|
<!-- now upload the items -->
|
||||||
<UploadToAzure
|
<UploadToAzure
|
||||||
AccountKey="$(CloudDropAccessToken)"
|
AccountKey="$(ArtifactCloudDropAccessToken)"
|
||||||
AccountName="$(CloudDropAccountName)"
|
AccountName="$(ArtifactCloudDropAccountName)"
|
||||||
ContainerName="$(ContainerName)"
|
ContainerName="$(ArtifactContainerName)"
|
||||||
Items="@(ForPublishing)"
|
Items="@(ForPublishing)"
|
||||||
Overwrite="$(OverwriteOnPublish)" />
|
Overwrite="$(OverwriteOnPublish)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
<!-- publishes checksums for the artifacts to blob storage in Azure -->
|
||||||
|
<Target Name="UploadChecksumsToAzure" DependsOnTargets="GenerateChecksums">
|
||||||
|
<Error Condition="'$(ChecksumContainerName)' == ''" Text="Missing property ChecksumContainerName." />
|
||||||
|
<Error Condition="'$(ChecksumCloudDropAccountName)' == ''" Text="Missing property ChecksumCloudDropAccountName." />
|
||||||
|
<Error Condition="'$(ChecksumCloudDropAccessToken)' == ''" Text="Missing property ChecksumCloudDropAccessToken." />
|
||||||
|
<!-- create the container if it doesn't exist -->
|
||||||
|
<CreateAzureContainer
|
||||||
|
AccountKey="$(ChecksumCloudDropAccessToken)"
|
||||||
|
AccountName="$(ChecksumCloudDropAccountName)"
|
||||||
|
ContainerName="$(ChecksumContainerName)" />
|
||||||
|
<!-- now upload the items -->
|
||||||
|
<UploadToAzure
|
||||||
|
AccountKey="$(ChecksumCloudDropAccessToken)"
|
||||||
|
AccountName="$(ChecksumCloudDropAccountName)"
|
||||||
|
ContainerName="$(ChecksumContainerName)"
|
||||||
|
Items="@(ArtifactsForGeneratingChecksums->'%(DestinationPath)')"
|
||||||
|
Overwrite="$(OverwriteOnPublish)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Build
|
||||||
|
{
|
||||||
|
public class CheckIfAllBuildsHavePublished : Task
|
||||||
|
{
|
||||||
|
private AzurePublisher _azurePublisher;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string AccountName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string AccountKey { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ContainerName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string NugetVersion { get; set; }
|
||||||
|
|
||||||
|
[Output]
|
||||||
|
public string HaveAllBuildsPublished { get; set; }
|
||||||
|
|
||||||
|
private AzurePublisher AzurePublisherTool
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_azurePublisher == null)
|
||||||
|
{
|
||||||
|
_azurePublisher = new AzurePublisher(AccountName, AccountKey, ContainerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _azurePublisher;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
var badges = new Dictionary<string, bool>()
|
||||||
|
{
|
||||||
|
{ "Windows_x86", false },
|
||||||
|
{ "Windows_x64", false },
|
||||||
|
{ "Ubuntu_x64", false },
|
||||||
|
{ "Ubuntu_16_04_x64", false },
|
||||||
|
{ "RHEL_x64", false },
|
||||||
|
{ "OSX_x64", false },
|
||||||
|
{ "Debian_x64", false },
|
||||||
|
{ "CentOS_x64", false },
|
||||||
|
{ "Fedora_23_x64", false },
|
||||||
|
{ "openSUSE_13_2_x64", false }
|
||||||
|
};
|
||||||
|
|
||||||
|
var versionBadgeName = $"{Monikers.GetBadgeMoniker()}";
|
||||||
|
if (!badges.ContainsKey(versionBadgeName))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"A new OS build '{versionBadgeName}' was added without adding the moniker to the {nameof(badges)} lookup");
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> blobs = AzurePublisherTool.ListBlobs(AzurePublisher.Product.Sdk, NugetVersion);
|
||||||
|
foreach (string file in blobs)
|
||||||
|
{
|
||||||
|
string name = Path.GetFileName(file);
|
||||||
|
foreach (string img in badges.Keys)
|
||||||
|
{
|
||||||
|
if ((name.StartsWith($"{img}")) && (name.EndsWith(".svg")))
|
||||||
|
{
|
||||||
|
badges[img] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HaveAllBuildsPublished = badges.Values.All(v => v).ToString();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
build_projects/dotnet-cli-build/CopyBlobsToLatest.cs
Normal file
108
build_projects/dotnet-cli-build/CopyBlobsToLatest.cs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Build
|
||||||
|
{
|
||||||
|
public class CopyBlobsToLatest : Task
|
||||||
|
{
|
||||||
|
private AzurePublisher _azurePublisher;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string AccountName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string AccountKey { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Channel { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string CommitHash { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ContainerName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string NugetVersion { get; set; }
|
||||||
|
|
||||||
|
private AzurePublisher AzurePublisherTool
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_azurePublisher == null)
|
||||||
|
{
|
||||||
|
_azurePublisher = new AzurePublisher(AccountName, AccountKey, ContainerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _azurePublisher;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
string targetFolder = $"{AzurePublisher.Product.Sdk}/{Channel}";
|
||||||
|
|
||||||
|
string targetVersionFile = $"{targetFolder}/{CommitHash}";
|
||||||
|
string semaphoreBlob = $"{targetFolder}/publishSemaphore";
|
||||||
|
AzurePublisherTool.CreateBlobIfNotExists(semaphoreBlob);
|
||||||
|
string leaseId = AzurePublisherTool.AcquireLeaseOnBlob(semaphoreBlob);
|
||||||
|
|
||||||
|
// Prevent race conditions by dropping a version hint of what version this is. If we see this file
|
||||||
|
// and it is the same as our version then we know that a race happened where two+ builds finished
|
||||||
|
// at the same time and someone already took care of publishing and we have no work to do.
|
||||||
|
if (AzurePublisherTool.IsLatestSpecifiedVersion(targetVersionFile))
|
||||||
|
{
|
||||||
|
AzurePublisherTool.ReleaseLeaseOnBlob(semaphoreBlob, leaseId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Regex versionFileRegex = new Regex(@"(?<CommitHash>[\w\d]{40})");
|
||||||
|
|
||||||
|
// Delete old version files
|
||||||
|
AzurePublisherTool.ListBlobs(targetFolder)
|
||||||
|
.Where(s => versionFileRegex.IsMatch(s))
|
||||||
|
.ToList()
|
||||||
|
.ForEach(f => AzurePublisherTool.TryDeleteBlob(f));
|
||||||
|
|
||||||
|
// Drop the version file signaling such for any race-condition builds (see above comment).
|
||||||
|
AzurePublisherTool.DropLatestSpecifiedVersion(targetVersionFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CopyBlobs(targetFolder);
|
||||||
|
|
||||||
|
string cliVersion = Utils.GetVersionFileContent(CommitHash, NugetVersion);
|
||||||
|
AzurePublisherTool.PublishStringToBlob($"{targetFolder}/latest.version", cliVersion);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AzurePublisherTool.ReleaseLeaseOnBlob(semaphoreBlob, leaseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CopyBlobs(string destinationFolder)
|
||||||
|
{
|
||||||
|
Log.LogMessage("Copying blobs to {0}/{1}", ContainerName, destinationFolder);
|
||||||
|
|
||||||
|
foreach (string blob in AzurePublisherTool.ListBlobs(AzurePublisher.Product.Sdk, NugetVersion))
|
||||||
|
{
|
||||||
|
string targetName = Path.GetFileName(blob)
|
||||||
|
.Replace(NugetVersion, "latest");
|
||||||
|
|
||||||
|
string target = $"{destinationFolder}/{targetName}";
|
||||||
|
|
||||||
|
AzurePublisherTool.CopyBlob(blob, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,163 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Microsoft.Build.Framework;
|
|
||||||
using Microsoft.Build.Utilities;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.Build
|
|
||||||
{
|
|
||||||
public class FinalizeBuild : Task
|
|
||||||
{
|
|
||||||
private AzurePublisher _azurePublisher;
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string AccountName { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string AccountKey { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string NugetVersion { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string Channel { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string CommitHash { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string BranchName { get; set; }
|
|
||||||
|
|
||||||
private AzurePublisher AzurePublisherTool
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if(_azurePublisher == null)
|
|
||||||
{
|
|
||||||
_azurePublisher = new AzurePublisher(AccountName, AccountKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _azurePublisher;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Execute()
|
|
||||||
{
|
|
||||||
DoFinalizeBuild();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoFinalizeBuild()
|
|
||||||
{
|
|
||||||
if (CheckIfAllBuildsHavePublished())
|
|
||||||
{
|
|
||||||
string targetContainer = $"{AzurePublisher.Product.Sdk}/{Channel}";
|
|
||||||
string targetVersionFile = $"{targetContainer}/{CommitHash}";
|
|
||||||
string semaphoreBlob = $"{targetContainer}/publishSemaphore";
|
|
||||||
AzurePublisherTool.CreateBlobIfNotExists(semaphoreBlob);
|
|
||||||
string leaseId = AzurePublisherTool.AcquireLeaseOnBlob(semaphoreBlob);
|
|
||||||
|
|
||||||
// Prevent race conditions by dropping a version hint of what version this is. If we see this file
|
|
||||||
// and it is the same as our version then we know that a race happened where two+ builds finished
|
|
||||||
// at the same time and someone already took care of publishing and we have no work to do.
|
|
||||||
if (AzurePublisherTool.IsLatestSpecifiedVersion(targetVersionFile))
|
|
||||||
{
|
|
||||||
AzurePublisherTool.ReleaseLeaseOnBlob(semaphoreBlob, leaseId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Regex versionFileRegex = new Regex(@"(?<CommitHash>[\w\d]{40})");
|
|
||||||
|
|
||||||
// Delete old version files
|
|
||||||
AzurePublisherTool.ListBlobs(targetContainer)
|
|
||||||
.Where(s => versionFileRegex.IsMatch(s))
|
|
||||||
.ToList()
|
|
||||||
.ForEach(f => AzurePublisherTool.TryDeleteBlob(f));
|
|
||||||
|
|
||||||
// Drop the version file signaling such for any race-condition builds (see above comment).
|
|
||||||
AzurePublisherTool.DropLatestSpecifiedVersion(targetVersionFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CopyBlobsToLatest(targetContainer);
|
|
||||||
|
|
||||||
string cliVersion = Utils.GetVersionFileContent(CommitHash, NugetVersion);
|
|
||||||
AzurePublisherTool.PublishStringToBlob($"{targetContainer}/latest.version", cliVersion);
|
|
||||||
|
|
||||||
UpdateVersionsRepo();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AzurePublisherTool.ReleaseLeaseOnBlob(semaphoreBlob, leaseId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckIfAllBuildsHavePublished()
|
|
||||||
{
|
|
||||||
var badges = new Dictionary<string, bool>()
|
|
||||||
{
|
|
||||||
{ "Windows_x86", false },
|
|
||||||
{ "Windows_x64", false },
|
|
||||||
{ "Ubuntu_x64", false },
|
|
||||||
{ "Ubuntu_16_04_x64", false },
|
|
||||||
{ "RHEL_x64", false },
|
|
||||||
{ "OSX_x64", false },
|
|
||||||
{ "Debian_x64", false },
|
|
||||||
{ "CentOS_x64", false },
|
|
||||||
{ "Fedora_23_x64", false },
|
|
||||||
{ "openSUSE_13_2_x64", false }
|
|
||||||
};
|
|
||||||
|
|
||||||
var versionBadgeName = $"{Monikers.GetBadgeMoniker()}";
|
|
||||||
if (!badges.ContainsKey(versionBadgeName))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"A new OS build '{versionBadgeName}' was added without adding the moniker to the {nameof(badges)} lookup");
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<string> blobs = AzurePublisherTool.ListBlobs(AzurePublisher.Product.Sdk, NugetVersion);
|
|
||||||
foreach (string file in blobs)
|
|
||||||
{
|
|
||||||
string name = Path.GetFileName(file);
|
|
||||||
foreach (string img in badges.Keys)
|
|
||||||
{
|
|
||||||
if ((name.StartsWith($"{img}")) && (name.EndsWith(".svg")))
|
|
||||||
{
|
|
||||||
badges[img] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return badges.Values.All(v => v);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CopyBlobsToLatest(string destinationFolder)
|
|
||||||
{
|
|
||||||
foreach (string blob in AzurePublisherTool.ListBlobs(AzurePublisher.Product.Sdk, NugetVersion))
|
|
||||||
{
|
|
||||||
string targetName = Path.GetFileName(blob)
|
|
||||||
.Replace(NugetVersion, "latest");
|
|
||||||
|
|
||||||
string target = $"{destinationFolder}/{targetName}";
|
|
||||||
AzurePublisherTool.CopyBlob(blob, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateVersionsRepo()
|
|
||||||
{
|
|
||||||
string githubAuthToken = EnvVars.EnsureVariable("GITHUB_PASSWORD");
|
|
||||||
string nupkgFilePath = Dirs.Packages;
|
|
||||||
string branchName = BranchName;
|
|
||||||
string versionsRepoPath = $"build-info/dotnet/cli/{branchName}/Latest";
|
|
||||||
|
|
||||||
VersionRepoUpdater repoUpdater = new VersionRepoUpdater(githubAuthToken);
|
|
||||||
repoUpdater.UpdatePublishedVersions(nupkgFilePath, versionsRepoPath).Wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
66
build_projects/dotnet-cli-build/GenerateChecksums.cs
Normal file
66
build_projects/dotnet-cli-build/GenerateChecksums.cs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Build.Tasks
|
||||||
|
{
|
||||||
|
public class GenerateChecksums : Task
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An item collection of files for which to generate checksums. Each item must have metadata
|
||||||
|
/// 'DestinationPath' that specifies the path of the checksum file to create.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public ITaskItem[] Items { get; set; }
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
foreach (ITaskItem item in Items)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string destinationPath = item.GetMetadata("DestinationPath");
|
||||||
|
if (string.IsNullOrEmpty(destinationPath))
|
||||||
|
{
|
||||||
|
throw new Exception($"Metadata 'DestinationPath' is missing for item '{item.ItemSpec}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(item.ItemSpec))
|
||||||
|
{
|
||||||
|
throw new Exception($"The file '{item.ItemSpec}' does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.LogMessage(
|
||||||
|
MessageImportance.High,
|
||||||
|
"Generating checksum for '{0}' into '{1}'...",
|
||||||
|
item.ItemSpec,
|
||||||
|
destinationPath);
|
||||||
|
|
||||||
|
using (FileStream stream = File.OpenRead(item.ItemSpec))
|
||||||
|
{
|
||||||
|
HashAlgorithm hashAlgorithm = SHA512.Create();
|
||||||
|
byte[] hash = hashAlgorithm.ComputeHash(stream);
|
||||||
|
string checksum = BitConverter.ToString(hash).Replace("-", string.Empty);
|
||||||
|
File.WriteAllText(destinationPath, checksum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// We have 2 log calls because we want a nice error message but we also want to capture the
|
||||||
|
// callstack in the log.
|
||||||
|
Log.LogError("An exception occurred while trying to generate a checksum for '{0}'.", item.ItemSpec);
|
||||||
|
Log.LogMessage(MessageImportance.Low, e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
build_projects/dotnet-cli-build/UpdateVersionsRepo.cs
Normal file
27
build_projects/dotnet-cli-build/UpdateVersionsRepo.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Build
|
||||||
|
{
|
||||||
|
public class UpdateVersionsRepo : Task
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string BranchName { get; set; }
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
string githubAuthToken = EnvVars.EnsureVariable("GITHUB_PASSWORD");
|
||||||
|
string nupkgFilePath = Dirs.Packages;
|
||||||
|
string branchName = BranchName;
|
||||||
|
string versionsRepoPath = $"build-info/dotnet/cli/{branchName}/Latest";
|
||||||
|
|
||||||
|
VersionRepoUpdater repoUpdater = new VersionRepoUpdater(githubAuthToken);
|
||||||
|
repoUpdater.UpdatePublishedVersions(nupkgFilePath, versionsRepoPath).Wait();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -126,8 +126,11 @@ docker run $INTERACTIVE -t --rm --sig-proxy=true \
|
||||||
-e NUGET_FEED_URL \
|
-e NUGET_FEED_URL \
|
||||||
-e NUGET_API_KEY \
|
-e NUGET_API_KEY \
|
||||||
-e GITHUB_PASSWORD \
|
-e GITHUB_PASSWORD \
|
||||||
-e STORAGE_KEY \
|
-e ARTIFACT_STORAGE_KEY \
|
||||||
-e STORAGE_ACCOUNT \
|
-e ARTIFACT_STORAGE_ACCOUNT \
|
||||||
-e STORAGE_CONTAINER \
|
-e ARTIFACT_STORAGE_CONTAINER \
|
||||||
|
-e CHECKSUM_STORAGE_KEY \
|
||||||
|
-e CHECKSUM_STORAGE_ACCOUNT \
|
||||||
|
-e CHECKSUM_STORAGE_CONTAINER \
|
||||||
$DOTNET_BUILD_CONTAINER_TAG \
|
$DOTNET_BUILD_CONTAINER_TAG \
|
||||||
$BUILD_COMMAND "$@"
|
$BUILD_COMMAND "$@"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue