diff --git a/backend/plugins/webhook/api/deployments.go b/backend/plugins/webhook/api/deployments.go
index fc2a463ef62..b65ca9d0873 100644
--- a/backend/plugins/webhook/api/deployments.go
+++ b/backend/plugins/webhook/api/deployments.go
@@ -126,7 +126,7 @@ func PostDeploymentsByName(input *plugin.ApiResourceInput) (*plugin.ApiResourceO
// @Router /projects/:projectName/deployments [POST]
func PostDeploymentsByProjectName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
// find or create the connection for this project
- connection, err, shouldReturn := getOrCreateConnection(input)
+ connection, err, shouldReturn := getOrCreateConnection(input, "deployments")
if shouldReturn {
return nil, err
}
@@ -134,10 +134,10 @@ func PostDeploymentsByProjectName(input *plugin.ApiResourceInput) (*plugin.ApiRe
return postDeployments(input, connection, err)
}
-func getOrCreateConnection(input *plugin.ApiResourceInput) (*models.WebhookConnection, errors.Error, bool) {
+func getOrCreateConnection(input *plugin.ApiResourceInput, webhookSuffix string) (*models.WebhookConnection, errors.Error, bool) {
connection := &models.WebhookConnection{}
projectName := input.Params["projectName"]
- webhookName := fmt.Sprintf("%s_deployments", projectName)
+ webhookName := fmt.Sprintf("%s_%s", projectName, webhookSuffix)
err := findByProjectName(connection, input.Params, pluginName, webhookName)
dal := basicRes.GetDal()
if err != nil {
diff --git a/backend/plugins/webhook/api/issues.go b/backend/plugins/webhook/api/issues.go
index 49ea72b51f1..a88f0763523 100644
--- a/backend/plugins/webhook/api/issues.go
+++ b/backend/plugins/webhook/api/issues.go
@@ -19,11 +19,12 @@ package api
import (
"fmt"
- "github.com/apache/incubator-devlake/core/log"
- "github.com/apache/incubator-devlake/helpers/dbhelper"
"net/http"
"time"
+ "github.com/apache/incubator-devlake/core/log"
+ "github.com/apache/incubator-devlake/helpers/dbhelper"
+
"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/models/domainlayer"
@@ -112,6 +113,26 @@ func PostIssueByName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
return postIssue(input, err, connection)
}
+// PostIssuesByProjectName
+// @Summary create issue by project name
+// @Description Create issue by project name. The webhook connection will be created automatically if it does not exist.
+// @Description example: {"url":"","issue_key":"DLK-1234","title":"a feature from DLK","description":"","epic_key":"","type":"BUG","status":"TODO","original_status":"created","story_point":0,"resolution_date":null,"created_date":"2020-01-01T12:00:00+00:00","updated_date":null,"lead_time_minutes":0,"parent_issue_key":"DLK-1200","priority":"","original_estimate_minutes":0,"time_spent_minutes":0,"time_remaining_minutes":0,"creator_id":"user1131","creator_name":"Nick name 1","assignee_id":"user1132","assignee_name":"Nick name 2","severity":"","component":""}
+// @Tags plugins/webhook
+// @Param body body WebhookIssueRequest true "json body"
+// @Success 200 {string} noResponse ""
+// @Failure 400 {string} errcode.Error "Bad Request"
+// @Failure 403 {string} errcode.Error "Forbidden"
+// @Failure 500 {string} errcode.Error "Internal Error"
+// @Router /projects/:projectName/issues [POST]
+func PostIssuesByProjectName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
+ // find or create the connection for this project
+ connection, err, shouldReturn := getOrCreateConnection(input, "issues")
+ if shouldReturn {
+ return nil, err
+ }
+ return postIssue(input, err, connection)
+}
+
func postIssue(input *plugin.ApiResourceInput, err errors.Error, connection *models.WebhookConnection) (*plugin.ApiResourceOutput, errors.Error) {
if err != nil {
return nil, err
diff --git a/backend/plugins/webhook/api/pull_requests.go b/backend/plugins/webhook/api/pull_requests.go
index a01bb6c4d93..50fcee5c43a 100644
--- a/backend/plugins/webhook/api/pull_requests.go
+++ b/backend/plugins/webhook/api/pull_requests.go
@@ -77,7 +77,7 @@ type WebhookPullRequestReq struct {
// @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]
+// @Router /plugins/webhook/connections/:connectionId/pull_requests [POST]
func PostPullRequests(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
connection := &models.WebhookConnection{}
err := connectionHelper.First(connection, input.Params)
@@ -96,7 +96,7 @@ func PostPullRequests(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput
// @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]
+// @Router /plugins/webhook/connections/by-name/:connectionName/pull_requests [POST]
func PostPullRequestsByName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
connection := &models.WebhookConnection{}
err := connectionHelper.FirstByName(connection, input.Params)
@@ -104,6 +104,27 @@ func PostPullRequestsByName(input *plugin.ApiResourceInput) (*plugin.ApiResource
return postPullRequests(input, connection, err)
}
+// PostPullRequestsByProjectName
+// @Summary create pull requests by project name
+// @Description Create pull request by project name. The webhook connection will be created automatically if it does not exist.
+// @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}
+// @Description "baseRepoId" should be equal to "webhook:{connectionId}" for consistent DORA calculations
+// @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 /projects/:projectName/pull_requests [POST]
+func PostPullRequestsByProjectName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
+ connection, err, shouldReturn := getOrCreateConnection(input, "pull_requests")
+ if shouldReturn {
+ return nil, err
+ }
+
+ 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
diff --git a/backend/plugins/webhook/impl/impl.go b/backend/plugins/webhook/impl/impl.go
index 9a67683584e..93f2ac5e022 100644
--- a/backend/plugins/webhook/impl/impl.go
+++ b/backend/plugins/webhook/impl/impl.go
@@ -131,5 +131,11 @@ func (p Webhook) ApiResources() map[string]map[string]plugin.ApiResourceHandler
"projects/:projectName/deployments": {
"POST": api.PostDeploymentsByProjectName,
},
+ "projects/:projectName/issues": {
+ "POST": api.PostIssuesByProjectName,
+ },
+ "projects/:projectName/pull_requests": {
+ "POST": api.PostPullRequestsByProjectName,
+ },
}
}