好的,所以我与微软的 VSTS 团队就这个问题进行了长时间的交谈,总而言之……
微软:
我们理解您对这个领域的不满,一个大项目是
即将启动以解决此问题
...
我就是我,想出了一些“实现它的窍门”。
由于某种奇怪的原因,我设法弄清楚构建框也不能是您正在部署的同一台服务器(不知道为什么),但发现我编写了一个简单的控制台应用程序,并获得了一些额外的反馈微软的表现相当不错。
它甚至可以将进度报告回进程,并可以将部署中的异常记录为异常,以便通过调用“内部命令”来使构建失败(通过向团队致敬的方式,这是如何工作的)。
这里有一些 hack,它并不完美,但希望它能对其他人有所帮助,我之所以这样称呼它是因为它是在我的 repo 中构建的代码的一部分,因此我可以在构建过程中添加一个步骤从构建输出中调用它,传递我要部署到的环境名称。
这在 tern 中抓取所有包(根据上面的设置)并使用它们的发布配置文件来确定包需要去哪里并将它们发送到正确的服务器以进行部署......
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
namespace Deploy
{
class Program
{
static string msDeployExe = @"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";
static void Main(string[] args)
{
var env = args[0];
var buildRoot = Path.Combine(Assembly.GetExecutingAssembly().Location.Replace("Deploy.exe", ""), env);
//var commands = GetCommands(buildRoot);
var packages = new DirectoryInfo(buildRoot).GetFiles("*.zip", SearchOption.AllDirectories);
bool success = true;
for (int i = 0; i < packages.Length; i++)
{
if (!Deploy(packages[i], env)) success = false;
Console.WriteLine("##vso[task.setprogress]" + (int)(((decimal)i / (decimal)packages.Length) * 100m));
}
Console.WriteLine("##vso[task.setprogress]100");
if(success) Console.WriteLine("##vso[task.complete result=Succeeded]");
else Console.WriteLine("##vso[task.complete result=SucceededWithIssues]");
}
static bool Deploy(FileInfo package, string environment)
{
bool succeeded = true;
Console.WriteLine("Deploying " + package.FullName);
var procArgs = new ProcessStartInfo
{
FileName = msDeployExe,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
Arguments =
"-source:package='" + package.FullName + "' " +
"-dest:auto,ComputerName='" + environment + ".YourDomain.com',UserName='deployment user',Password='password',AuthType='ntlm',IncludeAcls='False' " +
"-verb:sync " +
"-disableLink:AppPoolExtension " +
"-disableLink:ContentExtension " +
"-disableLink:CertificateExtension " +
"-setParamFile:\"" + package.FullName.Replace("zip", "SetParameters.xml") + "\""
};
try
{
Console.WriteLine(msDeployExe + " " + procArgs.Arguments);
using (var process = Process.Start(procArgs))
{
var result = process.StandardOutput.ReadToEnd().Split('\n');
var error = process.StandardError.ReadToEnd();
process.WaitForExit();
if (!string.IsNullOrEmpty(error))
{
Console.WriteLine("##vso[task.logissue type=error]" + error);
succeeded = false;
}
foreach (var l in result)
if (l.ToLowerInvariant().StartsWith("error"))
{
Console.WriteLine("##vso[task.logissue type=error]" + l);
succeeded = false;
}
else
Console.WriteLine(l);
}
}
catch (Exception ex) {
succeeded = false;
Console.WriteLine("##vso[task.logissue type=error]" + ex.Message);
Console.WriteLine("##vso[task.logissue type=error]" + ex.StackTrace);
}
return succeeded;
}
}
}