/// <summary>
        /// Builds the project and deploys it to Google Kubernetes Engine.
        /// </summary>
        /// <param name="project">The project to build and deploy.</param>
        /// <param name="options">Options for deploying and building.</param>
        public async Task DeployProjectToGkeAsync(IParsedProject project, Options options)
        {
            try
            {
                await GcpOutputWindow.ClearAsync();

                await GcpOutputWindow.ActivateAsync();

                await GcpOutputWindow.OutputLineAsync(string.Format(Resources.GkePublishDeployingToGkeMessage, project.Name));

                TimeSpan deploymentDuration;
                Result   result;
                using (await StatusbarService.FreezeAsync())
                    using (await StatusbarService.ShowDeployAnimationAsync())
                        using (IDisposableProgress progress =
                                   await StatusbarService.ShowProgressBarAsync(Resources.GkePublishDeploymentStatusMessage))
                            using (await ShellUtils.SetShellUIBusyAsync())
                            {
                                DateTime deploymentStartTime = DateTime.Now;

                                string imageTag = await BuildImageAsync(project, options, progress);

                                if (imageTag != null)
                                {
                                    result = await PublishImageToGkeAsync(imageTag, options, progress);
                                }
                                else
                                {
                                    result = Result.FailedResult;
                                }

                                deploymentDuration = DateTime.Now - deploymentStartTime;
                            }

                OutputResultData(project, options, result);

                if (options.OpenWebsite && result.ServiceExposed && result.ServicePublicIpAddress != null)
                {
                    BrowserService.OpenBrowser($"http://{result.ServicePublicIpAddress}");
                }

                if (result.Failed)
                {
                    await StatusbarService.SetTextAsync(Resources.PublishFailureStatusMessage);

                    EventsReporterWrapper.ReportEvent(GkeDeployedEvent.Create(CommandStatus.Failure));
                }
                else
                {
                    await StatusbarService.SetTextAsync(Resources.PublishSuccessStatusMessage);

                    EventsReporterWrapper.ReportEvent(
                        GkeDeployedEvent.Create(CommandStatus.Success, deploymentDuration));
                }
            }
            catch (Exception)
            {
                await GcpOutputWindow.OutputLineAsync(
                    string.Format(Resources.GkePublishDeploymentFailureMessage, project.Name));

                await StatusbarService.SetTextAsync(Resources.PublishFailureStatusMessage);

                EventsReporterWrapper.ReportEvent(GkeDeployedEvent.Create(CommandStatus.Failure));
            }
        }
        /// <summary>
        /// Start the publish operation.
        /// </summary>
        public override async void Publish()
        {
            if (!ValidateInput())
            {
                Debug.WriteLine("Invalid input cancelled the operation.");
                return;
            }

            var project = _publishDialog.Project;

            try
            {
                ShellUtils.SaveAllFiles();

                var verifyGCloudTask = GCloudWrapperUtils.VerifyGCloudDependencies("kubectl");
                _publishDialog.TrackTask(verifyGCloudTask);
                if (!await verifyGCloudTask)
                {
                    Debug.WriteLine("Aborting deployment, no kubectl was found.");
                    return;
                }

                var gcloudContext = new GCloudContext
                {
                    CredentialsPath = CredentialsStore.Default.CurrentAccountPath,
                    ProjectId       = CredentialsStore.Default.CurrentProjectId,
                    AppName         = GoogleCloudExtensionPackage.ApplicationName,
                    AppVersion      = GoogleCloudExtensionPackage.ApplicationVersion,
                };

                var kubectlContextTask = GCloudWrapper.GetKubectlContextForClusterAsync(
                    cluster: SelectedCluster.Name,
                    zone: SelectedCluster.Zone,
                    context: gcloudContext);
                _publishDialog.TrackTask(kubectlContextTask);

                using (var kubectlContext = await kubectlContextTask)
                {
                    var deploymentExistsTask = KubectlWrapper.DeploymentExistsAsync(DeploymentName, kubectlContext);
                    _publishDialog.TrackTask(deploymentExistsTask);
                    if (await deploymentExistsTask)
                    {
                        if (!UserPromptUtils.ActionPrompt(
                                String.Format(Resources.GkePublishDeploymentAlreadyExistsMessage, DeploymentName),
                                Resources.GkePublishDeploymentAlreadyExistsTitle,
                                actionCaption: Resources.UiUpdateButtonCaption))
                        {
                            return;
                        }
                    }

                    var options = new GkeDeployment.DeploymentOptions
                    {
                        Cluster                     = SelectedCluster.Name,
                        Zone                        = SelectedCluster.Zone,
                        DeploymentName              = DeploymentName,
                        DeploymentVersion           = DeploymentVersion,
                        ExposeService               = ExposeService,
                        ExposePublicService         = ExposePublicService,
                        GCloudContext               = gcloudContext,
                        KubectlContext              = kubectlContext,
                        Replicas                    = int.Parse(Replicas),
                        WaitingForServiceIpCallback = () => GcpOutputWindow.OutputLine(Resources.GkePublishWaitingForServiceIpMessage)
                    };

                    GcpOutputWindow.Activate();
                    GcpOutputWindow.Clear();
                    GcpOutputWindow.OutputLine(String.Format(Resources.GkePublishDeployingToGkeMessage, project.Name));

                    _publishDialog.FinishFlow();

                    TimeSpan            deploymentDuration;
                    GkeDeploymentResult result;
                    using (StatusbarHelper.Freeze())
                        using (StatusbarHelper.ShowDeployAnimation())
                            using (var progress = StatusbarHelper.ShowProgressBar(Resources.GkePublishDeploymentStatusMessage))
                                using (ShellUtils.SetShellUIBusy())
                                {
                                    var deploymentStartTime = DateTime.Now;
                                    result = await GkeDeployment.PublishProjectAsync(
                                        project,
                                        options,
                                        progress,
                                        VsVersionUtils.ToolsPathProvider,
                                        GcpOutputWindow.OutputLine);

                                    deploymentDuration = DateTime.Now - deploymentStartTime;
                                }

                    if (result != null)
                    {
                        OutputResultData(result, options);

                        StatusbarHelper.SetText(Resources.PublishSuccessStatusMessage);

                        if (OpenWebsite && result.ServiceExposed && result.PublicServiceIpAddress != null)
                        {
                            Process.Start($"http://{result.PublicServiceIpAddress}");
                        }

                        EventsReporterWrapper.ReportEvent(GkeDeployedEvent.Create(CommandStatus.Success, deploymentDuration));
                    }
                    else
                    {
                        GcpOutputWindow.OutputLine(String.Format(Resources.GkePublishDeploymentFailureMessage, project.Name));
                        StatusbarHelper.SetText(Resources.PublishFailureStatusMessage);

                        EventsReporterWrapper.ReportEvent(GkeDeployedEvent.Create(CommandStatus.Failure));
                    }
                }
            }
            catch (Exception ex) when(!ErrorHandlerUtils.IsCriticalException(ex))
            {
                GcpOutputWindow.OutputLine(String.Format(Resources.GkePublishDeploymentFailureMessage, project.Name));
                StatusbarHelper.SetText(Resources.PublishFailureStatusMessage);
                _publishDialog.FinishFlow();

                EventsReporterWrapper.ReportEvent(GkeDeployedEvent.Create(CommandStatus.Failure));
            }
        }