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);
            }
        }
Exemple #3
0
        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);
            }
        }
Exemple #5
0
        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}");
                }
            }
        }
Exemple #6
0
        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);
        }
Exemple #8
0
        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);
        }