Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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;
            }
        }
Beispiel #6
0
        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");
            }
        }