protected override IEnumerable<Notifications.INotification> CreateNotifications(IVssRequestContext requestContext, object notificationEventArgs, int maxLines) { var repositoryService = requestContext.GetService<ITeamFoundationGitRepositoryService>(); var identityService = requestContext.GetService<ITeamFoundationIdentityService>(); var commonService = requestContext.GetService<CommonStructureService>(); var locationService = requestContext.GetService<ILocationService>(); string baseUrl = String.Format("{0}/{1}/", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name); var gitNotification = notificationEventArgs as GitNotification; Notifications.RepositoryNotification notification = null; if (gitNotification is RepositoryCreatedNotification) { var ev = notificationEventArgs as RepositoryCreatedNotification; var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Creator.Identifier); notification = new Notifications.RepositoryCreatedNotification(); notification.UniqueName = identity.UniqueName; notification.DisplayName = identity.DisplayName; notification.TeamNames = GetUserTeamsByProjectUri(requestContext, gitNotification.TeamProjectUri, identity.Descriptor); using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, gitNotification.RepositoryId)) { notification.RepoUri = repository.GetRepositoryUri(); notification.RepoName = repository.Name; } } else if (gitNotification is RepositoryRenamedNotification) { notification = new Notifications.RepositoryRenamedNotification(); notification.RepoName = gitNotification.RepositoryName; using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, gitNotification.RepositoryId)) { notification.RepoUri = repository.GetRepositoryUri(); notification.RepoName = repository.Name; } notification.TeamNames = Enumerable.Empty<string>(); } else if (gitNotification is RepositoryDeletedNotification) { var repoInfo = repositoryService .QueryDeletedRepositories(requestContext, gitNotification.TeamProjectUri) .Single(r => r.RepositoryId == gitNotification.RepositoryId); var identity = identityService.ReadIdentities(requestContext, new[] { repoInfo.DeletedBy }).First(); notification = new Notifications.RepositoryDeletedNotification(); notification.UniqueName = identity.UniqueName; notification.DisplayName = identity.DisplayName; notification.TeamNames = GetUserTeamsByProjectUri(requestContext, gitNotification.TeamProjectUri, identity.Descriptor); notification.RepoName = repoInfo.Name; } notification.TeamProjectCollection = requestContext.ServiceHost.Name; notification.ProjectName = commonService.GetProject(requestContext, gitNotification.TeamProjectUri).Name; notification.ProjectUrl = baseUrl + notification.ProjectName; yield return notification; }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, BuildCompletionNotificationEvent buildNotification, int maxLines) { BuildDetail build = buildNotification.Build; var locationService = requestContext.GetService <ILocationService>(); var buildService = requestContext.GetService <TeamFoundationBuildService>(); using (var buildReader = buildService.QueryQueuedBuildsById(requestContext, build.QueueIds, new[] { "*" }, QueryOptions.None)) { var result = buildReader.Current <BuildQueueQueryResult>(); QueuedBuild qb = result.QueuedBuilds.FirstOrDefault(); string buildUrl = string.Format("{0}/{1}/{2}/_build#_a=summary&buildId={3}", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name, build.TeamProject, qb.BuildId); var notification = new BuildCompletionNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, BuildUrl = buildUrl, ProjectName = build.TeamProject, BuildNumber = build.BuildNumber, BuildStatus = build.Status, BuildReason = build.Reason, StartTime = build.StartTime, FinishTime = build.FinishTime, RequestedForUniqueName = qb.RequestedFor, RequestedForDisplayName = qb.RequestedForDisplayName, BuildDefinition = build.Definition.Name, DropLocation = build.DropLocation, TeamNames = GetUserTeamsByProjectName(requestContext, build.TeamProject, qb.RequestedFor) }; yield return(notification); } }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, ReleaseCreatedServerEvent ev, int maxLines) { var projectService = requestContext.GetService <IProjectService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var release = ev.Release; var creator = identityService.ReadIdentities(requestContext, new[] { release.CreatedBy }).First(); string projectName = projectService.GetProjectName(requestContext, ev.ProjectId); var releaseUrl = WebAccessUrlBuilder.GetReleaseWebAccessUri(requestContext, projectName, release.Id); var notification = new ReleaseCreatedNotification { TeamProjectCollection = requestContext.ServiceHost.Name, ProjectName = projectName, ReleaseDefinition = release.ReleaseDefinitionName, ReleaseName = release.Name, ReleaseReason = release.Reason, ReleaseStatus = release.Status, ReleaseUrl = releaseUrl, CreatedOn = release.CreatedOn, CreatedByUniqueName = creator.UniqueName, CreatedByDisplayName = creator.DisplayName, TeamNames = GetUserTeamsByProjectName(requestContext, projectName, creator.Descriptor) }; yield return(notification); }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, PolicyViolationEvent policyViolation, int maxLines) { var commonService = requestContext.GetService <CommonStructureService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, policyViolation.Identity.Identifier); var notification = new PolicyViolationNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, ProjectName = string.Empty, PolicyType = policyViolation.PolicyType, Message = policyViolation.Message, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName }; var push = policyViolation.OriginalEvent as PushNotification; if (push != null) { notification.ProjectName = commonService.GetProject(requestContext, push.TeamProjectUri).Name; } yield return(notification); }
protected override IEnumerable <Notifications.INotification> CreateNotifications(IVssRequestContext requestContext, object notificationEventArgs, int maxLines) { var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <CommonStructureService>(); var locationService = requestContext.GetService <ILocationService>(); string baseUrl = String.Format("{0}/{1}/", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name); var gitNotification = notificationEventArgs as GitNotification; Notifications.RepositoryNotification notification = null; if (gitNotification is RepositoryCreatedNotification) { var ev = notificationEventArgs as RepositoryCreatedNotification; var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Creator.Identifier); notification = new Notifications.RepositoryCreatedNotification(); notification.UniqueName = identity.UniqueName; notification.DisplayName = identity.DisplayName; notification.TeamNames = GetUserTeamsByProjectUri(requestContext, gitNotification.TeamProjectUri, identity.Descriptor); using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, gitNotification.RepositoryId)) { notification.RepoUri = repository.GetRepositoryUri(); notification.RepoName = repository.Name; } } else if (gitNotification is RepositoryRenamedNotification) { notification = new Notifications.RepositoryRenamedNotification(); notification.RepoName = gitNotification.RepositoryName; using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, gitNotification.RepositoryId)) { notification.RepoUri = repository.GetRepositoryUri(); notification.RepoName = repository.Name; } notification.TeamNames = Enumerable.Empty <string>(); } else if (gitNotification is RepositoryDeletedNotification) { var repoInfo = repositoryService .QueryDeletedRepositories(requestContext, gitNotification.TeamProjectUri) .Single(r => r.RepositoryId == gitNotification.RepositoryId); var identity = identityService.ReadIdentities(requestContext, new[] { repoInfo.DeletedBy }).First(); notification = new Notifications.RepositoryDeletedNotification(); notification.UniqueName = identity.UniqueName; notification.DisplayName = identity.DisplayName; notification.TeamNames = GetUserTeamsByProjectUri(requestContext, gitNotification.TeamProjectUri, identity.Descriptor); notification.RepoName = repoInfo.Name; } notification.TeamProjectCollection = requestContext.ServiceHost.Name; notification.ProjectName = commonService.GetProject(requestContext, gitNotification.TeamProjectUri).Name; notification.ProjectUrl = baseUrl + notification.ProjectName; yield return(notification); }
public Task NotifyAsync(IVssRequestContext requestContext, INotification notification, BotElement bot, EventRuleElement matchingRule) { if (!notification.TargetUserNames.Any()) { return(Task.FromResult(0)); } var config = TfsNotificationRelaySection.Instance; string host = bot.GetSetting("host", "127.0.0.1"); int port = bot.GetIntSetting("port", 25); string fromAddress = bot.GetSetting("fromAddress"); string fromName = bot.GetSetting("fromName"); string subjectTextId = bot.GetSetting("subjectTextId", "plaintext"); bool isHtml = bot.GetSetting("isHtml") == "true"; var subjectTextElement = config.Texts.FirstOrDefault(t => t.Id == subjectTextId) ?? bot.Text; string subject = notification.ToMessage(bot, subjectTextElement, s => s).First(); var client = new SmtpClient(host, port); var message = new MailMessage(); message.From = new MailAddress(fromAddress, fromName, Encoding.UTF8); message.SubjectEncoding = Encoding.UTF8; message.Subject = subject; message.IsBodyHtml = isHtml; message.BodyEncoding = Encoding.UTF8; message.Body = string.Join(isHtml ? "<br/>": "\n", notification.ToMessage(bot, s => s)); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); foreach (var username in notification.TargetUserNames) { var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.AccountName, username); var email = identityService.GetPreferredEmailAddress(requestContext, identity.TeamFoundationId); if (string.IsNullOrEmpty(email)) { string errmsg = $"TfsNotificationRelay.Smtp.SmtpNotifier: User {username} doesn't have an email address."; TeamFoundationApplicationCore.Log(requestContext, errmsg, 0, EventLogEntryType.Warning); } else { message.To.Add(email); } } if (message.To.Any()) { requestContext.Trace(0, TraceLevel.Info, Constants.TraceArea, "SmtpNotifier", string.Format("Sending {0} email notification to: {1}.", notification.GetType(), string.Join(", ", message.To.Select(m => m.Address)))); return(client.SendMailAsync(message)); } else { requestContext.Trace(0, TraceLevel.Warning, Constants.TraceArea, "SmtpNotifier", string.Format("No recipients to send {0} email notification to.", notification.GetType())); return(Task.FromResult(0)); } }
internal Mailer(IVssRequestContext requestContext) { this.Enabled = false; try { TeamFoundationRegistryService service = requestContext.GetService <TeamFoundationRegistryService>(); Microsoft.TeamFoundation.Framework.Server.RegistryEntryCollection registryEntryCollection = service.ReadEntriesFallThru(requestContext, FrameworkServerConstants.NotificationRootPath + "/*"); if (registryEntryCollection["EmailEnabled"].GetValue <bool>(true)) { this.SmtpServer = registryEntryCollection["SmtpServer"].GetValue(string.Empty); this.SmtpPort = registryEntryCollection["SmtpPort"].GetValue <int>(-1); this.EnableSsl = registryEntryCollection["SmtpEnableSsl"].GetValue <bool>(false); this.FromAddress = null; string value = registryEntryCollection["EmailNotificationFromAddress"].GetValue(string.Empty); if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(this.SmtpServer)) { this.FromAddress = new MailAddress(value); this.Enabled = true; } } } catch (System.Exception ex) { System.Diagnostics.Debug.WriteLine($"SendMail failed: {ex.Message}"); } }
private static IVssRequestContext CreateServicingContext(IVssDeploymentServiceHost deploymentServiceHost, Guid instanceId) { using (IVssRequestContext requestContext = deploymentServiceHost.CreateSystemContext(true)) { TeamFoundationHostManagementService host = requestContext.GetService <TeamFoundationHostManagementService>(); return(host.BeginRequest(requestContext, instanceId, RequestContextType.ServicingContext)); } }
public Task NotifyAsync(IVssRequestContext requestContext, INotification notification, BotElement bot, EventRuleElement matchingRule) { if (!notification.TargetUserNames.Any()) return Task.FromResult(0); var config = TfsNotificationRelaySection.Instance; string host = bot.GetSetting("host", "127.0.0.1"); int port = bot.GetIntSetting("port", 25); string fromAddress = bot.GetSetting("fromAddress"); string fromName = bot.GetSetting("fromName"); string subjectTextId = bot.GetSetting("subjectTextId", "plaintext"); bool isHtml = bot.GetSetting("isHtml") == "true"; var subjectTextElement = config.Texts.FirstOrDefault(t => t.Id == subjectTextId) ?? bot.Text; string subject = notification.ToMessage(bot, subjectTextElement, s => s).First(); var client = new SmtpClient(host, port); var message = new MailMessage(); message.From = new MailAddress(fromAddress, fromName, Encoding.UTF8); message.SubjectEncoding = Encoding.UTF8; message.Subject = subject; message.IsBodyHtml = isHtml; message.BodyEncoding = Encoding.UTF8; message.Body = string.Join(isHtml ? "<br/>": "\n", notification.ToMessage(bot, s => s)); var identityService = requestContext.GetService<ITeamFoundationIdentityService>(); foreach (var username in notification.TargetUserNames) { var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.AccountName, username); var email = identityService.GetPreferredEmailAddress(requestContext, identity.TeamFoundationId); if (string.IsNullOrEmpty(email)) { string errmsg = $"TfsNotificationRelay.Smtp.SmtpNotifier: User {username} doesn't have an email address."; TeamFoundationApplicationCore.Log(requestContext, errmsg, 0, EventLogEntryType.Warning); } else { message.To.Add(email); } } if (message.To.Any()) { requestContext.Trace(0, TraceLevel.Info, Constants.TraceArea, "SmtpNotifier", string.Format("Sending {0} email notification to: {1}.", notification.GetType(), string.Join(", ", message.To.Select(m => m.Address)))); return client.SendMailAsync(message); } else { requestContext.Trace(0, TraceLevel.Warning, Constants.TraceArea, "SmtpNotifier", string.Format("No recipients to send {0} email notification to.", notification.GetType())); return Task.FromResult(0); } }
protected override IEnumerable <Notifications.INotification> CreateNotifications(IVssRequestContext requestContext, ReviewerVoteNotification ev, int maxLines) { var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <ICommonStructureService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Reviewer.Descriptor.Identifier); using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, ev.RepositoryId)) { var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>(); TfsGitPullRequest pullRequest; if (pullRequestService.TryGetPullRequestDetails(requestContext, repository, ev.PullRequestId, out pullRequest)) { string repoUri = repository.GetRepositoryUri(); var creator = identityService.ReadIdentities(requestContext, new[] { pullRequest.Creator }).First(); var reviewers = identityService.ReadIdentities(requestContext, pullRequest.Reviewers.Select(r => r.Reviewer).ToArray()); var notification = new Notifications.PullRequestReviewerVoteNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, CreatorUniqueName = creator.UniqueName, Vote = ev.ReviewerVote, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName, ProjectName = commonService.GetProject(requestContext, ev.TeamProjectUri).Name, RepoUri = repoUri, RepoName = ev.RepositoryName, PrId = pullRequest.PullRequestId, PrUrl = $"{repoUri}/pullrequest/{ev.PullRequestId}#view=discussion", PrTitle = pullRequest.Title, TeamNames = GetUserTeamsByProjectUri(requestContext, ev.TeamProjectUri, ev.Reviewer.Descriptor), SourceBranch = new Notifications.GitRef(pullRequest.SourceBranchName), TargetBranch = new Notifications.GitRef(pullRequest.TargetBranchName), ReviewerUserNames = reviewers.Select(r => r.UniqueName) }; yield return(notification); } else { throw new TfsNotificationRelayException("Unable to get pull request " + ev.PullRequestId); } } }
protected override PolicyEvaluationResult Evaluate(IVssRequestContext requestContext, PushNotification notificationEventArgs) { var commonService = requestContext.GetService <ICommonStructureService>(); var push = (PushNotification)notificationEventArgs; var projectName = commonService.GetProject(requestContext, push.TeamProjectUri).Name; if (projectName == "TestCompany") { return(new PolicyEvaluationResult(true)); } return(EvaluateInternal(requestContext, notificationEventArgs)); }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, TFVC.CheckinNotification checkin, int maxLines) { var locationService = requestContext.GetService <ILocationService>(); string baseUrl = String.Format("{0}/{1}/", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name); var teamNames = new HashSet <string>(); var projects = new Dictionary <string, string>(); var submittedItems = checkin.GetSubmittedItems(requestContext).ToList(); const string pattern = @"^\$\/([^\/]*)\/"; foreach (string item in submittedItems) { Match match = Regex.Match(item, pattern); if (match.Success) { string projectName = match.Groups[1].Value; if (projects.ContainsKey(projectName)) { continue; } string projectUrl = baseUrl + projectName; projects.Add(projectName, projectUrl); foreach (var team in GetUserTeamsByProjectName(requestContext, projectName, checkin.ChangesetOwner.Descriptor)) { teamNames.Add(team); } } } var notification = new CheckinNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, UniqueName = checkin.ChangesetOwner.UniqueName, DisplayName = checkin.ChangesetOwner.DisplayName, ChangesetUrl = $"{baseUrl}_versionControl/changeset/{checkin.Changeset}", ChangesetId = checkin.Changeset, Projects = projects, Comment = TextHelper.Truncate(checkin.Comment, Settings.CommentMaxLength, true), TeamNames = teamNames, SubmittedItems = submittedItems }; yield return(notification); }
public EventNotificationStatus ProcessEvent( IVssRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties) { statusCode = 0; statusMessage = string.Empty; properties = null; if (notificationType == NotificationType.DecisionPoint && notificationEventArgs is PushNotification) { var pushNotification = notificationEventArgs as PushNotification; var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); using (var gitRepository = repositoryService.FindRepositoryById( requestContext, pushNotification.RepositoryId)) { // TODO: gitRepository.Name should probably equal "Estream". Company wide TFS instance! // TODO: Also, this name should not be hard coded and should be a collection. foreach (var item in pushNotification.IncludedCommits) { var gitCommit = (TfsGitCommit)gitRepository.LookupObject(item); var comment = gitCommit.GetComment(requestContext); if (!CommitRules.IsCommitAcceptable(comment)) { statusMessage = $"Non-merge commits must contain links to TFS (i.e. #12345) [Repository Name: {gitRepository.Name}]."; return(EventNotificationStatus.ActionDenied); } } } } return(EventNotificationStatus.ActionApproved); }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, ProjectCreatedEvent ev, int maxLines) { var locationService = requestContext.GetService <ILocationService>(); string projectUrl = String.Format("{0}/{1}/{2}", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name, ev.Name); if (!ProjectsNames.ContainsKey(ev.Uri)) { ProjectsNames.Add(ev.Uri, ev.Name); } yield return(new ProjectCreatedNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, ProjectUrl = projectUrl, ProjectName = ev.Name }); }
private static void ProvisionProjectFeatures(IVssRequestContext context, Microsoft.TeamFoundation.WorkItemTracking.Client.Project project, StreamWriter logFile) { // Get the Feature provisioning service ("Configure Features") var projectFeatureProvisioningService = context.GetService <ProjectFeatureProvisioningService>(); if (!projectFeatureProvisioningService.GetFeatures(context, project.Uri.ToString()).Where(f => (f.State == ProjectFeatureState.NotConfigured && !f.IsHidden)).Any()) { // When the team project is already fully or partially configured, report it Console.WriteLine("\t{0}: Project is up to date.", project.Name); logFile.WriteLine(">>> Team Project is now already up to date"); } else { // Find valid process templates var projectFeatureProvisioningDetails = projectFeatureProvisioningService.ValidateProcessTemplates(context, project.Uri.ToString()); var validProcessTemplateDetails = projectFeatureProvisioningDetails.Where(d => d.IsValid); switch (validProcessTemplateDetails.Count()) { case 0: Console.WriteLine("\t{0}: No valid process templates found.", project.Name); logFile.WriteLine(">>> No valid process templates found, the team project cannot be configured/upgraded automatically to adopt the latest features."); break; case 1: var projectFeatureProvisioningDetail = projectFeatureProvisioningDetails.ElementAt(0); Console.WriteLine(">>> Upgrading Team Project with template " + projectFeatureProvisioningDetail.ProcessTemplateDescriptorName); logFile.WriteLine(">>> Upgrading Team Project with template " + projectFeatureProvisioningDetail.ProcessTemplateDescriptorName); ProvisionProject(context, project, projectFeatureProvisioningService, projectFeatureProvisioningDetail); break; default: // Try to upgrade using the recommended process template var newRecommendedTemplate = validProcessTemplateDetails.FirstOrDefault(ptd => ptd.IsRecommended); Console.WriteLine(">>> Multiple valid process templates found. Upgrading Team Project with recommended template " + newRecommendedTemplate.ProcessTemplateDescriptorName); logFile.WriteLine(">>> Multiple valid process templates found. Upgrading Team Project with recommended template " + newRecommendedTemplate.ProcessTemplateDescriptorName); ProvisionProject(context, project, projectFeatureProvisioningService, newRecommendedTemplate); break; } } }
protected override PolicyEvaluationResult EvaluateInternal(IVssRequestContext requestContext, PushNotification push) { var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); var newBranches = push.RefUpdateResults.Where(r => r.OldObjectId == Sha1Id.Empty && r.Name.StartsWith(Constants.BranchPrefix)); var branch = newBranches.SingleOrDefault(b => b.Name == Constants.BranchPrefix + "master"); if (branch != null) { using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, push.RepositoryId)) { TfsGitCommit commit = (TfsGitCommit)repository.LookupObject(branch.NewObjectId); if (commit != null) { var tree = commit.GetTree(); var treeEntries = tree.GetTreeEntries(); if (treeEntries.Any()) { bool includesGitignore = false; bool includesGitattributes = false; foreach (var entry in treeEntries) { if (entry.ObjectType == GitObjectType.Blob && entry.Name.Equals(".gitignore", StringComparison.OrdinalIgnoreCase)) { includesGitignore = true; } if (entry.ObjectType == GitObjectType.Blob && entry.Name.Equals(".gitattributes", StringComparison.OrdinalIgnoreCase)) { using (var reader = new StreamReader(entry.Object.GetContent())) { var gitattributesContents = reader.ReadToEnd(); // Make sure .gitattributes file has a '* text=auto' line for eol normalization if (!Regex.IsMatch(gitattributesContents, @"^\*\s+text=auto\s*$", RegexOptions.Multiline)) { Logger.Log("pushNotification:", push); var statusMessage = $".gitattributes is missing '* text=auto'. See {Settings.DocsBaseUrl}/guidelines/scm/git-conventions/#mandatory-files."; Logger.Log(statusMessage); return(new PolicyEvaluationResult(false, push.Pusher, statusMessage)); } includesGitattributes = true; } } } if (!includesGitignore || !includesGitattributes) { Logger.Log("pushNotification:", push); var statusMessage = $"Mandatory files missing. See {Settings.DocsBaseUrl}/guidelines/scm/git-conventions/#mandatory-files."; Logger.Log(statusMessage); return(new PolicyEvaluationResult(false, push.Pusher, statusMessage)); } } else { Logger.Log("Commit without tree entries: " + branch.NewObjectId); } } else { Logger.Log("Unable to find commit " + branch.NewObjectId); } } } return(new PolicyEvaluationResult(true)); }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, DiscussionsNotification args, int maxLines) { var locationService = requestContext.GetService <ILocationService>(); var linkingService = requestContext.GetService <TeamFoundationLinkingService>(); var hyperlinkService = requestContext.GetService <TswaServerHyperlinkService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <ICommonStructureService>(); var discussionService = requestContext.GetService <ITeamFoundationDiscussionService>(); var notifications = new List <INotification>(); foreach (var thread in args.Threads) { if (thread.Comments == null) { continue; // e.g. when a comment is deleted } var artifactId = LinkingUtilities.DecodeUri(thread.ArtifactUri); int discussionId = thread.DiscussionId <= 0 ? thread.Comments[0].DiscussionId : thread.DiscussionId; if (artifactId.ArtifactType.Equals("Commit", StringComparison.OrdinalIgnoreCase)) { var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); var commitService = requestContext.GetService <ITeamFoundationGitCommitService>(); Guid projectId; Guid repositoryId; Sha1Id commitId; GitCommitArtifactId.Decode(artifactId, out projectId, out repositoryId, out commitId); using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, repositoryId)) { var project = commonService.GetProject(requestContext, projectId); var repoUri = repository.GetRepositoryUri(); var commitUri = repoUri + "/commit/" + commitId.ToHexString(); string itemPath; if (thread.Properties.TryGetValue <string>("Microsoft.TeamFoundation.Discussion.ItemPath", out itemPath)) { commitUri += string.Format("#path={0}&discussionId={1}&_a=contents", Uri.EscapeDataString(itemPath), discussionId); } var commitManifest = commitService.GetCommitManifest(requestContext, repository, commitId); var pushData = commitService.GetPushDataForPushIds(requestContext, repository.RepoId.RepoId, new[] { commitManifest.PushId }).FirstOrDefault(); var pusher = identityService.ReadIdentities(requestContext, new[] { pushData.PusherId }).FirstOrDefault(); foreach (var comment in thread.Comments) { var commenter = identityService.ReadIdentities(requestContext, new[] { Guid.Parse(comment.Author.Id) }).First(); var notification = new Notifications.CommitCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, PusherUniqueName = pusher?.UniqueName, UniqueName = commenter.UniqueName, DisplayName = comment.Author.DisplayName, ProjectName = project.Name, RepoUri = repoUri, RepoName = repository.Name, CommitId = commitId, CommitUri = commitUri, Comment = TextHelper.Truncate(comment.Content, Settings.DiscussionCommentMaxLength), TeamNames = GetUserTeamsByProjectUri(requestContext, project.Uri, commenter.Descriptor), }; notifications.Add(notification); } } } if (artifactId.Tool.Equals("CodeReview", StringComparison.OrdinalIgnoreCase)) { var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>(); var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); Guid projectId; int pullRequestId = PullRequestArtifactHelper.GetPullRequestId(requestContext, thread.ArtifactUri, out projectId); var pullRequest = pullRequestService.GetPullRequestDetails(requestContext, pullRequestId); using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pullRequest.RepositoryId)) { var project = commonService.GetProject(requestContext, projectId); string repoUri = repository.GetRepositoryUri(); var creator = identityService.ReadIdentities(requestContext, new[] { pullRequest.Creator }).FirstOrDefault(); foreach (var comment in thread.Comments) { var commenter = identityService.ReadIdentities(requestContext, new[] { Guid.Parse(comment.Author.Id) }).First(); var notification = new Notifications.PullRequestCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, CreatorUniqueName = creator?.UniqueName, UniqueName = commenter.UniqueName, DisplayName = commenter.DisplayName, ProjectName = project.Name, RepoUri = repoUri, RepoName = repository.Name, PrId = pullRequest.PullRequestId, PrUrl = $"{repoUri}/pullrequest/{pullRequest.PullRequestId}#view=discussion", PrTitle = pullRequest.Title, TeamNames = GetUserTeamsByProjectUri(requestContext, project.Uri, commenter.Descriptor), SourceBranch = new GitRef(pullRequest.SourceBranchName), TargetBranch = new GitRef(pullRequest.TargetBranchName), Comment = TextHelper.Truncate(comment.Content, Settings.DiscussionCommentMaxLength) }; notifications.Add(notification); } } } else if (artifactId.ArtifactType.Equals("Changeset", StringComparison.OrdinalIgnoreCase)) { var versionControlService = requestContext.GetService <TeamFoundationVersionControlService>(); var uri = new VersionControlIntegrationUri(thread.ArtifactUri); var changesetId = int.Parse(uri.ArtifactName); var reader = versionControlService.QueryChangeset(requestContext, changesetId, true, false, false); var changeset = reader.Current <Changeset>(); var changesetUrl = hyperlinkService.GetChangesetDetailsUrl(changesetId).AbsoluteUri; string baseUrl = String.Format("{0}/{1}/", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name); string itemPath = string.Empty; string projectName = string.Empty; const string projectNamePattern = @"^\$\/([^\/]*)\/"; if (thread.Properties != null && thread.Properties.TryGetValue <string>("Microsoft.TeamFoundation.Discussion.ItemPath", out itemPath)) { changesetUrl += string.Format("#path={0}&discussionId={1}&_a=contents", Uri.EscapeDataString(itemPath), discussionId); Match match = Regex.Match(itemPath, projectNamePattern); if (match.Success) { projectName = match.Groups[1].Value; } } else { // This assumes changeset doesn't span multiple projects. var serverItem = changeset.Changes.FirstOrDefault()?.Item.ServerItem; if (serverItem != null) { Match match = Regex.Match(serverItem, projectNamePattern); if (match.Success) { projectName = match.Groups[1].Value; } } } var commiter = identityService.ReadIdentity(requestContext, IdentitySearchFactor.AccountName, changeset.Committer); foreach (var comment in thread.Comments) { var commenter = identityService.ReadIdentities(requestContext, new[] { Guid.Parse(comment.Author.Id) }).First(); var notification = new Notifications.ChangesetCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, CreatorUniqueName = commiter?.UniqueName, UniqueName = commenter.UniqueName, DisplayName = commenter.DisplayName, ProjectUrl = baseUrl + projectName, ProjectName = projectName, ChangesetId = changesetId, ChangesetUrl = changesetUrl, TeamNames = GetUserTeamsByProjectName(requestContext, projectName, commenter.Descriptor), SourcePath = itemPath, Comment = TextHelper.Truncate(comment.Content, Settings.DiscussionCommentMaxLength) }; notifications.Add(notification); } } } return(notifications); }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, PushNotification pushNotification, int maxLines) { var repositoryService = requestContext.GetService <ITeamFoundationGitRepositoryService>(); var commonService = requestContext.GetService <CommonStructureService>(); var commitService = requestContext.GetService <ITeamFoundationGitCommitService>(); var identityService = requestContext.GetService <TeamFoundationIdentityService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, pushNotification.Pusher.Identifier); var teamNames = GetUserTeamsByProjectUri(requestContext, pushNotification.TeamProjectUri, pushNotification.Pusher); using (ITfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId)) { var pushRow = new PushRow() { UniqueName = pushNotification.AuthenticatedUserName, DisplayName = identity.DisplayName, RepoName = pushNotification.RepositoryName, RepoUri = repository.GetRepositoryUri(), ProjectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name, IsForcePush = Settings.IdentifyForcePush && pushNotification.IsForceRequired(requestContext, repository) }; var notification = new GitPushNotification(requestContext.ServiceHost.Name, pushRow.ProjectName, pushRow.RepoName, pushNotification.AuthenticatedUserName, teamNames, pushNotification.RefUpdateResults.Where(r => r.Succeeded).Select(r => new GitRef(r))); notification.Add(pushRow); notification.TotalLineCount++; var refLookup = new Dictionary <Sha1Id, List <GitRef> >(); var deletedRefs = new List <GitRef>(); var oldCommits = new HashSet <TfsGitCommit>(new TfsGitObjectEqualityComparer()); var unknowns = new List <TfsGitRefUpdateResult>(); // Associate refs (branch, lightweight and annotated tag) with corresponding commit foreach (var refUpdateResult in pushNotification.RefUpdateResults.Where(r => r.Succeeded)) { var newObjectId = refUpdateResult.NewObjectId; TfsGitCommit commit = null; if (newObjectId.IsEmpty) { deletedRefs.Add(new GitRef(refUpdateResult)); continue; } TfsGitObject gitObject = repository.LookupObject(newObjectId); if (gitObject.ObjectType == WebApi.GitObjectType.Commit) { commit = gitObject as TfsGitCommit; } else if (gitObject.ObjectType == WebApi.GitObjectType.Tag) { var tag = (TfsGitTag)gitObject; commit = tag.TryResolveToCommit(); } if (commit != null) { List <GitRef> refs; if (!refLookup.TryGetValue(commit.ObjectId, out refs)) { refs = new List <GitRef>(); refLookup.Add(commit.ObjectId, refs); } refs.Add(new GitRef(refUpdateResult)); if (!pushNotification.IncludedCommits.Contains(commit.ObjectId)) { oldCommits.Add(commit); } } else { unknowns.Add(refUpdateResult); } } notification.TotalLineCount += pushNotification.IncludedCommits.Count() + oldCommits.Count + unknowns.Count; // Add new commits with refs var pushCommits = pushNotification.IncludedCommits.Select(commitId => (TfsGitCommit)repository.LookupObject(commitId)).OrderByDescending(c => c.GetCommitter().Time); foreach (var commit in pushCommits.TakeWhile(c => notification.Count < maxLines)) { notification.Add(CreateCommitRow(requestContext, commitService, repository, commit, CommitRowType.Commit, pushNotification, refLookup)); } // Add updated refs to old commits foreach (TfsGitCommit gitCommit in oldCommits.OrderByDescending(c => c.GetCommitter().Time).TakeWhile(c => notification.Count < maxLines)) { notification.Add(CreateCommitRow(requestContext, commitService, repository, gitCommit, CommitRowType.RefUpdate, pushNotification, refLookup)); } // Add deleted refs if any if (deletedRefs.Any() && notification.Count < maxLines) { notification.Add(new DeleteRow() { Refs = deletedRefs }); } // Add "unknown" refs foreach (var refUpdateResult in unknowns.TakeWhile(c => notification.Count < maxLines)) { var newObjectId = refUpdateResult.NewObjectId; TfsGitObject gitObject = repository.LookupObject(newObjectId); notification.Add(new RefUpdateRow() { NewObjectId = newObjectId, ObjectType = gitObject.ObjectType, Refs = new[] { new GitRef(refUpdateResult) } }); } yield return(notification); } }
protected override IEnumerable <INotification> CreateNotifications(IVssRequestContext requestContext, WorkItemChangedEvent ev, int maxLines) { var notifications = new List <INotification>(); var identityService = requestContext.GetService <TeamFoundationIdentityService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.ChangerSid); if (ev.CoreFields == null) { throw new TfsNotificationRelayException("ev.CoreFields is null"); } if (ev.CoreFields.StringFields == null) { throw new TfsNotificationRelayException("ev.CoreFields.StringFields is null"); } if (ev.CoreFields.IntegerFields == null) { throw new TfsNotificationRelayException("ev.CoreFields.IntegerFields is null"); } var typeField = ev.CoreFields.StringFields.SingleOrDefault(f => f.ReferenceName == "System.WorkItemType"); if (typeField == null) { throw new TfsNotificationRelayException("missing System.WorkItemType"); } string type = typeField.NewValue; var idField = ev.CoreFields.IntegerFields.Single(f => f.ReferenceName == "System.Id"); if (idField == null) { throw new TfsNotificationRelayException("missing System.Id"); } int id = idField.NewValue; var assignedToString = ev.CoreFields.StringFields.GetFieldValue("System.AssignedTo", f => f.NewValue); string assignedToUniqueName = null; string assignedTo = null; if (!string.IsNullOrEmpty(assignedToString)) { UserField assignedToField = null; if (UserField.TryParse(assignedToString, out assignedToField) && assignedToField.Identifier != Guid.Empty) { assignedTo = assignedToField.DisplayName; var assignedToIdentity = identityService.ReadIdentities(requestContext, new[] { assignedToField.Identifier }).First(); assignedToUniqueName = assignedToIdentity.UniqueName; } } var teamNames = GetUserTeamsByProjectUri(requestContext, ev.ProjectNodeId, identity.Descriptor).ToList(); var comment = ev.TextFields?.FirstOrDefault(f => f.ReferenceName == "System.History" && !string.IsNullOrEmpty(f.Value)); if (comment != null) { var commentNotification = new WorkItemCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName, WiUrl = ev.DisplayUrl, WiType = type, WiId = id, WiTitle = ev.WorkItemTitle, ProjectName = ev.PortfolioProject, AreaPath = ev.AreaPath, AssignedTo = assignedTo, AssignedToUniqueName = assignedToUniqueName, CommentHtml = comment.Value, Comment = TextHelper.HtmlToText(comment.Value), TeamNames = teamNames }; notifications.Add(commentNotification); } var changeNotification = new WorkItemChangedNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, IsNew = ev.ChangeType == ChangeTypes.New, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName, WiUrl = ev.DisplayUrl, WiType = type, WiId = id, WiTitle = ev.WorkItemTitle, ProjectName = ev.PortfolioProject, AreaPath = ev.AreaPath, IsStateChanged = ev.ChangedFields?.StringFields?.Any(f => f.ReferenceName == "System.State") ?? false, IsAssignmentChanged = ev.ChangedFields?.StringFields?.Any(f => f.ReferenceName == "System.AssignedTo") ?? false, State = ev.CoreFields.StringFields.GetFieldValue("System.State", f => f.NewValue), AssignedTo = assignedTo, AssignedToUniqueName = assignedToUniqueName, CoreFields = ev.CoreFields, ChangedFields = ev.ChangedFields, TeamNames = teamNames }; notifications.Add(changeNotification); return(notifications); }