<commit_before>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using DeploymentJobs.DataAccess;
using DeploymentSettings.Models;
using DeployServiceWebApi.Exceptions;
using DeployServiceWebApi.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog.Events;

namespace DeployServiceWebApi.Services
{
	public interface IDeploymentService
	{
		bool TryRunJobIfNotInProgress(
			string project, 
			string group, 
			SettingsRepo repo, 
			IEnumerable<string> deployables,
			out DeploymentJob job);
	}

	public class DeploymentService : IDeploymentService
	{
		private readonly ILogger<DeploymentService> _logger;
		private readonly IDeploymentJobDataAccess _jobsDataAccess;
		private readonly string _svnCeckoutScriptPath;
		private const string SvnCheckoutFlags = "--non-interactive --trust-server-cert --no-auth-cache";

		public DeploymentService(
			IOptions<ConfigurationOptions> optionsAccessor,
			ILogger<DeploymentService> logger,
			IDeploymentJobDataAccess jobsDataAccess)
		{
			_logger = logger;
			_jobsDataAccess = jobsDataAccess;
			_svnCeckoutScriptPath = optionsAccessor.Value.RepoUpdateScriptPath;
		}

		public bool TryRunJobIfNotInProgress(
			string project, 
			string group,
			SettingsRepo repo, 
			IEnumerable<string> deployables,
			out DeploymentJob job)
		{
			job = _jobsDataAccess.GetOrCreate(project, group);
			if (job.Status == DeploymentJobStatus.IN_PROGRESS)
			{
				return false;
			}

			var jobId = job.Id;
			Task.Run(() => RunJob(jobId, repo, deployables));
			
			return true;
		}

		private void RunJob(
			string jobId, 
			SettingsRepo repo,
			IEnumerable<string> deployables)
		{
			try
			{
				// 1. make sure the settings repository is updated
				_jobsDataAccess.SetInProgress(jobId, "Updating settings repository.");

				UpdateRepository(repo.RemoteUrl, repo.LocalPath);

				// 2. run deployables located in the settings repository
				foreach (var deployable in deployables)
				{
					var path = Path.Combine(repo.LocalPath, deployable);
					if (!File.Exists(path)) continue;

					_jobsDataAccess.SetInProgress(jobId, $"Running deployable {Path.GetFileName(path)}");

					ExecuteScript(path);
				}

				_jobsDataAccess.SetSuccess(jobId);
			}
			catch (Exception ex)
			{
				var errorMessage = $"Error running deployables: {ex.Message}";

				_jobsDataAccess.SetFail(jobId, errorMessage);
				_logger.LogError(errorMessage, ex);
			}
		}

		private void UpdateRepository(string repoUrl, string localPath)
		{
			var args = $"\"{repoUrl}\" \"{localPath}\" {SvnCheckoutFlags}";
			ExecuteScript(_svnCeckoutScriptPath, args);
		}

		private void ExecuteScript(string scriptPath, string args = "")
		{
			var proc = new Process
			{
				StartInfo =
				{
					FileName = "cmd.exe \"scriptPath\"",
					Arguments = args,
					RedirectStandardOutput = true,
					RedirectStandardError = true
				}
			};
			_logger.LogInformation($"Starting script {Path.GetFileName(scriptPath)}");
			
			proc.Start();<commit_msg>Used full path to bat scripts in process start info.<commit_after>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using DeploymentJobs.DataAccess;
using DeploymentSettings.Models;
using DeployServiceWebApi.Exceptions;
using DeployServiceWebApi.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog.Events;

namespace DeployServiceWebApi.Services
{
	public interface IDeploymentService
	{
		bool TryRunJobIfNotInProgress(
			string project, 
			string group, 
			SettingsRepo repo, 
			IEnumerable<string> deployables,
			out DeploymentJob job);
	}

	public class DeploymentService : IDeploymentService
	{
		private readonly ILogger<DeploymentService> _logger;
		private readonly IDeploymentJobDataAccess _jobsDataAccess;
		private readonly string _svnCeckoutScriptPath;
		private const string SvnCheckoutFlags = "--non-interactive --trust-server-cert --no-auth-cache";

		public DeploymentService(
			IOptions<ConfigurationOptions> optionsAccessor,
			ILogger<DeploymentService> logger,
			IDeploymentJobDataAccess jobsDataAccess)
		{
			_logger = logger;
			_jobsDataAccess = jobsDataAccess;
			_svnCeckoutScriptPath = optionsAccessor.Value.RepoUpdateScriptPath;
		}

		public bool TryRunJobIfNotInProgress(
			string project, 
			string group,
			SettingsRepo repo, 
			IEnumerable<string> deployables,
			out DeploymentJob job)
		{
			job = _jobsDataAccess.GetOrCreate(project, group);
			if (job.Status == DeploymentJobStatus.IN_PROGRESS)
			{
				return false;
			}

			var jobId = job.Id;
			Task.Run(() => RunJob(jobId, repo, deployables));
			
			return true;
		}

		private void RunJob(
			string jobId, 
			SettingsRepo repo,
			IEnumerable<string> deployables)
		{
			try
			{
				_jobsDataAccess.SetInProgress(jobId, "Updating settings repository.");

				// 1. make sure the settings repository is updated
				UpdateRepository(repo.RemoteUrl, repo.LocalPath);

				// 2. run deployables located in the settings repository
				foreach (var deployable in deployables)
				{
					var path = Path.Combine(repo.LocalPath, deployable);
					_jobsDataAccess.SetInProgress(jobId, $"Running deployable {Path.GetFileName(path)}");
					
					if (!File.Exists(path)) 
					{
						throw new DeploymentException($"File cannot be found: {path}");
					};

					ExecuteScript(path);
				}

				_jobsDataAccess.SetSuccess(jobId);
			}
			catch (Exception ex)
			{
				var errorMessage = $"Error running deployables: {ex.Message}";

				_jobsDataAccess.SetFail(jobId, errorMessage);
				_logger.LogError(errorMessage, ex);
			}
		}

		private void UpdateRepository(string repoUrl, string localPath)
		{
			var args = $"\"{repoUrl}\" \"{localPath}\" {SvnCheckoutFlags}";
			ExecuteScript(_svnCeckoutScriptPath, args);
		}

		private void ExecuteScript(string scriptPath, string args = "")
		{
			var proc = new Process
			{
				StartInfo =
				{
					FileName = (new FileInfo(scriptPath)).FullName,
					Arguments = args,
					RedirectStandardOutput = true,
					RedirectStandardError = true
				}
			};
			_logger.LogInformation($"Starting script {Path.GetFileName(scriptPath)}");
			
			proc.Start();
{'fraction_non_alphanumeric': 0.09308975377283558, 'fraction_numerical': 0.0006354249404289118, 'mean_word_length': 4.024740622505986, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2275304', 'n_tokens_mistral': 2300, 'n_tokens_neox': 1881, 'n_words': 435}