Skip to content

Commit b375f67

Browse files
bhaveshbhatiBhavesh Bhati
andauthored
Changes for Supporting Global Version (#21009)
Co-authored-by: Bhavesh Bhati <[email protected]>
1 parent b749cc6 commit b375f67

File tree

3 files changed

+177
-11
lines changed

3 files changed

+177
-11
lines changed

BuildConfigGen/GitUtil.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,66 @@ public static string FixupPath(string s)
211211

212212
return s;
213213
}
214+
215+
internal static bool HasChangesComparedToDefaultBranch(string filePath)
216+
{
217+
if (!File.Exists(filePath))
218+
{
219+
throw new FileNotFoundException($"The file '{filePath}' does not exist.");
220+
}
221+
222+
string directory = Path.GetDirectoryName(filePath) ?? throw new Exception("Unable to determine the directory of the file.");
223+
string relativePath = FixupPath(filePath);
224+
225+
string[] output;
226+
int exitCode = ProcessUtil.RunCommandWithExitCode("git", $"diff master -- \"{relativePath}\"", directory, out output);
227+
228+
if (exitCode != 0)
229+
{
230+
throw new Exception("Failed to check git status. Non-zero exit code.");
231+
}
232+
233+
// If the output contains any lines, it means there are uncommitted changes
234+
return output.Length > 0;
235+
}
236+
237+
internal static string GetDefaultBranchContent(string filePath)
238+
{
239+
if (!File.Exists(filePath))
240+
{
241+
throw new FileNotFoundException($"The file '{filePath}' does not exist.");
242+
}
243+
244+
string directory = Path.GetDirectoryName(filePath) ?? throw new Exception("Unable to determine the directory of the file.");
245+
string relativePath = GetGitPath(filePath);
246+
247+
string[] output;
248+
int exitCode = ProcessUtil.RunCommandWithExitCode("git", $"show master:\"{relativePath}\"", directory, out output);
249+
250+
if (exitCode != 0)
251+
{
252+
throw new Exception("Failed to retrieve unchanged content. Non-zero exit code.");
253+
}
254+
255+
return string.Join(Environment.NewLine, output);
256+
}
257+
258+
private static string GetGitPath(string filePath)
259+
{
260+
if (!File.Exists(filePath))
261+
{
262+
throw new FileNotFoundException($"The file '{filePath}' does not exist.");
263+
}
264+
265+
string directory = Path.GetDirectoryName(filePath) ?? throw new Exception("Unable to determine the directory of the file.");
266+
string gitRoot = RunGitCommandScalar(directory, "rev-parse --show-toplevel");
267+
268+
if (!filePath.StartsWith(FixupPath(gitRoot)))
269+
{
270+
throw new Exception($"The file '{filePath}' is not within the Git repository root '{gitRoot}'.");
271+
}
272+
273+
return filePath.Substring(gitRoot.Length + 1).Replace(Path.DirectorySeparatorChar, '/');
274+
}
214275
}
215276
}

BuildConfigGen/Program.cs

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ internal class Knob
1919
public bool SourceDirectoriesMustContainPlaceHolders { get; init; }
2020
}
2121

22+
internal static class ConfigExtensions
23+
{
24+
public static bool UpdatesOuputUnconditionally(this Program.Config.ConfigRecord config)
25+
{
26+
return config.isNode
27+
|| config.shouldUpdateLocalPkgs
28+
|| config.mergeToBase
29+
|| config.useAltGeneratedPath;
30+
}
31+
32+
public static bool ManagePackageJsonInOverride(this Program.Config.ConfigRecord config)
33+
{
34+
return config.isNode ||
35+
config.shouldUpdateLocalPkgs;
36+
}
37+
}
38+
2239
internal class Program
2340
{
2441
private const string filesOverriddenForConfigGoHereReadmeTxt = "FilesOverriddenForConfigGoHereREADME.txt";
@@ -52,7 +69,7 @@ public record ConfigRecord(string name, string constMappingKey, bool isDefault,
5269
public static readonly ConfigRecord Node20_229_14 = new ConfigRecord(name: nameof(Node20_229_14), constMappingKey: "Node20_229_14", isDefault: false, isNode: true, nodePackageVersion: "^20.3.1", isWif: false, nodeHandler: "Node20_1", preprocessorVariableName: "NODE20", enableBuildConfigOverrides: true, deprecated: false, shouldUpdateTypescript: true, overriddenDirectoryName: "Node20", writeNpmrc: true, mergeToBase: true);
5370
public static readonly ConfigRecord WorkloadIdentityFederation = new ConfigRecord(name: nameof(WorkloadIdentityFederation), constMappingKey: "WorkloadIdentityFederation", isDefault: false, isNode: true, nodePackageVersion: "^16.11.39", isWif: true, nodeHandler: "Node16", preprocessorVariableName: "WORKLOADIDENTITYFEDERATION", enableBuildConfigOverrides: true, deprecated: false, shouldUpdateTypescript: false, writeNpmrc: false);
5471
public static readonly ConfigRecord wif_242 = new ConfigRecord(name: nameof(wif_242), constMappingKey: "wif_242", isDefault: false, isNode: true, nodePackageVersion: "^20.3.1", isWif: true, nodeHandler: "Node20_1", preprocessorVariableName: "WIF", enableBuildConfigOverrides: true, deprecated: false, shouldUpdateTypescript: true, overriddenDirectoryName: "Wif", writeNpmrc: true);
55-
public static readonly ConfigRecord LocalPackages = new ConfigRecord(name: nameof(LocalPackages), constMappingKey: "LocalPackages", isDefault: false, isNode: true, nodePackageVersion: "^20.3.1", isWif: false, nodeHandler: "Node20_1", preprocessorVariableName: "NODE20", enableBuildConfigOverrides: true, deprecated: false, shouldUpdateTypescript: true, overriddenDirectoryName: "LocalPackages", writeNpmrc: true, shouldUpdateLocalPkgs: true, useGlobalVersion: true, useAltGeneratedPath: true);
72+
public static readonly ConfigRecord LocalPackages = new ConfigRecord(name: nameof(LocalPackages), constMappingKey: "LocalPackages", isDefault: false, isNode: false, nodePackageVersion: "^20.3.1", isWif: false, nodeHandler: "Node20_1", preprocessorVariableName: "NODE20", enableBuildConfigOverrides: true, deprecated: false, shouldUpdateTypescript: true, overriddenDirectoryName: "LocalPackages", writeNpmrc: true, shouldUpdateLocalPkgs: true, useGlobalVersion: true, useAltGeneratedPath: true);
5673
public static ConfigRecord[] Configs = { Default, Node16, Node16_225, Node20, Node20_228, Node20_229_1, Node20_229_2, Node20_229_3, Node20_229_4, Node20_229_5, Node20_229_6, Node20_229_7, Node20_229_8, Node20_229_9, Node20_229_10, Node20_229_11, Node20_229_12, Node20_229_13, Node20_229_14, WorkloadIdentityFederation, wif_242, LocalPackages };
5774
}
5875

@@ -140,7 +157,7 @@ private static void MainInner(string? task, string? configs, int? currentSprintN
140157
? new NoDebugConfigGenerator()
141158
: new VsCodeLaunchConfigGenerator(gitRootPath, debugAgentDir);
142159

143-
int maxPatchForCurrentSprint = 0;
160+
int maxPatchForCurrentSprint = -1;
144161

145162
int currentSprint;
146163
if (currentSprintNullable.HasValue)
@@ -152,6 +169,8 @@ private static void MainInner(string? task, string? configs, int? currentSprintN
152169
currentSprint = GetCurrentSprint();
153170
}
154171

172+
Console.WriteLine($"Current sprint: {currentSprint}");
173+
155174
Dictionary<string, TaskStateStruct> taskVersionInfo = [];
156175

157176
{
@@ -183,7 +202,7 @@ private static void MainInner(string? task, string? configs, int? currentSprintN
183202
taskVersionInfo.Add(t.Value.Name, new TaskStateStruct());
184203
IEnumerable<string> configsList = FilterConfigsForTask(configs, t);
185204
HashSet<Config.ConfigRecord> targetConfigs = GetConfigRecords(configsList, writeUpdates);
186-
UpdateVersionsForTask(t.Value.Name, taskVersionInfo[t.Value.Name], targetConfigs, currentSprint, globalVersionPath, globalVersion, generatedFolder);
205+
UpdateVersionsForTask(t.Value.Name, taskVersionInfo[t.Value.Name], targetConfigs, currentSprint, globalVersionPath, globalVersion, generatedFolder, includeUpdatesForTasksWithoutVersionMap: true);
187206

188207
bool taskTargettedForUpdating = allTasks || tasks.Where(x => x.Key == t.Value.Name).Any();
189208
bool taskVersionsNeedUpdating = taskVersionInfo[t.Value.Name].versionsUpdated.Any();
@@ -199,7 +218,11 @@ private static void MainInner(string? task, string? configs, int? currentSprintN
199218

200219
if (tasksNeedingUpdates.Count > 0)
201220
{
202-
throw new Exception($"The following tasks have versions that need updating (needed for updating global version): {string.Join(", ", tasksNeedingUpdates)}. Please run 'node make.js build --task [taskname]' to update");
221+
Console.WriteLine($"The following tasks have versions that need updating (needed for updating global version); including in list of tasks to update: {string.Join(", ", tasksNeedingUpdates)}.");
222+
223+
Console.WriteLine("before concat: " + string.Join(",", tasks.Select(x => x.Key).ToArray()));
224+
tasks = ConcatAdditionalTasks(allTasksList: allTasksList, existingTasks: tasks, tasksToAppend: tasksNeedingUpdates);
225+
Console.WriteLine("after concat: " + string.Join(",", tasks.Select(x => x.Key).ToArray()));
203226
}
204227

205228
// bump patch number for global if any tasks invalidated or if there is no existing global version
@@ -225,7 +248,7 @@ private static void MainInner(string? task, string? configs, int? currentSprintN
225248
taskVersionInfo.Add(t.Value.Name, new TaskStateStruct());
226249
IEnumerable<string> configsList = FilterConfigsForTask(configs, t);
227250
HashSet<Config.ConfigRecord> targetConfigs = GetConfigRecords(configsList, writeUpdates);
228-
UpdateVersionsForTask(t.Value.Name, taskVersionInfo[t.Value.Name], targetConfigs, currentSprint, globalVersionPath, globalVersion, generatedFolder);
251+
UpdateVersionsForTask(t.Value.Name, taskVersionInfo[t.Value.Name], targetConfigs, currentSprint, globalVersionPath, globalVersion, generatedFolder, includeUpdatesForTasksWithoutVersionMap: false);
229252
CheckForDuplicates(t.Value.Name, taskVersionInfo[t.Value.Name].configTaskVersionMapping, checkGlobalVersion: true);
230253
}
231254
}
@@ -303,6 +326,41 @@ private static void MainInner(string? task, string? configs, int? currentSprintN
303326
}
304327
}
305328

329+
private static IEnumerable<KeyValuePair<string, MakeOptionsReader.AgentTask>> ConcatAdditionalTasks(
330+
IEnumerable<KeyValuePair<string, MakeOptionsReader.AgentTask>> allTasksList,
331+
IEnumerable<KeyValuePair<string, MakeOptionsReader.AgentTask>> existingTasks,
332+
List<string> tasksToAppend)
333+
{
334+
List<KeyValuePair<string, MakeOptionsReader.AgentTask>> newTasks = new(existingTasks);
335+
336+
foreach (var taskNeedingUpdates in tasksToAppend)
337+
{
338+
bool taskExists = false;
339+
340+
foreach (var existingTask in newTasks)
341+
{
342+
if (string.Equals(existingTask.Key, taskNeedingUpdates))
343+
{
344+
taskExists = true;
345+
break;
346+
}
347+
}
348+
349+
if (!taskExists)
350+
{
351+
foreach (var taskToAdd in allTasksList)
352+
{
353+
if (string.Equals(taskToAdd.Key, taskNeedingUpdates, StringComparison.OrdinalIgnoreCase))
354+
{
355+
newTasks.Add(taskToAdd);
356+
}
357+
}
358+
}
359+
}
360+
361+
return newTasks;
362+
}
363+
306364
private static string GetTasksRootPath(string inputCurrentDir)
307365
{
308366
string? currentDir = inputCurrentDir;
@@ -617,10 +675,8 @@ private static void MainUpdateTask(
617675
// Note: CheckTaskInputContainsPreprocessorInstructions is expensive, so only call if needed
618676
if (versionUpdated
619677
|| taskConfigExists
620-
|| HasTaskInputContainsPreprocessorInstructions(gitRootPath, taskTargetPath, config)
621-
|| config.isNode
622-
|| config.mergeToBase
623-
|| taskVersionState.OnlyHasDefaultOrGlobalVersion)
678+
|| config.UpdatesOuputUnconditionally()
679+
|| HasTaskInputContainsPreprocessorInstructions(gitRootPath, taskTargetPath, config))
624680
{
625681
if (config.mergeToBase)
626682
{
@@ -675,7 +731,7 @@ private static void MainUpdateTask(
675731
WriteInputTaskJson(taskTargetPath, taskVersionState.configTaskVersionMapping, "task.json");
676732
WriteInputTaskJson(taskTargetPath, taskVersionState.configTaskVersionMapping, "task.loc.json");
677733

678-
if (config.isNode)
734+
if (config.ManagePackageJsonInOverride())
679735
{
680736
GetBuildConfigFileOverridePaths(config, taskTargetPath, out string configTaskPath, out string readmePath, generatedFolder, task);
681737

@@ -1244,7 +1300,7 @@ private static void CopyConfig(string gitRootPath, string taskTargetPathOrUnders
12441300
}
12451301
}
12461302

1247-
private static void UpdateVersionsForTask(string task, TaskStateStruct taskState, HashSet<Config.ConfigRecord> targetConfigs, int currentSprint, string globalVersionPath, TaskVersion? globalVersion, string generatedFolder)
1303+
private static void UpdateVersionsForTask(string task, TaskStateStruct taskState, HashSet<Config.ConfigRecord> targetConfigs, int currentSprint, string globalVersionPath, TaskVersion? globalVersion, string generatedFolder, bool includeUpdatesForTasksWithoutVersionMap)
12481304
{
12491305
string currentDir = Environment.CurrentDirectory;
12501306
string gitRootPath = GetTasksRootPath(currentDir);
@@ -1435,6 +1491,21 @@ private static void UpdateVersionsForTask(string task, TaskStateStruct taskState
14351491
}
14361492
}
14371493
}
1494+
1495+
// make this conditional because HasTaskVersionChanged is expensive
1496+
if (includeUpdatesForTasksWithoutVersionMap)
1497+
{
1498+
if (!taskState.versionsUpdated.Any())
1499+
{
1500+
// we'll get here if there is a task with no mapping file, so without checking git, we don't know if the task version has changed
1501+
// we'll check git on the base task to see if the task version changed (e.g. HEAD vs uncommited change)
1502+
1503+
if (HasTaskVersionChanged(taskTargetPath))
1504+
{
1505+
taskState.versionsUpdated.Add(Config.Default);
1506+
}
1507+
}
1508+
}
14381509
}
14391510

14401511
private static void UpdateMaxPatchForSprint(TaskStateStruct taskState, int currentSprint, ref int maxPatchForCurrentSprint)
@@ -1449,6 +1520,35 @@ private static void UpdateMaxPatchForSprint(TaskStateStruct taskState, int curre
14491520
}
14501521
}
14511522

1523+
private static bool HasTaskVersionChanged(string taskTargetPath)
1524+
{
1525+
string taskJsonPath = Path.Combine(taskTargetPath, "task.json");
1526+
1527+
if (!File.Exists(taskJsonPath))
1528+
{
1529+
throw new Exception($"Task file not found: {taskJsonPath}");
1530+
}
1531+
1532+
if (GitUtil.HasChangesComparedToDefaultBranch(taskJsonPath))
1533+
{
1534+
var defaultBranchContent = GitUtil.GetDefaultBranchContent(taskJsonPath);
1535+
1536+
JsonNode taskJson = JsonNode.Parse(defaultBranchContent)!;
1537+
int major = taskJson["version"]!["Major"]!.GetValue<int>();
1538+
int minor = taskJson["version"]!["Minor"]!.GetValue<int>();
1539+
int patch = taskJson["version"]!["Patch"]!.GetValue<int>();
1540+
1541+
TaskVersion versionInUnChangedTaskJson = new TaskVersion(major, minor, patch);
1542+
TaskVersion versionInChangedTaskJson = GetInputVersion(taskTargetPath);
1543+
1544+
return !versionInUnChangedTaskJson.Equals(versionInChangedTaskJson);
1545+
}
1546+
else
1547+
{
1548+
return false;
1549+
}
1550+
}
1551+
14521552
private static void UpdateVersionsGlobal(string task, TaskStateStruct taskState, HashSet<Config.ConfigRecord> targetConfigs, TaskVersion globalVersion)
14531553
{
14541554
foreach (var config in targetConfigs)

BuildConfigGen/TaskVersion.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ private TaskVersion(TaskVersion taskVersionToClone)
3636

3737
public TaskVersion(int major, int minor, int overidePatch)
3838
{
39+
if (overidePatch < 0)
40+
{
41+
throw new Exception($"Bug, overridePatch must be >=0, got {overidePatch}");
42+
}
43+
3944
Major = major;
4045
Minor = minor;
4146
Patch = overidePatch;

0 commit comments

Comments
 (0)