public async Task <JobResult> Execute() { if (!File.Exists(AntaresDeploymentExecutablePath)) { var ex = new FileNotFoundException("Cannot find file", Path.GetFileName(AntaresDeploymentExecutablePath)); _logger.WriteError(_parameters, "Cannot find file", ex); throw ex; } var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = AntaresDeploymentExecutablePath; processStartInfo.Arguments = $"SetupPrivateStampWithGeo {_parameters.CloudName} /SubscriptionId:b27cf603-5c35-4451-a33a-abba1a08c9c2 /VirtualDedicated:true /bvtCapableStamp:true /DefaultLocation:\"Central US\""; processStartInfo.UseShellExecute = false; processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; processStartInfo.RedirectStandardError = true; processStartInfo.RedirectStandardOutput = true; _logger.WriteInfo(_parameters, $"Start {processStartInfo.FileName} {processStartInfo.Arguments}"); using (var createProcess = Process.Start(processStartInfo)) { createProcess.BeginErrorReadLine(); createProcess.BeginOutputReadLine(); createProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceived); createProcess.ErrorDataReceived += new DataReceivedEventHandler(ErrorReceived); createProcess.WaitForExit(); } var definitionsPath = $@"\\AntaresDeployment\PublicLockBox\{_parameters.CloudName}\developer.definitions"; var cloudStampyFirewallRules = @" <redefine name=""SqlFirewallAddressRangesList"" value=""131.107.0.0/16;167.220.0.0/16;65.55.188.0/24;104.44.112.0/24;157.58.30.0/24"" /><redefine name=""FirewallLockdownWhitelistedSources"" value=""131.107.0.0/16;167.220.0.0/16;65.55.188.0/24;104.44.112.0/24;157.58.30.0/24"" /> "; if (!TryModifyDefinitions(definitionsPath, cloudStampyFirewallRules)) { _statusMessageBuilder.AppendLine("Failed to add cloud stampy firewall rules to developer.definitions file."); _result.JobStatus = Status.Failed; } _result.Message = _statusMessageBuilder.ToString(); _result.JobStatus = JobStatus = _result.JobStatus == Status.None ? Status.Passed : _result.JobStatus; await Task.WhenAll(_azureLogsWriterUnfinishedJobs); return(_result); }
public async Task <JobResult> Execute() { JobResult jobResult; if (!Directory.Exists(_args.BuildPath)) { _logger.WriteError(_args, $"Failed to access fileshare: {_args.BuildPath}"); jobResult = new JobResult { JobStatus = Status.Failed, Message = $"Failed to access fileshare: {_args.BuildPath}" }; return(jobResult); } if (!TryCreateTestConfig($@"\\antaresdeployment\PublicLockbox\{_args.CloudName}geo")) { jobResult = new JobResult(); jobResult.JobStatus = Status.Failed; jobResult.Message = $"Failed to create TestCommon config file"; return(jobResult); } if (_args.TestCategories == null || _args.TestCategories.Count == 0) { jobResult = new JobResult(); jobResult.JobStatus = Status.Failed; jobResult.Message = $"Test names were not specified"; return(jobResult); } var testClient = TestClientFactory.GetTestClient(_logger, _args); _logger.WriteInfo(_args, $"Execute {_args.TestCategories[0].First()} tests"); var jResult = await JobStatusHelper.StartPeriodicStatusUpdates(this, (IJob)testClient, testClient.ExecuteTestAsync(_args.TestCategories[0].First())); return(jResult); }
public async Task <JobResult> Execute() { if (!AvailableDeploymentTemplates.Any(d => d.Equals(_parameters.DeploymentTemplate, StringComparison.CurrentCultureIgnoreCase))) { throw new ArgumentException("Deployment Template does not exist"); } if (!File.Exists(DeployConsolePath)) { throw new FileNotFoundException($"Cannot find {DeployConsolePath}"); } _logger.WriteInfo(_parameters, "Starting deployment..."); var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = DeployConsolePath; processStartInfo.Arguments = $"/LockBox={_parameters.CloudName} /Template={_parameters.DeploymentTemplate} /BuildPath={_parameters.BuildPath + @"\Hosting"} /TempDir={_deploymentArtificatsDirectory} /AutoRetry=true /LogFile={_localFilePath}"; processStartInfo.UseShellExecute = false; processStartInfo.WindowStyle = ProcessWindowStyle.Minimized; processStartInfo.RedirectStandardError = true; processStartInfo.RedirectStandardOutput = true; _logger.WriteInfo(_parameters, $"Start {processStartInfo.FileName} {processStartInfo.Arguments}"); using (var deployProcess = Process.Start(processStartInfo)) { deployProcess.BeginErrorReadLine(); deployProcess.BeginOutputReadLine(); deployProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceived); deployProcess.ErrorDataReceived += new DataReceivedEventHandler(ErrorReceived); deployProcess.WaitForExit(); } JobStatus = _result.JobStatus; _logger.WriteInfo(_parameters, "Finished deployment..."); _result.Message = _statusMessageBuilder.ToString(); while (_deploymentContent.Any()) { await CreateLogIfNotExistAppendAsync(); await Task.Delay(TimeSpan.FromSeconds(5)); } return(_result); }
public async Task <JobResult> Execute() { var job = (IJob)_buildClient; var jResult = await job.Execute(); object buildPath = null; if (jResult.ResultDetails.TryGetValue("Build Share", out buildPath)) { _logger.WriteInfo(_args, $"Finished executing build at {(string)buildPath}"); } else { _logger.WriteError(_args, "Failed to get build path"); } return(jResult); }
private async Task CreateIfNotExistAppendAsync(string path, string content) { try { var storageAccount = CloudStorageAccount.Parse(_configuration.StorageAccountConnectionString); var fileShareClient = storageAccount.CreateCloudFileClient(); var fileShare = fileShareClient.ListShares("stampy-job-results").FirstOrDefault(); var root = fileShare.GetRootDirectoryReference(); var requestDirectory = root.GetDirectoryReference(_parameters.RequestId); var operationContext = new OperationContext(); if (await requestDirectory.CreateIfNotExistsAsync(null, operationContext)) { _kustoLogger.WriteInfo(_parameters, string.Format("Created new file share to host logs at {0}. HttpResult:{1}", requestDirectory.Uri, operationContext.LastResult.HttpStatusCode)); } var logFileName = Path.GetFileName(path) ?? path; var fileReference = requestDirectory.GetFileReference(logFileName); var buffer = Encoding.UTF8.GetBytes(content); if (!await fileReference.ExistsAsync()) { await fileReference.CreateAsync(0, null, null, operationContext); _kustoLogger.WriteInfo(_parameters, $"Create {logFileName} file in azure. Location: {fileReference.Uri} HttpResult: {operationContext.LastResult.HttpStatusCode}"); } await fileReference.ResizeAsync(fileReference.Properties.Length + buffer.Length, null, null, operationContext); if (operationContext.LastResult.HttpStatusCode != 200) { _kustoLogger.WriteInfo(_parameters, $"Resize the azure file {fileReference.Uri} so to add new content. HttpResult: {operationContext.LastResult.HttpStatusCode}"); } using (var fileStream = await fileReference.OpenWriteAsync(null, null, null, operationContext)) { fileStream.Seek(buffer.Length * -1, SeekOrigin.End); await fileStream.WriteAsync(buffer, 0, buffer.Length); } SharedAccessFilePolicy sharedPolicy = new SharedAccessFilePolicy() { SharedAccessExpiryTime = DateTime.UtcNow.AddMonths(1), Permissions = SharedAccessFilePermissions.Read }; if (!LogUrls.ContainsKey(path)) { var permissions = await fileShare.GetPermissionsAsync(null, null, null); permissions.SharedAccessPolicies.Clear(); permissions.SharedAccessPolicies.Add("read", sharedPolicy); await fileShare.SetPermissionsAsync(permissions, null, null, null); var azureFilesUri = new Uri(fileReference.StorageUri.PrimaryUri.ToString() + fileReference.GetSharedAccessSignature(null, "read")).ToString(); LogUrls.Add(path, azureFilesUri); } } catch (Exception ex) { _kustoLogger.WriteError(_parameters, $"Failed to write deployment log to azure file", ex); throw; } }
public async Task <JobResult> ExecuteBuild(string dpkPath = null) { var jobResult = new JobResult(); if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("AntaresMainRepoLocation"))) { throw new Exception("Failed to find AAPT/Antares/Websites folder in local filesystem"); } var cleanAction = new ProcessAction() { WorkingDirectory = Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), ProgramPath = @"C:\Program Files\Git\cmd\git.exe", Arguments = "clean -fdx" }; var syncBranchScript = Path.Combine(Directory.GetParent(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName).FullName, "LocalSyncBranch.cmd"); var syncBranchAction = new ProcessAction() { WorkingDirectory = Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), ProgramPath = syncBranchScript, Arguments = $"{_cloudStampyArgs.GitBranchName}" }; var buildAction = new ProcessAction() { WorkingDirectory = Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), ProgramPath = Path.Combine(Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), "build-corext.cmd") }; var buildDirectoryName = $"{_cloudStampyArgs.GitBranchName.Replace(@"/", "-")}-{DateTime.UtcNow.ToString("yyyyMMddTHHmmss")}"; var copyBuildAction = new ProcessAction() { WorkingDirectory = Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), ProgramPath = @"C:\Windows\System32\Robocopy.exe", Arguments = $"out {Path.Combine(Environment.GetEnvironmentVariable("BuildVolume"), $"{buildDirectoryName}")} /MIR" }; _logger.WriteInfo(_cloudStampyArgs, "Clean the working tree by recursively removing files that are not under version control, starting from the current directory."); int cleanActionExitCode = await ProcessInvoker.Start(cleanAction, (output, isFailures) => { JobStatus = Status.InProgress; _buildLogsWriterUnfinishedJobs.Add(_buildLogsWritter.CreateLogIfNotExistAppendAsync(MACHINE_LOG, output)); _buildLogsWritter.LogUrls.TryGetValue(MACHINE_LOG, out _reportUri); }); if (cleanActionExitCode != 0) { JobStatus = Status.Failed; throw new Exception($"Git clean failed"); } _logger.WriteInfo(_cloudStampyArgs, $"Fetch the latest changes from {_cloudStampyArgs.GitBranchName} to the local file system"); int syncBranchExitCode = await ProcessInvoker.Start(syncBranchAction, (output, isFailure) => { JobStatus = Status.InProgress; _buildLogsWriterUnfinishedJobs.Add(_buildLogsWritter.CreateLogIfNotExistAppendAsync(MACHINE_LOG, output)); _buildLogsWritter.LogUrls.TryGetValue(MACHINE_LOG, out _reportUri); }); if (syncBranchExitCode != 0) { JobStatus = Status.Failed; throw new Exception("Fetch latest changes failed"); } var buildTask = ProcessInvoker.Start(buildAction, (output, ignore) => { JobStatus = Status.InProgress; _buildLogsWriterUnfinishedJobs.Add(_buildLogsWritter.CreateLogIfNotExistAppendAsync(BUILD_LOG, output)); _buildLogsWritter.LogUrls.TryGetValue(BUILD_LOG, out _reportUri); }); var copyOverMsBuildLogsTask = Task.Run(async() => { long offset = 0; long byteCount = 0; while (!buildTask.IsCompleted) { var msBuildLogFile = Path.Combine(Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), MSBUILD_LOG); if (File.Exists(msBuildLogFile)) { string content; using (FileStream msBuildFileStream = new FileStream(msBuildLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { //I noticed in the middle of build, the msbuild log rewrites from the top losing all previous data from the first build. //It could be build -x64 rewritting the log file that build -x32 commited, hence why its size is 0 bytes again if (byteCount > msBuildFileStream.Length) { //TEMPORARY reset offset to zero to read the new content written out by build -x64 offset = 0; } byteCount = msBuildFileStream.Length; msBuildFileStream.Seek(offset, SeekOrigin.Begin); var reader = new StreamReader(msBuildFileStream); content = await reader.ReadToEndAsync(); } offset += Encoding.UTF8.GetByteCount(content); _buildLogsWriterUnfinishedJobs.Add(_buildLogsWritter.CreateLogIfNotExistAppendAsync(BUILD_LOG, content)); } await Task.Delay(5000); } }); _logger.WriteInfo(_cloudStampyArgs, "Start build"); await Task.WhenAll(new Task[] { buildTask, copyOverMsBuildLogsTask }); if (buildTask.Result != 0) { JobStatus = Status.Failed; throw new Exception("Build failed"); } else { _logger.WriteInfo(_cloudStampyArgs, "Ran build successfully"); } string msBuildErrorFile = Path.Combine(Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), "msbuild.err"); if (File.Exists(msBuildErrorFile)) { var buildErrors = new List <string>(); using (var reader = new StreamReader(File.OpenRead(msBuildErrorFile))) { while (!reader.EndOfStream) { buildErrors.Add(await reader.ReadLineAsync()); } } jobResult.JobStatus = Status.Failed; jobResult.ResultDetails["BuildErrors"] = string.Join(@"\r\n", buildErrors); return(jobResult); } _logger.WriteInfo(_cloudStampyArgs, $"Copy build to {buildDirectoryName}"); var buildOutputDirectory = Path.Combine(Environment.GetEnvironmentVariable("AntaresMainRepoLocation"), "out"); if (!Directory.Exists(buildOutputDirectory)) { throw new DirectoryNotFoundException($"Cant find directory {buildOutputDirectory}"); } int copyBuildActionExitCode = await ProcessInvoker.Start(copyBuildAction, (output, isFailure) => { JobStatus = Status.InProgress; _buildLogsWriterUnfinishedJobs.Add(_buildLogsWritter.CreateLogIfNotExistAppendAsync(MACHINE_LOG, output)); _buildLogsWritter.LogUrls.TryGetValue(MACHINE_LOG, out _reportUri); }); if (copyBuildActionExitCode > 1)//Robocopy error codes 0×01 = 1 = One or more files were copied successfully (that is, new files have arrived). { throw new Exception("Build could not be copied"); } if (!Directory.Exists($@"\\{Environment.GetEnvironmentVariable("COMPUTERNAME")}\Builds")) { await ProcessInvoker.Start(@"C:\Windows\System32\net.exe", $@"share Builds={Environment.GetEnvironmentVariable("BuildVolume")}", null, (output, isFailed) => { JobStatus = Status.InProgress; _buildLogsWriterUnfinishedJobs.Add(_buildLogsWritter.CreateLogIfNotExistAppendAsync(MACHINE_LOG, output)); }); } _buildLogsWritter.LogUrls.TryGetValue(BUILD_LOG, out _reportUri); jobResult.JobStatus = Status.Passed; jobResult.ResultDetails["Build Share"] = $@"\\{Environment.GetEnvironmentVariable("COMPUTERNAME")}\Builds\{buildDirectoryName}\debug-amd64"; return(jobResult); }
public async Task <JobResult> ExecuteBuild(string dpkPath) { var result = new JobResult(); dpkPath = dpkPath ?? _args.DpkPath; var labMachineClient = JobClient.Link(@"http://stampy.lab.redant.selfhost.corp.microsoft.com:8080/api"); var jobAsyncTask = Task.Run(() => labMachineClient.Create(new Dictionary <string, string> { { "Package", dpkPath } })); _logger.WriteInfo(_args, "Submit build task to lab machines"); var labMachineJob = await jobAsyncTask.ConfigureAwait(false); if (labMachineJob != null) { _logger.WriteInfo(_args, "Waiting for build task..."); //periodically check the status of the build task var timeout = TimeSpan.FromMinutes(60); var sw = Stopwatch.StartNew(); while (sw.ElapsedTicks <= timeout.Ticks) { await Task.Delay(TimeSpan.FromMinutes(1)); var tmp = await Task.Run(() => labMachineClient.Get(labMachineJob.Id)).ConfigureAwait(false); if (tmp == null) { throw new Exception($"Failed to get job id {labMachineJob.Id} from lab."); } switch (tmp.State) { case JobState.Success: JobStatus = result.JobStatus = Status.Passed; break; case JobState.Failed: JobStatus = result.JobStatus = Status.Failed; break; case JobState.Aborting: case JobState.Aborted: JobStatus = result.JobStatus = Status.Cancelled; break; case JobState.Running: JobStatus = Status.InProgress; break; case JobState.Created: JobStatus = Status.Queued; break; default: break; } if (string.IsNullOrWhiteSpace(ReportUri)) { ReportUri = labMachineJob.Report; } //when the job is done, get the new build path if (result.JobStatus != default(Status) && result.JobStatus != Status.Queued && result.JobStatus != Status.InProgress) { _logger.WriteInfo(_args, "Getting build path from agent machines"); string xmlResult = labMachineClient.GetResult(labMachineJob.Id); var doc = new XmlDocument(); doc.LoadXml(xmlResult); XmlNodeList bss = doc.GetElementsByTagName("BuildPath"); string buildShare = bss[0].InnerText; result.ResultDetails.Add("Build Share", buildShare); return(result); } } throw new Exception("Waiting for build task timed out"); } else { throw new Exception("Failed to submit build task to lab machines"); } }