-
Notifications
You must be signed in to change notification settings - Fork 951
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve Actions Directly From Launch for Run Service Jobs (#2529)
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
- Loading branch information
1 parent
229b9b8
commit 22d1938
Showing
9 changed files
with
275 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using GitHub.DistributedTask.WebApi; | ||
using GitHub.Services.Launch.Client; | ||
using GitHub.Services.WebApi; | ||
|
||
namespace GitHub.Runner.Common | ||
{ | ||
[ServiceLocator(Default = typeof(LaunchServer))] | ||
public interface ILaunchServer : IRunnerService | ||
{ | ||
void InitializeLaunchClient(Uri uri, string token); | ||
|
||
Task<ActionDownloadInfoCollection> ResolveActionsDownloadInfoAsync(Guid planId, Guid jobId, ActionReferenceList actionReferenceList, CancellationToken cancellationToken); | ||
} | ||
|
||
public sealed class LaunchServer : RunnerService, ILaunchServer | ||
{ | ||
private LaunchHttpClient _launchClient; | ||
|
||
public void InitializeLaunchClient(Uri uri, string token) | ||
{ | ||
var httpMessageHandler = HostContext.CreateHttpClientHandler(); | ||
this._launchClient = new LaunchHttpClient(uri, httpMessageHandler, token, disposeHandler: true); | ||
} | ||
|
||
public Task<ActionDownloadInfoCollection> ResolveActionsDownloadInfoAsync(Guid planId, Guid jobId, ActionReferenceList actionReferenceList, | ||
CancellationToken cancellationToken) | ||
{ | ||
if (_launchClient != null) | ||
{ | ||
return _launchClient.GetResolveActionsDownloadInfoAsync(planId, jobId, actionReferenceList, | ||
cancellationToken: cancellationToken); | ||
} | ||
|
||
throw new InvalidOperationException("Launch client is not initialized."); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.Serialization; | ||
|
||
namespace GitHub.Services.Launch.Contracts | ||
{ | ||
[DataContract] | ||
public class ActionReferenceRequest | ||
{ | ||
[DataMember(EmitDefaultValue = false, Name = "action")] | ||
public string Action { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "version")] | ||
public string Version { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "path")] | ||
public string Path { get; set; } | ||
} | ||
|
||
[DataContract] | ||
public class ActionReferenceRequestList | ||
{ | ||
[DataMember(EmitDefaultValue = false, Name = "actions")] | ||
public IList<ActionReferenceRequest> Actions { get; set; } | ||
} | ||
|
||
[DataContract] | ||
public class ActionDownloadInfoResponse | ||
{ | ||
[DataMember(EmitDefaultValue = false, Name = "authentication")] | ||
public ActionDownloadAuthenticationResponse Authentication { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "name")] | ||
public string Name { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "resolved_name")] | ||
public string ResolvedName { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "resolved_sha")] | ||
public string ResolvedSha { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "tar_url")] | ||
public string TarUrl { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "version")] | ||
public string Version { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "zip_url")] | ||
public string ZipUrl { get; set; } | ||
} | ||
|
||
[DataContract] | ||
public class ActionDownloadAuthenticationResponse | ||
{ | ||
[DataMember(EmitDefaultValue = false, Name = "expires_at")] | ||
public DateTime ExpiresAt { get; set; } | ||
|
||
[DataMember(EmitDefaultValue = false, Name = "token")] | ||
public string Token { get; set; } | ||
} | ||
|
||
[DataContract] | ||
public class ActionDownloadInfoResponseCollection | ||
{ | ||
/// <summary>A mapping of action specifications to their download information.</summary> | ||
/// <remarks>The key is the full name of the action plus version, e.g. "actions/checkout@v2".</remarks> | ||
[DataMember(EmitDefaultValue = false, Name = "actions")] | ||
public IDictionary<string, ActionDownloadInfoResponse> Actions { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
#nullable enable | ||
|
||
using System; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Net.Http.Formatting; | ||
using System.Net.Http.Headers; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
using GitHub.DistributedTask.WebApi; | ||
using GitHub.Services.Launch.Contracts; | ||
|
||
using Sdk.WebApi.WebApi; | ||
|
||
namespace GitHub.Services.Launch.Client | ||
{ | ||
public class LaunchHttpClient : RawHttpClientBase | ||
{ | ||
public LaunchHttpClient( | ||
Uri baseUrl, | ||
HttpMessageHandler pipeline, | ||
string token, | ||
bool disposeHandler) | ||
: base(baseUrl, pipeline, disposeHandler) | ||
{ | ||
m_token = token; | ||
m_launchServiceUrl = baseUrl; | ||
m_formatter = new JsonMediaTypeFormatter(); | ||
} | ||
|
||
public async Task<ActionDownloadInfoCollection> GetResolveActionsDownloadInfoAsync(Guid planId, Guid jobId, ActionReferenceList actionReferenceList, CancellationToken cancellationToken) | ||
{ | ||
var GetResolveActionsDownloadInfoURLEndpoint = new Uri(m_launchServiceUrl, $"/actions/build/{planId.ToString()}/jobs/{jobId.ToString()}/runnerresolve/actions"); | ||
return ToServerData(await GetLaunchSignedURLResponse<ActionReferenceRequestList, ActionDownloadInfoResponseCollection>(GetResolveActionsDownloadInfoURLEndpoint, ToGitHubData(actionReferenceList), cancellationToken)); | ||
} | ||
|
||
// Resolve Actions | ||
private async Task<T> GetLaunchSignedURLResponse<R, T>(Uri uri, R request, CancellationToken cancellationToken) | ||
{ | ||
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, uri)) | ||
{ | ||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", m_token); | ||
requestMessage.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); | ||
|
||
using (HttpContent content = new ObjectContent<R>(request, m_formatter)) | ||
{ | ||
requestMessage.Content = content; | ||
using (var response = await SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, cancellationToken: cancellationToken)) | ||
{ | ||
return await ReadJsonContentAsync<T>(response, cancellationToken); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private static ActionReferenceRequestList ToGitHubData(ActionReferenceList actionReferenceList) | ||
{ | ||
return new ActionReferenceRequestList | ||
{ | ||
Actions = actionReferenceList.Actions?.Select(ToGitHubData).ToList() | ||
}; | ||
} | ||
|
||
private static ActionReferenceRequest ToGitHubData(ActionReference actionReference) | ||
{ | ||
return new ActionReferenceRequest | ||
{ | ||
Action = actionReference.NameWithOwner, | ||
Version = actionReference.Ref, | ||
Path = actionReference.Path | ||
}; | ||
} | ||
|
||
private static ActionDownloadInfoCollection ToServerData(ActionDownloadInfoResponseCollection actionDownloadInfoResponseCollection) | ||
{ | ||
return new ActionDownloadInfoCollection | ||
{ | ||
Actions = actionDownloadInfoResponseCollection.Actions?.ToDictionary(kvp => kvp.Key, kvp => ToServerData(kvp.Value)) | ||
}; | ||
} | ||
|
||
private static ActionDownloadInfo ToServerData(ActionDownloadInfoResponse actionDownloadInfoResponse) | ||
{ | ||
return new ActionDownloadInfo | ||
{ | ||
Authentication = ToServerData(actionDownloadInfoResponse.Authentication), | ||
NameWithOwner = actionDownloadInfoResponse.Name, | ||
ResolvedNameWithOwner = actionDownloadInfoResponse.ResolvedName, | ||
ResolvedSha = actionDownloadInfoResponse.ResolvedSha, | ||
TarballUrl = actionDownloadInfoResponse.TarUrl, | ||
Ref = actionDownloadInfoResponse.Version, | ||
ZipballUrl = actionDownloadInfoResponse.ZipUrl, | ||
}; | ||
} | ||
|
||
private static ActionDownloadAuthentication? ToServerData(ActionDownloadAuthenticationResponse? actionDownloadAuthenticationResponse) | ||
{ | ||
if (actionDownloadAuthenticationResponse == null) | ||
{ | ||
return null; | ||
} | ||
|
||
return new ActionDownloadAuthentication | ||
{ | ||
ExpiresAt = actionDownloadAuthenticationResponse.ExpiresAt, | ||
Token = actionDownloadAuthenticationResponse.Token | ||
}; | ||
} | ||
|
||
private MediaTypeFormatter m_formatter; | ||
private Uri m_launchServiceUrl; | ||
private string m_token; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters