github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/api/fossa/issues.go (about)

     1  package fossa
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"regexp"
     7  
     8  	"github.com/pkg/errors"
     9  )
    10  
    11  const IssuesAPI = "/api/cli/%s/issues"
    12  
    13  // A wrapped list of issues returned by the FOSSA CLI issues endpoint
    14  // If a push-only API key is used, then only the count is returned
    15  type Issues struct {
    16  	Count  int
    17  	Issues []Issue
    18  	Status string
    19  
    20  	NormalizedByType map[string][]Issue
    21  }
    22  
    23  // An Issue holds the FOSSA API response for the issue API.
    24  type Issue struct {
    25  	ID             int    `json:"id"`
    26  	PriorityString string `json:"priorityString"`
    27  	Resolved       bool   `json:"resolved"`
    28  	RevisionID     string `json:"revisionId"`
    29  	Type           string `json:"type"`
    30  	Rule           Rule   `json:"rule"`
    31  
    32  	Name     string
    33  	Revision string
    34  }
    35  
    36  // Rule holds the representation of an Issue's Rule.
    37  type Rule struct {
    38  	License string `json:"licenseId"`
    39  }
    40  
    41  // GetIssues loads the issues for a project.
    42  func GetIssues(locator Locator) (Issues, error) {
    43  	var issues Issues
    44  	_, err := GetJSON(fmt.Sprintf(IssuesAPI, url.PathEscape(locator.OrgString())), &issues)
    45  	if err != nil {
    46  		return Issues{}, errors.Wrap(err, "could not get Issues from API")
    47  	}
    48  
    49  	issues.normalize()
    50  	return issues, nil
    51  }
    52  
    53  func (issues *Issues) normalize() {
    54  	typeMap := make(map[string][]Issue)
    55  	for _, issue := range issues.Issues {
    56  		issue.extractLocator()
    57  		formattedType := formatType(issue.Type)
    58  		typeMap[formattedType] = append(typeMap[formattedType], issue)
    59  	}
    60  
    61  	issues.NormalizedByType = typeMap
    62  }
    63  
    64  func formatType(issueType string) string {
    65  	switch issueType {
    66  	case "policy_conflict":
    67  		return "Denied by Policy"
    68  	case "policy_flag":
    69  		return "Flagged by Policy"
    70  	case "vulnerability":
    71  		return "Vulnerability"
    72  	case "unlicensed_dependency":
    73  		return "Unlicensed Dependency"
    74  	case "outdated_dependency":
    75  		return "Outdated Dependency"
    76  	default:
    77  		return issueType
    78  	}
    79  }
    80  
    81  func (issue *Issue) extractLocator() {
    82  	locator := regexp.MustCompile("[+$]").Split(issue.RevisionID, -1)
    83  	if len(locator) >= 2 {
    84  		issue.Name = locator[1]
    85  	}
    86  	if len(locator) >= 3 {
    87  		issue.Revision = locator[2]
    88  	}
    89  }