我该如何设置TeamCity CI,以便解压Xamarin组件?

8
在Visual Studio中一切正常,且创建了一个包含适当dll的Components目录。然而,TeamCity无法检索Android Support Library dlls,因为还需要加载Xamarin VS插件才能触发恢复操作。对于Xamarin来说,相当于nuget package restore的操作是使用xamarin-component。我已经将xamarin-component.exe放置在了C:\Windows目录下。为了配置TeamCity,我在前面添加了一个命令行构建步骤。
Command executable: xamarin-component 
Command parameters: restore mysolution.sln

TeamCity作为NT Authority\System运行。因此,使用PsExec,

psexec -i -s %SystemRoot%\system32\cmd.exe

如果我运行 'xamarin-component login'

INFO (login): Computed cookie jar path: C:\Windows\system32\config\systemprofile\.xamarin-credentials 
INFO (login): Computed cookie jar path: C:\Windows\system32\config\systemprofile\.xamarin-credentials 
INFO (login): Credentials successfully stored.

当我在cmd中打开我的解决方案并尝试还原时,我会下载组件,并出现Json解析错误。这与我在TeamCity中遇到的错误相同。
如果使用“管理员”(将凭据存储在C:\Users\Administrator中),我也会遇到这个错误。之前我使用个人帐户时是可以的。然而,一旦我删除了C:\Users\tim\AppData\Local\Xamarin\Cache\Components,就会出现相同的问题。Fiddler显示,我们没有像输入无效令牌时那样收到Json返回结果,而是收到一个302重定向,说对象已经被移动到“这里”。这里指的是xamarin登录页面,显然不是Json。
尝试过:
1. 将COOKIE_JAR_PATH设置为C:\Users\tim.xamarin-credentials - xpkg可以识别,但出现相同的错误 2. 从Config\system32复制.xamarin-credentials到D:\,将COOKIE_JAR_PATH设置为D:.xamarin-credentials - xpkg可以识别,但出现相同的错误 3. 将.xamarin-credentials移到C:\,设置COOKIE_JAR_PATH - 出现相同的错误 4. 使用NT Authority重新登录,将COOKIE_JAR_PATH设置为C:.xamarin-credentials - 出现相同的错误 我现在的临时想法是找出NT Authority xamarin-component查找Cache的位置,并将文件放在那里。
C:\Windows\system32\config\systemprofile\AppData\Local\Xamarin\Cache\Components\xamandroidsupportv4-18-4.18.1.xam

我的xamarin-component版本是0.99 - 为了达到100,我们会更加努力...
4个回答

3
作为一种hack方法,我复制了缓存文件夹从

C:\Users\tim\AppData\Local\Xamarin 

为了

C:\Windows\system32\config\systemprofile\AppData\Local\Xamarin\

绕过了与Xamarin服务器的通信。

更新。我怀疑这可能是他们服务器端的错误链接或设置问题。当调用xamarin-component恢复时,会向其发出调用

GET /api/available_versions?alias=xamandroidsupportv4-18 HTTP/1.1

当“here”表示不存在时,返回“对象移动到此处”。

哦不

如果在删除缓存和组件文件夹(位于解决方案旁边)后启动Visual Studio,则Xamarin会调用

GET /api/download/xamandroidsupportv4-18/4.18.1 HTTP/1.0

这里有一个看起来类似的对象移动到了,但这次它将你引导到了xamarin-components.s3.amazonaws.com/。

哦,是的

GET /fdca922d2b77799fe208a08c9f3444fe/xamandroidsupportv4-18-4.18.1.xam HTTP/1.0

也许是有些变动,或者是available_versions API已经发生了改变。

好消息!我已经向Xamarin报告了这个错误,他们已经找到了问题所在。他们预计修复后的API将在本周末之前可用。 - Steve Rukuts

3

我曾经尝试从system32路径正确加载cookie jar,但是遇到了问题。我认为这是一种路径虚拟化问题,我还不太理解如何解决。

最终,我添加了一个环境变量供工具读取(我是Xamarin的主要作者),该变量指定了要读取的cookie jar路径,这解决了其他使用TeamCity的人的问题。环境变量名为COOKIE_JAR_PATH

可以从TeamCity的环境设置中设置它,以指向系统32个人资料目录之外的cookie jar路径(在我的原始测试中,我将其放在C驱动器的根目录下,但实际上它可以放在任何地方)。


谢谢Bojan。我希望能听到你的回复。我会尝试一下。建议在下一个版本中内置警告,或者提供指定cookie jar位置的选项。 - tofutim
是的,我得花一些时间来改善工具的错误处理和文档。 - Bojan Rajkovic
无法将NT Authority生成的版本从Config\systemprofile复制到D:\。从Fiddler来看,我被重定向了,而不是获取JSON。 - tofutim
你可以在另一台机器上创建 cookie jar,然后将其复制过来。我不建议尝试从 Config\systemprofile 处复制它到其他地方。这是一个简单的文本文件,你可以通过记事本创建。 - Bojan Rajkovic
这很有趣。当不使用COOKIE_JAR_PATH时,日志会有一点不同,尽管两者都以Json错误结束。当使用system32路径时,“计算cookie jar路径”三次,但在使用C:.xamarin-credentials中的路径时仅一次。 - tofutim
显示剩余5条评论

2
非常感谢您提出这个问题并对它进行回答。我并不喜欢在构建节点上存储授权cookie或手动复制缓存的想法,因此我想出了自己的解决方案,通过一个快速的PowerShell脚本来模拟xamarin-component.exe restore操作的行为,从而绕过了这个问题。
param
(
    [Parameter(Mandatory=$true)]
    $authCookie,

    [Parameter(Mandatory=$true)]
    $componentDirectory,

    [Parameter(Mandatory=$true)]
    $project
)

[void]([System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem'))
$xml = [xml] $(cat $project);
$components = $xml.Project.ItemGroup.XamarinComponentReference | ? { $_.Include.Length -gt 0 } | % { $_.Include };

if (!(test-path $componentDirectory))
{
    echo "$componentDirectory didn't exist, so it was created.";
    [void](mkdir $componentDirectory);
}

foreach ($component in $components)
{
    $source = "http://components.xamarin.com/download/$component";
    $destination = "$componentDirectory\$component.zip";

    if (test-path $destination)
    {
        echo "$destination already exists, skipping...";
        continue;
    }

    echo "Downloading $component from $source to $destination...";

    $client = New-Object System.Net.WebClient
    $client.Headers.Add([System.Net.HttpRequestHeader]::Cookie, "XAM_AUTH=$authCookie");

    try
    {
        $client.DownloadFile($source, $destination);
    }
    catch
    {
        # The error message will be on one of these lines hopefully:
        write-error "Failed to download! Errors are below:";
        write-error $_
        write-error $_.Exception
        write-error $_.Exception.InnerException
        write-error $_.Exception.InnerException.InnerException
        exit 1;
    }

    if (!(test-path $destination))
    {
        write-error "$destination doesn't exist - the download must have failed!";
        exit 1;
    }

    echo "Decompressing $source to $componentDirectory"
    [System.IO.Compression.ZipFile]::ExtractToDirectory($destination, $componentDirectory)
    echo ""
}

echo "Done!";
-authCookie参数可以从浏览器中的XAM_AUTH cookie或者您主目录中的.xamarin-credentials "cookiejar"中提取。将其参数化可以将其存储为TeamCity中的秘密变量,这样很好。 componentDirectory参数必须是组件目录的完整路径 - 如果不存在,则会创建该目录。 project参数应该是要恢复包的项目路径 - 如果有多个需要此操作的项目,则必须为每个项目执行脚本。不要指定解决方案,因为它无法工作。
不幸的是,这对Xamarin的反复无常并不太有韧性 - 简单的API更改可能会使其无用,因此最好的解决方案显然是等待Xamarin修复此问题。我向Xamarin支持发送了电子邮件以抱怨这个问题,但我不认为我会得到及时的回复(他们似乎非常忙碌)。希望这有用!

0
创建目录并将该目录路径放入环境变量XAMARIN_CACHEPATH中。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接