コード例 #1
0
        public void TestMergeBuildManifests()
        {
            var orchestratedModel = new OrchestratedBuildModel(new BuildIdentity("Orchestrated", "123"))
            {
                Endpoints = new List <EndpointModel>
                {
                    EndpointModel.CreateOrchestratedBlobFeed("http://example.org")
                }
            };

            orchestratedModel.AddParticipantBuild(CreatePackageOnlyBuildManifestModel());
            orchestratedModel.AddParticipantBuild(BuildModel.Parse(XElement.Parse(ExampleBuildString)));

            XElement modelXml = orchestratedModel.ToXml();
            XElement xml      = XElement.Parse(@"
<OrchestratedBuild Name=""Orchestrated"" BuildId=""123"">
  <Endpoint Id=""Orchestrated"" Type=""BlobFeed"" Url=""http://example.org"">
    <Package Id=""Foo"" Version=""1.2.3-example"" />
    <Package Id=""runtime.rhel.6-x64.Microsoft.Private.CoreFx.NETCoreApp"" Version=""4.5.0-preview1-25929-04"" Category=""noship"" />
    <Package Id=""System.Memory"" Version=""4.5.0-preview1-25927-01"" />
    <Blob Id=""symbols/inner/blank-dir-nonshipping"" NonShipping=""false"" />
    <Blob Id=""symbols/runtime.rhel.6-x64.Microsoft.Private.CoreFx.NETCoreApp.4.5.0-preview1-25929-04.symbols.nupkg"" />
    <Blob Id=""symbols/System.ValueTuple.4.5.0-preview1-25929-04.symbols.nupkg"" NonShipping=""true"" />
  </Endpoint>
  <Build Name=""SimpleBuildManifest"" BuildId=""123"" />
  <Build Name=""corefx"" BuildId=""20171129-04"" Branch=""master"" Commit=""defb6d52047cc3d6b5f5d0853b0afdb1512dfbf4"" />
</OrchestratedBuild>");

            Assert.True(XNode.DeepEquals(xml, modelXml));
        }
コード例 #2
0
        public override bool Execute()
        {
            // Leave out attributes if they would just have empty string values.
            if (ManifestBranch == string.Empty)
            {
                ManifestBranch = null;
            }
            if (ManifestCommit == string.Empty)
            {
                ManifestCommit = null;
            }

            var identity = new BuildIdentity
            {
                Name         = ManifestName,
                BuildId      = ManifestBuildId,
                Branch       = ManifestBranch,
                Commit       = ManifestCommit,
                IsStable     = IsStable,
                VersionStamp = VersionStamp
            };

            var orchestratedBuild = new OrchestratedBuildModel(identity)
            {
                Endpoints = new List <EndpointModel>
                {
                    EndpointModel.CreateOrchestratedBlobFeed(BlobFeedUrl)
                }
            };

            foreach (ITaskItem buildManifestFile in BuildManifestFiles)
            {
                string contents = System.IO.File.ReadAllText(buildManifestFile.ItemSpec);

                BuildModel build = BuildModel.Parse(XElement.Parse(contents));

                foreach (PackageArtifactModel package in build.Artifacts.Packages)
                {
                    package.OriginBuildName = build.Identity.Name;
                }

                orchestratedBuild.AddParticipantBuild(build);
            }

            System.IO.File.WriteAllText(File, orchestratedBuild.ToXml().ToString());

            return(!Log.HasLoggedErrors);
        }
コード例 #3
0
        public async Task TestPushConflictingChangeAsync()
        {
            var mockGitHub = new Mock <IGitHubClient>(MockBehavior.Strict);

            var    client           = new BuildManifestClient(mockGitHub.Object);
            var    proj             = new GitHubProject("versions", "dotnet");
            string @ref             = "heads/master";
            string basePath         = "build-info/dotnet/product/cli/master";
            string message          = "Test change manifest commit";
            string addSemaphorePath = "add-identity.semaphore";

            var fakeExistingBuild = new OrchestratedBuildModel(new BuildIdentity {
                Name = "orch", BuildId = "123"
            });
            var fakeNewExistingBuild = new OrchestratedBuildModel(new BuildIdentity {
                Name = "orch", BuildId = "456"
            });
            string fakeCommitHash = "fakeCommitHash";

            mockGitHub
            .Setup(c => c.GetReferenceAsync(proj, @ref))
            .ReturnsAsync(() => new GitReference
            {
                Object = new GitReferenceObject {
                    Sha = fakeCommitHash
                }
            });

            mockGitHub
            .Setup(c => c.GetGitHubFileContentsAsync(It.IsAny <string>(), proj, fakeCommitHash))
            .ReturnsAsync(() => fakeNewExistingBuild.ToXml().ToString());

            var pushClient = client.PushChangeAsync(
                new BuildManifestChange(
                    new BuildManifestLocation(proj, @ref, basePath),
                    message,
                    fakeExistingBuild.Identity.BuildId,
                    new[] { addSemaphorePath },
                    _ => { }
                    ));
            Func <Task> act = async() => { await pushClient; };
            await act.Should().ThrowAsync <ManifestChangeOutOfDateException>();

            mockGitHub.VerifyAll();
        }
コード例 #4
0
        public async Task PushNewBuildAsync(
            BuildManifestLocation location,
            OrchestratedBuildModel build,
            IEnumerable <SupplementaryUploadRequest> supplementaryUploads,
            string message)
        {
            await Retry.RunAsync(async attempt =>
            {
                GitReference remoteRef = await _github.GetReferenceAsync(
                    location.GitHubProject,
                    location.GitHubRef);

                string remoteCommit = remoteRef.Object.Sha;

                Trace.TraceInformation($"Creating update on remote commit: {remoteCommit}");

                IEnumerable <SupplementaryUploadRequest> uploads = supplementaryUploads.NullAsEmpty()
                                                                   .Concat(new[]
                {
                    new SupplementaryUploadRequest
                    {
                        Path     = BuildManifestXmlName,
                        Contents = build.ToXml().ToString()
                    },
                    new SupplementaryUploadRequest
                    {
                        Path     = SemaphoreModel.BuildSemaphorePath,
                        Contents = new SemaphoreModel
                        {
                            BuildId = build.Identity.BuildId
                        }.ToFileContent()
                    }
                })
                                                                   .ToArray();

                return(await PushUploadsAsync(location, message, remoteCommit, uploads));
            });
        }
        public override bool Execute()
        {
            // Leave out attributes if they would just have empty string values.
            if (ManifestBranch == string.Empty)
            {
                ManifestBranch = null;
            }
            if (ManifestCommit == string.Empty)
            {
                ManifestCommit = null;
            }

            var orchestratedBuild = new OrchestratedBuildModel(new BuildIdentity(
                                                                   ManifestName,
                                                                   ManifestBuildId,
                                                                   ManifestBranch,
                                                                   ManifestCommit))
            {
                Endpoints = new List <EndpointModel>
                {
                    EndpointModel.CreateOrchestratedBlobFeed(BlobFeedUrl)
                }
            };

            foreach (ITaskItem buildManifestFile in BuildManifestFiles)
            {
                string contents = System.IO.File.ReadAllText(buildManifestFile.ItemSpec);

                BuildModel build = BuildModel.Parse(XElement.Parse(contents));
                orchestratedBuild.AddParticipantBuild(build);
            }

            System.IO.File.WriteAllText(File, orchestratedBuild.ToXml().ToString());

            return(!Log.HasLoggedErrors);
        }
コード例 #6
0
        public async Task TestPushNewBuildAsync()
        {
            var mockGitHub = new Mock <IGitHubClient>(MockBehavior.Strict);

            var client = new BuildManifestClient(mockGitHub.Object);
            var build  = new OrchestratedBuildModel(new BuildIdentity {
                Name = "orch", BuildId = "123"
            });
            var    proj     = new GitHubProject("versions", "dotnet");
            string @ref     = "heads/master";
            string basePath = "build-info/dotnet/product/cli/master";
            string message  = "Test build upload commit";

            string fakeCommitHash    = "fakeCommitHash";
            string fakeTreeHash      = "fakeTreeHash";
            string fakeNewCommitHash = "fakeNewCommitHash";

            mockGitHub
            .Setup(c => c.GetReferenceAsync(proj, @ref))
            .ReturnsAsync(() => new GitReference
            {
                Object = new GitReferenceObject {
                    Sha = fakeCommitHash
                }
            });

            mockGitHub
            .Setup(c => c.PostTreeAsync(
                       proj,
                       fakeCommitHash,
                       It.Is <GitObject[]>(
                           objects =>
                           objects.Length == 2 &&
                           objects[0].Path == $"{basePath}/{BuildManifestClient.BuildManifestXmlName}" &&
                           objects[0].Content == build.ToXml().ToString() &&
                           objects[1].Path == $"{basePath}/{SemaphoreModel.BuildSemaphorePath}" &&
                           objects[1].Content == build.Identity.BuildId + "\n")))
            .ReturnsAsync(() => new GitTree {
                Sha = fakeTreeHash
            });

            mockGitHub
            .Setup(c => c.PostCommitAsync(
                       proj,
                       message,
                       fakeTreeHash,
                       It.Is <string[]>(parents => parents.Single() == fakeCommitHash)))
            .ReturnsAsync(() => new GitCommit {
                Sha = fakeNewCommitHash
            });

            mockGitHub
            .Setup(c => c.PatchReferenceAsync(proj, @ref, fakeNewCommitHash, false))
            .ReturnsAsync(() => null);

            await client.PushNewBuildAsync(
                new BuildManifestLocation(proj, @ref, basePath),
                build,
                null,
                message);

            mockGitHub.VerifyAll();
        }
コード例 #7
0
        public async Task PushChangeAsync(BuildManifestChange change)
        {
            await Retry.RunAsync(async attempt =>
            {
                BuildManifestLocation location = change.Location;

                // Get the current commit. Use this throughout to ensure a clean transaction.
                GitReference remoteRef = await _github.GetReferenceAsync(
                    location.GitHubProject,
                    location.GitHubRef);

                string remoteCommit = remoteRef.Object.Sha;

                Trace.TraceInformation($"Creating update on remote commit: {remoteCommit}");

                XElement remoteModelXml = await FetchModelXmlAsync(
                    location.GitHubProject,
                    remoteCommit,
                    location.GitHubBasePath);

                OrchestratedBuildModel remoteModel = OrchestratedBuildModel.Parse(remoteModelXml);

                // This is a subsequent publish step: make sure a new build hasn't happened already.
                if (change.OrchestratedBuildId != remoteModel.Identity.BuildId)
                {
                    throw new ManifestChangeOutOfDateException(
                        change.OrchestratedBuildId,
                        remoteModel.Identity.BuildId);
                }

                OrchestratedBuildModel modifiedModel = OrchestratedBuildModel.Parse(remoteModelXml);
                change.ApplyModelChanges(modifiedModel);

                if (modifiedModel.Identity.BuildId != change.OrchestratedBuildId)
                {
                    throw new ArgumentException(
                        "Change action shouldn't modify BuildId. Changed from " +
                        $"'{change.OrchestratedBuildId}' to '{modifiedModel.Identity.BuildId}'.",
                        nameof(change));
                }

                XElement modifiedModelXml = modifiedModel.ToXml();

                string[] changedSemaphorePaths = change.SemaphorePaths.ToArray();

                // Check if any join groups are completed by this change.
                var joinCompleteCheckTasks = change.JoinSemaphoreGroups.NullAsEmpty()
                                             .Select(async g => new
                {
                    Group    = g,
                    Joinable = await IsGroupJoinableAsync(
                        location,
                        remoteCommit,
                        change.OrchestratedBuildId,
                        changedSemaphorePaths,
                        g)
                });

                var completeJoinedSemaphores = (await Task.WhenAll(joinCompleteCheckTasks))
                                               .Where(g => g.Joinable)
                                               .Select(g => g.Group.JoinSemaphorePath)
                                               .ToArray();

                IEnumerable <SupplementaryUploadRequest> semaphoreUploads = completeJoinedSemaphores
                                                                            .Concat(changedSemaphorePaths)
                                                                            .Select(p => new SupplementaryUploadRequest
                {
                    Path     = p,
                    Contents = new SemaphoreModel
                    {
                        BuildId = change.OrchestratedBuildId
                    }.ToFileContent()
                });

                IEnumerable <SupplementaryUploadRequest> uploads =
                    semaphoreUploads.Concat(change.SupplementaryUploads.NullAsEmpty());

                if (!XNode.DeepEquals(modifiedModelXml, remoteModelXml))
                {
                    uploads = uploads.Concat(new[]
                    {
                        new SupplementaryUploadRequest
                        {
                            Path     = BuildManifestXmlName,
                            Contents = modifiedModelXml.ToString()
                        }
                    });
                }

                return(await PushUploadsAsync(
                           location,
                           change.CommitMessage,
                           remoteCommit,
                           uploads));
            });
        }
コード例 #8
0
        public async Task TestPushChangeSemaphoreAsync()
        {
            var mockGitHub = new Mock <IGitHubClient>(MockBehavior.Strict);

            var    client           = new BuildManifestClient(mockGitHub.Object);
            var    proj             = new GitHubProject("versions", "dotnet");
            string @ref             = "heads/master";
            string basePath         = "build-info/dotnet/product/cli/master";
            string message          = "Test change manifest commit";
            string addSemaphorePath = "add-identity.semaphore";

            var    fakeExistingBuild       = new OrchestratedBuildModel(new BuildIdentity("orch", "123"));
            string fakeExistingBuildString = fakeExistingBuild.ToXml().ToString();
            string fakeCommitHash          = "fakeCommitHash";
            string fakeTreeHash            = "fakeTreeHash";
            string fakeNewCommitHash       = "fakeNewCommitHash";

            mockGitHub
            .Setup(c => c.GetReferenceAsync(proj, @ref))
            .ReturnsAsync(() => new GitReference
            {
                Object = new GitReferenceObject {
                    Sha = fakeCommitHash
                }
            });

            mockGitHub
            .Setup(c => c.GetGitHubFileContentsAsync(
                       $"{basePath}/{BuildManifestClient.BuildManifestXmlName}",
                       proj,
                       fakeCommitHash))
            .ReturnsAsync(() => fakeExistingBuildString);

            mockGitHub
            .Setup(c => c.PostTreeAsync(
                       proj,
                       fakeCommitHash,
                       It.Is <GitObject[]>(
                           objects =>
                           objects.Length == 1 &&
                           objects[0].Path == $"{basePath}/{addSemaphorePath}" &&
                           objects[0].Content == fakeExistingBuild.Identity.BuildId + "\n")))
            .ReturnsAsync(() => new GitTree {
                Sha = fakeTreeHash
            });

            mockGitHub
            .Setup(c => c.PostCommitAsync(
                       proj,
                       message,
                       fakeTreeHash,
                       It.Is <string[]>(parents => parents.Single() == fakeCommitHash)))
            .ReturnsAsync(() => new GitCommit {
                Sha = fakeNewCommitHash
            });

            mockGitHub
            .Setup(c => c.PatchReferenceAsync(proj, @ref, fakeNewCommitHash, false))
            .ReturnsAsync(() => null);

            await client.PushChangeAsync(
                proj,
                @ref,
                basePath,
                fakeExistingBuild.Identity.BuildId,
                _ => { },
                new[] { addSemaphorePath },
                null,
                message);

            mockGitHub.VerifyAll();
        }
コード例 #9
0
        public async Task PushChangeAsync(
            GitHubProject project,
            string @ref,
            string basePath,
            string orchestratedBuildId,
            Action <OrchestratedBuildModel> changeModel,
            IEnumerable <string> semaphorePaths,
            IEnumerable <SupplementaryUploadRequest> supplementaryUploads,
            string message)
        {
            await Retry.RunAsync(async attempt =>
            {
                // Get the current commit. Use this throughout to ensure a clean transaction.
                string remoteCommit = (await _github.GetReferenceAsync(project, @ref)).Object.Sha;

                Trace.TraceInformation($"Creating update on remote commit: {remoteCommit}");

                // This is a subsequent publish step: check to make sure the build id matches.
                XElement remoteModelXml = await FetchModelXmlAsync(project, remoteCommit, basePath);

                OrchestratedBuildModel remoteModel = OrchestratedBuildModel.Parse(remoteModelXml);

                if (orchestratedBuildId != remoteModel.Identity.BuildId)
                {
                    throw new ManifestChangeOutOfDateException(
                        orchestratedBuildId,
                        remoteModel.Identity.BuildId);
                }

                OrchestratedBuildModel modifiedModel = OrchestratedBuildModel.Parse(remoteModelXml);
                changeModel(modifiedModel);

                if (modifiedModel.Identity.BuildId != orchestratedBuildId)
                {
                    throw new ArgumentException(
                        "Change action shouldn't modify BuildId. Changed from " +
                        $"'{orchestratedBuildId}' to '{modifiedModel.Identity.BuildId}'.",
                        nameof(changeModel));
                }

                XElement modifiedModelXml = modifiedModel.ToXml();

                IEnumerable <SupplementaryUploadRequest> uploads = semaphorePaths.NullAsEmpty()
                                                                   .Select(p => new SupplementaryUploadRequest
                {
                    Path     = p,
                    Contents = new SemaphoreModel
                    {
                        BuildId = orchestratedBuildId
                    }.ToFileContent()
                })
                                                                   .Concat(supplementaryUploads.NullAsEmpty())
                                                                   .ToArray();

                if (!XNode.DeepEquals(modifiedModelXml, remoteModelXml))
                {
                    uploads = uploads.Concat(new[]
                    {
                        new SupplementaryUploadRequest
                        {
                            Path     = BuildManifestXmlName,
                            Contents = modifiedModelXml.ToString()
                        }
                    });
                }

                return(await PushUploadsAsync(project, @ref, basePath, message, remoteCommit, uploads));
            });
        }