public async Task <IActionResult> AddBuildToChannel(int channelId, int buildId) { Data.Models.Channel channel = await _context.Channels.FindAsync(channelId); if (channel == null) { return(NotFound(new ApiError($"The channel with id '{channelId}' was not found."))); } Data.Models.Build build = await _context.Builds.FindAsync(buildId); if (build == null) { return(NotFound(new ApiError($"The build with id '{buildId}' was not found."))); } var buildChannel = new Data.Models.BuildChannel { Channel = channel, Build = build }; await _context.BuildChannels.AddAsync(buildChannel); await _context.SaveChangesAsync(); return(StatusCode((int)HttpStatusCode.Created)); }
public Build([NotNull] Data.Models.Build other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } Id = other.Id; Commit = other.Commit; GitHubRepository = other.GitHubRepository; GitHubBranch = other.GitHubBranch; PublishUsingPipelines = other.PublishUsingPipelines; AzureDevOpsBuildId = other.AzureDevOpsBuildId; AzureDevOpsBuildDefinitionId = other.AzureDevOpsBuildDefinitionId; AzureDevOpsAccount = other.AzureDevOpsAccount; AzureDevOpsProject = other.AzureDevOpsProject; AzureDevOpsBuildNumber = other.AzureDevOpsBuildNumber; AzureDevOpsRepository = other.AzureDevOpsRepository; AzureDevOpsBranch = other.AzureDevOpsBranch; DateProduced = other.DateProduced; Channels = other.BuildChannels?.Select(bc => bc.Channel) .Where(c => c != null) .Select(c => new v2018_07_16.Models.Channel(c)) .ToList(); Assets = other.Assets?.Select(a => new v2018_07_16.Models.Asset(a)).ToList(); Dependencies = other.DependentBuildIds?.Select(d => new BuildRef(d.DependentBuildId, d.IsProduct, d.TimeToInclusionInMinutes)).ToList(); Staleness = other.Staleness; Released = other.Released; }
protected async Task <IActionResult> TriggerSubscriptionCore(Guid id, int buildId) { Data.Models.Subscription subscription = await _context.Subscriptions.Include(sub => sub.LastAppliedBuild) .Include(sub => sub.Channel) .FirstOrDefaultAsync(sub => sub.Id == id); if (buildId != 0) { Data.Models.Build build = await _context.Builds.Where(b => b.Id == buildId).FirstOrDefaultAsync(); // Non-existent build if (build == null) { return(BadRequest($"Build {buildId} was not found")); } // Build doesn't match source repo if (!(build.GitHubRepository?.Equals(subscription.SourceRepository, StringComparison.InvariantCultureIgnoreCase) == true || build.AzureDevOpsRepository?.Equals(subscription.SourceRepository, StringComparison.InvariantCultureIgnoreCase) == true)) { return(BadRequest($"Build {buildId} does not match source repo")); } } if (subscription == null) { return(NotFound()); } var values = new { SubId = id, BuildId = buildId }; _queue.Post <StartSubscriptionUpdateWorkItem>(JToken.FromObject(values)); return(Accepted(new Subscription(subscription))); }
private Build ToClientModelBuild(Data.Models.Build other) { var channels = other.BuildChannels? .Select(bc => ToClientModelChannel(bc.Channel)) .ToImmutableList(); var assets = other.Assets? .Select(a => new Asset(a.Id, a.BuildId, a.NonShipping, a.Name, a.Version, null)) .ToImmutableList(); var dependencies = other.DependentBuildIds? .Select(ToClientModelBuildDependency) .ToImmutableList(); var incoherences = other.Incoherencies? .Select(ToClientModelBuildIncoherence) .ToImmutableList(); return(new Build( other.Id, other.DateProduced, other.Staleness, other.Released, other.Stable, other.Commit, channels, assets, dependencies, incoherences)); }
public virtual async Task <IActionResult> Update(int buildId, [FromBody, Required] BuildUpdate buildUpdate) { Data.Models.Build build = await _context.Builds.Where(b => b.Id == buildId).FirstOrDefaultAsync(); if (build == null) { return(NotFound()); } bool doUpdate = false; if (buildUpdate.Released.HasValue && build.Released != buildUpdate.Released.Value) { build.Released = buildUpdate.Released.Value; doUpdate = true; } if (doUpdate) { _context.Builds.Update(build); await _context.SaveChangesAsync(); } return(Ok(new Models.Build(build))); }
public async Task <IActionResult> Create([FromBody, Required] BuildData build) { Data.Models.Build buildModel = build.ToDb(); buildModel.DateProduced = DateTimeOffset.UtcNow; if (build.Dependencies != null) { await _context.BuildDependencies.AddRangeAsync( build.Dependencies.Select( b => new Data.Models.BuildDependency { Build = buildModel, DependentBuildId = b.BuildId, IsProduct = b.IsProduct, })); } await _context.Builds.AddAsync(buildModel); await _context.SaveChangesAsync(); return(CreatedAtRoute( new { action = "GetBuild", id = buildModel.Id }, new Models.Build(buildModel))); }
public override async Task <IActionResult> GetLatest( string repository, string commit, string buildNumber, int?channelId, DateTimeOffset?notBefore, DateTimeOffset?notAfter, bool?loadCollections) { IQueryable <Data.Models.Build> query = Query( repository, commit, buildNumber, null, null, null, channelId, notBefore, notAfter, loadCollections); Data.Models.Build build = await query.OrderByDescending(o => o.DateProduced).FirstOrDefaultAsync(); if (build == null) { return(NotFound()); } return(Ok(new Models.Build(build))); }
public async Task <IActionResult> Create([FromBody] BuildData build) { var buildModel = new Data.Models.Build(build) { DateProduced = DateTimeOffset.UtcNow, Dependencies = await _context.Builds.Where(b => build.Dependencies.Contains(b.Id)).ToListAsync() }; await _context.Builds.AddAsync(buildModel); var defaultChannels = await _context.DefaultChannels .Where(dc => dc.Repository == buildModel.Repository && dc.Branch == buildModel.Branch) .Select(dc => dc.ChannelId) .ToListAsync(); foreach (var channelId in defaultChannels) { await _context.BuildChannels.AddAsync(new Data.Models.BuildChannel { ChannelId = channelId, Build = buildModel, }); } await _context.SaveChangesAsync(); return(CreatedAtRoute(new { action = "GetBuild", id = buildModel.Id }, new Build(buildModel))); }
public Build([NotNull] Data.Models.Build other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } var hasGitHubInfo = other.GitHubRepository != null; Id = other.Id; Repository = (hasGitHubInfo) ? other.GitHubRepository : other.AzureDevOpsRepository; Branch = (hasGitHubInfo) ? other.GitHubBranch : other.AzureDevOpsBranch; Commit = other.Commit; BuildNumber = other.AzureDevOpsBuildNumber; DateProduced = other.DateProduced; Channels = other.BuildChannels?.Select(bc => bc.Channel) .Where(c => c != null) .Select(c => new Channel(c)) .ToList(); Assets = other.Assets?.Select(a => new Asset(a)).ToList(); }
public async Task <IActionResult> Create([FromBody] BuildData build) { Data.Models.Build buildModel = build.ToDb(); buildModel.DateProduced = DateTimeOffset.UtcNow; buildModel.Dependencies = build.Dependencies != null ? await _context.Builds.Where(b => build.Dependencies.Contains(b.Id)).ToListAsync() : null; await _context.Builds.AddAsync(buildModel); await _context.SaveChangesAsync(); return(CreatedAtRoute(new { action = "GetBuild", id = buildModel.Id }, new Build(buildModel))); }
public override async Task <IActionResult> GetBuildGraph(int id) { Data.Models.Build build = await _context.Builds.Include(b => b.Incoherencies).FirstOrDefaultAsync(b => b.Id == id); if (build == null) { return(NotFound()); } var builds = await _context.GetBuildGraphAsync(build.Id); return(Ok(BuildGraph.Create(builds.Select(b => new Build(b))))); }
public async Task ProcessAsync(JToken argumentToken) { // This method is called asynchronously whenever a new build is inserted in BAR. // It's goal is to compute the incoherent dependencies that the build have and // persist the list of them in BAR. int buildId = argumentToken.Value <int>(); DependencyGraphBuildOptions graphBuildOptions = new DependencyGraphBuildOptions() { IncludeToolset = false, LookupBuilds = false, NodeDiff = NodeDiff.None }; try { Data.Models.Build build = await _context.Builds.FindAsync(buildId); DependencyGraph graph = await DependencyGraph.BuildRemoteDependencyGraphAsync( _remoteFactory, build.GitHubRepository ?? build.AzureDevOpsRepository, build.Commit, graphBuildOptions, _logger); var incoherencies = new List <Data.Models.BuildIncoherence>(); foreach (var incoherence in graph.IncoherentDependencies) { incoherencies.Add(new Data.Models.BuildIncoherence { Name = incoherence.Name, Version = incoherence.Version, Repository = incoherence.RepoUri, Commit = incoherence.Commit }); } _context.Entry(build).Reload(); build.Incoherencies = incoherencies; _context.Builds.Update(build); await _context.SaveChangesAsync(); } catch (Exception e) { _logger.LogWarning(e, $"Problems computing the dependency incoherencies for BAR build {buildId}"); } }
public async Task <IActionResult> GetCommit(int buildId) { Data.Models.Build build = await _context.Builds.Include(b => b.Incoherencies).FirstOrDefaultAsync(b => b.Id == buildId); if (build == null) { return(NotFound()); } IRemote remote = await Factory.GetRemoteAsync(build.AzureDevOpsRepository ?? build.GitHubRepository, null); Microsoft.DotNet.DarcLib.Commit commit = await remote.GetCommitAsync(build.AzureDevOpsRepository ?? build.GitHubRepository, build.Commit); return(Ok(new Models.Commit(commit.Author, commit.Sha, commit.Message))); }
public override async Task <IActionResult> GetBuild(int id) { Data.Models.Build build = await _context.Builds.Where(b => b.Id == id) .Include(b => b.BuildChannels) .ThenInclude(bc => bc.Channel) .Include(b => b.Assets) .FirstOrDefaultAsync(); if (build == null) { return(NotFound()); } return(Ok(new Build(build))); }
/// <summary> /// This method is called asynchronously whenever a new build is inserted in BAR. /// It's goal is to compute the incoherent dependencies that the build have and /// persist the list of them in BAR. /// </summary> /// <param name="buildId">Build id for which the incoherencies should be computed.</param> private async Task SetBuildIncoherencyInfoAsync(int buildId) { DependencyGraphBuildOptions graphBuildOptions = new DependencyGraphBuildOptions() { IncludeToolset = false, LookupBuilds = false, NodeDiff = NodeDiff.None }; try { using (IServiceScope scope = ServiceScopeFactory.CreateScope()) { BuildAssetRegistryContext context = scope.ServiceProvider.GetRequiredService <BuildAssetRegistryContext>(); Data.Models.Build build = await context.Builds.FindAsync(buildId); DependencyGraph graph = await DependencyGraph.BuildRemoteDependencyGraphAsync( RemoteFactory, build.GitHubRepository ?? build.AzureDevOpsRepository, build.Commit, graphBuildOptions, Logger); var incoherencies = new List <Data.Models.BuildIncoherence>(); foreach (var incoherence in graph.IncoherentDependencies) { build.Incoherencies.Add(new Data.Models.BuildIncoherence { Name = incoherence.Name, Version = incoherence.Version, Repository = incoherence.RepoUri, Commit = incoherence.Commit }); } context.Entry <Data.Models.Build>(build).Reload(); build.Incoherencies = incoherencies; context.Builds.Update(build); await context.SaveChangesAsync(); } } catch (Exception e) { Logger.LogWarning(e, $"Problems computing the dependency incoherencies for BAR build {buildId}"); } }
public Build([NotNull] Data.Models.Build other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } Id = other.Id; Repository = other.Repository; Commit = other.Commit; BuildNumber = other.BuildNumber; DateProduced = other.DateProduced; Channels = other.BuildChannels?.Select(bc => bc.Channel).Where(c => c != null).Select(c => new Channel(c)).ToList(); Assets = other.Assets?.Select(a => new Asset(a)).ToList(); Dependencies = other.Dependencies?.Select(b => new BuildRef { Id = b.Id }).ToList(); }
public virtual async Task <IActionResult> Create([FromBody] BuildData build) { Data.Models.Build buildModel = build.ToDb(); buildModel.DateProduced = DateTimeOffset.UtcNow; if (build.Dependencies?.Count > 0) { return(BadRequest("This api version doesn't support build dependencies.")); } await _context.Builds.AddAsync(buildModel); await _context.SaveChangesAsync(); return(CreatedAtRoute( new { action = "GetBuild", id = buildModel.Id }, new Models.Build(buildModel))); }
public async Task <IActionResult> Create([FromBody, Required] BuildData build) { Data.Models.Build buildModel = build.ToDb(); buildModel.DateProduced = DateTimeOffset.UtcNow; if (build.Dependencies != null) { // For each Dependency, update the time to Inclusion. // This measure is to be used for telemetry purposes, and has several known corner cases // where the measurement will not be correct: // 1. For any dependencies that were added before this column was added, the TimeToInclusionInMinutes // will be 0. // 2. For new release branches, until new builds of dependencies are added, this will recalculate // the TimeToInclusion, so it will seem inordinately large until new builds are added. This will // be particularly true for dependencies that are infrequently updated. foreach (var dep in build.Dependencies) { // Heuristic to discover if this dependency has been added to the same repository and branch // of the current build. If we find a match in the BuildDependencies table, it means // that this is not a new dependency, and we should use the TimeToInclusionInMinutes // of the previous time this dependency was added. var buildDependency = _context.BuildDependencies.Where(d => d.DependentBuildId == dep.BuildId && d.Build.GitHubRepository == buildModel.GitHubRepository && d.Build.GitHubBranch == buildModel.GitHubBranch && d.Build.AzureDevOpsRepository == buildModel.AzureDevOpsRepository && d.Build.AzureDevOpsBranch == buildModel.AzureDevOpsBranch ).FirstOrDefault(); if (buildDependency != null) { dep.TimeToInclusionInMinutes = buildDependency.TimeToInclusionInMinutes; } else { // If the dependent build is not currently in the BuildDependency table for this repo/branch (ie is a new dependency), // find the dependency in the Builds table and calculate the time to inclusion // We want to use the BuildChannel insert time if it exists. So we need to heuristically: // 1. Find the subscription between these two repositories on the current branch // 2. Find the entry in BuildChannels and get the insert time // In certain corner cases, we may pick the wrong subscription or BuildChannel Data.Models.Build depBuild = await _context.Builds.FindAsync(dep.BuildId); // If we don't find a subscription or a BuildChannel entry, use the dependency's // date produced. DateTimeOffset startTime = depBuild.DateProduced; Data.Models.Subscription subscription = _context.Subscriptions.Where(s => (s.SourceRepository == depBuild.GitHubRepository || s.SourceRepository == depBuild.AzureDevOpsRepository) && (s.TargetRepository == buildModel.GitHubRepository || s.TargetRepository == buildModel.AzureDevOpsRepository) && (s.TargetBranch == buildModel.GitHubBranch || s.TargetBranch == buildModel.AzureDevOpsBranch) ).LastOrDefault(); if (subscription != null) { Data.Models.BuildChannel buildChannel = _context.BuildChannels.Where(bc => bc.BuildId == depBuild.Id && bc.ChannelId == subscription.ChannelId ).LastOrDefault(); if (buildChannel != null) { startTime = buildChannel.DateTimeAdded; } } dep.TimeToInclusionInMinutes = (buildModel.DateProduced - startTime).TotalMinutes; } } await _context.BuildDependencies.AddRangeAsync( build.Dependencies.Select( b => new Data.Models.BuildDependency { Build = buildModel, DependentBuildId = b.BuildId, IsProduct = b.IsProduct, TimeToInclusionInMinutes = b.TimeToInclusionInMinutes, })); } await _context.Builds.AddAsync(buildModel); await _context.SaveChangesAsync(); // Compute the dependency incoherencies of the build. // Since this might be an expensive operation we do it asynchronously. Queue.Post( async() => { await SetBuildIncoherencyInfoAsync(buildModel.Id); }); return(CreatedAtRoute( new { action = "GetBuild", id = buildModel.Id }, new Models.Build(buildModel))); }