TFS Release Download Artifacts

Team Service Erweiterung – Download Artifacts

Mit dem Tool Download Artifacts können Sie einzelne Artifacts auf den lokalen Zielsystemen, auf dem die Build Agent installiert sind, bereitstellen.

Über den folgenden Link bekommen Sie das komplette Paket Download Artifacts – als ZIP bereitgestellt. Das Skript ist kostenfrei und kann nach Ihren wünschen angepasst werden. Downlaod Team Service Erweiterung Downlaod Artifacts

a455700affce9c2b29d9b85067622640
  • Als Vorraussetzung ist wie beschrieben, dass der Build Agent auf dem Zielsystem installiert ist. Eine Anleitung für die Konfiguration finden Sie hier: Deploy an agent on Windows
  • Entpacken Sie das Zip und Importieren den PowerShell Task. Eine Beschreibung für den Import finden Sie hier:  Eigene TFS Build / Release Aufgaben bereitstellen
  • Erstellen Sie eine neue Release definition. Infos finden Sie hier: Define your CD release process
  • Fügen Sie jetzt Ihre Aufgaben wie SPS Deploy hinzu.
  • Geben Sie nun alle notwendigen Werte ein und führen die Bereitstellung aus.

Folgende Parameter können Sie mitgeben:

  • : Artifactsnamen
Team Service Erweiterung Download Artifacts
Team Service Erweiterung Download Artifacts
[CmdletBinding(DefaultParameterSetName = 'None')]
param(
    [Parameter()]
    [string]$ArtifactNames = "*",
    [Parameter()]
    [string]$ArtifactDestinationFolder  
)

$ErrorActionPreference = "Stop"
Write-Output "Artifact Names: $ArtifactNames"
Write-Output "Artifact Destination Folder: $ArtifactDestinationFolder"

$buildDefinitionName = $Env:BUILD_DEFINITIONNAME
if ([string]::IsNullOrEmpty($ArtifactDestinationFolder))
{
	$ArtifactDestinationFolder = $Env:SYSTEM_DEFAULTWORKINGDIRECTORY
}

Add-Type -assembly 'system.io.compression.filesystem'
#--------------------------CreateCleanDirectory----------------------

function CreateOrCleanDirectory($DirectoryPath)
{
    if ([IO.Directory]::Exists($DirectoryPath)) 
    { 
	    $DeletePath = $DirectoryPath + "\*"
	    Remove-Item $DeletePath -recurse -Force
		[IO.Directory]::CreateDirectory($DirectoryPath) | Out-Null
    } 
    else
    { 
	    [IO.Directory]::CreateDirectory($DirectoryPath) | Out-Null
	    
    } 
}

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$artifactNamesArray = [regex]::split($ArtifactNames, ";")

$vssEndPoint = Get-ServiceEndPoint -Name "SystemVssConnection" -Context $distributedTaskContext
$personalAccessToken = $vssEndpoint.Authorization.Parameters.AccessToken
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization" ,"Bearer $personalAccessToken")

$tfscollection = $Env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI	
$tfsUrl = $Env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI 
$relAPIUrl = $Env:SYSTEM_TEAMFOUNDATIONSERVERURI + $Env:SYSTEM_TEAMPROJECT
$releaseId = $Env:RELEASE_RELEASEID

$releaseInfoURI = $relAPIUrl +'/_apis/release/releases/' + $releaseId + '?api-version=3.0-preview.2'

#get the release
Write-Output "Get Releseinfo: Invoke-RestMethod -Uri $releaseInfoURI -Method GET -Headers $headers"
$releaseInfo = Invoke-RestMethod -Uri $releaseInfoURI -Method GET -Headers $headers

# Clean Destination
CreateOrCleanDirectory -DirectoryPath $ArtifactDestinationFolder

foreach ($linkedArtifact in $releaseInfo.artifacts)
    {
    <#$BuildDefUri = ($tfsURL + '/_apis/build/definitions?api-version=2.0&name=' + $buildDefinitionName)

    #Get Build Defintion ID
    Write-Host "REST Call [$BuildDefUri]"
    $buildDefinition = Invoke-RestMethod -Uri $BuildDefUri -Method GET -Headers $headers #-UseDefaultCredentials
    $buildDefinitionId = ($buildDefinition.value).id;#>
    $buildDefinitionId = $linkedArtifact.definitionReference.definition.id
    $buildDefinitionName = $linkedArtifact.alias
    $buildDefinitionProject = $linkedArtifact.definitionReference.project.name
    Write-Output "Build Def.Id: [$buildDefinitionId]"
    Write-Output "Build Def.Name: [$buildDefinitionName]"
    Write-Output "Build Def.Project Name: [$buildDefinitionProject]"
    
    $buildId = $linkedArtifact.definitionReference.version.id
    Write-Host "Build Id: [$buildId]"

    #get artifacts
    $buildArtifactsURI = $tfsURL + $buildDefinitionProject + '/_apis/build/builds/' + $buildId + '/artifacts?api-version=2.0'
    Write-Output "REST Call [$buildArtifactsURI]"
    $buildArtifacts = Invoke-RestMethod -Uri $buildArtifactsURI -Method GET -Headers $headers #-UseDefaultCredentials

    $dropDestination = join-path $ArtifactDestinationFolder $buildDefinitionName

    # Clean Destination
    CreateOrCleanDirectory -DirectoryPath $dropDestination

    foreach($buildArtifact in $buildArtifacts.value)
    {
        $buildartifactFullName = join-path $buildDefinitionName $buildArtifact.name # Createing full artifact naem similar to ArtfactSourceAlias\Drop1

        foreach($artifactPathName in $artifactNamesArray) # Try for each Artifact Path
        {
            $artifactPathPartsArray = [regex]::split($artifactPathName, "\\")

            if(($artifactPathName -eq "*") -or ($artifactPathName -eq $buildartifactFullName) -or (($artifactPathPartsArray[0] -eq $buildDefinitionName ) -and ($artifactPathPartsArray[1] -eq $buildArtifact.name)))
            {
                <# 
                    Only * (default) as artifat path allow all artifacts download. 
                    Artifact name allows to download given artifact. Multiple artifacts can be specified with pattern Drop1;Drop2
                    Artifact name with subpath allows to download sub item of a given artifact. Multiple can be specified with pattern ArtifactsourceAlias\Drop1\MyWebProj;ArtifactsourceAlias\Drop1\ReleaseNote.html;ArtifactsourceAlias\Drop2;ArtifactsourceAlias\Drop3\MyWebProj2

                    Wild cards in paths are NOT Supported. * value as default supported to specify all artifacts.
                #>
                Write-Output "Downloading artifact: " + $artifactPathName
            
                if($buildArtifact.resource.type -eq "FilePath")
                {
                    # UNC Path
                    $droppath = $buildArtifact.resource.downloadUrl -replace "file://","\\"
                    $droppath = $droppath -replace "%20"," "
                    $droppath = $droppath -replace "/","\"                    

                    
                    if (($artifactPathName -ne "*") -and ($artifactPathName -ne $buildartifactFullName))
                    {
                        for($i=1;$i -lt ($artifactPathPartsArray.Length);$i++)
                        {
                            $dropDestination = Join-Path $dropDestination $artifactPathPartsArray[$i]
                            $droppath = Join-Path $droppath $artifactPathPartsArray[$i]
                        }

                        #Subpath used - Create the destination path by drop folder
                        if (-not([IO.Directory]::Exists($dropDestination))) 
                        {
                            Write-Output "Creating destination path: " + $dropDestination
                            [IO.Directory]::CreateDirectory($dropDestination) | Out-Null
                        }
                    
                    }
                    else
                    {
                        $droppath = Join-Path $droppath $buildArtifact.name # Creating drop path with specified artifact path
                    }
                
					$start_time = Get-Date
                    Write-Output "Downloading run: Copy-Item -Path $droppath -Destination $dropDestination -Recurse -Verbose"		
                    Copy-Item -Path $droppath -Destination $dropDestination -Recurse -Verbose
                    Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
                }
                else
                {   # Drop available as server
                    
                    if (($artifactPathName -eq "*") -or ($artifactPathName -eq $buildartifactFullName))
                    {
                        $dropArchiveDestination = Join-path $dropDestination ("{0}.zip" -f $buildArtifact.name)
                        $droppath = $buildArtifact.resource.downloadUrl # If only artifact name default download url can be used
                    }
                    else
                    {
                        $tempArtifactPath= $buildArtifact.name
                        for($i=2;$i -lt ($artifactPathPartsArray.Length);$i++)
                        {
                            $tempArtifactPath = Join-Path $tempArtifactPath $artifactPathPartsArray[$i]
                            Write-Output "temp artifact path: " + $tempArtifactPath
                        }

                        $dropArchiveDestination = Join-path $dropDestination ("{0}.zip" -f ($tempArtifactPath -replace "\\", "."))
                        # for sub path generate download url. Using the data ID.
                        $droppath =  $tfscollection + "_apis/resources/Containers/" + $buildArtifact.resource.data.Split("/")[1] + "?itemPath=" + ($tempArtifactPath -replace "\\", "%2F") + "&`$format=zip"
                    }

					$start_time = Get-Date
                    Write-Output "Downloading run: Invoke-WebRequest -uri $droppath -OutFile $dropArchiveDestination -Headers $headers"
                    Invoke-WebRequest -uri $droppath -OutFile $dropArchiveDestination -Headers $headers #-UseDefaultCredentials
                    Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
                
                    Write-Output "Extracting artifact: " + $buildArtifact.name
                    Write-Output "Extracting to: " + $dropDestination
                    [io.compression.zipfile]::ExtractToDirectory($dropArchiveDestination, $dropDestination)
                    Write-Output "Extracting completed for: {0} to: {1}" -f $buildArtifact.name, $dropDestination
                }
            }
        }
    }
}
Write-Output "##vso[task.complete result=Succeeded;]DONE"

 



Weitere Links:

Release Management

Team Service Erweiterung – Application Pool Start / Stop

Team Service Erweiterung – Deploy

Team Service Erweiterung – Remote Deploy