Skip to content

Conversation

@brittanyellich
Copy link
Contributor

This PR introduces a new way to queue and upload step summaries.

@brittanyellich brittanyellich requested a review from a team as a code owner December 5, 2022 23:33
yacaovsnc
yacaovsnc previously approved these changes Dec 6, 2022
Copy link
Contributor

@yacaovsnc yacaovsnc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!


namespace GitHub.Services.Results.Client
{
public class ResultsHttpClient : RawHttpClientBase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one thing to check if you plan to use ResultsHttpClient in production for customers, does the RawHttpClientBase support all the network settings for the runner, ex: proxy, SSL cert, etc?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for my education only, isn't the RawHttpClientBase the abstraction layer for proxy, SSL certs, retry and all other common http requirements?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should, but I didn't review the initial PR and am not sure whether we implement all required pieces, it was added to testing RunService only in the dev environment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm that is a good question, I'm not familiar with what all the runner requires so I'm not sure if it supports that 🤔 I can look into it and make sure it at least satisfies our needs, though. Good call out!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yacaovsnc and I chatted and we are both thinking that we should push that effort into another issue, so we can work on incrementally getting this work in and tested. I'll make an issue for this so that we can track the effort.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can tell, RawHttpMessagehandler.cs handles timeouts, retries and has partial support for proxy - it doesn't apply proxy authentication.

It also doesn't support certs which is okay in Results case since we don't need to support self signed certificate yet.

I will try to add the proxy authentication support in the other issue created.

yacaovsnc
yacaovsnc previously approved these changes Dec 6, 2022
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: {0}. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.";
public static readonly string SummaryUploadError = "$GITHUB_STEP_SUMMARY upload aborted, an error occurred when uploading the summary. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/. Please update the following actions to use Node.js 16: {0}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have a bad merge/rebase? the Node12DetectedAfterEndOfLife looks a little bit different.

Comment on lines 324 to 325
Trace.Info("Results client is not initialized. Skipping the step summary upload.");
return Task.CompletedTask;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to skip or throw?

void Start(Pipelines.AgentJobRequestMessage jobRequest);
void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null);
void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource);
void QueueResultsSummaryUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, string stepId, bool deleteSource);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest renaming to QueueSummaryUpload.

private static readonly TimeSpan _delayForWebConsoleLineDequeue = TimeSpan.FromMilliseconds(500);
private static readonly TimeSpan _delayForTimelineUpdateDequeue = TimeSpan.FromMilliseconds(500);
private static readonly TimeSpan _delayForFileUploadDequeue = TimeSpan.FromMilliseconds(1000);
private static readonly TimeSpan _delayForResultsSummaryUploadDequeue = TimeSpan.FromMilliseconds(1000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename everything in this file to not include Result, IJobServerQueue doesn't need to know it's uploading stuff to ResultService.

Task<TaskLog> AppendLogContentAsync(Guid scopeIdentifier, string hubName, Guid planId, int logId, Stream uploadStream, CancellationToken cancellationToken);
Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken);
Task<TaskAttachment> CreateAttachmentAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, String type, String name, Stream uploadStream, CancellationToken cancellationToken);
Task CreateResultsStepSymmaryAsync(string planId, string jobId, string stepId, string file, CancellationToken cancellationToken);
Copy link
Member

@TingluoHuang TingluoHuang Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Task CreateResultsStepSymmaryAsync(string planId, string jobId, string stepId, string file, CancellationToken cancellationToken);
Task CreateStepSummaryAsync(string planId, string jobId, string stepId, string file, CancellationToken cancellationToken);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are creating a summary, and it happens to upload to the ResultService.

_jobServer.InitializeWebsocketClient(serviceEndPoint);

// This code is usually wrapped by an instance of IExecutionContext which isn't available here.
jobRequest.Variables.TryGetValue("system.github.results_endpoint", out VariableValue resultsEndpointVariable);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use the SystemConnection to pass the URL? we have the same pattern for passing CacheServerUrl and GenerateIdTokenUrl from the service to the runner.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference and the advantage of using SystemConnection?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to keep is as a variable for now. The SystemConnction has authorization parameters and for Results we are just sticking with the system access token.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the auth in the SystemConnection is exactly the system access token.
the advantage is aline with the existing pattern, the SystemConnection was holding some connection info back to the service, I think the result service URL is just one of them.

try
{
Trace.Info($"Starting to upload summary file to results service {file.Type}, {file.Name}, {file.Path}");

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Trace.Info($"Starting to upload summary file to results service {file.Type}, {file.Name}, {file.Path}");


if (String.Equals(file.Type, ChecksAttachmentType.ResultsStepSummary, StringComparison.OrdinalIgnoreCase))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will there every be other types of files?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not planned yet.

Comment on lines +241 to +242
TimelineId = timelineId,
TimelineRecordId = timelineRecordId,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need these 2 fields? TimelineId and TimelineRecordId


public static async Task<HttpResponseMessage> UploadFileAsync(string url, string blobStorageType, FileStream file, CancellationToken cancellationToken) {
// Upload the file to the url
var httpClient = new HttpClient();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we create a new HttpClient if we are using the RawHttpClientBase? should we use the RawHttpClientBase.SendAsync?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the intention is this upload goes to Blob, not Results - that said, I think the Raw http client should still work.

public static async Task<HttpResponseMessage> UploadFileAsync(string url, string blobStorageType, FileStream file, CancellationToken cancellationToken) {
// Upload the file to the url
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Put, url)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also same about dispose.


using (var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken)) {
if (!response.IsSuccessStatusCode) {
throw new Exception($"Failed to upload file, status code: {response.StatusCode}, reason: {response.ReasonPhrase}, blobStorageType: {blobStorageType}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same about whether this will be on user's face.

}
}

public static async Task<HttpResponseMessage> UploadFileAsync(string url, string blobStorageType, FileStream file, CancellationToken cancellationToken) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public or private?

}

// Handle file upload for step summary
public async Task UploadStepSummaryAsync(string jobId, string planId, string stepId, string file, CancellationToken cancellationToken)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

order the parameters.

var fileSize = new FileInfo(file).Length;
if (fileSize > uploadUrlResponse.soft_size_limit)
{
throw new Exception($"File size is larger than the upload url allows, file size: {fileSize}, upload url size: {uploadUrlResponse.soft_size_limit}, blobType: {uploadUrlResponse.blob_storage_type}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the user care about the storage type?

await StepSummaryUploadCompleteAsync(jobId, planId, stepId, fileSize, cancellationToken);
}
catch (Exception ex) {
throw new Exception("Failed to upload step summary to results", ex);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this print out a nest error message with tons of stack about the inner exception?

Co-authored-by: Tingluo Huang <tingluohuang@github.com>
Copy link
Contributor

@fhammerl fhammerl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fhammerl fhammerl merged commit f41f5d2 into actions:main Dec 14, 2022
yacaovsnc added a commit to yacaovsnc/runner that referenced this pull request Dec 16, 2022
yacaovsnc added a commit to yacaovsnc/runner that referenced this pull request Dec 16, 2022
Comment on lines +819 to +820
public Guid TimelineId { get; set; }
public Guid TimelineRecordId { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't get why we need these fields.

await _jobServer.CreateStepSymmaryAsync(file.PlanId, file.JobId, file.StepId, file.Path, cancellationTokenSource.Token);

Do we only pass PlanId/JobId/StepId/Path to the _jobServer?

nikola-jokic pushed a commit to nikola-jokic/runner that referenced this pull request May 12, 2023
* Use results service for uploading step summaries

* Use results summary over generic results naming convention

* Apply suggestions from code review

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Addressing feedback

* Fix merge issue

* Remove empty line

* Update Results json objects to use snake case

* Adding the reference

Co-authored-by: Yang Cao <yacaovsnc@github.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
AdamOlech pushed a commit to antmicro/runner that referenced this pull request Jun 17, 2024
* Use results service for uploading step summaries

* Use results summary over generic results naming convention

* Apply suggestions from code review

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Addressing feedback

* Fix merge issue

* Remove empty line

* Update Results json objects to use snake case

* Adding the reference

Co-authored-by: Yang Cao <yacaovsnc@github.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants