Skip to content

Commit

Permalink
refactor(cmd): Use IO services for effects [WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
elldritch committed Apr 4, 2018
1 parent 013e269 commit 571cf4e
Show file tree
Hide file tree
Showing 36 changed files with 2,348 additions and 61 deletions.
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

84 changes: 84 additions & 0 deletions api/normalize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package api

import (
"encoding/json"

"github.com/pkg/errors"

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

type SourceUnit struct {
Name string
Type string
Manifest string
Build Build
}

type Build struct {
Artifact string
Context interface{}

Succeeded bool
Error error `json:",omitempty"`

Dependencies []Dependency
}

type Dependency struct {
// Location
Locator string `json:"locator"`

// Metadata
Data *json.RawMessage `json:"data,omitempty"`

// Context
Depth int `json:"depth,omitempty"`
Parent string `json:"parent,omitempty"`
UnresolvedLocators []string `json:"unresolved_locators,omitempty"`
}

func NormalizeType(t module.Type) (string, error) {
// TODO: handle more normalizations
switch t {
case module.Nodejs:
return "commonjspackage", nil
}
return "", errors.Errorf("unknown module type: %s", string(t))
}

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")
}

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

normalizedType, err := NormalizeType(analyzed.Module.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
}
92 changes: 92 additions & 0 deletions cmd/fossa/analyze/analyze.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package analyze

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

"github.com/urfave/cli"

"github.com/fossas/fossa-cli/config"
"github.com/fossas/fossa-cli/module"
"github.com/fossas/fossa-cli/services"
)

func Run(c *cli.Context) {
conf := config.MustNew(c)
io := services.New(false, false)

if len(conf.Modules) == 0 {
io.Logger.Fatalf("No modules specified.")
}

analysis, err := doAnalyze(conf.Modules, conf.AnalyzeCmd.AllowUnresolved)
if err != nil {
io.Logger.Fatalf("Analysis failed: %s", err.Error())
}
io.Logger.Debugf("Analysis complete: %#v", analysis)

normalModules, err := normalizeAnalysis(analysis)
if err != nil {
io.Logger.Fatalf("Could not normalize build data: %s", err.Error())
}

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

msg, err := doUpload(conf, normalModules)
if err != nil {
io.Logger.Fatalf("Upload failed: %s", err.Error())
}
fmt.Print(msg)
}

type analysisKey struct {
builder module.Builder
module module.Module
}

type analysis map[analysisKey][]module.Dependency

func Do(modules []module.Config, allowUnresolved bool) (analysis, error) {
io.Logger.Debugf("Running analysis on modules: %#v", modules)
dependencies := make(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)
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)
}

deps, err := builder.Analyze(m, allowUnresolved)
if err != nil {
return nil, fmt.Errorf("analysis failed on module %s: %s", m.Name, err.Error())
}
dependencies[analysisKey{
builder: builder,
module: m,
}] = deps
}

return dependencies, nil
}
12 changes: 12 additions & 0 deletions cmd/fossa/common/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package common

import "github.com/urfave/cli"

var GlobalFlags = []cli.Flag{
cli.BoolFlag{Name: "debug", Usage: "print debug information to stderr"},
cli.BoolFlag{Name: "no-ansi", Usage: "do not use interactive mode (ANSI codes)"},
}

func WithGlobalFlags(flags []cli.Flag) []cli.Flag {
return append(flags, GlobalFlags...)
}
19 changes: 19 additions & 0 deletions cmd/fossa/common/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package common

import (
"github.com/urfave/cli"

"github.com/fossas/fossa-cli/config"
"github.com/fossas/fossa-cli/services"
)

func MustInit(ctx *cli.Context) (services.Services, config.CLIConfig) {
c := config.MustNew(ctx)
io := services.New(c.Interactive, c.Debug)
err := io.API.Initialize(c.Endpoint, c.APIKey)
if err != nil {
io.Logger.Fatalf("Could not initialize API: %s", err.Error())
}

return io, c
}
27 changes: 11 additions & 16 deletions cmd/fossa/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/urfave/cli"

"github.com/fossas/fossa-cli/builders"
"github.com/fossas/fossa-cli/cmd/fossa/upload"
"github.com/fossas/fossa-cli/config"
"github.com/fossas/fossa-cli/module"
)
Expand Down Expand Up @@ -40,15 +41,23 @@ func main() {
app.Name = "fossa-cli"
app.Usage = "Fast, portable and reliable dependency analysis (https://github.com/fossas/fossa-cli/)"
app.Version = fmt.Sprintf("%s (revision %s compiled with %s)", version, commit, goversion)
app.Metadata = make(map[string]interface{})
app.Metadata["version"] = version

app.Action = defaultCmd
app.Flags = []cli.Flag{
cli.StringFlag{Name: "c, config", Usage: configUsage},
cli.StringFlag{Name: "p, project", Usage: projectUsage},
cli.StringFlag{Name: "r, revision", Usage: revisionUsage},
cli.StringFlag{Name: "e, endpoint", Usage: endpointUsage},
cli.StringFlag{Name: "m, modules", Usage: "the modules to build and analyze"},
cli.StringSliceFlag{Name: "m, modules", Usage: "the modules to build and analyze"},
cli.StringFlag{Name: "fetcher", Usage: fetcherUsage},
// --strategy=pipreqs
// --strategy=foo:bar
// --gradle-task=foo
// --gradle-configuration=bar
// --allow-unbuilt
// --no-ansi
cli.BoolFlag{Name: "o, output", Usage: analyzeOutputUsage},
cli.BoolFlag{Name: "allow-unresolved", Usage: analyzeAllowResolvedUsage},
cli.BoolFlag{Name: "b, build", Usage: "run a default build in module directories if they have not been pre-built"},
Expand Down Expand Up @@ -109,21 +118,7 @@ func main() {
cli.BoolFlag{Name: "debug", Usage: debugUsage},
},
},
{
Name: "upload",
Usage: "Uploads user-provided test results to FOSSA",
Action: uploadCmd,
Flags: []cli.Flag{
cli.StringFlag{Name: "c, config", Usage: configUsage},
cli.StringFlag{Name: "fetcher", Usage: fetcherUsage},
cli.StringFlag{Name: "p, project", Usage: projectUsage},
cli.StringFlag{Name: "r, revision", Usage: revisionUsage},
cli.StringFlag{Name: "e, endpoint", Usage: endpointUsage},
cli.BoolFlag{Name: "l, locators", Usage: "upload data in locator format instead of JSON"},
cli.StringFlag{Name: "d, data", Usage: "the user-provided build data to upload"},
cli.BoolFlag{Name: "debug", Usage: debugUsage},
},
},
upload.Cmd,
{
Name: "update",
Usage: "Updates `fossa` to the latest version",
Expand Down
2 changes: 1 addition & 1 deletion cmd/fossa/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func reportLicenses(s *spinner.Spinner, endpoint, apiKey string, a analysis) {
for _, deps := range a {
for _, dep := range deps {
if module.IsResolved(dep) {
locator := module.DepLocator(dep)
locator := module.LocatorOf(dep)
goPkg, ok := dep.(builders.GoPkg)
if ok {
locator = module.MakeLocator("git", goPkg.ImportPath, goPkg.Version)
Expand Down
4 changes: 2 additions & 2 deletions cmd/fossa/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func normalize(builder module.Builder, m module.Module, deps []module.Dependency
}

normalDeps = append(normalDeps, normalizedDependency{
Locator: string(module.DepLocator(deps[i])),
Locator: string(module.LocatorOf(deps[i])),
Data: (*json.RawMessage)(&data),
})
}
Expand Down Expand Up @@ -98,7 +98,7 @@ func uploadCmd(c *cli.Context) {
}

var data []normalizedModule
if conf.UploadCmd.Locators {
if conf.UploadCmd.UseLocators {
var deps []normalizedDependency
lines := strings.Split(conf.UploadCmd.Data, "\n")
for _, line := range lines {
Expand Down
Loading

0 comments on commit 571cf4e

Please sign in to comment.