feat(webhook): add support for webhook PRs (#8435)
* feat: pr webhook
* feat: pr webhook
* feat: finish PR Webhook and Frontend Updates
* fix: cleanup and comments
* fix: go deps
* fix: base_repo_id static for webhook
fix: ui
diff --git a/backend/go.mod b/backend/go.mod
index 6a43821..7dd96bc 100644
--- a/backend/go.mod
+++ b/backend/go.mod
@@ -9,7 +9,7 @@
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-git/go-git/v5 v5.12.0
github.com/go-playground/validator/v10 v10.19.0
- github.com/gocarina/gocsv v0.0.0-20220707092902-b9da1f06c77e
+ github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1
github.com/google/uuid v1.3.0
github.com/jackc/pgx/v5 v5.6.0 // indirect
github.com/lib/pq v1.10.2
@@ -127,4 +127,6 @@
golang.org/x/mod v0.17.0
)
+replace github.com/chenzhuoyu/iasm => github.com/cloudwego/iasm v0.2.0
+
//replace github.com/apache/incubator-devlake => ./
diff --git a/backend/go.sum b/backend/go.sum
index dc22ad7..0e44f0c 100644
--- a/backend/go.sum
+++ b/backend/go.sum
@@ -80,6 +80,7 @@
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -178,6 +179,8 @@
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gocarina/gocsv v0.0.0-20220707092902-b9da1f06c77e h1:GMIV+S6grz+vlIaUsP+fedQ6L+FovyMPMY26WO8dwQE=
github.com/gocarina/gocsv v0.0.0-20220707092902-b9da1f06c77e/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
+github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ=
+github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
diff --git a/backend/plugins/webhook/api/blueprint_v200.go b/backend/plugins/webhook/api/blueprint_v200.go
index eaa6be3..6dca8ff 100644
--- a/backend/plugins/webhook/api/blueprint_v200.go
+++ b/backend/plugins/webhook/api/blueprint_v200.go
@@ -23,6 +23,7 @@
"github.com/apache/incubator-devlake/core/errors"
coreModels "github.com/apache/incubator-devlake/core/models"
"github.com/apache/incubator-devlake/core/models/domainlayer"
+ "github.com/apache/incubator-devlake/core/models/domainlayer/code"
"github.com/apache/incubator-devlake/core/models/domainlayer/devops"
"github.com/apache/incubator-devlake/core/models/domainlayer/ticket"
"github.com/apache/incubator-devlake/core/plugin"
@@ -54,5 +55,13 @@
Name: connection.Name,
})
+ // add repos to scopes
+ scopes = append(scopes, &code.Repo{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: fmt.Sprintf("%s:%d", "webhook", connection.ID),
+ },
+ Name: connection.Name,
+ })
+
return nil, scopes, nil
}
diff --git a/backend/plugins/webhook/api/connection.go b/backend/plugins/webhook/api/connection.go
index 89ca884..16f027d 100644
--- a/backend/plugins/webhook/api/connection.go
+++ b/backend/plugins/webhook/api/connection.go
@@ -184,6 +184,7 @@
models.WebhookConnection
PostIssuesEndpoint string `json:"postIssuesEndpoint"`
CloseIssuesEndpoint string `json:"closeIssuesEndpoint"`
+ PostPullRequestsEndpoint string `json:"postPullRequestsEndpoint"`
PostPipelineTaskEndpoint string `json:"postPipelineTaskEndpoint"`
PostPipelineDeployTaskEndpoint string `json:"postPipelineDeployTaskEndpoint"`
ClosePipelineEndpoint string `json:"closePipelineEndpoint"`
@@ -256,6 +257,7 @@
response := &WebhookConnectionResponse{WebhookConnection: *connection}
response.PostIssuesEndpoint = fmt.Sprintf(`/rest/plugins/webhook/connections/%d/issues`, connection.ID)
response.CloseIssuesEndpoint = fmt.Sprintf(`/rest/plugins/webhook/connections/%d/issue/:issueKey/close`, connection.ID)
+ response.PostPullRequestsEndpoint = fmt.Sprintf(`/rest/plugins/webhook/connections/%d/pull_requests`, connection.ID)
response.PostPipelineTaskEndpoint = fmt.Sprintf(`/rest/plugins/webhook/connections/%d/cicd_tasks`, connection.ID)
response.PostPipelineDeployTaskEndpoint = fmt.Sprintf(`/rest/plugins/webhook/connections/%d/deployments`, connection.ID)
response.ClosePipelineEndpoint = fmt.Sprintf(`/rest/plugins/webhook/connections/%d/cicd_pipeline/:pipelineName/finish`, connection.ID)
diff --git a/backend/plugins/webhook/api/pull_requests.go b/backend/plugins/webhook/api/pull_requests.go
new file mode 100644
index 0000000..a01bb6c
--- /dev/null
+++ b/backend/plugins/webhook/api/pull_requests.go
@@ -0,0 +1,176 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package api
+
+import (
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/apache/incubator-devlake/core/dal"
+ "github.com/apache/incubator-devlake/core/log"
+
+ "github.com/apache/incubator-devlake/helpers/dbhelper"
+ "github.com/go-playground/validator/v10"
+
+ "github.com/apache/incubator-devlake/core/errors"
+ "github.com/apache/incubator-devlake/core/models/domainlayer"
+ "github.com/apache/incubator-devlake/core/models/domainlayer/code"
+ "github.com/apache/incubator-devlake/core/plugin"
+ "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+ "github.com/apache/incubator-devlake/plugins/webhook/models"
+)
+
+type WebhookPullRequestReq struct {
+ Id string `mapstructure:"id" validate:"required"`
+ BaseRepoId string `mapstructure:"baseRepoId"`
+ HeadRepoId string `mapstructure:"headRepoId"`
+ Status string `mapstructure:"status" validate:"omitempty,oneof=OPEN CLOSED MERGED"`
+ OriginalStatus string `mapstructure:"originalStatus"`
+ Title string `mapstructure:"displayTitle" validate:"required"`
+ Description string `mapstructure:"description"`
+ Url string `mapstructure:"url"`
+ AuthorName string `mapstructure:"authorName"`
+ AuthorId string `mapstructure:"authorId"`
+ MergedByName string `mapstructure:"mergedByName"`
+ MergedById string `mapstructure:"mergedById"`
+ ParentPrId string `mapstructure:"parentPrId"`
+ PullRequestKey int `mapstructure:"pullRequestKey" validate:"required"`
+ CreatedDate time.Time `mapstructure:"createdDate" validate:"required"`
+ MergedDate *time.Time `mapstructure:"mergedDate"`
+ ClosedDate *time.Time `mapstructure:"closedDate"`
+ Type string `mapstructure:"type"`
+ Component string `mapstructure:"component"`
+ MergeCommitSha string `mapstructure:"mergeCommitSha"`
+ HeadRef string `mapstructure:"headRef"`
+ BaseRef string `mapstructure:"baseRef"`
+ BaseCommitSha string `mapstructure:"baseCommitSha"`
+ HeadCommitSha string `mapstructure:"headCommitSha"`
+ Additions int `mapstructure:"additions"`
+ Deletions int `mapstructure:"deletions"`
+ IsDraft bool `mapstructure:"isDraft"`
+}
+
+// PostPullRequests
+// @Summary create pull requests by webhook
+// @Description Create pull request by webhook.<br/>
+// @Description example1: {"id": "pr1","baseRepoId": "webhook:1","headRepoId": "repo_fork1","status": "MERGED","originalStatus": "OPEN","displayTitle": "Feature: Add new functionality","description": "This PR adds new features","url": "https://github.com/org/repo/pull/1","authorName": "johndoe","authorId": "johnd123","mergedByName": "janedoe","mergedById": "janed123","parentPrId": "","pullRequestKey": 1,"createdDate": "2025-02-20T16:17:36Z","mergedDate": "2025-02-20T17:17:36Z","closedDate": null,"type": "feature","component": "backend","mergeCommitSha": "bf0a79c57dff8f5f1f393de315ee5105a535e059","headRef": "repo_fork1:feature-branch","baseRef": "main","baseCommitSha": "e73325c2c9863f42ea25871cbfaeebcb8edcf604","headCommitSha": "b22f772f1197edfafd4cc5fe679a2d299ec12837","additions": 100,"deletions": 50,"isDraft": false}<br/>
+// @Description "baseRepoId" must be equal to "webhook:{connectionId}" for this to work correctly and calculate DORA metrics
+// @Tags plugins/webhook
+// @Param body body WebhookPullRequestReq true "json body"
+// @Success 200
+// @Failure 400 {string} errcode.Error "Bad Request"
+// @Failure 403 {string} errcode.Error "Forbidden"
+// @Failure 500 {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/connections/:connectionId/pullrequests [POST]
+func PostPullRequests(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
+ connection := &models.WebhookConnection{}
+ err := connectionHelper.First(connection, input.Params)
+
+ return postPullRequests(input, connection, err)
+}
+
+// PostPullRequestsByName
+// @Summary create pull requests by webhook name
+// @Description Create pull request by webhook name.<br/>
+// @Description example1: {"id": "pr1","baseRepoId": "webhook:1","headRepoId": "repo_fork1","status": "MERGED","originalStatus": "OPEN","displayTitle": "Feature: Add new functionality","description": "This PR adds new features","url": "https://github.com/org/repo/pull/1","authorName": "johndoe","authorId": "johnd123","mergedByName": "janedoe","mergedById": "janed123","parentPrId": "","pullRequestKey": 1,"createdDate": "2025-02-20T16:17:36Z","mergedDate": "2025-02-20T17:17:36Z","closedDate": null,"type": "feature","component": "backend","mergeCommitSha": "bf0a79c57dff8f5f1f393de315ee5105a535e059","headRef": "repo_fork1:feature-branch","baseRef": "main","baseCommitSha": "e73325c2c9863f42ea25871cbfaeebcb8edcf604","headCommitSha": "b22f772f1197edfafd4cc5fe679a2d299ec12837","additions": 100,"deletions": 50,"isDraft": false}<br/>
+// @Description "baseRepoId" must be equal to "webhook:{connectionId}" for this to work correctly and calculate DORA metrics
+// @Tags plugins/webhook
+// @Param body body WebhookPullRequestReq true "json body"
+// @Success 200
+// @Failure 400 {string} errcode.Error "Bad Request"
+// @Failure 403 {string} errcode.Error "Forbidden"
+// @Failure 500 {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/connections/by-name/:connectionName/pullrequests [POST]
+func PostPullRequestsByName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
+ connection := &models.WebhookConnection{}
+ err := connectionHelper.FirstByName(connection, input.Params)
+
+ return postPullRequests(input, connection, err)
+}
+
+func postPullRequests(input *plugin.ApiResourceInput, connection *models.WebhookConnection, err errors.Error) (*plugin.ApiResourceOutput, errors.Error) {
+ if err != nil {
+ return nil, err
+ }
+ // get request
+ request := &WebhookPullRequestReq{}
+ err = api.DecodeMapStruct(input.Body, request, true)
+ if err != nil {
+ return &plugin.ApiResourceOutput{Body: err.Error(), Status: http.StatusBadRequest}, nil
+ }
+ // validate
+ vld = validator.New()
+ err = errors.Convert(vld.Struct(request))
+ if err != nil {
+ return nil, errors.BadInput.Wrap(vld.Struct(request), `input json error`)
+ }
+ txHelper := dbhelper.NewTxHelper(basicRes, &err)
+ defer txHelper.End()
+ tx := txHelper.Begin()
+ if err := CreatePullRequest(connection, request, tx, logger); err != nil {
+ logger.Error(err, "create pull requests")
+ return nil, err
+ }
+
+ return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil
+}
+
+func CreatePullRequest(connection *models.WebhookConnection, request *WebhookPullRequestReq, tx dal.Transaction, logger log.Logger) errors.Error {
+ // validation
+ if request == nil {
+ return errors.BadInput.New("request body is nil")
+ }
+ // create a pull_request record
+ pullRequest := &code.PullRequest{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: fmt.Sprintf("%s:%d:%d", "webhook", connection.ID, request.PullRequestKey),
+ },
+ BaseRepoId: fmt.Sprintf("%s:%d", "webhook", connection.ID),
+ HeadRepoId: request.HeadRepoId,
+ Status: request.Status,
+ OriginalStatus: request.OriginalStatus,
+ Title: request.Title,
+ Description: request.Description,
+ Url: request.Url,
+ AuthorName: request.AuthorName,
+ AuthorId: request.AuthorId,
+ MergedByName: request.MergedByName,
+ MergedById: request.MergedById,
+ ParentPrId: request.ParentPrId,
+ PullRequestKey: request.PullRequestKey,
+ CreatedDate: request.CreatedDate,
+ MergedDate: request.MergedDate,
+ ClosedDate: request.ClosedDate,
+ Type: request.Type,
+ Component: request.Component,
+ MergeCommitSha: request.MergeCommitSha,
+ HeadRef: request.HeadRef,
+ BaseRef: request.BaseRef,
+ BaseCommitSha: request.BaseCommitSha,
+ HeadCommitSha: request.HeadCommitSha,
+ Additions: request.Additions,
+ Deletions: request.Deletions,
+ IsDraft: request.IsDraft,
+ }
+ if err := tx.CreateOrUpdate(pullRequest); err != nil {
+ logger.Error(err, "failed to save pull request")
+ return err
+ }
+ return nil
+}
diff --git a/backend/plugins/webhook/impl/impl.go b/backend/plugins/webhook/impl/impl.go
index c0d2e70..b969180 100644
--- a/backend/plugins/webhook/impl/impl.go
+++ b/backend/plugins/webhook/impl/impl.go
@@ -95,6 +95,9 @@
"connections/:connectionId/deployments": {
"POST": api.PostDeployments,
},
+ "connections/:connectionId/pull_requests": {
+ "POST": api.PostPullRequests,
+ },
"connections/:connectionId/issues": {
"POST": api.PostIssue,
},
@@ -104,6 +107,9 @@
":connectionId/deployments": {
"POST": api.PostDeployments,
},
+ ":connectionId/pull_requests": {
+ "POST": api.PostPullRequests,
+ },
":connectionId/issues": {
"POST": api.PostIssue,
},
@@ -118,6 +124,9 @@
"connections/by-name/:connectionName/deployments": {
"POST": api.PostDeploymentsByName,
},
+ "connections/by-name/:connectionName/pull_requests": {
+ "POST": api.PostPullRequestsByName,
+ },
"connections/by-name/:connectionName/issues": {
"POST": api.PostIssueByName,
},
diff --git a/config-ui/src/features/connections/utils.ts b/config-ui/src/features/connections/utils.ts
index 781fb4f..e64e32d 100644
--- a/config-ui/src/features/connections/utils.ts
+++ b/config-ui/src/features/connections/utils.ts
@@ -50,6 +50,7 @@
postIssuesEndpoint: connection.postIssuesEndpoint,
closeIssuesEndpoint: connection.closeIssuesEndpoint,
postPipelineDeployTaskEndpoint: connection.postPipelineDeployTaskEndpoint,
+ postPullRequestsEndpoint: connection.postPullRequestsEndpoint,
apiKeyId: connection.apiKey.id,
};
};
diff --git a/config-ui/src/plugins/register/webhook/components/create-dialog.tsx b/config-ui/src/plugins/register/webhook/components/create-dialog.tsx
index 54ec50a..47f861b 100644
--- a/config-ui/src/plugins/register/webhook/components/create-dialog.tsx
+++ b/config-ui/src/plugins/register/webhook/components/create-dialog.tsx
@@ -44,6 +44,7 @@
postIssuesEndpoint: '',
closeIssuesEndpoint: '',
postDeploymentsCurl: '',
+ postPullRequestsEndpoint: '',
apiKey: '',
});
@@ -55,7 +56,7 @@
const [success, res] = await operator(
async () => {
const {
- webhook: { id, postIssuesEndpoint, closeIssuesEndpoint, postPipelineDeployTaskEndpoint },
+ webhook: { id, postIssuesEndpoint, closeIssuesEndpoint, postPipelineDeployTaskEndpoint, postPullRequestsEndpoint },
apiKey,
} = await dispatch(addWebhook({ name })).unwrap();
@@ -65,6 +66,7 @@
postIssuesEndpoint,
closeIssuesEndpoint,
postPipelineDeployTaskEndpoint,
+ postPullRequestsEndpoint,
};
},
{
@@ -151,6 +153,17 @@
.
</p>
</Block>
+ <Block title="Pull Requests">
+ <h5>Post to register a pull request</h5>
+ <CopyText content={record.postPullRequestsEndpoint} />
+ <p>
+ See the{' '}
+ <ExternalLink link="https://devlake.apache.org/docs/Plugins/webhook#pull_requests">
+ full payload schema
+ </ExternalLink>
+ .
+ </p>
+ </Block>
</S.Wrapper>
)}
</Modal>
diff --git a/config-ui/src/plugins/register/webhook/components/utils.ts b/config-ui/src/plugins/register/webhook/components/utils.ts
index e417216..5892b33 100644
--- a/config-ui/src/plugins/register/webhook/components/utils.ts
+++ b/config-ui/src/plugins/register/webhook/components/utils.ts
@@ -20,9 +20,8 @@
export const transformURI = (prefix: string, webhook: IWebhook, apiKey: string) => {
return {
- postIssuesEndpoint: `curl ${prefix}${webhook.postIssuesEndpoint} -X 'POST' -H 'Authorization: Bearer ${
- apiKey ?? '{API_KEY}'
- }' -d '{
+ postIssuesEndpoint: `curl ${prefix}${webhook.postIssuesEndpoint} -X 'POST' -H 'Authorization: Bearer ${apiKey ?? '{API_KEY}'
+ }' -d '{
"issueKey":"DLK-1234",
"title":"an incident from DLK",
"type":"INCIDENT",
@@ -31,12 +30,10 @@
"createdDate":"2020-01-01T12:00:00+00:00",
"updatedDate":"2020-01-01T12:00:00+00:00"
}'`,
- closeIssuesEndpoint: `curl ${prefix}${webhook.closeIssuesEndpoint} -X 'POST' -H 'Authorization: Bearer ${
- apiKey ?? '{API_KEY}'
- }'`,
- postDeploymentsCurl: `curl ${prefix}${webhook.postPipelineDeployTaskEndpoint} -X 'POST' -H 'Authorization: Bearer ${
- apiKey ?? '{API_KEY}'
- }' -d '{
+ closeIssuesEndpoint: `curl ${prefix}${webhook.closeIssuesEndpoint} -X 'POST' -H 'Authorization: Bearer ${apiKey ?? '{API_KEY}'
+ }'`,
+ postDeploymentsCurl: `curl ${prefix}${webhook.postPipelineDeployTaskEndpoint} -X 'POST' -H 'Authorization: Bearer ${apiKey ?? '{API_KEY}'
+ }' -d '{
"id": "Required. This will be the unique ID of the deployment",
"startedDate": "2023-01-01T12:00:00+00:00",
"finishedDate": "2023-01-01T12:00:00+00:00",
@@ -53,5 +50,26 @@
}
]
}'`,
+ postPullRequestsEndpoint: `curl ${prefix}${webhook.postPullRequestsEndpoint} -X 'POST' -H 'Authorization: Bearer ${apiKey ?? '{API_KEY}'
+ }' -d '{
+ "id": "Required. This will be the unique ID of the pull request",
+ "baseRepoId": "your-repo-id",
+ "headRepoId": "your-repo-id",
+ "status": "MERGED",
+ "originalStatus": "OPEN",
+ "displayTitle": "Feature: Add new functionality",
+ "description": "This PR adds new features",
+ "url": "https://github.com/org/repo/pull/1",
+ "pullRequestKey": 1,
+ "createdDate": "2025-02-20T16:17:36Z",
+ "mergedDate": "2025-02-20T17:17:36Z",
+ "closedDate": null,
+ "mergeCommitSha": "bf0a79c57dff8f5f1f393de315ee5105a535e059",
+ "headRef": "your-branch-name",
+ "baseRef": "main",
+ "baseCommitSha": "e73325c2c9863f42ea25871cbfaeebcb8edcf604",
+ "headCommitSha": "b22f772f1197edfafd4cc5fe679a2d299ec12837",
+ "isDraft": false
+ }`,
};
};
diff --git a/config-ui/src/plugins/register/webhook/components/view-dialog.tsx b/config-ui/src/plugins/register/webhook/components/view-dialog.tsx
index 95750c0..a7bfd80 100644
--- a/config-ui/src/plugins/register/webhook/components/view-dialog.tsx
+++ b/config-ui/src/plugins/register/webhook/components/view-dialog.tsx
@@ -94,6 +94,17 @@
.
</p>
</Block>
+ <Block title="Pull Requests">
+ <h5>Post to register/update a pull_request</h5>
+ <CopyText content={URI.postPullRequestsEndpoint} />
+ <p>
+ See the{' '}
+ <ExternalLink link="https://devlake.apache.org/docs/Plugins/webhook#pull_requests">
+ full payload schema
+ </ExternalLink>
+ .
+ </p>
+ </Block>
<Block
title="API Key"
description="If you have forgotten your API key, you can revoke the previous key and generate a new one as a replacement."
diff --git a/config-ui/src/types/webhook.ts b/config-ui/src/types/webhook.ts
index 5ea4b89..0ea41ec 100644
--- a/config-ui/src/types/webhook.ts
+++ b/config-ui/src/types/webhook.ts
@@ -22,6 +22,7 @@
postIssuesEndpoint: string;
closeIssuesEndpoint: string;
postPipelineDeployTaskEndpoint: string;
+ postPullRequestsEndpoint: string;
apiKey: {
id: number;
apiKey: string;
@@ -34,5 +35,6 @@
postIssuesEndpoint: string;
closeIssuesEndpoint: string;
postPipelineDeployTaskEndpoint: string;
+ postPullRequestsEndpoint: string;
apiKeyId: number;
}