async Task DetermineLastVersionChangeCommit(Context context) { Log.StatusLine($" {context.Characters.Bullet} Commit of last version change", ConsoleColor.Gray); GitRunner git = CreateGitRunner(context); IList <GitRunner.BlamePorcelainEntry> blameEntries; blameEntries = await git.Blame("Configuration.props"); if (blameEntries == null || blameEntries.Count == 0) { throw new InvalidOperationException("Unable to determine the last version change commit"); } foreach (GitRunner.BlamePorcelainEntry be in blameEntries) { if (be == null || String.IsNullOrEmpty(be.Line)) { continue; } if (be.Line.IndexOf("<ProductVersion>") >= 0) { Log.DebugLine($"Last version change on {GetCommitDate (be)} by {be.Author}"); CommitOfLastVersionChange = be.Commit; Log.StatusLine(" Commit: ", be.Commit, tailColor: ConsoleColor.Cyan); break; } } }
void DetermineMonoHash(Context context) { GitRunner git = CreateGitRunner(context); Log.StatusLine($" {context.Characters.Bullet} Mono commit hash", ConsoleColor.Gray); List <ExternalGitDependency> externalDependencies = ExternalGitDependency.GetDependencies(context, Configurables.Paths.ExternalGitDepsFilePath, quiet: true); ExternalGitDependency mono = externalDependencies?.Where( eg => eg != null && String.Compare("mono", eg.Owner, StringComparison.Ordinal) == 0 && String.Compare("mono", eg.Name, StringComparison.Ordinal) == 0).FirstOrDefault(); FullMonoHash = mono?.Commit?.Trim(); MonoHash = EnsureHash("Mono", Utilities.ShortenGitHash(FullMonoHash)); string EnsureHash(string name, string hash) { if (String.IsNullOrEmpty(hash)) { throw new InvalidOperationException($"Unable to determine {name} commit hash"); } Log.StatusLine(" Commit: ", hash, tailColor: ConsoleColor.Cyan); Log.StatusLine(); return(hash); } }
protected override async Task <bool> Execute(Context context) { var nugets = MSBuildPackageReferenceInfo.GetPackageReferences(); var git = new GitRunner(context); var gitSubmoduleInfo = await git.ConfigList(new[] { "--blob", "HEAD:.gitmodules" }); var gitSubmoduleStatus = await git.SubmoduleStatus(); var gitSubmodules = GitSubmoduleInfo.GetGitSubmodules(gitSubmoduleInfo, gitSubmoduleStatus); var cgManifestEntries = ((IEnumerable <CGManifestEntry>)nugets).Concat(gitSubmodules) .OrderBy(e => e.Name); var jsonPath = Path.Combine(Configurables.Paths.BuildBinDir, "CGManifest.json"); using var json = File.CreateText(jsonPath); json.WriteLine("{"); json.WriteLine(" \"Registrations\": ["); var properties = new Dictionary <string, string> (); bool first = true; foreach (var entry in cgManifestEntries) { if (first) { first = false; } else { json.WriteLine(","); } WriteComponent(json, entry, properties); } json.WriteLine(); json.WriteLine(" ]"); json.WriteLine("}"); return(true); }
void DetermineBundleHashes(Context context) { GitRunner git = CreateGitRunner(context); Log.StatusLine($" {context.Characters.Bullet} LibZip commit hash", ConsoleColor.Gray); FullLibZipHash = git.GetTopCommitHash(context.Properties.GetRequiredValue(KnownProperties.LibZipSourceFullPath), shortHash: false); LibZipHash = EnsureHash("LibZip", Utilities.ShortenGitHash(FullLibZipHash)); Log.StatusLine($" {context.Characters.Bullet} Mono commit hash", ConsoleColor.Gray); List <ExternalGitDependency> externalDependencies = ExternalGitDependency.GetDependencies(context, Configurables.Paths.ExternalGitDepsFilePath, quiet: true); ExternalGitDependency mono = externalDependencies?.Where( eg => eg != null && String.Compare("mono", eg.Owner, StringComparison.Ordinal) == 0 && String.Compare("mono", eg.Name, StringComparison.Ordinal) == 0).FirstOrDefault(); FullMonoHash = mono?.Commit?.Trim(); MonoHash = EnsureHash("Mono", Utilities.ShortenGitHash(FullMonoHash)); if (Configurables.Paths.BundleVersionHashFiles == null || Configurables.Paths.BundleVersionHashFiles.Count == 0) { Log.WarningLine("Bundle version hash files not specified"); return; } Log.StatusLine($" {context.Characters.Bullet} Generating bundle version hash", ConsoleColor.Gray); using (var ha = HashAlgorithm.Create(context.HashAlgorithm)) { HashFiles(ha, Configurables.Paths.BundleVersionHashFiles); VersionHash = FormatHash(ha.Hash).Substring(0, (int)Configurables.Defaults.AbbreviatedHashLength); Log.StatusLine(" Hash: ", VersionHash, tailColor: ConsoleColor.Cyan); } string EnsureHash(string name, string hash) { if (String.IsNullOrEmpty(hash)) { throw new InvalidOperationException($"Unable to determine {name} commit hash"); } Log.StatusLine(" Commit: ", hash, tailColor: ConsoleColor.Cyan); Log.StatusLine(); return(hash); } }
async Task <string> GetGitHubURL(ExternalGitDependency egd, GitRunner git) { string ghToken = Environment.GetEnvironmentVariable("GH_AUTH_SECRET"); if (!String.IsNullOrEmpty(ghToken)) { return($"https://{ghToken}@github.com:/{egd.Owner}/{egd.Name}"); } else { if (await git.IsRepoUrlHttps(BuildPaths.XamarinAndroidSourceRoot)) { return($"https://github.com:/{egd.Owner}/{egd.Name}"); } else { return($"[email protected]:/{egd.Owner}/{egd.Name}"); } } }
void DetermineBundleHashes(Context context) { GitRunner git = CreateGitRunner(context); Log.StatusLine($" {context.Characters.Bullet} LibZip commit hash", ConsoleColor.Gray); FullLibZipHash = git.GetTopCommitHash(context.Properties.GetRequiredValue(KnownProperties.LibZipSourceFullPath), shortHash: false); LibZipHash = EnsureHash("LibZip", Utilities.ShortenGitHash(FullLibZipHash)); Log.StatusLine($" {context.Characters.Bullet} Mono commit hash", ConsoleColor.Gray); FullMonoHash = git.GetTopCommitHash(context.Properties.GetRequiredValue(KnownProperties.MonoSourceFullPath), shortHash: false); MonoHash = EnsureHash("Mono", Utilities.ShortenGitHash(FullMonoHash)); if (Configurables.Paths.BundleVersionHashFiles == null || Configurables.Paths.BundleVersionHashFiles.Count == 0) { Log.WarningLine("Bundle version hash files not specified"); return; } Log.StatusLine($" {context.Characters.Bullet} Generating bundle version hash", ConsoleColor.Gray); using (var ha = HashAlgorithm.Create(context.HashAlgorithm)) { HashFiles(ha, Configurables.Paths.BundleVersionHashFiles); VersionHash = FormatHash(ha.Hash).Substring(0, (int)Configurables.Defaults.AbbreviatedHashLength); Log.StatusLine(" Hash: ", VersionHash, tailColor: ConsoleColor.Cyan); } string EnsureHash(string name, string hash) { if (String.IsNullOrEmpty(hash)) { throw new InvalidOperationException($"Unable to determine {name} commit hash"); } Log.StatusLine(" Commit: ", hash, tailColor: ConsoleColor.Cyan); Log.StatusLine(); return(hash); } }
protected override async Task <bool> Execute(Context context) { Log.StatusLine("Determining test jobs to run..."); string commitRevision = Environment.GetEnvironmentVariable("BUILD_SOURCEVERSION"); string commitMessage = Environment.GetEnvironmentVariable("BUILD_SOURCEVERSIONMESSAGE"); if (string.IsNullOrEmpty(commitRevision) || string.IsNullOrEmpty(commitMessage)) { Log.ErrorLine("One or more source version variable values were empty:"); Log.ErrorLine($"BUILD_SOURCEVERSION='{commitRevision}' BUILD_SOURCEVERSIONMESSAGE='{commitMessage}'."); return(false); } // Assume we're building a merge commit as part of an Azure Pipelines PR build. Otherwise, this step will fail. // Example: Merge 0b66502c8b9f33cbb8d21b2dab7c100629aec081 into 0bef8aa5cd74d83d77c4e2b3f63975a0deb804b3 var commitMessagePieces = commitMessage.Split(new string [] { " " }, StringSplitOptions.RemoveEmptyEntries); if (string.IsNullOrEmpty(commitMessagePieces [3])) { Log.ErrorLine($"Unable to parse merge commit message from: '{commitMessage}'."); return(false); } var git = new GitRunner(context); var filesChanged = await git.RunCommandForOutputAsync(BuildPaths.XamarinAndroidSourceRoot, "diff", "--name-only", commitRevision, commitMessagePieces [3]); if (filesChanged == null || filesChanged.Count < 1) { Log.ErrorLine($"Unable to determine if any files were changed in this PR."); return(false); } var testAreas = new HashSet <string> (); foreach (string file in filesChanged) { Log.InfoLine($"Detected change in file: '{file}'."); // Compare files changed against common areas requiring additional test scope. // MSBuild: Runs all legacy and One .NET Xamarin.Android.Build.Task tests // MSBuildDevice: Runs all MSBuildDeviceIntegration tests // BCL: Runs BCL tests on emulator // TimeZone: Runs timezone unit tests on emulator // Designer: Runs designer integration tests if (file == ".external" || file == "Configuration.props") { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); testAreas.Add("BCL"); testAreas.Add("TimeZone"); testAreas.Add("Designer"); } if (file.Contains("build-tools/installers")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); testAreas.Add("Designer"); } if (file.Contains("external/Java.Interop")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); testAreas.Add("Designer"); } if (file.Contains("external/proguard")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("external/sqlite")) { testAreas.Add("MSBuildDevice"); } if (file.Contains("src/aapt2")) { testAreas.Add("MSBuild"); } if (file.Contains("src/apksigner")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("src/bundletool")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("src/java-runtime")) { testAreas.Add("MSBuildDevice"); } if (file.Contains("src/manifestmerger")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("src/Microsoft.Android.Sdk.ILLink")) { testAreas.Add("MSBuild"); } if (file.Contains("src/Mono.Android")) { testAreas.Add("Designer"); } if (file.Contains("src/monodroid")) { testAreas.Add("MSBuildDevice"); testAreas.Add("Designer"); } if (file.Contains("src/proguard")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("src/r8")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("src/Xamarin.Android.Build.Tasks")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); testAreas.Add("Designer"); } if (file.Contains("src/Xamarin.Android.Tools.Aidl")) { testAreas.Add("MSBuild"); } if (file.Contains("src/Xamarin.Android.Tools.JavadocImporter")) { testAreas.Add("MSBuild"); } if (file.Contains("src-ThirdParty/android-platform-tools-base")) { testAreas.Add("MSBuild"); testAreas.Add("MSBuildDevice"); } if (file.Contains("src-ThirdParty/bazel")) { testAreas.Add("MSBuildDevice"); } if (file.Contains("tests/BCL-Tests")) { testAreas.Add("BCL"); } if (file.Contains("tests/MSBuildDeviceIntegration")) { testAreas.Add("MSBuildDevice"); testAreas.Add("TimeZone"); } if (file.Contains("tests/msbuild-times-reference")) { testAreas.Add("MSBuildDevice"); } } Log.MessageLine($"##vso[task.setvariable variable=TestAreas;isOutput=true]{string.Join (",", testAreas)}"); return(true); }
protected override async Task <bool> Execute(Context context) { List <ExternalGitDependency> externalDependencies = ExternalGitDependency.GetDependencies(context, Configurables.Paths.ExternalGitDepsFilePath); bool failed = false; Log.StatusLine(); Log.StatusLine("Updating external repositories"); var git = new GitRunner(context) { EchoCmdAndArguments = false }; foreach (ExternalGitDependency egd in externalDependencies) { Log.StatusLine($" {context.Characters.Bullet} {egd.Name}"); string destDir = Path.Combine(Configurables.Paths.ExternalGitDepsDestDir, egd.Name); if (!Directory.Exists(destDir)) { var egdUrl = await GetGitHubURL(egd, git); Log.StatusLine($" {context.Characters.Link} cloning from {egd.Owner}/{egd.Name}"); if (!await git.Clone(egdUrl, destDir)) { Log.ErrorLine($"Failed to clone {egd.Name}"); failed = true; continue; } } Log.StatusLine($" {context.Characters.Link} fetching changes from {egd.Owner}/{egd.Name}"); if (!await git.Fetch(destDir)) { Log.ErrorLine($"Failed to fetch changes for {egd.Name}"); failed = true; continue; } Log.StatusLine($" {context.Characters.Bullet} checking out commit {egd.Commit}"); if (!await git.CheckoutCommit(destDir, egd.Commit)) { Log.ErrorLine($"Failed to checkout commit {egd.Commit} for {egd.Name}"); failed = true; continue; } // // Commented out for now because we only have monodroid in .external and its submodules are updated // elsewhere and there's no need to duplicate the (time-consuming) work. However, it might be a good // idea to re-enable this code for the benefit of future .external additions (and, possibly, monodroid // itself after its integration code is updated to not initialize submodules) // // string gitModules = Path.Combine (destDir, ".gitmodules"); // if (!Utilities.FileExists (gitModules)) // continue; // Log.StatusLine ($" {context.Characters.Bullet} updating submodules"); // if (!await git.SubmoduleUpdate (destDir)) { // Log.ErrorLine ($"Failed to update submodules for {egd.Name}"); // failed = true; // } } return(!failed); }