From 1ebd23a017f1c04aede34c707e54ba42792a510a Mon Sep 17 00:00:00 2001 From: Patrick Zhao Date: Thu, 19 Sep 2024 10:50:21 +0800 Subject: [PATCH] support jira status change in jira webhook Signed-off-by: Patrick Zhao --- .../common/repository/models/workflow_v4.go | 19 +- .../core/system/handler/project_management.go | 34 ++- .../aslan/core/system/handler/router.go | 3 +- .../core/system/service/project_management.go | 49 +++- .../aslan/server/rest/doc/docs.go | 233 +++++++++++++++++- .../aslan/server/rest/doc/swagger.json | 233 +++++++++++++++++- .../aslan/server/rest/doc/swagger.yaml | 156 +++++++++++- pkg/tool/jira/client.go | 10 +- pkg/tool/jira/platform.go | 45 ++++ pkg/tool/jira/project.go | 2 +- pkg/tool/jira/types.go | 23 +- 11 files changed, 770 insertions(+), 37 deletions(-) create mode 100644 pkg/tool/jira/platform.go diff --git a/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go b/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go index d5e0125592..62eb8b1bb0 100644 --- a/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go +++ b/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go @@ -1020,10 +1020,21 @@ type WorkflowV4Hook struct { } type JiraHook struct { - Name string `bson:"name" json:"name"` - Enabled bool `bson:"enabled" json:"enabled"` - Description string `bson:"description" json:"description"` - WorkflowArg *WorkflowV4 `bson:"workflow_arg" json:"workflow_arg"` + Name string `bson:"name" json:"name"` + Enabled bool `bson:"enabled" json:"enabled"` + Description string `bson:"description" json:"description"` + JiraID string `bson:"jira_id" json:"jira_id"` + JiraSystemIdentity string `bson:"jira_system_identity" json:"jira_system_identity"` + JiraURL string `bson:"jira_url" json:"jira_url"` + EnabledIssueStatusChange bool `bson:"enabled_issue_status_change" json:"enabled_issue_status_change"` + FromStatus JiraHookStatus `bson:"from_status" json:"from_status"` + ToStatus JiraHookStatus `bson:"to_status" json:"to_status"` + WorkflowArg *WorkflowV4 `bson:"workflow_arg" json:"workflow_arg"` +} + +type JiraHookStatus struct { + ID string `bson:"id,omitempty" json:"id,omitempty"` + Name string `bson:"name,omitempty" json:"name,omitempty"` } type MeegoHook struct { diff --git a/pkg/microservice/aslan/core/system/handler/project_management.go b/pkg/microservice/aslan/core/system/handler/project_management.go index 3a78459ac7..59fc2c406a 100644 --- a/pkg/microservice/aslan/core/system/handler/project_management.go +++ b/pkg/microservice/aslan/core/system/handler/project_management.go @@ -311,16 +311,48 @@ func SearchJiraProjectIssuesWithJQL(c *gin.Context) { ctx.Resp, ctx.Err = service.SearchJiraProjectIssuesWithJQL(c.Param("id"), c.Query("project"), strings.ReplaceAll(c.Query("jql"), "{{.system.username}}", ctx.UserName), c.Query("summary")) } +// @Summary Get Jira Types +// @Description Get Jira Types +// @Tags system +// @Accept json +// @Produce json +// @Param id path string true "jira id" +// @Param project query string true "jira project key" +// @Success 200 {array} jira.IssueTypeWithStatus +// @Router /api/aslan/system/project_management/{id}/jira/type [get] func GetJiraTypes(c *gin.Context) { ctx := internalhandler.NewContext(c) defer func() { internalhandler.JSONResponse(c, ctx) }() ctx.Resp, ctx.Err = service.GetJiraTypes(c.Param("id"), c.Query("project")) } +// @Summary Get Jira Project Status +// @Description Get Jira Project Status +// @Tags system +// @Accept json +// @Produce json +// @Param id path string true "jira id" +// @Param project query string true "jira project id" +// @Success 200 {array} string +// @Router /api/aslan/system/project_management/{id}/jira/status [get] +func GetJiraProjectStatus(c *gin.Context) { + ctx := internalhandler.NewContext(c) + defer func() { internalhandler.JSONResponse(c, ctx) }() + ctx.Resp, ctx.Err = service.GetJiraProjectStatus(c.Param("id"), c.Query("project")) +} + +// @Summary Get Jira All Status +// @Description Get Jira All Status +// @Tags system +// @Accept json +// @Produce json +// @Param id path string true "jira id" +// @Success 200 {array} jira.Status +// @Router /api/aslan/system/project_management/{id}/jira/allStatus [get] func GetJiraAllStatus(c *gin.Context) { ctx := internalhandler.NewContext(c) defer func() { internalhandler.JSONResponse(c, ctx) }() - ctx.Resp, ctx.Err = service.GetJiraAllStatus(c.Param("id"), c.Query("project")) + ctx.Resp, ctx.Err = service.GetJiraAllStatus(c.Param("id")) } func HandleJiraEvent(c *gin.Context) { diff --git a/pkg/microservice/aslan/core/system/handler/router.go b/pkg/microservice/aslan/core/system/handler/router.go index 66460d20c1..28ee7ef315 100644 --- a/pkg/microservice/aslan/core/system/handler/router.go +++ b/pkg/microservice/aslan/core/system/handler/router.go @@ -348,7 +348,8 @@ func (*Router) Inject(router *gin.RouterGroup) { pm.GET("/:id/jira/issue", SearchJiraIssues) pm.GET("/:id/jira/issue/jql", SearchJiraProjectIssuesWithJQL) pm.GET("/:id/jira/type", GetJiraTypes) - pm.GET("/:id/jira/status", GetJiraAllStatus) + pm.GET("/:id/jira/status", GetJiraProjectStatus) + pm.GET("/:id/jira/allStatus", GetJiraAllStatus) pm.POST("/jira/webhook/:workflowName/:hookName", HandleJiraEvent) pm.POST("/meego/webhook/:workflowName/:hookName", HandleMeegoEvent) } diff --git a/pkg/microservice/aslan/core/system/service/project_management.go b/pkg/microservice/aslan/core/system/service/project_management.go index 3f866e00ce..4520c0f1c3 100644 --- a/pkg/microservice/aslan/core/system/service/project_management.go +++ b/pkg/microservice/aslan/core/system/service/project_management.go @@ -319,7 +319,7 @@ func GetJiraTypes(id, project string) ([]*jira.IssueTypeWithStatus, error) { return jira.NewJiraClientWithAuthType(info.JiraHost, info.JiraUser, info.JiraToken, info.JiraPersonalAccessToken, info.JiraAuthType).Issue.GetTypes(project) } -func GetJiraAllStatus(id, project string) ([]string, error) { +func GetJiraProjectStatus(id, project string) ([]string, error) { info, err := mongodb.NewProjectManagementColl().GetJiraByID(id) if err != nil { if err == mongo.ErrNoDocuments { @@ -327,7 +327,18 @@ func GetJiraAllStatus(id, project string) ([]string, error) { } return nil, err } - return jira.NewJiraClientWithAuthType(info.JiraHost, info.JiraUser, info.JiraToken, info.JiraPersonalAccessToken, info.JiraAuthType).Project.ListAllStatues(project) + return jira.NewJiraClientWithAuthType(info.JiraHost, info.JiraUser, info.JiraToken, info.JiraPersonalAccessToken, info.JiraAuthType).Project.ListProjectStatues(project) +} + +func GetJiraAllStatus(id string) ([]*jira.Status, error) { + info, err := mongodb.NewProjectManagementColl().GetJiraByID(id) + if err != nil { + if err == mongo.ErrNoDocuments { + return nil, nil + } + return nil, err + } + return jira.NewJiraClientWithAuthType(info.JiraHost, info.JiraUser, info.JiraToken, info.JiraPersonalAccessToken, info.JiraAuthType).Platform.ListAllStatues() } func SearchJiraIssues(id, project, _type, status, summary string, ne bool) ([]*jira.Issue, error) { @@ -402,6 +413,40 @@ func HandleJiraHookEvent(workflowName, hookName string, event *jira.Event, logge logger.Error(errMsg) return errors.New(errMsg) } + + if jiraHook.EnabledIssueStatusChange { + if event.ChangeLog == nil || len(event.ChangeLog.Items) == 0 { + logger.Errorf("HandleJiraHookEvent: nil change log or change log items, skip") + return nil + } + + statusChangeMatched := false + changelog := &jira.ChangeLogItem{} + for _, item := range event.ChangeLog.Items { + if item.Field != "status" || item.FieldType != "jira" { + continue + } + + if jiraHook.FromStatus.ID == "000000" { + if item.To == jiraHook.ToStatus.ID { + statusChangeMatched = true + } + } else { + if item.From == jiraHook.FromStatus.ID && item.To == jiraHook.ToStatus.ID { + statusChangeMatched = true + } + } + + changelog = item + break + } + + if !statusChangeMatched { + logger.Infof("HandleJiraHookEvent: hook %s/%s status change not matched, skip. status changelog: %+v", workflowName, hookName, changelog) + return nil + } + } + taskInfo, err := workflow.CreateWorkflowTaskV4ByBuildInTrigger(setting.JiraHookTaskCreator, jiraHook.WorkflowArg, logger) if err != nil { errMsg := fmt.Sprintf("HandleJiraHookEvent: failed to create workflow task: %s", err) diff --git a/pkg/microservice/aslan/server/rest/doc/docs.go b/pkg/microservice/aslan/server/rest/doc/docs.go index 931e69cd91..c0cc42ddbf 100644 --- a/pkg/microservice/aslan/server/rest/doc/docs.go +++ b/pkg/microservice/aslan/server/rest/doc/docs.go @@ -4256,6 +4256,41 @@ const docTemplate = `{ } } }, + "/api/aslan/system/project_management/{id}/jira/allStatus": { + "get": { + "description": "Get Jira All Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "system" + ], + "summary": "Get Jira All Status", + "parameters": [ + { + "type": "string", + "description": "jira id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/jira.Status" + } + } + } + } + } + }, "/api/aslan/system/project_management/{id}/jira/board": { "get": { "description": "List Jira Boards", @@ -4453,6 +4488,90 @@ const docTemplate = `{ } } }, + "/api/aslan/system/project_management/{id}/jira/status": { + "get": { + "description": "Get Jira Project Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "system" + ], + "summary": "Get Jira Project Status", + "parameters": [ + { + "type": "string", + "description": "jira id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "jira project id", + "name": "project", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/api/aslan/system/project_management/{id}/jira/type": { + "get": { + "description": "Get Jira Types", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "system" + ], + "summary": "Get Jira Types", + "parameters": [ + { + "type": "string", + "description": "jira id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "jira project key", + "name": "project", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/jira.IssueTypeWithStatus" + } + } + } + } + } + }, "/api/aslan/system/registry/project": { "get": { "description": "List Registries", @@ -5485,6 +5604,17 @@ const docTemplate = `{ "SourceFromJob" ] }, + "config.DistributeImageMethod": { + "type": "string", + "enum": [ + "image_push", + "cloud_sync" + ], + "x-enum-varnames": [ + "DistributeImageMethodImagePush", + "DistributeImageMethodCloudSync" + ] + }, "config.JiraAuthType": { "type": "string", "enum": [ @@ -5496,6 +5626,21 @@ const docTemplate = `{ "JiraPersonalAccessToken" ] }, + "config.JobErrorPolicy": { + "type": "string", + "enum": [ + "stop", + "ignore_error", + "manual_check", + "retry" + ], + "x-enum-varnames": [ + "JobErrorPolicyStop", + "JobErrorPolicyIgnoreError", + "JobErrorPolicyManualCheck", + "JobErrorPolicyRetry" + ] + }, "config.JobRunPolicy": { "type": "string", "enum": [ @@ -5701,7 +5846,9 @@ const docTemplate = `{ "distributed", "wait_for_approval", "debug_before", - "debug_after" + "debug_after", + "unstable", + "wait_for_manual_error_handling" ], "x-enum-varnames": [ "StatusDisabled", @@ -5724,7 +5871,9 @@ const docTemplate = `{ "StatusDistributed", "StatusWaitingApprove", "StatusDebugBefore", - "StatusDebugAfter" + "StatusDebugAfter", + "StatusUnstable", + "StatusManualApproval" ] }, "github_com_koderover_zadig_v2_pkg_microservice_aslan_core_common_service.EnvService": { @@ -6184,6 +6333,45 @@ const docTemplate = `{ } } }, + "jira.IssueTypeWithStatus": { + "type": "object", + "properties": { + "status": { + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "type": "string" + } + } + }, + "jira.Status": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "statusCategory": { + "$ref": "#/definitions/jira.StatusCategory" + } + } + }, + "jira.StatusCategory": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "key": { + "type": "string" + } + } + }, "kube.SetIstioGrayscaleConfigRequest": { "type": "object", "properties": { @@ -6803,12 +6991,6 @@ const docTemplate = `{ "$ref": "#/definitions/models.ServiceKeyVal" } }, - "latest_variable_kvs": { - "type": "array", - "items": { - "$ref": "#/definitions/types.RenderVariableKV" - } - }, "modules": { "type": "array", "items": { @@ -6838,6 +7020,7 @@ const docTemplate = `{ } }, "variable_yaml": { + "description": "LatestVariableKVs []*commontypes.RenderVariableKV ` + "`" + `bson:\"latest_variable_kvs\" yaml:\"latest_variable_kvs\" json:\"latest_variable_kvs\"` + "`" + `", "type": "string" } } @@ -6997,6 +7180,9 @@ const docTemplate = `{ "env_name": { "type": "string" }, + "health_checks": { + "$ref": "#/definitions/models.PmHealthCheck" + }, "host_id": { "type": "string" }, @@ -7256,6 +7442,9 @@ const docTemplate = `{ "models.Job": { "type": "object", "properties": { + "error_policy": { + "$ref": "#/definitions/models.JobErrorPolicy" + }, "name": { "type": "string" }, @@ -7278,6 +7467,23 @@ const docTemplate = `{ } } }, + "models.JobErrorPolicy": { + "type": "object", + "properties": { + "approval_users": { + "type": "array", + "items": { + "$ref": "#/definitions/models.User" + } + }, + "maximum_retry": { + "type": "integer" + }, + "policy": { + "$ref": "#/definitions/config.JobErrorPolicy" + } + } + }, "models.JobTaskSQLSpec": { "type": "object", "properties": { @@ -7336,6 +7542,9 @@ const docTemplate = `{ "key": { "type": "string" }, + "registry_id": { + "type": "string" + }, "type": { "$ref": "#/definitions/models.ParameterSettingType" }, @@ -7549,11 +7758,13 @@ const docTemplate = `{ "enum": [ "string", "choice", + "image", "external" ], "x-enum-varnames": [ "StringType", "ChoiceType", + "ImageType", "ExternalType" ] }, @@ -7975,6 +8186,9 @@ const docTemplate = `{ }, "sprint_id": { "type": "integer" + }, + "sprint_name": { + "type": "string" } } }, @@ -8768,6 +8982,9 @@ const docTemplate = `{ "cluster_id": { "type": "string" }, + "distribute_method": { + "$ref": "#/definitions/config.DistributeImageMethod" + }, "enable_target_image_tag_rule": { "type": "boolean" }, diff --git a/pkg/microservice/aslan/server/rest/doc/swagger.json b/pkg/microservice/aslan/server/rest/doc/swagger.json index 6207f788db..3475479205 100644 --- a/pkg/microservice/aslan/server/rest/doc/swagger.json +++ b/pkg/microservice/aslan/server/rest/doc/swagger.json @@ -4247,6 +4247,41 @@ } } }, + "/api/aslan/system/project_management/{id}/jira/allStatus": { + "get": { + "description": "Get Jira All Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "system" + ], + "summary": "Get Jira All Status", + "parameters": [ + { + "type": "string", + "description": "jira id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/jira.Status" + } + } + } + } + } + }, "/api/aslan/system/project_management/{id}/jira/board": { "get": { "description": "List Jira Boards", @@ -4444,6 +4479,90 @@ } } }, + "/api/aslan/system/project_management/{id}/jira/status": { + "get": { + "description": "Get Jira Project Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "system" + ], + "summary": "Get Jira Project Status", + "parameters": [ + { + "type": "string", + "description": "jira id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "jira project id", + "name": "project", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/api/aslan/system/project_management/{id}/jira/type": { + "get": { + "description": "Get Jira Types", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "system" + ], + "summary": "Get Jira Types", + "parameters": [ + { + "type": "string", + "description": "jira id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "jira project key", + "name": "project", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/jira.IssueTypeWithStatus" + } + } + } + } + } + }, "/api/aslan/system/registry/project": { "get": { "description": "List Registries", @@ -5476,6 +5595,17 @@ "SourceFromJob" ] }, + "config.DistributeImageMethod": { + "type": "string", + "enum": [ + "image_push", + "cloud_sync" + ], + "x-enum-varnames": [ + "DistributeImageMethodImagePush", + "DistributeImageMethodCloudSync" + ] + }, "config.JiraAuthType": { "type": "string", "enum": [ @@ -5487,6 +5617,21 @@ "JiraPersonalAccessToken" ] }, + "config.JobErrorPolicy": { + "type": "string", + "enum": [ + "stop", + "ignore_error", + "manual_check", + "retry" + ], + "x-enum-varnames": [ + "JobErrorPolicyStop", + "JobErrorPolicyIgnoreError", + "JobErrorPolicyManualCheck", + "JobErrorPolicyRetry" + ] + }, "config.JobRunPolicy": { "type": "string", "enum": [ @@ -5692,7 +5837,9 @@ "distributed", "wait_for_approval", "debug_before", - "debug_after" + "debug_after", + "unstable", + "wait_for_manual_error_handling" ], "x-enum-varnames": [ "StatusDisabled", @@ -5715,7 +5862,9 @@ "StatusDistributed", "StatusWaitingApprove", "StatusDebugBefore", - "StatusDebugAfter" + "StatusDebugAfter", + "StatusUnstable", + "StatusManualApproval" ] }, "github_com_koderover_zadig_v2_pkg_microservice_aslan_core_common_service.EnvService": { @@ -6175,6 +6324,45 @@ } } }, + "jira.IssueTypeWithStatus": { + "type": "object", + "properties": { + "status": { + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "type": "string" + } + } + }, + "jira.Status": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "statusCategory": { + "$ref": "#/definitions/jira.StatusCategory" + } + } + }, + "jira.StatusCategory": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "key": { + "type": "string" + } + } + }, "kube.SetIstioGrayscaleConfigRequest": { "type": "object", "properties": { @@ -6794,12 +6982,6 @@ "$ref": "#/definitions/models.ServiceKeyVal" } }, - "latest_variable_kvs": { - "type": "array", - "items": { - "$ref": "#/definitions/types.RenderVariableKV" - } - }, "modules": { "type": "array", "items": { @@ -6829,6 +7011,7 @@ } }, "variable_yaml": { + "description": "LatestVariableKVs []*commontypes.RenderVariableKV `bson:\"latest_variable_kvs\" yaml:\"latest_variable_kvs\" json:\"latest_variable_kvs\"`", "type": "string" } } @@ -6988,6 +7171,9 @@ "env_name": { "type": "string" }, + "health_checks": { + "$ref": "#/definitions/models.PmHealthCheck" + }, "host_id": { "type": "string" }, @@ -7247,6 +7433,9 @@ "models.Job": { "type": "object", "properties": { + "error_policy": { + "$ref": "#/definitions/models.JobErrorPolicy" + }, "name": { "type": "string" }, @@ -7269,6 +7458,23 @@ } } }, + "models.JobErrorPolicy": { + "type": "object", + "properties": { + "approval_users": { + "type": "array", + "items": { + "$ref": "#/definitions/models.User" + } + }, + "maximum_retry": { + "type": "integer" + }, + "policy": { + "$ref": "#/definitions/config.JobErrorPolicy" + } + } + }, "models.JobTaskSQLSpec": { "type": "object", "properties": { @@ -7327,6 +7533,9 @@ "key": { "type": "string" }, + "registry_id": { + "type": "string" + }, "type": { "$ref": "#/definitions/models.ParameterSettingType" }, @@ -7540,11 +7749,13 @@ "enum": [ "string", "choice", + "image", "external" ], "x-enum-varnames": [ "StringType", "ChoiceType", + "ImageType", "ExternalType" ] }, @@ -7966,6 +8177,9 @@ }, "sprint_id": { "type": "integer" + }, + "sprint_name": { + "type": "string" } } }, @@ -8759,6 +8973,9 @@ "cluster_id": { "type": "string" }, + "distribute_method": { + "$ref": "#/definitions/config.DistributeImageMethod" + }, "enable_target_image_tag_rule": { "type": "boolean" }, diff --git a/pkg/microservice/aslan/server/rest/doc/swagger.yaml b/pkg/microservice/aslan/server/rest/doc/swagger.yaml index 18b4107b5f..260476eabf 100644 --- a/pkg/microservice/aslan/server/rest/doc/swagger.yaml +++ b/pkg/microservice/aslan/server/rest/doc/swagger.yaml @@ -65,6 +65,14 @@ definitions: x-enum-varnames: - SourceRuntime - SourceFromJob + config.DistributeImageMethod: + enum: + - image_push + - cloud_sync + type: string + x-enum-varnames: + - DistributeImageMethodImagePush + - DistributeImageMethodCloudSync config.JiraAuthType: enum: - password_or_token @@ -73,6 +81,18 @@ definitions: x-enum-varnames: - JiraBasicAuth - JiraPersonalAccessToken + config.JobErrorPolicy: + enum: + - stop + - ignore_error + - manual_check + - retry + type: string + x-enum-varnames: + - JobErrorPolicyStop + - JobErrorPolicyIgnoreError + - JobErrorPolicyManualCheck + - JobErrorPolicyRetry config.JobRunPolicy: enum: - "" @@ -256,6 +276,8 @@ definitions: - wait_for_approval - debug_before - debug_after + - unstable + - wait_for_manual_error_handling type: string x-enum-varnames: - StatusDisabled @@ -279,6 +301,8 @@ definitions: - StatusWaitingApprove - StatusDebugBefore - StatusDebugAfter + - StatusUnstable + - StatusManualApproval github_com_koderover_zadig_v2_pkg_microservice_aslan_core_common_service.EnvService: properties: deployed: @@ -579,6 +603,31 @@ definitions: - service_variable_kvs - variable_yaml type: object + jira.IssueTypeWithStatus: + properties: + status: + items: + type: string + type: array + type: + type: string + type: object + jira.Status: + properties: + id: + type: string + name: + type: string + statusCategory: + $ref: '#/definitions/jira.StatusCategory' + type: object + jira.StatusCategory: + properties: + id: + type: integer + key: + type: string + type: object kube.SetIstioGrayscaleConfigRequest: properties: grayscale_strategy: @@ -992,10 +1041,6 @@ definitions: items: $ref: '#/definitions/models.ServiceKeyVal' type: array - latest_variable_kvs: - items: - $ref: '#/definitions/types.RenderVariableKV' - type: array modules: items: $ref: '#/definitions/models.DeployModuleInfo' @@ -1017,6 +1062,7 @@ definitions: $ref: '#/definitions/types.RenderVariableKV' type: array variable_yaml: + description: LatestVariableKVs []*commontypes.RenderVariableKV `bson:"latest_variable_kvs" yaml:"latest_variable_kvs" json:"latest_variable_kvs"` type: string type: object models.DeployTargets: @@ -1121,6 +1167,8 @@ definitions: type: string env_name: type: string + health_checks: + $ref: '#/definitions/models.PmHealthCheck' host_id: type: string pm_info: @@ -1291,6 +1339,8 @@ definitions: type: object models.Job: properties: + error_policy: + $ref: '#/definitions/models.JobErrorPolicy' name: type: string run_policy: @@ -1306,6 +1356,17 @@ definitions: type: $ref: '#/definitions/config.JobType' type: object + models.JobErrorPolicy: + properties: + approval_users: + items: + $ref: '#/definitions/models.User' + type: array + maximum_retry: + type: integer + policy: + $ref: '#/definitions/config.JobErrorPolicy' + type: object models.JobTaskSQLSpec: properties: id: @@ -1344,6 +1405,8 @@ definitions: type: boolean key: type: string + registry_id: + type: string type: $ref: '#/definitions/models.ParameterSettingType' value: @@ -1487,11 +1550,13 @@ definitions: enum: - string - choice + - image - external type: string x-enum-varnames: - StringType - ChoiceType + - ImageType - ExternalType models.PatchItem: properties: @@ -1777,6 +1842,8 @@ definitions: type: string sprint_id: type: integer + sprint_name: + type: string type: object models.ReleasePlanJiraSprintAssociation: properties: @@ -2309,6 +2376,8 @@ definitions: properties: cluster_id: type: string + distribute_method: + $ref: '#/definitions/config.DistributeImageMethod' enable_target_image_tag_rule: type: boolean job_name: @@ -7135,6 +7204,29 @@ paths: summary: Get Meego Work Item Type List tags: - system + /api/aslan/system/project_management/{id}/jira/allStatus: + get: + consumes: + - application/json + description: Get Jira All Status + parameters: + - description: jira id + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/jira.Status' + type: array + summary: Get Jira All Status + tags: + - system /api/aslan/system/project_management/{id}/jira/board: get: consumes: @@ -7266,6 +7358,62 @@ paths: summary: List Jira Sprint Issues tags: - system + /api/aslan/system/project_management/{id}/jira/status: + get: + consumes: + - application/json + description: Get Jira Project Status + parameters: + - description: jira id + in: path + name: id + required: true + type: string + - description: jira project id + in: query + name: project + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Get Jira Project Status + tags: + - system + /api/aslan/system/project_management/{id}/jira/type: + get: + consumes: + - application/json + description: Get Jira Types + parameters: + - description: jira id + in: path + name: id + required: true + type: string + - description: jira project key + in: query + name: project + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/jira.IssueTypeWithStatus' + type: array + summary: Get Jira Types + tags: + - system /api/aslan/system/project_management/project: get: consumes: diff --git a/pkg/tool/jira/client.go b/pkg/tool/jira/client.go index d32ef9a4c3..0be7f36976 100644 --- a/pkg/tool/jira/client.go +++ b/pkg/tool/jira/client.go @@ -27,10 +27,11 @@ import ( type Client struct { Host string *req.Client - Issue *IssueService - Project *ProjectService - Board *BoardService - Sprint *SprintService + Issue *IssueService + Project *ProjectService + Board *BoardService + Sprint *SprintService + Platform *PlatformService } func NewJiraClientWithAuthType(host, username, password, token string, _type config.JiraAuthType) *Client { @@ -58,6 +59,7 @@ func NewJiraClientWithBasicAuth(host, username, password string) *Client { c.Project = &ProjectService{client: c} c.Board = &BoardService{client: c} c.Sprint = &SprintService{client: c} + c.Platform = &PlatformService{client: c} return c } diff --git a/pkg/tool/jira/platform.go b/pkg/tool/jira/platform.go new file mode 100644 index 0000000000..1ad6443cf3 --- /dev/null +++ b/pkg/tool/jira/platform.go @@ -0,0 +1,45 @@ +/* +Copyright 2024 The KodeRover Authors. + +Licensed 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 jira + +import ( + "github.com/pkg/errors" +) + +// ProjectService ... +type PlatformService struct { + client *Client +} + +// Get all status https://developer.atlassian.com/server/jira/platform/rest/v10000/api-group-status/#api-group-status +func (s *PlatformService) ListAllStatues() ([]*Status, error) { + list := make([]*Status, 0) + url := s.client.Host + "/rest/api/2/status" + + resp, err := s.client.R().Get(url) + if err != nil { + return nil, err + } + if resp.GetStatusCode()/100 != 2 { + return nil, errors.Errorf("get unexpected status code %d, body: %s", resp.GetStatusCode(), resp.String()) + } + if err = resp.UnmarshalJson(&list); err != nil { + return nil, errors.Wrap(err, "unmarshal") + } + + return list, nil +} diff --git a/pkg/tool/jira/project.go b/pkg/tool/jira/project.go index 540583a6ec..30abf22867 100644 --- a/pkg/tool/jira/project.go +++ b/pkg/tool/jira/project.go @@ -52,7 +52,7 @@ func (s *ProjectService) ListProjects() ([]*Project, error) { return list, nil } -func (s *ProjectService) ListAllStatues(project string) ([]string, error) { +func (s *ProjectService) ListProjectStatues(project string) ([]string, error) { resp, err := s.client.Issue.GetTypes(project) if err != nil { return nil, err diff --git a/pkg/tool/jira/types.go b/pkg/tool/jira/types.go index 529a3e1ec8..0a687cd9e7 100644 --- a/pkg/tool/jira/types.go +++ b/pkg/tool/jira/types.go @@ -53,10 +53,11 @@ func (ifs IssueFields) String() string { } type Event struct { - Timestamp int64 `json:"timestamp"` - WebhookEvent string `json:"webhookEvent"` - IssueEventTypeName string `json:"issue_event_type_name"` - Issue *Issue `json:"issue"` + Timestamp int64 `json:"timestamp"` + WebhookEvent string `json:"webhookEvent"` + IssueEventTypeName string `json:"issue_event_type_name"` + Issue *Issue `json:"issue"` + ChangeLog *ChangeLog `json:"changelog"` } // Issue IssueResult:Issues @@ -179,3 +180,17 @@ type Component struct { Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` } + +type ChangeLog struct { + ID string `json:"id,omitempty"` + Items []*ChangeLogItem `json:"items,omitempty"` +} + +type ChangeLogItem struct { + Field string `json:"field,omitempty"` + FieldType string `json:"fieldtype,omitempty"` + From string `json:"from,omitempty"` + FromString string `json:"fromString,omitempty"` + To string `json:"to,omitempty"` + ToString string `json:"toString,omitempty"` +}