Skip to content

Commit

Permalink
WIP: analysis command refactor complete
Browse files Browse the repository at this point in the history
  • Loading branch information
elldritch committed Jun 7, 2018
1 parent 20365ba commit 64d77b4
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 188 deletions.
2 changes: 1 addition & 1 deletion .fossa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ analyze:
modules:
- name: fossa
path: cmd/fossa
type: Go
type: go
10 changes: 10 additions & 0 deletions api/fossa/locator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package fossa
import (
"regexp"
"strings"

"github.com/fossas/fossa-cli/pkg"
)

type Locator struct {
Expand Down Expand Up @@ -67,3 +69,11 @@ func ReadImportPath(s ImportPathString) ImportPath {
}
return out
}

func LocatorOf(id pkg.ID) Locator {
return Locator{
Fetcher: id.Type.String(),
Project: id.Name,
Revision: id.Revision,
}
}
68 changes: 35 additions & 33 deletions api/fossa/normalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/pkg/errors"

"github.com/fossas/fossa-cli/module"
"github.com/fossas/fossa-cli/pkg"
)

Expand Down Expand Up @@ -43,42 +44,43 @@ func NormalizeType(t pkg.Type) (string, error) {
switch t {
case pkg.NodeJS:
return "commonjspackage", nil
default:
return t.String(), nil
}
return "", errors.Errorf("unknown module type: %s", string(t))
return "", errors.Errorf("unknown module type: %s", t.String())
}

// func Normalize(analysis []module.Analyzed) ([]SourceUnit, error) {
// var normalized []SourceUnit
// for _, analyzed := range analysis {
// var deps []Dependency
// for _, dep := range analyzed.Dependencies {
// data, err := json.Marshal(dep)
// if err != nil {
// return nil, errors.Wrap(err, "could not marshal analyzed dependency")
// }
func Normalize(modules []module.Module) ([]SourceUnit, error) {
var normalized []SourceUnit
for _, analyzed := range modules {
var deps []Dependency
for _, dep := range analyzed.Deps {
data, err := json.Marshal(dep)
if err != nil {
return nil, errors.Wrap(err, "could not marshal analyzed dependency")
}

// deps = append(deps, Dependency{
// Locator: dep.Locator.String(),
// Data: (*json.RawMessage)(&data),
// })
// }
deps = append(deps, Dependency{
Locator: LocatorOf(dep.ID).String(),
Data: (*json.RawMessage)(&data),
})
}

// normalizedType, err := NormalizeType(analyzed.pkg.Type)
// if err != nil {
// return nil, errors.Wrap(err, "could not normalize analyzed module type")
// }
normalizedType, err := NormalizeType(analyzed.Type)
if err != nil {
return nil, errors.Wrap(err, "could not normalize analyzed module type")
}

// normalized = append(normalized, SourceUnit{
// Name: analyzed.Module.Name,
// Type: normalizedType,
// Manifest: analyzed.Module.Target,
// Build: Build{
// Artifact: "default",
// Context: analyzed.Builder,
// Succeeded: true,
// Dependencies: deps,
// },
// })
// }
// return normalized, nil
// }
normalized = append(normalized, SourceUnit{
Name: analyzed.Name,
Type: normalizedType,
Manifest: analyzed.BuildTarget,
Build: Build{
Artifact: "default",
Succeeded: true,
Dependencies: deps,
},
})
}
return normalized, nil
}
120 changes: 52 additions & 68 deletions cmd/fossa/cmd/analyze/analyze.go
Original file line number Diff line number Diff line change
@@ -1,93 +1,77 @@
package main
package analyze

import (
"encoding/json"
"fmt"
"os"

"github.com/urfave/cli"

"github.com/fossas/fossa-cli/analyzers"
"github.com/fossas/fossa-cli/api/fossa"
"github.com/fossas/fossa-cli/cmd/fossa/cmdutil"
"github.com/fossas/fossa-cli/cmd/fossa/flags"
"github.com/fossas/fossa-cli/config"
"github.com/fossas/fossa-cli/log"
"github.com/fossas/fossa-cli/module"
"github.com/urfave/cli"
)

func analyzeCmd(c *cli.Context) {
conf, err := config.New(c)
if err != nil {
log.Logger.Fatalf("Could not load configuration: %s", err.Error())
}
if len(conf.Modules) == 0 {
log.Logger.Fatal("No modules specified.")
}
var (
Output = "output"
)

analyses, err := doAnalyze(conf.Modules, conf.AnalyzeCmd.AllowUnresolved)
if err != nil {
log.Logger.Fatalf("Analysis failed: %s", err.Error())
}
var Cmd = cli.Command{
Name: "analyze",
Usage: "Analyze built dependencies",
Action: Run,
ArgsUsage: "MODULE",
Flags: flags.WithGlobalFlags(flags.WithAPIFlags(flags.WithModulesFlags([]cli.Flag{
cli.BoolFlag{Name: flags.Short(Output), Usage: "show analysis output instead of uploading to FOSSA"},
}))),
}

log.Logger.Debugf("Analysis complete: %#v", analyses)
var _ cli.ActionFunc = Run

normalModules, err := normalizeAnalysis(analyses)
func Run(ctx *cli.Context) error {
err := cmdutil.Init(ctx)
if err != nil {
log.Logger.Fatalf("Could not normalize build data: %s", err.Error())
}

if conf.AnalyzeCmd.Output {
buildData, err := json.Marshal(normalModules)
if err != nil {
log.Logger.Fatalf("Could not marshal analysis results: %s", err.Error())
}
fmt.Println(string(buildData))
os.Exit(0)
return
log.Logger.Fatalf("Could not initialize: %s", err.Error())
}

msg, err := doUpload(conf, normalModules)
modules, err := config.Modules()
if err != nil {
log.Logger.Fatalf("Upload failed: %s", err.Error())
log.Logger.Fatalf("Could not parse modules: %s", err.Error())
}
if len(modules) == 0 {
log.Logger.Fatal("No modules specified.")
}
fmt.Print(msg)
}

type analysis struct {
builder module.Builder
module module.Module
dependencies []module.Dependency
}

func doAnalyze(modules []module.Config, allowUnresolved bool) ([]analysis, error) {
log.Logger.Debugf("Running analysis on modules: %#v", modules)
analyses := []analysis{}

for _, moduleConfig := range modules {
builder, m, err := resolveModuleConfig(moduleConfig)
if err != nil {
return nil, fmt.Errorf("failed to resolve modules: %s", err.Error())
}

err = builder.Initialize()
if err != nil {
return nil, fmt.Errorf("failed to initialize build: %s", err.Error())
}

isBuilt, err := builder.IsBuilt(m, allowUnresolved)
var analyzed []module.Module
defer log.StopSpinner()
for i, m := range modules {
log.ShowSpinner(fmt.Sprintf("Analyzing module (%d/%d): %s", i+1, len(modules), m.Name))
analyzer, err := analyzers.New(m.Type, m.Options)
if err != nil {
return nil, fmt.Errorf("could not determine whether module %#v is built: %#v", m.Name, err.Error())
}
if !isBuilt {
return nil, fmt.Errorf("module %s does not appear to be built (try first running your build or `fossa build`, and then running `fossa`)", m.Name)
log.Logger.Warningf("Could not load analyzer: %s", err.Error())
}

deps, err := builder.Analyze(m, allowUnresolved)
result, err := analyzer.Analyze(m)
if err != nil {
return nil, fmt.Errorf("analysis failed on module %s: %s", m.Name, err.Error())
log.Logger.Warningf("Could not analyze: %s", err.Error())
}
analyses = append(analyses, analysis{
builder: builder,
module: m,
dependencies: deps,
})
analyzed = append(analyzed, result)
}
log.StopSpinner()

return analyses, nil
normalized, err := fossa.Normalize(analyzed)
if err != nil {
log.Logger.Fatalf("Could not normalize output: %s", err.Error())
}
if ctx.Bool(Output) {
log.Printf("%#v", normalized)
return nil
}
locator, err := fossa.Upload(config.Fetcher(), config.Project(), config.Revision(), config.Title(), config.Branch(), normalized)
if err != nil {
log.Logger.Fatalf("Error during upload: %s", err.Error())
}
log.Printf(cmdutil.FmtReportURL(locator))
return nil
}
5 changes: 4 additions & 1 deletion cmd/fossa/cmd/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ func Run(ctx *cli.Context) error {
log.Logger.Fatalf("Could not initialize: %s", err.Error())
}

modules := config.Modules()
modules, err := config.Modules()
if err != nil {
log.Logger.Fatalf("Could not parse modules: %s", err.Error())
}
if len(modules) == 0 {
log.Logger.Fatal("No modules specified.")
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/fossa/cmd/test/test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package test

import (
"encoding/json"
Expand Down
45 changes: 16 additions & 29 deletions cmd/fossa/cmd/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package upload
import (
"encoding/json"
"io/ioutil"
"net/url"
"os"
"strings"

Expand All @@ -17,13 +16,17 @@ import (
"github.com/fossas/fossa-cli/log"
)

var (
Locators = "locators"
)

var Cmd = cli.Command{
Name: "upload",
Usage: "Uploads user-provided test results to FOSSA",
Action: Run,
ArgsUsage: "DATA",
Flags: flags.WithGlobalFlags([]cli.Flag{
cli.BoolFlag{Name: "l, locators", Usage: "upload data in locator format (instead of JSON)"},
cli.BoolFlag{Name: flags.Short(Locators), Usage: "upload data in locator format (instead of JSON)"},
}),
}

Expand Down Expand Up @@ -89,49 +92,33 @@ func getInput(ctx *cli.Context, usingLocators bool) ([]fossa.SourceUnit, error)
}

func Run(ctx *cli.Context) {
cmdutil.Init(ctx)
c := config.MustNew(ctx)
err := cmdutil.Init(ctx)
if err != nil {
log.Logger.Fatalf("Could not initialize: %s", err.Error())
}

data, err := getInput(ctx, c.UploadCmd.UseLocators)
data, err := getInput(ctx, ctx.Bool(Locators))
if err != nil {
log.Logger.Fatalf("Bad input: %s", err.Error())
}

locator, err := Do(c, data)
locator, err := Do(data)
if err != nil {
log.Logger.Fatalf("Upload failed: %s", err.Error())
}
baseURL, err := url.Parse(c.Endpoint)
reportBranch := c.Branch
if reportBranch == "" {
reportBranch = "master"
}
reportURL, err := url.Parse("/projects/" + url.QueryEscape(locator.Fetcher+"+"+locator.Project) + "/refs/branch/" + reportBranch + "/" + url.QueryEscape(locator.Revision) + "/browse/dependencies")
log.Printf(`
============================================================
View FOSSA Report:
` + strings.Replace(baseURL.ResolveReference(reportURL).String(), "%", "%%", -1) + `
============================================================
`)
log.Printf(cmdutil.FmtReportURL(locator))
}

func Do(c config.CLIConfig, data []fossa.SourceUnit) (fossa.Locator, error) {
if c.Project == "" {
func Do(data []fossa.SourceUnit) (fossa.Locator, error) {
if config.Project() == "" {
log.Logger.Fatalf("Could not infer project name from either `.fossa.yml` or `git` remote named `origin`")
}
if c.Fetcher != "custom" && c.Revision == "" {
if config.Fetcher() != "custom" && config.Revision() == "" {
log.Logger.Fatalf("Could not infer revision name from `git` remote named `origin`. To submit a custom project, set Fetcher to `custom` in `.fossa.yml`")
}
if len(data) == 0 {
log.Logger.Fatalf("No data to upload")
}

title := data[0].Name
if c.Fetcher == "custom" && title == "" {
title = c.Project
}

return fossa.Upload(c.Fetcher, c.Project, c.Revision, title, c.Branch, data)
return fossa.Upload(config.Fetcher(), config.Project(), config.Revision(), config.Title(), config.Branch(), data)
}

0 comments on commit 64d77b4

Please sign in to comment.