Compare commits

..

1 Commits

Author SHA1 Message Date
Bassem Dghaidi
2977a0fa02 Upgrade to dotnet 7.0 2023-05-03 14:16:37 +00:00
289 changed files with 1890 additions and 2886 deletions

9
.editorconfig Normal file
View File

@@ -0,0 +1,9 @@
# https://editorconfig.org/
[*]
charset = utf-8 # Set default charset to utf-8
insert_final_newline = true # ensure all files end with a single newline
trim_trailing_whitespace = true # attempt to remove trailing whitespace on save
[*.md]
trim_trailing_whitespace = false # in markdown, "two trailing spaces" is unfortunately meaningful; it means `<br>`

View File

@@ -1,9 +1,8 @@
# Source: https://github.com/dotnet/dotnet-docker FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy as build
ARG RUNNER_VERSION ARG RUNNER_VERSION
ARG RUNNER_ARCH="x64" ARG RUNNER_ARCH="x64"
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.3.2 ARG RUNNER_CONTAINER_HOOKS_VERSION=0.3.1
ARG DOCKER_VERSION=20.10.23 ARG DOCKER_VERSION=20.10.23
RUN apt update -y && apt install curl unzip -y RUN apt update -y && apt install curl unzip -y
@@ -23,7 +22,7 @@ RUN export DOCKER_ARCH=x86_64 \
&& tar zxvf docker.tgz \ && tar zxvf docker.tgz \
&& rm -rf docker.tgz && rm -rf docker.tgz
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy FROM mcr.microsoft.com/dotnet/runtime-deps:6.0
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
ENV RUNNER_MANUALLY_TRAP_SIG=1 ENV RUNNER_MANUALLY_TRAP_SIG=1
@@ -32,7 +31,6 @@ ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
RUN apt-get update -y \ RUN apt-get update -y \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
sudo \ sudo \
lsb-release \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN adduser --disabled-password --gecos "" --uid 1001 runner \ RUN adduser --disabled-password --gecos "" --uid 1001 runner \

View File

@@ -1,19 +1,18 @@
## Features ## Features
- Add warning to notify about forcing actions to run on node16 instead of node12 (#2678) - Runner changes for communication with Results service (#2510, #2531, #2535, #2516)
- Add `*.ghe.localhost` domains to hosted server check (#2536)
- Add `OrchestrationId` to user-agent for better telemetry correlation. (#2568)
## Bugs ## Bugs
- Remove job completion from runner listener (#2659) - Fix JIT configurations on Windows (#2497)
- Fix double error reporting (#2656) - Guard against NullReference while creating HostContext (#2343)
- Fix a bug with incorrect parsing of image values in a container action (#1873) - Handles broken symlink in `Which` (#2150, #2196)
- Fix error message reported on non-local action setup (#2668) - Adding curl retry for external tool downloads (#2552, #2557)
- Extend github context with host-workspace (#2517) - Limit the time we wait for waiting websocket to connect. (#2554)
- Fixed a bug where a misplaced = character could bypass heredoc-style processing (#2627)
## Misc ## Misc
- Send environment url to Run Service (#2650) - Bump container hooks version to 0.3.1 in runner image (#2496)
- Reduce token service and unnecessary calls - send token to redirects (#2660) - Runner changes to communicate with vNext services (#2487, #2500, #2505, #2541, #2547)
- Add 'http://' to http(s)_proxy if there is no protocol (#2663)
- Remove extra result step for job itself (#2620)
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet. _Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository. To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.

View File

@@ -1,5 +1,5 @@
[*.cs] [*.cs]
charset = utf-8-bom charset = utf-8
insert_final_newline = true insert_final_newline = true
csharp_new_line_before_else = true csharp_new_line_before_else = true

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -1,4 +1,4 @@
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
public enum ActionResult public enum ActionResult
{ {
@@ -10,4 +10,4 @@
Skipped = 3 Skipped = 3
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GitHub.DistributedTask.Logging; using GitHub.DistributedTask.Logging;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@@ -1,4 +1,4 @@
using System; using System;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
@@ -132,7 +132,6 @@ namespace GitHub.Runner.Common
public static readonly string GenerateServiceConfig = "generateServiceConfig"; public static readonly string GenerateServiceConfig = "generateServiceConfig";
public static readonly string Help = "help"; public static readonly string Help = "help";
public static readonly string Local = "local"; public static readonly string Local = "local";
public static readonly string NoDefaultLabels = "no-default-labels";
public static readonly string Replace = "replace"; public static readonly string Replace = "replace";
public static readonly string DisableUpdate = "disableupdate"; public static readonly string DisableUpdate = "disableupdate";
public static readonly string Once = "once"; // Keep this around since customers still relies on it public static readonly string Once = "once"; // Keep this around since customers still relies on it
@@ -155,7 +154,6 @@ namespace GitHub.Runner.Common
{ {
public static readonly string DiskSpaceWarning = "runner.diskspace.warning"; public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action"; public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
public static readonly string LogTemplateErrorsAsDebugMessages = "DistributedTask.LogTemplateErrorsAsDebugMessages";
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate"; public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks"; public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
} }
@@ -172,8 +170,6 @@ namespace GitHub.Runner.Common
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 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 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 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. 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 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 EnforcedNode12DetectedAfterEndOfLife = "The following actions uses node12 which is deprecated and will be forced to run on node16: {0}. For more info: https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/";
public static readonly string EnforcedNode12DetectedAfterEndOfLifeEnvVariable = "Node16ForceActionsWarnings";
} }
public static class RunnerEvent public static class RunnerEvent
@@ -265,7 +261,6 @@ namespace GitHub.Runner.Common
public static readonly string AccessToken = "system.accessToken"; public static readonly string AccessToken = "system.accessToken";
public static readonly string Culture = "system.culture"; public static readonly string Culture = "system.culture";
public static readonly string PhaseDisplayName = "system.phaseDisplayName"; public static readonly string PhaseDisplayName = "system.phaseDisplayName";
public static readonly string JobRequestType = "system.jobRequestType";
public static readonly string OrchestrationId = "system.orchestrationId"; public static readonly string OrchestrationId = "system.orchestrationId";
} }
} }

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
@@ -24,4 +24,4 @@ namespace GitHub.Runner.Common
return client; return client;
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
@@ -37,10 +37,10 @@ namespace GitHub.Runner.Common
{ {
ConnectMonitor(monitorSocketAddress); ConnectMonitor(monitorSocketAddress);
} }
private void StartMonitor(Guid jobId, string accessToken, Uri serverUri) private void StartMonitor(Guid jobId, string accessToken, Uri serverUri)
{ {
if (String.IsNullOrEmpty(accessToken)) if(String.IsNullOrEmpty(accessToken))
{ {
Trace.Info("No access token could be retrieved to start the monitor."); Trace.Info("No access token could be retrieved to start the monitor.");
return; return;
@@ -82,7 +82,7 @@ namespace GitHub.Runner.Common
_monitorSocket.Send(Encoding.UTF8.GetBytes(message)); _monitorSocket.Send(Encoding.UTF8.GetBytes(message));
Trace.Info("Finished EndMonitor writing to socket"); Trace.Info("Finished EndMonitor writing to socket");
await Task.Delay(TimeSpan.FromSeconds(2)); await Task.Delay(TimeSpan.FromSeconds(2));
} }
} }
catch (SocketException e) catch (SocketException e)

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -11,10 +11,10 @@ using System.Threading.Tasks;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.OAuth;
using GitHub.Services.Results.Client;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using GitHub.Services.WebApi.Utilities.Internal; using GitHub.Services.WebApi.Utilities.Internal;
using GitHub.Services.Results.Client;
using GitHub.Services.OAuth;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
@@ -254,7 +254,7 @@ namespace GitHub.Runner.Common
{ {
failedAttemptsToPostBatchedLinesByWebsocket++; failedAttemptsToPostBatchedLinesByWebsocket++;
Trace.Info($"Caught exception during append web console line to websocket, let's fallback to sending via non-websocket call (total calls: {totalBatchedLinesAttemptedByWebsocket}, failed calls: {failedAttemptsToPostBatchedLinesByWebsocket}, websocket state: {this._websocketClient?.State})."); Trace.Info($"Caught exception during append web console line to websocket, let's fallback to sending via non-websocket call (total calls: {totalBatchedLinesAttemptedByWebsocket}, failed calls: {failedAttemptsToPostBatchedLinesByWebsocket}, websocket state: {this._websocketClient?.State}).");
Trace.Verbose(ex.ToString()); Trace.Error(ex);
if (totalBatchedLinesAttemptedByWebsocket > _minWebsocketBatchedLinesCountToConsider) if (totalBatchedLinesAttemptedByWebsocket > _minWebsocketBatchedLinesCountToConsider)
{ {
// let's consider failure percentage // let's consider failure percentage

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -756,17 +756,17 @@ namespace GitHub.Runner.Common
timelineRecord.State = rec.State ?? timelineRecord.State; timelineRecord.State = rec.State ?? timelineRecord.State;
timelineRecord.WorkerName = rec.WorkerName ?? timelineRecord.WorkerName; timelineRecord.WorkerName = rec.WorkerName ?? timelineRecord.WorkerName;
if (rec.ErrorCount > 0) if (rec.ErrorCount != null && rec.ErrorCount > 0)
{ {
timelineRecord.ErrorCount = rec.ErrorCount; timelineRecord.ErrorCount = rec.ErrorCount;
} }
if (rec.WarningCount > 0) if (rec.WarningCount != null && rec.WarningCount > 0)
{ {
timelineRecord.WarningCount = rec.WarningCount; timelineRecord.WarningCount = rec.WarningCount;
} }
if (rec.NoticeCount > 0) if (rec.NoticeCount != null && rec.NoticeCount > 0)
{ {
timelineRecord.NoticeCount = rec.NoticeCount; timelineRecord.NoticeCount = rec.NoticeCount;
} }
@@ -797,7 +797,7 @@ namespace GitHub.Runner.Common
foreach (var record in mergedRecords) foreach (var record in mergedRecords)
{ {
Trace.Verbose($" Record: t={record.RecordType}, n={record.Name}, s={record.State}, st={record.StartTime}, {record.PercentComplete}%, ft={record.FinishTime}, r={record.Result}: {record.CurrentOperation}"); Trace.Verbose($" Record: t={record.RecordType}, n={record.Name}, s={record.State}, st={record.StartTime}, {record.PercentComplete}%, ft={record.FinishTime}, r={record.Result}: {record.CurrentOperation}");
if (record.Issues != null) if (record.Issues != null && record.Issues.Count > 0)
{ {
foreach (var issue in record.Issues) foreach (var issue in record.Issues)
{ {
@@ -807,7 +807,7 @@ namespace GitHub.Runner.Common
} }
} }
if (record.Variables != null) if (record.Variables != null && record.Variables.Count > 0)
{ {
foreach (var variable in record.Variables) foreach (var variable in record.Variables)
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common

View File

@@ -1,42 +0,0 @@
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.");
}
}
}

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http.Headers; using System.Net.Http.Headers;
@@ -222,7 +222,7 @@ namespace GitHub.Runner.Common
{ {
var delay = BackoffTimerHelper.GetRandomBackoff(MinDelayForWebsocketReconnect, MaxDelayForWebsocketReconnect); var delay = BackoffTimerHelper.GetRandomBackoff(MinDelayForWebsocketReconnect, MaxDelayForWebsocketReconnect);
Trace.Info($"Websocket is not open, let's attempt to connect back again with random backoff {delay} ms."); Trace.Info($"Websocket is not open, let's attempt to connect back again with random backoff {delay} ms.");
Trace.Verbose(ex.ToString()); Trace.Error(ex);
retries++; retries++;
InitializeWebsocketClient(_liveConsoleFeedUrl, _token, delay); InitializeWebsocketClient(_liveConsoleFeedUrl, _token, delay);
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -26,7 +26,6 @@ namespace GitHub.Runner.Common
Dictionary<String, VariableValue> outputs, Dictionary<String, VariableValue> outputs,
IList<StepResult> stepResults, IList<StepResult> stepResults,
IList<Annotation> jobAnnotations, IList<Annotation> jobAnnotations,
string environmentUrl,
CancellationToken token); CancellationToken token);
Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken token); Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken token);
@@ -71,12 +70,11 @@ namespace GitHub.Runner.Common
Dictionary<String, VariableValue> outputs, Dictionary<String, VariableValue> outputs,
IList<StepResult> stepResults, IList<StepResult> stepResults,
IList<Annotation> jobAnnotations, IList<Annotation> jobAnnotations,
string environmentUrl,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
CheckConnection(); CheckConnection();
return RetryRequest( return RetryRequest(
async () => await _runServiceHttpClient.CompleteJobAsync(requestUri, planId, jobId, result, outputs, stepResults, jobAnnotations, environmentUrl, cancellationToken), cancellationToken); async () => await _runServiceHttpClient.CompleteJobAsync(requestUri, planId, jobId, result, outputs, stepResults, jobAnnotations, cancellationToken), cancellationToken);
} }
public Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken cancellationToken) public Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken cancellationToken)

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>

View File

@@ -1,4 +1,4 @@
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@@ -1,4 +1,4 @@
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -93,4 +93,4 @@ namespace GitHub.Runner.Common
IndentLevel--; IndentLevel--;
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using GitHub.DistributedTask.Logging; using GitHub.DistributedTask.Logging;

View File

@@ -1,4 +1,4 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

View File

@@ -1,8 +1,8 @@
// Represents absence of value. // Represents absence of value.
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
public readonly struct Unit public readonly struct Unit
{ {
public static readonly Unit Value = default; public static readonly Unit Value = default;
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -4,7 +4,7 @@
public static class EnumUtil public static class EnumUtil
{ {
public static T? TryParse<T>(string value) where T : struct public static T? TryParse<T>(string value) where T: struct
{ {
T val; T val;
if (Enum.TryParse(value ?? string.Empty, ignoreCase: true, result: out val)) if (Enum.TryParse(value ?? string.Empty, ignoreCase: true, result: out val))

View File

@@ -1,4 +1,4 @@
namespace GitHub.Runner.Common.Util namespace GitHub.Runner.Common.Util
{ {
using System; using System;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;

View File

@@ -1,4 +1,4 @@
using System; using System;
namespace GitHub.Runner.Common.Util namespace GitHub.Runner.Common.Util
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -90,4 +90,4 @@ namespace GitHub.Runner.Listener.Check
return result; return result;
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Tracing; using System.Diagnostics.Tracing;
using System.IO; using System.IO;
@@ -415,4 +415,4 @@ namespace GitHub.Runner.Listener.Check
} }
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Common; using GitHub.Runner.Common;
@@ -27,4 +27,4 @@ namespace GitHub.Runner.Listener.Check
public List<string> Logs { get; set; } public List<string> Logs { get; set; }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -56,4 +56,4 @@ namespace GitHub.Runner.Listener.Check
return result; return result;
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Listener.Configuration; using GitHub.Runner.Listener.Configuration;
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using System; using System;
using System.Collections; using System.Collections;
@@ -29,8 +29,8 @@ namespace GitHub.Runner.Listener
private readonly Dictionary<string, string[]> validOptions = new() private readonly Dictionary<string, string[]> validOptions = new()
{ {
// Valid configure flags and args // Valid configure flags and args
[Constants.Runner.CommandLine.Commands.Configure] = [Constants.Runner.CommandLine.Commands.Configure] =
new string[] new string[]
{ {
Constants.Runner.CommandLine.Flags.DisableUpdate, Constants.Runner.CommandLine.Flags.DisableUpdate,
Constants.Runner.CommandLine.Flags.Ephemeral, Constants.Runner.CommandLine.Flags.Ephemeral,
@@ -38,7 +38,6 @@ namespace GitHub.Runner.Listener
Constants.Runner.CommandLine.Flags.Replace, Constants.Runner.CommandLine.Flags.Replace,
Constants.Runner.CommandLine.Flags.RunAsService, Constants.Runner.CommandLine.Flags.RunAsService,
Constants.Runner.CommandLine.Flags.Unattended, Constants.Runner.CommandLine.Flags.Unattended,
Constants.Runner.CommandLine.Flags.NoDefaultLabels,
Constants.Runner.CommandLine.Args.Auth, Constants.Runner.CommandLine.Args.Auth,
Constants.Runner.CommandLine.Args.Labels, Constants.Runner.CommandLine.Args.Labels,
Constants.Runner.CommandLine.Args.MonitorSocketAddress, Constants.Runner.CommandLine.Args.MonitorSocketAddress,
@@ -86,7 +85,6 @@ namespace GitHub.Runner.Listener
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral); public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
public bool GenerateServiceConfig => TestFlag(Constants.Runner.CommandLine.Flags.GenerateServiceConfig); public bool GenerateServiceConfig => TestFlag(Constants.Runner.CommandLine.Flags.GenerateServiceConfig);
public bool Help => TestFlag(Constants.Runner.CommandLine.Flags.Help); public bool Help => TestFlag(Constants.Runner.CommandLine.Flags.Help);
public bool NoDefaultLabels => TestFlag(Constants.Runner.CommandLine.Flags.NoDefaultLabels);
public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended); public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended);
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version); public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
public bool RemoveLocalConfig => TestFlag(Constants.Runner.CommandLine.Flags.Local); public bool RemoveLocalConfig => TestFlag(Constants.Runner.CommandLine.Flags.Local);
@@ -184,7 +182,7 @@ namespace GitHub.Runner.Listener
{ {
command = Constants.Runner.CommandLine.Commands.Warmup; command = Constants.Runner.CommandLine.Commands.Warmup;
} }
return command; return command;
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
@@ -137,7 +137,7 @@ namespace GitHub.Runner.Listener.Configuration
GitHubAuthResult authResult = await GetTenantCredential(inputUrl, registerToken, Constants.RunnerEvent.Register); GitHubAuthResult authResult = await GetTenantCredential(inputUrl, registerToken, Constants.RunnerEvent.Register);
runnerSettings.ServerUrl = authResult.TenantUrl; runnerSettings.ServerUrl = authResult.TenantUrl;
runnerSettings.UseV2Flow = authResult.UseV2Flow; runnerSettings.UseV2Flow = authResult.UseV2Flow;
Trace.Info($"Using V2 flow: {runnerSettings.UseV2Flow}"); _term.WriteLine($"Using V2 flow: {runnerSettings.UseV2Flow}");
creds = authResult.ToVssCredentials(); creds = authResult.ToVssCredentials();
Trace.Info("cred retrieved via GitHub auth"); Trace.Info("cred retrieved via GitHub auth");
} }
@@ -259,7 +259,7 @@ namespace GitHub.Runner.Listener.Configuration
if (command.GetReplace()) if (command.GetReplace())
{ {
// Update existing agent with new PublicKey, agent version. // Update existing agent with new PublicKey, agent version.
agent = UpdateExistingAgent(agent, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate, command.NoDefaultLabels); agent = UpdateExistingAgent(agent, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
try try
{ {
@@ -293,7 +293,7 @@ namespace GitHub.Runner.Listener.Configuration
else else
{ {
// Create a new agent. // Create a new agent.
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate, command.NoDefaultLabels); agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
try try
{ {
@@ -554,7 +554,7 @@ namespace GitHub.Runner.Listener.Configuration
} }
private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate, bool noDefaultLabels) private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
{ {
ArgUtil.NotNull(agent, nameof(agent)); ArgUtil.NotNull(agent, nameof(agent));
agent.Authorization = new TaskAgentAuthorization agent.Authorization = new TaskAgentAuthorization
@@ -571,16 +571,9 @@ namespace GitHub.Runner.Listener.Configuration
agent.Labels.Clear(); agent.Labels.Clear();
if (!noDefaultLabels) agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
{ agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System)); agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
}
else if (userLabels.Count == 0)
{
throw new NotSupportedException("Disabling default labels via --no-default-labels without specifying --labels is not supported");
}
foreach (var userLabel in userLabels) foreach (var userLabel in userLabels)
{ {
@@ -590,7 +583,7 @@ namespace GitHub.Runner.Listener.Configuration
return agent; return agent;
} }
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate, bool noDefaultLabels) private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
{ {
TaskAgent agent = new(agentName) TaskAgent agent = new(agentName)
{ {
@@ -605,16 +598,9 @@ namespace GitHub.Runner.Listener.Configuration
DisableUpdate = disableUpdate DisableUpdate = disableUpdate
}; };
if (!noDefaultLabels) agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
{ agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System)); agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
}
else if (userLabels.Count == 0)
{
throw new NotSupportedException("Disabling default labels via --no-default-labels without specifying --labels is not supported");
}
foreach (var userLabel in userLabels) foreach (var userLabel in userLabels)
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using GitHub.Runner.Common; using GitHub.Runner.Common;

View File

@@ -1,4 +1,4 @@
#if OS_WINDOWS #if OS_WINDOWS
#pragma warning disable CA1416 #pragma warning disable CA1416
using System; using System;
using System.Collections; using System.Collections;

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;

View File

@@ -1,4 +1,4 @@
#if OS_WINDOWS #if OS_WINDOWS
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;

View File

@@ -1,4 +1,4 @@
#if OS_LINUX || OS_OSX #if OS_LINUX || OS_OSX
using System; using System;
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using GitHub.Runner.Common; using GitHub.Runner.Common;
@@ -68,7 +68,7 @@ namespace GitHub.Runner.Listener.Configuration
// Lets add a suffix with a random number to reduce the chance of collisions between runner names once we truncate // Lets add a suffix with a random number to reduce the chance of collisions between runner names once we truncate
var random = new Random(); var random = new Random();
var num = random.Next(1000, 9999).ToString(); var num = random.Next(1000, 9999).ToString();
runnerNameSubstring += $"-{num}"; runnerNameSubstring +=$"-{num}";
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgNameSubstring, runnerNameSubstring); serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgNameSubstring, runnerNameSubstring);
} }
@@ -76,12 +76,12 @@ namespace GitHub.Runner.Listener.Configuration
Trace.Info($"Service name '{serviceName}' display name '{serviceDisplayName}' will be used for service configuration."); Trace.Info($"Service name '{serviceName}' display name '{serviceDisplayName}' will be used for service configuration.");
} }
#if (OS_LINUX || OS_OSX) #if (OS_LINUX || OS_OSX)
const int MaxServiceNameLength = 150; const int MaxServiceNameLength = 150;
const int MaxRepoOrgCharacters = 70; const int MaxRepoOrgCharacters = 70;
#elif OS_WINDOWS #elif OS_WINDOWS
const int MaxServiceNameLength = 80; const int MaxServiceNameLength = 80;
const int MaxRepoOrgCharacters = 45; const int MaxRepoOrgCharacters = 45;
#endif #endif
} }
} }

View File

@@ -1,4 +1,4 @@
#if OS_LINUX #if OS_LINUX
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Linq; using System.Linq;

View File

@@ -1,4 +1,4 @@
#if OS_WINDOWS #if OS_WINDOWS
#pragma warning disable CA1416 #pragma warning disable CA1416
using System; using System;
using System.IO; using System.IO;

View File

@@ -1,3 +1,3 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Test")] [assembly: InternalsVisibleTo("Test")]

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -1077,7 +1077,23 @@ namespace GitHub.Runner.Listener
if (this._isRunServiceJob) if (this._isRunServiceJob)
{ {
Trace.Verbose($"Skip CompleteJobRequestAsync call from Listener because it's RunService job"); var runServer = await GetRunServerAsync(systemConnection);
var unhandledExceptionIssue = new Issue() { Type = IssueType.Error, Message = detailInfo };
var unhandledAnnotation = unhandledExceptionIssue.ToAnnotation();
var jobAnnotations = new List<Annotation>();
if (unhandledAnnotation.HasValue)
{
jobAnnotations.Add(unhandledAnnotation.Value);
}
try
{
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, result, outputs: null, stepResults: null, jobAnnotations: jobAnnotations, CancellationToken.None);
}
catch (Exception ex)
{
Trace.Error("Fail to raise job completion back to service.");
Trace.Error(ex);
}
return; return;
} }
@@ -1177,7 +1193,7 @@ namespace GitHub.Runner.Listener
jobAnnotations.Add(unhandledAnnotation.Value); jobAnnotations.Add(unhandledAnnotation.Value);
} }
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, TaskResult.Failed, outputs: null, stepResults: null, jobAnnotations: jobAnnotations, environmentUrl: null, CancellationToken.None); await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, TaskResult.Failed, outputs: null, stepResults: null, jobAnnotations: jobAnnotations, CancellationToken.None);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Globalization; using System.Globalization;

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -683,8 +683,7 @@ Config Options:
--token string Registration token. Required if unattended --token string Registration token. Required if unattended
--name string Name of the runner to configure (default {Environment.MachineName ?? "myrunner"}) --name string Name of the runner to configure (default {Environment.MachineName ?? "myrunner"})
--runnergroup string Name of the runner group to add this runner to (defaults to the default runner group) --runnergroup string Name of the runner group to add this runner to (defaults to the default runner group)
--labels string Custom labels that will be added to the runner. This option is mandatory if --no-default-labels is used. --labels string Extra labels in addition to the default: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
--no-default-labels Disables adding the default labels: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
--local Removes the runner config files from your local machine. Used as an option to the remove command --local Removes the runner config files from your local machine. Used as an option to the remove command
--work string Relative runner work directory (default {Constants.Path.WorkDirectory}) --work string Relative runner work directory (default {Constants.Path.WorkDirectory})
--replace Replace any existing runner with the same name (default false) --replace Replace any existing runner with the same name (default false)

View File

@@ -1,4 +1,4 @@
using System.Runtime.Serialization; using System.Runtime.Serialization;
namespace GitHub.Runner.Listener namespace GitHub.Runner.Listener
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>

View File

@@ -682,4 +682,4 @@ namespace GitHub.Runner.Plugins.Artifact
: base(message, inner) : base(message, inner)
{ } { }
} }
} }

View File

@@ -1,4 +1,4 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Actions.Pipelines.WebApi; using GitHub.Actions.Pipelines.WebApi;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
@@ -36,7 +36,7 @@ namespace GitHub.Runner.Plugins.Artifact
return await _pipelinesHttpClient.CreateArtifactAsync( return await _pipelinesHttpClient.CreateArtifactAsync(
parameters, parameters,
pipelineId, pipelineId,
runId, runId,
cancellationToken: cancellationToken) as Pipelines.ActionsStorageArtifact; cancellationToken: cancellationToken) as Pipelines.ActionsStorageArtifact;
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -97,8 +97,8 @@ namespace GitHub.Runner.Plugins.Artifact
size, size,
token); token);
context.Output($"Associated artifact {artifactName} ({artifact.ContainerId}) with run #{buildId}"); context.Output($"Associated artifact {artifactName} ({artifact.ContainerId}) with run #{buildId}");
} }
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@@ -1,4 +1,4 @@
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -1,4 +1,4 @@
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http.Headers; using System.Net.Http.Headers;
@@ -220,12 +220,20 @@ namespace GitHub.Runner.Sdk
return input; return input;
} }
private Dictionary<string, string> _commandEscapeMappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) private Dictionary<string, string> _commandEscapeMappings = new(StringComparer.OrdinalIgnoreCase)
{ {
{ ";", "%3B" }, {
{ "\r", "%0D" }, ";", "%3B"
{ "\n", "%0A" }, },
{ "]", "%5D" }, {
"\r", "%0D"
},
{
"\n", "%0A"
},
{
"]", "%5D"
},
}; };
} }
} }

View File

@@ -1,4 +1,4 @@
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {
/*** /***
* WARNING: This file is automatically regenerated on layout so the runner can provide version/commit info (do not manually edit it). * WARNING: This file is automatically regenerated on layout so the runner can provide version/commit info (do not manually edit it).

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -69,10 +69,6 @@ namespace GitHub.Runner.Sdk
return; return;
} }
if (!string.IsNullOrEmpty(httpProxyAddress) && !Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var _))
{
httpProxyAddress = PrependHttpIfMissing(httpProxyAddress);
}
if (!string.IsNullOrEmpty(httpProxyAddress) && Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var proxyHttpUri)) if (!string.IsNullOrEmpty(httpProxyAddress) && Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var proxyHttpUri))
{ {
_httpProxyAddress = proxyHttpUri.OriginalString; _httpProxyAddress = proxyHttpUri.OriginalString;
@@ -103,10 +99,6 @@ namespace GitHub.Runner.Sdk
} }
} }
if (!string.IsNullOrEmpty(httpsProxyAddress) && !Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var _))
{
httpsProxyAddress = PrependHttpIfMissing(httpsProxyAddress);
}
if (!string.IsNullOrEmpty(httpsProxyAddress) && Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var proxyHttpsUri)) if (!string.IsNullOrEmpty(httpsProxyAddress) && Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var proxyHttpsUri))
{ {
_httpsProxyAddress = proxyHttpsUri.OriginalString; _httpsProxyAddress = proxyHttpsUri.OriginalString;
@@ -248,20 +240,5 @@ namespace GitHub.Runner.Sdk
return false; return false;
} }
private string PrependHttpIfMissing(string proxyAddress)
{
// much like in golang, see https://github.com/golang/net/blob/f5464ddb689c015d1abf4df78a806a54af977e6c/http/httpproxy/proxy.go#LL156C31-L156C31
if (!proxyAddress.StartsWith("http://", StringComparison.Ordinal) && !proxyAddress.StartsWith("https://", StringComparison.Ordinal))
{
var prependedProxyAddress = "http://" + proxyAddress;
if (Uri.TryCreate(prependedProxyAddress, UriKind.Absolute, out var _))
{
// if prepending http:// turns the proxyAddress into a valid Uri, then use that
return prependedProxyAddress;
}
}
return proxyAddress;
}
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@@ -1,4 +1,4 @@
using System.IO; using System.IO;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {

View File

@@ -1,4 +1,4 @@
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Globalization; using System.Globalization;

View File

@@ -1,4 +1,4 @@
using System; using System;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {

View File

@@ -64,7 +64,7 @@ namespace GitHub.Runner.Sdk
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW"))) if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
{ {
settings.AllowAutoRedirectForBroker = true; settings.AllowAutoRedirect = true;
} }
// Remove Invariant from the list of accepted languages. // Remove Invariant from the list of accepted languages.

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -134,7 +134,7 @@ namespace GitHub.Runner.Sdk
{ {
var fileInfo = new FileInfo(path); var fileInfo = new FileInfo(path);
var linkTargetFullPath = fileInfo.Directory?.FullName + Path.DirectorySeparatorChar + fileInfo.LinkTarget; var linkTargetFullPath = fileInfo.Directory?.FullName + Path.DirectorySeparatorChar + fileInfo.LinkTarget;
if (fileInfo.LinkTarget == null || File.Exists(linkTargetFullPath) || File.Exists(fileInfo.LinkTarget)) return true; if(fileInfo.LinkTarget == null || File.Exists(linkTargetFullPath) || File.Exists(fileInfo.LinkTarget)) return true;
trace?.Info($"the target '{fileInfo.LinkTarget}' of the symbolic link '{path}', does not exist"); trace?.Info($"the target '{fileInfo.LinkTarget}' of the symbolic link '{path}', does not exist");
return false; return false;
} }

View File

@@ -36,7 +36,7 @@ namespace RunnerService
catch (Win32Exception ex) catch (Win32Exception ex)
{ {
Console.WriteLine("[ERROR] Unable to create '{0}' event source under 'Application' event log.", RunnerService.EventSourceName); Console.WriteLine("[ERROR] Unable to create '{0}' event source under 'Application' event log.", RunnerService.EventSourceName);
Console.WriteLine("[ERROR] {0}", ex.Message); Console.WriteLine("[ERROR] {0}",ex.Message);
Console.WriteLine("[ERROR] Error Code: {0}", ex.ErrorCode); Console.WriteLine("[ERROR] Error Code: {0}", ex.ErrorCode);
return 1; return 1;
} }

View File

@@ -276,7 +276,7 @@ namespace GitHub.Runner.Worker
Message = $"Can't update {blocked} environment variable using ::set-env:: command." Message = $"Can't update {blocked} environment variable using ::set-env:: command."
}; };
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = $"{Constants.Runner.UnsupportedCommand}_{envName}"; issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = $"{Constants.Runner.UnsupportedCommand}_{envName}";
context.AddIssue(issue, ExecutionContextLogOptions.Default); context.AddIssue(issue);
return; return;
} }
@@ -315,7 +315,7 @@ namespace GitHub.Runner.Worker
Message = String.Format(Constants.Runner.UnsupportedCommandMessage, this.Command) Message = String.Format(Constants.Runner.UnsupportedCommandMessage, this.Command)
}; };
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.UnsupportedCommand; issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.UnsupportedCommand;
context.AddIssue(issue, ExecutionContextLogOptions.Default); context.AddIssue(issue);
} }
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName)) if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
@@ -350,7 +350,7 @@ namespace GitHub.Runner.Worker
Message = String.Format(Constants.Runner.UnsupportedCommandMessage, this.Command) Message = String.Format(Constants.Runner.UnsupportedCommandMessage, this.Command)
}; };
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.UnsupportedCommand; issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.UnsupportedCommand;
context.AddIssue(issue, ExecutionContextLogOptions.Default); context.AddIssue(issue);
} }
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName)) if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
@@ -666,7 +666,7 @@ namespace GitHub.Runner.Worker
} }
} }
context.AddIssue(issue, ExecutionContextLogOptions.Default); context.AddIssue(issue);
} }
public static void ValidateLinesAndColumns(ActionCommand command, IExecutionContext context) public static void ValidateLinesAndColumns(ActionCommand command, IExecutionContext context)

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
@@ -11,14 +11,12 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.ObjectTemplating.Tokens;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
using GitHub.Services.Common; using GitHub.Services.Common;
using WebApi = GitHub.DistributedTask.WebApi; using WebApi = GitHub.DistributedTask.WebApi;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants; using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants;
using GitHub.DistributedTask.WebApi;
namespace GitHub.Runner.Worker namespace GitHub.Runner.Worker
{ {
@@ -102,19 +100,7 @@ namespace GitHub.Runner.Worker
} }
IEnumerable<Pipelines.ActionStep> actions = steps.OfType<Pipelines.ActionStep>(); IEnumerable<Pipelines.ActionStep> actions = steps.OfType<Pipelines.ActionStep>();
executionContext.Output("Prepare all required actions"); executionContext.Output("Prepare all required actions");
PrepareActionsState result = new PrepareActionsState(); var result = await PrepareActionsRecursiveAsync(executionContext, state, actions, depth, rootStepId);
try
{
result = await PrepareActionsRecursiveAsync(executionContext, state, actions, depth, rootStepId);
}
catch (FailedToResolveActionDownloadInfoException ex)
{
// Log the error and fail the PrepareActionsAsync Initialization.
Trace.Error($"Caught exception from PrepareActionsAsync Initialization: {ex}");
executionContext.InfrastructureError(ex.Message);
executionContext.Result = TaskResult.Failed;
throw;
}
if (!FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables)) if (!FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables))
{ {
if (state.ImagesToPull.Count > 0) if (state.ImagesToPull.Count > 0)
@@ -317,28 +303,15 @@ namespace GitHub.Runner.Worker
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry) if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
{ {
if (FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables)) Trace.Info("Load action that reference container from registry.");
CachedActionContainers.TryGetValue(action.Id, out var container);
ArgUtil.NotNull(container, nameof(container));
definition.Data.Execution = new ContainerActionExecutionData()
{ {
Trace.Info("Load action that will run container through container hooks."); Image = container.ContainerImage
var containerAction = action.Reference as Pipelines.ContainerRegistryReference; };
definition.Data.Execution = new ContainerActionExecutionData()
{
Image = containerAction.Image,
};
Trace.Info($"Using action container image: {containerAction.Image}.");
}
else
{
Trace.Info("Load action that reference container from registry.");
CachedActionContainers.TryGetValue(action.Id, out var container);
ArgUtil.NotNull(container, nameof(container));
definition.Data.Execution = new ContainerActionExecutionData()
{
Image = container.ContainerImage
};
Trace.Info($"Using action container image: {container.ContainerImage}."); Trace.Info($"Using action container image: {container.ContainerImage}.");
}
} }
else if (action.Reference.Type == Pipelines.ActionSourceType.Repository) else if (action.Reference.Type == Pipelines.ActionSourceType.Repository)
{ {
@@ -675,21 +648,13 @@ namespace GitHub.Runner.Worker
} }
// Resolve download info // Resolve download info
var launchServer = HostContext.GetService<ILaunchServer>();
var jobServer = HostContext.GetService<IJobServer>(); var jobServer = HostContext.GetService<IJobServer>();
var actionDownloadInfos = default(WebApi.ActionDownloadInfoCollection); var actionDownloadInfos = default(WebApi.ActionDownloadInfoCollection);
for (var attempt = 1; attempt <= 3; attempt++) for (var attempt = 1; attempt <= 3; attempt++)
{ {
try try
{ {
if (MessageUtil.IsRunServiceJob(executionContext.Global.Variables.Get(Constants.Variables.System.JobRequestType))) actionDownloadInfos = await jobServer.ResolveActionDownloadInfoAsync(executionContext.Global.Plan.ScopeIdentifier, executionContext.Global.Plan.PlanType, executionContext.Global.Plan.PlanId, executionContext.Root.Id, new WebApi.ActionReferenceList { Actions = actionReferences }, executionContext.CancellationToken);
{
actionDownloadInfos = await launchServer.ResolveActionsDownloadInfoAsync(executionContext.Global.Plan.PlanId, executionContext.Root.Id, new WebApi.ActionReferenceList { Actions = actionReferences }, executionContext.CancellationToken);
}
else
{
actionDownloadInfos = await jobServer.ResolveActionDownloadInfoAsync(executionContext.Global.Plan.ScopeIdentifier, executionContext.Global.Plan.PlanType, executionContext.Global.Plan.PlanId, executionContext.Root.Id, new WebApi.ActionReferenceList { Actions = actionReferences }, executionContext.CancellationToken);
}
break; break;
} }
catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is cancelled. catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is cancelled.
@@ -1042,7 +1007,7 @@ namespace GitHub.Runner.Worker
if (actionDefinitionData.Execution.ExecutionType == ActionExecutionType.Container) if (actionDefinitionData.Execution.ExecutionType == ActionExecutionType.Container)
{ {
var containerAction = actionDefinitionData.Execution as ContainerActionExecutionData; var containerAction = actionDefinitionData.Execution as ContainerActionExecutionData;
if (DockerUtil.IsDockerfile(containerAction.Image)) if (containerAction.Image.EndsWith("Dockerfile") || containerAction.Image.EndsWith("dockerfile"))
{ {
var dockerFileFullPath = Path.Combine(actionEntryDirectory, containerAction.Image); var dockerFileFullPath = Path.Combine(actionEntryDirectory, containerAction.Image);
executionContext.Debug($"Dockerfile for action: '{dockerFileFullPath}'."); executionContext.Debug($"Dockerfile for action: '{dockerFileFullPath}'.");
@@ -1127,16 +1092,8 @@ namespace GitHub.Runner.Worker
} }
else else
{ {
var reference = repositoryReference.Name; var fullPath = IOUtil.ResolvePath(actionEntryDirectory, "."); // resolve full path without access filesystem.
if (!string.IsNullOrEmpty(repositoryReference.Path)) throw new InvalidOperationException($"Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under '{fullPath}'. Did you forget to run actions/checkout before running your local action?");
{
reference = $"{reference}/{repositoryReference.Path}";
}
if (!string.IsNullOrEmpty(repositoryReference.Ref))
{
reference = $"{reference}@{repositoryReference.Ref}";
}
throw new InvalidOperationException($"Can't find 'action.yml', 'action.yaml' or 'Dockerfile' for action '{reference}'.");
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
@@ -448,7 +448,7 @@ namespace GitHub.Runner.Worker
}; };
} }
} }
else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase) || else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase)||
string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase)) string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase))
{ {
if (string.IsNullOrEmpty(mainToken?.Value)) if (string.IsNullOrEmpty(mainToken?.Value))

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
namespace GitHub.Runner.Worker namespace GitHub.Runner.Worker
@@ -30,4 +30,4 @@ namespace GitHub.Runner.Worker
return $"An action could not be found at the URI '{actionUri}'"; return $"An action could not be found at the URI '{actionUri}'";
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.ObjectTemplating; using GitHub.DistributedTask.ObjectTemplating;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Text; using System.Text;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
@@ -83,7 +83,7 @@ namespace GitHub.Runner.Worker.Container.ContainerHooks
public HookContainer(ContainerInfo container) public HookContainer(ContainerInfo container)
{ {
Image = container.ContainerImage; Image = container.ContainerImage;
EntryPointArgs = container.ContainerEntryPointArgs?.Split(' ').Select(arg => arg.Trim()).Where(arg => !string.IsNullOrEmpty(arg)) ?? new List<string>(); EntryPointArgs = container.ContainerEntryPointArgs?.Split(' ').Select(arg => arg.Trim()) ?? new List<string>();
EntryPoint = container.ContainerEntryPoint; EntryPoint = container.ContainerEntryPoint;
WorkingDirectory = container.ContainerWorkDirectory; WorkingDirectory = container.ContainerWorkDirectory;
CreateOptions = container.ContainerCreateOptions; CreateOptions = container.ContainerCreateOptions;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace GitHub.Runner.Worker.Container namespace GitHub.Runner.Worker.Container
@@ -66,16 +65,6 @@ namespace GitHub.Runner.Worker.Container
return ""; return "";
} }
public static bool IsDockerfile(string image)
{
if (image.StartsWith("docker://", StringComparison.OrdinalIgnoreCase))
{
return false;
}
var imageWithoutPath = image.Split('/').Last();
return imageWithoutPath.StartsWith("Dockerfile.", StringComparison.OrdinalIgnoreCase) || imageWithoutPath.EndsWith("Dockerfile", StringComparison.OrdinalIgnoreCase);
}
public static string CreateEscapedOption(string flag, string key) public static string CreateEscapedOption(string flag, string key)
{ {
if (String.IsNullOrEmpty(key)) if (String.IsNullOrEmpty(key))
@@ -107,7 +96,7 @@ namespace GitHub.Runner.Worker.Container
// https://docs.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs?redirectedfrom=MSDN&view=net-6.0#remarks // https://docs.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs?redirectedfrom=MSDN&view=net-6.0#remarks
// First, find any \ followed by a " and double the number of \ + 1. // First, find any \ followed by a " and double the number of \ + 1.
value = QuoteEscape.Replace(value, @"$1$1\" + "\""); value = QuoteEscape.Replace(value, @"$1$1\" + "\"");
// Next, what if it ends in `\`, it would escape the end quote. So, we need to detect that at the end of the string and perform the same escape // Next, what if it ends in `\`, it would escape the end quote. So, we need to detect that at the end of the string and perform the same escape
// Luckily, we can just use the $ character with detects the end of string in regex // Luckily, we can just use the $ character with detects the end of string in regex
value = EndOfStringEscape.Replace(value, @"$1$1"); value = EndOfStringEscape.Replace(value, @"$1$1");

View File

@@ -32,7 +32,7 @@ namespace GitHub.Runner.Worker
{ {
private static string DateTimeFormat = "yyyyMMdd-HHmmss"; private static string DateTimeFormat = "yyyyMMdd-HHmmss";
public void UploadDiagnosticLogs(IExecutionContext executionContext, public void UploadDiagnosticLogs(IExecutionContext executionContext,
IExecutionContext parentContext, IExecutionContext parentContext,
Pipelines.AgentJobRequestMessage message, Pipelines.AgentJobRequestMessage message,
DateTime jobStartTimeUtc) DateTime jobStartTimeUtc)
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -24,16 +24,10 @@ using Pipelines = GitHub.DistributedTask.Pipelines;
namespace GitHub.Runner.Worker namespace GitHub.Runner.Worker
{ {
public static class ExecutionContextType public class ExecutionContextType
{ {
public const string Job = "Job"; public static string Job = "Job";
public const string Task = "Task"; public static string Task = "Task";
}
public record ExecutionContextLogOptions(bool WriteToLog, string LogMessageOverride)
{
public static readonly ExecutionContextLogOptions None = new(false, null);
public static readonly ExecutionContextLogOptions Default = new(true, null);
} }
[ServiceLocator(Default = typeof(ExecutionContext))] [ServiceLocator(Default = typeof(ExecutionContext))]
@@ -78,7 +72,6 @@ namespace GitHub.Runner.Worker
List<string> StepEnvironmentOverrides { get; } List<string> StepEnvironmentOverrides { get; }
ExecutionContext Root { get; } ExecutionContext Root { get; }
ExecutionContext Parent { get; }
// Initialize // Initialize
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token); void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
@@ -100,7 +93,7 @@ namespace GitHub.Runner.Worker
void SetGitHubContext(string name, string value); void SetGitHubContext(string name, string value);
void SetOutput(string name, string value, out string reference); void SetOutput(string name, string value, out string reference);
void SetTimeout(TimeSpan? timeout); void SetTimeout(TimeSpan? timeout);
void AddIssue(Issue issue, ExecutionContextLogOptions logOptions); void AddIssue(Issue issue, string message = null);
void Progress(int percentage, string currentOperation = null); void Progress(int percentage, string currentOperation = null);
void UpdateDetailTimelineRecord(TimelineRecord record); void UpdateDetailTimelineRecord(TimelineRecord record);
@@ -126,7 +119,7 @@ namespace GitHub.Runner.Worker
public sealed class ExecutionContext : RunnerService, IExecutionContext public sealed class ExecutionContext : RunnerService, IExecutionContext
{ {
private const int _maxCountPerIssueType = 10; private const int _maxIssueCount = 10;
private const int _throttlingDelayReportThreshold = 10 * 1000; // Don't report throttling with less than 10 seconds delay private const int _throttlingDelayReportThreshold = 10 * 1000; // Don't report throttling with less than 10 seconds delay
private const int _maxIssueMessageLength = 4096; // Don't send issue with huge message since we can't forward them from actions to check annotation. private const int _maxIssueMessageLength = 4096; // Don't send issue with huge message since we can't forward them from actions to check annotation.
private const int _maxIssueCountInTelemetry = 3; // Only send the first 3 issues to telemetry private const int _maxIssueCountInTelemetry = 3; // Only send the first 3 issues to telemetry
@@ -134,10 +127,8 @@ namespace GitHub.Runner.Worker
private readonly TimelineRecord _record = new(); private readonly TimelineRecord _record = new();
private readonly Dictionary<Guid, TimelineRecord> _detailRecords = new(); private readonly Dictionary<Guid, TimelineRecord> _detailRecords = new();
private readonly List<Issue> _embeddedIssueCollector;
private readonly object _loggerLock = new(); private readonly object _loggerLock = new();
private readonly object _matchersLock = new(); private readonly object _matchersLock = new();
private readonly ExecutionContext _parentExecutionContext;
private event OnMatcherChanged _onMatcherChanged; private event OnMatcherChanged _onMatcherChanged;
@@ -145,6 +136,7 @@ namespace GitHub.Runner.Worker
private IPagingLogger _logger; private IPagingLogger _logger;
private IJobServerQueue _jobServerQueue; private IJobServerQueue _jobServerQueue;
private ExecutionContext _parentExecutionContext;
private Guid _mainTimelineId; private Guid _mainTimelineId;
private Guid _detailTimelineId; private Guid _detailTimelineId;
@@ -158,29 +150,6 @@ namespace GitHub.Runner.Worker
private long _totalThrottlingDelayInMilliseconds = 0; private long _totalThrottlingDelayInMilliseconds = 0;
private bool _stepTelemetryPublished = false; private bool _stepTelemetryPublished = false;
public ExecutionContext()
: this(parent: null, embedded: false)
{
}
private ExecutionContext(ExecutionContext parent, bool embedded)
{
if (embedded)
{
ArgUtil.NotNull(parent, nameof(parent));
}
_parentExecutionContext = parent;
this.IsEmbedded = embedded;
this.StepTelemetry = new ActionsStepTelemetry
{
IsEmbedded = embedded
};
//Embedded Execution Contexts pseudo-inherit their parent's embeddedIssueCollector.
_embeddedIssueCollector = embedded ? parent._embeddedIssueCollector : new();
}
public Guid Id => _record.Id; public Guid Id => _record.Id;
public Guid EmbeddedId { get; private set; } public Guid EmbeddedId { get; private set; }
public string ScopeName { get; private set; } public string ScopeName { get; private set; }
@@ -193,7 +162,7 @@ namespace GitHub.Runner.Worker
public Dictionary<string, VariableValue> JobOutputs { get; private set; } public Dictionary<string, VariableValue> JobOutputs { get; private set; }
public ActionsEnvironmentReference ActionsEnvironment { get; private set; } public ActionsEnvironmentReference ActionsEnvironment { get; private set; }
public ActionsStepTelemetry StepTelemetry { get; private init; } public ActionsStepTelemetry StepTelemetry { get; } = new ActionsStepTelemetry();
public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData(); public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData();
public IList<IFunctionInfo> ExpressionFunctions { get; } = new List<IFunctionInfo>(); public IList<IFunctionInfo> ExpressionFunctions { get; } = new List<IFunctionInfo>();
@@ -218,7 +187,7 @@ namespace GitHub.Runner.Worker
// An embedded execution context shares the same record ID, record name, and logger // An embedded execution context shares the same record ID, record name, and logger
// as its enclosing execution context. // as its enclosing execution context.
public bool IsEmbedded { get; private init; } public bool IsEmbedded { get; private set; }
public TaskResult? Result public TaskResult? Result
{ {
@@ -265,14 +234,6 @@ namespace GitHub.Runner.Worker
} }
} }
public ExecutionContext Parent
{
get
{
return _parentExecutionContext;
}
}
public JobContext JobContext public JobContext JobContext
{ {
get get
@@ -361,7 +322,7 @@ namespace GitHub.Runner.Worker
{ {
Trace.Entering(); Trace.Entering();
var child = new ExecutionContext(this, isEmbedded); var child = new ExecutionContext();
child.Initialize(HostContext); child.Initialize(HostContext);
child.Global = Global; child.Global = Global;
child.ScopeName = scopeName; child.ScopeName = scopeName;
@@ -386,6 +347,7 @@ namespace GitHub.Runner.Worker
child.ExpressionFunctions.Add(item); child.ExpressionFunctions.Add(item);
} }
child._cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource(); child._cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource();
child._parentExecutionContext = this;
child.EchoOnActionCommand = EchoOnActionCommand; child.EchoOnActionCommand = EchoOnActionCommand;
if (recordOrder != null) if (recordOrder != null)
@@ -406,16 +368,18 @@ namespace GitHub.Runner.Worker
child._logger.Setup(_mainTimelineId, recordId); child._logger.Setup(_mainTimelineId, recordId);
} }
child.IsEmbedded = isEmbedded;
child.StepTelemetry.StepId = recordId; child.StepTelemetry.StepId = recordId;
child.StepTelemetry.Stage = stage.ToString(); child.StepTelemetry.Stage = stage.ToString();
child.StepTelemetry.StepContextName = child.GetFullyQualifiedContextName(); child.StepTelemetry.IsEmbedded = isEmbedded;
child.StepTelemetry.StepContextName = child.GetFullyQualifiedContextName(); ;
return child; return child;
} }
/// <summary> /// <summary>
/// An embedded execution context shares the same record ID, record name, logger, /// An embedded execution context shares the same record ID, record name, logger,
/// but NOT the cancellation token (just like workflow steps contexts - they don't share a token) /// and a linked cancellation token.
/// </summary> /// </summary>
public IExecutionContext CreateEmbeddedChild( public IExecutionContext CreateEmbeddedChild(
string scopeName, string scopeName,
@@ -425,7 +389,7 @@ namespace GitHub.Runner.Worker
Dictionary<string, string> intraActionState = null, Dictionary<string, string> intraActionState = null,
string siblingScopeName = null) string siblingScopeName = null)
{ {
return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, stage, logger: _logger, isEmbedded: true, cancellationTokenSource: null, intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName); return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, stage, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token), intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName);
} }
public void Start(string currentOperation = null) public void Start(string currentOperation = null)
@@ -450,24 +414,13 @@ namespace GitHub.Runner.Worker
this.Warning($"The job has experienced {TimeSpan.FromMilliseconds(_totalThrottlingDelayInMilliseconds).TotalSeconds} seconds total delay caused by server throttling."); this.Warning($"The job has experienced {TimeSpan.FromMilliseconds(_totalThrottlingDelayInMilliseconds).TotalSeconds} seconds total delay caused by server throttling.");
} }
DateTime now = DateTime.UtcNow;
_record.CurrentOperation = currentOperation ?? _record.CurrentOperation; _record.CurrentOperation = currentOperation ?? _record.CurrentOperation;
_record.ResultCode = resultCode ?? _record.ResultCode; _record.ResultCode = resultCode ?? _record.ResultCode;
_record.FinishTime = now; _record.FinishTime = DateTime.UtcNow;
_record.PercentComplete = 100; _record.PercentComplete = 100;
_record.Result = _record.Result ?? TaskResult.Succeeded; _record.Result = _record.Result ?? TaskResult.Succeeded;
_record.State = TimelineRecordState.Completed; _record.State = TimelineRecordState.Completed;
// Before our main timeline's final QueueTimelineRecordUpdate,
// inject any issues collected by embedded ExecutionContexts.
if (!this.IsEmbedded)
{
foreach (var issue in _embeddedIssueCollector)
{
AddIssue(issue, ExecutionContextLogOptions.None);
}
}
_jobServerQueue.QueueTimelineRecordUpdate(_mainTimelineId, _record); _jobServerQueue.QueueTimelineRecordUpdate(_mainTimelineId, _record);
// complete all detail timeline records. // complete all detail timeline records.
@@ -475,7 +428,7 @@ namespace GitHub.Runner.Worker
{ {
foreach (var record in _detailRecords) foreach (var record in _detailRecords)
{ {
record.Value.FinishTime = record.Value.FinishTime ?? now; record.Value.FinishTime = record.Value.FinishTime ?? DateTime.UtcNow;
record.Value.PercentComplete = record.Value.PercentComplete ?? 100; record.Value.PercentComplete = record.Value.PercentComplete ?? 100;
record.Value.Result = record.Value.Result ?? TaskResult.Succeeded; record.Value.Result = record.Value.Result ?? TaskResult.Succeeded;
record.Value.State = TimelineRecordState.Completed; record.Value.State = TimelineRecordState.Completed;
@@ -486,32 +439,28 @@ namespace GitHub.Runner.Worker
PublishStepTelemetry(); PublishStepTelemetry();
if (_record.RecordType == "Task") var stepResult = new StepResult
{ {
var stepResult = new StepResult ExternalID = _record.Id,
Conclusion = _record.Result ?? TaskResult.Succeeded,
Status = _record.State,
Number = _record.Order,
Name = _record.Name,
StartedAt = _record.StartTime,
CompletedAt = _record.FinishTime,
Annotations = new List<Annotation>()
};
_record.Issues?.ForEach(issue =>
{
var annotation = issue.ToAnnotation();
if (annotation != null)
{ {
ExternalID = _record.Id, stepResult.Annotations.Add(annotation.Value);
Conclusion = _record.Result ?? TaskResult.Succeeded, }
Status = _record.State, });
Number = _record.Order,
Name = _record.Name,
StartedAt = _record.StartTime,
CompletedAt = _record.FinishTime,
Annotations = new List<Annotation>()
};
_record.Issues?.ForEach(issue =>
{
var annotation = issue.ToAnnotation();
if (annotation != null)
{
stepResult.Annotations.Add(annotation.Value);
}
});
Global.StepsResult.Add(stepResult);
}
Global.StepsResult.Add(stepResult);
if (Root != this) if (Root != this)
{ {
@@ -606,33 +555,9 @@ namespace GitHub.Runner.Worker
if (timeout != null) if (timeout != null)
{ {
_cancellationTokenSource.CancelAfter(timeout.Value); _cancellationTokenSource.CancelAfter(timeout.Value);
m_timeoutStartedAt = DateTime.UtcNow;
m_timeout = timeout.Value;
} }
} }
DateTime? m_timeoutStartedAt;
TimeSpan? m_timeout;
public TimeSpan? GetRemainingTimeout()
{
if (m_timeoutStartedAt != null && m_timeout != null)
{
var elapsedSinceTimeoutSet = DateTime.UtcNow - m_timeoutStartedAt.Value;
var remainingTimeout = m_timeout.Value - elapsedSinceTimeoutSet;
if (remainingTimeout.Ticks > 0)
{
return remainingTimeout;
}
else
{
// there was a timeout and it has expired
return TimeSpan.Zero;
}
}
// no timeout was ever set
return null;
}
public void Progress(int percentage, string currentOperation = null) public void Progress(int percentage, string currentOperation = null)
{ {
if (percentage > 100 || percentage < 0) if (percentage > 100 || percentage < 0)
@@ -647,10 +572,14 @@ namespace GitHub.Runner.Worker
} }
// This is not thread safe, the caller need to take lock before calling issue() // This is not thread safe, the caller need to take lock before calling issue()
public void AddIssue(Issue issue, ExecutionContextLogOptions logOptions) public void AddIssue(Issue issue, string logMessage = null)
{ {
ArgUtil.NotNull(issue, nameof(issue)); ArgUtil.NotNull(issue, nameof(issue));
ArgUtil.NotNull(logOptions, nameof(logOptions));
if (string.IsNullOrEmpty(logMessage))
{
logMessage = issue.Message;
}
issue.Message = HostContext.SecretMasker.MaskSecrets(issue.Message); issue.Message = HostContext.SecretMasker.MaskSecrets(issue.Message);
if (issue.Message.Length > _maxIssueMessageLength) if (issue.Message.Length > _maxIssueMessageLength)
@@ -665,64 +594,53 @@ namespace GitHub.Runner.Worker
issue.Data["stepNumber"] = _record.Order.ToString(); issue.Data["stepNumber"] = _record.Order.ToString();
} }
string wellKnownTag = null; if (issue.Type == IssueType.Error)
Int32 previousCountForIssueType = 0;
Action incrementIssueTypeCount = NoOp;
switch (issue.Type)
{ {
case IssueType.Error: if (!string.IsNullOrEmpty(logMessage))
wellKnownTag = WellKnownTags.Error; {
previousCountForIssueType = _record.ErrorCount; long logLineNumber = Write(WellKnownTags.Error, logMessage);
incrementIssueTypeCount = () => { _record.ErrorCount++; }; issue.Data["logFileLineNumber"] = logLineNumber.ToString();
break; }
case IssueType.Warning:
wellKnownTag = WellKnownTags.Warning; if (_record.ErrorCount < _maxIssueCount)
previousCountForIssueType = _record.WarningCount;
incrementIssueTypeCount = () => { _record.WarningCount++; };
break;
case IssueType.Notice:
wellKnownTag = WellKnownTags.Notice;
previousCountForIssueType = _record.NoticeCount;
incrementIssueTypeCount = () => { _record.NoticeCount++; };
break;
}
if (!string.IsNullOrEmpty(wellKnownTag))
{
if (!this.IsEmbedded && previousCountForIssueType < _maxCountPerIssueType)
{ {
incrementIssueTypeCount();
_record.Issues.Add(issue); _record.Issues.Add(issue);
} }
if (logOptions.WriteToLog) _record.ErrorCount++;
}
else if (issue.Type == IssueType.Warning)
{
if (!string.IsNullOrEmpty(logMessage))
{ {
string logMessage = issue.Message; long logLineNumber = Write(WellKnownTags.Warning, logMessage);
if (!string.IsNullOrEmpty(logOptions.LogMessageOverride)) issue.Data["logFileLineNumber"] = logLineNumber.ToString();
{
logMessage = logOptions.LogMessageOverride;
}
if (!string.IsNullOrEmpty(logMessage))
{
// Note that ::Write() has its own secret-masking logic.
long logLineNumber = Write(wellKnownTag, logMessage);
issue.Data["logFileLineNumber"] = logLineNumber.ToString();
}
} }
if (_record.WarningCount < _maxIssueCount)
{
_record.Issues.Add(issue);
}
_record.WarningCount++;
}
else if (issue.Type == IssueType.Notice)
{
if (!string.IsNullOrEmpty(logMessage))
{
long logLineNumber = Write(WellKnownTags.Notice, logMessage);
issue.Data["logFileLineNumber"] = logLineNumber.ToString();
}
if (_record.NoticeCount < _maxIssueCount)
{
_record.Issues.Add(issue);
}
_record.NoticeCount++;
} }
// Embedded ExecutionContexts (a.k.a. Composite actions) should never upload a timeline record to the server. _jobServerQueue.QueueTimelineRecordUpdate(_mainTimelineId, _record);
// Instead, we store processed issues on a shared (psuedo-inherited) list (belonging to the closest
// non-embedded ancestor ExecutionContext) so that they can be processed when that ancestor completes.
if (this.IsEmbedded)
{
_embeddedIssueCollector.Add(issue);
}
else
{
_jobServerQueue.QueueTimelineRecordUpdate(_mainTimelineId, _record);
}
} }
public void UpdateDetailTimelineRecord(TimelineRecord record) public void UpdateDetailTimelineRecord(TimelineRecord record)
@@ -839,9 +757,6 @@ namespace GitHub.Runner.Worker
// File table // File table
Global.FileTable = new List<String>(message.FileTable ?? new string[0]); Global.FileTable = new List<String>(message.FileTable ?? new string[0]);
// What type of job request is running (i.e. Run Service vs. pipelines)
Global.Variables.Set(Constants.Variables.System.JobRequestType, message.MessageType);
// Expression values // Expression values
if (message.ContextData?.Count > 0) if (message.ContextData?.Count > 0)
{ {
@@ -1096,7 +1011,8 @@ namespace GitHub.Runner.Worker
StepTelemetry.FinishTime = _record.FinishTime; StepTelemetry.FinishTime = _record.FinishTime;
} }
if (!IsEmbedded) if (!IsEmbedded &&
_record.Issues.Count > 0)
{ {
foreach (var issue in _record.Issues) foreach (var issue in _record.Issues)
{ {
@@ -1262,11 +1178,6 @@ namespace GitHub.Runner.Worker
UpdateGlobalStepsContext(); UpdateGlobalStepsContext();
} }
private static void NoOp()
{
}
} }
// The Error/Warning/etc methods are created as extension methods to simplify unit testing. // The Error/Warning/etc methods are created as extension methods to simplify unit testing.
@@ -1291,22 +1202,19 @@ namespace GitHub.Runner.Worker
// Do not add a format string overload. See comment on ExecutionContext.Write(). // Do not add a format string overload. See comment on ExecutionContext.Write().
public static void Error(this IExecutionContext context, string message) public static void Error(this IExecutionContext context, string message)
{ {
var issue = new Issue() { Type = IssueType.Error, Message = message }; context.AddIssue(new Issue() { Type = IssueType.Error, Message = message });
context.AddIssue(issue, ExecutionContextLogOptions.Default);
} }
// Do not add a format string overload. See comment on ExecutionContext.Write(). // Do not add a format string overload. See comment on ExecutionContext.Write().
public static void InfrastructureError(this IExecutionContext context, string message) public static void InfrastructureError(this IExecutionContext context, string message)
{ {
var issue = new Issue() { Type = IssueType.Error, Message = message, IsInfrastructureIssue = true }; context.AddIssue(new Issue() { Type = IssueType.Error, Message = message, IsInfrastructureIssue = true });
context.AddIssue(issue, ExecutionContextLogOptions.Default);
} }
// Do not add a format string overload. See comment on ExecutionContext.Write(). // Do not add a format string overload. See comment on ExecutionContext.Write().
public static void Warning(this IExecutionContext context, string message) public static void Warning(this IExecutionContext context, string message)
{ {
var issue = new Issue() { Type = IssueType.Warning, Message = message }; context.AddIssue(new Issue() { Type = IssueType.Warning, Message = message });
context.AddIssue(issue, ExecutionContextLogOptions.Default);
} }
// Do not add a format string overload. See comment on ExecutionContext.Write(). // Do not add a format string overload. See comment on ExecutionContext.Write().
@@ -1392,12 +1300,6 @@ namespace GitHub.Runner.Worker
{ {
foreach (var key in dict.Keys.ToList()) foreach (var key in dict.Keys.ToList())
{ {
if (key == PipelineTemplateConstants.HostWorkspace)
{
// The HostWorkspace context var is excluded so that there is a var that always points to the host path.
// This var can be used to translate back from container paths, e.g. in HashFilesFunction, which always runs on the host machine
continue;
}
if (dict[key] is StringContextData) if (dict[key] is StringContextData)
{ {
var value = dict[key].ToString(); var value = dict[key].ToString();
@@ -1444,15 +1346,7 @@ namespace GitHub.Runner.Worker
public void Error(string format, params Object[] args) public void Error(string format, params Object[] args)
{ {
/* TraceWriter should be used for logging and not creating erros. */ _executionContext.Error(string.Format(CultureInfo.CurrentCulture, format, args));
if (logTemplateErrorsAsDebugMessages())
{
_executionContext.Debug(string.Format(CultureInfo.CurrentCulture, format, args));
}
else
{
_executionContext.Error(string.Format(CultureInfo.CurrentCulture, format, args));
}
} }
public void Info(string format, params Object[] args) public void Info(string format, params Object[] args)
@@ -1465,18 +1359,8 @@ namespace GitHub.Runner.Worker
// todo: switch to verbose? // todo: switch to verbose?
_executionContext.Debug(string.Format(CultureInfo.CurrentCulture, $"{format}", args)); _executionContext.Debug(string.Format(CultureInfo.CurrentCulture, $"{format}", args));
} }
private bool logTemplateErrorsAsDebugMessages()
{
if (_executionContext.Global.Variables.TryGetValue(Constants.Runner.Features.LogTemplateErrorsAsDebugMessages, out var logErrorsAsDebug))
{
return StringUtil.ConvertToBoolean(logErrorsAsDebug, defaultValue: false);
}
return false;
}
} }
public static class WellKnownTags public static class WellKnownTags
{ {
public static readonly string Section = "##[section]"; public static readonly string Section = "##[section]";

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
using GitHub.DistributedTask.Expressions2.Sdk; using GitHub.DistributedTask.Expressions2.Sdk;
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ContextData;
@@ -26,18 +26,11 @@ namespace GitHub.Runner.Worker.Expressions
ArgUtil.NotNull(githubContextData, nameof(githubContextData)); ArgUtil.NotNull(githubContextData, nameof(githubContextData));
var githubContext = githubContextData as DictionaryContextData; var githubContext = githubContextData as DictionaryContextData;
ArgUtil.NotNull(githubContext, nameof(githubContext)); ArgUtil.NotNull(githubContext, nameof(githubContext));
githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out var workspace);
if (!githubContext.TryGetValue(PipelineTemplateConstants.HostWorkspace, out var workspace))
{
githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out workspace);
}
ArgUtil.NotNull(workspace, nameof(workspace));
var workspaceData = workspace as StringContextData; var workspaceData = workspace as StringContextData;
ArgUtil.NotNull(workspaceData, nameof(workspaceData)); ArgUtil.NotNull(workspaceData, nameof(workspaceData));
string githubWorkspace = workspaceData.Value; string githubWorkspace = workspaceData.Value;
bool followSymlink = false; bool followSymlink = false;
List<string> patterns = new(); List<string> patterns = new();
var firstParameter = true; var firstParameter = true;
@@ -143,4 +136,4 @@ namespace GitHub.Runner.Worker.Expressions
} }
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using System; using System;
@@ -281,7 +281,7 @@ namespace GitHub.Runner.Worker
} }
} }
public sealed class EnvFileKeyValuePairs : IEnumerable<KeyValuePair<string, string>> public sealed class EnvFileKeyValuePairs: IEnumerable<KeyValuePair<string, string>>
{ {
private IExecutionContext _context; private IExecutionContext _context;
private string _filePath; private string _filePath;
@@ -322,28 +322,28 @@ namespace GitHub.Runner.Worker
var equalsIndex = line.IndexOf("=", StringComparison.Ordinal); var equalsIndex = line.IndexOf("=", StringComparison.Ordinal);
var heredocIndex = line.IndexOf("<<", StringComparison.Ordinal); var heredocIndex = line.IndexOf("<<", StringComparison.Ordinal);
// Heredoc style NAME=<<EOF (where EOF is typically randomly-generated Base64 and may include an '=' character) // Normal style NAME=VALUE
// see https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings if (equalsIndex >= 0 && (heredocIndex < 0 || equalsIndex < heredocIndex))
// "key=<<EOF is also considered heredoc where the key contains an =. {
// Also we detect heredoc if whitespace chars exist between = and <<. (ex: "key <<EOF") var split = line.Split(new[] { '=' }, 2, StringSplitOptions.None);
var isHeredoc = heredocIndex >= 0 && if (string.IsNullOrEmpty(line))
( {
equalsIndex < 0 || throw new Exception($"Invalid format '{line}'. Name must not be empty");
heredocIndex < equalsIndex || }
(
heredocIndex > equalsIndex && key = split[0];
OnlyContainsWhiteSpaceBetweenPositions(line, equalsIndex, heredocIndex) output = split[1];
) }
);
// Heredoc style NAME<<EOF
if (isHeredoc) else if (heredocIndex >= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex))
{ {
var split = line.Split(new[] { "<<" }, 2, StringSplitOptions.None); var split = line.Split(new[] { "<<" }, 2, StringSplitOptions.None);
if (string.IsNullOrEmpty(split[0]) || string.IsNullOrEmpty(split[1])) if (string.IsNullOrEmpty(split[0]) || string.IsNullOrEmpty(split[1]))
{ {
throw new Exception($"Invalid format '{line}'. Name must not be empty and delimiter must not be empty"); throw new Exception($"Invalid format '{line}'. Name must not be empty and delimiter must not be empty");
} }
key = split[0].Trim().TrimEnd('='); key = split[0];
var delimiter = split[1]; var delimiter = split[1];
var startIndex = index; // Start index of the value (inclusive) var startIndex = index; // Start index of the value (inclusive)
var endIndex = index; // End index of the value (exclusive) var endIndex = index; // End index of the value (exclusive)
@@ -364,18 +364,6 @@ namespace GitHub.Runner.Worker
output = endIndex > startIndex ? text.Substring(startIndex, endIndex - startIndex) : string.Empty; output = endIndex > startIndex ? text.Substring(startIndex, endIndex - startIndex) : string.Empty;
} }
// Normal style NAME=VALUE, can have << in the value.
else if (equalsIndex >= 0)
{
var split = line.Split(new[] { '=' }, 2, StringSplitOptions.None);
if (string.IsNullOrEmpty(line))
{
throw new Exception($"Invalid format '{line}'. Name must not be empty");
}
key = split[0];
output = split[1];
}
else else
{ {
throw new Exception($"Invalid format '{line}'"); throw new Exception($"Invalid format '{line}'");
@@ -395,32 +383,6 @@ namespace GitHub.Runner.Worker
return GetEnumerator(); return GetEnumerator();
} }
// accepts a string, two indexes, and returns true if only whitespace chars exist between those two indexes (non-inclusive)
private static bool OnlyContainsWhiteSpaceBetweenPositions(string str, int pos1, int pos2)
{
// Check if the provided positions are valid
if (pos1 < 0 || pos2 < 0 || pos1 >= str.Length || pos2 >= str.Length)
{
throw new ArgumentOutOfRangeException("OnlyContainsWhiteSpaceBetweenPositions: Positions should be within the string length.");
}
// Ensure pos1 is always the smaller position
if (pos2 < pos1)
{
throw new ArgumentException("OnlyContainsWhiteSpaceBetweenPositions: pos1 must be less than or equal to pos2.");
}
for (int i = pos1 + 1; i < pos2; i++)
{
if (!char.IsWhiteSpace(str[i]))
{
return false;
}
}
return true;
}
private static string ReadLine( private static string ReadLine(
string text, string text,
ref int index) ref int index)

View File

@@ -1,4 +1,4 @@
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ContextData;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

Some files were not shown because too many files have changed in this diff Show More