Skip to content

Commit

Permalink
Out of proc agent system plugins.
Browse files Browse the repository at this point in the history
  • Loading branch information
tingluohuang-test authored and TingluoHuang committed May 4, 2018
1 parent 52f1973 commit dedfd9b
Show file tree
Hide file tree
Showing 32 changed files with 8,347 additions and 28 deletions.
43 changes: 43 additions & 0 deletions src/Agent.PluginHost/Agent.PluginHost.csproj
@@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701</NoWarn>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Agent.Sdk\Agent.Sdk.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="vss-api-netcore" Version="0.5.63-private" />
</ItemGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>portable</DebugType>
</PropertyGroup>

<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">
<DefineConstants>OS_WINDOWS;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_WINDOWS;DEBUG;TRACE</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;TRACE</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">
<DefineConstants>OS_LINUX;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_LINUX;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project>
122 changes: 122 additions & 0 deletions src/Agent.PluginHost/Program.cs
@@ -0,0 +1,122 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading;
using Agent.Sdk;
using Microsoft.TeamFoundation.DistributedTask.WebApi;

namespace Agent.PluginHost
{
public static class Program
{
private static CancellationTokenSource tokenSource = new CancellationTokenSource();
private static string executingAssemblyLocation = string.Empty;

public static int Main(string[] args)
{
Console.CancelKeyPress += Console_CancelKeyPress;

try
{
PluginUtil.NotNull(args, nameof(args));
PluginUtil.Equal(2, args.Length, nameof(args.Length));

string pluginType = args[0];
if (string.Equals("task", pluginType, StringComparison.OrdinalIgnoreCase))
{
string assemblyQualifiedName = args[1];
PluginUtil.NotNullOrEmpty(assemblyQualifiedName, nameof(assemblyQualifiedName));

string serializedContext = Console.ReadLine();
PluginUtil.NotNullOrEmpty(serializedContext, nameof(serializedContext));

AgentTaskPluginExecutionContext executionContext = PluginUtil.ConvertFromJson<AgentTaskPluginExecutionContext>(serializedContext);
PluginUtil.NotNull(executionContext, nameof(executionContext));

AssemblyLoadContext.Default.Resolving += ResolveAssembly;
try
{
Type type = Type.GetType(assemblyQualifiedName, throwOnError: true);
var taskPlugin = Activator.CreateInstance(type) as IAgentTaskPlugin;
PluginUtil.NotNull(taskPlugin, nameof(taskPlugin));
taskPlugin.RunAsync(executionContext, tokenSource.Token).GetAwaiter().GetResult();
}
catch (Exception ex)
{
// any exception throw from plugin will fail the task.
executionContext.Error(ex.ToString());
}
finally
{
AssemblyLoadContext.Default.Resolving -= ResolveAssembly;
}

return 0;
}
else if (string.Equals("command", pluginType, StringComparison.OrdinalIgnoreCase))
{
string assemblyQualifiedName = args[1];
PluginUtil.NotNullOrEmpty(assemblyQualifiedName, nameof(assemblyQualifiedName));

string serializedContext = Console.ReadLine();
PluginUtil.NotNullOrEmpty(serializedContext, nameof(serializedContext));

AgentCommandPluginExecutionContext executionContext = PluginUtil.ConvertFromJson<AgentCommandPluginExecutionContext>(serializedContext);
PluginUtil.NotNull(executionContext, nameof(executionContext));

AssemblyLoadContext.Default.Resolving += ResolveAssembly;
try
{
Type type = Type.GetType(assemblyQualifiedName, throwOnError: true);
var commandPlugin = Activator.CreateInstance(type) as IAgentCommandPlugin;
PluginUtil.NotNull(commandPlugin, nameof(commandPlugin));
commandPlugin.ProcessCommandAsync(executionContext, tokenSource.Token).GetAwaiter().GetResult();
}
catch (Exception ex)
{
// any exception throw from plugin will fail the command.
executionContext.Error(ex.ToString());
}
finally
{
AssemblyLoadContext.Default.Resolving -= ResolveAssembly;
}

return 0;
}
else
{
throw new ArgumentOutOfRangeException(pluginType);
}
}
catch (Exception ex)
{
// infrastructure failure.
Console.Error.WriteLine(ex.ToString());
return 1;
}
finally
{
Console.CancelKeyPress -= Console_CancelKeyPress;
}
}

private static Assembly ResolveAssembly(AssemblyLoadContext context, AssemblyName assembly)
{
string assemblyFilename = assembly.Name + ".dll";
if (string.IsNullOrEmpty(executingAssemblyLocation))
{
executingAssemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
return context.LoadFromAssemblyPath(Path.Combine(executingAssemblyLocation, assemblyFilename));
}

private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
tokenSource.Cancel();
}
}
}
47 changes: 47 additions & 0 deletions src/Agent.Plugins/Agent.Plugins.csproj
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701</NoWarn>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Agent.Sdk\Agent.Sdk.csproj" />
</ItemGroup>

<ItemGroup>
<!-- <PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" /> -->
<PackageReference Include="vss-api-netcore" Version="0.5.63-private" />
</ItemGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>portable</DebugType>
</PropertyGroup>

<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">
<DefineConstants>OS_WINDOWS;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_WINDOWS;DEBUG;TRACE</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;TRACE</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">
<DefineConstants>OS_LINUX;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_LINUX;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project>
45 changes: 45 additions & 0 deletions src/Agent.Plugins/BuildServer.cs
@@ -0,0 +1,45 @@
using Microsoft.TeamFoundation.Core.WebApi;
using Agent.Sdk;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.VisualStudio.Services.WebApi;

namespace Agent.Plugins.Drop
{
public class BuildServer
{
private readonly BuildHttpClient _buildHttpClient;

public BuildServer(VssConnection connection)
{
PluginUtil.NotNull(connection, nameof(connection));
_buildHttpClient = connection.GetClient<BuildHttpClient>();
}

public async Task<BuildArtifact> AssociateArtifact(
Guid projectId,
int buildId,
string name,
string type,
string data,
Dictionary<string, string> propertiesDictionary,
CancellationToken cancellationToken = default(CancellationToken))
{
BuildArtifact artifact = new BuildArtifact()
{
Name = name,
Resource = new ArtifactResource()
{
Data = data,
Type = type,
Properties = propertiesDictionary
}
};

return await _buildHttpClient.CreateArtifactAsync(artifact, projectId, buildId, cancellationToken: cancellationToken);
}
}
}

0 comments on commit dedfd9b

Please sign in to comment.