Пример #1
0
 public OrchestratedBuildDependencyInfo(
     string simpleName,
     OrchestratedBuildModel model)
 {
     SimpleName             = simpleName;
     OrchestratedBuildModel = model;
 }
        public override bool Execute()
        {
            string contents = System.IO.File.ReadAllText(ManifestFile);
            var    model    = OrchestratedBuildModel.Parse(XElement.Parse(contents));

            if (string.IsNullOrEmpty(CommitMessage))
            {
                CommitMessage = $"{model.Identity} orchestrated build manifest";
            }

            var gitHubAuth = new GitHubAuth(GitHubAuthToken, GitHubUser, GitHubEmail);

            using (var gitHubClient = new GitHubClient(gitHubAuth))
            {
                var client = new BuildManifestClient(gitHubClient);

                var location = new BuildManifestLocation(
                    new GitHubProject(VersionsRepo, VersionsRepoOwner),
                    $"heads/{VersionsRepoBranch}",
                    VersionsRepoPath);

                var pushTask = client.PushNewBuildAsync(
                    location,
                    model,
                    CreateUploadRequests(SupplementaryFiles),
                    CommitMessage);

                pushTask.Wait();
            }
            return(!Log.HasLoggedErrors);
        }
Пример #3
0
 public async Task <OrchestratedBuildModel> FetchManifestAsync(
     GitHubProject project,
     string @ref,
     string basePath)
 {
     return(OrchestratedBuildModel.Parse(await FetchModelXmlAsync(project, @ref, basePath)));
 }
Пример #4
0
        private static async Task <IEnumerable <IDependencyInfo> > LoadBuildInfoXml()
        {
            Trace.TraceInformation($"Retrieving build info from '{Options.BuildInfoUrl}'");

            XDocument buildInfoXml;

            if (File.Exists(Options.BuildInfoUrl.LocalPath))
            {
                buildInfoXml = XDocument.Load(Options.BuildInfoUrl.LocalPath);
            }
            else
            {
                using (HttpClient client = new HttpClient())
                    using (Stream stream = await client.GetStreamAsync(Options.BuildInfoUrl))
                    {
                        buildInfoXml = XDocument.Load(stream);
                    }
            }

            OrchestratedBuildModel buildInfo = OrchestratedBuildModel.Parse(buildInfoXml.Root);

            return(new[]
            {
                CreateDependencyBuildInfo(SdkBuildInfoName, buildInfo.Builds),
                CreateDependencyBuildInfo(RuntimeBuildInfoName, buildInfo.Builds),
                CreateDependencyBuildInfo(AspNetCoreBuildInfoName, buildInfo.Builds),
            });
        }
        private static void ApplyUpdate(OrchestratedBuildModel manifest, ITaskItem update)
        {
            string     type = update.GetMetadata(nameof(UpdateType));
            UpdateType updateType;

            if (!Enum.TryParse(type, true, out updateType))
            {
                throw new ArgumentException(
                          $"UpdateType '{type}' on update '{update.ItemSpec}' is not valid.");
            }

            switch (updateType)
            {
            case UpdateType.AddOrMergeEndpoint:
                var           xml      = XElement.Parse(update.GetMetadata(XmlMetadataName));
                EndpointModel endpoint = EndpointModel.Parse(xml);

                EndpointModel existingEndpoint = manifest.Endpoints
                                                 .FirstOrDefault(e => SameAttributes(endpoint.Attributes, e.Attributes));

                if (existingEndpoint == null)
                {
                    manifest.Endpoints.Add(endpoint);
                }
                else
                {
                    existingEndpoint.Artifacts.Add(endpoint.Artifacts);
                }
                break;
            }
        }
Пример #6
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));
        }
Пример #7
0
        public void TestExampleOrchestratedBuildManifestRoundtrip()
        {
            XElement xml      = XElement.Parse(ExampleOrchestratedBuildString);
            var      model    = OrchestratedBuildModel.Parse(xml);
            XElement modelXml = model.ToXml();

            XNode.DeepEquals(xml, modelXml).Should().BeTrue("Model failed to output the parsed XML.");
        }
        public async Task TestPushConflictAsync()
        {
            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.IsAny <GitObject[]>()))
            .ReturnsAsync(() => new GitTree {
                Sha = fakeTreeHash
            });

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

            mockGitHub
            .Setup(c => c.PatchReferenceAsync(proj, @ref, fakeNewCommitHash, false))
            .Callback(() =>
            {
                // Once the exception is hit, let the next patch call work.
                mockGitHub
                .Setup(c => c.PatchReferenceAsync(proj, @ref, fakeNewCommitHash, false))
                .ReturnsAsync(() => null);
            })
            .ThrowsAsync(new NotFastForwardUpdateException("Testing non-fast-forward update."));

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

            mockGitHub.VerifyAll();
        }
Пример #9
0
 public OrchestratedBuildDependencyInfo(
     string simpleName,
     string basePath,
     OrchestratedBuildModel model)
 {
     SimpleName             = simpleName;
     BasePath               = basePath;
     OrchestratedBuildModel = model;
 }
Пример #10
0
        protected IEnumerable <IDependencyInfo> CreateDependencyInfos(
            bool remote,
            string versionsCommit)
        {
            foreach (ITaskItem info in DependencyInfo ?? Enumerable.Empty <ITaskItem>())
            {
                IDependencyInfo dependencyInfo;

                string type = info.GetMetadata("DependencyType");
                switch (type)
                {
                case "Build":
                    SetVersionsCommitOverride(info, versionsCommit);
                    dependencyInfo = CreateBuildInfoDependency(info, BuildInfoCacheDir);
                    break;

                case "Submodule":
                    dependencyInfo = SubmoduleDependencyInfo.Create(
                        GetRequiredMetadata(info, "Repository"),
                        GetRequiredMetadata(info, "Ref"),
                        GetRequiredMetadata(info, "Path"),
                        remote);
                    break;

                case "Orchestrated build":
                    SetVersionsCommitOverride(info, versionsCommit);
                    dependencyInfo = OrchestratedBuildDependencyInfo.CreateAsync(
                        info.ItemSpec,
                        new GitHubProject(
                            GetRequiredMetadata(info, "VersionsRepo"),
                            GetRequiredMetadata(info, "VersionsRepoOwner")),
                        GetRequiredMetadata(info, CurrentRefMetadataName),
                        GetRequiredMetadata(info, "BasePath"),
                        new BuildManifestClient(GitHubClient)).Result;
                    break;

                case "Orchestrated build file":
                    dependencyInfo = new OrchestratedBuildDependencyInfo(
                        info.ItemSpec,
                        OrchestratedBuildModel.Parse(
                            XElement.Parse(
                                File.ReadAllText(
                                    GetRequiredMetadata(info, "Path")))));
                    break;

                default:
                    throw new NotSupportedException(
                              $"Unsupported DependencyInfo '{info.ItemSpec}': DependencyType '{type}'.");
                }

                DependencyInfoConfigItems[dependencyInfo] = info;
                yield return(dependencyInfo);
            }
        }
Пример #11
0
        public async Task <OrchestratedBuildModel> FetchManifestAsync(
            GitHubProject project,
            string @ref,
            string basePath)
        {
            XElement contents = await FetchModelXmlAsync(project, @ref, basePath);

            if (contents == null)
            {
                return(null);
            }

            return(OrchestratedBuildModel.Parse(contents));
        }
        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);
        }
Пример #13
0
        public override bool Execute()
        {
            GitHubAuth gitHubAuth = null;

            if (!string.IsNullOrEmpty(GitHubAuthToken))
            {
                gitHubAuth = new GitHubAuth(GitHubAuthToken, GitHubUser, GitHubEmail);
            }
            using (var gitHubClient = new GitHubClient(gitHubAuth))
            {
                var client = new BuildManifestClient(gitHubClient);

                OrchestratedBuildModel manifest = client.FetchManifestAsync(
                    new GitHubProject(VersionsRepo, VersionsRepoOwner),
                    VersionsRepoRef,
                    VersionsRepoPath)
                                                  .Result;

                OrchestratedBuild = CreateItem(manifest.Identity);

                EndpointModel[] orchestratedFeeds = manifest.Endpoints
                                                    .Where(e => e.IsOrchestratedBlobFeed)
                                                    .ToArray();

                if (orchestratedFeeds.Length != 1)
                {
                    throw new Exception(
                              "Invalid manifest. Expected 1 orchestrated blob feed, " +
                              $"found {orchestratedFeeds.Length}.");
                }

                EndpointModel feed = orchestratedFeeds[0];

                IEnumerable <ITaskItem> packageItems = feed.Artifacts.Packages.Select(CreateItem);
                IEnumerable <ITaskItem> blobItems    = feed.Artifacts.Blobs.Select(CreateItem);

                OrchestratedBlobFeed          = new[] { new TaskItem("Endpoint", feed.Attributes) };
                OrchestratedBlobFeedArtifacts = packageItems.Concat(blobItems).ToArray();

                IEnumerable <ITaskItem> buildItems = manifest.Builds.Select(CreateItem);

                OrchestratedBuildConstituents = buildItems.ToArray();
            }

            return(!Log.HasLoggedErrors);
        }
        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();
        }
Пример #15
0
        private static async Task <IEnumerable <IDependencyInfo> > GetBuildInfoAsync()
        {
            Trace.TraceInformation($"Retrieving build info from '{Options.BuildInfoUrl}'");

            using (HttpClient client = new HttpClient())
                using (Stream stream = await client.GetStreamAsync(Options.BuildInfoUrl))
                {
                    XDocument buildInfoXml           = XDocument.Load(stream);
                    OrchestratedBuildModel buildInfo = OrchestratedBuildModel.Parse(buildInfoXml.Root);
                    BuildIdentity          sdkBuild  = buildInfo.Builds
                                                       .First(build => string.Equals(build.Name, "cli", StringComparison.OrdinalIgnoreCase));
                    BuildIdentity coreSetupBuild = buildInfo.Builds
                                                   .First(build => string.Equals(build.Name, "core-setup", StringComparison.OrdinalIgnoreCase));

                    return(new[]
                    {
                        CreateDependencyBuildInfo(SdkBuildInfoName, sdkBuild.ProductVersion),
                        CreateDependencyBuildInfo(RuntimeBuildInfoName, coreSetupBuild.ProductVersion),
                    });
                };
        }
Пример #16
0
        public static async Task <OrchestratedBuildDependencyInfo> CreateAsync(
            string simpleName,
            GitHubProject project,
            string @ref,
            string basePath,
            BuildManifestClient client)
        {
            OrchestratedBuildModel model = await client.FetchManifestAsync(
                project,
                @ref,
                basePath);

            if (model == null)
            {
                throw new ArgumentException(
                          $"Found no manifest for '{simpleName}' at " +
                          $"'{project.Segments}' '{basePath}' ref '{@ref}'");
            }

            return(new OrchestratedBuildDependencyInfo(simpleName, basePath, model));
        }
Пример #17
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));
            });
        }
Пример #18
0
        private async Task <IDependencyInfo> GetBuildInfoAsync()
        {
            Trace.TraceInformation($"Retrieving build info from '{BuildInfoUrl}'");

            using (var client = new HttpClient())
                using (var stream = await client.GetStreamAsync(BuildInfoUrl))
                {
                    var buildInfoXml = XDocument.Load(stream);
                    var buildInfo    = OrchestratedBuildModel.Parse(buildInfoXml.Root);
                    var aspnetBuild  = buildInfo.Builds
                                       .First(build => string.Equals(build.Name, "aspnet", StringComparison.OrdinalIgnoreCase));

                    return(new BuildDependencyInfo(
                               new BuildInfo()
                    {
                        Name = RuntimeBuildInfo,
                        LatestReleaseVersion = aspnetBuild.ProductVersion,
                        LatestPackages = new Dictionary <string, string>()
                    },
                               false,
                               Enumerable.Empty <string>()));
                }
        }
        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);
        }
Пример #20
0
        public static OrchestratedBuild Load(string xmlText, string branch)
        {
            var model = OrchestratedBuildModel.Parse(XDocument.Parse(xmlText).Root);

            var orchestratedBuild = new OrchestratedBuild
            {
                BuildNumber         = model.Identity.BuildId,
                Branch              = branch,
                OrchestratedBuildId = $"{branch}/{model.Identity.BuildId}",
                Name         = model.Identity.Name,
                IsStable     = string.IsNullOrEmpty(model.Identity.IsStable) ? false : bool.Parse(model.Identity.IsStable),
                VersionStamp = model.Identity.VersionStamp
            };

            var buildsIndex = new Dictionary <string, Build>();

            foreach (var buildModel in model.Builds.Where(b => b.Name != "anonymous"))
            {
                var build = new Build
                {
                    OrchestratedBuildId = orchestratedBuild.OrchestratedBuildId,
                    Name           = buildModel.Name,
                    BuildNumber    = buildModel.BuildId,
                    BuildId        = $"{orchestratedBuild.OrchestratedBuildId}/builds/{buildModel.Name}/{buildModel.BuildId}",
                    Branch         = buildModel.Branch,
                    ProductVersion = buildModel.ProductVersion,
                    Commit         = buildModel.Commit,
                };

                buildsIndex[build.Name] = build;
                orchestratedBuild.Builds.Add(build);
            }

            var endpointIndex = new Dictionary <string, Endpoint>();
            var packageIndex  = new Dictionary <string, Package>();
            var blobIndex     = new Dictionary <string, Blob>();

            foreach (var endpoint in model.Endpoints)
            {
                var baseUrl = endpoint.Url;
                if (baseUrl.EndsWith("/index.json"))
                {
                    baseUrl = baseUrl.Substring(0, baseUrl.Length - 11);
                }
                if (endpoint.IsOrchestratedBlobFeed)
                {
                    baseUrl += "/assets";
                }

                var ep = new Endpoint
                {
                    EndpointId = $"{orchestratedBuild.OrchestratedBuildId}/endpoints/{endpoint.Id}",
                    Id         = endpoint.Id,
                    Type       = endpoint.Type,
                    Url        = endpoint.Url
                };

                endpointIndex[ep.EndpointId] = ep;
                orchestratedBuild.Endpoints.Add(ep);

                foreach (var artifact in endpoint.Artifacts.Packages)
                {
                    if (packageIndex.TryGetValue(artifact.Id, out var existingRef))
                    {
                        existingRef.Endpoints.Add(new EndpointRef()
                        {
                            EndpointRefId = $"{orchestratedBuild.OrchestratedBuildId}/endpoints/{ep.EndpointId}/packages/{artifact.Id}",
                            EndpointId    = ep.EndpointId,
                            ArtifactUrl   = $"{baseUrl}/flatcontainer/{artifact.Id}/{artifact.Version}/{artifact.Id}.{artifact.Version}.nupkg",
                        });
                    }
                    else
                    {
                        var packageRef = new Package
                        {
                            PackageId   = $"{orchestratedBuild.OrchestratedBuildId}/packages/{artifact.Id}",
                            Id          = artifact.Id,
                            Version     = artifact.Version,
                            NonShipping = bool.Parse(artifact.Attributes.TryGetValue("NonShipping", bool.TrueString))
                        };
                        if (!string.IsNullOrEmpty(artifact.OriginBuildName) && buildsIndex.TryGetValue(artifact.OriginBuildName, out var build))
                        {
                            packageRef.OriginBuildId = build.BuildId;
                        }
                        packageIndex[artifact.Id] = packageRef;
                        orchestratedBuild.Packages.Add(packageRef);
                    }
                }

                foreach (var artifact in endpoint.Artifacts.Blobs)
                {
                    if (blobIndex.TryGetValue(artifact.Id, out var existingRef))
                    {
                        existingRef.Endpoints.Add(new EndpointRef()
                        {
                            EndpointRefId = $"{orchestratedBuild.OrchestratedBuildId}/endpoints/{ep.EndpointId}/blobs/{artifact.Id}",
                            EndpointId    = ep.EndpointId,
                            ArtifactUrl   = $"{baseUrl}/assets/{artifact.Id}",
                        });
                    }
                    else
                    {
                        var blobRef = new Blob
                        {
                            BlobId        = $"{orchestratedBuild.OrchestratedBuildId}/blobs/{artifact.Id}",
                            Id            = artifact.Id,
                            Type          = artifact.Attributes.TryGetValue("Type"),
                            ShipInstaller = artifact.Attributes.TryGetValue("ShipInstaller")
                        };
                        blobIndex[artifact.Id] = blobRef;
                        orchestratedBuild.Blobs.Add(blobRef);
                    }
                }
            }

            return(orchestratedBuild);
        }
        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));
            });
        }
        public override bool Execute()
        {
            string contents = System.IO.File.ReadAllText(ManifestFile);
            OrchestratedBuildModel model    = OrchestratedBuildModel.Parse(XElement.Parse(contents));
            EndpointModel          blobFeed = model.Endpoints.First(e => e.IsOrchestratedBlobFeed);

            string feedAssetsRoot = blobFeed.Url.Replace("/index.json", "/assets");

            string sdkProductVersion = model.Builds
                                       .FirstOrDefault(b => b.Name == "cli")
                                       ?.ProductVersion;

            string runtimeProductVersion = model.Builds
                                           .FirstOrDefault(b => b.Name == "core-setup")
                                           ?.ProductVersion;

            string aspnetProductVersion = model.Builds
                                          .FirstOrDefault(b => b.Name == "aspnet")
                                          ?.ProductVersion;

            var builder = new StringBuilder();

            builder.Append("## Product build: ");
            builder.AppendLine(model.Identity.ToString());

            if (!string.IsNullOrEmpty(SdkTableTemplateFile) && sdkProductVersion != null)
            {
                builder.AppendLine();
                builder.AppendLine(FillTemplate(
                                       SdkTableTemplateFile,
                                       feedAssetsRoot,
                                       sdkProductVersion));
            }

            if (!string.IsNullOrEmpty(DotNetRuntimeTableTemplateFile) && runtimeProductVersion != null)
            {
                builder.AppendLine();
                builder.AppendLine(FillTemplate(
                                       DotNetRuntimeTableTemplateFile,
                                       feedAssetsRoot,
                                       runtimeProductVersion));
            }

            if (!string.IsNullOrEmpty(AspNetCoreRuntimeTableTemplateFile) && aspnetProductVersion != null)
            {
                builder.AppendLine();
                builder.AppendLine(FillTemplate(
                                       AspNetCoreRuntimeTableTemplateFile,
                                       feedAssetsRoot,
                                       aspnetProductVersion));
            }

            builder.AppendLine();
            builder.AppendLine("### Built Repositories");

            foreach (BuildIdentity build in model.Builds
                     .Where(b => b.Name != "anonymous")
                     .OrderBy(b => b.Name))
            {
                builder.Append(" * ");
                builder.AppendLine(build.ToString());
            }

            System.IO.File.WriteAllText(File, builder.ToString());

            return(!Log.HasLoggedErrors);
        }
Пример #23
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();
        }
        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();
        }
Пример #25
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));
            });
        }