private async Task ProcessPipelineAsync(TestResultsScrapeContext context, PipelineConfig config, CancellationToken stoppingToken)
        {
            try
            {
                var pipelineContext = await context.CreatePipelineSyncContextAsync(config, stoppingToken);

                foreach (var branch in config.Branches)
                {
                    using (_logger.BeginScope("Branch: {SourceBranch}", branch))
                    {
                        _logger.LogInformation(new EventId(0, "ProcessingBranch"), "Processing builds in branch {BranchName}...", branch);
                        await ProcessBranchAsync(pipelineContext, config, branch, stoppingToken);

                        _logger.LogInformation(new EventId(0, "ProcessedBranch"), "Processed builds in branch {BranchName}.", branch);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug(new EventId(0, "CancellingPipelineProcessing"), "Cancelling processing of pipeline: {PipelineProject}/{PipelineName}.", config.Project, config.Name);
                throw;
            }
        }
        private async Task ProcessBranchAsync(PipelineScrapeContext context, PipelineConfig config, string branch, CancellationToken stoppingToken)
        {
            // Look up the most recent build (for now)
            _logger.LogDebug(new EventId(0, "FetchingBuilds"), "Fetching builds for {PipelineProject}/{PipelineName} in {BranchName}...", config.Project, config.Name, branch);
            var builds = await context.GetBuildsAsync(branch, stoppingToken);

            _logger.LogInformation(new EventId(0, "FetchedBuilds"), "Fetched {BuildCount} builds.", builds.Count);

            foreach (var build in builds)
            {
                using (_logger.BeginScope("Build {BuildId} #{BuildNumber}", build.Id, build.BuildNumber, build.SourceVersion))
                {
                    using (var scope = _scopeFactory.CreateScope())
                    {
                        var db = scope.ServiceProvider.GetRequiredService <TestResultsDbContext>();
                        // Load the Build from the new db context
                        var dbBuild = await db.Builds.FirstOrDefaultAsync(b => b.Id == build.Id);

                        if (dbBuild == null)
                        {
                            _logger.LogError(new EventId(0, "CouldNotFindBuild"), "Could not find build #{BuildNumber} (ID: {BuildDbId}) in the database!", build.BuildNumber, build.Id);
                            continue;
                        }

                        var buildContext = new BuildSyncContext(context, dbBuild, db);

                        // TODO: Retry of unsynced builds?
                        _logger.LogInformation(new EventId(0, "ProcessingBuild"), "Processing build #{BuildNumber}...", build.BuildNumber);
                        var sw = Stopwatch.StartNew();
                        await ProcessBuildAsync(buildContext, stoppingToken);

                        _logger.LogInformation(new EventId(0, "ProcessedBuild"), "Processed build #{BuildNumber} in {Elapsed}.", build.BuildNumber, sw.Elapsed);
                    }
                }
            }
        }