Exemple #1
0
        private async Task <bool> UpdateDeploymentManifests(
            Repository gitRepository,
            DeploymentUpdate deploymentUpdate,
            Dictionary <Image, string> imageToFilenameMap,
            string currentImageTag,
            string applicationSourcePath,
            YamlUtilities yamlUtilities,
            string relativePath)
        {
            if (!imageToFilenameMap.TryGetValue(deploymentUpdate.Image, out string 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.");
                return(false);
            }

            _log.LogInformation("Upgrading {Repository} to {NewTag} from {Tag}",
                                deploymentUpdate.Image.Repository,
                                deploymentUpdate.TargetTag,
                                currentImageTag
                                );

            var yaml     = new YamlStream();
            var filePath = Path.Combine(applicationSourcePath, file);

            yamlUtilities.ReadYamlStream(yaml, filePath);

            var image = deploymentUpdate.Image;

            var doCommit = false;

            foreach (var doc in yaml.Documents)
            {
                var tagInManifest = yamlUtilities.ExtractValueFromDoc(image.TagProperty.Path, doc);
                if (tagInManifest == null)
                {
                    continue;
                }

                if (tagInManifest == deploymentUpdate.TargetTag)
                {
                    _log.LogInformation("Tag for {Repository} matches new tag {NewTag}", image.Repository, deploymentUpdate.TargetTag);
                    continue;
                }

                _log.LogInformation("Setting current-tag for {Repository} to {Tag}", image.Repository,
                                    deploymentUpdate.TargetTag);
                yamlUtilities.SetValueInDoc(image.TagProperty.Path, doc, deploymentUpdate.TargetTag);

                doCommit = true;
            }

            if (!doCommit)
            {
                return(true);
            }

            yamlUtilities.WriteYamlStream(yaml, filePath);

            _log.LogInformation("Adding {Path} to repository staging", filePath);
            var gitFilePath = Path.Combine(relativePath, file);

            Commands.Stage(gitRepository, gitFilePath);

            gitRepository.Commit(
                $"[{deploymentUpdate.Application}] Updated deployment for {image.RepositoryName}; {deploymentUpdate.CurrentTag} to {deploymentUpdate.TargetTag}",
                new Signature("deploy-bot", "*****@*****.**", DateTimeOffset.Now),
                new Signature("deploy-bot", "*****@*****.**", DateTimeOffset.Now)
                );

            // add delay instruction due to the deployment update notification delivered too fast
            await Task.Delay(500);

            return(true);
        }
Exemple #2
0
        private async Task <bool> SynchronizeHelmApplicationSource(Repository gitRepository,
                                                                   ApplicationSourceTrackingContext context,
                                                                   HelmApplicationSource helmApplicationSource)
        {
            var relativePath          = helmApplicationSource.Path;
            var applicationSourcePath = Path.Combine(context.GitRepositoryPath, relativePath);

            var application   = context.Application;
            var yamlUtilities = new YamlUtilities();

            // build map of images -> yaml file that defines them and image -> current tag
            _log.LogInformation("Beginning to parse value files defined in application source ...");

            var imageToFilenameMap   = new Dictionary <Image, string>();
            var imageToTagInManifest = new Dictionary <Image, string>();

            foreach (var file in helmApplicationSource.ValuesFiles)
            {
                var yaml     = new YamlStream();
                var filePath = Path.Combine(applicationSourcePath, file);
                yamlUtilities.ReadYamlStream(yaml, filePath);

                foreach (var doc in yaml.Documents)
                {
                    foreach (var image in context.Application.Images)
                    {
                        var tagInManifest = yamlUtilities.ExtractValueFromDoc(image.TagProperty.Path, doc);

                        if (tagInManifest == null)
                        {
                            continue;
                        }

                        if (imageToFilenameMap.ContainsKey(image))
                        {
                            // TODO: handle situation where multiple files define the same image tag (ERROR and warn user)
                        }

                        imageToFilenameMap[image]   = file;
                        imageToTagInManifest[image] = tagInManifest;
                    }
                }
            }

            _log.LogInformation("Completing parsing value files defined in application source ...");

            // start updating files
            var manifestsChanged = false;
            DeploymentUpdate deploymentUpdate = null;

            while ((deploymentUpdate = await _deploymentService.GetNextPendingDeploymentUpdate(application)) != null)
            {
                _log.LogInformation("Executing pending deployment update ...");

                await _deploymentService.ChangeDeploymentUpdateStatus(
                    deploymentUpdate,
                    DeploymentUpdateStatus.UpdatingManifests
                    );

                manifestsChanged = await UpdateDeploymentManifests(gitRepository,
                                                                   deploymentUpdate,
                                                                   imageToFilenameMap,
                                                                   imageToTagInManifest.TryGetAndReturn(deploymentUpdate.Image) ?? "n/a",
                                                                   applicationSourcePath,
                                                                   yamlUtilities,
                                                                   relativePath);

                if (manifestsChanged)
                {
                    imageToTagInManifest[deploymentUpdate.Image] = deploymentUpdate.TargetTag;
                }

                await _deploymentService.FinishDeploymentUpdate(
                    deploymentUpdate,
                    manifestsChanged?DeploymentUpdateStatus.Complete : DeploymentUpdateStatus.Failed
                    );
            }

            if (!manifestsChanged)
            {
                // we don't have a deployment, ensure application manifest is up to date with latest image tags
                foreach (var keyValuePair in imageToTagInManifest)
                {
                    _applicationService.SetCurrentImageTag(application, keyValuePair.Key, keyValuePair.Value);
                }
            }

            return(manifestsChanged);
        }