private async Task SyncApplicationMetadataFromManifest <TManifest>(TManifest manifest, Application application, Dictionary <ApplicationImageInstanceKey, string> updatedImageTags) where TManifest : DeploymentManifest { _log.LogTrace("Parsing deployment manifest prior to updating application info ..."); var deploymentManifestInfo = await _deploymentManifestSourceManagementFacade.GetDeploymentManifestInfo(manifest); foreach (var(deploymentManifestInstanceKey, value) in deploymentManifestInfo.Instances) { var applicationImage = deploymentManifestInstanceKey.ApplicationImage; var instanceId = deploymentManifestInstanceKey.InstanceName; var key = new ApplicationImageInstanceKey(application, applicationImage, instanceId); if (!updatedImageTags.TryGetValue(key, out var currentTag)) { // we didn't update the tag in the deployment manifest, use the original tag loaded from the manifest currentTag = value.Tag; } await _applicationImageInstanceService.AddOrUpdateInstance( application, applicationImage, value.Name, value.Type, value.Source, currentTag ); } }
private async Task <bool> InternalExecute <TManifest>(TManifest manifest, Application application) where TManifest : DeploymentManifest { // prefetch and structure some metadata required throughout var imageMap = application.Images.ToDictionary( x => $"{x.Repository}-{x.TagProperty.Path}" ); // store var manifestsChanged = false; // 1. check for any orphan preview releases var appImagesWithPreviewReleases = imageMap.Values .Where(x => x.SourceCode.IsAvailable && x.DeploymentSettings.PreviewReleases.Enabled) .ToArray(); if (appImagesWithPreviewReleases.Any()) { _log.LogInformation("Checking for orphan preview releases ..."); foreach (var item in appImagesWithPreviewReleases) { if (!item.SourceCode.IsAvailable) { continue; } var openPullRequests = (await _githubPullRequestService.GetOpenPRs(item)) .ToArray(); _log.LogTrace("Found {prCount} open pull requests", openPullRequests.Length); var appImageInstances = (await _applicationImageInstanceService.GetInstancesFor(application, item)) .ToArray(); _log.LogTrace("Found {instanceCount} active instances", appImageInstances.Length); foreach (var applicationImageInstance in appImageInstances) { if (applicationImageInstance.Source.Type != ApplicationImageInstanceSourceType.PullRequest) { continue; } if (openPullRequests.Any(x => x.PrNumber.Equals(applicationImageInstance.Source.PullRequestId))) { continue; } _log.LogTrace("No pull request found for instance {instanceName}, removing ...", applicationImageInstance.Name); await _deploymentManifestSourceManagementFacade.RemovePreviewRelease(manifest, item, applicationImageInstance.Name); await _applicationImageInstanceService.RemoveInstance(application, item, applicationImageInstance); manifestsChanged = true; } } } _log.LogTrace("Checking for pending deployments to apply."); // start updating files var updatedImageTags = new Dictionary <ApplicationImageInstanceKey, string>(); Deployment?nextPendingDeployment = null; while ((nextPendingDeployment = await _deploymentQueueService.GetNextPendingDeploymentUpdate(application)) != null) { await _deploymentService.ChangeDeploymentUpdateStatus( nextPendingDeployment.Id, DeploymentStatus.Starting ); _log.LogTrace("Executing pending deployment update ..."); await _deploymentService.ChangeDeploymentUpdateStatus( nextPendingDeployment.Id, DeploymentStatus.UpdatingManifests ); var deploymentManifestInfo = await _deploymentManifestSourceManagementFacade.GetDeploymentManifestInfo(manifest); var image = imageMap[$"{nextPendingDeployment.ImageRepository}-{nextPendingDeployment.UpdatePath}"]; var dmiKey = new DeploymentManifestInstanceKey(image, nextPendingDeployment.InstanceId); switch (nextPendingDeployment.Type) { case DeploymentType.ImageUpdate: await _deploymentManifestSourceManagementFacade.UpdateApplicationImageVersion( manifest, image, nextPendingDeployment.InstanceId, nextPendingDeployment.TargetTag ); break; case DeploymentType.PreviewRelease: if (!deploymentManifestInfo.Instances.ContainsKey(dmiKey)) { await _deploymentManifestSourceManagementFacade.CreatePreviewRelease( manifest, image, nextPendingDeployment.InstanceId, nextPendingDeployment.TargetTag ); } else { await _deploymentManifestSourceManagementFacade.UpdateApplicationImageVersion( manifest, image, nextPendingDeployment.InstanceId, nextPendingDeployment.TargetTag ); } break; default: throw new ArgumentOutOfRangeException(); } var key = new ApplicationImageInstanceKey(application, image, nextPendingDeployment.InstanceId); updatedImageTags[key] = nextPendingDeployment.TargetTag; manifestsChanged = true; // TODO: rework this so that failures to push get indicated await _deploymentService.FinishDeploymentUpdate( nextPendingDeployment.Id, manifestsChanged?DeploymentStatus.Complete : DeploymentStatus.Failed ); } await SyncApplicationMetadataFromManifest(manifest, application, updatedImageTags); _log.LogTrace("Deployment manifest repository syncing complete ..."); return(manifestsChanged); }