Program.cs
 1  using System.Security.Cryptography;
 2  using System.Text;
 3  using Utils;
 4  
 5  public static class Program
 6  {
 7      private const string Search = "<INSERT-OPENAPI-YAML-HASH>";
 8      private const string CodexPluginFolderName = "CodexPlugin";
 9      private const string ProjectPluginsFolderName = "ProjectPlugins";
10  
11      public static void Main(string[] args)
12      {
13          Console.WriteLine("Injecting hash of 'openapi.yaml'...");
14  
15          var pluginRoot = FindCodexPluginFolder();
16          var clientRoot = FindCodexClientFolder();
17          Console.WriteLine("Located CodexPlugin: " + pluginRoot);
18          var openApiFile = Path.Combine(clientRoot, "openapi.yaml");
19          var clientFile = Path.Combine(clientRoot, "obj", "openapiClient.cs");
20          var targetFile = Path.Combine(pluginRoot, "ApiChecker.cs");
21  
22          // Force client rebuild by deleting previous artifact.
23          File.Delete(clientFile);
24  
25          var hash = CreateHash(openApiFile);
26          // This hash is used to verify that the Codex docker image being used is compatible
27          // with the openapi.yaml being used by the Codex plugin.
28          // If the openapi.yaml files don't match, an exception is thrown.
29  
30          SearchAndInject(hash, targetFile);
31  
32          // This program runs as the pre-build trigger for "CodexPlugin".
33          // You might be wondering why this work isn't done by a shell script.
34          // This is because this project is being run on many different platforms.
35          // (Mac, Unix, Win, but also desktop/cloud containers.)
36          // In order to not go insane trying to make a shell script that works in all possible cases,
37          // instead we use the one tool that's definitely installed in all platforms and locations
38          // when you're trying to run this plugin.
39  
40          Console.WriteLine("Done!");
41      }
42  
43      private static string FindCodexPluginFolder()
44      {
45          var folder = Path.Combine(PluginPathUtils.ProjectPluginsDir, "CodexPlugin");
46          if (!Directory.Exists(folder)) throw new Exception("CodexPlugin folder not found. Expected: " + folder);
47          return folder;
48      }
49  
50      private static string FindCodexClientFolder()
51      {
52          var folder = Path.Combine(PluginPathUtils.ProjectPluginsDir, "CodexClient");
53          if (!Directory.Exists(folder)) throw new Exception("CodexClient folder not found. Expected: " + folder);
54          return folder;
55      }
56  
57      private static string CreateHash(string openApiFile)
58      {
59          var file = File.ReadAllText(openApiFile);
60          var fileBytes = Encoding.ASCII.GetBytes(file
61              .Replace(Environment.NewLine, ""));
62  
63          var sha = SHA256.Create();
64          var hash = sha.ComputeHash(fileBytes);
65          return BitConverter.ToString(hash);
66      }
67  
68      private static void SearchAndInject(string hash, string targetFile)
69      {
70          var lines = File.ReadAllLines(targetFile);
71          Inject(lines, hash);
72          File.WriteAllLines(targetFile, lines);
73      }
74  
75      private static void Inject(string[] lines, string hash)
76      {
77          for (var i = 0; i < lines.Length; i++)
78          {
79              if (lines[i].Contains(Search))
80              {
81                  lines[i + 1] = $"        private const string OpenApiYamlHash = \"{hash}\";";
82                  return;
83              }
84          }
85      }
86  }