Skip to content

Commit

Permalink
✨ adding ability to run dep command during analysis command (#531)
Browse files Browse the repository at this point in the history
Make it so that the analysis command can also, in parallel can do the
dependency output if desired

Signed-off-by: Shawn Hurley <[email protected]>
  • Loading branch information
shawn-hurley authored Mar 13, 2024
1 parent dc5fbe1 commit e0b3756
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 5 deletions.
13 changes: 8 additions & 5 deletions .github/workflows/demo-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ jobs:

- name: run demo image and ensure violations output unchanged
run: |
podman run -v $(pwd)/demo-output.yaml:/analyzer-lsp/output.yaml:Z localhost/testing:latest
podman run --entrypoint /usr/bin/konveyor-analyzer -v $(pwd)/demo-dep-output.yaml:/analyzer-lsp/demo-dep-output.yaml:Z -v $(pwd)/demo-output.yaml:/analyzer-lsp/output.yaml:Z localhost/testing:latest --dep-output-file=demo-dep-output.yaml
diff \
<(yq -P 'sort_keys(..)' -o=props <(git show HEAD:demo-output.yaml)) \
<(yq -P 'sort_keys(..)' -o=props <(cat demo-output.yaml))
- name: run demo image and ensure dependency output unchanged
run: |
podman run --entrypoint /usr/bin/konveyor-analyzer-dep -v $(pwd)/demo-dep-output.yaml:/analyzer-lsp/demo-dep-output.yaml:Z localhost/testing:latest --output-file=demo-dep-output.yaml
diff \
<(yq -P 'sort_keys(..)' -o=props <(git show HEAD:demo-dep-output.yaml)) \
<(yq -P 'sort_keys(..)' -o=props <(cat demo-dep-output.yaml))
# - name: run demo image and ensure dependency output unchanged
# run: |
# podman run --entrypoint /usr/bin/konveyor-analyzer-dep -v $(pwd)/demo-dep-output.yaml:/analyzer-lsp/demo-dep-output.yaml:Z localhost/testing:latest --output-file=demo-dep-output.yaml --dep-output-file=de
# diff \
# <(yq -P 'sort_keys(..)' -o=props <(git show HEAD:demo-dep-output.yaml)) \
# <(yq -P 'sort_keys(..)' -o=props <(cat demo-dep-output.yaml))

- uses: actions/checkout@v3
with:
fetch-depth: 0
Expand Down
105 changes: 105 additions & 0 deletions cmd/analyzer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"sort"
"strings"
"sync"

logrusr "github.com/bombsimon/logrusr/v3"
"github.com/go-logr/logr"
Expand All @@ -21,6 +22,7 @@ import (
"github.com/spf13/cobra"
"github.com/swaggest/openapi-go/openapi3"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"gopkg.in/yaml.v2"
)

Expand All @@ -45,6 +47,8 @@ var (
noDependencyRules bool
contextLines int
getOpenAPISpec string
treeOutput bool
depOutputFile string
)

func AnalysisCmd() *cobra.Command {
Expand Down Expand Up @@ -205,8 +209,22 @@ func AnalysisCmd() *cobra.Command {
initSpan.End()
}

wg := &sync.WaitGroup{}
var depSpan trace.Span
var depCtx context.Context
if depOutputFile != "" {
depCtx, depSpan = tracing.StartNewSpan(ctx, "dep")
wg.Add(1)
go DependencyOutput(depCtx, providers, log, errLog, depOutputFile, dependencyLabelSelector, wg)
}

// This will already wait
rulesets := eng.RunRules(ctx, ruleSets, selectors...)
engineSpan.End()
wg.Wait()
if depSpan != nil {
depSpan.End()
}
eng.Stop()

for _, provider := range needProviders {
Expand Down Expand Up @@ -248,6 +266,8 @@ func AnalysisCmd() *cobra.Command {
rootCmd.Flags().BoolVar(&noDependencyRules, "no-dependency-rules", false, "Disable dependency analysis rules")
rootCmd.Flags().IntVar(&contextLines, "context-lines", 10, "When violation occurs, A part of source code is added to the output, So this flag configures the number of source code lines to be printed to the output.")
rootCmd.Flags().StringVar(&getOpenAPISpec, "get-openapi-spec", "", "Get the openAPI spec for the rulesets, rules and provider capabilities and put in file passed in.")
rootCmd.Flags().BoolVar(&treeOutput, "tree", false, "output dependencies as a tree")
rootCmd.Flags().StringVar(&depOutputFile, "dep-output-file", "", "path to dependency output file")

return rootCmd
}
Expand Down Expand Up @@ -399,3 +419,88 @@ func createOpenAPISchema(providers map[string]provider.InternalProviderClient, l

return sc
}

func DependencyOutput(ctx context.Context, providers map[string]provider.InternalProviderClient, log logr.Logger, errLog logr.Logger, depOutputFile string, labelSelector *labels.LabelSelector[*konveyor.Dep], wg *sync.WaitGroup) {
defer wg.Done()
var depsFlat []konveyor.DepsFlatItem
var depsTree []konveyor.DepsTreeItem
for name, prov := range providers {
if !provider.HasCapability(prov.Capabilities(), "dependency") {
log.Info("provider does not have dependency capability", "provider", name)
continue
}

if treeOutput {
deps, err := prov.GetDependenciesDAG(ctx)
if err != nil {
errLog.Error(err, "failed to get list of dependencies for provider", "provider", name)
continue
}
for u, ds := range deps {
depsTree = append(depsTree, konveyor.DepsTreeItem{
FileURI: string(u),
Provider: name,
Dependencies: ds,
})
}
} else {
deps, err := prov.GetDependencies(ctx)
if err != nil {
errLog.Error(err, "failed to get list of dependencies for provider", "provider", name)
continue
}
for u, ds := range deps {
newDeps := ds
if labelSelector != nil {
newDeps, err = labelSelector.MatchList(ds)
if err != nil {
errLog.Error(err, "error matching label selector on deps")
continue
}
}
depsFlat = append(depsFlat, konveyor.DepsFlatItem{
Provider: name,
FileURI: string(u),
Dependencies: newDeps,
})
}
}
}

if depsFlat == nil && depsTree == nil {
errLog.Info("failed to get dependencies from all given providers")
os.Exit(1)
}

var b []byte
var err error
if treeOutput {
b, err = yaml.Marshal(depsTree)
if err != nil {
errLog.Error(err, "failed to marshal dependency data as yaml")
os.Exit(1)
}
} else {
// Sort depsFlat
sort.SliceStable(depsFlat, func(i, j int) bool {
if depsFlat[i].Provider == depsFlat[j].Provider {
return depsFlat[i].FileURI < depsFlat[j].FileURI
} else {
return depsFlat[i].Provider < depsFlat[j].Provider
}
})

b, err = yaml.Marshal(depsFlat)
if err != nil {
errLog.Error(err, "failed to marshal dependency data as yaml")
os.Exit(1)
}
}

err = os.WriteFile(depOutputFile, b, 0644)
if err != nil {
errLog.Error(err, "failed to write dependencies to output file", "file", depOutputFile)
os.Exit(1)
}

}

0 comments on commit e0b3756

Please sign in to comment.