获取压缩TFS 2015(vNext)通过powershell构建输出日志(就像构建后的下载链接一样)

时间:2016-09-27 04:15:49

标签: powershell logging tfs zip

我想知道是否有人有PowerShell脚本通过Rest API for TFS 2015(vNext)下载此构建ID的所有当前构建日志(直到当前步骤),为每个记录创建单独的文本文件构建步骤,并压缩所有文本文件?

或者,如果已经有办法让下载URL执行“将所有日志压缩为zip”链接(在构建之后),那么如何在PowerShell脚本中获取它?

我可以花一点时间自己做这件事,但我想我会问,因为某人必须已经拥有此功能,如果你这样做,请分享。

3 个答案:

答案 0 :(得分:3)

回答我自己的帖子:

好的,所以我继续花时间编写一个PowerShell脚本,它完全符合我的要求,这基本上复制了"将所有日志下载为zip" TFS 2015(vNext)的链接。

您可以将其放入正在运行的构建中的一个步骤,也可以将其修改为在运行构建之后作为构建定义中的构建后步骤运行。

不同之处在于,在正在运行的构建中,它只会向您提供日志,直到此PowerShell脚本步骤之前的步骤。使用此PowerShell脚本的后期构建定义允许您获取所有日志。

我选择不使用后期构建定义,因为此步骤是我正在运行的构建定义中的最后一步,并且后面的步骤对我来说是无关紧要的(例如,我的最后两个步骤是CreateZippedLogs)。 ps1并将Zipped Logs复制到文件服务器。)

仅供参考,我在撰写本文时使用的是内部部署TFS 2015(更新3)。使用适合您情况的相应授权凭据替换Invoke-RestMethod行中的-UseDefaultCredentials。

这是CreateZippedLogs.ps1,根据自己的喜好进行修改,然后享受:

[CmdletBinding()]
param()

# Create base URI for the REST API
$baseURI = $Env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI + $Env:SYSTEM_TEAMPROJECT + "/_apis/"

# Get Build ID from the environment variable
$buildID = $Env:BUILD_BUILDID

# Build Timeline URI for $Env:BUILD_BUILDID
$buildTimelineURI = "$baseURI/build/builds/$buildID/timeline`?api-version=2.0"

# Output intent to create Zipped Log content for this build id
Write-Output "Attempting to create Zipped Log content for Build ID $buildID from URL: ""$buildTimelineURI"""

# Get sorted build timeline (ascending by default)
$buildTimeline = (Invoke-RestMethod -Uri $buildTimelineURI -UseDefaultCredentials).records | Sort-Object { $_.log.id }

# Get log count
$logsCount = $buildTimeline.Count  # the number of timeline records (i.e. logs in the array)

# Remove sub-staging folder recursively for the logs
# Note: $Env:My_BuildLabel is defined as "$Env:BUILD_DEFINITIONNAME`_$Env:BUILD_BUILDNUMBER" for my builds; use whatever name is appropriate for your builds
$singleLogFileFolder = "$Env:BUILD_ARTIFACTSTAGINGDIRECTORY\$Env:My_BuildLabel`_Logs"
Remove-Item "$singleLogFileFolder" -recurse -ErrorAction SilentlyContinue -Verbose

# Remove any previously created Zip file with the same filename that we are about to create
Remove-Item "$singleLogFileFolder.zip" -ErrorAction SilentlyContinue -Verbose

# If number of logs in the array is > 0, create sub-staging folders for the logs
if ($logsCount -gt 0)
{
    # First, a top-level folder to hold all logs in a single .txt file
    New-Item -ItemType directory -Path "$singleLogFileFolder" -ErrorAction Stop -Verbose
    $stepLogsSingleFile = "$singleLogFileFolder\1_Build.txt"

    # Second, a subfolder to hold individual build step log files
    $stepLogFilesFolder = "$singleLogFileFolder\Build"
    New-Item -ItemType directory -Path "$stepLogFilesFolder" -ErrorAction Stop -Verbose
}
else
{
    # Output that there were no logs found for this Build ID
    Write-Output "No logs found for Build ID $buildID"
    Exit 0  # Exit successfully
}

# Get list of invalid filename characters (in a regex string)
$invalidFilenameCharactersRegexString = "[{0}]+" -f [regex]::Escape(([System.IO.Path]::GetInvalidFileNameChars() -join ""))

# Output progress
Write-Output "Getting Log content and saving to files:"

# Iterate through each record in the build timeline array
foreach ($timelineRecord in $buildTimeline)
{
    # Extract url for each log
    $logURL = $timelineRecord.log.url

    # Don't try to get empty log URL's
    if ([string]::IsNullOrWhiteSpace($logURL))
    {
        continue
    }

    # Get log content
    $logContent = (Invoke-RestMethod -Uri $logURL -UseDefaultCredentials).value

    # Append step log output to the single file (not -Verbose because it duplicates information)
    $logContent | Out-File "$stepLogsSingleFile" -Append

    # Get log id
    $logID = $timelineRecord.log.id

    # Remove any invalid filename characters from the step name
    $stepName = $timelineRecord.name -replace "$invalidFilenameCharactersRegexString", ""

    # Create a step log output filename appropriate to the step number and name
    $stepLogFile = "$stepLogFilesFolder\$logID`_$stepName`.txt"

    # Save the step log content
    $logContent | Out-File "$stepLogFile" -Verbose
}

Write-Output "Compressing Log files:"
if ($PSVersionTable.PSVersion.Major -lt 5)
{
    Add-Type -assembly "system.io.compression.filesystem"
    [io.compression.zipfile]::CreateFromDirectory($singleLogFileFolder, $singleLogFileFolder + ".zip")
}
else
{
    Compress-Archive "$singleLogFileFolder\*" -DestinationPath "$singleLogFileFolder.zip" -Verbose
}

# ----------------------------------------------------------

# Remove temporary sub-staging folder recursively for the logs (don't leave it hanging around)
Write-Output "Removing temporary Log folders and files:"
Remove-Item "$singleLogFileFolder" -recurse -ErrorAction SilentlyContinue -Verbose

答案 1 :(得分:0)

您可以在脚本中将TFS REST API直接用于get Build Logs

GET https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/logs
  

实例:VS Team Services帐户({account} .visualstudio.com)或TFS   服务器({server:port})。

答案 2 :(得分:0)

没有任何方法可以直接下载压缩日志,您需要通过Rest API获取它们并将其保存到文本文件然后压缩文件。附上我的代码供您参考,获取整个日志并将其保存到一个文本文件中:

$buildID = "12345"
$project = "ProjectName"
$projecturi = "https://xxxxxxxxxx/"

# Setting up basic authentication
$username="username"
$password="password"

$basicAuth= ("{0}:{1}"-f $username,$password)
$basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth=[System.Convert]::ToBase64String($basicAuth)
$headers= @{Authorization=("Basic {0}"-f $basicAuth)}

$url= $projecturi + $project + "/_apis/build/builds/" + $buildID + "/logs?api-version=2.0"

$responseBuild = Invoke-RestMethod -Uri $url -headers $headers -Method Get | select value

$logid = $responseBuild.value.Count - 1;

$logurl = $projecturi + $project + "/_apis/build/builds/" + $buildID + "/logs/" + $logid;

$getlog = Invoke-RestMethod -Uri $logurl -headers $headers -Method Get 

$getlog | Out-File "D:\Temp\$buildID.txt"