Пример #1
0
        private Task <FileInfo?> InternalUpdateApplicationImageTag(
            RawDeploymentManifest manifest,
            DeploymentManifestInfo deploymentManifestInfo,
            ApplicationImage applicationImage,
            string instance,
            string targetTag
            )
        {
            var yamlUtilities = new YamlUtilities();

            var    key             = new DeploymentManifestInstanceKey(applicationImage, instance);
            string currentImageTag = deploymentManifestInfo.ManifestTags.GetValueOrDefault(key) ?? "n/a";

            if (!deploymentManifestInfo.ApplicationImageToFileMapping.TryGetValue(key, out FileInfo? file))
            {
                // TODO: warn that we have an image tag update but no corresponding file
                // _log.LogWarning("Update to {Repository} cannot be applied since there isn't matching file.");
                throw new InvalidOperationException("Update cannot be applied since there isn't matching file.");
            }

            _log.LogTrace("Upgrading {Repository} to {NewTag} from {Tag}",
                          applicationImage.Repository,
                          targetTag,
                          currentImageTag
                          );

            return(yamlUtilities.UpdateValueInYamlFile(file, applicationImage.TagProperty.Path, targetTag)
                ? Task.FromResult((FileInfo?)file)
                : Task.FromResult((FileInfo?)null));
        }
Пример #2
0
        public async Task UpdateApplicationImageVersion(
            RawDeploymentManifest manifest,
            ApplicationImage applicationImage,
            string instance,
            string targetTag
            )
        {
            var manifestInfo = await _parser.BuildDeploymentManifestInfo(manifest);

            var    key             = new DeploymentManifestInstanceKey(applicationImage, instance);
            string currentImageTag = manifestInfo.ManifestTags.GetValueOrDefault(key) ?? "n/a";

            var result = await InternalUpdateApplicationImageTag(manifest, manifestInfo, applicationImage, instance, targetTag);

            if (result == null)
            {
                return;
            }

            // this is GIT requirement: we only work with relative paths in the git repository.
            _log.LogTrace("Adding {Path} to repository git staging", result);
//            var gitFilePath = Path.Combine(relativePath, file.Name);
            // var gitFilePath = Path.GetRelativePath(context.GitRepositoryRoot.FullName, file.FullName);
            // Commands.Stage(gitRepository, gitFilePath);
            var application = GetApplicationForApplicationImage(applicationImage);

            await _deploymentManifestRepositoryService.StageChanges(manifest.Repository, new[] { result });

            await _deploymentManifestRepositoryService.Commit(
                manifest.Repository,
                $"[{application}] Updated deployment for {applicationImage.ShortRepository}; {currentImageTag} to {targetTag}"
                );
        }
Пример #3
0
        public async Task RemovePreviewRelease(RawDeploymentManifest manifest, ApplicationImage applicationImage, string instance)
        {
            var manifestInfo = await _parser.BuildDeploymentManifestInfo(manifest);

            var key = new DeploymentManifestInstanceKey(applicationImage, instance);

            if (!manifestInfo.Instances.ContainsKey(key))
            {
                _log.LogError($"Cannot remove instance {key} because it doesn't exist");
                return;
            }

            var instanceInfo = manifestInfo.Instances[key];
            var files        = instanceInfo.GetInstanceDeploymentFiles().ToList();

            files.ForEach(f => f.Delete());

            var application = GetApplicationForApplicationImage(applicationImage);

            await _deploymentManifestRepositoryService.StageChanges(manifest.Repository, files);

            await _deploymentManifestRepositoryService.Commit(manifest.Repository, $"[{application}] Remove preview release '{instance}'.");
        }
Пример #4
0
        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);
        }