/// <summary> /// gets changesets for all work items of the specified state /// </summary> /// <param name="project"></param> /// <param name="state"></param> /// <param name="environment"></param> /// <returns></returns> public IEnumerable <Changeset> GetChangesetsByWorkItemState(Project project, string state, MergeEnvironment environment) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var workItems = TfsTrackingDataAccess.GetTfsWorkItemsByState(tfs, project, state); return(workItems.SelectMany(w => GetTfsChangesetsBySource(tfs, w, environment)).ToList()); }
internal static TfsWorkItem GetTfsWorkItem(int workItemId) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var store = tfs.GetService <WorkItemStore>(); return(store.GetWorkItem(workItemId)); }
/// <summary> /// gets changesets for the specified merge environment /// </summary> /// <param name="workItem"></param> /// <param name="environment"></param> /// <returns></returns> public IEnumerable <Changeset> GetChangesets(IWorkItem workItem, MergeEnvironment environment) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var tfsWorkItem = TfsTrackingDataAccess.GetTfsWorkItem(workItem.Id); return(GetTfsChangesetsBySource(tfs, tfsWorkItem, environment).ToList()); }
/// <summary> /// commits changes for the local workspace and associates specified work items and comment /// </summary> /// <param name="workspace"></param> /// <param name="changes"></param> /// <param name="comment"></param> /// <param name="associatedWorkItems"></param> /// <returns></returns> private static Changeset Commit(Workspace workspace, PendingChange[] changes, string comment, IEnumerable <WorkItem> associatedWorkItems) { if (changes == null || !changes.Any()) { return(null); } var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var versionControl = tfs.GetService <VersionControlServer>(); var associateTfsWorkItems = associatedWorkItems.Select(w => TfsTrackingDataAccess.GetTfsWorkItem(w.Id)) .GroupBy(g => g.Id) .Select(w => new WorkItemCheckinInfo(w.First(), WorkItemCheckinAction.Associate)).ToArray(); comment = string.Format("{0}: {1} {2}", string.Join(",", associateTfsWorkItems.OrderBy(o => o.WorkItem.Id).Select(a => a.WorkItem.Id.ToString(CultureInfo.InvariantCulture))), comment, ConfigurationManager.AppSettings["AutomationMessage"]); var changesetId = 0; try { changesetId = workspace.CheckIn(changes, comment, null, associateTfsWorkItems, null); } catch (GatedCheckinException gatedException) { // Gated check-in is required. Get the list of build definitions affected by the check-in var buildDefs = gatedException.AffectedBuildDefinitions; // Take first build def. I don't really have any better way to determine it. var buildEnum = buildDefs.GetEnumerator(); buildEnum.MoveNext(); var buildDef = buildEnum.Current; var gatedBuildDefUri = buildDef.Value; var shelvesetSpecName = gatedException.ShelvesetName; var shelvesetTokens = shelvesetSpecName.Split(new[] { ';' }); // Create a build request for the gated check-in build var buildServer = tfs.GetService <IBuildServer>(); var buildRequest = buildServer.CreateBuildRequest(gatedBuildDefUri); buildRequest.ShelvesetName = shelvesetTokens[0]; // Specify the name of the existing shelveset buildRequest.Reason = BuildReason.CheckInShelveset; // Check-in the shelveset if successful buildRequest.GatedCheckInTicket = gatedException.CheckInTicket; // Associate the check-in var build = TfsBuildDataAccess.QueueTfsBuild(buildRequest, null, true); if (build.Build != null) { var firstOrDefault = build.Build.Changesets.FirstOrDefault(); // shouldn't be null for gated check in, for pete's sake. if (firstOrDefault != null) { changesetId = firstOrDefault.Id; } if (build.Build.Status == BuildStatus.Succeeded) { workspace.Undo(changes); } } } var newTfsChangeset = versionControl.GetChangeset(changesetId); return(newTfsChangeset == null ? null : MapChangeset(newTfsChangeset)); }
public IQueuedBuild QueueBuild(IBuildRequest buildRequest) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var buildServer = tfs.GetService <IBuildServer>(); var tfsBuildRequest = buildServer.CreateBuildRequest(buildRequest.BuildDefinitionUri); return(QueueTfsBuild(tfsBuildRequest, buildRequest.Quality, buildRequest.Wait)); }
/// <summary> /// commits pending changes for the local workspace and associates specified work items and comment /// </summary> /// <param name="comment"></param> /// <param name="associatedWorkItems"></param> /// <returns></returns> public Changeset CommitPending(string comment, IEnumerable <WorkItem> associatedWorkItems) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var versionControl = tfs.GetService <VersionControlServer>(); var workspace = versionControl.GetWorkspace(Workstation.Current.Name, tfs.AuthorizedIdentity.UniqueName); return(Commit(workspace, workspace.GetPendingChanges(), comment, associatedWorkItems)); }
public MergeTask CreateMergeTask(IWorkItem parent, string taskTitle) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var store = tfs.GetService <WorkItemStore>(); var project = store.Projects[parent.Type.Project.Name]; var taskType = project.WorkItemTypes["Task"]; var hierarchyLinkType = store.WorkItemLinkTypes[CoreLinkTypeReferenceNames.Hierarchy]; var tfsParent = GetTfsWorkItem(parent.Id); if (tfsParent == null) { return(null); } var existing = (from WorkItemLink l in tfsParent.WorkItemLinks select l).ToList() .Find(p => p.LinkTypeEnd.Name == "Child" && GetTfsWorkItem(p.TargetId).Title == taskTitle); if (existing != null) { var tfsExistingWorkItem = GetTfsWorkItem(existing.TargetId); return(new MergeTask(MapWorkItem(tfsExistingWorkItem)) { Parent = MapWorkItem(tfsParent) }); } var task = new TfsWorkItem(taskType) { Title = taskTitle }; task.Fields["Assigned To"].Value = "Jill LaMay"; // todo: get identity task.Links.Add(new WorkItemLink(hierarchyLinkType.ReverseEnd, parent.Id)); // Check for data script and tag. var changesets = TfsSourceDataAccess.GetTfsChangesetsByPathName(tfs, tfsParent, "Data Scripts").ToList(); // todo: not hard code. obvs. if (changesets.Any()) { changesets.SelectMany(s => s.Changes).GroupBy(g => g.Item.ServerItem).ToList().ForEach(f => { var descr = string.Format("{0} Data Script: {1};", task.Fields["Description"].Value, f.First().Item.ServerItem); task.Title = descr; // temp }); //task.Fields["Tags"].Value = "data-script"; // todo: Not in 2012 :( } // todo: turn off save while testing //task.Save(); //task.State = "Active"; //task.Save(); return(new MergeTask(MapWorkItem(task)) { Parent = parent }); }
public IQueuedBuild QueueBuild(string project, string buildDefinition, string quality, bool wait) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var buildServer = tfs.GetService <IBuildServer>(); var buildDef = buildServer.GetBuildDefinition(project, buildDefinition); var buildRequest = buildServer.CreateBuildRequest(buildDef.Uri); return(QueueTfsBuild(buildRequest, quality, wait)); }
public IEnumerable <IQueuedBuild> QueryQueuedBuilds() { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var buildServer = tfs.GetService <IBuildServer>(); var spec = buildServer.CreateBuildQueueSpec("*", "*"); var buildResults = buildServer.QueryQueuedBuilds(spec); return(buildResults.QueuedBuilds.Select(MapQueuedBuild).ToList()); }
public IEnumerable <IBuildDetail> QueryBuilds() { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var buildServer = tfs.GetService <IBuildServer>(); var spec = buildServer.CreateBuildDetailSpec("*", "*"); spec.MinFinishTime = DateTime.Today.AddDays(-7); spec.MaxFinishTime = DateTime.Today.AddDays(1); spec.RequestedFor = tfs.AuthorizedIdentity.UniqueName; var buildResults = buildServer.QueryBuilds(spec); return(buildResults.Builds.Select(MapBuild).ToList()); }
/// <summary> /// commits pending changes for a changeset that have been merged to the specified target and associates specified work items and comment /// </summary> /// <param name="changeset"></param> /// <param name="environment"></param> /// <param name="comment"></param> /// <returns></returns> public Changeset CommitChangeset(Changeset changeset, MergeEnvironment environment, string comment) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var versionControl = tfs.GetService <VersionControlServer>(); var workspace = versionControl.GetWorkspace(Workstation.Current.Name, tfs.AuthorizedIdentity.UniqueName); var tfsChangeset = versionControl.GetChangeset(changeset.Id); var changes = (from change in tfsChangeset.Changes select change).ToList(); var relationship = GetMergeRelationship(changeset, environment); var pending = workspace.GetPendingChanges(changes .Select(m => new ItemSpec(m.Item.ServerItem.ToLower() .Replace(string.Format("/{0}/", changeset.Branch.Name.ToLower()), string.Format("/{0}/", relationship.Target.Name)), RecursionType.None)).ToArray(), false, int.MaxValue, null, true).ToList(); var pendingChangesetChanges = pending.ToArray(); //.Where(p => p.IsMerge && p.MergeSources.Any(source => changes.Any(change => string.Compare(change.Item.ServerItem, source.ServerItem, StringComparison.OrdinalIgnoreCase) == 0))).ToArray(); return(Commit(workspace, pendingChangesetChanges, comment, changeset.WorkItems)); }
internal static IQueuedBuild QueueTfsBuild(Microsoft.TeamFoundation.Build.Client.IBuildRequest buildRequest, string quality, bool wait) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); // Create a build request for the gated check-in build var buildServer = tfs.GetService <IBuildServer>(); //Queue the build request var queuedBuild = buildServer.QueueBuild(buildRequest); if (wait) { // Wait for the build to complete. while (!queuedBuild.Build.BuildFinished) { // Get the latest status of the build, and pause to yield CPU queuedBuild.Refresh(QueryOptions.Process); System.Threading.Thread.Sleep(1000); } } if (queuedBuild.Build == null) { return(MapQueuedBuild(queuedBuild)); } if (queuedBuild.Build.Status == Microsoft.TeamFoundation.Build.Client.BuildStatus.Succeeded) { queuedBuild.Build.RefreshAllDetails(); if (!string.IsNullOrEmpty(quality)) { queuedBuild.Build.Quality = quality; //todo: implement Release data access queuedBuild.Build.Save(); } } var changesetSummaries = InformationNodeConverters.GetAssociatedChangesets(queuedBuild.Build); var build = MapQueuedBuild(queuedBuild); build.Build.Changesets = changesetSummaries.Select(c => new Changeset { Id = c.ChangesetId }); return(build); }
/// <summary> /// get merge candidates for a project and environment /// </summary> /// <param name="project"></param> /// <param name="environment"></param> /// <returns></returns> public IEnumerable <Changeset> GetMergeCandidates(Project project, MergeEnvironment environment) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var projects = TfsTeamDataAccess.GetTfsProjects().ToList(); var versionControl = tfs.GetService <VersionControlServer>(); var mergeCandidates = new List <Changeset>(); projects.ForEach(tfsProject => environment.Relationships.ToList().ForEach(relationship => { var projectName = !tfsProject.ServerItem.EndsWith("/") ? tfsProject.ServerItem + "/" : tfsProject.Name; var sourcePath = string.Format("{0}{1}/", projectName, relationship.Source.Name); var targetPath = string.Format("{0}{1}/", projectName, relationship.Target.Name); try { var candidates = versionControl.GetMergeCandidates(sourcePath, targetPath, RecursionType.Full).ToList(); candidates.ForEach(candidate => { var workItems = candidate.Changeset.WorkItems.Where( workItem => workItem.State != "Active" && workItem.State != "In Review" && workItem.Type != workItem.Project.WorkItemTypes["Task"] && // ignore changesets associated with task. Will create another audit that checks for changesets ONLY associated to task. string.Compare(project.Name, workItem.Project.Name, StringComparison.OrdinalIgnoreCase) == 0); if (workItems.Any()) { mergeCandidates.Add(MapChangeset(candidate.Changeset, relationship.Source)); } }); } catch (Exception e) { } })); return(mergeCandidates); }
public IEnumerable <MergeTask> GetWorkItemsWithMigrationScripts(Project project, string state) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var tasks = new List <MergeTask>(); var workItems = GetWorkItemsByState(project, state); workItems.ToList().ForEach(workItem => { var tfsWorkItem = GetTfsWorkItem(workItem.Id); // Check for data script and tag. var changesets = TfsSourceDataAccess.GetTfsChangesetsByPathName(tfs, tfsWorkItem, "Data Scripts").ToList(); // todo: not hard code. obvs. if (changesets.Any()) { tasks.AddRange(changesets.SelectMany(s => s.Changes).GroupBy(g => g.Item.ServerItem).Select(change => new MergeTask { Title = string.Format("Execute Data Script: {0};", change.First().Item.ServerItem), Parent = workItem })); } }); return(tasks); }
public IEnumerable <WorkItem> GetWorkItemsByState(Project project, string state) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); return(GetTfsWorkItemsByState(tfs, project, state).Select(MapWorkItem)); }
/// <summary> /// merges a changeset for the specified environment /// </summary> /// <param name="changeset"></param> /// <param name="environment"></param> /// <returns></returns> public MergeStatus MergeChangeset(Changeset changeset, MergeEnvironment environment) { var tfs = TfsTeamDataAccess.GetTfsTeamProjectCollection(); var versionControl = tfs.GetService <VersionControlServer>(); var workspace = versionControl.GetWorkspace(Workstation.Current.Name, tfs.AuthorizedIdentity.UniqueName); var tfsChangeset = versionControl.GetChangeset(changeset.Id); var statusList = new List <MergeStatus>(); tfsChangeset.Changes.ToList().ForEach(change => { var sourcePath = change.Item.ServerItem.Substring(0, change.Item.ServerItem.LastIndexOf("/", StringComparison.Ordinal)); sourcePath = !sourcePath.EndsWith("/") ? sourcePath + "/" : sourcePath; var mergeRelationship = GetMergeRelationship(changeset, environment); if (mergeRelationship == null) { statusList.Add(new MergeStatus { NumFailures = 1, Message = string.Format("There are no merge relationships configured for {0}", changeset.Branch.Name) }); return; } var targetPath = sourcePath.ToLower().Replace(string.Format("/{0}/", changeset.Branch.Name.ToLower()), string.Format("/{0}/", mergeRelationship.Target.Name)); if (string.Compare(sourcePath, targetPath, StringComparison.OrdinalIgnoreCase) == 0) // this happens with feature branches. They will get picked up on next "changeset". { return; } // Get Latest first string[] itemsSpec = { targetPath }; workspace.Get(itemsSpec, VersionSpec.Latest, RecursionType.Full, GetOptions.Overwrite); // Get ready to Merge. MergeStatus status; var verSpec = new ChangesetVersionSpec(tfsChangeset.ChangesetId); try { status = MapMergeStatus(workspace.Merge(sourcePath, targetPath, verSpec, verSpec, LockLevel.None, RecursionType.Full, MergeOptions.None)); } catch (Exception e) { status = new MergeStatus { NumFailures = 1, Message = e.Message }; } var conflicts = workspace.QueryConflicts(new[] { targetPath }, true); conflicts.ToList().ForEach(conflict => { workspace.MergeContent(conflict, false); if (conflict.ContentMergeSummary.TotalConflicting > 0) { return; } // Conflict was resolved. Does not require a human! conflict.Resolution = Resolution.AcceptMerge; // If the conflict is successfully resolved, the IsResolved property is set to true. // If resolving this conflict caused other conflicts to be deleted besides the current conflict, the list of other deleted conflicts appears in resolvedConflicts. Conflict[] resolvedConflicts; workspace.ResolveConflict(conflict, out resolvedConflicts); if (!conflict.IsResolved) { return; } var totalResolved = resolvedConflicts.Count(); status.NumResolvedConflicts = status.NumResolvedConflicts + 1 + totalResolved; status.NumConflicts = status.NumConflicts - 1 - totalResolved; }); statusList.Add(status); }); return(new MergeStatus // create summary of all merges for this changeset { HaveResolvableWarnings = statusList.Any(s => s.HaveResolvableWarnings), NoActionNeeded = statusList.All(s => s.NoActionNeeded), NumBytes = statusList.Sum(s => s.NumBytes), NumConflicts = statusList.Sum(s => s.NumConflicts), NumFailures = statusList.Sum(s => s.NumFailures), NumFiles = statusList.Sum(s => s.NumFiles), NumOperations = statusList.Sum(s => s.NumOperations), NumResolvedConflicts = statusList.Sum(s => s.NumResolvedConflicts), NumUpdated = statusList.Sum(s => s.NumUpdated), NumWarnings = statusList.Sum(s => s.NumWarnings) }); }