117 lines
4.4 KiB
C#
117 lines
4.4 KiB
C#
|
using CodexPlugin;
|
|||
|
using Logging;
|
|||
|
using System.Diagnostics;
|
|||
|
|
|||
|
namespace CodexNetDeployer
|
|||
|
{
|
|||
|
public class LocalCodexBuilder
|
|||
|
{
|
|||
|
private readonly ILog log;
|
|||
|
private readonly string? repoPath;
|
|||
|
private readonly string? dockerUsername;
|
|||
|
|
|||
|
public LocalCodexBuilder(ILog log, string? repoPath, string? dockerUsername)
|
|||
|
{
|
|||
|
this.log = log;
|
|||
|
this.repoPath = repoPath;
|
|||
|
this.dockerUsername = dockerUsername;
|
|||
|
}
|
|||
|
|
|||
|
public LocalCodexBuilder(ILog log, string? repoPath)
|
|||
|
: this(log, repoPath, Environment.GetEnvironmentVariable("DOCKERUSERNAME"))
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public LocalCodexBuilder(ILog log)
|
|||
|
: this(log, Environment.GetEnvironmentVariable("CODEXREPOPATH"))
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void Intialize()
|
|||
|
{
|
|||
|
if (!IsEnabled()) return;
|
|||
|
|
|||
|
if (string.IsNullOrEmpty(dockerUsername)) throw new Exception("Docker username required. (Pass to constructor or set 'DOCKERUSERNAME' environment variable.)");
|
|||
|
if (string.IsNullOrEmpty(repoPath)) throw new Exception("Codex repo path required. (Pass to constructor or set 'CODEXREPOPATH' environment variable.)");
|
|||
|
if (!Directory.Exists(repoPath)) throw new Exception($"Path '{repoPath}' does not exist.");
|
|||
|
var files = Directory.GetFiles(repoPath);
|
|||
|
if (!files.Any(f => f.ToLowerInvariant().EndsWith("codex.nim"))) throw new Exception($"Path '{repoPath}' does not appear to be the Codex repo root.");
|
|||
|
|
|||
|
Log($"Codex docker image will be built in path '{repoPath}'.");
|
|||
|
Log("Please note this can take several minutes. If you're not trying to use a Codex image with local code changes,");
|
|||
|
Log("Consider using the default test image or consider setting the 'CODEXDOCKERIMAGE' environment variable to use an already built image.");
|
|||
|
CodexContainerRecipe.DockerImageOverride = $"Using docker image locally built in path '{repoPath}'.";
|
|||
|
}
|
|||
|
|
|||
|
public void Build()
|
|||
|
{
|
|||
|
if (!IsEnabled()) return;
|
|||
|
Log("Docker login...");
|
|||
|
DockerLogin();
|
|||
|
|
|||
|
Log($"Logged in. Building Codex image in path '{repoPath}'...");
|
|||
|
|
|||
|
var customImage = GenerateImageName();
|
|||
|
Docker($"build", "-t", customImage, "-f", "./codex.Dockerfile",
|
|||
|
"--build-arg=\"MAKE_PARALLEL=4\"",
|
|||
|
"--build-arg=\"NIMFLAGS=-d:disableMarchNative -d:codex_enable_api_debug_peers=true -d:codex_enable_api_debug_fetch=true -d:codex_enable_simulated_proof_failures\"",
|
|||
|
"--build-arg=\"NAT_IP_AUTO=true\"",
|
|||
|
"..");
|
|||
|
|
|||
|
Log($"Image '{customImage}' built successfully. Pushing...");
|
|||
|
|
|||
|
Docker("push", customImage);
|
|||
|
|
|||
|
CodexContainerRecipe.DockerImageOverride = customImage;
|
|||
|
Log("Image pushed. Good to go!");
|
|||
|
}
|
|||
|
|
|||
|
private void DockerLogin()
|
|||
|
{
|
|||
|
var dockerPassword = Environment.GetEnvironmentVariable("DOCKERPASSWORD");
|
|||
|
|
|||
|
if (string.IsNullOrEmpty(dockerUsername) || string.IsNullOrEmpty(dockerPassword))
|
|||
|
{
|
|||
|
Log("Environment variable 'DOCKERPASSWORD' not provided.");
|
|||
|
Log("Trying system default...");
|
|||
|
Docker("login");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Docker("login", "-u", dockerUsername, "-p", dockerPassword);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private string GenerateImageName()
|
|||
|
{
|
|||
|
return $"{dockerUsername!}/nim-codex-autoimage:{Guid.NewGuid().ToString().ToLowerInvariant()}";
|
|||
|
}
|
|||
|
|
|||
|
private void Docker(params string[] args)
|
|||
|
{
|
|||
|
var dockerPath = Path.Combine(repoPath!, "docker");
|
|||
|
|
|||
|
var startInfo = new ProcessStartInfo()
|
|||
|
{
|
|||
|
FileName = "docker",
|
|||
|
Arguments = string.Join(" ", args),
|
|||
|
WorkingDirectory = dockerPath,
|
|||
|
};
|
|||
|
var process = Process.Start(startInfo);
|
|||
|
if (process == null) throw new Exception("Failed to start docker process.");
|
|||
|
if (!process.WaitForExit(TimeSpan.FromMinutes(10))) throw new Exception("Docker processed timed out after 10 minutes.");
|
|||
|
if (process.ExitCode != 0) throw new Exception("Docker process exited with error.");
|
|||
|
}
|
|||
|
|
|||
|
private bool IsEnabled()
|
|||
|
{
|
|||
|
return !string.IsNullOrEmpty(repoPath);
|
|||
|
}
|
|||
|
|
|||
|
private void Log(string msg)
|
|||
|
{
|
|||
|
log.Log(msg);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|