[PR] Recheck Unchecked PR Merge Status (#434)

This commit is contained in:
Johannes Batzill 2023-09-12 16:26:18 +00:00 committed by Harness
parent fd7ed1e496
commit 50b66d9342
11 changed files with 266 additions and 23 deletions

View File

@ -22,7 +22,7 @@ import (
"github.com/harness/gitness/internal/api/controller/pipeline" "github.com/harness/gitness/internal/api/controller/pipeline"
"github.com/harness/gitness/internal/api/controller/plugin" "github.com/harness/gitness/internal/api/controller/plugin"
"github.com/harness/gitness/internal/api/controller/principal" "github.com/harness/gitness/internal/api/controller/principal"
"github.com/harness/gitness/internal/api/controller/pullreq" pullreq2 "github.com/harness/gitness/internal/api/controller/pullreq"
"github.com/harness/gitness/internal/api/controller/repo" "github.com/harness/gitness/internal/api/controller/repo"
"github.com/harness/gitness/internal/api/controller/secret" "github.com/harness/gitness/internal/api/controller/secret"
"github.com/harness/gitness/internal/api/controller/service" "github.com/harness/gitness/internal/api/controller/service"
@ -51,7 +51,7 @@ import (
"github.com/harness/gitness/internal/services/codecomments" "github.com/harness/gitness/internal/services/codecomments"
"github.com/harness/gitness/internal/services/importer" "github.com/harness/gitness/internal/services/importer"
"github.com/harness/gitness/internal/services/job" "github.com/harness/gitness/internal/services/job"
pullreq2 "github.com/harness/gitness/internal/services/pullreq" "github.com/harness/gitness/internal/services/pullreq"
trigger2 "github.com/harness/gitness/internal/services/trigger" trigger2 "github.com/harness/gitness/internal/services/trigger"
"github.com/harness/gitness/internal/services/webhook" "github.com/harness/gitness/internal/services/webhook"
"github.com/harness/gitness/internal/store" "github.com/harness/gitness/internal/store"
@ -174,10 +174,6 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err return nil, err
} }
migrator := codecomments.ProvideMigrator(gitrpcInterface) migrator := codecomments.ProvideMigrator(gitrpcInterface)
pullreqController := pullreq.ProvideController(db, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, gitrpcInterface, reporter, mutexManager, migrator)
webhookConfig := server.ProvideWebhookConfig(config)
webhookStore := database.ProvideWebhookStore(db)
webhookExecutionStore := database.ProvideWebhookExecutionStore(db)
readerFactory, err := events4.ProvideReaderFactory(eventsSystem) readerFactory, err := events4.ProvideReaderFactory(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
@ -186,6 +182,16 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
repoGitInfoView := database.ProvideRepoGitInfoView(db)
repoGitInfoCache := cache.ProvideRepoGitInfoCache(repoGitInfoView)
pullreqService, err := pullreq.ProvideService(ctx, config, readerFactory, eventsReaderFactory, reporter, gitrpcInterface, db, repoGitInfoCache, repoStore, pullReqStore, pullReqActivityStore, codeCommentView, migrator, pubSub, provider)
if err != nil {
return nil, err
}
pullreqController := pullreq2.ProvideController(db, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, gitrpcInterface, reporter, mutexManager, migrator, pullreqService)
webhookConfig := server.ProvideWebhookConfig(config)
webhookStore := database.ProvideWebhookStore(db)
webhookExecutionStore := database.ProvideWebhookExecutionStore(db)
webhookService, err := webhook.ProvideService(ctx, webhookConfig, readerFactory, eventsReaderFactory, webhookStore, webhookExecutionStore, repoStore, pullReqStore, provider, principalStore, gitrpcInterface) webhookService, err := webhook.ProvideService(ctx, webhookConfig, readerFactory, eventsReaderFactory, webhookStore, webhookExecutionStore, repoStore, pullReqStore, provider, principalStore, gitrpcInterface)
if err != nil { if err != nil {
return nil, err return nil, err
@ -228,12 +234,6 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err return nil, err
} }
cronManager := cron.ProvideManager(serverConfig) cronManager := cron.ProvideManager(serverConfig)
repoGitInfoView := database.ProvideRepoGitInfoView(db)
repoGitInfoCache := cache.ProvideRepoGitInfoCache(repoGitInfoView)
pullreqService, err := pullreq2.ProvideService(ctx, config, readerFactory, eventsReaderFactory, reporter, gitrpcInterface, db, repoGitInfoCache, repoStore, pullReqStore, pullReqActivityStore, codeCommentView, migrator, pubSub, provider)
if err != nil {
return nil, err
}
triggerConfig := server.ProvideTriggerConfig(config) triggerConfig := server.ProvideTriggerConfig(config)
triggerService, err := trigger2.ProvideService(ctx, triggerConfig, triggerStore, commitService, pullReqStore, repoStore, pipelineStore, triggererTriggerer, readerFactory, eventsReaderFactory) triggerService, err := trigger2.ProvideService(ctx, triggerConfig, triggerStore, commitService, pullReqStore, repoStore, pipelineStore, triggererTriggerer, readerFactory, eventsReaderFactory)
if err != nil { if err != nil {

View File

@ -16,6 +16,7 @@ import (
"github.com/harness/gitness/internal/auth/authz" "github.com/harness/gitness/internal/auth/authz"
pullreqevents "github.com/harness/gitness/internal/events/pullreq" pullreqevents "github.com/harness/gitness/internal/events/pullreq"
"github.com/harness/gitness/internal/services/codecomments" "github.com/harness/gitness/internal/services/codecomments"
"github.com/harness/gitness/internal/services/pullreq"
"github.com/harness/gitness/internal/store" "github.com/harness/gitness/internal/store"
"github.com/harness/gitness/internal/url" "github.com/harness/gitness/internal/url"
"github.com/harness/gitness/lock" "github.com/harness/gitness/lock"
@ -40,6 +41,7 @@ type Controller struct {
eventReporter *pullreqevents.Reporter eventReporter *pullreqevents.Reporter
mtxManager lock.MutexManager mtxManager lock.MutexManager
codeCommentMigrator *codecomments.Migrator codeCommentMigrator *codecomments.Migrator
pullreqService *pullreq.Service
} }
func NewController( func NewController(
@ -57,6 +59,7 @@ func NewController(
eventReporter *pullreqevents.Reporter, eventReporter *pullreqevents.Reporter,
mtxManager lock.MutexManager, mtxManager lock.MutexManager,
codeCommentMigrator *codecomments.Migrator, codeCommentMigrator *codecomments.Migrator,
pullreqService *pullreq.Service,
) *Controller { ) *Controller {
return &Controller{ return &Controller{
db: db, db: db,
@ -73,6 +76,7 @@ func NewController(
codeCommentMigrator: codeCommentMigrator, codeCommentMigrator: codeCommentMigrator,
eventReporter: eventReporter, eventReporter: eventReporter,
mtxManager: mtxManager, mtxManager: mtxManager,
pullreqService: pullreqService,
} }
} }

View File

@ -0,0 +1,33 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package pullreq
import (
"context"
"fmt"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/types/enum"
)
// Recheck re-checks all system PR checks (mergeability check, ...).
func (c *Controller) Recheck(
ctx context.Context,
session *auth.Session,
repoRef string,
prNum int64,
) error {
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush)
if err != nil {
return fmt.Errorf("failed to acquire access to repo: %w", err)
}
err = c.pullreqService.UpdateMergeDataIfRequired(ctx, repo.ID, prNum)
if err != nil {
return fmt.Errorf("failed to refresh merge data: %w", err)
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"github.com/harness/gitness/internal/auth/authz" "github.com/harness/gitness/internal/auth/authz"
pullreqevents "github.com/harness/gitness/internal/events/pullreq" pullreqevents "github.com/harness/gitness/internal/events/pullreq"
"github.com/harness/gitness/internal/services/codecomments" "github.com/harness/gitness/internal/services/codecomments"
"github.com/harness/gitness/internal/services/pullreq"
"github.com/harness/gitness/internal/store" "github.com/harness/gitness/internal/store"
"github.com/harness/gitness/internal/url" "github.com/harness/gitness/internal/url"
"github.com/harness/gitness/lock" "github.com/harness/gitness/lock"
@ -28,12 +29,14 @@ func ProvideController(db *sqlx.DB, urlProvider *url.Provider, authorizer authz.
pullReqReviewStore store.PullReqReviewStore, pullReqReviewerStore store.PullReqReviewerStore, pullReqReviewStore store.PullReqReviewStore, pullReqReviewerStore store.PullReqReviewerStore,
repoStore store.RepoStore, principalStore store.PrincipalStore, repoStore store.RepoStore, principalStore store.PrincipalStore,
rpcClient gitrpc.Interface, eventReporter *pullreqevents.Reporter, rpcClient gitrpc.Interface, eventReporter *pullreqevents.Reporter,
mtxManager lock.MutexManager, codeCommentMigrator *codecomments.Migrator) *Controller { mtxManager lock.MutexManager, codeCommentMigrator *codecomments.Migrator,
pullreqService *pullreq.Service,
) *Controller {
return NewController(db, urlProvider, authorizer, return NewController(db, urlProvider, authorizer,
pullReqStore, pullReqActivityStore, pullReqStore, pullReqActivityStore,
codeCommentsView, codeCommentsView,
pullReqReviewStore, pullReqReviewerStore, pullReqReviewStore, pullReqReviewerStore,
repoStore, principalStore, repoStore, principalStore,
rpcClient, eventReporter, rpcClient, eventReporter,
mtxManager, codeCommentMigrator) mtxManager, codeCommentMigrator, pullreqService)
} }

View File

@ -0,0 +1,41 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package pullreq
import (
"net/http"
"github.com/harness/gitness/internal/api/controller/pullreq"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
// HandleRecheck handles API that re-checks all system PR checks (mergeability check, ...).
func HandleRecheck(pullreqCtrl *pullreq.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
repoRef, err := request.GetRepoRefFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
pullreqNumber, err := request.GetPullReqNumberFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
err = pullreqCtrl.Recheck(ctx, session, repoRef, pullreqNumber)
if err != nil {
render.TranslatedUserError(w, err)
return
}
w.WriteHeader(http.StatusNoContent)
}
}

View File

@ -469,4 +469,15 @@ func pullReqOperations(reflector *openapi3.Reflector) {
_ = reflector.SetJSONResponse(&opMetaData, new(usererror.Error), http.StatusForbidden) _ = reflector.SetJSONResponse(&opMetaData, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&opMetaData, new(usererror.Error), http.StatusNotFound) _ = reflector.SetJSONResponse(&opMetaData, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/pullreq/{pullreq_number}/metadata", opMetaData) _ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/pullreq/{pullreq_number}/metadata", opMetaData)
recheckPullReq := openapi3.Operation{}
recheckPullReq.WithTags("pullreq")
recheckPullReq.WithMapOfAnything(map[string]interface{}{"operationId": "recheckPullReq"})
_ = reflector.SetRequest(&recheckPullReq, nil, http.MethodPost)
_ = reflector.SetJSONResponse(&recheckPullReq, nil, http.StatusNoContent)
_ = reflector.SetJSONResponse(&recheckPullReq, new(usererror.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&recheckPullReq, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&recheckPullReq, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&recheckPullReq, new(usererror.Error), http.StatusForbidden)
_ = reflector.Spec.AddOperation(http.MethodPost, "/repos/{repo_ref}/pullreq/{pullreq_number}/recheck", recheckPullReq)
} }

View File

@ -461,6 +461,7 @@ func SetupPullReq(r chi.Router, pullreqCtrl *pullreq.Controller) {
r.Get("/", handlerpullreq.HandleFind(pullreqCtrl)) r.Get("/", handlerpullreq.HandleFind(pullreqCtrl))
r.Patch("/", handlerpullreq.HandleUpdate(pullreqCtrl)) r.Patch("/", handlerpullreq.HandleUpdate(pullreqCtrl))
r.Post("/state", handlerpullreq.HandleState(pullreqCtrl)) r.Post("/state", handlerpullreq.HandleState(pullreqCtrl))
r.Post("/recheck", handlerpullreq.HandleRecheck(pullreqCtrl))
r.Get("/activities", handlerpullreq.HandleListActivities(pullreqCtrl)) r.Get("/activities", handlerpullreq.HandleListActivities(pullreqCtrl))
r.Route("/comments", func(r chi.Router) { r.Route("/comments", func(r chi.Router) {
r.Post("/", handlerpullreq.HandleCommentCreate(pullreqCtrl)) r.Post("/", handlerpullreq.HandleCommentCreate(pullreqCtrl))

View File

@ -106,6 +106,28 @@ func (s *Service) deleteMergeRef(ctx context.Context, repoID int64, prNum int64)
return nil return nil
} }
// UpdateMergeDataIfRequired rechecks the merge data of a PR.
// TODO: This is a temporary solution - doesn't fix changed merge-base or other things.
func (s *Service) UpdateMergeDataIfRequired(
ctx context.Context,
repoID int64,
prNum int64,
) error {
pr, err := s.pullreqStore.FindByNumber(ctx, repoID, prNum)
if err != nil {
return fmt.Errorf("failed to get pull request number %d: %w", prNum, err)
}
// nothing to-do if check was already performed
if pr.MergeCheckStatus != enum.MergeCheckStatusUnchecked {
return nil
}
// WARNING: This CAN lead to two (or more) merge-checks on the same SHA
// running on different machines at the same time.
return s.updateMergeDataInner(ctx, pr, "", pr.SourceSHA)
}
//nolint:funlen // refactor if required. //nolint:funlen // refactor if required.
func (s *Service) updateMergeData( func (s *Service) updateMergeData(
ctx context.Context, ctx context.Context,
@ -114,21 +136,31 @@ func (s *Service) updateMergeData(
oldSHA string, oldSHA string,
newSHA string, newSHA string,
) error { ) error {
// TODO: Merge check should not update the merge base.
// TODO: Instead it should accept it as an argument and fail if it doesn't match.
// Then is would not longer be necessary to cancel already active mergeability checks.
pr, err := s.pullreqStore.FindByNumber(ctx, repoID, prNum) pr, err := s.pullreqStore.FindByNumber(ctx, repoID, prNum)
if err != nil { if err != nil {
return fmt.Errorf("failed to get pull request number %d: %w", prNum, err) return fmt.Errorf("failed to get pull request number %d: %w", prNum, err)
} }
return s.updateMergeDataInner(ctx, pr, oldSHA, newSHA)
}
//nolint:funlen // refactor if required.
func (s *Service) updateMergeDataInner(
ctx context.Context,
pr *types.PullReq,
oldSHA string,
newSHA string,
) error {
// TODO: Merge check should not update the merge base.
// TODO: Instead it should accept it as an argument and fail if it doesn't match.
// Then is would not longer be necessary to cancel already active mergeability checks.
if pr.State != enum.PullReqStateOpen { if pr.State != enum.PullReqStateOpen {
return fmt.Errorf("cannot do mergability check on closed PR %d", prNum) return fmt.Errorf("cannot do mergability check on closed PR %d", pr.Number)
} }
// cancel all previous mergability work for this PR based on oldSHA // cancel all previous mergability work for this PR based on oldSHA
if err = s.pubsub.Publish(ctx, cancelMergeCheckKey, []byte(oldSHA), if err := s.pubsub.Publish(ctx, cancelMergeCheckKey, []byte(oldSHA),
pubsub.WithPublishNamespace("pullreq")); err != nil { pubsub.WithPublishNamespace("pullreq")); err != nil {
return err return err
} }
@ -137,6 +169,13 @@ func (s *Service) updateMergeData(
ctx, cancel = context.WithCancel(ctx) ctx, cancel = context.WithCancel(ctx)
s.cancelMutex.Lock() s.cancelMutex.Lock()
// NOTE: Temporary workaround to avoid overwriting existing cancel method on same machine.
// This doesn't avoid same SHA running on multiple machines
if _, ok := s.cancelMergeability[newSHA]; ok {
s.cancelMutex.Unlock()
cancel()
return nil
}
s.cancelMergeability[newSHA] = cancel s.cancelMergeability[newSHA] = cancel
s.cancelMutex.Unlock() s.cancelMutex.Unlock()
@ -175,7 +214,7 @@ func (s *Service) updateMergeData(
HeadRepoUID: sourceRepo.GitUID, HeadRepoUID: sourceRepo.GitUID,
HeadBranch: pr.SourceBranch, HeadBranch: pr.SourceBranch,
RefType: gitrpcenum.RefTypePullReqMerge, RefType: gitrpcenum.RefTypePullReqMerge,
RefName: strconv.Itoa(int(prNum)), RefName: strconv.Itoa(int(pr.Number)),
HeadExpectedSHA: newSHA, HeadExpectedSHA: newSHA,
Force: true, Force: true,

View File

@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react' import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { Container, Layout, PageBody, Tabs, Text } from '@harnessio/uicore' import { Container, Layout, PageBody, Tabs, Text } from '@harnessio/uicore'
import { FontVariation } from '@harnessio/design-system' import { FontVariation } from '@harnessio/design-system'
import { useGet } from 'restful-react' import { useGet, useMutate } from 'restful-react'
import { Render } from 'react-jsx-match' import { Render } from 'react-jsx-match'
import { useHistory } from 'react-router-dom' import { useHistory } from 'react-router-dom'
import { compact } from 'lodash-es' import { compact } from 'lodash-es'
@ -9,7 +9,7 @@ import { useAppContext } from 'AppContext'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata' import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { useStrings } from 'framework/strings' import { useStrings } from 'framework/strings'
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader' import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
import { voidFn, getErrorMessage, PullRequestSection } from 'utils/Utils' import { voidFn, getErrorMessage, PullRequestSection, MergeCheckStatus } from 'utils/Utils'
import { CodeIcon } from 'utils/GitUtils' import { CodeIcon } from 'utils/GitUtils'
import type { TypesPullReq, TypesPullReqStats, TypesRepository } from 'services/code' import type { TypesPullReq, TypesPullReqStats, TypesRepository } from 'services/code'
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner' import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
@ -83,6 +83,14 @@ export default function PullRequest() {
}) })
) )
}, [history, routes, repoMetadata?.path, pullRequestId]) }, [history, routes, repoMetadata?.path, pullRequestId])
const recheckPath = useMemo(
() => `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullRequestId}/recheck`,
[repoMetadata?.path, pullRequestId]
)
const { mutate : recheckPR, loading: loadingRecheckPR } = useMutate({
verb: 'POST',
path: recheckPath,
})
useEffect( useEffect(
function setStatsIfNotSet() { function setStatsIfNotSet() {
@ -98,6 +106,27 @@ export default function PullRequest() {
useEffect( useEffect(
function setPrDataIfNotSet() { function setPrDataIfNotSet() {
if (pullRequestData) { if (pullRequestData) {
// recheck pr (merge-check, ...) in case it's unavailable
// Approximation of identifying target branch update:
// 1. branch got updated before page was loaded (status is unchecked and prData is empty)
// NOTE: This doesn't guarantee the status is UNCHECKED due to target branch update and can cause duplicate
// PR merge checks being run on PR creation or source branch update.
// 2. branch got updated while we are on the page (same source_sha but status changed to UNCHECKED)
// NOTE: This doesn't cover the case in which the status changed back to UNCHECKED before the PR is refetched.
// In that case, the user will have to re-open the PR - better than us spamming the backend with rechecks.
// This is a TEMPORARY SOLUTION and will most likely change in the future (more so on backend side)
if (pullRequestData.state == 'open' &&
pullRequestData.merge_check_status == MergeCheckStatus.UNCHECKED &&
(
// case 1:
!prData ||
// case 2:
(prData?.merge_check_status != MergeCheckStatus.UNCHECKED && prData?.source_sha == pullRequestData.source_sha)
) && !loadingRecheckPR) {
// best effort attempt to recheck PR - fail silently
recheckPR({})
}
setPrData(pullRequestData) setPrData(pullRequestData)
} }
}, },

View File

@ -3398,6 +3398,40 @@ export const usePullReqMetaData = ({ repo_ref, pullreq_number, ...props }: UsePu
{ base: getConfig('code/api/v1'), pathParams: { repo_ref, pullreq_number }, ...props } { base: getConfig('code/api/v1'), pathParams: { repo_ref, pullreq_number }, ...props }
) )
export interface RecheckPullReqPathParams {
repo_ref: string
pullreq_number: number
}
export type RecheckPullReqProps = Omit<
MutateProps<void, UsererrorError, void, OpenapiUpdatePullReqRequest, RecheckPullReqPathParams>,
'path' | 'verb'
> &
RecheckPullReqPathParams
export const RecheckPullReq = ({ repo_ref, pullreq_number, ...props }: RecheckPullReqProps) => (
<Mutate<void, UsererrorError, void, OpenapiUpdatePullReqRequest, RecheckPullReqPathParams>
verb="POST"
path={`/repos/${repo_ref}/pullreq/${pullreq_number}/recheck`}
base={getConfig('code/api/v1')}
{...props}
/>
)
export type UseRecheckPullReqProps = Omit<
UseMutateProps<void, UsererrorError, void, OpenapiUpdatePullReqRequest, RecheckPullReqPathParams>,
'path' | 'verb'
> &
RecheckPullReqPathParams
export const useRecheckPullReq = ({ repo_ref, pullreq_number, ...props }: UseRecheckPullReqProps) =>
useMutate<void, UsererrorError, void, OpenapiUpdatePullReqRequest, RecheckPullReqPathParams>(
'POST',
(paramsInPath: RecheckPullReqPathParams) =>
`/repos/${paramsInPath.repo_ref}/pullreq/${paramsInPath.pullreq_number}/recheck`,
{ base: getConfig('code/api/v1'), pathParams: { repo_ref, pullreq_number }, ...props }
)
export interface ReviewerListPullReqPathParams { export interface ReviewerListPullReqPathParams {
repo_ref: string repo_ref: string
pullreq_number: number pullreq_number: number

View File

@ -3622,6 +3622,54 @@ paths:
description: Internal Server Error description: Internal Server Error
tags: tags:
- pullreq - pullreq
/repos/{repo_ref}/pullreq/{pullreq_number}/recheck:
post:
operationId: recheckPullReq
parameters:
- in: path
name: repo_ref
required: true
schema:
type: string
- in: path
name: pullreq_number
required: true
schema:
type: integer
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiUpdatePullReqRequest'
responses:
"204":
description: No Content
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/UsererrorError'
description: Bad Request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/UsererrorError'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/UsererrorError'
description: Forbidden
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/UsererrorError'
description: Internal Server Error
tags:
- pullreq
/repos/{repo_ref}/pullreq/{pullreq_number}/reviewers: /repos/{repo_ref}/pullreq/{pullreq_number}/reviewers:
get: get:
operationId: reviewerListPullReq operationId: reviewerListPullReq