From e4a971efd460ed31bcf01901ab7dc16bf6d674d7 Mon Sep 17 00:00:00 2001 From: yangwei999 <348134071@qq.com> Date: Wed, 8 Jan 2025 17:28:27 +0800 Subject: [PATCH 1/5] set issue state by reason --- cve-vulner-manager/common/analysis.go | 39 ++++ cve-vulner-manager/controllers/hook.go | 260 ++++++++++++++++-------- cve-vulner-manager/models/issue.go | 30 +++ cve-vulner-manager/taskhandler/issue.go | 27 +++ 4 files changed, 275 insertions(+), 81 deletions(-) diff --git a/cve-vulner-manager/common/analysis.go b/cve-vulner-manager/common/analysis.go index d2bb73e..8d24a6e 100644 --- a/cve-vulner-manager/common/analysis.go +++ b/cve-vulner-manager/common/analysis.go @@ -18,6 +18,11 @@ const ( TypeAffected = "Affected" TypeUnaffected = "Unaffected" TypeUnderInvestigation = "Under Investigation" + + StateOpen = "open" + StateProcessing = "progressing" + StateSuspend = "suspended" + StateClosed = "closed" ) var AnalysisUnaffected = map[string]struct{}{ @@ -56,4 +61,38 @@ var ( AnalysisNotExecute, AnalysisCodeNotPresent, ) + + AnalysisStateMap = map[string]string{ + AnalysisStill: StateSuspend, + AnalysisNoPatch: StateSuspend, + AnalysisUpgrade: StateSuspend, + AnalysisOutScope: StateClosed, + AnalysisNotFix: StateClosed, + AnalysisComponentNotPresent: StateClosed, + AnalysisMitigationsExist: StateClosed, + AnalysisCannotControlled: StateClosed, + AnalysisNotExecute: StateClosed, + AnalysisCodeNotPresent: StateClosed, + } + + StatePriority = []string{ + StateClosed, + StateSuspend, + StateProcessing, + StateOpen, + } + + StateNameMap = map[string]string{ + StateClosed: "已完成", + StateSuspend: "已挂起", + StateProcessing: "进行中", + StateOpen: "待办的", + } + + StateIdMap = map[string]int64{ + StateClosed: 437577, + StateSuspend: 751673, + StateProcessing: 437576, + StateOpen: 437575, + } ) diff --git a/cve-vulner-manager/controllers/hook.go b/cve-vulner-manager/controllers/hook.go index 3113497..10d9bb3 100644 --- a/cve-vulner-manager/controllers/hook.go +++ b/cve-vulner-manager/controllers/hook.go @@ -14,6 +14,10 @@ import ( "sync" "time" + sdk "github.com/opensourceways/go-gitee/gitee" + "github.com/opensourceways/server-common-lib/utils" + "k8s.io/apimachinery/pkg/util/sets" + "cvevulner/common" "cvevulner/cve-timed-task/tabletask" "cvevulner/models" @@ -480,26 +484,15 @@ func closeIssueProc(issueHook *models.IssuePayload, issueTmp *models.IssueTempla } return } - issueTmp.IssueLabel = unFix - issueTmp.StatusName = "open" - issueTmp.Status = 1 - issuePrFlag := VerifyIssueAsPr(issueTmp, *cveCenter, false, - assignee, issueHook.Sender.UserName) - if issuePrFlag { - issueTmp.StatusName = issueHook.Issue.StateName - issueTmp.Status = 3 - if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { - issueTmp.IssueStatus = 2 - cveCenter.IsExport = 3 - issueTmp.IssueLabel = fixed - } else { - issueTmp.IssueStatus = 6 - cveCenter.IsExport = 2 - issueTmp.IssueLabel = unFix + + if err := SetIssueStateByReason(issueTmp, issueHook.Issue.StateName); err != nil { + logs.Error("SetIssueStateByReason of failed:", issueTmp.IssueNum, err) + } + + if issueTmp.IsIssueComplete() { + if issueTmp.IsAllUnaffected() { + issueTmp.ResetLabel() } - } else { - issueTmp.IssueStatus = 1 - cveCenter.IsExport = 0 } } } @@ -1329,7 +1322,7 @@ func otherMaintainerApprove( } func maintainerApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, fixed, - unfixed string, organizationID int8) { + unfixed string, organizationID int8, payload *models.CommentPayload) { if msg, _, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp, organizationID); !ok { //send comment to issue na := "\n**请确认分析内容的准确性,待分析内容请填写完整,否则将无法关闭当前issue.**" @@ -1348,43 +1341,25 @@ func maintainerApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, if err != nil { return } - issueTmp.IssueLabel = unfixed - issueTmp.StatusName = "open" - assignee := getMaintainer(issueTmp.Repo, cuAccount, issueTmp.Assignee) - issuePrFlag := VerifyIssueAsPr(issueTmp, cveCenter, false, assignee, cuAccount) - if issuePrFlag { - issueTmp.IssueLabel = fixed - issueTmp.StatusName = "closed" - taskhandler.AddCommentToIssue(fmt.Sprintf(`@%v 你已审核模板内容, cve-manager 将关闭issue!`, - cuAccount), issueTmp.IssueNum, owner, issueTmp.Repo, token) - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, issueTmp.Repo, - cveCenter, *issueTmp) - if issueErr == nil { - logs.Info("Initiate an issue to close, issuetmp: ", issueTmp) - } else { - logs.Error("Issue closing operation failed, issuetmp: ", issueTmp, ",issueErr: ", issueErr) - return - } - //issueTmp.SaAuditFlag = 1 - issueTmp.Status = 3 - if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { - issueTmp.IssueStatus = 2 - cveCenter.IsExport = 3 - } else { - issueTmp.IssueStatus = 6 - cveCenter.IsExport = 2 - } - updateBool := updateTempAndCenter(*issueTmp, cveCenter, token, owner) - if !updateBool { - return + + if err = SetIssueStateByReason(issueTmp, payload.Issue.StateName); err != nil { + logs.Error(webhookCommentLogTag, "SetIssueStateByReason, err: ", err, ",issueTmp: ", issueTmp.IssueNum) + } + + if issueTmp.IsIssueComplete() { + if issueTmp.IsAllUnaffected() { + issueTmp.ResetLabel() } } + + updateTempAndCenter(*issueTmp, cveCenter, token, owner) + return } } func securityApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, - fixed, unfixed string, organizationID int8) { + fixed, unfixed string, organizationID int8, payload *models.CommentPayload) { if msg, _, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp, organizationID); !ok { //send comment to issue na := "\n**请确认分析内容的准确性,待分析内容请填写完整,否则将无法关闭当前issue.**" @@ -1402,37 +1377,19 @@ func securityApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, if err != nil { return } - issueTmp.IssueLabel = unfixed - issueTmp.StatusName = "open" - assignee := getMaintainer(issueTmp.Repo, cuAccount, issueTmp.Assignee) - issuePrFlag := VerifyIssueAsPr(issueTmp, cveCenter, false, assignee, cuAccount) - if issuePrFlag { - issueTmp.IssueLabel = fixed - issueTmp.StatusName = "closed" - taskhandler.AddCommentToIssue(fmt.Sprintf(`@%v 你已审核模板内容,cve-manager 将关闭issue!`, - cuAccount), issueTmp.IssueNum, owner, issueTmp.Repo, token) - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, issueTmp.Repo, - cveCenter, *issueTmp) - if issueErr == nil { - logs.Info("Initiate an issue to close, issuetmp: ", issueTmp) - } else { - logs.Error("issue close operation failed, issuetmp: ", issueTmp, ",issueErr: ", issueErr) - return - } - issueTmp.SaAuditFlag = 1 - issueTmp.Status = 3 - if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { - issueTmp.IssueStatus = 2 - cveCenter.IsExport = 3 - } else { - issueTmp.IssueStatus = 6 - cveCenter.IsExport = 2 - } - updateBool := updateTempAndCenter(*issueTmp, cveCenter, token, owner) - if !updateBool { - return + + if err = SetIssueStateByReason(issueTmp, payload.Issue.StateName); err != nil { + logs.Error(webhookCommentLogTag, "SetIssueStateByReason, err: ", err, ",issueTmp: ", issueTmp.IssueNum) + } + + if issueTmp.IsIssueComplete() { + if issueTmp.IsAllUnaffected() { + issueTmp.ResetLabel() } } + + updateTempAndCenter(*issueTmp, cveCenter, token, owner) + return } } @@ -1582,11 +1539,11 @@ func handleIssueComment(payload models.CommentPayload) { } if mtAuditFlag { comLock.Lock() - maintainerApprove(&issueTmp, cuAccount, owner, accessToken, fixed, unfixed, vc.OrganizationID) + maintainerApprove(&issueTmp, cuAccount, owner, accessToken, fixed, unfixed, vc.OrganizationID, &payload) comLock.Unlock() } else { comLock.Lock() - securityApprove(&issueTmp, cuAccount, owner, accessToken, fixed, unfixed, vc.OrganizationID) + securityApprove(&issueTmp, cuAccount, owner, accessToken, fixed, unfixed, vc.OrganizationID, &payload) comLock.Unlock() } } @@ -1916,6 +1873,18 @@ func analysisComment(owner, accessToken, path string, cuAccount string, cBody st if err != nil { logs.Error(webhookCommentLogTag, "changeOpenEulerScoreStatus, err: ", err, ",issueTmp: ", issueTmp.IssueNum) } + + if err = SetIssueStateByReason(&issueTmp, payload.Issue.StateName); err != nil { + logs.Error(webhookCommentLogTag, "SetIssueStateByReason, err: ", err, ",issueTmp: ", issueTmp.IssueNum) + } + + if issueTmp.IsIssueComplete() { + if issueTmp.IsAllUnaffected() { + issueTmp.ResetLabel() + } + } + + updateTempAndCenter(issueTmp, v, accessToken, owner) } } else { na := "\n**请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.**" @@ -2462,3 +2431,132 @@ func gitDelIssueProc(issueHook *models.IssuePayload, organizationID int8) error DelOrgIssue(issueHook, organizationID) return nil } + +func SetIssueStateByReason(issue *models.IssueTemplate, remoteStateName string) error { + state, err := GetIssueStateByAllReason(issue) + if err != nil { + return err + } + + // issue本身的状态和计算后的状态一致,则不做任何操作 + stateName, ok := common.StateNameMap[state] + if !ok || stateName == remoteStateName { + return nil + } + + issue.StatusName = state + switch state { + case common.StateOpen: + issue.Status = 1 + case common.StateProcessing: + issue.Status = 2 + case common.StateSuspend: + issue.Status = 5 + case common.StateClosed: + issue.Status = 3 + } + + models.UpdateIssueTemplate(issue, "Status", "StatusName") + + stateId, ok := common.StateIdMap[state] + if !ok { + return errors.New("can not find state id") + } + + return taskhandler.UpdateIssueStateToGitee(issue.IssueId, stateId) +} + +func GetIssueStateByAllReason(issue *models.IssueTemplate) (string, error) { + allState, err := StateByAllReason(issue) + if err != nil { + return "", err + } + + return MaxPriorityState(allState), nil +} + +func MaxPriorityState(allState []string) string { + var maxPriority string + for _, v := range common.StatePriority { + for _, state := range allState { + if v == state { + maxPriority = v + } + } + } + + return maxPriority +} + +func StateByAllReason(issue *models.IssueTemplate) (allState []string, err error) { + var mergedPR []string + if issue.ContainsWillFix() { + if mergedPR, err = GetMergedPR(issue); err != nil { + return + } + } + + split := strings.Split(issue.AnalysisVersion, ",") + for _, v := range split { + allState = append(allState, StateFromReason(v, mergedPR)) + } + + return +} + +func GetRelatedPR(issue *models.IssueTemplate) (prs []sdk.PullRequest, err error) { + token := beego.AppConfig.String("gitee::git_token") + + endpoint := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/issues/%v/pull_requests?access_token=%s&repo=%s", + issue.Owner, issue.IssueNum, token, issue.Repo, + ) + req, err := http.NewRequest(http.MethodGet, endpoint, nil) + if err != nil { + return + } + + cli := utils.NewHttpClient(3) + b, _, err := cli.Download(req) + if err != nil { + return + } + + err = json.Unmarshal(b, &prs) + + return +} + +func GetMergedPR(issue *models.IssueTemplate) ([]string, error) { + prs, err := GetRelatedPR(issue) + if err != nil { + return nil, err + } + + var mergedPR []string + for _, pr := range prs { + if pr.State == "merged" { + mergedPR = append(mergedPR, pr.Base.Ref) + } + } + + return mergedPR, nil +} + +func StateFromReason(branchAndReason string, mergedPR []string) string { + item := strings.Split(strings.ReplaceAll(branchAndReason, ":", ":"), ":") + if len(item) != 2 || item[1] == "" { + return common.StateOpen + } + + if v, ok := common.AnalysisStateMap[item[1]]; ok { + return v + } + + // 原因为正常修复的分支,需要看对应分支的PR是否合入来决定状态 + mergedPRSets := sets.NewString(mergedPR...) + if mergedPRSets.Has(item[0]) { + return common.StateClosed + } else { + return common.StateProcessing + } +} diff --git a/cve-vulner-manager/models/issue.go b/cve-vulner-manager/models/issue.go index c9f0a1a..22f1eba 100644 --- a/cve-vulner-manager/models/issue.go +++ b/cve-vulner-manager/models/issue.go @@ -6,6 +6,8 @@ import ( "strings" "sync" + "github.com/astaxie/beego" + "cvevulner/common" "cvevulner/util" @@ -789,3 +791,31 @@ func (t *IssueTemplate) IsIssueComplete() bool { const StatusCompleted = 3 return t.Status == StatusCompleted } + +func (t *IssueTemplate) ContainsWillFix() bool { + return strings.Contains(t.AnalysisVersion, common.AnalysisWillFix) +} + +func (t *IssueTemplate) IsAllUnaffected() bool { + split := strings.Split(t.AnalysisVersion, ",") + for _, v := range split { + item := strings.Split(strings.ReplaceAll(v, ":", ":"), ":") + if len(item) != 2 { + return false + } + + if _, ok := common.AnalysisUnaffected[item[1]]; !ok { + return false + } + } + + return true +} + +func (t *IssueTemplate) ResetLabel() { + if t.IsAllUnaffected() { + t.IssueLabel = beego.AppConfig.String("labeUnaffected") + } else { + t.IssueLabel = beego.AppConfig.String("labelFixed") + } +} diff --git a/cve-vulner-manager/taskhandler/issue.go b/cve-vulner-manager/taskhandler/issue.go index 75da6b9..88c898c 100644 --- a/cve-vulner-manager/taskhandler/issue.go +++ b/cve-vulner-manager/taskhandler/issue.go @@ -1,6 +1,7 @@ package taskhandler import ( + "encoding/json" "fmt" "strings" "time" @@ -288,3 +289,29 @@ func UpdateEntIssueDetail(enterpriseId, issueId int64, token, planAt, deadLine s return } } + +type updateIssueState struct { + AccessToken string `json:"access_token"` + IssueStateId int64 `json:"issue_state_id"` +} + +func UpdateIssueStateToGitee(issueId, stateId int64) error { + at := models.AuthTokenInfo{OrganizationID: models.OrganizationIdOpeneuler} + if err := models.QueryAuthTokenById(&at, "organizate_id"); err != nil { + return err + } + + url := fmt.Sprintf("https://api.gitee.com/enterprises/%v/issues/%v", at.EnId, issueId) + request := updateIssueState{ + AccessToken: at.AccessToken, + IssueStateId: stateId, + } + + payload, err := json.Marshal(request) + if err != nil { + return err + } + + _, err = util.HTTPPutMap(url, string(payload)) + return err +} -- Gitee From 65fa58050db9156f0b9930d0230b907712961a02 Mon Sep 17 00:00:00 2001 From: yangwei999 <348134071@qq.com> Date: Mon, 13 Jan 2025 09:41:20 +0800 Subject: [PATCH 2/5] collect and bulletin need status 5 in vuln --- .../cve-ddd/infrastructure/repositoryimpl/impl.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cve-vulner-manager/cve-ddd/infrastructure/repositoryimpl/impl.go b/cve-vulner-manager/cve-ddd/infrastructure/repositoryimpl/impl.go index 5aeebb3..5c75679 100644 --- a/cve-vulner-manager/cve-ddd/infrastructure/repositoryimpl/impl.go +++ b/cve-vulner-manager/cve-ddd/infrastructure/repositoryimpl/impl.go @@ -31,7 +31,7 @@ join cve_security_notice c on a.cve_id=c.cve_id where a.cve_num in (%s) and a.cve_status = 2 and a.organizate_id = 1 -and b.status < 4 +and b.status in (1,2,3,5) ` if opt.Component != "" { sql += fmt.Sprintf(`and a.pack_name = "%s"`, opt.Component) @@ -119,7 +119,7 @@ func (impl repositoryImpl) GetAllIssue() (data domain.CollectedDataSlice, err er sql := `select a.*, b.affect_product, b.will_fix_product from cve_issue_template a join cve_security_notice b on a.cve_id=b.cve_id where a.cve_id in (select cve_id from cve_vuln_center where cve_status = 2 and is_export in (0,3) and organizate_id = 1) - and a.status < 4 + and a.status in (1,2,3,5) ` var issueTemp []list -- Gitee From bc98182ea8dfe6bd746c47fc3fc54b586a98f7a0 Mon Sep 17 00:00:00 2001 From: yangwei999 <348134071@qq.com> Date: Thu, 16 Jan 2025 15:18:37 +0800 Subject: [PATCH 3/5] fix reset label --- cve-vulner-manager/controllers/hook.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/cve-vulner-manager/controllers/hook.go b/cve-vulner-manager/controllers/hook.go index 10d9bb3..dd49f78 100644 --- a/cve-vulner-manager/controllers/hook.go +++ b/cve-vulner-manager/controllers/hook.go @@ -490,9 +490,7 @@ func closeIssueProc(issueHook *models.IssuePayload, issueTmp *models.IssueTempla } if issueTmp.IsIssueComplete() { - if issueTmp.IsAllUnaffected() { - issueTmp.ResetLabel() - } + issueTmp.ResetLabel() } } } @@ -1347,9 +1345,7 @@ func maintainerApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, } if issueTmp.IsIssueComplete() { - if issueTmp.IsAllUnaffected() { - issueTmp.ResetLabel() - } + issueTmp.ResetLabel() } updateTempAndCenter(*issueTmp, cveCenter, token, owner) @@ -1383,9 +1379,7 @@ func securityApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, } if issueTmp.IsIssueComplete() { - if issueTmp.IsAllUnaffected() { - issueTmp.ResetLabel() - } + issueTmp.ResetLabel() } updateTempAndCenter(*issueTmp, cveCenter, token, owner) @@ -1879,9 +1873,7 @@ func analysisComment(owner, accessToken, path string, cuAccount string, cBody st } if issueTmp.IsIssueComplete() { - if issueTmp.IsAllUnaffected() { - issueTmp.ResetLabel() - } + issueTmp.ResetLabel() } updateTempAndCenter(issueTmp, v, accessToken, owner) -- Gitee From ac60aa5bfc87a69d6805f74588b5f973bef8fd3c Mon Sep 17 00:00:00 2001 From: yangwei999 <348134071@qq.com> Date: Thu, 16 Jan 2025 16:10:03 +0800 Subject: [PATCH 4/5] release cve with issue status 5 --- cve-vulner-manager/models/cve.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cve-vulner-manager/models/cve.go b/cve-vulner-manager/models/cve.go index 1bee1d7..a9cbc2d 100644 --- a/cve-vulner-manager/models/cve.go +++ b/cve-vulner-manager/models/cve.go @@ -1110,7 +1110,7 @@ is_export in (0,3) and pack_name in ('%s') and organizate_id = 1) and status < 4 func GetUnffectIssueNumber(startTime string, cves []string) (issueTemp []IssueTemplate, err error) { var sql string if len(cves) == 0 { - sql = `SELECT * FROM cve_issue_template WHERE STATUS <= 3 AND issue_status in (1,2,3,6) AND cve_id IN ( + sql = `SELECT * FROM cve_issue_template WHERE STATUS in (1,2,3,5) AND issue_status in (1,2,3,6) AND cve_id IN ( SELECT DISTINCT cve_id FROM cve_vuln_center WHERE cve_status = 2 AND is_export IN (0,3) and organizate_id = 1) AND create_time >= '%s'` } else { -- Gitee From f6a8e6c15754898c52285de33d3bf1727b9b0d4b Mon Sep 17 00:00:00 2001 From: yangwei999 <348134071@qq.com> Date: Thu, 6 Feb 2025 11:39:13 +0800 Subject: [PATCH 5/5] fix ci --- cve-vulner-manager/common/analysis.go | 28 ++++++++++++--- cve-vulner-manager/controllers/hook.go | 45 +++++++++++++++++-------- cve-vulner-manager/models/issue.go | 6 +++- cve-vulner-manager/taskhandler/issue.go | 1 + 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/cve-vulner-manager/common/analysis.go b/cve-vulner-manager/common/analysis.go index 8d24a6e..dde7774 100644 --- a/cve-vulner-manager/common/analysis.go +++ b/cve-vulner-manager/common/analysis.go @@ -62,7 +62,7 @@ var ( AnalysisCodeNotPresent, ) - AnalysisStateMap = map[string]string{ + analysisStateMap = map[string]string{ AnalysisStill: StateSuspend, AnalysisNoPatch: StateSuspend, AnalysisUpgrade: StateSuspend, @@ -75,24 +75,44 @@ var ( AnalysisCodeNotPresent: StateClosed, } - StatePriority = []string{ + statePriority = []string{ StateClosed, StateSuspend, StateProcessing, StateOpen, } - StateNameMap = map[string]string{ + stateNameMap = map[string]string{ StateClosed: "已完成", StateSuspend: "已挂起", StateProcessing: "进行中", StateOpen: "待办的", } - StateIdMap = map[string]int64{ + stateIdMap = map[string]int64{ StateClosed: 437577, StateSuspend: 751673, StateProcessing: 437576, StateOpen: 437575, } ) + +// GetAnalysisStateMap returns a map containing the analysis states and their corresponding values. +func GetAnalysisStateMap() map[string]string { + return analysisStateMap +} + +// GetStatePriority returns the priority of states as a slice of strings. +func GetStatePriority() []string { + return statePriority +} + +// GetStateNameMap returns a map of state names to their corresponding values. +func GetStateNameMap() map[string]string { + return stateNameMap +} + +// GetStateIdMap returns a map of state names to their corresponding IDs. +func GetStateIdMap() map[string]int64 { + return stateIdMap +} diff --git a/cve-vulner-manager/controllers/hook.go b/cve-vulner-manager/controllers/hook.go index dd49f78..1839089 100644 --- a/cve-vulner-manager/controllers/hook.go +++ b/cve-vulner-manager/controllers/hook.go @@ -14,7 +14,7 @@ import ( "sync" "time" - sdk "github.com/opensourceways/go-gitee/gitee" + "github.com/opensourceways/go-gitee/gitee" "github.com/opensourceways/server-common-lib/utils" "k8s.io/apimachinery/pkg/util/sets" @@ -2424,6 +2424,7 @@ func gitDelIssueProc(issueHook *models.IssuePayload, organizationID int8) error return nil } +// SetIssueStateByReason sets the issue state based on the given reason. func SetIssueStateByReason(issue *models.IssueTemplate, remoteStateName string) error { state, err := GetIssueStateByAllReason(issue) if err != nil { @@ -2431,7 +2432,8 @@ func SetIssueStateByReason(issue *models.IssueTemplate, remoteStateName string) } // issue本身的状态和计算后的状态一致,则不做任何操作 - stateName, ok := common.StateNameMap[state] + stateNameMap := common.GetStateNameMap() + stateName, ok := stateNameMap[state] if !ok || stateName == remoteStateName { return nil } @@ -2450,7 +2452,8 @@ func SetIssueStateByReason(issue *models.IssueTemplate, remoteStateName string) models.UpdateIssueTemplate(issue, "Status", "StatusName") - stateId, ok := common.StateIdMap[state] + stateIdMap := common.GetStateIdMap() + stateId, ok := stateIdMap[state] if !ok { return errors.New("can not find state id") } @@ -2458,6 +2461,7 @@ func SetIssueStateByReason(issue *models.IssueTemplate, remoteStateName string) return taskhandler.UpdateIssueStateToGitee(issue.IssueId, stateId) } +// GetIssueStateByAllReason retrieves the issue state based on all reasons associated with the issue. func GetIssueStateByAllReason(issue *models.IssueTemplate) (string, error) { allState, err := StateByAllReason(issue) if err != nil { @@ -2467,9 +2471,10 @@ func GetIssueStateByAllReason(issue *models.IssueTemplate) (string, error) { return MaxPriorityState(allState), nil } +// MaxPriorityState returns the state with the highest priority from the given list of states. func MaxPriorityState(allState []string) string { var maxPriority string - for _, v := range common.StatePriority { + for _, v := range common.GetStatePriority() { for _, state := range allState { if v == state { maxPriority = v @@ -2480,23 +2485,27 @@ func MaxPriorityState(allState []string) string { return maxPriority } -func StateByAllReason(issue *models.IssueTemplate) (allState []string, err error) { +// StateByAllReason return all reason from the given issue. +func StateByAllReason(issue *models.IssueTemplate) ([]string, error) { var mergedPR []string + var err error if issue.ContainsWillFix() { if mergedPR, err = GetMergedPR(issue); err != nil { - return + return nil, err } } split := strings.Split(issue.AnalysisVersion, ",") + var allState []string for _, v := range split { allState = append(allState, StateFromReason(v, mergedPR)) } - return + return allState, nil } -func GetRelatedPR(issue *models.IssueTemplate) (prs []sdk.PullRequest, err error) { +// GetRelatedPR retrieves related pull requests for a given issue template. +func GetRelatedPR(issue *models.IssueTemplate) ([]gitee.PullRequest, error) { token := beego.AppConfig.String("gitee::git_token") endpoint := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/issues/%v/pull_requests?access_token=%s&repo=%s", @@ -2504,20 +2513,23 @@ func GetRelatedPR(issue *models.IssueTemplate) (prs []sdk.PullRequest, err error ) req, err := http.NewRequest(http.MethodGet, endpoint, nil) if err != nil { - return + return nil, err } - cli := utils.NewHttpClient(3) + const retryTimes = 3 + cli := utils.NewHttpClient(retryTimes) b, _, err := cli.Download(req) if err != nil { - return + return nil, err } + var prs []gitee.PullRequest err = json.Unmarshal(b, &prs) - return + return prs, err } +// GetMergedPR retrieves a list of merged pull requests related to the given issue. func GetMergedPR(issue *models.IssueTemplate) ([]string, error) { prs, err := GetRelatedPR(issue) if err != nil { @@ -2534,13 +2546,18 @@ func GetMergedPR(issue *models.IssueTemplate) ([]string, error) { return mergedPR, nil } +// StateFromReason determines the state of a pull request based on the branch and reason provided. +// It returns the state as a string. If the branch and reason are not valid or the reason is empty, +// it returns the common.StateOpen. func StateFromReason(branchAndReason string, mergedPR []string) string { + const splitLen = 2 item := strings.Split(strings.ReplaceAll(branchAndReason, ":", ":"), ":") - if len(item) != 2 || item[1] == "" { + if len(item) != splitLen || item[1] == "" { return common.StateOpen } - if v, ok := common.AnalysisStateMap[item[1]]; ok { + analysisStateMap := common.GetAnalysisStateMap() + if v, ok := analysisStateMap[item[1]]; ok { return v } diff --git a/cve-vulner-manager/models/issue.go b/cve-vulner-manager/models/issue.go index 8506cd7..d5dc6a9 100644 --- a/cve-vulner-manager/models/issue.go +++ b/cve-vulner-manager/models/issue.go @@ -811,15 +811,18 @@ func (t *IssueTemplate) HasAffected() bool { return false } +// ContainsWillFix checks if the AnalysisVersion contains the common.AnalysisWillFix string. func (t *IssueTemplate) ContainsWillFix() bool { return strings.Contains(t.AnalysisVersion, common.AnalysisWillFix) } +// IsAllUnaffected splits the AnalysisVersion by commas and checks if all parts are unaffected. func (t *IssueTemplate) IsAllUnaffected() bool { + const splitLen = 2 split := strings.Split(t.AnalysisVersion, ",") for _, v := range split { item := strings.Split(strings.ReplaceAll(v, ":", ":"), ":") - if len(item) != 2 { + if len(item) != splitLen { return false } @@ -831,6 +834,7 @@ func (t *IssueTemplate) IsAllUnaffected() bool { return true } +// ResetLabel resets the issue label based on whether the issue is all unaffected or fixed. func (t *IssueTemplate) ResetLabel() { if t.IsAllUnaffected() { t.IssueLabel = beego.AppConfig.String("labeUnaffected") diff --git a/cve-vulner-manager/taskhandler/issue.go b/cve-vulner-manager/taskhandler/issue.go index 88c898c..f3b407e 100644 --- a/cve-vulner-manager/taskhandler/issue.go +++ b/cve-vulner-manager/taskhandler/issue.go @@ -295,6 +295,7 @@ type updateIssueState struct { IssueStateId int64 `json:"issue_state_id"` } +// UpdateIssueStateToGitee update issue state with enterprise api. func UpdateIssueStateToGitee(issueId, stateId int64) error { at := models.AuthTokenInfo{OrganizationID: models.OrganizationIdOpeneuler} if err := models.QueryAuthTokenById(&at, "organizate_id"); err != nil { -- Gitee