зеркало из
1
0
Форкнуть 0
This commit is contained in:
Ethan Dennis 2022-03-23 16:43:08 -07:00
Родитель e1305cdce5
Коммит e0a0bfbfe7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 6C85E14D00C447F7
6 изменённых файлов: 149 добавлений и 67 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -9,6 +9,9 @@
*.user *.user
*.userosscache *.userosscache
*.sln.docstates *.sln.docstates
.DS_STORE
output/
dist/
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs

Просмотреть файл

@ -41,9 +41,7 @@ public class App
public async Task<int> ExecuteValetAsync(string[] args) public async Task<int> ExecuteValetAsync(string[] args)
{ {
Console.WriteLine(string.Join(' ', args)); var result = await _dockerService.ExecuteCommandAsync($"{ValetContainerRegistry}/{ValetImage}:latest", args);
return result ? 0 : 1;
await _dockerService.ExecuteCommandAsync($"{ValetContainerRegistry}/{ValetImage}:latest", args);
return 1;
} }
} }

Просмотреть файл

@ -0,0 +1,6 @@
namespace Valet.Interfaces;
public interface IProcessService
{
Task<bool> RunAsync(string filename, string arguments, string? cwd = null, IEnumerable<(string, string)>? environmentVariables = null);
}

Просмотреть файл

@ -1,27 +1,43 @@
// See https://aka.ms/new-console-template for more information // See https://aka.ms/new-console-template for more information
using CommandLine; using CommandLine;
using CommandLine.Text;
using Valet; using Valet;
using Valet.Models; using Valet.Models;
using Valet.Services; using Valet.Services;
var processService = new ProcessService();
var app = new App( var app = new App(
new DockerService(), new DockerService(processService),
new AuthenticationService() new AuthenticationService()
); );
var parser = new Parser(with => with.HelpWriter = null);
var parserResult = parser.ParseArguments<UpdateOptions, ExecuteOptions>(args);
// TODO: Utilize help menu from Valet itself // TODO: Utilize help menu from Valet itself
await Parser.Default.ParseArguments<UpdateOptions, ExecuteOptions>(args) await parserResult.WithNotParsedAsync(errs =>
.MapResult( {
(UpdateOptions opts) => return app.ExecuteValetAsync(args);
{ });
return app.UpdateValetAsync(opts.Username, opts.Password);
}, await parserResult.WithParsedAsync<UpdateOptions>(options => app.UpdateValetAsync(options.Username, options.Password));
(ExecuteOptions opts) =>
{
return Task.FromResult(1); // (UpdateOptions opts) => app.UpdateValetAsync(opts.Username, opts.Password),
}, // (ExecuteOptions opts) => Task.FromResult(1),
_ => // _ =>
{ // {
return app.ExecuteValetAsync(args); // var helpText = new HelpText
}); // {
// Heading = "Tool tool usage",
// AdditionalNewLineAfterOption = false,
// AddDashesToOption = true
// };
//
// Console.Error.WriteLine(helpText);
//
// return app.ExecuteValetAsync(args);
// });

Просмотреть файл

@ -1,3 +1,5 @@
using System.Diagnostics;
using System.Text;
using Docker.DotNet; using Docker.DotNet;
using Docker.DotNet.Models; using Docker.DotNet.Models;
using Valet.Interfaces; using Valet.Interfaces;
@ -8,8 +10,10 @@ namespace Valet.Services;
public class DockerService : IDockerService public class DockerService : IDockerService
{ {
private readonly DockerClient _client; private readonly DockerClient _client;
private readonly IProcessService _processService;
private readonly string[] _valetEnvVars = { private readonly string[] _valetEnvVars =
{
"GH_ACCESS_TOKEN", "GH_INSTANCE_URL", "GITHUB_ACCESS_TOKEN", "GITHUB_INSTANCE_URL", "GH_ACCESS_TOKEN", "GH_INSTANCE_URL", "GITHUB_ACCESS_TOKEN", "GITHUB_INSTANCE_URL",
"JENKINSFILE_ACCESS_TOKEN", "JENKINS_USERNAME", "JENKINS_ACCESS_TOKEN", "JENKINS_INSTANCE_URL", "JENKINSFILE_ACCESS_TOKEN", "JENKINS_USERNAME", "JENKINS_ACCESS_TOKEN", "JENKINS_INSTANCE_URL",
"TRAVIS_CI_ACCESS_TOKEN", "TRAVIS_CI_INSTANCE_URL", "TRAVIS_CI_SOURCE_GITHUB_ACCESS_TOKEN", "TRAVIS_CI_SOURCE_GITHUB_INSTANCE_URL", "TRAVIS_CI_ORGANIZATION", "TRAVIS_CI_ACCESS_TOKEN", "TRAVIS_CI_INSTANCE_URL", "TRAVIS_CI_SOURCE_GITHUB_ACCESS_TOKEN", "TRAVIS_CI_SOURCE_GITHUB_INSTANCE_URL", "TRAVIS_CI_ORGANIZATION",
@ -18,9 +22,11 @@ public class DockerService : IDockerService
"AZURE_DEVOPS_ACCESS_TOKEN", "AZURE_DEVOPS_PROJECT", "AZURE_DEVOPS_ORGANIZATION", "AZURE_DEVOPS_INSTANCE_URL", "AZURE_DEVOPS_ACCESS_TOKEN", "AZURE_DEVOPS_PROJECT", "AZURE_DEVOPS_ORGANIZATION", "AZURE_DEVOPS_INSTANCE_URL",
"YAML_VERBOSITY", "HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY", "OCTOKIT_PROXY", "OCTOKIT_SSL_VERIFY_MODE", "YAML_VERBOSITY", "HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY", "OCTOKIT_PROXY", "OCTOKIT_SSL_VERIFY_MODE",
}; };
public DockerService() public DockerService(IProcessService processService)
{ {
_processService = processService;
// TODO: Raise error if docker daemon not started // TODO: Raise error if docker daemon not started
_client = new DockerClientConfiguration() _client = new DockerClientConfiguration()
.CreateClient(); .CreateClient();
@ -47,65 +53,47 @@ public class DockerService : IDockerService
public async Task<bool> ExecuteCommandAsync(string image, params string[] arguments) public async Task<bool> ExecuteCommandAsync(string image, params string[] arguments)
{ {
// MSYS_NO_PATHCONV=1 docker run --rm $dockerArgs --env INSTALLATION_ID="$INSTALLATION_ID" $DOCKER_OPTIONS -v "$VALET_LOCAL_FOLDER"":/data" "$VALET_IMAGE":"$VALET_IMAGE_VERSION" "$@" var valetArguments = new List<string>();
var container = await _client.Containers.CreateContainerAsync( valetArguments.Add("run --rm");
new CreateContainerParameters valetArguments.AddRange(GetEnvironmentVariableArguments());
{ valetArguments.Add($"-v \"{Directory.GetCurrentDirectory()}\":/data");
Image = image, valetArguments.Add(image);
HostConfig = new HostConfig valetArguments.AddRange(arguments);
{
Binds = new[] { $"{Directory.GetCurrentDirectory()}:/data" },
AutoRemove = true,
},
Env = GetEnvironmentVariables().ToArray()
}
).ConfigureAwait(false);
await _client.Containers.StartContainerAsync( Debug.WriteLine(string.Join(' ', valetArguments));
container.ID,
new ContainerStartParameters() var result = await _processService.RunAsync(
"docker",
string.Join(' ', valetArguments),
Directory.GetCurrentDirectory(),
new[] { ("MSYS_NO_PATHCONV", "1") }
); );
return result;
return true;
} }
private IEnumerable<string> GetEnvironmentVariables() private IEnumerable<string> GetEnvironmentVariableArguments()
{ {
if (File.Exists(".env.local")) if (File.Exists(".env.local"))
{ {
foreach (var line in File.ReadAllLines(".env.local")) yield return "--env-file .env.local";
{
var parts = line.Split('=', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
continue;
yield return $"{parts[0]}={parts[1]}";
}
} }
var installationId = Environment.GetEnvironmentVariable("INSTALLATION_ID") ?? "get_from_client";
yield return $"--env INSTALLATION_ID={installationId}";
foreach (var env in _valetEnvVars) foreach (var env in _valetEnvVars)
{ {
var value = Environment.GetEnvironmentVariable(env); var value = Environment.GetEnvironmentVariable(env);
if (!string.IsNullOrWhiteSpace(value)) if (string.IsNullOrWhiteSpace(value)) continue;
{
var key = env;
// TODO: This can probably be cleaner
if (key.StartsWith("GH_"))
key = key.Replace("GH_", "GITHUB_");
yield return $"{key}={value}";
}
}
var installationId = Environment.GetEnvironmentVariable("INSTALLATION_ID"); var key = env;
if (installationId == null) // TODO: This can probably be cleaner
{ if (key.StartsWith("GH_"))
installationId = "get_from_client"; key = key.Replace("GH_", "GITHUB_");
}
yield return $"INSTALLATION_ID={installationId}"; yield return $"--env {key}={value}";
}
} }
} }

Просмотреть файл

@ -0,0 +1,71 @@
using System.Collections.Specialized;
using Valet.Interfaces;
namespace Valet.Services;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
public class ProcessService : IProcessService
{
public Task<bool> RunAsync(string filename, string arguments, string? cwd = null, IEnumerable<(string, string)>? environmentVariables = null)
{
var tcs = new TaskCompletionSource<bool>();
var startInfo = new ProcessStartInfo
{
FileName = filename,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
WorkingDirectory = cwd
};
if (environmentVariables != null)
{
foreach (var (key, value) in environmentVariables)
{
startInfo.EnvironmentVariables.Add(key, value);
}
}
var process = new Process
{
StartInfo = startInfo,
EnableRaisingEvents = true
};
void OnProcessExited(object? sender, EventArgs args)
{
process.Exited -= OnProcessExited;
process.OutputDataReceived -= OnOutputDataReceived;
if (process.ExitCode == 0)
{
tcs.TrySetResult(true);
}
else
{
// TODO: Verify works
var error = process.StandardError.ReadToEnd();
tcs.TrySetException(new Exception(error));
}
process.Dispose();
}
void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}
process.OutputDataReceived += OnOutputDataReceived;
process.Exited += OnProcessExited;
process.Start();
process.BeginOutputReadLine();
return tcs.Task;
}
}