mirror of
https://github.com/actions/runner.git
synced 2025-12-11 21:06:55 +00:00
Compare commits
14 Commits
test
...
docker-log
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f8d55dcb8 | ||
|
|
5e0c2ef816 | ||
|
|
95459dea5f | ||
|
|
59894790de | ||
|
|
cba19c4d7e | ||
|
|
01fd04464d | ||
|
|
1cb1779d6b | ||
|
|
42c86665a7 | ||
|
|
f9c2bf1dd7 | ||
|
|
84e7949457 | ||
|
|
694d73d43c | ||
|
|
352f201c62 | ||
|
|
503e50acb9 | ||
|
|
813af29886 |
@@ -1,11 +1,6 @@
|
|||||||
## Features
|
|
||||||
- Added support for a JIT runner config (#1925)
|
|
||||||
- Added `ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION` env option to force actions to run on a specific node version (#1913)
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Fixed a bug where container hooks passed in path as a string rather then an array of strings (#1948)
|
- Fixed an issue where job and service container envs were corrupted (#2091)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- Minor cleanup of error messages when running container hooks (#1949)
|
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||||
@@ -32,7 +27,7 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
|
|||||||
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
## [Pre-release] OSX arm64 (Apple silicon)
|
## OSX arm64 (Apple silicon)
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
|
|||||||
@@ -120,6 +120,9 @@ if ERRORLEVEL 1 (
|
|||||||
|
|
||||||
echo [%date% %time%] Update succeed >> "%logfile%" 2>&1
|
echo [%date% %time%] Update succeed >> "%logfile%" 2>&1
|
||||||
|
|
||||||
|
type nul > update.finished
|
||||||
|
echo [%date% %time%] update.finished file creation succeed >> "%logfile%" 2>&1
|
||||||
|
|
||||||
rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
||||||
rem runner service host can base on the log file name determin the result of the runner update
|
rem runner service host can base on the log file name determin the result of the runner update
|
||||||
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1
|
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ fi
|
|||||||
|
|
||||||
date "+[%F %T-%4N] Update succeed" >> "$logfile"
|
date "+[%F %T-%4N] Update succeed" >> "$logfile"
|
||||||
|
|
||||||
|
touch update.finished
|
||||||
|
date "+[%F %T-%4N] update.finished file creation succeed" >> "$logfile"
|
||||||
|
|
||||||
# rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
# rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
||||||
# runner service host can base on the log file name determin the result of the runner update
|
# runner service host can base on the log file name determin the result of the runner update
|
||||||
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
SET UPDATEFILE=update.finished
|
||||||
"%~dp0\bin\Runner.Listener.exe" run %*
|
"%~dp0\bin\Runner.Listener.exe" run %*
|
||||||
|
|
||||||
rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N`
|
rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N`
|
||||||
@@ -22,16 +22,30 @@ if %ERRORLEVEL% EQU 2 (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 3 (
|
if %ERRORLEVEL% EQU 3 (
|
||||||
rem Sleep 5 seconds to wait for the runner update process finish
|
rem Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch runner in 5 seconds"
|
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||||
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
FOR /L %%G IN (1,1,30) DO (
|
||||||
|
IF EXIST %UPDATEFILE% (
|
||||||
|
echo "Update finished successfully."
|
||||||
|
del %FILE%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
ping 127.0.0.1 -n 2 -w 1000 >NUL
|
||||||
|
)
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 4 (
|
if %ERRORLEVEL% EQU 4 (
|
||||||
rem Sleep 5 seconds to wait for the ephemeral runner update process finish
|
rem Wait for 30 seconds or for flag file to exists for the runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds"
|
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||||
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
FOR /L %%G IN (1,1,30) DO (
|
||||||
|
IF EXIST %UPDATEFILE% (
|
||||||
|
echo "Update finished successfully."
|
||||||
|
del %FILE%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
ping 127.0.0.1 -n 2 -w 1000 >NUL
|
||||||
|
)
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli
|
|||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
done
|
done
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
|
|
||||||
|
updateFile="update.finished"
|
||||||
"$DIR"/bin/Runner.Listener run $*
|
"$DIR"/bin/Runner.Listener run $*
|
||||||
|
|
||||||
returnCode=$?
|
returnCode=$?
|
||||||
@@ -31,14 +33,28 @@ elif [[ $returnCode == 2 ]]; then
|
|||||||
"$DIR"/safe_sleep.sh 5
|
"$DIR"/safe_sleep.sh 5
|
||||||
exit 2
|
exit 2
|
||||||
elif [[ $returnCode == 3 ]]; then
|
elif [[ $returnCode == 3 ]]; then
|
||||||
# Sleep 5 seconds to wait for the runner update process finish
|
# Wait for 30 seconds or for flag file to exists for the runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch runner in 5 seconds"
|
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||||
"$DIR"/safe_sleep.sh 5
|
for i in {0..30}; do
|
||||||
|
if test -f "$updateFile"; then
|
||||||
|
echo "Update finished successfully."
|
||||||
|
rm "$updateFile"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
"$DIR"/safe_sleep.sh 1
|
||||||
|
done
|
||||||
exit 2
|
exit 2
|
||||||
elif [[ $returnCode == 4 ]]; then
|
elif [[ $returnCode == 4 ]]; then
|
||||||
# Sleep 5 seconds to wait for the ephemeral runner update process finish
|
# Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds"
|
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||||
"$DIR"/safe_sleep.sh 5
|
for i in {0..30}; do
|
||||||
|
if test -f "$updateFile"; then
|
||||||
|
echo "Update finished successfully."
|
||||||
|
rm "$updateFile"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
"$DIR"/safe_sleep.sh 1
|
||||||
|
done
|
||||||
exit 2
|
exit 2
|
||||||
else
|
else
|
||||||
echo "Exiting with unknown error code: ${returnCode}"
|
echo "Exiting with unknown error code: ${returnCode}"
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli
|
|||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
done
|
done
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
|
||||||
# run the helper process which keep the listener alive
|
# run the helper process which keep the listener alive
|
||||||
while :;
|
while :;
|
||||||
do
|
do
|
||||||
|
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
||||||
"$DIR"/run-helper.sh $*
|
"$DIR"/run-helper.sh $*
|
||||||
returnCode=$?
|
returnCode=$?
|
||||||
if [[ $returnCode -eq 2 ]]; then
|
if [[ $returnCode -eq 2 ]]; then
|
||||||
|
|||||||
14
src/Runner.Common/JobStatusEventArgs.cs
Normal file
14
src/Runner.Common/JobStatusEventArgs.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
|
{
|
||||||
|
public class JobStatusEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public JobStatusEventArgs(TaskAgentStatus status)
|
||||||
|
{
|
||||||
|
this.Status = status;
|
||||||
|
}
|
||||||
|
public TaskAgentStatus Status { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ namespace GitHub.Runner.Common
|
|||||||
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
|
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
|
||||||
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
|
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
|
||||||
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
|
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
|
||||||
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken);
|
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// job request
|
// job request
|
||||||
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
||||||
@@ -298,10 +298,10 @@ namespace GitHub.Runner.Common
|
|||||||
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken)
|
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||||
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using GitHub.Runner.Common;
|
|||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.Common.Internal;
|
||||||
using GitHub.Services.OAuth;
|
using GitHub.Services.OAuth;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -128,7 +129,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// Example githubServerUrl is https://my-ghes
|
// Example githubServerUrl is https://my-ghes
|
||||||
var actionsServerUrl = new Uri(runnerSettings.ServerUrl);
|
var actionsServerUrl = new Uri(runnerSettings.ServerUrl);
|
||||||
var githubServerUrl = new Uri(runnerSettings.GitHubUrl);
|
var githubServerUrl = new Uri(runnerSettings.GitHubUrl);
|
||||||
if (!string.Equals(actionsServerUrl.Authority, githubServerUrl.Authority, StringComparison.OrdinalIgnoreCase))
|
if (!UriUtility.IsSubdomainOf(actionsServerUrl.Authority, githubServerUrl.Authority))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"GitHub Actions is not properly configured in GHES. GHES url: {runnerSettings.GitHubUrl}, Actions url: {runnerSettings.ServerUrl}.");
|
throw new InvalidOperationException($"GitHub Actions is not properly configured in GHES. GHES url: {runnerSettings.GitHubUrl}, Actions url: {runnerSettings.ServerUrl}.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace GitHub.Runner.Listener
|
|||||||
bool Cancel(JobCancelMessage message);
|
bool Cancel(JobCancelMessage message);
|
||||||
Task WaitAsync(CancellationToken token);
|
Task WaitAsync(CancellationToken token);
|
||||||
Task ShutdownAsync();
|
Task ShutdownAsync();
|
||||||
|
event EventHandler<JobStatusEventArgs> JobStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This implementation of IJobDispatcher is not thread safe.
|
// This implementation of IJobDispatcher is not thread safe.
|
||||||
@@ -55,6 +56,8 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
private TaskCompletionSource<bool> _runOnceJobCompleted = new TaskCompletionSource<bool>();
|
private TaskCompletionSource<bool> _runOnceJobCompleted = new TaskCompletionSource<bool>();
|
||||||
|
|
||||||
|
public event EventHandler<JobStatusEventArgs> JobStatus;
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
base.Initialize(hostContext);
|
base.Initialize(hostContext);
|
||||||
@@ -335,6 +338,11 @@ namespace GitHub.Runner.Listener
|
|||||||
Busy = true;
|
Busy = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (JobStatus != null)
|
||||||
|
{
|
||||||
|
JobStatus(this, new JobStatusEventArgs(TaskAgentStatus.Busy));
|
||||||
|
}
|
||||||
|
|
||||||
if (previousJobDispatch != null)
|
if (previousJobDispatch != null)
|
||||||
{
|
{
|
||||||
Trace.Verbose($"Make sure the previous job request {previousJobDispatch.JobId} has successfully finished on worker.");
|
Trace.Verbose($"Make sure the previous job request {previousJobDispatch.JobId} has successfully finished on worker.");
|
||||||
@@ -650,6 +658,11 @@ namespace GitHub.Runner.Listener
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Busy = false;
|
Busy = false;
|
||||||
|
|
||||||
|
if (JobStatus != null)
|
||||||
|
{
|
||||||
|
JobStatus(this, new JobStatusEventArgs(TaskAgentStatus.Online));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace GitHub.Runner.Listener
|
|||||||
Task DeleteSessionAsync();
|
Task DeleteSessionAsync();
|
||||||
Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token);
|
Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token);
|
||||||
Task DeleteMessageAsync(TaskAgentMessage message);
|
Task DeleteMessageAsync(TaskAgentMessage message);
|
||||||
|
void OnJobStatus(object sender, JobStatusEventArgs e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MessageListener : RunnerService, IMessageListener
|
public sealed class MessageListener : RunnerService, IMessageListener
|
||||||
@@ -38,6 +39,8 @@ namespace GitHub.Runner.Listener
|
|||||||
private readonly TimeSpan _sessionConflictRetryLimit = TimeSpan.FromMinutes(4);
|
private readonly TimeSpan _sessionConflictRetryLimit = TimeSpan.FromMinutes(4);
|
||||||
private readonly TimeSpan _clockSkewRetryLimit = TimeSpan.FromMinutes(30);
|
private readonly TimeSpan _clockSkewRetryLimit = TimeSpan.FromMinutes(30);
|
||||||
private readonly Dictionary<string, int> _sessionCreationExceptionTracker = new Dictionary<string, int>();
|
private readonly Dictionary<string, int> _sessionCreationExceptionTracker = new Dictionary<string, int>();
|
||||||
|
private TaskAgentStatus runnerStatus = TaskAgentStatus.Online;
|
||||||
|
private CancellationTokenSource _getMessagesTokenSource;
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
@@ -170,6 +173,23 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnJobStatus(object sender, JobStatusEventArgs e)
|
||||||
|
{
|
||||||
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
|
||||||
|
{
|
||||||
|
Trace.Info("Received job status event. JobState: {0}", e.Status);
|
||||||
|
runnerStatus = e.Status;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_getMessagesTokenSource?.Cancel();
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
Trace.Info("_getMessagesTokenSource is already disposed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
|
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
@@ -184,12 +204,14 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
TaskAgentMessage message = null;
|
TaskAgentMessage message = null;
|
||||||
|
_getMessagesTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
|
message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
|
||||||
_session.SessionId,
|
_session.SessionId,
|
||||||
_lastMessageId,
|
_lastMessageId,
|
||||||
token);
|
runnerStatus,
|
||||||
|
_getMessagesTokenSource.Token);
|
||||||
|
|
||||||
// Decrypt the message body if the session is using encryption
|
// Decrypt the message body if the session is using encryption
|
||||||
message = DecryptMessage(message);
|
message = DecryptMessage(message);
|
||||||
@@ -206,6 +228,11 @@ namespace GitHub.Runner.Listener
|
|||||||
continuousError = 0;
|
continuousError = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException) when (_getMessagesTokenSource.Token.IsCancellationRequested && !token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Trace.Info("Get messages has been cancelled using local token source. Continue to get messages with new status.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Trace.Info("Get next message has been cancelled.");
|
Trace.Info("Get next message has been cancelled.");
|
||||||
@@ -261,6 +288,10 @@ namespace GitHub.Runner.Listener
|
|||||||
await HostContext.Delay(_getNextMessageRetryInterval, token);
|
await HostContext.Delay(_getNextMessageRetryInterval, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_getMessagesTokenSource.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -360,6 +360,8 @@ namespace GitHub.Runner.Listener
|
|||||||
bool runOnceJobReceived = false;
|
bool runOnceJobReceived = false;
|
||||||
jobDispatcher = HostContext.CreateService<IJobDispatcher>();
|
jobDispatcher = HostContext.CreateService<IJobDispatcher>();
|
||||||
|
|
||||||
|
jobDispatcher.JobStatus += _listener.OnJobStatus;
|
||||||
|
|
||||||
while (!HostContext.RunnerShutdownToken.IsCancellationRequested)
|
while (!HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
TaskAgentMessage message = null;
|
TaskAgentMessage message = null;
|
||||||
@@ -561,6 +563,7 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
if (jobDispatcher != null)
|
if (jobDispatcher != null)
|
||||||
{
|
{
|
||||||
|
jobDispatcher.JobStatus -= _listener.OnJobStatus;
|
||||||
await jobDispatcher.ShutdownAsync();
|
await jobDispatcher.ShutdownAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ namespace GitHub.Runner.Listener
|
|||||||
// For L0, we will skip execute update script.
|
// For L0, we will skip execute update script.
|
||||||
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_EXECUTE_UPDATE_SCRIPT")))
|
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_EXECUTE_UPDATE_SCRIPT")))
|
||||||
{
|
{
|
||||||
|
string flagFile = "update.finished";
|
||||||
|
IOUtil.DeleteFile(flagFile);
|
||||||
// kick off update script
|
// kick off update script
|
||||||
Process invokeScript = new Process();
|
Process invokeScript = new Process();
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace GitHub.Runner.Sdk
|
|||||||
settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200));
|
settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ALLOW_REDIRECT")))
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
|
||||||
{
|
{
|
||||||
settings.AllowAutoRedirect = true;
|
settings.AllowAutoRedirect = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -585,6 +585,8 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container)
|
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container)
|
||||||
{
|
{
|
||||||
|
ValidateLinesAndColumns(command, context);
|
||||||
|
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
|
command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
||||||
|
|||||||
@@ -503,7 +503,7 @@ namespace GitHub.Runner.Worker
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotSupportedException(nameof(ConvertRuns));
|
throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConvertInputs(
|
private void ConvertInputs(
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
public async Task<string> DockerCreate(IExecutionContext context, ContainerInfo container)
|
public async Task<string> DockerCreate(IExecutionContext context, ContainerInfo container)
|
||||||
{
|
{
|
||||||
IList<string> dockerOptions = new List<string>();
|
IList<string> dockerOptions = new List<string>();
|
||||||
|
IDictionary<string, string> environment = new Dictionary<string, string>();
|
||||||
// OPTIONS
|
// OPTIONS
|
||||||
dockerOptions.Add($"--name {container.ContainerDisplayName}");
|
dockerOptions.Add($"--name {container.ContainerDisplayName}");
|
||||||
dockerOptions.Add($"--label {DockerInstanceLabel}");
|
dockerOptions.Add($"--label {DockerInstanceLabel}");
|
||||||
@@ -131,11 +132,12 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(env.Value))
|
if (String.IsNullOrEmpty(env.Value))
|
||||||
{
|
{
|
||||||
dockerOptions.Add($"-e \"{env.Key}\"");
|
dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dockerOptions.Add($"-e \"{env.Key}={env.Value.Replace("\"", "\\\"")}\"");
|
environment.Add(env.Key, env.Value);
|
||||||
|
dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +185,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
dockerOptions.Add($"{container.ContainerEntryPointArgs}");
|
dockerOptions.Add($"{container.ContainerEntryPointArgs}");
|
||||||
|
|
||||||
var optionsString = string.Join(" ", dockerOptions);
|
var optionsString = string.Join(" ", dockerOptions);
|
||||||
List<string> outputStrings = await ExecuteDockerCommandAsync(context, "create", optionsString);
|
List<string> outputStrings = await ExecuteDockerCommandAsync(context, "create", optionsString, environment);
|
||||||
|
|
||||||
return outputStrings.FirstOrDefault();
|
return outputStrings.FirstOrDefault();
|
||||||
}
|
}
|
||||||
@@ -202,7 +204,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
{
|
{
|
||||||
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
||||||
// the value directly in the command
|
// the value directly in the command
|
||||||
dockerOptions.Add($"-e {env.Key}");
|
dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watermark for GitHub Action environment
|
// Watermark for GitHub Action environment
|
||||||
@@ -443,6 +445,11 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<string>> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options)
|
private async Task<List<string>> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options)
|
||||||
|
{
|
||||||
|
return await ExecuteDockerCommandAsync(context, command, options, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary<string, string> environment)
|
||||||
{
|
{
|
||||||
string arg = $"{command} {options}".Trim();
|
string arg = $"{command} {options}".Trim();
|
||||||
context.Command($"{DockerPath} {arg}");
|
context.Command($"{DockerPath} {arg}");
|
||||||
@@ -470,7 +477,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
workingDirectory: context.GetGitHubContext("workspace"),
|
workingDirectory: context.GetGitHubContext("workspace"),
|
||||||
fileName: DockerPath,
|
fileName: DockerPath,
|
||||||
arguments: arg,
|
arguments: arg,
|
||||||
environment: null,
|
environment: environment,
|
||||||
requireExitCodeZero: true,
|
requireExitCodeZero: true,
|
||||||
outputEncoding: null,
|
outputEncoding: null,
|
||||||
cancellationToken: CancellationToken.None);
|
cancellationToken: CancellationToken.None);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
string pattern = $"^(?<{targetPort}>\\d+)/(?<{proto}>\\w+) -> (?<{host}>.+):(?<{hostPort}>\\d+)$";
|
string pattern = $"^(?<{targetPort}>\\d+)/(?<{proto}>\\w+) -> (?<{host}>.+):(?<{hostPort}>\\d+)$";
|
||||||
|
|
||||||
List<PortMapping> portMappings = new List<PortMapping>();
|
List<PortMapping> portMappings = new List<PortMapping>();
|
||||||
foreach(var line in portMappingLines)
|
foreach (var line in portMappingLines)
|
||||||
{
|
{
|
||||||
Match m = Regex.Match(line, pattern, RegexOptions.None, TimeSpan.FromSeconds(1));
|
Match m = Regex.Match(line, pattern, RegexOptions.None, TimeSpan.FromSeconds(1));
|
||||||
if (m.Success)
|
if (m.Success)
|
||||||
@@ -61,5 +61,19 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string CreateEscapedOption(string flag, string key)
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(key))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return $"{flag} \"{EscapeString(key)}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string EscapeString(string value)
|
||||||
|
{
|
||||||
|
return value.Replace("\\", "\\\\").Replace("\"", "\\\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ namespace GitHub.Runner.Worker
|
|||||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
ArgUtil.NotNull(container, nameof(container));
|
ArgUtil.NotNull(container, nameof(container));
|
||||||
ArgUtil.NotNullOrEmpty(container.ContainerImage, nameof(container.ContainerImage));
|
ArgUtil.NotNullOrEmpty(container.ContainerImage, nameof(container.ContainerImage));
|
||||||
|
|
||||||
Trace.Info($"Container name: {container.ContainerName}");
|
Trace.Info($"Container name: {container.ContainerName}");
|
||||||
Trace.Info($"Container image: {container.ContainerImage}");
|
Trace.Info($"Container image: {container.ContainerImage}");
|
||||||
Trace.Info($"Container options: {container.ContainerCreateOptions}");
|
Trace.Info($"Container options: {container.ContainerCreateOptions}");
|
||||||
@@ -198,6 +197,8 @@ namespace GitHub.Runner.Worker
|
|||||||
container.ContainerId = await _dockerManager.DockerCreate(executionContext, container);
|
container.ContainerId = await _dockerManager.DockerCreate(executionContext, container);
|
||||||
ArgUtil.NotNullOrEmpty(container.ContainerId, nameof(container.ContainerId));
|
ArgUtil.NotNullOrEmpty(container.ContainerId, nameof(container.ContainerId));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Start container
|
// Start container
|
||||||
int startExitCode = await _dockerManager.DockerStart(executionContext, container.ContainerId);
|
int startExitCode = await _dockerManager.DockerStart(executionContext, container.ContainerId);
|
||||||
if (startExitCode != 0)
|
if (startExitCode != 0)
|
||||||
@@ -207,20 +208,37 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
// Make sure container is up and running
|
// Make sure container is up and running
|
||||||
var psOutputs = await _dockerManager.DockerPS(executionContext, $"--all --filter id={container.ContainerId} --filter status=running --no-trunc --format \"{{{{.ID}}}} {{{{.Status}}}}\"");
|
var psOutputs = await _dockerManager.DockerPS(executionContext, $"--all --filter id={container.ContainerId} --filter status=running --no-trunc --format \"{{{{.ID}}}} {{{{.Status}}}}\"");
|
||||||
|
|
||||||
if (psOutputs.FirstOrDefault(x => !string.IsNullOrEmpty(x))?.StartsWith(container.ContainerId) != true)
|
if (psOutputs.FirstOrDefault(x => !string.IsNullOrEmpty(x))?.StartsWith(container.ContainerId) != true)
|
||||||
{
|
{
|
||||||
// container is not up and running, pull docker log for this container.
|
// container is not up and running, pull docker log for this container.
|
||||||
await _dockerManager.DockerPS(executionContext, $"--all --filter id={container.ContainerId} --no-trunc --format \"{{{{.ID}}}} {{{{.Status}}}}\"");
|
await _dockerManager.DockerPS(executionContext, $"--all --filter id={container.ContainerId} --no-trunc --format \"{{{{.ID}}}} {{{{.Status}}}}\"");
|
||||||
|
|
||||||
|
|
||||||
|
//executionContext.Output("##[group]Getting docker logs..");
|
||||||
|
|
||||||
int logsExitCode = await _dockerManager.DockerLogs(executionContext, container.ContainerId);
|
int logsExitCode = await _dockerManager.DockerLogs(executionContext, container.ContainerId);
|
||||||
|
|
||||||
if (logsExitCode != 0)
|
if (logsExitCode != 0)
|
||||||
{
|
{
|
||||||
executionContext.Warning($"Docker logs fail with exit code {logsExitCode}");
|
executionContext.Warning($"Docker logs fail with exit code {logsExitCode}");
|
||||||
}
|
}
|
||||||
|
//executionContext.Output("##[endgroup]");
|
||||||
executionContext.Warning($"Docker container {container.ContainerId} is not in running state.");
|
executionContext.Warning($"Docker container {container.ContainerId} is not in running state.");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
executionContext.Output($"##[group]Container {container.ContainerId} is not running!");
|
||||||
|
string opt = "--format=\'{{.State.ExitCode}}\'";
|
||||||
|
await _dockerManager.DockerInspect(executionContext, container.ContainerId, opt);
|
||||||
|
await _dockerManager.DockerLogs(executionContext, container.ContainerId);
|
||||||
|
//if exit code is not 0 we can maybe print a message?
|
||||||
|
//executionContext.Output("Container exit code: ");
|
||||||
|
|
||||||
|
executionContext.Output("##[endgroup]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -369,6 +369,7 @@ namespace GitHub.Runner.Worker
|
|||||||
child.StepTelemetry.StepId = recordId;
|
child.StepTelemetry.StepId = recordId;
|
||||||
child.StepTelemetry.Stage = stage.ToString();
|
child.StepTelemetry.Stage = stage.ToString();
|
||||||
child.StepTelemetry.IsEmbedded = isEmbedded;
|
child.StepTelemetry.IsEmbedded = isEmbedded;
|
||||||
|
child.StepTelemetry.StepContextName = child.GetFullyQualifiedContextName(); ;
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
@@ -959,6 +960,8 @@ namespace GitHub.Runner.Worker
|
|||||||
_record.StartTime != null)
|
_record.StartTime != null)
|
||||||
{
|
{
|
||||||
StepTelemetry.ExecutionTimeInSeconds = (int)Math.Ceiling((_record.FinishTime - _record.StartTime)?.TotalSeconds ?? 0);
|
StepTelemetry.ExecutionTimeInSeconds = (int)Math.Ceiling((_record.FinishTime - _record.StartTime)?.TotalSeconds ?? 0);
|
||||||
|
StepTelemetry.StartTime = _record.StartTime;
|
||||||
|
StepTelemetry.FinishTime = _record.FinishTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsEmbedded &&
|
if (!IsEmbedded &&
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
{
|
{
|
||||||
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
||||||
// the value directly in the command
|
// the value directly in the command
|
||||||
dockerCommandArgs.Add($"-e {env.Key}");
|
dockerCommandArgs.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(PrependPath))
|
if (!string.IsNullOrEmpty(PrependPath))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
preJobSteps.Add(new JobExtensionRunner(runAsync: containerProvider.StartContainersAsync,
|
preJobSteps.Add(new JobExtensionRunner(runAsync: containerProvider.StartContainersAsync,
|
||||||
condition: $"{PipelineTemplateConstants.Success}()",
|
condition: $"{PipelineTemplateConstants.Success}()",
|
||||||
displayName: "Initialize containers",
|
displayName: "**Initialize containers**",
|
||||||
data: (object)containers));
|
data: (object)containers));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +316,29 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.Variables.TryGetValue("system.workflowFileFullPath", out VariableValue workflowFileFullPath))
|
||||||
|
{
|
||||||
|
context.Output($"Uses: {workflowFileFullPath.Value}");
|
||||||
|
if (message.ContextData.TryGetValue("inputs", out var pipelineContextData))
|
||||||
|
{
|
||||||
|
var inputs = pipelineContextData.AssertDictionary("inputs");
|
||||||
|
if (inputs.Any())
|
||||||
|
{
|
||||||
|
context.Output($"##[group] Inputs");
|
||||||
|
foreach (var input in inputs)
|
||||||
|
{
|
||||||
|
context.Output($" {input.Key}: {input.Value}");
|
||||||
|
}
|
||||||
|
context.Output("##[endgroup]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(message.JobDisplayName))
|
||||||
|
{
|
||||||
|
context.Output($"Complete job name: {message.JobDisplayName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var intraActionStates = new Dictionary<Guid, Dictionary<string, string>>();
|
var intraActionStates = new Dictionary<Guid, Dictionary<string, string>>();
|
||||||
foreach (var preStep in prepareResult.PreStepTracker)
|
foreach (var preStep in prepareResult.PreStepTracker)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -457,6 +457,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
int poolId,
|
int poolId,
|
||||||
Guid sessionId,
|
Guid sessionId,
|
||||||
long? lastMessageId = null,
|
long? lastMessageId = null,
|
||||||
|
TaskAgentStatus? status = null,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -470,6 +471,10 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
{
|
{
|
||||||
queryParams.Add("lastMessageId", lastMessageId.Value.ToString(CultureInfo.InvariantCulture));
|
queryParams.Add("lastMessageId", lastMessageId.Value.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
if (status != null)
|
||||||
|
{
|
||||||
|
queryParams.Add("status", status.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return SendAsync<TaskAgentMessage>(
|
return SendAsync<TaskAgentMessage>(
|
||||||
httpMethod,
|
httpMethod,
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public Guid StepId { get; set; }
|
public Guid StepId { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public string StepContextName { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public bool? HasRunsStep { get; set; }
|
public bool? HasRunsStep { get; set; }
|
||||||
|
|
||||||
@@ -57,6 +60,12 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public int? ExecutionTimeInSeconds { get; set; }
|
public int? ExecutionTimeInSeconds { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? StartTime { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? FinishTime { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string ContainerHookData { get; set; }
|
public string ContainerHookData { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,5 +10,8 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
|
|
||||||
[EnumMember]
|
[EnumMember]
|
||||||
Online = 2,
|
Online = 2,
|
||||||
|
|
||||||
|
[EnumMember]
|
||||||
|
Busy = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,5 +144,32 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
|
|||||||
var actual = DockerUtil.ParseRegistryHostnameFromImageName(input);
|
var actual = DockerUtil.ParseRegistryHostnameFromImageName(input);
|
||||||
Assert.Equal(expected, actual);
|
Assert.Equal(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
[InlineData("", "")]
|
||||||
|
[InlineData("HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #")]
|
||||||
|
[InlineData("HOME \"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #")]
|
||||||
|
[InlineData("HOME \\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #")]
|
||||||
|
[InlineData("HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #")]
|
||||||
|
[InlineData("HOME \"\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #")]
|
||||||
|
[InlineData("HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #")]
|
||||||
|
[InlineData("HOME \"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #")]
|
||||||
|
public void CreateEscapedOption_keyOnly(string input, string escaped)
|
||||||
|
{
|
||||||
|
var flag = "--example";
|
||||||
|
var actual = DockerUtil.CreateEscapedOption(flag, input);
|
||||||
|
string expected;
|
||||||
|
if (String.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expected = $"{flag} \"{escaped}\"";
|
||||||
|
}
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,8 +192,8 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
|
|
||||||
_runnerServer
|
_runnerServer
|
||||||
.Setup(x => x.GetAgentMessageAsync(
|
.Setup(x => x.GetAgentMessageAsync(
|
||||||
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), tokenSource.Token))
|
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()))
|
||||||
.Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) =>
|
.Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken) =>
|
||||||
{
|
{
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
return messages.Dequeue();
|
return messages.Dequeue();
|
||||||
@@ -208,7 +208,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
//Assert
|
//Assert
|
||||||
_runnerServer
|
_runnerServer
|
||||||
.Verify(x => x.GetAgentMessageAsync(
|
.Verify(x => x.GetAgentMessageAsync(
|
||||||
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), tokenSource.Token), Times.Exactly(arMessages.Length));
|
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()), Times.Exactly(arMessages.Length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
|
|
||||||
_runnerServer
|
_runnerServer
|
||||||
.Setup(x => x.GetAgentMessageAsync(
|
.Setup(x => x.GetAgentMessageAsync(
|
||||||
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), tokenSource.Token))
|
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()))
|
||||||
.Throws(new TaskAgentAccessTokenExpiredException("test"));
|
.Throws(new TaskAgentAccessTokenExpiredException("test"));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -311,7 +311,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
//Assert
|
//Assert
|
||||||
_runnerServer
|
_runnerServer
|
||||||
.Verify(x => x.GetAgentMessageAsync(
|
.Verify(x => x.GetAgentMessageAsync(
|
||||||
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), tokenSource.Token), Times.Once);
|
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()), Times.Once);
|
||||||
|
|
||||||
_runnerServer
|
_runnerServer
|
||||||
.Verify(x => x.DeleteAgentSessionAsync(
|
.Verify(x => x.DeleteAgentSessionAsync(
|
||||||
|
|||||||
@@ -698,6 +698,31 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void Load_CompositeActionNoUsing()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
Setup();
|
||||||
|
|
||||||
|
var actionManifest = new ActionManifestManager();
|
||||||
|
actionManifest.Initialize(_hc);
|
||||||
|
var action_path = Path.Combine(TestUtil.GetTestDataPath(), "composite_action_without_using_token.yml");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
var err = Assert.Throws<ArgumentException>(() => actionManifest.Load(_ec.Object, action_path));
|
||||||
|
Assert.Contains($"Fail to load {action_path}", err.Message);
|
||||||
|
_ec.Verify(x => x.AddIssue(It.Is<Issue>(s => s.Message.Contains("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.")), It.IsAny<string>()), Times.Once);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Teardown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: "composite action"
|
||||||
|
description: "test composite action without value for the 'using' token in 'runs'"
|
||||||
|
|
||||||
|
runs:
|
||||||
|
steps:
|
||||||
|
- id: mystep
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "hello world"
|
||||||
@@ -1 +1 @@
|
|||||||
2.294.0
|
2.296.1
|
||||||
Reference in New Issue
Block a user