private static CiEvent createEvent(TfsBuildInfo buildInfo, String buildDefinitionName, bool isManualCause, DateTime?startTime,
                                           DateTime?finishTime)
        {
            var ciEvent = new CiEvent();

            ciEvent.BuildInfo = buildInfo;

            ciEvent.BuildId    = buildInfo.BuildId + "." + buildInfo.BuildNumber;
            ciEvent.BuildTitle = buildInfo.BuildNumber;

            ciEvent.ProjectDisplayName = buildDefinitionName;
            ciEvent.PhaseType          = "post";

            //cause
            var cause = new CiEventCause();

            cause.CauseType = isManualCause ? CiEventCauseType.User : CiEventCauseType.Undefined;
            ciEvent.Causes.Add(cause);

            if (startTime.HasValue)
            {
                ciEvent.StartTime = OctaneUtils.ConvertToOctaneTime(startTime.Value);
                if (finishTime.HasValue)
                {
                    ciEvent.Duration = (long)(finishTime.Value - startTime.Value).TotalMilliseconds;
                }
            }

            return(ciEvent);
        }
        private static CiEvent ConvertToCiEvent2019(Microsoft.TeamFoundation.Build2.Server.BuildData build)
        {
            TfsBuildInfo buildInfo = new TfsBuildInfo(build.Id.ToString(), build.BuildNumber, build.ProjectId.ToString(), build.Definition.Id.ToString());

            bool isManualCause = Microsoft.TeamFoundation.Build2.Server.BuildReason.Manual.Equals(build.Reason);
            var  ciEvent       = createEvent(buildInfo, build.Definition.Name, isManualCause, build.StartTime, build.FinishTime);

            if (build.Result.HasValue)
            {
                switch (build.Result)
                {
                case Microsoft.TeamFoundation.Build2.Server.BuildResult.Succeeded:
                    ciEvent.BuildResult = CiBuildResult.Success;
                    break;

                case Microsoft.TeamFoundation.Build2.Server.BuildResult.Failed:
                    ciEvent.BuildResult = CiBuildResult.Failure;
                    break;

                case Microsoft.TeamFoundation.Build2.Server.BuildResult.Canceled:
                    ciEvent.BuildResult = CiBuildResult.Aborted;
                    break;

                case Microsoft.TeamFoundation.Build2.Server.BuildResult.PartiallySucceeded:
                    ciEvent.BuildResult = CiBuildResult.Unstable;
                    break;

                default:
                    ciEvent.BuildResult = CiBuildResult.Unavailable;
                    break;
                }
            }

            return(ciEvent);
        }
        public CiEvent ToCiEvent()
        {
            var ciEvent = new CiEvent();

            //create  build info
            TfsBuildInfo buildInfo = new TfsBuildInfo();
            var          elements  = Resource.Definition.Url.Split('/').ToList();
            var          i         = elements.FindIndex(x => x == "_apis");

            buildInfo.CollectionName    = elements[i - 2];
            buildInfo.Project           = elements[i - 1];
            buildInfo.BuildDefinitionId = Resource.Definition.Id;
            buildInfo.BuildId           = Resource.Id.ToString();
            buildInfo.BuildName         = Resource.BuildNumber;
            ciEvent.BuildInfo           = buildInfo;

            //start filling ciEvent
            switch (EventType)
            {
            case "build.complete":
                ciEvent.EventType = CiEventType.Finished;
                break;

            default:
                ciEvent.EventType = CiEventType.Undefined;
                break;
            }

            ciEvent.BuildId    = buildInfo.BuildId + "." + buildInfo.BuildName;
            ciEvent.Project    = OctaneUtils.GenerateOctaneJobCiId(buildInfo.CollectionName, buildInfo.Project, buildInfo.BuildDefinitionId);
            ciEvent.BuildTitle = buildInfo.BuildName;
            var cause = new CiEventCause();

            switch (Resource.Reason)
            {
            case "manual":
                cause.CauseType = CiEventCauseType.User;
                break;

            default:
                cause.CauseType = CiEventCauseType.Undefined;
                break;
            }
            ciEvent.Causes.Add(cause);
            ciEvent.StartTime          = OctaneUtils.ConvertToOctaneTime(Resource.StartTime);
            ciEvent.Duration           = (long)(Resource.FinishTime - Resource.StartTime).TotalMilliseconds;
            ciEvent.ProjectDisplayName = Resource.Definition.Name;
            ciEvent.PhaseType          = "post";

            switch (Resource.Status)
            {
            case "succeeded":
                ciEvent.BuildResult = CiBuildResult.Success;
                break;

            case "failed":
                ciEvent.BuildResult = CiBuildResult.Failure;
                break;

            case "stopped":
                ciEvent.BuildResult = CiBuildResult.Aborted;
                break;

            default:
                ciEvent.BuildResult = CiBuildResult.Unavailable;
                break;

                //UNSTABLE("unstable"),
            }

            return(ciEvent);
        }
        public static ScmData GetScmData(TfsApis tfsManager, TfsBuildInfo buildInfo)
        {
            try
            {
                ScmData scmData         = null;
                var     originalChanges = tfsManager.GetBuildChanges(buildInfo.ProjectId, buildInfo.BuildId);
                if (originalChanges.Count > 0)
                {
                    var build = tfsManager.GetBuild(buildInfo.ProjectId, buildInfo.BuildId);
                    ICollection <TfsScmChange> filteredChanges = GetFilteredBuildChanges(tfsManager, buildInfo, build, originalChanges);
                    if (filteredChanges.Count > 0)
                    {
                        scmData = new ScmData();
                        var repository = tfsManager.GetRepositoryById(buildInfo.ProjectId, build.Repository.Id);
                        scmData.Repository        = new ScmRepository();
                        scmData.Repository.Branch = build.SourceBranch;
                        scmData.Repository.Type   = build.Repository.Type;
                        scmData.Repository.Url    = repository.RemoteUrl;

                        scmData.BuiltRevId = build.SourceVersion;
                        scmData.Commits    = new List <ScmCommit>();
                        foreach (TfsScmChange change in filteredChanges)
                        {
                            var       tfsCommit = tfsManager.GetCommitWithChanges(change.Location);
                            ScmCommit scmCommit = new ScmCommit();
                            scmData.Commits.Add(scmCommit);
                            scmCommit.User      = tfsCommit.Committer.Name;
                            scmCommit.UserEmail = tfsCommit.Committer.Email;
                            scmCommit.Time      = OctaneUtils.ConvertToOctaneTime(tfsCommit.Committer.Date);
                            scmCommit.RevId     = tfsCommit.CommitId;
                            if (tfsCommit.Parents.Count > 0)
                            {
                                scmCommit.ParentRevId = tfsCommit.Parents[0];
                            }

                            scmCommit.Comment = tfsCommit.Comment;
                            scmCommit.Changes = new List <ScmCommitFileChange>();

                            foreach (var tfsCommitChange in tfsCommit.Changes)
                            {
                                if (!tfsCommitChange.Item.IsFolder)
                                {
                                    ScmCommitFileChange commitChange = new ScmCommitFileChange();
                                    scmCommit.Changes.Add(commitChange);

                                    string commitChangeType = tfsCommitChange.ChangeType.ToLowerInvariant();
                                    switch (commitChangeType)
                                    {
                                    case "add":
                                    case "edit":
                                    case "delete":
                                        //do nothins
                                        break;

                                    case "delete, sourcerename":
                                        commitChangeType = "delete";
                                        break;

                                    case "rename":
                                    case "edit, rename":
                                        commitChangeType = "add";
                                        break;

                                    default:
                                        Log.Debug($"Build {buildInfo} - Unexpected change type <{commitChangeType}> for file <{tfsCommitChange.Item.Path}>. Setting default to 'edit'.");
                                        commitChangeType = "edit";

                                        break;
                                    }

                                    commitChange.Type = commitChangeType;
                                    commitChange.File = tfsCommitChange.Item.Path;
                                }
                            }
                        }
                    }
                }
                return(scmData);
            }
            catch (Exception e)
            {
                Log.Error($"Build {buildInfo} - failed to create scm data : {e.Message}");
                return(null);
            }
        }
        /// <summary>
        /// Tfs returns associated changes from last successful build. That mean, for failed build it can return change that was reported for previous failed build.
        /// This method - clear previously reported changes of previous failed build
        /// </summary>
        private static ICollection <TfsScmChange> GetFilteredBuildChanges(TfsApis tfsManager, TfsBuildInfo buildInfo, TfsBuild build, ICollection <TfsScmChange> changes)
        {
            //put changes in map
            Dictionary <string, TfsScmChange> changesMap = new Dictionary <string, TfsScmChange>();

            foreach (TfsScmChange change in changes)
            {
                changesMap[change.Id] = change;
            }

            //find previous failed build
            IList <TfsBuild> previousBuilds           = tfsManager.GetPreviousFailedBuilds(buildInfo.ProjectId, build.StartTime);
            TfsBuild         foundPreviousFailedBuild = null;

            foreach (TfsBuild previousBuild in previousBuilds)
            {
                //pick only build that done on the same branch
                if (build.SourceBranch.Equals(previousBuild.SourceBranch))
                {
                    foundPreviousFailedBuild = previousBuild;
                    break;
                }
            }

            if (foundPreviousFailedBuild != null)
            {
                //remove changes from previous build
                var previousChanges = tfsManager.GetBuildChanges(buildInfo.ProjectId, foundPreviousFailedBuild.Id.ToString());
                foreach (TfsScmChange previousChange in previousChanges)
                {
                    changesMap.Remove(previousChange.Id);
                }

                int removedCount = changes.Count - changesMap.Count;
                if (removedCount == 0)
                {
                    Log.Debug($"Build {buildInfo} - build {build.Id} contains {changes.Count} associated changes. No one of them was already reported in previous build {foundPreviousFailedBuild.Id}");
                }
                else
                {
                    Log.Debug($"Build {buildInfo} - build {build.Id} contains {changes.Count} associated changes while {removedCount} changes were already reported in build {foundPreviousFailedBuild.Id}");
                }
            }

            return(changesMap.Values);
        }
        public static CiEvent ToCiEvent(Build build)
        {
            var ciEvent = new CiEvent();


            //create  build info
            TfsBuildInfo buildInfo = new TfsBuildInfo();
            var          elements  = build.Definition.Url.Split('/').ToList();
            var          i         = elements.FindIndex(x => x == "_apis");

            buildInfo.CollectionName    = elements[i - 2];
            buildInfo.Project           = elements[i - 1];
            buildInfo.BuildDefinitionId = build.Definition.Id.ToString();
            buildInfo.BuildId           = build.Id.ToString();
            buildInfo.BuildName         = build.BuildNumber;
            ciEvent.BuildInfo           = buildInfo;

            //start filling ciEvent
            ciEvent.BuildId = buildInfo.BuildId + "." + buildInfo.BuildName;

            ciEvent.Project    = OctaneUtils.GenerateOctaneJobCiId(buildInfo.CollectionName, buildInfo.Project, buildInfo.BuildDefinitionId);
            ciEvent.BuildTitle = buildInfo.BuildName;
            var cause = new CiEventCause();

            switch (build.Reason)
            {
            case BuildReason.Manual:
                cause.CauseType = CiEventCauseType.User;
                break;

            default:
                cause.CauseType = CiEventCauseType.Undefined;
                break;
            }
            ciEvent.Causes.Add(cause);

            ciEvent.ProjectDisplayName = build.Definition.Name;
            ciEvent.PhaseType          = "post";


            if (build.StartTime.HasValue)
            {
                ciEvent.StartTime = OctaneUtils.ConvertToOctaneTime(build.StartTime.Value);
                if (build.FinishTime.HasValue)
                {
                    ciEvent.Duration = (long)(build.FinishTime.Value - build.StartTime.Value).TotalMilliseconds;
                }
            }

            if (build.Result.HasValue)
            {
                switch (build.Result)
                {
                case BuildResult.Succeeded:
                    ciEvent.BuildResult = CiBuildResult.Success;
                    break;

                case BuildResult.Failed:
                    ciEvent.BuildResult = CiBuildResult.Failure;
                    break;

                case BuildResult.Canceled:
                    ciEvent.BuildResult = CiBuildResult.Aborted;
                    break;

                case BuildResult.PartiallySucceeded:
                    ciEvent.BuildResult = CiBuildResult.Unstable;
                    break;

                default:
                    ciEvent.BuildResult = CiBuildResult.Unavailable;
                    break;
                }
            }


            return(ciEvent);
        }