如何通过Powershell命令Invoke-RESTMethod从CircleCI下载工件



我正在尝试从Powershell中的CircleCI获取工件并返回不熟悉的数据格式?

Powershell喜欢将API的JSON响应自动转换为PSCustomObject。这通常是我想要的。

以下是我尝试获取干净数据的示例。

Add the necessary .NET assembly
Add-Type -AssemblyName System.Net.Http
Create the HttpClient object
$client = New-Object -TypeName System.Net.Http.Httpclient
Get the web content.
$task = $client.GetByteArrayAsync(“https://circleci.com/api/v1.1/project/$vcs_type/$username/$project/$build_number/artifacts?circle-token=$CIRCLE_TOKEN”)
Wait for the async call to finish
$task.wait();

结果:

(({
:path “src./file1.txt”,
:pretty-path “src/file1.txt”,
:node-index 0,
:url “https://15-198716507-gh.circle-artifacts.com/0/src/file1.txt”
} {
:path “src/file2.txt”,
:pretty-path “src/file2.txt”,
:node-index 0,
:url “https://15-198716507-gh.circle-artifacts.com/0/src/file2.txt”
}…continued

如您所见,这不是JSON或YAML。让我们尝试内置的PowerShell工具,如Invoke-RestMethod。

Invoke-RESTMethod -uri https://circleci.com/api/v1.1/project/$vcs_type/$username/$project/$build_number/artifacts?circle-token=$CIRCLE_TOKEN -Method GET
**Output:**
({
:path “src/file1.txt”,
:pretty-path “src/file1.txt”,
:node-index 0,
:url “https://15-198716507-gh.circle-artifacts.com/0/src/file1.txt”
} {
:path “src/file2.txt”,
:pretty-path “src/file2.txt”,
:node-index 0,
:url “https://15-198716507-gh.circle-artifacts.com/0/src/file2.txt”
}…continued

当相同的输出。我从Invoke-RestMethod文档中知道PS看到JSON并将其自动转换为PS对象。也许它正在转换我不熟悉的数据类型?我发现PowerShell获得EDN类型很奇怪,而PowerShell之外的所有其他尝试都是JSON。

也许他们应该更新 API 以默认使用 JSON 回复 PS 请求。

PowerShell无法获取JSON数据有什么问题?

这是EDN,直到CircleCI回答了关于这个话题的问题才知道这一点。因此,如果您使用PowerShell从CircleCI检索工件,您肯定想知道这一点。

您需要传递一个标头,指定返回的数据类型。

(Accept: application/json)

一位 CircleCI 支持成员告诉我,在 PowerShell 中,您必须指定一个 Accept 标头才能接收 JSON 中的数据。难怪我得到奇怪的输出! 因此,请使用新的接受 JSON 标头重试,我们在下面有此命令。

用于获取 JSON 数据并将其自动转换为 PSObject 的工作命令。

Invoke-RestMethod -Uri https://circleci.com/api/v1.1/project/$vcs_type/$username/$project/$build_number/artifacts?circle-token=$CIRCLE_TOKEN -Method GET -ContentType 'application/json' -UseBasicParsing -Header @{"Accept" = "application/json"}

输出

$response|select path,url
  • 路径
  • ----
  • src.orig/file1.txt
  • src.orig/file2.txt
  • 网址
  • ---
  • https://15-824975-gh.circle-artifacts.com/0/src.orig/file1.txt
  • https://15-824975-gh.circle-artifacts.com/0/src.orig/file2.txt

如果您不执行以下操作,请使用 PS 命令 Invoke-WebRequest/Invoke-RestMethod 接收 EDN 格式的数据。是的,现在我可以根据需要使用数据来下载我的工件。

来自CircleCI的回复为我提供了解决方案。

@burninmedia So what's being sent back is actually a data format called EDN. If you want to return JSON you'll need to pass a header specifying so (Accept: application/json). Thanks!

这是我编写的用于下载所有工件的简单脚本。请确保您正在设置环境变量。

if ($USERNAME -eq $null) { write-host " please add required variable USERNAME" ;exit }
if ($VCS_TYPE -eq $null) { write-host " please add required variable VCS_TYPE" ;exit}
if ($CIRCLE_TOKEN -eq $null) { write-host " please add required variable CIRCLE_TOKEN" ;exit}
if ($BUILD_NUMBER -eq $null) { write-host " please add required variable BUILD_NUMBER" ;exit}
if ($PROJECT -eq $null) { write-host " please add required variable PROJECT" ;exit}
if ($BASEPATH -eq $null) { write-host " please add required variable BASEPATH" ;exit}
$response = Invoke-RestMethod -Uri https://circleci.com/api/v1.1/project/$VCS_TYPE/$USERNAME/$PROJECT/$BUILD_NUMBER/artifacts?circle-token=$CIRCLE_TOKEN -Method GET -ContentType 'application/json' -UseBasicParsing -Header @{"Accept" = "application/json"}
ForEach ($i in $response){
$PATH = $(Split-Path -Path "$($BASEPATH)$($i.path)")
if (-Not ( Test-Path $PATH) ) {
write-host "Creating folder: $($PATH)"
New-Item -ItemType Directory -Force -Path "$($PATH)"
}
Write-Host "Saving artifact $($i.pretty_path) to file: $($BASEPATH)$($i.path)"
Invoke-RestMethod "$($i.url)?circle-token=$($CIRCLE_TOKEN)" -UseBasicParsing -OutFile "$($BASEPATH)$($i.path)"
}

砰砰版

export CIRCLE_TOKEN=':your_token'
echo $(https://circleci.com/api/v1.1/project/$vcs-type/$username/$project/$build_number/artifacts?circle-token=$CIRCLE_TOKEN) > ./artifact_json
for ((i = 0 ; i <= $(jq -c '.[].url ' ./artifact_json|wc -l) ; i++));
do
path=$(jq -c ".[$i].path" ./artifact_json|tr -d '"');
url=$(jq -c ".[$i].url" ./artifact_json|tr -d '"');
pathdir=$(dirname "$path")
echo "URL: $url"
echo "path: $path"
echo "Pathdir: $pathdir"
[ -d $pathdir ] && mkdir -p "$pathdir" #check if folder exists if not mkdir
wget -o $path $url
done
rm ./artifact_json```

最新更新