コード例 #1
0
            public async Task <Result> Execute(GetReviewInfo query)
            {
                var pastRevisions = (
                    from r in _session.Query <ReviewRevision>()
                    where r.ReviewId == query._reviewId
                    orderby r.RevisionNumber
                    select new Revision {
                    Number = r.RevisionNumber, Head = r.HeadCommit, Base = r.BaseCommit
                }
                    ).ToArray();

                var project = await _api.Project(query._reviewId.ProjectId);

                var commentsTree = GetCommentsTree(query);

                var reviewStatus = await _query.Query(new GetReviewStatus(query._reviewId));

                var fileMatrix = await _query.Query(new GetFileMatrix(query._reviewId));

                var buildStatuses = await _api.GetBuildStatuses(query._reviewId.ProjectId, reviewStatus.CurrentHead);

                var commitStatus = await _query.Query(new GetCommitStatus(query._reviewId));

                var author = reviewStatus.Author;

                return(new Result
                {
                    FilesToReview = fileMatrix.FindFilesToReview(_currentUser.UserName).ToList(),
                    ReviewId = query._reviewId,
                    Title = reviewStatus.Title,
                    ProjectPath = $"{project.Namespace}/{project.Name}",
                    Description = reviewStatus.Description,
                    SourceBranch = reviewStatus.SourceBranch,
                    TargetBranch = reviewStatus.TargetBranch,
                    PastRevisions = pastRevisions,
                    HasProvisionalRevision = !reviewStatus.RevisionForCurrentHead,
                    HeadCommit = reviewStatus.CurrentHead,
                    BaseCommit = reviewStatus.CurrentBase,
                    HeadRevision = reviewStatus.RevisionForCurrentHead
                        ? new RevisionId.Selected(pastRevisions.Last().Number)
                        : (RevisionId) new RevisionId.Hash(reviewStatus.CurrentHead),
                    State = reviewStatus.MergeRequestState,
                    MergeStatus = reviewStatus.MergeStatus,
                    ReviewFinished = commitStatus.State == CommitStatusState.Success,
                    WebUrl = reviewStatus.WebUrl,
                    FileDiscussions = GetFileDiscussions(query, commentsTree),
                    ReviewDiscussions = GetReviewDiscussions(query, commentsTree),
                    Author = author,
                    FileMatrix = fileMatrix,
                    BuildStatuses = buildStatuses,
                    IsAuthor = reviewStatus.Author.Username == _currentUser.UserName
                });
            }
コード例 #2
0
        public async Task Handle(ReviewPublishedEvent @event)
        {
            var summary = await _query.Query(new GetReviewStatus(@event.ReviewId));

            var fileMatrix = await _query.Query(new GetFileMatrix(@event.ReviewId));

            (int reviewedAtLatestRevision, int unreviewedAtLatestRevision) = fileMatrix.CalculateStatistics();

            var body = $"{_currentUser.Name} posted review on this merge request.\n\n{reviewedAtLatestRevision} files reviewed in latest version, {unreviewedAtLatestRevision} yet to review.\n\n{summary.UnresolvedDiscussions} unresolved discussions\n\nSee full review [here]({_siteBase}/project/{@event.ReviewId.ProjectId}/review/{@event.ReviewId.ReviewId})";

            await _api.CreateNewMergeRequestNote(@event.ReviewId.ProjectId, @event.ReviewId.ReviewId, body);
        }
コード例 #3
0
            public async Task <object> Execute(GetCommitStatusInput query)
            {
                var fileMatrix = await _queryRunner.Query(new GetFileMatrix(query.ReviewId));

                var summary = await _queryRunner.Query(new GetReviewStatus(query.ReviewId));

                return(new
                {
                    Matrix = fileMatrix,
                    UnresolvedDiscussions = summary.UnresolvedDiscussions,
                    ResolvedDiscussions = summary.ResolvedDiscussions,
                    Discussions = summary.Discussions
                });
            }
コード例 #4
0
            public async Task <CommitStatus> Execute(GetCommitStatus query)
            {
                var cacheKey = CacheKey(query.ReviewId);

                var summary = await _queryRunner.Query(new GetReviewStatus(query.ReviewId));

                if (_cache.TryGetValue <CommitStatus>(cacheKey, out var cachedStatus) && cachedStatus.Commit == summary.CurrentHead)
                {
                    return(cachedStatus);
                }

                var fileMatrix = await _queryRunner.Query(new GetFileMatrix(query.ReviewId));

                var reviewFile = await GetReviewFiles(query, summary);

                var statusInput = new
                {
                    Matrix = fileMatrix,
                    UnresolvedDiscussions = summary.UnresolvedDiscussions,
                    ResolvedDiscussions   = summary.ResolvedDiscussions,
                    Discussions           = summary.Discussions
                };

                var commitStatus = new CommitStatus
                {
                    Commit    = summary.CurrentHead,
                    Name      = "Code review (CodeSaw)",
                    TargetUrl = $"{_siteBase}/project/{query.ReviewId.ProjectId}/review/{query.ReviewId.ReviewId}"
                };

                try
                {
                    var result = _node.ExecuteScriptFunction(reviewFile, "status", statusInput);

                    if (result is JObject obj && obj.Property("ok") != null && obj.Property("reasons") != null)
                    {
                        var isOk    = obj.Property("ok").Value.Value <bool>();
                        var reasons = obj.Property("reasons").Value.Values <string>();

                        commitStatus.State       = isOk ? CommitStatusState.Success : CommitStatusState.Pending;
                        commitStatus.Description = string.Join(", ", reasons);
                    }
                    else
                    {
                        commitStatus.State       = CommitStatusState.Failed;
                        commitStatus.Description = "Invalid review script output";
                    }
                }
コード例 #5
0
            public override async Task Handle(UserTicketCreated command)
            {
                var existingUser = await _queryRunner.Query(new FindUserByName(command.UserName));

                if (existingUser == null)
                {
                    await _session.SaveAsync(new ReviewUser
                    {
                        UserName  = command.UserName,
                        Name      = command.GivenName,
                        AvatarUrl = command.AvatarUrl,
                        Token     = command.AccessToken
                    });

                    Console.WriteLine("New user created");
                }
                else
                {
                    existingUser.Token     = command.AccessToken;
                    existingUser.Name      = command.GivenName;
                    existingUser.AvatarUrl = command.AvatarUrl;

                    await _session.UpdateAsync(existingUser);

                    Console.WriteLine($"Found existing user with ID {existingUser.Id}, token updated.");
                }
            }
コード例 #6
0
            public async Task <Result> Execute(GetReviewEmoji query)
            {
                var summary = await _queryRunner.Query(new GetReviewStatus(query.ReviewId));

                var fileMatrix = await _queryRunner.Query(new GetFileMatrix(query.ReviewId));

                var reviewFile = await GetReviewFiles(query, summary);

                var statusInput = new
                {
                    Matrix = fileMatrix,
                    summary.UnresolvedDiscussions,
                    summary.ResolvedDiscussions,
                    summary.Discussions
                };

                try
                {
                    var result = _node.ExecuteScriptFunction(reviewFile, "thumb", statusInput, _currentUser.UserName);

                    var numericResult = result.Value <int?>();

                    if (numericResult == 1)
                    {
                        return(Result.AddAndRemove(EmojiType.ThumbsUp, EmojiType.ThumbsDown));
                    }

                    if (numericResult == -1)
                    {
                        return(Result.AddAndRemove(EmojiType.ThumbsDown, EmojiType.ThumbsUp));
                    }

                    return(Result.Remove(EmojiType.ThumbsUp, EmojiType.ThumbsDown));
                }
                catch (NodeException e)
                {
                    Log.Warn(e, "Thumb script failed");
                }

                return(new Result()
                {
                    ToAdd = new EmojiType[0],
                    ToRemove = new EmojiType[0]
                });
            }
コード例 #7
0
        public HooksModule(IQueryRunner query, ICommandDispatcher command) : base("/api/admin")
        {
            Get("/projects", async _ => await query.Query(new GetProjects()));

            Post("/project/{projectId}/setup_hooks", async _ =>
            {
                await command.Execute(new SetupProjectHooks(_.projectId));
                return(new { ok = true });
            });
        }
コード例 #8
0
        private async Task Update(ReviewIdentifier reviewId)
        {
            var commitStatus = await _query.Query(new GetCommitStatus(reviewId));

            using (var innerScope = _scope.BeginLifetimeScope(UseGlobalAccessToken))
            {
                var api = innerScope.Resolve <IRepository>();

                await api.SetCommitStatus(reviewId.ProjectId, commitStatus);
            }
        }
コード例 #9
0
 public ReviewsModule(IQueryRunner query) : base("/api/reviews")
 {
     Get("/", async _ => await query.Query(new GetReviewList(new MergeRequestSearchArgs
     {
         State   = Request.Query.state,
         OrderBy = Request.Query.orderBy,
         Sort    = Request.Query.sort,
         Search  = Request.Query.search,
         Scope   = "all",
         Page    = Request.Query.page
     })));
 }
コード例 #10
0
        public async Task Handle(ReviewPublishedEvent @event)
        {
            var mergeRequest = await _api.GetMergeRequestInfo(@event.ReviewId.ProjectId, @event.ReviewId.ReviewId);

            if (mergeRequest.Author.Username == _user.UserName)
            {
                return;
            }

            var emoji = await _query.Query(new GetReviewEmoji(@event.ReviewId));

            await SetEmojiAward(@event, emoji.ToAdd, emoji.ToRemove);
        }
コード例 #11
0
        public ReviewInfoModule(IQueryRunner query, ICommandDispatcher command, FeatureToggle features) : base("/api/project/{projectId}/review/{reviewId}")
        {
            this.AddToLogContext(new Dictionary <string, Func <object> >
            {
                ["api.projectId"] = () => ReviewId.ProjectId,
                ["api.reviewId"]  = () => ReviewId.ReviewId
            });

            Get("/info", async _ => await query.Query(new GetReviewInfo(_.projectId, _.reviewId)));
            Get("/matrix", async _ => await query.Query(new GetFileMatrix(ReviewId)));

            if (features.For("DiffV3").IsActive)
            {
                Get("/diff/{previous_base}/{previous_head}/{current_base}/{current_head}",
                    async _ => await query.Query(new GetFileDiff_Line(
                                                     ReviewId,
                                                     new GetFileDiff_Line.HashSet
                {
                    PreviousBase = (string)_.previous_base,
                    PreviousHead = (string)_.previous_head,
                    CurrentBase  = (string)_.current_base,
                    CurrentHead  = (string)_.current_head,
                },
                                                     Request.Query.oldPath, Request.Query.newPath
                                                     )));
            }
            else
            {
                Get("/diff/{previous_base}/{previous_head}/{current_base}/{current_head}",
                    async _ => await query.Query(new GetFileDiff(
                                                     ReviewId,
                                                     new GetFileDiff.HashSet
                {
                    PreviousBase = (string)_.previous_base,
                    PreviousHead = (string)_.previous_head,
                    CurrentBase  = (string)_.current_base,
                    CurrentHead  = (string)_.current_head,
                },
                                                     Request.Query.oldPath, Request.Query.newPath
                                                     )));
            }

            Get("/discussions/{previous_base}/{previous_head}/{current_base}/{current_head}/{fileId}",
                async _ => await query.Query(new GetDiffDiscussions(
                                                 ReviewId,
                                                 new GetDiffDiscussions.HashSet
            {
                PreviousBase = (string)_.previous_base,
                PreviousHead = (string)_.previous_head,
                CurrentBase  = (string)_.current_base,
                CurrentHead  = (string)_.current_head,
            },
                                                 ClientFileId.Parse((string)_.fileId),
                                                 (string)Request.Query.fileName
                                                 )));

            Post("/publish", async _ =>
            {
                try
                {
                    await command.Execute(this.Bind <PublishReview>());
                    return(new
                    {
                        ok = true
                    });
                }
                catch (ReviewConcurrencyException)
                {
                    return(Response.AsJson(new { error = "review_concurrency" }, HttpStatusCode.Conflict));
                }
            });

            Post("/merge_request/merge", async _ =>
            {
                try
                {
                    await command.Execute(this.Bind <MergePullRequest>());
                    return(new { });
                }
                catch (MergeFailedException)
                {
                    return(Response.AsJson(new { error = "merge_failed" }, HttpStatusCode.ImATeapot));
                }
            });

            Get("/status", async _ => await query.Query(new GetReviewStatus(ReviewId)));

            Get("/commit_status_base", async _ => await query.Query(new GetCommitStatusInput(ReviewId)));

            Get("/emoji", async _ => await query.Query(new GetReviewEmoji(ReviewId)));
        }
コード例 #12
0
 public async Task <ReviewUser> FindByIdAsync(string userId, CancellationToken cancellationToken)
 {
     return(await _queries.Query(new FindUserById(userId)));
 }
コード例 #13
0
 public UserModule(IQueryRunner query) : base("/api/user")
 {
     Get("/current", async _ => await query.Query(new GetCurrentUser()));
 }