mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
.
This commit is contained in:
@@ -107,9 +107,37 @@ async function run(): Promise<void> {
|
|||||||
|
|
||||||
await exec.exec('podman', ['rm', '-f', jobContainerId])
|
await exec.exec('podman', ['rm', '-f', jobContainerId])
|
||||||
await exec.exec('podman', ['network', 'rm', '-f', network])
|
await exec.exec('podman', ['network', 'rm', '-f', network])
|
||||||
|
} else if (command === 'Exec') {
|
||||||
|
const execInput = inputJson.execInput
|
||||||
|
core.debug(JSON.stringify(execInput))
|
||||||
|
|
||||||
|
// podman exec -i --workdir /__w/canary/canary
|
||||||
|
// -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY
|
||||||
|
// -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
|
||||||
|
// -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR
|
||||||
|
// -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
|
||||||
|
// -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL
|
||||||
|
// -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY
|
||||||
|
// -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_DEBUG
|
||||||
|
// -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE
|
||||||
|
// -e RUNNER_TEMP -e RUNNER_WORKSPACE
|
||||||
|
// eccdf520697a035599d6e8c8dc801f004fdd3797cdce88f590aba3669a88d9bc sh -e /__w/_temp/d3b30383-719c-4e76-a16f-8f85443352be.sh
|
||||||
|
|
||||||
|
const execArgs = ['exec']
|
||||||
|
execArgs.push('-i')
|
||||||
|
execArgs.push(`--wordir=${execInput.workingDirectory}`)
|
||||||
|
for (const envKey of execInput.environmentKeys) {
|
||||||
|
execArgs.push(`-e=${envKey}`)
|
||||||
|
}
|
||||||
|
execArgs.push(execInput.jobContainer.containerId)
|
||||||
|
execArgs.push(execInput.fileName)
|
||||||
|
execArgs.push(execInput.arguments)
|
||||||
|
|
||||||
|
core.debug(JSON.stringify(execArgs))
|
||||||
|
|
||||||
|
await exec.exec('podman', execArgs)
|
||||||
}
|
}
|
||||||
// else if (command === 'Exec') {
|
|
||||||
// }
|
|
||||||
await exec.exec('podman', ['network', 'ls'])
|
await exec.exec('podman', ['network', 'ls'])
|
||||||
await exec.exec('podman', ['ps', '-a'])
|
await exec.exec('podman', ['ps', '-a'])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1130,8 +1130,32 @@ function run() {
|
|||||||
yield exec.exec('podman', ['rm', '-f', jobContainerId]);
|
yield exec.exec('podman', ['rm', '-f', jobContainerId]);
|
||||||
yield exec.exec('podman', ['network', 'rm', '-f', network]);
|
yield exec.exec('podman', ['network', 'rm', '-f', network]);
|
||||||
}
|
}
|
||||||
// else if (command === 'Exec') {
|
else if (command === 'Exec') {
|
||||||
// }
|
const execInput = inputJson.execInput;
|
||||||
|
core.debug(JSON.stringify(execInput));
|
||||||
|
// podman exec -i --workdir /__w/canary/canary
|
||||||
|
// -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY
|
||||||
|
// -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
|
||||||
|
// -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR
|
||||||
|
// -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
|
||||||
|
// -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL
|
||||||
|
// -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY
|
||||||
|
// -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_DEBUG
|
||||||
|
// -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE
|
||||||
|
// -e RUNNER_TEMP -e RUNNER_WORKSPACE
|
||||||
|
// eccdf520697a035599d6e8c8dc801f004fdd3797cdce88f590aba3669a88d9bc sh -e /__w/_temp/d3b30383-719c-4e76-a16f-8f85443352be.sh
|
||||||
|
const execArgs = ['exec'];
|
||||||
|
execArgs.push("-i");
|
||||||
|
execArgs.push(`--wordir=${execInput.workingDirectory}`);
|
||||||
|
for (const envKey of execInput.environmentKeys) {
|
||||||
|
execArgs.push(`-e=${envKey}`);
|
||||||
|
}
|
||||||
|
execArgs.push(execInput.jobContainer.containerId);
|
||||||
|
execArgs.push(execInput.fileName);
|
||||||
|
execArgs.push(execInput.arguments);
|
||||||
|
core.debug(JSON.stringify(execArgs));
|
||||||
|
yield exec.exec('podman', execArgs);
|
||||||
|
}
|
||||||
yield exec.exec('podman', ['network', 'ls']);
|
yield exec.exec('podman', ['network', 'ls']);
|
||||||
yield exec.exec('podman', ['ps', '-a']);
|
yield exec.exec('podman', ['ps', '-a']);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,12 +29,34 @@ namespace GitHub.Runner.Worker
|
|||||||
public ContainersCreationInput CreationInput { get; set; }
|
public ContainersCreationInput CreationInput { get; set; }
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public object JobContainerExecInput { get; set; }
|
public JobContainerExecInput ExecInput { get; set; }
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public ContainersRemoveInput RemoveInput { get; set; }
|
public ContainersRemoveInput RemoveInput { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DataContract]
|
||||||
|
public class JobContainerExecInput
|
||||||
|
{
|
||||||
|
[DataMember]
|
||||||
|
public ContainerInfo JobContainer { get; set; }
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public string WorkingDirectory { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public List<string> EnvironmentKeys { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[DataContract]
|
[DataContract]
|
||||||
public class ContainersCreationInput
|
public class ContainersCreationInput
|
||||||
{
|
{
|
||||||
@@ -192,6 +214,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
executionContext.JobContext.Container["network"] = new StringContextData(podmanOutput.CreationOutput.Network);
|
executionContext.JobContext.Container["network"] = new StringContextData(podmanOutput.CreationOutput.Network);
|
||||||
executionContext.JobContext.Container["id"] = new StringContextData(podmanOutput.CreationOutput.JobContainerId);
|
executionContext.JobContext.Container["id"] = new StringContextData(podmanOutput.CreationOutput.JobContainerId);
|
||||||
|
executionContext.Global.Container.ContainerId = podmanOutput.CreationOutput.JobContainerId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
||||||
event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
||||||
|
|
||||||
|
IExecutionContext ExecutionContext { get; set; }
|
||||||
|
|
||||||
string ResolvePathForStepHost(string path);
|
string ResolvePathForStepHost(string path);
|
||||||
|
|
||||||
Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext);
|
Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext);
|
||||||
@@ -53,6 +55,8 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
||||||
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
||||||
|
|
||||||
|
public IExecutionContext ExecutionContext { get; set; }
|
||||||
|
|
||||||
public string ResolvePathForStepHost(string path)
|
public string ResolvePathForStepHost(string path)
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
@@ -99,6 +103,8 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
||||||
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
||||||
|
|
||||||
|
public IExecutionContext ExecutionContext { get; set; }
|
||||||
|
|
||||||
public string ResolvePathForStepHost(string path)
|
public string ResolvePathForStepHost(string path)
|
||||||
{
|
{
|
||||||
// make sure container exist.
|
// make sure container exist.
|
||||||
@@ -174,69 +180,137 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
ArgUtil.NotNull(Container, nameof(Container));
|
ArgUtil.NotNull(Container, nameof(Container));
|
||||||
ArgUtil.NotNullOrEmpty(Container.ContainerId, nameof(Container.ContainerId));
|
ArgUtil.NotNullOrEmpty(Container.ContainerId, nameof(Container.ContainerId));
|
||||||
|
|
||||||
var dockerManager = HostContext.GetService<IDockerCommandManager>();
|
var podManHandler = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "podmanHandler", "index.js");
|
||||||
string dockerClientPath = dockerManager.DockerPath;
|
if (File.Exists(podManHandler))
|
||||||
|
|
||||||
// Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
|
|
||||||
IList<string> dockerCommandArgs = new List<string>();
|
|
||||||
dockerCommandArgs.Add($"exec");
|
|
||||||
|
|
||||||
// [OPTIONS]
|
|
||||||
dockerCommandArgs.Add($"-i");
|
|
||||||
dockerCommandArgs.Add($"--workdir {workingDirectory}");
|
|
||||||
foreach (var env in environment)
|
|
||||||
{
|
{
|
||||||
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
var podmanInput = new ContainerEngineHandlerInput()
|
||||||
// the value directly in the command
|
{
|
||||||
dockerCommandArgs.Add($"-e {env.Key}");
|
Command = "Exec",
|
||||||
|
ExecInput = new JobContainerExecInput()
|
||||||
|
{
|
||||||
|
JobContainer = this.Container,
|
||||||
|
WorkingDirectory = workingDirectory,
|
||||||
|
FileName = fileName,
|
||||||
|
Arguments = arguments,
|
||||||
|
EnvironmentKeys = environment.Keys.ToList()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// make sure all env are using container path
|
||||||
|
foreach (var envKey in environment.Keys.ToList())
|
||||||
|
{
|
||||||
|
environment[envKey] = this.Container.TranslateToContainerPath(environment[envKey]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerEngineHandlerOutput podmanOutput = null;
|
||||||
|
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||||
|
{
|
||||||
|
var redirectStandardIn = Channel.CreateUnbounded<string>(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = true });
|
||||||
|
redirectStandardIn.Writer.TryWrite(JsonUtility.ToString(podmanInput));
|
||||||
|
|
||||||
|
// processInvoker.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||||
|
// {
|
||||||
|
// ExecutionContext.Output(message.Data);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// processInvoker.ErrorDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||||
|
// {
|
||||||
|
// executionContext.Output(message.Data);
|
||||||
|
// if (podmanOutput == null && message.Data.IndexOf("___CONTAINER_ENGINE_HANDLER_OUTPUT___") >= 0)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// podmanOutput = JsonUtility.FromString<ContainerEngineHandlerOutput>(message.Data.Replace("___CONTAINER_ENGINE_HANDLER_OUTPUT___", ""));
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// executionContext.Error(ex);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
processInvoker.OutputDataReceived += OutputDataReceived;
|
||||||
|
processInvoker.ErrorDataReceived += ErrorDataReceived;
|
||||||
|
|
||||||
|
// Execute the process. Exit code 0 should always be returned.
|
||||||
|
// A non-zero exit code indicates infrastructural failure.
|
||||||
|
// Task failure should be communicated over STDOUT using ## commands.
|
||||||
|
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
||||||
|
fileName: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"),
|
||||||
|
arguments: podManHandler,
|
||||||
|
environment: environment,
|
||||||
|
requireExitCodeZero: requireExitCodeZero,
|
||||||
|
outputEncoding: Encoding.UTF8,
|
||||||
|
killProcessOnCancel: killProcessOnCancel,
|
||||||
|
redirectStandardIn: redirectStandardIn,
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(PrependPath))
|
else
|
||||||
{
|
{
|
||||||
// Prepend tool paths to container's PATH
|
var dockerManager = HostContext.GetService<IDockerCommandManager>();
|
||||||
var fullPath = !string.IsNullOrEmpty(Container.ContainerRuntimePath) ? $"{PrependPath}:{Container.ContainerRuntimePath}" : PrependPath;
|
string dockerClientPath = dockerManager.DockerPath;
|
||||||
dockerCommandArgs.Add($"-e PATH=\"{fullPath}\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
// CONTAINER
|
// Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
|
||||||
dockerCommandArgs.Add($"{Container.ContainerId}");
|
IList<string> dockerCommandArgs = new List<string>();
|
||||||
|
dockerCommandArgs.Add($"exec");
|
||||||
|
|
||||||
// COMMAND
|
// [OPTIONS]
|
||||||
dockerCommandArgs.Add(fileName);
|
dockerCommandArgs.Add($"-i");
|
||||||
|
dockerCommandArgs.Add($"--workdir {workingDirectory}");
|
||||||
|
foreach (var env in environment)
|
||||||
|
{
|
||||||
|
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
||||||
|
// the value directly in the command
|
||||||
|
dockerCommandArgs.Add($"-e {env.Key}");
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(PrependPath))
|
||||||
|
{
|
||||||
|
// Prepend tool paths to container's PATH
|
||||||
|
var fullPath = !string.IsNullOrEmpty(Container.ContainerRuntimePath) ? $"{PrependPath}:{Container.ContainerRuntimePath}" : PrependPath;
|
||||||
|
dockerCommandArgs.Add($"-e PATH=\"{fullPath}\"");
|
||||||
|
}
|
||||||
|
|
||||||
// [ARG...]
|
// CONTAINER
|
||||||
dockerCommandArgs.Add(arguments);
|
dockerCommandArgs.Add($"{Container.ContainerId}");
|
||||||
|
|
||||||
string dockerCommandArgstring = string.Join(" ", dockerCommandArgs);
|
// COMMAND
|
||||||
|
dockerCommandArgs.Add(fileName);
|
||||||
|
|
||||||
// make sure all env are using container path
|
// [ARG...]
|
||||||
foreach (var envKey in environment.Keys.ToList())
|
dockerCommandArgs.Add(arguments);
|
||||||
{
|
|
||||||
environment[envKey] = this.Container.TranslateToContainerPath(environment[envKey]);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
string dockerCommandArgstring = string.Join(" ", dockerCommandArgs);
|
||||||
{
|
|
||||||
processInvoker.OutputDataReceived += OutputDataReceived;
|
// make sure all env are using container path
|
||||||
processInvoker.ErrorDataReceived += ErrorDataReceived;
|
foreach (var envKey in environment.Keys.ToList())
|
||||||
|
{
|
||||||
|
environment[envKey] = this.Container.TranslateToContainerPath(environment[envKey]);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||||
|
{
|
||||||
|
processInvoker.OutputDataReceived += OutputDataReceived;
|
||||||
|
processInvoker.ErrorDataReceived += ErrorDataReceived;
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
// It appears that node.exe outputs UTF8 when not in TTY mode.
|
// It appears that node.exe outputs UTF8 when not in TTY mode.
|
||||||
outputEncoding = Encoding.UTF8;
|
outputEncoding = Encoding.UTF8;
|
||||||
#else
|
#else
|
||||||
// Let .NET choose the default.
|
// Let .NET choose the default.
|
||||||
outputEncoding = null;
|
outputEncoding = null;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
||||||
fileName: dockerClientPath,
|
fileName: dockerClientPath,
|
||||||
arguments: dockerCommandArgstring,
|
arguments: dockerCommandArgstring,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
requireExitCodeZero: requireExitCodeZero,
|
requireExitCodeZero: requireExitCodeZero,
|
||||||
outputEncoding: outputEncoding,
|
outputEncoding: outputEncoding,
|
||||||
killProcessOnCancel: killProcessOnCancel,
|
killProcessOnCancel: killProcessOnCancel,
|
||||||
redirectStandardIn: null,
|
redirectStandardIn: null,
|
||||||
inheritConsoleHandler: inheritConsoleHandler,
|
inheritConsoleHandler: inheritConsoleHandler,
|
||||||
cancellationToken: cancellationToken);
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user