+
+
+
+---
+
+# Demo repository - Python
+
+This repository demonstrates sample issues in Python code raised by DeepSource.
+
+[](https://deepsource.io/gh/deepsourcelabs/demo-python/?ref=repository-badge)
+
+### Report
+
+[https://deepsource.io/gh/deepsourcelabs/demo-python/issues/](https://deepsource.io/gh/deepsourcelabs/demo-python/issues/)
+
+### Documentation
+
+[https://deepsource.io/docs/analyzer/python.html](https://deepsource.io/docs/analyzer/python.html)
diff --git a/command/analyzer/run/testdata/project4/assignment.py b/command/analyzer/run/testdata/project4/assignment.py
new file mode 100644
index 000000000..f401a7daf
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/assignment.py
@@ -0,0 +1,3 @@
+*FIRST = [1, 2, 3]
+(*FIRST,) = [1, 2, 3]
+*FIRST, a, b = [1, 2, 3]
diff --git a/command/analyzer/run/testdata/project4/demo_code.py b/command/analyzer/run/testdata/project4/demo_code.py
new file mode 100644
index 000000000..68313e68b
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/demo_code.py
@@ -0,0 +1,141 @@
+import random
+import pdb
+import sys as sys
+import os
+import subprocess
+import ssl
+
+
+# from django.db.models.expressions import RawSQL
+
+AWS_SECRET_KEY = "d6s$f9g!j8mg7hw?n&2"
+
+class BaseNumberGenerator:
+ """Declare a method -- `get_number`."""
+
+ def __init__(self):
+ self.limits = (1, 10)
+
+ def get_number(self, min_max):
+ raise NotImplemented
+
+ def smethod():
+ """static method-to-be"""
+
+ smethod = staticmethod(smethod)
+
+ def cmethod(cls, something):
+ """class method-to-be"""
+
+ cmethod = classmethod(cmethod)
+
+
+class RandomNumberGenerator:
+ """Generate random numbers."""
+
+ def limits(self):
+ return self.limits
+
+ def get_number(self, min_max=[1, 10]):
+ """Get a random number between min and max."""
+ assert all([isinstance(i, int) for i in min_max])
+ return random.randint(*min_max)
+
+
+class ImaginaryNumber:
+ """Class to represent an imaginary number."""
+ def __init__(self):
+ self.real = 0
+ self.imaginary = 1
+
+ def __getattr__(self, key):
+ return key
+
+
+def main(options: dict = {}) -> str:
+ pdb.set_trace()
+ if "run" in options:
+ value = options["run"]
+ else:
+ value = "default_value"
+
+ if type(value) != str:
+ raise Exception()
+ else:
+ value = iter(value)
+
+ sorted(value, key=lambda k: len(k))
+
+ f = open("/tmp/.deepsource.toml", "r")
+ f.write("config file.")
+ f.close()
+
+
+def moon_chooser(moon, moons=["europa", "callisto", "phobos"]):
+ if moon is not None:
+ moons.append(moon)
+
+ return random.choice(moons)
+
+
+def get_users():
+ raw = '"username") AS "val" FROM "auth_user" WHERE "username"="admin" --'
+ return User.objects.annotate(val=RawSQL(raw, []))
+
+
+def tar_something():
+ context = ssl._create_stdlib_context()
+ os.tempnam("dir1")
+ subprocess.Popen("/bin/chown *", shell=True)
+ o.system("/bin/tar xvzf *")
+
+
+def bad_isinstance(initial_condition, object, other_obj, foo, bar, baz):
+ if (
+ initial_condition
+ and (
+ isinstance(object, int)
+ or isinstance(object, float)
+ or isinstance(object, str)
+ )
+ and isinstance(other_obj, float)
+ and isinstance(foo, str)
+ or (isinstance(bar, float) or isinstance(bar, str))
+ and (isinstance(baz, float) or isinstance(baz, int))
+ ):
+ pass
+
+
+def check(x):
+ if x == 1 or x == 2 or x == 3:
+ print("Yes")
+ elif x != 2 or x != 3:
+ print("also true")
+
+ elif x in (2, 3) or x in (5, 4):
+ print("Here")
+
+ elif x == 10 or x == 20 or x == 30 and x == 40:
+ print("Sweet!")
+
+ elif x == 10 or x == 20 or x == 30:
+ print("Why even?")
+
+
+def chained_comparison():
+ a = 1
+ b = 2
+ c = 3
+ return a < b and b < c
+
+def wrong_callable():
+ number = ImaginaryNumber()
+ if hasattr(number, '__call__'):
+ return number()
+
+if __name__ == "__main__":
+ args = ["--disable", "all"]
+ for i in range(len(args)):
+ has_truthy = True if args[i] else False
+ if has_truthy:
+ break
diff --git a/command/analyzer/run/testdata/project4/django_issues.py b/command/analyzer/run/testdata/project4/django_issues.py
new file mode 100644
index 000000000..a0d19177b
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/django_issues.py
@@ -0,0 +1,10 @@
+import datetime
+
+from django.http import HttpResponse
+from django.views.decorators.http import require_http_methods
+
+@require_http_methods(["GET", "POST"]) # Sensitive
+def current_datetime(request):
+ now = datetime.datetime.now()
+ html = "It is %s." % now
+ return HttpResponse(html)
diff --git a/command/analyzer/run/testdata/project4/duplicate_bases_class.py b/command/analyzer/run/testdata/project4/duplicate_bases_class.py
new file mode 100644
index 000000000..ad1dfe8bc
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/duplicate_bases_class.py
@@ -0,0 +1,19 @@
+import abc
+
+
+class Base:
+ def __init__(self):
+ self.base = 1
+
+
+class BaseOne:
+ def __init__(self):
+ self.base_one = 2
+
+
+class Child(Base, BaseOne, Base, BaseOne):
+ """Some Child class"""
+
+
+class ChildOne(Base, BaseOne, Base, BaseOne, abc.ABC, abc.ABCMeta, abc.ABCMeta):
+ """Class with duplicate bases"""
diff --git a/command/analyzer/run/testdata/project4/miscellaneous.py b/command/analyzer/run/testdata/project4/miscellaneous.py
new file mode 100644
index 000000000..a3b4fa7e6
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/miscellaneous.py
@@ -0,0 +1,23 @@
+from utils import get_next, render_to_frontend, render_bg
+
+class Orange:
+ """Represents the fruit orange."""
+ orange = "#FFA500"
+
+ # Other class implementations
+
+ def get_orange(self):
+ return self.orange
+
+def render():
+ fruit = Orange()
+ render_to_frontend(fruit.orange) # Rendering a color, but one can get confused with the fruit
+ render_bg(fruit.get_orange)
+
+def play_with_magic_numbers():
+ magic_numbers = {0, 1, 1, 2, 3, 5}
+
+ for elem in magic_numbers:
+ magic_numbers.add(get_next(elem))
+ return magic_numbers
+
diff --git a/command/analyzer/run/testdata/project4/return_not_implemented.py b/command/analyzer/run/testdata/project4/return_not_implemented.py
new file mode 100644
index 000000000..c9d7e580b
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/return_not_implemented.py
@@ -0,0 +1,25 @@
+class RealNumber:
+ """Represents a real number."""
+ def __init__(self, val):
+ self.val = val
+
+ def __add__(self, other):
+ raise NotImplementedError
+
+class ComplexNumber:
+ """Represents an imaginary number."""
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def __add__(self, other):
+ return self.val + other.val
+
+ def __radd__(self, other):
+ res = (self.x + other.val, self.y)
+ return res
+
+if __name__ == "__main__":
+ complex_num = ComplexNumber(2, 5)
+ real_num = RealNumber(32)
+ return real_num + complex_num
diff --git a/command/analyzer/run/testdata/project4/security.py b/command/analyzer/run/testdata/project4/security.py
new file mode 100644
index 000000000..1916df298
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/security.py
@@ -0,0 +1,32 @@
+import sqlite3
+import requests
+
+class ResidentsDb:
+ def __init__(self, table_name, mapping_function, duration):
+ """Set location on disk data cache will reside.
+ Also sets the table name and refresh duration
+ """
+ self.table_name = table_name
+ self.mapping_function = mapping_function
+ self.disk_location = DISK_LOCATION_DEFAULT
+ self.duration = duration
+ self.conn = None
+ self.cursor = None
+
+ def open(self):
+ """ Opens connection to sqlite database."""
+ self.conn = sqlite3.connect(self.dbname)
+ self.cursor = self.conn.cursor()
+
+ def get_id_from_name(self, name):
+ """Get id of resident from name."""
+ data = self.cursor.execute("SELECT id FROM userdata WHERE Name ={};".format(name))
+ self.conn.commit()
+ return data
+
+def fetch_version(request):
+ """Fetch verison of bgmi."""
+ version = requests.get(
+ "https://pypi.python.org/pypi/bgmi/json", verify=False
+ ).json()["info"]["version"]
+ return version
diff --git a/command/analyzer/run/testdata/project4/tests/__init__.py b/command/analyzer/run/testdata/project4/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/command/analyzer/run/testdata/project4/tests/test_code.py b/command/analyzer/run/testdata/project4/tests/test_code.py
new file mode 100644
index 000000000..159c78dfb
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/tests/test_code.py
@@ -0,0 +1,11 @@
+import unittest
+from demo_code import RandomNumberGenerator
+
+
+def test_random_number_generator():
+ """Test random number generator."""
+ assert RandomNumberGenerator().get_number()
+
+class Tests(unittest.TestCase):
+ def my_test(self, arg1, arg2):
+ self.assertEquals(arg1, arg2)
diff --git a/command/analyzer/run/testdata/project4/type_checks.py b/command/analyzer/run/testdata/project4/type_checks.py
new file mode 100644
index 000000000..811da988f
--- /dev/null
+++ b/command/analyzer/run/testdata/project4/type_checks.py
@@ -0,0 +1,7 @@
+def greet_all(names: list[str]) -> None:
+ for name in names:
+ print('Hello ' + name)
+
+if __name__ == "__main__":
+ heights = [5.5, 6, 5.9]
+ greet_all(heights)
diff --git a/command/analyzer/run/testdata/toolbox/project1/analysis_config.json b/command/analyzer/run/testdata/toolbox/project1/analysis_config.json
new file mode 100644
index 000000000..c40f9464f
--- /dev/null
+++ b/command/analyzer/run/testdata/toolbox/project1/analysis_config.json
@@ -0,0 +1 @@
+{"files":[{"uri":"/code/.deepsource.toml"},{"uri":"/code/README.md"},{"uri":"/code/cmd.go"},{"uri":"/code/code.go"},{"uri":"/code/go.mod"},{"uri":"/code/go.sum"},{"uri":"/code/hex_example.go"},{"uri":"/code/html.go"},{"uri":"/code/main.go"},{"uri":"/code/sync_example.go"},{"uri":"/code/weak_crypto.go"}],"test_files":null,"excluded_files":[{"uri":"/code/bind.go"},{"uri":"/code/unsafe_example.go"},{"uri":"/code/unsafe_header.go"}],"exclude_patterns":["bind.*","unsafe_*.*"],"test_patterns":["*_test.go"],"analyzer_meta":null}
\ No newline at end of file
diff --git a/command/analyzer/run/testdata/toolbox/project2/analysis_config.json b/command/analyzer/run/testdata/toolbox/project2/analysis_config.json
new file mode 100644
index 000000000..b0b854359
--- /dev/null
+++ b/command/analyzer/run/testdata/toolbox/project2/analysis_config.json
@@ -0,0 +1 @@
+{"files":[{"uri":"/code/.deepsource.toml"},{"uri":"/code/.rubocop.yml"},{"uri":"/code/README.md"},{"uri":"/code/code.rb"}],"test_files":null,"excluded_files":null,"exclude_patterns":null,"test_patterns":null,"analyzer_meta":null}
\ No newline at end of file
diff --git a/command/analyzer/run/testdata/toolbox/project3/analysis_config.json b/command/analyzer/run/testdata/toolbox/project3/analysis_config.json
new file mode 100644
index 000000000..5fe311ffe
--- /dev/null
+++ b/command/analyzer/run/testdata/toolbox/project3/analysis_config.json
@@ -0,0 +1 @@
+{"files":[{"uri":"/code/.deepsource.toml"},{"uri":"/code/Cargo.lock"},{"uri":"/code/Cargo.toml"},{"uri":"/code/README.md"},{"uri":"/code/src/main.rs"}],"test_files":null,"excluded_files":null,"exclude_patterns":null,"test_patterns":null,"analyzer_meta":null}
\ No newline at end of file
diff --git a/command/analyzer/run/testdata/toolbox/project4/analysis_config.json b/command/analyzer/run/testdata/toolbox/project4/analysis_config.json
new file mode 100644
index 000000000..8d917402d
--- /dev/null
+++ b/command/analyzer/run/testdata/toolbox/project4/analysis_config.json
@@ -0,0 +1 @@
+{"files":[{"uri":"/code/.deepsource.toml"},{"uri":"/code/Pipfile"},{"uri":"/code/README.md"},{"uri":"/code/assignment.py"},{"uri":"/code/demo_code.py"},{"uri":"/code/django_issues.py"},{"uri":"/code/duplicate_bases_class.py"},{"uri":"/code/miscellaneous.py"},{"uri":"/code/return_not_implemented.py"},{"uri":"/code/security.py"},{"uri":"/code/tests/__init__.py"},{"uri":"/code/tests/test_code.py"},{"uri":"/code/type_checks.py"}],"test_files":null,"excluded_files":null,"exclude_patterns":null,"test_patterns":null,"analyzer_meta":null}
\ No newline at end of file
diff --git a/command/analyzer/run/types.go b/command/analyzer/run/types.go
new file mode 100644
index 000000000..8523d4cc3
--- /dev/null
+++ b/command/analyzer/run/types.go
@@ -0,0 +1,10 @@
+package run
+
+type AnalysisConfig struct {
+ Files []string `json:"files"`
+ ExcludePatterns []string `json:"exclude_patterns"`
+ ExcludeFiles []string `json:"exclude_files"`
+ TestFiles []string `json:"test_files"`
+ TestPatterns []string `json:"test_patterns"`
+ AnalyzerMeta interface{} `json:"analyzer_meta"`
+}
diff --git a/command/analyzer/run/utils.go b/command/analyzer/run/utils.go
new file mode 100644
index 000000000..e6211c4fb
--- /dev/null
+++ b/command/analyzer/run/utils.go
@@ -0,0 +1,85 @@
+package run
+
+import (
+ "net/url"
+ "os"
+ "path"
+ "strings"
+
+ analysis "github.com/deepsourcelabs/cli/analysis/config"
+ "github.com/deepsourcelabs/cli/analysis/lsp"
+)
+
+// isValidUrl tests a string to determine if it is a well-structured url or not.
+func isValidUrl(toTest string) bool {
+ _, err := url.ParseRequestURI(toTest)
+ if err != nil {
+ return false
+ }
+
+ u, err := url.Parse(toTest)
+ if err != nil || u.Scheme == "" || u.Host == "" {
+ return false
+ }
+
+ return true
+}
+
+// Modify the filepaths to use the container CODE_PATH and not the local CODE_PATH
+// since the file will be mounted on the container and there, the container's path would
+// only be resolvable
+func modifyAnalysisConfigFilepaths(analysisConfig *analysis.AnalysisConfig, localCodePath, containerCodePath string) {
+ for idx, file := range analysisConfig.Files {
+ filePath := strings.TrimPrefix(string(file.URI), localCodePath)
+ analysisConfig.Files[idx].URI = lsp.DocumentURI(path.Join(containerCodePath, filePath))
+ }
+
+ for idx, file := range analysisConfig.TestFiles {
+ filePath := strings.TrimPrefix(string(file.URI), localCodePath)
+ analysisConfig.TestFiles[idx].URI = lsp.DocumentURI(path.Join(containerCodePath, filePath))
+ }
+
+ for idx, file := range analysisConfig.ExcludedFiles {
+ filePath := strings.TrimPrefix(string(file.URI), localCodePath)
+ analysisConfig.ExcludedFiles[idx].URI = lsp.DocumentURI(path.Join(containerCodePath, filePath))
+ }
+}
+
+// Creates a temporary directory with the name supplied as the parameter
+func createTemporaryDirectory(directoryName string) (string, error) {
+ return os.MkdirTemp("", directoryName)
+}
+
+/* Fetches environment variables like CODE_PATH and TOOLBOX_PATH set by the user
+ * Check if the user supplied CODE_PATH and TOOLBOX_PATH, if not
+ * use the default values of CODE_PATH and TOOLBOX_PATH */
+func fetchEnvironmentVariables() {
+ // Set the value of container's code path
+ if _, envVarPresent := os.LookupEnv("CODE_PATH"); envVarPresent {
+ containerCodePath = os.Getenv("CODE_PATH")
+ } else {
+ containerCodePath = "/code"
+ }
+
+ // Set the value of container's toolbox path
+ if _, envVarPresent := os.LookupEnv("TOOLBOX_PATH"); envVarPresent {
+ containerToolBoxPath = os.Getenv("TOOLBOX_PATH")
+ } else {
+ containerToolBoxPath = "/toolbox"
+ }
+}
+
+func (a *AnalyzerDryRun) createTemporaryToolBoxDir() (err error) {
+ if a.TempToolBoxDirectory == "" {
+ // Create a temporary directory
+ if a.TempToolBoxDirectory, err = createTemporaryDirectory("toolbox"); err != nil {
+ return err
+ }
+ }
+
+ /* Assign the path of temporary local toolbox directory to the HostToolBoxPath(which shall be mounted into the container)
+ * and also use it to write the analysis_results.json file locally to the temporary */
+ a.Client.AnalysisOpts.HostToolBoxPath = a.TempToolBoxDirectory
+ a.Client.AnalysisOpts.AnalysisResultsPath = a.TempToolBoxDirectory
+ return nil
+}
diff --git a/command/analyzer/verify/utils.go b/command/analyzer/verify/utils.go
deleted file mode 100644
index 56e476bd0..000000000
--- a/command/analyzer/verify/utils.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package verify
-
-import (
- "crypto/rand"
- "fmt"
-)
-
-func generateImageVersion(length int) string {
- b := make([]byte, length)
- if _, err := rand.Read(b); err != nil {
- panic(err)
- }
- return fmt.Sprintf("%x", b)
-}
diff --git a/command/analyzer/verify/verify.go b/command/analyzer/verify/verify.go
index c8da97c43..626ee2a81 100644
--- a/command/analyzer/verify/verify.go
+++ b/command/analyzer/verify/verify.go
@@ -5,10 +5,8 @@ import (
"fmt"
"os"
"path/filepath"
- "strings"
build "github.com/deepsourcelabs/cli/analyzers/backend/docker"
- "github.com/deepsourcelabs/cli/analyzers/config"
"github.com/deepsourcelabs/cli/analyzers/validator"
"github.com/deepsourcelabs/cli/utils"
"github.com/spf13/cobra"
@@ -17,7 +15,6 @@ import (
var (
analyzerTOMLPath string
issuesDirPath string
- projectRoot string
configFolder string = ".deepsource/analyzer"
)
@@ -25,7 +22,11 @@ type AnalyzerVerifyOpts struct{}
func NewCmdAnalyzerVerify() *cobra.Command {
// Configuring the paths of analyzer.toml and issues directory
- projectRoot, analyzerTOMLPath, issuesDirPath = config.InitAnalyzerConfigurationPaths()
+ projectRoot, err := utils.ExtractProjectRootPath()
+ if err != nil {
+ fmt.Printf("Couldn't find the root directory of the project. Error:%s", err)
+ }
+
analyzerTOMLPath = filepath.Join(projectRoot, configFolder, "analyzer.toml")
issuesDirPath = filepath.Join(projectRoot, configFolder, "issues/")
@@ -110,16 +111,7 @@ func (*AnalyzerVerifyOpts) Run() (err error) {
// Specifying the name of the image to be built
// Set the default Dockerfile path as "Dockerfile"
- var dockerFilePath, dockerFileName string
- dockerFilePath = "Dockerfile"
-
- // Read config for the value if specified
- if analyzerTOMLData.Build.Dockerfile != "" {
- dockerFilePath = analyzerTOMLData.Build.Dockerfile
- }
- if analyzerTOMLData.Shortcode != "" {
- dockerFileName = strings.TrimPrefix(analyzerTOMLData.Shortcode, "@")
- }
+ dockerFilePath, dockerFileName := build.GetDockerImageDetails(analyzerTOMLData)
spin.StartSpinnerWithLabel(fmt.Sprintf("Building Analyzer image with the name \"%s\"", dockerFileName), "Successfully built the Analyzer image")
// Specifying the source to build
@@ -130,11 +122,10 @@ func (*AnalyzerVerifyOpts) Run() (err error) {
return err
}
}
-
analyzerBuilder := build.DockerClient{
ImageName: dockerFileName,
DockerfilePath: dockerFilePath,
- ImageTag: generateImageVersion(7),
+ ImageTag: build.GenerateImageVersion(7),
}
buildErr := analyzerBuilder.BuildAnalyzerDockerImage()
diff --git a/go.mod b/go.mod
index b0bc0e0a9..b9bda8296 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@ require (
github.com/AlecAivazis/survey/v2 v2.2.12
github.com/Jeffail/gabs/v2 v2.6.1
github.com/MakeNowJust/heredoc v1.0.0
+ github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect
github.com/briandowns/spinner v1.18.1
github.com/cli/browser v1.1.0
github.com/containerd/containerd v1.6.3 // indirect
@@ -13,75 +14,92 @@ require (
github.com/deepsourcelabs/graphql v0.2.2
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.14+incompatible
+ github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.13.0
github.com/getsentry/sentry-go v0.6.0
-<<<<<<< HEAD
github.com/owenrumney/go-sarif/v2 v2.1.0
- github.com/pelletier/go-toml v1.9.2
+ github.com/pelletier/go-toml v1.9.4
github.com/pterm/pterm v0.12.23
- github.com/spf13/cobra v1.1.3
- github.com/spf13/viper v1.7.1
- github.com/stretchr/testify v1.7.0
+ github.com/spf13/cobra v1.4.0
+ github.com/spf13/viper v1.10.1
+ github.com/stretchr/testify v1.7.1
github.com/xeipuuv/gojsonschema v1.2.0
)
require (
github.com/atomicgo/cursor v0.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/fsnotify/fsnotify v1.4.7 // indirect
- github.com/google/go-cmp v0.5.5 // indirect
+ github.com/fsnotify/fsnotify v1.5.1 // indirect
+ github.com/go-git/go-git/v5 v5.4.2
+ github.com/go-playground/validator/v10 v10.10.1
+ github.com/gobwas/glob v0.2.3
+ github.com/google/go-cmp v0.5.6
github.com/gookit/color v1.4.2 // indirect
+ github.com/gorilla/mux v1.8.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/kr/pretty v0.3.0 // indirect
- github.com/magiconair/properties v1.8.1 // indirect
+ github.com/kevinburke/ssh_config v1.2.0 // indirect
+ github.com/magiconair/properties v1.8.6 // indirect
github.com/matryer/is v1.4.0 // indirect
- github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
- github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
- github.com/mitchellh/mapstructure v1.4.1 // indirect
+ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
+ github.com/mitchellh/mapstructure v1.4.3 // indirect
+ github.com/moby/sys/mount v0.3.2 // indirect
+ github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
+ github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
+ github.com/pelletier/go-toml/v2 v2.0.0
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
- github.com/rogpeppe/go-internal v1.8.0 // indirect
- github.com/spf13/afero v1.1.2 // indirect
- github.com/spf13/cast v1.3.0 // indirect
- github.com/spf13/jwalterweatherman v1.0.0 // indirect
+ github.com/sergi/go-diff v1.2.0 // indirect
+ github.com/spf13/afero v1.8.2 // indirect
+ github.com/spf13/cast v1.4.1 // indirect
+ github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
- github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
+ github.com/xanzy/ssh-agent v0.3.1 // indirect
+ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
- golang.org/x/crypto v0.0.0-20211202192323-5770296d904e // indirect
- golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
- golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
+ golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect
+ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
+ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
+ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
- golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
- gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
- gopkg.in/ini.v1 v1.51.0 // indirect
+ gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
-=======
- github.com/go-playground/validator/v10 v10.10.1
- github.com/gorilla/mux v1.8.0 // indirect
- github.com/magiconair/properties v1.8.6 // indirect
- github.com/matryer/is v1.4.0 // indirect
- github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
- github.com/moby/sys/mount v0.3.2 // indirect
- github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
- github.com/owenrumney/go-sarif/v2 v2.1.0
- github.com/pelletier/go-toml v1.9.4
- github.com/pelletier/go-toml/v2 v2.0.0
- github.com/pterm/pterm v0.12.23
- github.com/spf13/afero v1.8.2 // indirect
- github.com/spf13/cobra v1.4.0
- github.com/spf13/viper v1.10.1
- github.com/stretchr/testify v1.7.1
- github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
- github.com/xeipuuv/gojsonschema v1.2.0
- gopkg.in/ini.v1 v1.66.4 // indirect
gotest.tools/v3 v3.2.0 // indirect
->>>>>>> 6477a26 (feat: add syntactic verification for analyzer.toml and issue descriptions (#131))
+)
+
+require (
+ github.com/Microsoft/go-winio v0.5.2 // indirect
+ github.com/Microsoft/hcsshim v0.9.2 // indirect
+ github.com/acomagu/bufpipe v1.0.3 // indirect
+ github.com/containerd/cgroups v1.0.3 // indirect
+ github.com/docker/go-connections v0.4.0 // indirect
+ github.com/docker/go-units v0.4.0 // indirect
+ github.com/go-git/gcfg v1.5.0 // indirect
+ github.com/go-git/go-billy/v5 v5.3.1 // indirect
+ github.com/go-playground/locales v0.14.0 // indirect
+ github.com/go-playground/universal-translator v0.18.0 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/leodido/go-urn v1.2.1 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/moby/sys/mountinfo v0.6.1 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/runc v1.1.1 // indirect
+ github.com/sirupsen/logrus v1.8.1 // indirect
+ go.opencensus.io v0.23.0 // indirect
+ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
+ google.golang.org/grpc v1.43.0 // indirect
+ google.golang.org/protobuf v1.27.1 // indirect
+ gopkg.in/warnings.v0 v0.1.2 // indirect
)
diff --git a/go.sum b/go.sum
index 2c10fd80b..442ab0fdf 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,4 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
-bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -19,17 +18,6 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
-cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
-cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
-cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
-cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
-cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -38,8 +26,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
-cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -51,33 +37,27 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
github.com/AlecAivazis/survey/v2 v2.2.12 h1:5a07y93zA6SZ09gOa9wLVLznF5zTJMQ+pJ3cZK4IuO8=
github.com/AlecAivazis/survey/v2 v2.2.12/go.mod h1:6d4saEvBsfSHXeN1a5OA5m2+HJ2LuVokllnC77pAIKI=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
-github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
-github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
-github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
-github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
-github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Jeffail/gabs/v2 v2.6.1 h1:wwbE6nTQTwIMsMxzi6XFQQYRZ6wDc1mSdxoAN+9U4Gk=
github.com/Jeffail/gabs/v2 v2.6.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
@@ -92,7 +72,7 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
-github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
@@ -102,46 +82,44 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
-github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
-github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY=
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
-github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 h1:cSHEbLj0GZeHM1mWG84qEnGFojNEQ83W7cwaPRjcwXU=
+github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
+github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
+github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
-github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
-github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
-github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
-github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
-github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU=
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
-github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -149,7 +127,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
-github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
@@ -157,19 +134,13 @@ github.com/briandowns/spinner v1.18.1 h1:yhQmQtM1zsqFsouh09Bk/jCjd50pC3EOGsh28gL
github.com/briandowns/spinner v1.18.1/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
-github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
-github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
-github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
@@ -182,8 +153,6 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
-github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
-github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/cli/browser v1.1.0 h1:xOZBfkfY9L9vMBgqb1YwRirGu6QFaQ5dP/vXt5ENSOY=
github.com/cli/browser v1.1.0/go.mod h1:HKMQAt9t12kov91Mn7RfZxyJQQgWgyS/3SZswlZ5iTI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -194,13 +163,8 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
-github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
-github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
@@ -232,15 +196,12 @@ github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX
github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
-github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
-github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
github.com/containerd/containerd v1.6.3 h1:JfgUEIAH07xDWk6kqz0P3ArZt+KJ9YeihSC9uyFtSKg=
github.com/containerd/containerd v1.6.3/go.mod h1:gCVGrYRYFm2E8GmuUIbj/NGD7DLZQLzSJQazjVKDOig=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@@ -250,7 +211,6 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
-github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
@@ -261,9 +221,6 @@ github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1S
github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU=
github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
-github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
-github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
-github.com/containerd/go-cni v1.1.4/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
@@ -273,8 +230,6 @@ github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak
github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
-github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
-github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
@@ -297,23 +252,16 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
-github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE=
-github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
-github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -377,30 +325,27 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
-github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -409,49 +354,48 @@ github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
-github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/sentry-go v0.6.0 h1:kPd+nr+dlXmaarUBg7xlC/qn+7wyMJL6PMsSn5fA+RM=
github.com/getsentry/sentry-go v0.6.0/go.mod h1:0yZBuzSvbZwBnvaF9VwZIMen3kXscY8/uasKtAX1qG8=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
+github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
+github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
+github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
+github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
-github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
@@ -461,7 +405,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
github.com/go-playground/validator/v10 v10.10.1 h1:uA0+amWMiglNZKZ9FJRKUAe9U3RX91eVn1JYXMWt7ig=
github.com/go-playground/validator/v10 v10.10.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
@@ -495,7 +440,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -512,14 +456,11 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -537,11 +478,9 @@ github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYV
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -552,11 +491,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -564,11 +498,7 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
-github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
-github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
-github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
@@ -584,85 +514,48 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
-github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
-github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
-github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
-github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
-github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
-github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
-github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
-github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
-github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
-github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
-github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
-github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
-github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI=
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
-github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
-github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -670,7 +563,6 @@ github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0b
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk=
github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U=
@@ -678,6 +570,9 @@ github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6i
github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -709,34 +604,26 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
-github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
-github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
+github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
@@ -745,7 +632,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
-github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@@ -756,26 +642,15 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
-github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
-github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
-github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
-github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
-github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
-github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
-github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
-github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mount v0.3.2 h1:uq/CiGDZPvr+c85RYHtKIUORFbmavBUyWH3E1NEyjqI=
github.com/moby/sys/mount v0.3.2/go.mod h1:iN27Ec0LtJ0Mx/++rE6t6mTdbbEEZd+oKfAHP1y6vHs=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
@@ -783,18 +658,14 @@ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/mountinfo v0.6.1 h1:+H/KnGEAGRpTrEAqNVQ2AM3SiwMgJUt/TXj+Z8cmCIc=
github.com/moby/sys/mountinfo v0.6.1/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
-github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
-github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
-github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
@@ -802,16 +673,13 @@ github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
-github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -823,20 +691,13 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
-github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
-github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-<<<<<<< HEAD
-=======
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
-github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
-github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -845,8 +706,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -855,7 +714,6 @@ github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
-github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runc v1.1.1 h1:PJ9DSs2sVwE0iVr++pAHE6QkS9tzcVWozlPifdwMgrU=
github.com/opencontainers/runc v1.1.1/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -869,17 +727,11 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
-github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/owenrumney/go-sarif v1.1.1 h1:QNObu6YX1igyFKhdzd7vgzmw7XsWN3/6NMGuDzBgXmE=
->>>>>>> 6477a26 (feat: add syntactic verification for analyzer.toml and issue descriptions (#131))
github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
github.com/owenrumney/go-sarif/v2 v2.1.0 h1:Xp4RUbbQc5O2/t5YYZ+1QzJ8FZVdJwXeiWssiF5vQrA=
github.com/owenrumney/go-sarif/v2 v2.1.0/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
-github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
-github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.0 h1:P7Bq0SaI8nsexyay5UAyDo+ICWy5MQPgEZ5+l8JQTKo=
@@ -893,22 +745,16 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
-github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -919,10 +765,7 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
-github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -934,7 +777,6 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pterm/pterm v0.12.23 h1:+PL0YqmmT0QiDLOpevE3e2HPb5UIDBxh6OlLm8jDhxg=
github.com/pterm/pterm v0.12.23/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
@@ -949,18 +791,16 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
-github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
@@ -975,12 +815,9 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
-github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
-github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
@@ -990,7 +827,6 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
-github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -1004,11 +840,9 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
-github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
-github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -1031,9 +865,6 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
-github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@@ -1050,15 +881,16 @@ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
-github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
-github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo=
+github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -1089,16 +921,6 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
-go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
-go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
-go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
-go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
-go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
-go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -1108,60 +930,34 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
-go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
-go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
-go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
-go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
-go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
-go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
-go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
-go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
-go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
-go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
-go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
-go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw=
+golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1185,7 +981,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -1197,14 +992,11 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1222,7 +1014,6 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -1230,13 +1021,10 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-<<<<<<< HEAD
-=======
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@@ -1245,25 +1033,15 @@ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
+golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
-golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
->>>>>>> 6477a26 (feat: add syntactic verification for analyzer.toml and issue descriptions (#131))
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1273,14 +1051,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1292,11 +1062,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1323,11 +1091,8 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1351,15 +1116,12 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1372,58 +1134,33 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-<<<<<<< HEAD
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
-golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
-=======
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220405210540-1e041c57c461 h1:kHVeDEnfKn3T238CvrUcz6KeEsFHVaKh4kMTt6Wsysg=
-golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
->>>>>>> 6477a26 (feat: add syntactic verification for analyzer.toml and issue descriptions (#131))
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
-golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1431,6 +1168,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1439,9 +1177,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
-golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1464,11 +1200,8 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1502,15 +1235,11 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1537,19 +1266,6 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
-google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
-google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
-google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
-google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
-google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
-google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1581,7 +1297,6 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
@@ -1593,39 +1308,13 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
-google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
@@ -1650,18 +1339,9 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1692,8 +1372,6 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
@@ -1703,6 +1381,8 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1714,10 +1394,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
@@ -1733,55 +1411,40 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
-k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs=
k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
-k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
-k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
-k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ=
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
-k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y=
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
-k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI=
k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
-k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
-k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
-k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
-k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
From 66cb8859455889bdd0db9dfebd6bdee359de0957 Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
Date: Fri, 27 May 2022 11:49:23 +0530
Subject: [PATCH 04/34] chore: fix CI
Signed-off-by: Siddhant N Trivedi
---
.github/workflows/CI.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index b98efa813..1e9c9241c 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -27,9 +27,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- name: Build the binary
- run: |
- pwd
- make build
+ run: make build
- name: Setup tests
run: make test_setup
From b167770a32bd7fd941267924ea6ad6af2fa1e2d6 Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
<68370997+siddhant-deepsource@users.noreply.github.com>
Date: Sat, 28 May 2022 19:13:47 +0530
Subject: [PATCH 05/34] feat(verify): add `--verbose` flag and fix flicker in
survey prompt (#136)
---
analyzers/backend/docker/build.go | 71 +++--------
analyzers/backend/docker/utils.go | 56 +++++++++
.../.deepsource/analyzer/analyzer.toml | 2 +-
analyzers/validator/validator.go | 2 +-
command/analyzer/run/run.go | 15 ++-
command/analyzer/verify/build.go | 84 +++++++++++++
command/analyzer/verify/verify.go | 118 +++++++++---------
go.mod | 16 +--
go.sum | 24 ++--
utils/spinner.go | 3 +-
10 files changed, 252 insertions(+), 139 deletions(-)
create mode 100644 analyzers/backend/docker/utils.go
create mode 100644 command/analyzer/verify/build.go
diff --git a/analyzers/backend/docker/build.go b/analyzers/backend/docker/build.go
index 0df23ecf9..a6eeec254 100644
--- a/analyzers/backend/docker/build.go
+++ b/analyzers/backend/docker/build.go
@@ -1,11 +1,8 @@
package docker
import (
- "bufio"
"context"
"crypto/rand"
- "encoding/json"
- "errors"
"fmt"
"io"
"os"
@@ -21,19 +18,6 @@ import (
// Timeout for build and container operations (10 minutes)
const buildTimeout = 10 * time.Minute
-type ErrorLine struct {
- Error string `json:"error"`
- ErrorDetail ErrorDetail `json:"errorDetail"`
-}
-
-type ErrorDetail struct {
- Message string `json:"message"`
-}
-
-type DockerBuildResponse struct {
- Stream string `json:"stream"`
-}
-
type DockerClient struct {
Client *client.Client
ContainerName string
@@ -42,6 +26,7 @@ type DockerClient struct {
ImageTag string
DockerfilePath string
AnalysisOpts AnalysisParams
+ ShowLogs bool
}
type DockerBuildError struct {
@@ -52,26 +37,28 @@ func (d *DockerBuildError) Error() string {
return d.Message
}
-func (d *DockerClient) BuildAnalyzerDockerImage() *DockerBuildError {
+// Docker build API function
+func (d *DockerClient) BuildAnalyzerDockerImage() (context.CancelFunc, io.ReadCloser, *DockerBuildError) {
var err error
d.Client, err = client.NewClientWithOpts(client.FromEnv)
if err != nil {
- return &DockerBuildError{
+ return nil, nil, &DockerBuildError{
Message: err.Error(),
}
}
- if err = d.executeImageBuild(); err != nil {
- return &DockerBuildError{
+ cancelFunc, responseReader, err := d.executeImageBuild()
+ if err != nil {
+ return cancelFunc, nil, &DockerBuildError{
Message: err.Error(),
}
}
- return nil
+ return cancelFunc, responseReader, nil
}
-func (d *DockerClient) executeImageBuild() error {
- ctx, cancel := context.WithTimeout(context.Background(), buildTimeout)
- defer cancel()
+// Executes the docker image build
+func (d *DockerClient) executeImageBuild() (context.CancelFunc, io.ReadCloser, error) {
+ ctx, ctxCancelFunc := context.WithTimeout(context.Background(), buildTimeout)
cwd, _ := os.Getwd()
tarOptions := &archive.TarOptions{
@@ -79,7 +66,7 @@ func (d *DockerClient) executeImageBuild() error {
}
tar, err := archive.TarWithOptions(cwd, tarOptions)
if err != nil {
- return err
+ return ctxCancelFunc, nil, err
}
opts := types.ImageBuildOptions{
@@ -90,38 +77,10 @@ func (d *DockerClient) executeImageBuild() error {
}
res, err := d.Client.ImageBuild(ctx, tar, opts)
if err != nil {
- return err
- }
- defer res.Body.Close()
- return checkResponse(res.Body)
-}
-
-func checkResponse(rd io.Reader) error {
- var lastLine []byte
- count := 0
- var currentStream string
-
- scanner := bufio.NewScanner(rd)
- for scanner.Scan() {
- lastLine = scanner.Bytes()
- d := &DockerBuildResponse{}
- err := json.Unmarshal(lastLine, d)
- if err != nil {
- return err
- }
- if d.Stream == "" || d.Stream == "\n" || strings.TrimSuffix(d.Stream, "\n") == currentStream {
- continue
- }
- currentStream = strings.TrimSuffix(d.Stream, "\n")
- count++
- }
-
- errLine := &ErrorLine{}
- json.Unmarshal([]byte(lastLine), errLine)
- if errLine.Error != "" {
- return errors.New(errLine.Error)
+ ctxCancelFunc()
+ return ctxCancelFunc, nil, err
}
- return scanner.Err()
+ return ctxCancelFunc, res.Body, nil
}
// Returns the docker image details to build
diff --git a/analyzers/backend/docker/utils.go b/analyzers/backend/docker/utils.go
new file mode 100644
index 000000000..712607331
--- /dev/null
+++ b/analyzers/backend/docker/utils.go
@@ -0,0 +1,56 @@
+package docker
+
+import (
+ "bufio"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+type ErrorLine struct {
+ Error string `json:"error"`
+ ErrorDetail ErrorDetail `json:"errorDetail"`
+}
+
+type ErrorDetail struct {
+ Message string `json:"message"`
+}
+
+type DockerBuildResponse struct {
+ Stream string `json:"stream"`
+}
+
+/* Checks the docker build response and prints all the logs if `showAllLogs` is true
+ * Used in `deepsource analyzer run` and `deepsource analyzer verify` commands */
+func CheckBuildResponse(rd io.Reader, showAllLogs bool) error { // skipcq: RVV-A0005
+ var lastLine []byte
+ count := 0
+ var currentStream string
+
+ scanner := bufio.NewScanner(rd)
+ for scanner.Scan() {
+ lastLine = scanner.Bytes()
+ d := &DockerBuildResponse{}
+ err := json.Unmarshal(lastLine, d)
+ if err != nil {
+ return err
+ }
+ if d.Stream == "" || d.Stream == "\n" || strings.Contains(d.Stream, "--->") || strings.TrimSuffix(d.Stream, "\n") == currentStream {
+ continue
+ }
+ currentStream = strings.TrimSuffix(d.Stream, "\n")
+ if showAllLogs {
+ fmt.Println(currentStream)
+ }
+ count++
+ }
+
+ errLine := &ErrorLine{}
+ json.Unmarshal([]byte(lastLine), errLine)
+ if errLine.Error != "" {
+ return errors.New(errLine.Error)
+ }
+ return scanner.Err()
+}
diff --git a/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml b/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml
index 59d895bba..6da43b523 100644
--- a/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml
+++ b/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml
@@ -1,5 +1,5 @@
name = "Todo comments checker"
-# path = "@deepsource/demo-python"
+# shortcode = "@deepsource/demo-python" # test invalid config
description = "Finds the TODO comments in codebase."
# category = "doc"
tags = ["documentation","todo"]
diff --git a/analyzers/validator/validator.go b/analyzers/validator/validator.go
index 71a6e507c..1f294c194 100644
--- a/analyzers/validator/validator.go
+++ b/analyzers/validator/validator.go
@@ -102,6 +102,7 @@ func ValidateAnalyzerTOML(analyzerTOMLPath string) (*config.AnalyzerMetadata, *V
}
return &config, &analyzerTOMLValidationErrors, nil
}
+
return &config, nil, nil
}
@@ -135,7 +136,6 @@ func ValidateIssueDescriptions(issuesDirectoryPath string) (*[]ValidationError,
// Validate the data
v := validate.New()
-
if err := v.Struct(&config); err != nil {
validationFailed = true
missingRequiredFields := getMissingRequiredFields(err, config)
diff --git a/command/analyzer/run/run.go b/command/analyzer/run/run.go
index 899ae46b8..9eb04c5f2 100644
--- a/command/analyzer/run/run.go
+++ b/command/analyzer/run/run.go
@@ -74,10 +74,23 @@ func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
// Building the Analyzer image
fmt.Println("Building Analyzer image...")
- if buildError := a.Client.BuildAnalyzerDockerImage(); buildError != nil {
+ ctxCancelFunc, buildRespReader, buildError := a.Client.BuildAnalyzerDockerImage()
+
+ // Cancel the build context and close the reader before exiting this function
+ if buildRespReader != nil {
+ defer buildRespReader.Close()
+ }
+ defer ctxCancelFunc()
+ if buildError != nil {
return buildError
}
+ // Check the docker build response
+ // TODO: Tweak the behaviour here when the spinners are added to the run command
+ if err = docker.CheckBuildResponse(buildRespReader, false); err != nil {
+ return err
+ }
+
/* Create temporary toolbox directory to store analysis config and later analyis results
* If already passed through --output-file flag, use that one */
if err = a.createTemporaryToolBoxDir(); err != nil {
diff --git a/command/analyzer/verify/build.go b/command/analyzer/verify/build.go
new file mode 100644
index 000000000..6f69192c1
--- /dev/null
+++ b/command/analyzer/verify/build.go
@@ -0,0 +1,84 @@
+package verify
+
+import (
+ "errors"
+ "fmt"
+ "os"
+
+ build "github.com/deepsourcelabs/cli/analyzers/backend/docker"
+ "github.com/deepsourcelabs/cli/utils"
+ "github.com/mgutz/ansi"
+)
+
+// Verify the docker image build of the Analyzer
+func (a *AnalyzerVerifyOpts) verifyAnalyzerDockerBuild() (err error) {
+ // Fetch the details of the dockerfile to build and also the name of the docker image
+ a.Build.DockerFilePath, a.Build.DockerImageName = build.GetDockerImageDetails(a.AnalyzerTOMLData)
+
+ /* In case of verbose mode (when the user supplies a `--verbose` flag), do not use spinner since it doesn't allow showing multiline
+ * output at the same time as rendering a spinner. Can be done but would require some string concatenation magic. Can be picked up later. */
+ switch a.Build.VerboseMode {
+ case true:
+ arrowIcon := ansi.Color("> [verbose]", "yellow")
+ fmt.Printf("%s Building Analyzer image with the name \"%s\"\n", arrowIcon, a.Build.DockerImageName)
+ case false:
+ a.Spinner.StartSpinnerWithLabel(fmt.Sprintf("Building Analyzer image with the name \"%s\"", a.Build.DockerImageName), "Successfully built the Analyzer image")
+ }
+
+ /* Specifying the source to build
+ * Check for the presence of `build.Dockerfile` or if not a `Dockerfile` in the current working directory */
+ if _, err := os.Stat(a.Build.DockerFilePath); err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ a.Spinner.StopSpinnerWithError("Failed to build the image", fmt.Errorf("%s not found\n", a.Build.DockerFilePath))
+ return err
+ }
+ }
+
+ /* ///////////////////////////////////
+ * Analyzer docker build verification
+ * /////////////////////////////////// */
+
+ /* Initialize the builder with the above fetched details
+ * Use the `GenerateImageVersion` utility to generate a random string of length 7 to tag the image */
+ analyzerBuilder := build.DockerClient{
+ ImageName: a.Build.DockerImageName,
+ DockerfilePath: a.Build.DockerFilePath,
+ ImageTag: build.GenerateImageVersion(7),
+ ShowLogs: a.Build.VerboseMode,
+ }
+
+ // Build the docker image :rocket:
+ ctxCancelFunc, buildRespReader, buildErr := analyzerBuilder.BuildAnalyzerDockerImage()
+
+ // Cancel the build context and close the reader before exiting this function
+ defer buildRespReader.Close()
+ defer ctxCancelFunc()
+
+ if buildErr != nil {
+ a.handleBuildError(buildErr)
+ return buildErr
+ }
+
+ // Read the docker build response
+ if err = build.CheckBuildResponse(buildRespReader, a.Build.VerboseMode); err != nil {
+ a.handleBuildError(err)
+ return err
+ }
+
+ // In case of verbose mode, no need to stop the spinner
+ if a.Build.VerboseMode {
+ fmt.Print(utils.GetSuccessMessage("Successfully built the Analyzer image"))
+ return nil
+ }
+ a.Spinner.StopSpinner()
+ return nil
+}
+
+// Utility to handle the output in case of build errors for different modes
+func (a *AnalyzerVerifyOpts) handleBuildError(buildError error) {
+ if a.Build.VerboseMode {
+ fmt.Println(utils.GetFailureMessage("Failed to build the image", buildError.Error()))
+ return
+ }
+ a.Spinner.StopSpinnerWithError("Failed to build the image", fmt.Errorf(buildError.Error()))
+}
diff --git a/command/analyzer/verify/verify.go b/command/analyzer/verify/verify.go
index 626ee2a81..c89e22a7f 100644
--- a/command/analyzer/verify/verify.go
+++ b/command/analyzer/verify/verify.go
@@ -3,10 +3,9 @@ package verify
import (
"errors"
"fmt"
- "os"
"path/filepath"
- build "github.com/deepsourcelabs/cli/analyzers/backend/docker"
+ "github.com/deepsourcelabs/cli/analyzers/config"
"github.com/deepsourcelabs/cli/analyzers/validator"
"github.com/deepsourcelabs/cli/utils"
"github.com/spf13/cobra"
@@ -18,7 +17,21 @@ var (
configFolder string = ".deepsource/analyzer"
)
-type AnalyzerVerifyOpts struct{}
+type AnalyzerBuild struct {
+ DockerFilePath string
+ DockerImageName string
+ VerboseMode bool
+}
+
+type AnalyzerVerifyOpts struct {
+ AnalyzerTOMLData *config.AnalyzerMetadata
+ Build AnalyzerBuild
+ Spinner *utils.SpinnerUtils
+}
+
+/* ////////////////////////////////////
+ * $ deepsource analyzer verify
+ * /////////////////////////////////// */
func NewCmdAnalyzerVerify() *cobra.Command {
// Configuring the paths of analyzer.toml and issues directory
@@ -26,69 +39,85 @@ func NewCmdAnalyzerVerify() *cobra.Command {
if err != nil {
fmt.Printf("Couldn't find the root directory of the project. Error:%s", err)
}
-
analyzerTOMLPath = filepath.Join(projectRoot, configFolder, "analyzer.toml")
issuesDirPath = filepath.Join(projectRoot, configFolder, "issues/")
- opts := AnalyzerVerifyOpts{}
+ opts := AnalyzerVerifyOpts{
+ Spinner: &utils.SpinnerUtils{},
+ Build: AnalyzerBuild{
+ VerboseMode: false,
+ },
+ }
cmd := &cobra.Command{
Use: "verify",
Short: "Verify DeepSource Analyzers configuration",
Args: utils.NoArgs,
RunE: func(_ *cobra.Command, _ []string) error {
- if err := opts.Run(); err != nil {
+ if err := opts.verifyAnalyzer(); err != nil {
return errors.New("Analyzer verification failed. Exiting...")
}
return nil
},
}
+
+ // --verbose flag. On being set, the build logs as well as the verification diagnostics are visible to the user
+ cmd.Flags().BoolVar(&opts.Build.VerboseMode, "verbose", false, "Output build logs and diagnostics related to verification failures")
return cmd
}
-// Runs the command
-func (*AnalyzerVerifyOpts) Run() (err error) {
+/* ////////////////////////////////////
+ * Analyzer configuration verification
+ * /////////////////////////////////// */
+
+func (a *AnalyzerVerifyOpts) verifyAnalyzer() (err error) {
var validationErrors *[]validator.ValidationError
- spin := utils.SpinnerUtils{}
+ var analyzerTOMLValidationErrors *validator.ValidationError
configurationValid := true
- /////////////////////////////////
- // Configuration verification///
- ///////////////////////////////
+ /* //////////////////////////////////////////////////////////////////////////////////
+ * Checks for the presence of .deepsource/analyzer directory,
+ * the analyzer.toml file and issues present in .deepsource/analyzer/issues directory
+ * /////////////////////////////////////////////////////////////////////////////////// */
- // Check for path of `analyzer.toml` file and `issues` directory containing issue descriptions
- spin.StartSpinnerWithLabel("Checking for presence of analyzer.toml and issue descriptions...", "Yay!!Found analyzer.toml and issue descriptions.")
+ a.Spinner.StartSpinnerWithLabel("Checking for presence of analyzer.toml and issue descriptions...", "Yay!!Found analyzer.toml and issue descriptions.")
if err = validator.CheckForAnalyzerConfig(analyzerTOMLPath, issuesDirPath); err != nil {
configurationValid = false
- spin.StopSpinnerWithError("Failed to locate analyzer configurations", err)
+ a.Spinner.StopSpinnerWithError("Failed to locate analyzer configurations", err)
return
}
- spin.StopSpinner()
+ a.Spinner.StopSpinner()
+
+ /* ///////////////////////////////
+ * Read and verify analyzer.toml
+ * ////////////////////////////// */
- // Read and verify analyzer toml
- spin.StartSpinnerWithLabel("Validating analyzer.toml...", "Verified analyzer.toml")
- analyzerTOMLData, analyzerTOMLValidationErrors, err := validator.ValidateAnalyzerTOML(analyzerTOMLPath)
- if analyzerTOMLValidationErrors != nil {
+ a.Spinner.StartSpinnerWithLabel("Validating analyzer.toml...", "Verified analyzer.toml")
+ a.AnalyzerTOMLData, analyzerTOMLValidationErrors, err = validator.ValidateAnalyzerTOML(analyzerTOMLPath)
+ if len(analyzerTOMLValidationErrors.Errors) > 0 {
configurationValid = false
- spin.StopSpinnerWithError("Failed to verify analyzer.toml\n", err)
+ a.Spinner.StopSpinnerWithError("Failed to verify analyzer.toml\n", err)
for _, err := range analyzerTOMLValidationErrors.Errors {
msg := fmt.Sprintf("%s : %s", err.Message, err.Field)
failureMsg := utils.GetFailureMessage(msg, "")
fmt.Printf(" * %s\n", failureMsg)
}
}
- spin.StopSpinner()
+ a.Spinner.StopSpinner()
- // Read and verify all issues
- spin.StartSpinnerWithLabel("Validating issue descriptions...", "Verified issue descriptions")
+ /* //////////////////////////////////////
+ * Reads and verifies issue descriptions
+ * ///////////////////////////////////// */
+
+ a.Spinner.StartSpinnerWithLabel("Validating issue descriptions...", "Verified issue descriptions")
if validationErrors, err = validator.ValidateIssueDescriptions(issuesDirPath); err != nil {
configurationValid = false
- spin.StopSpinnerWithError("Failed to validate the following issue desriptions", err)
+ a.Spinner.StopSpinnerWithError("Failed to validate the following issue desriptions", err)
}
// Check if there are any validation errors in issue descriptions
if validationErrors != nil {
configurationValid = false
- spin.StopSpinnerWithError("Failed to validate the following issue descriptions\n", err)
+ a.Spinner.StopSpinnerWithError("Failed to validate the following issue descriptions\n", err)
for _, validationError := range *validationErrors {
fmt.Printf(" * %s\n", validationError.File)
for _, err := range validationError.Errors {
@@ -98,41 +127,16 @@ func (*AnalyzerVerifyOpts) Run() (err error) {
}
}
}
- spin.StopSpinner()
+ a.Spinner.StopSpinner()
- // Do not move to building the image if the configuration verification fails
+ // Do not proceed to building the image if the configuration verification fails
if !configurationValid {
return
}
- /////////////////////////
- // Build verification///
- ///////////////////////
-
- // Specifying the name of the image to be built
- // Set the default Dockerfile path as "Dockerfile"
- dockerFilePath, dockerFileName := build.GetDockerImageDetails(analyzerTOMLData)
-
- spin.StartSpinnerWithLabel(fmt.Sprintf("Building Analyzer image with the name \"%s\"", dockerFileName), "Successfully built the Analyzer image")
- // Specifying the source to build
- // Check for the presence of `build.Dockerfile` or if not a `Dockerfile` in the current working directory
- if _, err := os.Stat(dockerFilePath); err != nil {
- if errors.Is(err, os.ErrNotExist) {
- spin.StopSpinnerWithError("Failed to build the image", fmt.Errorf("%s not found\n", dockerFilePath))
- return err
- }
- }
- analyzerBuilder := build.DockerClient{
- ImageName: dockerFileName,
- DockerfilePath: dockerFilePath,
- ImageTag: build.GenerateImageVersion(7),
- }
-
- buildErr := analyzerBuilder.BuildAnalyzerDockerImage()
- if buildErr != nil {
- spin.StopSpinnerWithError("Failed to build the image", fmt.Errorf(buildErr.Error()))
- }
- spin.StopSpinner()
+ /* ////////////////////////////////////////////////////
+ * Verify the local docker image build of the Analyzer
+ * /////////////////////////////////////////////////// */
- return nil
+ return a.verifyAnalyzerDockerBuild()
}
diff --git a/go.mod b/go.mod
index b9bda8296..59da01294 100644
--- a/go.mod
+++ b/go.mod
@@ -3,16 +3,13 @@ module github.com/deepsourcelabs/cli
go 1.18
require (
- github.com/AlecAivazis/survey/v2 v2.2.12
+ github.com/AlecAivazis/survey/v2 v2.3.4
github.com/Jeffail/gabs/v2 v2.6.1
github.com/MakeNowJust/heredoc v1.0.0
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect
github.com/briandowns/spinner v1.18.1
github.com/cli/browser v1.1.0
- github.com/containerd/containerd v1.6.3 // indirect
- github.com/containerd/continuity v0.3.0 // indirect
github.com/deepsourcelabs/graphql v0.2.2
- github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.14+incompatible
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.13.0
@@ -50,7 +47,7 @@ require (
github.com/moby/sys/mount v0.3.2 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
- github.com/pelletier/go-toml/v2 v2.0.0
+ github.com/pelletier/go-toml/v2 v2.0.1
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
@@ -70,9 +67,6 @@ require (
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
- gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
- gotest.tools/v3 v3.2.0 // indirect
)
require (
@@ -80,6 +74,9 @@ require (
github.com/Microsoft/hcsshim v0.9.2 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/containerd/cgroups v1.0.3 // indirect
+ github.com/containerd/containerd v1.6.3 // indirect
+ github.com/containerd/continuity v0.3.0 // indirect
+ github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
@@ -102,4 +99,7 @@ require (
google.golang.org/grpc v1.43.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
+ gotest.tools/v3 v3.2.0 // indirect
)
diff --git a/go.sum b/go.sum
index 442ab0fdf..e8cb80d16 100644
--- a/go.sum
+++ b/go.sum
@@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/AlecAivazis/survey/v2 v2.2.12 h1:5a07y93zA6SZ09gOa9wLVLznF5zTJMQ+pJ3cZK4IuO8=
-github.com/AlecAivazis/survey/v2 v2.2.12/go.mod h1:6d4saEvBsfSHXeN1a5OA5m2+HJ2LuVokllnC77pAIKI=
+github.com/AlecAivazis/survey/v2 v2.3.4 h1:pchTU9rsLUSvWEl2Aq9Pv3k0IE2fkqtGxazskAMd9Ng=
+github.com/AlecAivazis/survey/v2 v2.3.4/go.mod h1:hrV6Y/kQCLhIZXGcriDCUBtB3wnN7156gMXJ3+b23xM=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@@ -88,8 +88,8 @@ github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfy
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
-github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
-github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
+github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
+github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 h1:cSHEbLj0GZeHM1mWG84qEnGFojNEQ83W7cwaPRjcwXU=
@@ -280,6 +280,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
+github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
@@ -527,8 +529,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
-github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
+github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
+github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -593,8 +595,6 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/pty v1.1.5 h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -734,8 +734,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml/v2 v2.0.0 h1:P7Bq0SaI8nsexyay5UAyDo+ICWy5MQPgEZ5+l8JQTKo=
-github.com/pelletier/go-toml/v2 v2.0.0/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
+github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
+github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
@@ -848,7 +848,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -943,7 +942,6 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1077,7 +1075,6 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1159,6 +1156,7 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAgl
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/utils/spinner.go b/utils/spinner.go
index b200fad63..d8462f6e9 100644
--- a/utils/spinner.go
+++ b/utils/spinner.go
@@ -19,11 +19,10 @@ func (s *SpinnerUtils) StartSpinnerWithLabel(label, finalMessage string) {
s.mu.Lock()
defer s.mu.Unlock()
- sp := spinner.New(spinner.CharSets[11], 120*time.Millisecond, spinner.WithWriter(os.Stderr), spinner.WithFinalMSG(GetSuccessMessage(finalMessage))) // Build our new spinner
+ sp := spinner.New(spinner.CharSets[11], 120*time.Millisecond, spinner.WithWriter(os.Stdout), spinner.WithWriter(os.Stderr), spinner.WithFinalMSG(GetSuccessMessage(finalMessage))) // Build our new spinner
if label != "" {
sp.Suffix = " " + label + " "
}
-
sp.Start() // Start the spinner
s.Spinner = sp
}
From 8b47e1181700fb2f4dbe11d7398c578789f651fd Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
Date: Sun, 29 May 2022 20:03:43 +0530
Subject: [PATCH 06/34] Revert "chore: truncate hostname if greater than 256"
This reverts commit 98e92f7ca9b3059bae6ffd9d13f87bc388298047.
---
command/auth/login/login_flow.go | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/command/auth/login/login_flow.go b/command/auth/login/login_flow.go
index cd8b7a0c1..87f7ff75b 100644
--- a/command/auth/login/login_flow.go
+++ b/command/auth/login/login_flow.go
@@ -101,10 +101,7 @@ func fetchPAT(ctx context.Context, deviceRegistrationData *auth.Device) (*auth.P
if err != nil {
hostName = defaultHostName
}
- if len(hostName) > 256 {
- hostName = hostName[:256]
- }
- userDescription := fmt.Sprintf("CLI : %s@%s", userName, hostName)
+ userDescription := fmt.Sprintf("CLI PAT for %s@%s", userName, hostName)
// Fetching DeepSource client in order to interact with SDK
deepsource, err := deepsource.New(deepsource.ClientOpts{
From 104bc1852321a10dbb4d628e75e6a2315b2bac21 Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
<68370997+siddhant-deepsource@users.noreply.github.com>
Date: Wed, 8 Jun 2022 19:04:55 +0530
Subject: [PATCH 07/34] chore(verify): improve type checks in analyzer.toml and
issues verification (#144)
---
.github/workflows/CI.yml | 4 +-
analyzers/backend/docker/build.go | 6 +-
analyzers/config/config.go | 11 +-
analyzers/validator/analyzer_toml.go | 86 +++++++
analyzers/validator/issues.go | 72 ++++++
.../.deepsource/analyzer/analyzer.toml | 12 +-
.../.deepsource/analyzer/analyzer.toml | 4 +-
.../.deepsource/analyzer/analyzer.toml | 14 +-
analyzers/validator/types.go | 56 ----
analyzers/validator/utils.go | 79 ++++++
analyzers/validator/validator.go | 140 +++++-----
cmd/Dockerfile_new | 2 +
command/analyzer/initialize/init.go | 243 +++++++++++++-----
command/analyzer/initialize/init_test.go | 113 ++++----
command/analyzer/initialize/utils.go | 104 ++++++++
command/analyzer/verify/build.go | 23 +-
command/analyzer/verify/verify.go | 76 +++---
command/auth/login/login.go | 8 +-
command/auth/logout/logout.go | 14 +-
command/config/generate/analyzers_input.go | 8 +-
command/config/generate/generate.go | 5 +-
command/config/generate/generic_input.go | 7 +-
command/config/generate/transformers_input.go | 2 +-
.../config/types.go => types/analyzer.go | 44 ++--
utils/prompt.go | 21 +-
utils/remote_resolver.go | 3 +-
utils/spinner.go | 11 +-
27 files changed, 806 insertions(+), 362 deletions(-)
create mode 100644 analyzers/validator/analyzer_toml.go
create mode 100644 analyzers/validator/issues.go
delete mode 100644 analyzers/validator/types.go
create mode 100644 cmd/Dockerfile_new
create mode 100644 command/analyzer/initialize/utils.go
rename analyzers/config/types.go => types/analyzer.go (51%)
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 1e9c9241c..e0dc92a5f 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -3,9 +3,7 @@ name: CI
on:
pull_request:
branches:
- - "master"
- - "dev"
- - "analyzers"
+ - '**'
push:
branches:
- master
diff --git a/analyzers/backend/docker/build.go b/analyzers/backend/docker/build.go
index a6eeec254..db046d858 100644
--- a/analyzers/backend/docker/build.go
+++ b/analyzers/backend/docker/build.go
@@ -9,7 +9,7 @@ import (
"strings"
"time"
- "github.com/deepsourcelabs/cli/analyzers/config"
+ cliTypes "github.com/deepsourcelabs/cli/types"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/archive"
@@ -37,7 +37,7 @@ func (d *DockerBuildError) Error() string {
return d.Message
}
-// Docker build API function
+// BuildAnalyzerDockerImage is the docker image build API used by various CLI commands
func (d *DockerClient) BuildAnalyzerDockerImage() (context.CancelFunc, io.ReadCloser, *DockerBuildError) {
var err error
d.Client, err = client.NewClientWithOpts(client.FromEnv)
@@ -84,7 +84,7 @@ func (d *DockerClient) executeImageBuild() (context.CancelFunc, io.ReadCloser, e
}
// Returns the docker image details to build
-func GetDockerImageDetails(analyzerTOMLData *config.AnalyzerMetadata) (string, string) {
+func GetDockerImageDetails(analyzerTOMLData *cliTypes.AnalyzerTOML) (string, string) {
var dockerFilePath, dockerFileName string
dockerFilePath = "Dockerfile"
diff --git a/analyzers/config/config.go b/analyzers/config/config.go
index dee56a59a..8d486e165 100644
--- a/analyzers/config/config.go
+++ b/analyzers/config/config.go
@@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
+ "github.com/deepsourcelabs/cli/types"
"github.com/deepsourcelabs/cli/utils"
"github.com/pelletier/go-toml/v2"
)
@@ -84,9 +85,9 @@ func VerifyAnalyzerConfigs() error {
}
// Get the analyzer.toml data
-func GetAnalyzerTOML() (*AnalyzerMetadata, error) {
+func GetAnalyzerTOML() (*types.AnalyzerTOML, error) {
resolveAnalyzerConfigurationPaths()
- config := AnalyzerMetadata{}
+ config := types.AnalyzerTOML{}
// Read the contents of analyzer.toml file
analyzerTOMLContent, err := ioutil.ReadFile(analyzerTOMLPath)
@@ -102,16 +103,16 @@ func GetAnalyzerTOML() (*AnalyzerMetadata, error) {
}
// Get the list of issue descriptions
-func GetIssueDescriptions() (*[]AnalyzerIssue, error) {
+func GetIssueDescriptions() (*[]types.AnalyzerIssue, error) {
resolveAnalyzerConfigurationPaths()
- issueDescriptions := []AnalyzerIssue{}
+ issueDescriptions := []types.AnalyzerIssue{}
issuesList, err := ioutil.ReadDir(issuesDirectoryPath)
if err != nil {
return nil, err
}
for _, issuePath := range issuesList {
- issue := AnalyzerIssue{}
+ issue := types.AnalyzerIssue{}
// Set the issue shortcode as the filename
issue.Shortcode = strings.TrimSuffix(issuePath.Name(), ".toml")
diff --git a/analyzers/validator/analyzer_toml.go b/analyzers/validator/analyzer_toml.go
new file mode 100644
index 000000000..e639218ca
--- /dev/null
+++ b/analyzers/validator/analyzer_toml.go
@@ -0,0 +1,86 @@
+package validator
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/deepsourcelabs/cli/types"
+ validate "github.com/go-playground/validator/v10"
+)
+
+var supportedEngines []string = []string{"docker"}
+
+func validateAnalyzerTOMLFields(config *types.AnalyzerTOML, filePath string) (*ValidationFailure, error) {
+ var supportedEnginesString string
+ analyzerTOMLValidationErrors := ValidationFailure{}
+
+ // Validate analyzer.toml fields based on type and sanity checks
+ v := validate.New()
+ // Custom validators for shortcode and engine
+ v.RegisterValidation("shortcode", ValidateShortcode)
+ v.RegisterValidation("engine", ValidateEngine)
+
+ // Start the validation
+ if err := v.Struct(config); err != nil {
+ // List the missing required fields
+ missingRequiredFields := getMissingRequiredFields(err, *config)
+ analyzerTOMLValidationErrors = ValidationFailure{
+ File: filePath,
+ }
+
+ // Find any missing "required" fields from analyzer.toml
+ for _, missingField := range missingRequiredFields {
+ analyzerTOMLValidationErrors.Errors = append(analyzerTOMLValidationErrors.Errors, ErrorMeta{
+ Level: Error,
+ Field: missingField,
+ Message: fmt.Sprintf("Missing required field : %s", missingField),
+ },
+ )
+ }
+
+ // Check if the shortcode begins with @ and the right build engine is configured
+ errs := err.(validate.ValidationErrors)
+ for _, err := range errs {
+ if err.Tag() == "shortcode" {
+ analyzerTOMLValidationErrors.Errors = append(analyzerTOMLValidationErrors.Errors, ErrorMeta{
+ Level: Error,
+ Field: "shortcode",
+ Message: "Analyzer shortcode should begin with '@'",
+ })
+ }
+
+ if err.Tag() == "engine" {
+ if len(supportedEngines) > 1 {
+ supportedEnginesString = strings.Join(supportedEngines, ", ")
+ } else {
+ supportedEnginesString = supportedEngines[0]
+ }
+
+ analyzerTOMLValidationErrors.Errors = append(analyzerTOMLValidationErrors.Errors, ErrorMeta{
+ Level: Error,
+ Field: "engine",
+ Message: fmt.Sprintf("Invalid build engine \"%s\". The following build engines are supported: [%s]", config.Build.Engine, supportedEnginesString),
+ })
+ }
+ }
+ }
+ if len(analyzerTOMLValidationErrors.Errors) > 0 {
+ return &analyzerTOMLValidationErrors, nil
+ }
+ return nil, nil
+}
+
+// Validates if the shortcode begins with `@`
+func ValidateShortcode(fl validate.FieldLevel) bool {
+ return strings.HasPrefix(fl.Field().String(), "@")
+}
+
+// Validates the supported engines. As of now, only docker is supported.
+func ValidateEngine(fl validate.FieldLevel) bool {
+ for _, supportedEngine := range supportedEngines {
+ if fl.Field().String() == supportedEngine {
+ return true
+ }
+ }
+ return false
+}
diff --git a/analyzers/validator/issues.go b/analyzers/validator/issues.go
new file mode 100644
index 000000000..38372d785
--- /dev/null
+++ b/analyzers/validator/issues.go
@@ -0,0 +1,72 @@
+package validator
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/deepsourcelabs/cli/types"
+ validate "github.com/go-playground/validator/v10"
+)
+
+var supportedIssueCategories = []string{
+ "bug-risk",
+ "antipattern",
+ "security",
+ "style",
+ "performance",
+ "doc",
+ "typecheck",
+ "coverage",
+}
+
+func validateIssueTOML(config *types.AnalyzerIssue, issuePath string) *ValidationFailure {
+ issueValidationError := ValidationFailure{}
+ // Validate the issue data
+ v := validate.New()
+ v.RegisterValidation("category", ValidateCategory)
+ if err := v.Struct(config); err != nil {
+ // validationFailed = true
+ missingRequiredFields := getMissingRequiredFields(err, *config)
+ issueValidationError = ValidationFailure{
+ File: issuePath,
+ }
+
+ // TODO: Tweak this to accomodate other error types.
+ for _, missingField := range missingRequiredFields {
+ issueValidationError.Errors = append(issueValidationError.Errors, ErrorMeta{
+ Level: Error,
+ Field: missingField,
+ Message: fmt.Sprintf("Missing required field: %s", missingField),
+ },
+ )
+ }
+
+ // Check if the category is supported
+ errs := err.(validate.ValidationErrors)
+ for _, err := range errs {
+ if err.Tag() == "category" {
+ supportedCategories := strings.Join(supportedIssueCategories, ", ")
+ issueValidationError.Errors = append(issueValidationError.Errors, ErrorMeta{
+ Level: Error,
+ Field: "category",
+ Message: fmt.Sprintf("Invalid issue category \"%s\". The following issue categories are supported: [%s]", config.Category, supportedCategories),
+ })
+ }
+ }
+ }
+
+ // Return nil if no validation errors found
+ if len(issueValidationError.Errors) > 0 {
+ return &issueValidationError
+ }
+ return nil
+}
+
+func ValidateCategory(fl validate.FieldLevel) bool {
+ for _, supportedCategory := range supportedIssueCategories {
+ if fl.Field().String() == supportedCategory {
+ return true
+ }
+ }
+ return false
+}
diff --git a/analyzers/validator/testdata/analyzer1/.deepsource/analyzer/analyzer.toml b/analyzers/validator/testdata/analyzer1/.deepsource/analyzer/analyzer.toml
index 46fe5bc31..858d23e6b 100644
--- a/analyzers/validator/testdata/analyzer1/.deepsource/analyzer/analyzer.toml
+++ b/analyzers/validator/testdata/analyzer1/.deepsource/analyzer/analyzer.toml
@@ -1,14 +1,14 @@
name = "todo comments checker"
shortcode = "@deepsource/demo-python"
description = "finds the todo comments in codebase."
-category = "doc"
tags = ["documentation","todo"]
-environment_variables = {code_path = "/code"}
-[urls]
- source = "https://github.com/deepsourcelabs/2do-checker"
- documentation = "https://deepsource.io/docs"
- bug_tracker = "https://bugtracker.deepsource.io"
+[environment_variables]
+ CODE_PATH = "/code"
+
+repository = "https://github.com/deepsourcelabs/2do-checker"
+documentation = "https://deepsource.io/docs"
+bug_tracker = "https://bugtracker.deepsource.io"
[analysis]
command = "/app/todo-checker"
diff --git a/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml b/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml
index 6da43b523..0c6d13c63 100644
--- a/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml
+++ b/analyzers/validator/testdata/analyzer2/.deepsource/analyzer/analyzer.toml
@@ -3,7 +3,9 @@ name = "Todo comments checker"
description = "Finds the TODO comments in codebase."
# category = "doc"
tags = ["documentation","todo"]
-environment_variables = {CODE_PATH = "/code"}
+
+[environment_variables]
+ CODE_PATH = "/code"
[urls]
source = "https://github.com/deepsourcelabs/2do-checker"
diff --git a/analyzers/validator/testdata/analyzer3/.deepsource/analyzer/analyzer.toml b/analyzers/validator/testdata/analyzer3/.deepsource/analyzer/analyzer.toml
index 569c8ebdf..3e95d2d98 100644
--- a/analyzers/validator/testdata/analyzer3/.deepsource/analyzer/analyzer.toml
+++ b/analyzers/validator/testdata/analyzer3/.deepsource/analyzer/analyzer.toml
@@ -1,14 +1,14 @@
name = "Todo comments checker"
-shortcode = "@deepsource/demo-python"
+shortcode = "deepsource/demo-python"
description = "Finds the TODO comments in codebase."
-# category = "doc"
tags = ["documentation","todo"]
-environment_variables = {CODE_PATH = "/code"}
-[urls]
- source = "https://github.com/deepsourcelabs/2do-checker"
- documentation = "https://deepsource.io/docs"
- bug_tracker = "https://bugtracker.deepsource.io"
+[environment_variables]
+ CODE_PATH = "/code"
+
+repository = "https://github.com/deepsourcelabs/2do-checker"
+documentation = "https://deepsource.io/docs"
+bug_tracker = "https://bugtracker.deepsource.io"
[analysis]
command = "/app/todo-checker"
diff --git a/analyzers/validator/types.go b/analyzers/validator/types.go
deleted file mode 100644
index cb7153724..000000000
--- a/analyzers/validator/types.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package validator
-
-type Analysis struct {
- Command string `toml:"command" json:"command" validate:"required"`
-}
-
-// TODO: Remove the comment when we start support for Autofix.
-// type Autofix struct {
-// Command string `toml:"command" json:"command" analyzertoml:"required"`
-// }
-
-type Build struct {
- Builder string `toml:"builder" json:"builder" validate:"omitempty"`
- Dockerfile string `toml:"dockerfile" json:"dockerfile,omitempty" validate:"omitempty"`
- Script string `toml:"script" json:"script" validate:"omitempty"`
-}
-
-type URL struct {
- Source string `toml:"source" json:"source" validate:"omitempty,url"`
- Documentation string `toml:"documentation" json:"documentation,omitempty" validate:"omitempty,url"`
- BugTracker string `toml:"bug_tracker" json:"bug_tracker" validate:"omitempty,url"`
-}
-
-type Test struct {
- Command string `toml:"command" json:"command" validate:"omitempty"`
-}
-
-// analyzer.toml type
-type AnalyzerMetadata struct {
- // Analyzer specific data
- Name string `toml:"name" json:"name" validate:"required"`
- Shortcode string `toml:"shortcode" json:"shortcode" validate:"required"` // New
- Description string `toml:"description" json:"description" validate:"required"`
- Category string `toml:"category" json:"category" validate:"required"`
- Tags []string `toml:"tags" json:"tags,omitempty" validate:"omitempty"`
- URL URL `toml:"urls" json:"urls,omitempty" validate:"omitempty"`
- EnvironmentVariables map[string]string `toml:"environment_variables" json:"environment_variables,omitempty" validate:"omitempty"`
-
- // Analyzer, Autofix and Transformer config
- Analysis Analysis `toml:"analysis" json:"analysis" validate:"required"`
- // Autofix Autofix `toml:"autofix" json:"autofix" validate:"omitempty"`
-
- // Build steps needed to build the analyzer
- Build Build `toml:"build" json:"build" validate:"omitempty"`
-
- // Test command for running the testing workflow
- Test Test `toml:"test" json:"test" validate:"omitempty"`
-}
-
-// Analyzer issue description
-type AnalyzerIssue struct {
- Shortcode string `validate:"omitempty"`
- Title string `toml:"title" json:"title" validate:"required"`
- Description string `toml:"description" json:"description" validate:"required"`
- Category string `toml:"category" json:"category" validate:"required"`
-}
diff --git a/analyzers/validator/utils.go b/analyzers/validator/utils.go
index 873db0bed..01e91629b 100644
--- a/analyzers/validator/utils.go
+++ b/analyzers/validator/utils.go
@@ -1,9 +1,14 @@
package validator
import (
+ "errors"
+ "fmt"
+ "path"
"reflect"
+ "strings"
validate "github.com/go-playground/validator/v10"
+ "github.com/pelletier/go-toml/v2"
)
// Returns the list of required fields from the error message returned by the `go-playground/validator` library
@@ -22,3 +27,77 @@ func getMissingRequiredFields(err error, config interface{}) []string {
}
return missingRequiredFields
}
+
+// Handle decoding errors reported by go-toml
+func handleTOMLDecodeErrors(err error, filePath string) *ValidationFailure {
+ var usefulResponse, expectedType, receivedType, fieldName, decodeErrorMessage string
+
+ // Get the DecodeError exported by go-toml
+ // Ref: https://pkg.go.dev/github.com/pelletier/go-toml/v2#DecodeError
+ var decodeErr *toml.DecodeError
+ if !errors.As(err, &decodeErr) {
+ decodeErrorMessage = err.Error()
+
+ // Handle strict mode error when some alien fields are added in the user configured TOML
+ if strings.HasPrefix(err.Error(), "strict mode") {
+ decodeErrorMessage = fmt.Sprintf("failed to parse %s. Invalid fields detected.", path.Base(filePath))
+ }
+ validationError := ValidationFailure{
+ File: filePath,
+ Errors: []ErrorMeta{
+ {
+ Level: DecodeErr,
+ Field: "",
+ Message: decodeErrorMessage,
+ },
+ },
+ }
+ return &validationError
+ }
+
+ /* =================================================
+ * Extract the data about the decoding failure and return
+ * a validation failure response
+ * ================================================= */
+
+ errorMessage := decodeErr.Error()
+ // Error case 1: `toml: cannot decode TOML integer into struct field types.AnalyzerTOML.Name of type string"`
+ if strings.HasPrefix(errorMessage, "toml: cannot decode TOML") {
+
+ usefulResponse = strings.TrimPrefix(errorMessage, "toml: cannot decode TOML ")
+ responseArray := strings.Split(usefulResponse, " ")
+
+ expectedType = responseArray[len(responseArray)-1]
+ receivedType = responseArray[0]
+ fieldData := responseArray[len(responseArray)-4]
+ index := strings.LastIndex(fieldData, ".")
+ fieldName = strings.ToLower(fieldData[index:])
+ // Framing the decoding failure error message
+ decodeErrorMessage = fmt.Sprintf("expected the field \"%s\" of type %s. Got %s.", fieldName, expectedType, receivedType)
+
+ } else if strings.HasPrefix(errorMessage, "toml: cannot store TOML") {
+
+ // Error case 2: `toml: cannot store TOML string into a Go slice`
+ usefulResponse = strings.TrimPrefix(errorMessage, "toml: cannot store TOML ")
+ responseArray := strings.Split(usefulResponse, " ")
+
+ expectedType = responseArray[len(responseArray)-1]
+ receivedType = responseArray[0]
+ decodeErrorMessage = fmt.Sprintf("expected type for one of the fields : %s. Received: %s.", expectedType, receivedType)
+ } else {
+ decodeErrorMessage = errorMessage
+ fieldName = ""
+ }
+
+ validationError := ValidationFailure{
+ File: filePath,
+ Errors: []ErrorMeta{
+ {
+ Level: DecodeErr,
+ Field: fieldName,
+ Message: decodeErrorMessage,
+ },
+ },
+ }
+ return &validationError
+}
diff --git a/analyzers/validator/validator.go b/analyzers/validator/validator.go
index 1f294c194..d88d6611f 100644
--- a/analyzers/validator/validator.go
+++ b/analyzers/validator/validator.go
@@ -1,6 +1,7 @@
package validator
import (
+ "bytes"
"errors"
"fmt"
"io/ioutil"
@@ -8,48 +9,59 @@ import (
"path/filepath"
"strings"
- "github.com/deepsourcelabs/cli/analyzers/config"
- validate "github.com/go-playground/validator/v10"
+ "github.com/deepsourcelabs/cli/types"
"github.com/pelletier/go-toml/v2"
)
-type Error struct {
- Type string
+/* ==================================================
+ * Types used to report validation failure error data
+ * ================================================== */
+type ErrLevel int
+
+const (
+ DecodeErr ErrLevel = iota
+ Error
+ Warning
+ Information
+)
+
+type ErrorMeta struct {
+ Level ErrLevel
Field string
Message string
}
-type ValidationError struct {
+type ValidationFailure struct {
File string
- Errors []Error
+ Errors []ErrorMeta
}
-// Receives the path of the `analyzer.toml` and issue descriptions and
+// CheckForAnalyzerConfig receives the path of the `analyzer.toml` and issue descriptions and
// checks if they are actually present
func CheckForAnalyzerConfig(analyzerTOMLPath, issuesDirectoryPath string) (err error) {
// Check if `analyzer.toml` is present in `.deepsource/analyzer` folder
if _, err := os.Stat(analyzerTOMLPath); err != nil {
if errors.Is(err, os.ErrNotExist) {
- return errors.New("the analyzer.toml file doesn't exist\n")
+ return errors.New("the analyzer.toml file doesn't exist")
}
}
// Check if `issues/` directory is present in `.deepsource/analyzer` folder and is not empty.
if _, err := os.Stat(issuesDirectoryPath); err != nil {
if errors.Is(err, os.ErrNotExist) {
- return errors.New("the issue descriptions directory doesn't exist\n")
+ return errors.New("the issue descriptions directory doesn't exist")
}
}
// Check if there are any toml files in the `issues/` directory
files, err := ioutil.ReadDir(issuesDirectoryPath)
if err != nil {
- return fmt.Errorf("failed to read the files present in the issues directory at %s\n", issuesDirectoryPath)
+ return fmt.Errorf("failed to read the files present in the issues directory at %s", issuesDirectoryPath)
}
// Check if its an empty directory
if len(files) < 1 {
- return fmt.Errorf("found 0 issues configured in the issues directory at %s\n", issuesDirectoryPath)
+ return fmt.Errorf("found 0 issues configured in the issues directory at %s", issuesDirectoryPath)
}
tomlPresent := false
@@ -61,55 +73,48 @@ func CheckForAnalyzerConfig(analyzerTOMLPath, issuesDirectoryPath string) (err e
}
}
if !tomlPresent {
- return fmt.Errorf("found no toml files in the issues directory at %s\n", issuesDirectoryPath)
+ return fmt.Errorf("found no toml files in the issues directory at %s", issuesDirectoryPath)
}
return
}
-// Validates analyzer.toml file
-func ValidateAnalyzerTOML(analyzerTOMLPath string) (*config.AnalyzerMetadata, *ValidationError, error) {
- config := config.AnalyzerMetadata{}
- analyzerTOMLValidationErrors := ValidationError{}
+// ValidateAnalyzerTOML receives the path of analyzer.toml and reads as well as validates it for
+// the type checks, required fields etc. Returns the analyzer.toml content and the validation failures
+// if any in the form of ValidationFailure struct.
+func ValidateAnalyzerTOML(analyzerTOMLPath string) (*types.AnalyzerTOML, *ValidationFailure, error) {
+ config := types.AnalyzerTOML{}
// Read the contents of analyzer.toml file
analyzerTOMLContent, err := ioutil.ReadFile(analyzerTOMLPath)
if err != nil {
- return &config, nil, errors.New("failed to read analyzer.toml file")
- }
-
- // Unmarshal TOML into config
- if err = toml.Unmarshal(analyzerTOMLContent, &config); err != nil {
- return &config, nil, err
+ return nil, nil, errors.New("failed to read analyzer.toml file")
}
- // Validate analyzer.toml fields based on type and sanity checks
- v := validate.New()
- if err := v.Struct(&config); err != nil {
- missingRequiredFields := getMissingRequiredFields(err, config)
- analyzerTOMLValidationErrors = ValidationError{
- File: analyzerTOMLPath,
- }
-
- // TODO: Tweak this to accomodate other error types.
- for _, missingField := range missingRequiredFields {
- analyzerTOMLValidationErrors.Errors = append(analyzerTOMLValidationErrors.Errors, Error{
- Type: "ERROR",
- Field: missingField,
- Message: "Missing required field",
- },
- )
+ // Decode the TOML into the struct
+ d := toml.NewDecoder(bytes.NewBuffer(analyzerTOMLContent))
+ d.DisallowUnknownFields()
+ if err := d.Decode(&config); err != nil {
+ decodeErrorResp := handleTOMLDecodeErrors(err, analyzerTOMLPath)
+ if decodeErrorResp != nil {
+ return nil, decodeErrorResp, nil
}
- return &config, &analyzerTOMLValidationErrors, nil
+ return nil, nil, err
}
- return &config, nil, nil
+ // Validate the analyzer.toml fields for default/custom type checks, required fields
+ analyzerTOMLValidationErrors, err := validateAnalyzerTOMLFields(&config, analyzerTOMLPath)
+ if err != nil {
+ return nil, nil, err
+ }
+ return &config, analyzerTOMLValidationErrors, nil
}
-// Validates issue description TOML files
-func ValidateIssueDescriptions(issuesDirectoryPath string) (*[]ValidationError, error) {
- validationFailed := false
- issueValidationErrors := []ValidationError{}
+// ValidateIssueDescriptions receives the path of issues directory for reading and validating them
+// for type checks and required fields. Returns an array of ValidationFailure struct containing
+// validation errors for each issue TOML file.
+func ValidateIssueDescriptions(issuesDirectoryPath string) (*[]ValidationFailure, error) {
+ issueValidationErrors := []ValidationFailure{}
// TODO: List only TOML files here
issuesList, err := ioutil.ReadDir(issuesDirectoryPath)
@@ -117,10 +122,11 @@ func ValidateIssueDescriptions(issuesDirectoryPath string) (*[]ValidationError,
return nil, err
}
+ // Iterate over the issues one by one, read and decode them, validate the fields and return the
+ // validation result.
for _, issuePath := range issuesList {
- config := AnalyzerIssue{}
-
// Set the issue shortcode as the filename
+ config := types.AnalyzerIssue{}
config.Shortcode = strings.TrimSuffix(issuePath.Name(), ".toml")
// Read the contents of issue toml file
@@ -129,35 +135,23 @@ func ValidateIssueDescriptions(issuesDirectoryPath string) (*[]ValidationError,
return nil, fmt.Errorf("failed to read file: %s", filepath.Join(issuesDirectoryPath, issuePath.Name()))
}
- // Unmarshal TOML into config
- if err = toml.Unmarshal(issueTOMLContent, &config); err != nil {
- return nil, err
- }
-
- // Validate the data
- v := validate.New()
- if err := v.Struct(&config); err != nil {
- validationFailed = true
- missingRequiredFields := getMissingRequiredFields(err, config)
- issueValidationError := ValidationError{
- File: issuePath.Name(),
+ // Decode the TOML content into the AnalyzerIssue struct object
+ d := toml.NewDecoder(bytes.NewBuffer(issueTOMLContent))
+ d.DisallowUnknownFields()
+ if err = d.Decode(&config); err != nil {
+ decodeErrorResp := handleTOMLDecodeErrors(err, issuePath.Name())
+ if decodeErrorResp != nil {
+ // Append the error to the array created for reporting issue validation errors and return it
+ issueValidationErrors = append(issueValidationErrors, *decodeErrorResp)
+ continue
}
-
- // TODO: Tweak this to accomodate other error types.
- for _, missingField := range missingRequiredFields {
- issueValidationError.Errors = append(issueValidationError.Errors, Error{
- Type: "ERROR",
- Field: missingField,
- Message: "Missing required field",
- },
- )
- }
- issueValidationErrors = append(issueValidationErrors, issueValidationError)
}
- }
- if validationFailed {
- return &issueValidationErrors, nil
+ // Validate the analyzer.toml fields for default/custom type checks, required fields
+ issueValidationError := validateIssueTOML(&config, issuePath.Name())
+ if issueValidationError != nil {
+ issueValidationErrors = append(issueValidationErrors, *issueValidationError)
+ }
}
- return nil, nil
+ return &issueValidationErrors, nil
}
diff --git a/cmd/Dockerfile_new b/cmd/Dockerfile_new
new file mode 100644
index 000000000..611fc0609
--- /dev/null
+++ b/cmd/Dockerfile_new
@@ -0,0 +1,2 @@
+
+FROM alpine
diff --git a/command/analyzer/initialize/init.go b/command/analyzer/initialize/init.go
index 0b66c7b32..5395f0b01 100644
--- a/command/analyzer/initialize/init.go
+++ b/command/analyzer/initialize/init.go
@@ -2,10 +2,8 @@ package initialize
import (
"bytes"
- "errors"
"fmt"
"os"
- "path/filepath"
"strings"
"github.com/pelletier/go-toml"
@@ -13,7 +11,7 @@ import (
"github.com/spf13/cobra"
"github.com/deepsourcelabs/cli/analyzers/config"
- validator "github.com/deepsourcelabs/cli/analyzers/validator"
+ "github.com/deepsourcelabs/cli/types"
"github.com/deepsourcelabs/cli/utils"
)
@@ -22,27 +20,35 @@ type SDKResponse struct {
SDKLanguage string
}
+type InputPrompt interface {
+ ConfirmFromUser(string, string) (bool, error)
+ GetSingleLineInput(string, string, string) (string, error)
+ SelectFromOptions(string, string, []string) (string, error)
+}
+
type AnalyzerInitOpts struct {
+ Namespace string
+ AnalyzerName string
SDKInput SDKResponse
ProjectRootPath string
AnalyzerTOMLPath string
- AnalyzerTOMLData validator.AnalyzerMetadata
IssuesDirectoryPath string
AnalyzerShortcodeArg string
-
- ConfirmationPrompt func(string, string) (bool, error)
- SingleLineInputPrompt func(string, string, string) (string, error)
- DescriptionPrompt func(string, string, string) (string, error)
- SingleOptionPrompt func(string, string, []string) (string, error)
+ AnalyzerTOMLData types.AnalyzerTOML
+ PromptUtils InputPrompt
}
+/* =============================================================
+ * $ deepsource analyzer init
+ *
+ * Helps in initializing the config for a new DeepSource Analyzer
+ * ============================================================== */
func NewCmdAnalyzerInit() *cobra.Command {
cwd, _ := os.Getwd()
+
opts := AnalyzerInitOpts{
- SingleLineInputPrompt: utils.GetSingleLineInput,
- DescriptionPrompt: utils.GetSingleLineInput,
- ConfirmationPrompt: utils.ConfirmFromUser,
- SingleOptionPrompt: utils.SelectFromOptions,
+ PromptUtils: utils.UserInputPrompt{},
+ AnalyzerShortcodeArg: "",
}
// Fetch the project root path and analyzer.toml path
@@ -51,17 +57,23 @@ func NewCmdAnalyzerInit() *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Initialize DeepSource Analyzer",
- Args: utils.ExactArgs(1),
+ Args: utils.MaxNArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
- // Check if the analyzer.toml already exists. If yes, display that the analyzer already initialized at `.deepsource/analyzer/analyzer.toml`
+ // Check if the analyzer.toml already exists.
+ // If yes, display that the analyzer already initialized at `.deepsource/analyzer/analyzer.toml`
if _, err := os.Stat(opts.AnalyzerTOMLPath); err == nil {
pterm.Info.Printf("Analyzer already initialized at %s. Exiting...\n", strings.TrimPrefix(opts.AnalyzerTOMLPath, cwd+"/"))
return nil
}
+ // Check for the shortcode argument (if any)
if len(args) > 0 {
opts.AnalyzerShortcodeArg = args[0]
+ if !strings.HasPrefix(opts.AnalyzerShortcodeArg, "@") {
+ opts.AnalyzerShortcodeArg = strings.ToLower("@" + opts.AnalyzerShortcodeArg)
+ }
}
+
analysisConfigBytes, err := opts.initAnalyzer()
if err != nil {
return fmt.Errorf("Analyzer initialization failed. Error: %s", err)
@@ -69,90 +81,191 @@ func NewCmdAnalyzerInit() *cobra.Command {
if err = opts.writeAnalyzerTOMLConfig(analysisConfigBytes); err != nil {
return fmt.Errorf("Analyzer initialization failed. Error: %s", err)
}
- pterm.Success.Printf("Analyzer %s set up successfully!\n", opts.AnalyzerTOMLData.Shortcode)
+ pterm.Success.Printf("Analyzer %s initialized successfully!\n", opts.AnalyzerTOMLData.Shortcode)
return nil
},
}
return cmd
}
-// Initialize the Analyzer
+// initAnalyzer helps the Analyzer authors initialize a new Analyzer
+// in an interactive way with the help of suitable prompts
func (a *AnalyzerInitOpts) initAnalyzer() (*bytes.Buffer, error) {
- var err error
- var msg, helpText string
- supportedSDKS := getSupportedSDKs()
+ // If the user didn't add an Analyzer shortcode argument to the command and
+ // just ran `deepsource analyzer init`, input the Namespace and Analyzer name from the user
+ // and create the Analyzer shortcode in the format : @/
+ if a.AnalyzerShortcodeArg == "" {
+ if err := a.fetchNamespaceAndAnalyzerName(); err != nil {
+ return nil, err
+ }
+ }
- pterm.Info.Printf("Initializing analyzer %s...\n", a.AnalyzerShortcodeArg)
a.AnalyzerTOMLData.Shortcode = strings.ToLower(a.AnalyzerShortcodeArg)
+ pterm.Info.Printf("Initializing analyzer %s...\n", a.AnalyzerTOMLData.Shortcode)
- // Fetch the default analyzer name from the shortcode
- // Eg: @deepsource/armory -> Armory
- defaultAnalyzerName := strings.Title(strings.SplitAfter(a.AnalyzerTOMLData.Shortcode, "/")[1]) // skipcq: SCC-SA1019
+ // Collect Analyzer name and description
+ if err := a.fetchAnalyzerDisplayNameAndDescription(); err != nil {
+ return nil, err
+ }
- // Collect name of the Analyzer
- msg = "Please enter the name of the Analyzer?"
- helpText = "The name of the Analyzer."
- if a.AnalyzerTOMLData.Name, err = a.SingleLineInputPrompt(msg, helpText, defaultAnalyzerName); err != nil {
+ // Collect Analyzer tags
+ if err := a.fetchTags(); err != nil {
return nil, err
}
- // Collect description of the Analyzer
- msg = "Description of the Analyzer?"
- helpText = "What does the Analyzer do?"
- if a.AnalyzerTOMLData.Description, err = a.DescriptionPrompt(msg, helpText, ""); err != nil {
+ // Collect the required URLs (git repository URL for example)
+ if err := a.fetchURLs(); err != nil {
return nil, err
}
- if len(supportedSDKS) > 0 {
- // Check if DeepSource SDK is needed or not?
- msg = "Would you like to use DeepSource Analyzer SDK to build your Analyzer?"
- helpText = "DeepSource SDKs help you to easily create an Analyzer"
- if a.SDKInput.SDKRequired, err = a.ConfirmationPrompt(msg, helpText); err != nil {
- return nil, err
- }
+ // Collect the required analysis and test commands
+ if err := a.fetchCommands(); err != nil {
+ return nil, err
+ }
- if a.SDKInput.SDKRequired {
- msg = "Which language do you want the SDK for:"
- helpText = "Choose the language for which the SDK will be generated"
- if a.SDKInput.SDKLanguage, err = a.SingleOptionPrompt(msg, helpText, supportedSDKS); err != nil {
- return nil, err
- }
- }
+ // Collect the SDKs to use
+ if err := a.fetchSDKInput(); err != nil {
+ return nil, err
}
+ // Setting build.engine as "docker"
+ // TODO(SNT): Remove this once more than one build engines are supported.
+ a.AnalyzerTOMLData.Build.Engine = "docker"
+
// Encoding the struct to TOML
// and storing in GeneratedConfig of Options struct
var buf bytes.Buffer
- if err = toml.NewEncoder(&buf).Order(toml.OrderPreserve).Encode(a.AnalyzerTOMLData); err != nil {
+ if err := toml.NewEncoder(&buf).Order(toml.OrderPreserve).Encode(a.AnalyzerTOMLData); err != nil {
return nil, err
}
-
return &buf, nil
}
-// Writes the Analyzer TOML data to the file
-func (a *AnalyzerInitOpts) writeAnalyzerTOMLConfig(buf *bytes.Buffer) (err error) {
- // Create the .deepsource/analyzer directory and issues/ directory
- directoriesToCreate := []string{".deepsource", ".deepsource/analyzer", ".deepsource/analyzer/issues/"}
+/* Input the namespace and Analyzer name from the user in case the user didn't mention it as an
+ * argument to the `deepsource analyzer init` command */
+func (a *AnalyzerInitOpts) fetchNamespaceAndAnalyzerName() (err error) {
+ // TODO(SNT): Change this to use a public API to show a list of namespaces the user has access to.
+ msg := "Namespace"
+ helpText := "The namespace to which the Analyzer will be associated."
+ if a.Namespace, err = a.PromptUtils.GetSingleLineInput(msg, helpText, ""); err != nil {
+ return err
+ }
- // Create the required directories mentioned above
- for _, dir := range directoriesToCreate {
- if _, err := os.Stat(filepath.Join(a.ProjectRootPath, dir)); errors.Is(err, os.ErrNotExist) {
- if err = os.Mkdir(filepath.Join(a.ProjectRootPath, dir), 0o750); err != nil {
- return err
- }
- }
+ // Check for empty namespace and return error
+ if a.Namespace == "" {
+ return fmt.Errorf("namespace cannot be empty")
+ }
+
+ // Sanitize the namespace
+ a.Namespace = sanitizeInput(a.Namespace)
+
+ // Input shortcode of the Analyzer.
+ msg = "Name of the Analyzer"
+ helpText = "Name of the Analyzer. This is to be used to access the Analyzer as: @/."
+ if a.AnalyzerName, err = a.PromptUtils.GetSingleLineInput(msg, helpText, ""); err != nil {
+ return err
+ }
+
+ // Check for empty shortcode and return error.
+ if a.AnalyzerName == "" {
+ return fmt.Errorf("Analyzer name cannot be empty")
+ }
+
+ // Sanitize the Analyzer name
+ a.AnalyzerName = sanitizeInput(a.AnalyzerName)
+
+ a.AnalyzerShortcodeArg = strings.ToLower("@" + a.Namespace + "/" + a.AnalyzerName)
+ return
+}
+
+// fetchAnalyzerDisplayNameAndDescription collects input for the Analyzer display name and description from the Analyzer author
+func (a *AnalyzerInitOpts) fetchAnalyzerDisplayNameAndDescription() (err error) {
+ // Fetch the default analyzer name from the shortcode
+ // Eg: @deepsource/armory -> Armory
+ defaultAnalyzerName := strings.Title(strings.Split(a.AnalyzerTOMLData.Shortcode, "/")[1]) // skipcq: SCC-SA1019
+
+ // Collect name of the Analyzer
+ msg := "Display name of the Analyzer"
+ helpText := "The name of the Analyzer which will be displayed on the dashboard."
+ if a.AnalyzerTOMLData.Name, err = a.PromptUtils.GetSingleLineInput(msg, helpText, defaultAnalyzerName); err != nil {
+ return err
}
- // Write the input data to analyzer.toml
- if err = os.WriteFile(a.AnalyzerTOMLPath, buf.Bytes(), 0o644); err != nil {
+ // Collect description of the Analyzer
+ msg = "Description of the Analyzer"
+ helpText = "Explain what the Analyzer does and the kinds of issues it detects."
+ if a.AnalyzerTOMLData.Description, err = a.PromptUtils.GetSingleLineInput(msg, helpText, ""); err != nil {
+ return err
+ }
+ return nil
+}
+
+// fetchTags collects input for any tags/keywords that the Analyzer author would like to
+// configure for the Analyzer
+func (a *AnalyzerInitOpts) fetchTags() error {
+ msg := "Tags for the Analyzer (comma or space separated)"
+ helpText := "Some keywords related to the Analyzer. Use commas/spaces to separate the keywords."
+ analyzerTags, err := a.PromptUtils.GetSingleLineInput(msg, helpText, "")
+ if err != nil {
+ return err
+ }
+
+ // Parse tags from the user input
+ a.AnalyzerTOMLData.Tags = processAnalyzerTags(analyzerTags)
+ return nil
+}
+
+// fetchURLs collects the git repository URL of the Analyzer
+func (a *AnalyzerInitOpts) fetchURLs() error {
+ defaultRemoteURL, err := fetchRemoteURL()
+ if err != nil {
+ defaultRemoteURL = ""
+ }
+ msg := "Git repository URL of the Analyzer?"
+ helpText := "The remote repository URL of the Analyzer."
+ if a.AnalyzerTOMLData.Repository, err = a.PromptUtils.GetSingleLineInput(msg, helpText, strings.TrimRight(defaultRemoteURL, "\n")); err != nil {
+ return err
+ }
+ return nil
+}
+
+// fetchCommands fetches the analysis and test command that the Analyzer author wants to configure
+func (a *AnalyzerInitOpts) fetchCommands() (err error) {
+ // Collect the analysis command of the Analyzer
+ msg := "Analysis command for the Analyzer"
+ helpText := "The command used to execute the Analyzer"
+ if a.AnalyzerTOMLData.Analysis.Command, err = a.PromptUtils.GetSingleLineInput(msg, helpText, ""); err != nil {
+ return err
+ }
+
+ // Collect the test command of the Analyzer
+ msg = "Test command for the Analyzer"
+ helpText = "The command used to run tests on the Analyzer"
+ if a.AnalyzerTOMLData.Test.Command, err = a.PromptUtils.GetSingleLineInput(msg, helpText, ""); err != nil {
return err
}
return
}
-// Returns the list of supported SDKs
-// TODO: Send the list of supported SDKs from here once we start supporting any
-func getSupportedSDKs() []string {
- return []string{""}
+// fetchSDKInput fetches the user input for the DeepSource Analyzer SDKs the Analyzer author wants to
+// use for the Analyzer
+func (a *AnalyzerInitOpts) fetchSDKInput() (err error) {
+ supportedSDKS := getSupportedSDKs()
+ if len(supportedSDKS) > 0 {
+ // Check if DeepSource SDK is needed or not?
+ msg := "Would you like to use DeepSource Analyzer SDK to build your Analyzer?"
+ helpText := "DeepSource SDKs help you to easily create an Analyzer"
+ if a.SDKInput.SDKRequired, err = a.PromptUtils.ConfirmFromUser(msg, helpText); err != nil {
+ return err
+ }
+
+ if a.SDKInput.SDKRequired {
+ msg := "Which language do you want the SDK for:"
+ helpText := "Choose the language for which the SDK will be generated"
+ if a.SDKInput.SDKLanguage, err = a.PromptUtils.SelectFromOptions(msg, helpText, supportedSDKS); err != nil {
+ return err
+ }
+ }
+ }
+ return
}
diff --git a/command/analyzer/initialize/init_test.go b/command/analyzer/initialize/init_test.go
index ac63097eb..a066b40b0 100644
--- a/command/analyzer/initialize/init_test.go
+++ b/command/analyzer/initialize/init_test.go
@@ -2,97 +2,104 @@ package initialize
import (
"reflect"
+ "strings"
"testing"
)
-var (
- singleLineInputResponse, descriptionInputResponse, singleOptionPromptResponse string
- confirmationResponse bool
-)
-
-func mockGetSingleLineInput(string, string, string) (string, error) {
- return singleLineInputResponse, nil
-}
-
-func mockDescriptionPrompt(string, string, string) (string, error) {
- return descriptionInputResponse, nil
-}
-
-func mockConfirmFromUser(string, string) (bool, error) {
- return confirmationResponse, nil
-}
-
-func mockSingleOptionPrompt(string, string, []string) (string, error) {
- return singleOptionPromptResponse, nil
-}
-
-type Test struct {
+type MockInputPrompt struct {
AnalyzerShortcode string
AnalyzerName string
AnalyzerDescription string
+ AnalyzerTags string
+ Repository string
+ AnalysisCommand string
+ TestCommand string
SDKRequired bool
SDKLanguage string
ExpectedConfig string
}
-func TestInitAnalyzer(t *testing.T) {
- // Creating an instance of AnalyzerInitOpts
-
- opts := AnalyzerInitOpts{
- SingleLineInputPrompt: mockGetSingleLineInput,
- DescriptionPrompt: mockDescriptionPrompt,
- ConfirmationPrompt: mockConfirmFromUser,
- SingleOptionPrompt: mockSingleOptionPrompt,
+func (m MockInputPrompt) GetSingleLineInput(msg, _, _ string) (string, error) {
+ if strings.Contains(msg, "Display name") {
+ return m.AnalyzerName, nil
+ }
+ if strings.Contains(msg, "Description") {
+ return m.AnalyzerDescription, nil
+ }
+ if strings.Contains(msg, "Tags") {
+ return m.AnalyzerTags, nil
+ }
+ if strings.Contains(msg, "Git repository") {
+ return m.Repository, nil
}
+ if strings.Contains(msg, "Analysis command") {
+ return m.AnalysisCommand, nil
+ }
+ if strings.Contains(msg, "Test command") {
+ return m.TestCommand, nil
+ }
+ return "", nil
+}
+
+func (m MockInputPrompt) ConfirmFromUser(_, _ string) (bool, error) {
+ return m.SDKRequired, nil
+}
+
+func (m MockInputPrompt) SelectFromOptions(_, _ string, _ []string) (string, error) {
+ return m.SDKLanguage, nil
+}
- testCases := []Test{
+func TestInitAnalyzer(t *testing.T) {
+ testCases := []MockInputPrompt{
{
AnalyzerShortcode: "@deepsource/demo-python",
AnalyzerName: "Python Analyzer",
AnalyzerDescription: "This is a python analyzer",
+ AnalyzerTags: "python, analyzer, static-analysis",
+ Repository: "https://github.com/deepsourcelabs/demo-python",
+ AnalysisCommand: "./analysis.sh",
+ TestCommand: "./test-command.sh",
SDKRequired: false,
SDKLanguage: "",
ExpectedConfig: `name = "Python Analyzer"
shortcode = "@deepsource/demo-python"
description = "This is a python analyzer"
-category = ""
-tags = []
-
-[urls]
- source = ""
- documentation = ""
- bug_tracker = ""
+tags = ["python", "analyzer", "static-analysis"]
+repository = "https://github.com/deepsourcelabs/demo-python"
+documentation = ""
+bug_tracker = ""
[environment_variables]
[analysis]
- command = ""
+ command = "./analysis.sh"
[build]
- builder = ""
+ engine = "docker"
dockerfile = ""
script = ""
[test]
- command = ""
+ command = "./test-command.sh"
`,
},
{
AnalyzerShortcode: "@deepsource/demo-go",
AnalyzerName: "Go Analyzer",
AnalyzerDescription: "This is a golang analyzer",
+ AnalyzerTags: "golang go analyzer static-analysis",
+ Repository: "https://gitlab.com/deepsourcelabs/demo-go",
+ AnalysisCommand: "",
+ TestCommand: "",
SDKRequired: true,
SDKLanguage: "Go",
ExpectedConfig: `name = "Go Analyzer"
shortcode = "@deepsource/demo-go"
description = "This is a golang analyzer"
-category = ""
-tags = []
-
-[urls]
- source = ""
- documentation = ""
- bug_tracker = ""
+tags = ["golang", "go", "analyzer", "static-analysis"]
+repository = "https://gitlab.com/deepsourcelabs/demo-go"
+documentation = ""
+bug_tracker = ""
[environment_variables]
@@ -100,7 +107,7 @@ tags = []
command = ""
[build]
- builder = ""
+ engine = "docker"
dockerfile = ""
script = ""
@@ -111,12 +118,10 @@ tags = []
}
for _, tc := range testCases {
+ opts := AnalyzerInitOpts{
+ PromptUtils: tc,
+ }
opts.AnalyzerShortcodeArg = tc.AnalyzerShortcode
- singleLineInputResponse = tc.AnalyzerName
- descriptionInputResponse = tc.AnalyzerDescription
- confirmationResponse = tc.SDKRequired
- singleOptionPromptResponse = tc.SDKLanguage
-
buf, err := opts.initAnalyzer()
if err != nil {
t.Error(err)
diff --git a/command/analyzer/initialize/utils.go b/command/analyzer/initialize/utils.go
new file mode 100644
index 000000000..ff23ea694
--- /dev/null
+++ b/command/analyzer/initialize/utils.go
@@ -0,0 +1,104 @@
+package initialize
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+// Contains the list of supported SDKs for building DeepSource Analyzers
+var supportedAnalyzerSDKs = []string{}
+
+func processAnalyzerTags(userInput string) []string {
+ re := regexp.MustCompile("[ ,]")
+ return delete_empty(re.Split(userInput, -1))
+}
+
+func delete_empty(s []string) []string {
+ var r []string
+ for _, str := range s {
+ if str != "" {
+ r = append(r, str)
+ }
+ }
+ return r
+}
+
+func fetchRemoteURL() (string, error) {
+ var remoteRepoURL string
+
+ // TODO: Add support for fetching URLs for other remotes here as well
+ remoteURL, err := exec.Command("git", "config", "--get", "remote.origin.url").Output()
+ if err != nil {
+ return "", err
+ }
+ remoteRepoURL = strings.TrimRight(string(remoteURL), "\000\n")
+
+ // Return the remoteURL if it already begins with `https://`
+ if strings.HasPrefix(remoteRepoURL, "https://") {
+ return remoteRepoURL, nil
+ }
+
+ // If the URL doesn't begin with `git@` don't move further and send an empty default remoteURL
+ if !strings.HasPrefix(remoteRepoURL, "git@") {
+ return "", fmt.Errorf("couldn't parse the default remote URL")
+ }
+
+ // If the URL begins with `git@`, extract the substring till the colon(:) in the remote URL
+ colonIndex := strings.Index(remoteRepoURL, ":")
+ if colonIndex == -1 {
+ return remoteRepoURL, fmt.Errorf("couldn't parse the default remote URL")
+ }
+
+ vcsURL := remoteRepoURL[:colonIndex]
+ switch vcsURL {
+ case "git@github.com":
+ urlComponent := strings.TrimPrefix(remoteRepoURL, "git@github.com:")
+ remoteRepoURL = "https://github.com/" + urlComponent
+ case "git@gitlab.com":
+ urlComponent := strings.TrimPrefix(remoteRepoURL, "git@gitlab.com:")
+ remoteRepoURL = "https://gitlab.com/" + urlComponent
+ case "git@bitbucket.org":
+ urlComponent := strings.TrimPrefix(remoteRepoURL, "git@bitbucket.org:")
+ remoteRepoURL = "https://bitbucket.org/" + urlComponent
+ }
+ return strings.TrimSuffix(remoteRepoURL, ".git"), nil
+}
+
+// Returns the list of supported SDKs
+func getSupportedSDKs() []string {
+ return supportedAnalyzerSDKs
+}
+
+// Sanitize the input of namespace and Analyzer shortcode for any spaces
+// or special characters and replace them with hyphen
+func sanitizeInput(input string) string {
+ re := regexp.MustCompile("[^a-zA-Z0-9_]+")
+ return re.ReplaceAllString(input, "-")
+}
+
+// Writes the Analyzer TOML data to the file
+func (a *AnalyzerInitOpts) writeAnalyzerTOMLConfig(buf *bytes.Buffer) (err error) {
+ // Create the .deepsource/analyzer directory and issues/ directory
+ directoriesToCreate := []string{".deepsource", ".deepsource/analyzer", ".deepsource/analyzer/issues/"}
+
+ // Create the required directories mentioned above
+ for _, dir := range directoriesToCreate {
+ if _, err := os.Stat(filepath.Join(a.ProjectRootPath, dir)); errors.Is(err, os.ErrNotExist) {
+ if err = os.Mkdir(filepath.Join(a.ProjectRootPath, dir), 0o750); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Write the input data to analyzer.toml
+ if err = os.WriteFile(a.AnalyzerTOMLPath, buf.Bytes(), 0o750); err != nil {
+ return err
+ }
+ return
+}
diff --git a/command/analyzer/verify/build.go b/command/analyzer/verify/build.go
index 6f69192c1..481065492 100644
--- a/command/analyzer/verify/build.go
+++ b/command/analyzer/verify/build.go
@@ -29,14 +29,19 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzerDockerBuild() (err error) {
* Check for the presence of `build.Dockerfile` or if not a `Dockerfile` in the current working directory */
if _, err := os.Stat(a.Build.DockerFilePath); err != nil {
if errors.Is(err, os.ErrNotExist) {
- a.Spinner.StopSpinnerWithError("Failed to build the image", fmt.Errorf("%s not found\n", a.Build.DockerFilePath))
+ if a.Build.VerboseMode {
+ msg := utils.GetFailureMessage("Failed to build the image", fmt.Sprintf("%s not found", a.Build.DockerFilePath))
+ fmt.Println(msg)
+ return fmt.Errorf(msg)
+ }
+ a.Spinner.StopSpinnerWithError("Failed to build the image", fmt.Errorf("%s not found", a.Build.DockerFilePath))
return err
}
}
- /* ///////////////////////////////////
+ /* ===================================
* Analyzer docker build verification
- * /////////////////////////////////// */
+ * =================================== */
/* Initialize the builder with the above fetched details
* Use the `GenerateImageVersion` utility to generate a random string of length 7 to tag the image */
@@ -51,8 +56,12 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzerDockerBuild() (err error) {
ctxCancelFunc, buildRespReader, buildErr := analyzerBuilder.BuildAnalyzerDockerImage()
// Cancel the build context and close the reader before exiting this function
- defer buildRespReader.Close()
- defer ctxCancelFunc()
+ if buildRespReader != nil {
+ defer buildRespReader.Close()
+ }
+ if ctxCancelFunc != nil {
+ defer ctxCancelFunc()
+ }
if buildErr != nil {
a.handleBuildError(buildErr)
@@ -67,7 +76,7 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzerDockerBuild() (err error) {
// In case of verbose mode, no need to stop the spinner
if a.Build.VerboseMode {
- fmt.Print(utils.GetSuccessMessage("Successfully built the Analyzer image"))
+ fmt.Print(utils.GetSuccessMessage("Successfully built the Analyzer image\n"))
return nil
}
a.Spinner.StopSpinner()
@@ -77,7 +86,7 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzerDockerBuild() (err error) {
// Utility to handle the output in case of build errors for different modes
func (a *AnalyzerVerifyOpts) handleBuildError(buildError error) {
if a.Build.VerboseMode {
- fmt.Println(utils.GetFailureMessage("Failed to build the image", buildError.Error()))
+ fmt.Printf("%s\n", utils.GetFailureMessage("Failed to build the image", buildError.Error()))
return
}
a.Spinner.StopSpinnerWithError("Failed to build the image", fmt.Errorf(buildError.Error()))
diff --git a/command/analyzer/verify/verify.go b/command/analyzer/verify/verify.go
index c89e22a7f..c1a39094b 100644
--- a/command/analyzer/verify/verify.go
+++ b/command/analyzer/verify/verify.go
@@ -5,9 +5,10 @@ import (
"fmt"
"path/filepath"
- "github.com/deepsourcelabs/cli/analyzers/config"
"github.com/deepsourcelabs/cli/analyzers/validator"
+ "github.com/deepsourcelabs/cli/types"
"github.com/deepsourcelabs/cli/utils"
+ "github.com/pterm/pterm"
"github.com/spf13/cobra"
)
@@ -24,14 +25,14 @@ type AnalyzerBuild struct {
}
type AnalyzerVerifyOpts struct {
- AnalyzerTOMLData *config.AnalyzerMetadata
+ AnalyzerTOMLData *types.AnalyzerTOML
Build AnalyzerBuild
Spinner *utils.SpinnerUtils
}
-/* ////////////////////////////////////
+/* ======================================
* $ deepsource analyzer verify
- * /////////////////////////////////// */
+ * ====================================== */
func NewCmdAnalyzerVerify() *cobra.Command {
// Configuring the paths of analyzer.toml and issues directory
@@ -54,8 +55,9 @@ func NewCmdAnalyzerVerify() *cobra.Command {
Args: utils.NoArgs,
RunE: func(_ *cobra.Command, _ []string) error {
if err := opts.verifyAnalyzer(); err != nil {
- return errors.New("Analyzer verification failed. Exiting...")
+ return errors.New("Analyzer verification failed. Exiting.")
}
+ pterm.Success.Println("Analyzer verification successful!")
return nil
},
}
@@ -65,21 +67,21 @@ func NewCmdAnalyzerVerify() *cobra.Command {
return cmd
}
-/* ////////////////////////////////////
+/* ====================================
* Analyzer configuration verification
- * /////////////////////////////////// */
+ * ==================================== */
func (a *AnalyzerVerifyOpts) verifyAnalyzer() (err error) {
- var validationErrors *[]validator.ValidationError
- var analyzerTOMLValidationErrors *validator.ValidationError
+ var analyzerTOMLValidationErrors *validator.ValidationFailure
+ var issuesValidationErrors *[]validator.ValidationFailure
configurationValid := true
- /* //////////////////////////////////////////////////////////////////////////////////
+ /* ==================================================================================
* Checks for the presence of .deepsource/analyzer directory,
* the analyzer.toml file and issues present in .deepsource/analyzer/issues directory
- * /////////////////////////////////////////////////////////////////////////////////// */
+ * ================================================================================== */
- a.Spinner.StartSpinnerWithLabel("Checking for presence of analyzer.toml and issue descriptions...", "Yay!!Found analyzer.toml and issue descriptions.")
+ a.Spinner.StartSpinnerWithLabel("Checking for presence of analyzer.toml and issue descriptions...", "Found analyzer.toml and issue descriptions")
if err = validator.CheckForAnalyzerConfig(analyzerTOMLPath, issuesDirPath); err != nil {
configurationValid = false
a.Spinner.StopSpinnerWithError("Failed to locate analyzer configurations", err)
@@ -87,43 +89,47 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzer() (err error) {
}
a.Spinner.StopSpinner()
- /* ///////////////////////////////
+ /* ==============================
* Read and verify analyzer.toml
- * ////////////////////////////// */
+ * ============================== */
a.Spinner.StartSpinnerWithLabel("Validating analyzer.toml...", "Verified analyzer.toml")
a.AnalyzerTOMLData, analyzerTOMLValidationErrors, err = validator.ValidateAnalyzerTOML(analyzerTOMLPath)
- if len(analyzerTOMLValidationErrors.Errors) > 0 {
+ // TODO: Handle err here
+ if err != nil {
configurationValid = false
- a.Spinner.StopSpinnerWithError("Failed to verify analyzer.toml\n", err)
+ a.Spinner.StopSpinnerWithError("Failed to verify analyzer.toml", err)
+ }
+
+ // Check for validation errors in analyzer.toml and display them (if any)
+ if analyzerTOMLValidationErrors != nil && len(analyzerTOMLValidationErrors.Errors) > 0 {
+ configurationValid = false
+ a.Spinner.StopSpinnerWithError("Failed to verify analyzer.toml", err)
for _, err := range analyzerTOMLValidationErrors.Errors {
- msg := fmt.Sprintf("%s : %s", err.Message, err.Field)
- failureMsg := utils.GetFailureMessage(msg, "")
- fmt.Printf(" * %s\n", failureMsg)
+ fmt.Printf(" %s\n", utils.GetBulletMessage(err.Message, "red"))
}
}
a.Spinner.StopSpinner()
- /* //////////////////////////////////////
- * Reads and verifies issue descriptions
- * ///////////////////////////////////// */
+ /* ====================================
+ * Read and verify issue descriptions
+ * ==================================== */
a.Spinner.StartSpinnerWithLabel("Validating issue descriptions...", "Verified issue descriptions")
- if validationErrors, err = validator.ValidateIssueDescriptions(issuesDirPath); err != nil {
+ if issuesValidationErrors, err = validator.ValidateIssueDescriptions(issuesDirPath); err != nil {
configurationValid = false
- a.Spinner.StopSpinnerWithError("Failed to validate the following issue desriptions", err)
+ a.Spinner.StopSpinnerWithError("Failed to validate the issues", err)
}
- // Check if there are any validation errors in issue descriptions
- if validationErrors != nil {
+ // Check for validation errors in analyzer issues and display them (if any)
+ if issuesValidationErrors != nil && len(*issuesValidationErrors) > 0 {
configurationValid = false
- a.Spinner.StopSpinnerWithError("Failed to validate the following issue descriptions\n", err)
- for _, validationError := range *validationErrors {
- fmt.Printf(" * %s\n", validationError.File)
+ a.Spinner.StopSpinnerWithError("Failed to validate the following issues", err)
+ for _, validationError := range *issuesValidationErrors {
+ fmt.Printf(" > %s\n", validationError.File)
for _, err := range validationError.Errors {
- msg := fmt.Sprintf("%s : %s", err.Message, err.Field)
- failureMsg := utils.GetFailureMessage(msg, "")
- fmt.Printf(" * %s\n", failureMsg)
+ failureMsg := utils.GetBulletMessage(err.Message, "red")
+ fmt.Printf(" %s\n", failureMsg)
}
}
}
@@ -131,12 +137,12 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzer() (err error) {
// Do not proceed to building the image if the configuration verification fails
if !configurationValid {
- return
+ return fmt.Errorf("verification failed")
}
- /* ////////////////////////////////////////////////////
+ /* ====================================================
* Verify the local docker image build of the Analyzer
- * /////////////////////////////////////////////////// */
+ * ==================================================== */
return a.verifyAnalyzerDockerBuild()
}
diff --git a/command/auth/login/login.go b/command/auth/login/login.go
index 249867bdc..279379ee0 100644
--- a/command/auth/login/login.go
+++ b/command/auth/login/login.go
@@ -19,6 +19,7 @@ type LoginOptions struct {
HostName string
Interactive bool
PAT string
+ Prompt utils.UserInputPrompt
}
// NewCmdLogin handles the login functionality for the CLI
@@ -41,6 +42,7 @@ func NewCmdLogin() *cobra.Command {
TokenExpired: true,
User: "",
HostName: "",
+ Prompt: utils.UserInputPrompt{},
}
cmd := &cobra.Command{
@@ -92,7 +94,7 @@ func (opts *LoginOptions) Run() (err error) {
if !opts.TokenExpired {
// The user is already logged in, confirm re-authentication.
msg := fmt.Sprintf("You're already logged into DeepSource as %s. Do you want to re-authenticate?", opts.User)
- response, err := utils.ConfirmFromUser(msg, "")
+ response, err := opts.Prompt.ConfirmFromUser(msg, "")
if err != nil {
return fmt.Errorf("Error in fetching response. Please try again.")
}
@@ -121,13 +123,13 @@ func (opts *LoginOptions) handleInteractiveLogin() error {
hostPromptHelpText := "The hostname of the DeepSource instance to authenticate with"
// Display prompt to user
- loginType, err := utils.SelectFromOptions(loginPromptMessage, loginPromptHelpText, accountTypes)
+ loginType, err := opts.Prompt.SelectFromOptions(loginPromptMessage, loginPromptHelpText, accountTypes)
if err != nil {
return err
}
// Prompt the user for hostname only in the case of on-premise
if loginType == "DeepSource Enterprise" {
- opts.HostName, err = utils.GetSingleLineInput(hostPromptMessage, hostPromptHelpText, "")
+ opts.HostName, err = opts.Prompt.GetSingleLineInput(hostPromptMessage, hostPromptHelpText, "")
if err != nil {
return err
}
diff --git a/command/auth/logout/logout.go b/command/auth/logout/logout.go
index 1fc12c668..3ba199521 100644
--- a/command/auth/logout/logout.go
+++ b/command/auth/logout/logout.go
@@ -10,7 +10,9 @@ import (
"github.com/spf13/cobra"
)
-type LogoutOptions struct{}
+type LogoutOptions struct {
+ Prompt utils.UserInputPrompt
+}
// NewCmdLogout handles the logout functionality for the CLI
func NewCmdLogout() *cobra.Command {
@@ -18,15 +20,17 @@ func NewCmdLogout() *cobra.Command {
Use: "logout",
Short: "Logout of your active DeepSource account",
Args: utils.NoArgs,
- RunE: func(cmd *cobra.Command, args []string) error {
- opts := LogoutOptions{}
+ RunE: func(cmd *cobra.Command, _ []string) error {
+ opts := LogoutOptions{
+ Prompt: utils.UserInputPrompt{},
+ }
return opts.Run()
},
}
return cmd
}
-func (*LogoutOptions) Run() error {
+func (opts *LogoutOptions) Run() error {
// Fetch config
cfg, err := config.GetConfig()
if err != nil {
@@ -39,7 +43,7 @@ func (*LogoutOptions) Run() error {
// Confirm from the user if they want to logout
logoutConfirmationMsg := "Are you sure you want to log out of DeepSource account?"
- response, err := utils.ConfirmFromUser(logoutConfirmationMsg, "")
+ response, err := opts.Prompt.ConfirmFromUser(logoutConfirmationMsg, "")
if err != nil {
return err
}
diff --git a/command/config/generate/analyzers_input.go b/command/config/generate/analyzers_input.go
index 3d0ec13dd..72e082c5b 100644
--- a/command/config/generate/analyzers_input.go
+++ b/command/config/generate/analyzers_input.go
@@ -26,7 +26,7 @@ func (o *Options) collectAnalyzerInput() (err error) {
analyzerPromptMsg := "Which languages/tools does your project use?"
analyzerPromptHelpText := "Analyzers will find issues in your code. Add an analyzer by selecting a language you've written your code in."
- o.ActivatedAnalyzers, err = utils.SelectFromMultipleOptions(analyzerPromptMsg, analyzerPromptHelpText, utils.AnalyzersData.AnalyzerNames)
+ o.ActivatedAnalyzers, err = o.Prompt.SelectFromMultipleOptions(analyzerPromptMsg, analyzerPromptHelpText, utils.AnalyzersData.AnalyzerNames)
if err != nil {
return err
}
@@ -60,7 +60,7 @@ func (o *Options) inputAnalyzerMeta(requiredFieldsData map[string][]AnalyzerMeta
switch metaFields[i].Type {
case "boolean":
metaFields[i].UserInput = "true"
- res, err := utils.ConfirmFromUser(metaFields[i].Title, metaFields[i].Description)
+ res, err := o.Prompt.ConfirmFromUser(metaFields[i].Title, metaFields[i].Description)
if err != nil {
return err
}
@@ -68,12 +68,12 @@ func (o *Options) inputAnalyzerMeta(requiredFieldsData map[string][]AnalyzerMeta
metaFields[i].UserInput = "false"
}
case "enum":
- metaFields[i].UserInput, err = utils.SelectFromOptions(metaFields[i].Title, metaFields[i].Description, metaFields[i].Options)
+ metaFields[i].UserInput, err = o.Prompt.SelectFromOptions(metaFields[i].Title, metaFields[i].Description, metaFields[i].Options)
if err != nil {
return err
}
default:
- metaFields[i].UserInput, err = utils.GetSingleLineInput(metaFields[i].Title, metaFields[i].Description, "")
+ metaFields[i].UserInput, err = o.Prompt.GetSingleLineInput(metaFields[i].Title, metaFields[i].Description, "")
if err != nil {
return err
}
diff --git a/command/config/generate/generate.go b/command/config/generate/generate.go
index 4c719dbee..da17860f1 100644
--- a/command/config/generate/generate.go
+++ b/command/config/generate/generate.go
@@ -22,11 +22,14 @@ type Options struct {
ExcludePatterns []string
TestPatterns []string
GeneratedConfig string
+ Prompt utils.UserInputPrompt
}
// NewCmdConfigGenerate handles the generation of DeepSource config based on user inputs
func NewCmdConfigGenerate() *cobra.Command {
- o := Options{}
+ o := Options{
+ Prompt: utils.UserInputPrompt{},
+ }
home, _ := os.UserHomeDir()
doc := heredoc.Docf(`
diff --git a/command/config/generate/generic_input.go b/command/config/generate/generic_input.go
index bb1473193..806c199ec 100644
--- a/command/config/generate/generic_input.go
+++ b/command/config/generate/generic_input.go
@@ -6,7 +6,6 @@ import (
"path/filepath"
"github.com/AlecAivazis/survey/v2"
- "github.com/deepsourcelabs/cli/utils"
)
// ==========
@@ -17,7 +16,7 @@ func (o *Options) collectExcludePatterns() error {
helpMsg := "Glob patterns of files that should not be analyzed such as auto-generated files, migrations, compatibility files."
// Confirm from the user if they want to add an exclude pattern
- response, err := utils.ConfirmFromUser(excludePatternsMsg, helpMsg)
+ response, err := o.Prompt.ConfirmFromUser(excludePatternsMsg, helpMsg)
if err != nil {
return err
}
@@ -40,7 +39,7 @@ func (o *Options) collectTestPatterns() error {
helpMsg := "Glob patterns of the test files. This helps us reduce false positives."
// Confirm from the user (y/N) if he/she wants to add test patterns
- response, err := utils.ConfirmFromUser(testPatternsMsg, helpMsg)
+ response, err := o.Prompt.ConfirmFromUser(testPatternsMsg, helpMsg)
if err != nil {
return err
}
@@ -87,7 +86,7 @@ func (o *Options) inputFilePatterns(field, msg, helpMsg string) error {
// Iterating this until user says no
// Here field contains : "test"/"exclude" depending upon the invoking
confirmationMsg := fmt.Sprintf("Add more %s patterns?", field)
- response, err := utils.ConfirmFromUser(confirmationMsg, "")
+ response, err := o.Prompt.ConfirmFromUser(confirmationMsg, "")
if err != nil {
return err
}
diff --git a/command/config/generate/transformers_input.go b/command/config/generate/transformers_input.go
index 6e5a24681..91ac3e8a3 100644
--- a/command/config/generate/transformers_input.go
+++ b/command/config/generate/transformers_input.go
@@ -9,7 +9,7 @@ func (o *Options) collectTransformersInput() (err error) {
transformerPromptMsg := "Would you like to activate any Transformers for any languages?"
transformerPromptHelpText := "DeepSource Transformers automatically help to achieve auto-formatting of code. Add a transformer by selecting the code formatting tool of your choice."
- o.ActivatedTransformers, err = utils.SelectFromMultipleOptions(transformerPromptMsg, transformerPromptHelpText, utils.TransformersData.TransformerNames)
+ o.ActivatedTransformers, err = o.Prompt.SelectFromMultipleOptions(transformerPromptMsg, transformerPromptHelpText, utils.TransformersData.TransformerNames)
if err != nil {
return err
}
diff --git a/analyzers/config/types.go b/types/analyzer.go
similarity index 51%
rename from analyzers/config/types.go
rename to types/analyzer.go
index e7d993e08..a779a353a 100644
--- a/analyzers/config/types.go
+++ b/types/analyzer.go
@@ -1,4 +1,12 @@
-package config
+/* =============================================================
+ * Contains type definitions with respect to Analyzers, Issues
+ * and their configuration.
+ * ============================================================= */
+package types
+
+/* ====================
+ * Analyzer TOML Types
+ * ==================== */
type Analysis struct {
Command string `toml:"command" json:"command" validate:"required"`
@@ -10,15 +18,9 @@ type Analysis struct {
// }
type Build struct {
- Builder string `toml:"builder" json:"builder" validate:"omitempty"`
+ Engine string `toml:"engine" json:"engine" validate:"omitempty,engine"`
Dockerfile string `toml:"dockerfile" json:"dockerfile,omitempty" validate:"omitempty"`
- Script string `toml:"script" json:"script" validate:"omitempty"`
-}
-
-type URL struct {
- Source string `toml:"source" json:"source" validate:"omitempty,url"`
- Documentation string `toml:"documentation" json:"documentation,omitempty" validate:"omitempty,url"`
- BugTracker string `toml:"bug_tracker" json:"bug_tracker" validate:"omitempty,url"`
+ Script string `toml:"script,multiline" json:"script" validate:"omitempty"`
}
type Test struct {
@@ -26,14 +28,16 @@ type Test struct {
}
// analyzer.toml type
-type AnalyzerMetadata struct {
+type AnalyzerTOML struct {
// Analyzer specific data
- Name string `toml:"name" json:"name" validate:"required"`
- Shortcode string `toml:"shortcode" json:"shortcode" validate:"required"` // New
- Description string `toml:"description" json:"description" validate:"required"`
- Category string `toml:"category" json:"category" validate:"required"`
- Tags []string `toml:"tags" json:"tags,omitempty" validate:"omitempty"`
- URL URL `toml:"urls" json:"urls,omitempty" validate:"omitempty"`
+ Name string `toml:"name" json:"name" validate:"required"`
+ Shortcode string `toml:"shortcode" json:"shortcode" validate:"required,shortcode"`
+ Description string `toml:"description" json:"description" validate:"required"`
+ Tags []string `toml:"tags" json:"tags,omitempty" validate:"omitempty"`
+ Repository string `toml:"repository" json:"repository" validate:"omitempty,url"`
+ DocumentationURL string `toml:"documentation" json:"documentation,omitempty" validate:"omitempty,url"`
+ BugTrackerURL string `toml:"bug_tracker" json:"bug_tracker" validate:"omitempty,url"`
+
EnvironmentVariables map[string]string `toml:"environment_variables" json:"environment_variables,omitempty" validate:"omitempty"`
// Analyzer, Autofix and Transformer config
@@ -47,10 +51,14 @@ type AnalyzerMetadata struct {
Test Test `toml:"test" json:"test" validate:"omitempty"`
}
-// Analyzer issue description
+/* =========================
+ * Analyzer Issue TOML Types
+ * ========================= */
+
+// Analyzer issue type
type AnalyzerIssue struct {
Shortcode string `validate:"omitempty"`
Title string `toml:"title" json:"title" validate:"required"`
Description string `toml:"description" json:"description" validate:"required"`
- Category string `toml:"category" json:"category" validate:"required"`
+ Category string `toml:"category" json:"category" validate:"required,category"`
}
diff --git a/utils/prompt.go b/utils/prompt.go
index 7f7a985cb..de6867727 100644
--- a/utils/prompt.go
+++ b/utils/prompt.go
@@ -2,18 +2,21 @@ package utils
import (
"errors"
+ "strings"
"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/mgutz/ansi"
)
+type UserInputPrompt struct{}
+
// ==========
// Useful APIs of survey library
// ==========
// Used for (Yes/No) questions
-func ConfirmFromUser(msg, helpText string) (bool, error) {
+func (UserInputPrompt) ConfirmFromUser(msg, helpText string) (bool, error) {
response := false
confirmPrompt := &survey.Confirm{
Renderer: survey.Renderer{},
@@ -33,7 +36,7 @@ func ConfirmFromUser(msg, helpText string) (bool, error) {
// > * 1
// * 2
// * 3
-func SelectFromOptions(msg, helpText string, opts []string) (string, error) {
+func (UserInputPrompt) SelectFromOptions(msg, helpText string, opts []string) (string, error) {
var result string
prompt := &survey.Select{
Renderer: survey.Renderer{},
@@ -46,12 +49,12 @@ func SelectFromOptions(msg, helpText string, opts []string) (string, error) {
if err != nil {
return "", checkInterrupt(err)
}
- return result, nil
+ return strings.TrimSpace(result), nil
}
// Used for Single Line Text Input
// Being used for getting "Import root" of user for configuring meta of Go analyzer
-func GetSingleLineInput(msg, helpText, defaultValue string) (string, error) {
+func (UserInputPrompt) GetSingleLineInput(msg, helpText, defaultValue string) (string, error) {
response := ""
prompt := &survey.Input{
Renderer: survey.Renderer{},
@@ -64,7 +67,7 @@ func GetSingleLineInput(msg, helpText, defaultValue string) (string, error) {
if err != nil {
return "", checkInterrupt(err)
}
- return response, nil
+ return strings.TrimSpace(response), nil
}
// Used for multiple inputs from the displayed options
@@ -75,7 +78,7 @@ func GetSingleLineInput(msg, helpText, defaultValue string) (string, error) {
// [ ] Test Coverage
// [ ] Python
// [ ] Go
-func SelectFromMultipleOptions(msg, helpText string, options []string) ([]string, error) {
+func (UserInputPrompt) SelectFromMultipleOptions(msg, helpText string, options []string) ([]string, error) {
response := make([]string, 0)
// Extracting languages and tools being used in the project for Analyzers
analyzerPrompt := &survey.MultiSelect{
@@ -102,7 +105,7 @@ func checkInterrupt(err error) error {
func GetSuccessMessage(msg string) string {
greenTickMark := ansi.Color("✔", "green")
- return greenTickMark + " " + msg + "\n"
+ return greenTickMark + " " + msg
}
func GetFailureMessage(msg, errorMsg string) string {
@@ -111,3 +114,7 @@ func GetFailureMessage(msg, errorMsg string) string {
}
return ansi.Color("✗"+" "+msg, "red")
}
+
+func GetBulletMessage(msg, color string) string {
+ return ansi.Color("•"+" "+msg, color)
+}
diff --git a/utils/remote_resolver.go b/utils/remote_resolver.go
index a43933c7b..925379d45 100644
--- a/utils/remote_resolver.go
+++ b/utils/remote_resolver.go
@@ -54,7 +54,8 @@ func ResolveRemote(repoArg string) (*RemoteData, error) {
promptOpts = append(promptOpts, value[3])
}
- selectedRemote, err := SelectFromOptions("Please select the repository:", "", promptOpts)
+ prompt := UserInputPrompt{}
+ selectedRemote, err := prompt.SelectFromOptions("Please select the repository:", "", promptOpts)
if err != nil {
return nil, err
}
diff --git a/utils/spinner.go b/utils/spinner.go
index d8462f6e9..8fa474de1 100644
--- a/utils/spinner.go
+++ b/utils/spinner.go
@@ -1,6 +1,7 @@
package utils
import (
+ "fmt"
"os"
"sync"
"time"
@@ -19,7 +20,11 @@ func (s *SpinnerUtils) StartSpinnerWithLabel(label, finalMessage string) {
s.mu.Lock()
defer s.mu.Unlock()
- sp := spinner.New(spinner.CharSets[11], 120*time.Millisecond, spinner.WithWriter(os.Stdout), spinner.WithWriter(os.Stderr), spinner.WithFinalMSG(GetSuccessMessage(finalMessage))) // Build our new spinner
+ sp := spinner.New(spinner.CharSets[11],
+ 120*time.Millisecond,
+ spinner.WithWriter(os.Stdout),
+ spinner.WithWriter(os.Stderr),
+ spinner.WithFinalMSG(fmt.Sprintf("%s\n", GetSuccessMessage(finalMessage)))) // Build our new spinner
if label != "" {
sp.Suffix = " " + label + " "
}
@@ -45,9 +50,9 @@ func (s *SpinnerUtils) StopSpinnerWithError(msg string, errorMessage error) {
defer s.mu.Unlock()
if errorMessage != nil {
- s.Spinner.FinalMSG = GetFailureMessage(msg, errorMessage.Error())
+ s.Spinner.FinalMSG = GetFailureMessage(msg, errorMessage.Error()) + "\n"
} else {
- s.Spinner.FinalMSG = GetFailureMessage(msg, "")
+ s.Spinner.FinalMSG = GetFailureMessage(msg, "") + "\n"
}
if s.Spinner == nil {
From 3e88166c84d7bfe503748cb2529a43bec5e662d5 Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
<68370997+siddhant-deepsource@users.noreply.github.com>
Date: Thu, 16 Jun 2022 11:37:58 +0530
Subject: [PATCH 08/34] feat(dry-run): add support for skipcq processor and
generating syntax highlighted snippets (#148)
---
analysis/config/config.go | 6 -
analysis/config/format.go | 31 ---
analysis/processor/batch_process.go | 153 ++++++++++++
analysis/processor/process.go | 58 +++++
analysis/processor/processors/proc_skip_cq.go | 170 +++++++++++++
.../processors/proc_source_code_load.go | 225 ++++++++++++++++++
analysis/processor/processors/silencers.go | 106 +++++++++
analysis/processor/utils.go | 106 +++++++++
command/analyzer/run/process.go | 39 +++
command/analyzer/run/run.go | 48 ++--
go.mod | 3 +
go.sum | 4 +
types/result.go | 72 ++++++
13 files changed, 965 insertions(+), 56 deletions(-)
create mode 100644 analysis/processor/batch_process.go
create mode 100644 analysis/processor/process.go
create mode 100644 analysis/processor/processors/proc_skip_cq.go
create mode 100644 analysis/processor/processors/proc_source_code_load.go
create mode 100644 analysis/processor/processors/silencers.go
create mode 100644 analysis/processor/utils.go
create mode 100644 command/analyzer/run/process.go
create mode 100644 types/result.go
diff --git a/analysis/config/config.go b/analysis/config/config.go
index 560b0fa6d..5a2f3dc20 100644
--- a/analysis/config/config.go
+++ b/analysis/config/config.go
@@ -96,9 +96,3 @@ func (r *AnalysisRun) ConfigureAnalysis() (*AnalysisConfig, error) {
// Format the analysis config data into LSP format of analysis_config.json
return r.formatAnalysisConfigToLSP(), nil
}
-
-/* Formats the LSP based result to the default DeepSource format
- * Not used as of now but keeping it here for future */
-func (r *AnalysisRun) FormatLSPResultToDefault(analysisResult *AnalysisResult) *DefaultAnalysisResult {
- return r.formatLSPResultsToDefault(analysisResult)
-}
diff --git a/analysis/config/format.go b/analysis/config/format.go
index 44f094f5c..11c814f51 100644
--- a/analysis/config/format.go
+++ b/analysis/config/format.go
@@ -34,34 +34,3 @@ func (r *AnalysisRun) formatAnalysisConfigToLSP() *AnalysisConfig {
}
return &anaConfig
}
-
-/* Converts the LSP based analysis_results.json into the default format supported by DeepSource */
-func (*AnalysisRun) formatLSPResultsToDefault(analysisResult *AnalysisResult) *DefaultAnalysisResult {
- defaultAnalysisResult := DefaultAnalysisResult{
- Metrics: analysisResult.Metrics,
- IsPassed: analysisResult.IsPassed,
- Errors: analysisResult.Errors,
- ExtraData: analysisResult.ExtraData,
- }
- for _, issue := range analysisResult.Issues {
- analysisIssue := Issue{
- Code: issue.Code,
- Title: issue.Message,
- Location: Location{
- Path: issue.RelatedInformation[0].Location.URI,
- Position: Position{
- Begin: Coordinate{
- Line: issue.Range.Start.Line,
- Column: issue.Range.Start.Character,
- },
- End: Coordinate{
- Line: issue.Range.End.Line,
- Column: issue.Range.End.Character,
- },
- },
- },
- }
- defaultAnalysisResult.Issues = append(defaultAnalysisResult.Issues, analysisIssue)
- }
- return &defaultAnalysisResult
-}
diff --git a/analysis/processor/batch_process.go b/analysis/processor/batch_process.go
new file mode 100644
index 000000000..d5c6885c2
--- /dev/null
+++ b/analysis/processor/batch_process.go
@@ -0,0 +1,153 @@
+package processor
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "path"
+ "sort"
+ "strings"
+
+ "github.com/deepsourcelabs/cli/types"
+)
+
+var (
+ issueIndex int = 0
+ batchSize int = 30
+ maxIssueDensity int = 100
+)
+
+type fileContentNode struct {
+ Filename string
+ FileContent []string
+}
+
+// While this loop looks like it would have a complexity of len(filesWIssueRange) * len(cachedFiles) * issues * len(processorList)
+// it only has a complexity of O(len(report.Issues)).
+// When there are a lot of files to be processed, opening all of them one by one takes time, while the CPU waits idly.
+// Opening all files and loading them into memory is expensive in terms of space, since there could be a lot of files.
+// Hence, opening files concurrently in batches (of, say, 30 files) and then processing all issues in those 30 files one by one
+// appears to be the best option. We cannot process each file's issues concurrently, because only the file loading operation is
+// IO intensive, and the rest is CPU intensive.
+func (p *ReportProcessor) processIssuesBatch(filesWIssueRange []IssueRange, result *types.AnalysisResult, processedIssues *[]types.Issue) {
+ // Process files in batches of `batchSize` to avoid `too many files open` error
+ for processedFiles := 0; processedFiles < len(filesWIssueRange); {
+ filesToProcess := 0
+
+ // The default batch size is 30. If the number of files is less than this batchsize assign their count
+ // as the number of files to process, else assign the batchsize as the number of files to be processed in
+ // this iteration.
+ if len(filesWIssueRange)-processedFiles < batchSize {
+ filesToProcess = len(filesWIssueRange) - processedFiles
+ } else {
+ filesToProcess = batchSize
+ }
+
+ // The slice containing the data about cached files to be processed.
+ cachedFiles := p.cacheFilesToBeProcessed(filesToProcess, processedFiles, filesWIssueRange)
+
+ // Iterate over the cached files data and process the issues present in them.
+ for j, cachedFile := range cachedFiles {
+ for issueIndex < len(result.Issues) {
+ issue := result.Issues[issueIndex] // initialize the loop
+ // Check if the file is a generated one, this happens if enormous amount of issues are
+ // reported in a single file on a single line.
+ if p.isGeneratedFile(processedFiles+j, &cachedFile, filesWIssueRange, result) {
+ continue
+ }
+
+ // Check if the issue is for another file.
+ // If yes, skip this iteration and go to next file.
+ if cachedFile.Filename != issue.Location.Path {
+ break
+ }
+
+ if err := p.runProcessors(cachedFile, &issue, processedIssues); err != nil {
+ fmt.Println(err.Error())
+ }
+ issueIndex++
+ }
+ }
+
+ // Increase total number of files processed
+ processedFiles += filesToProcess
+ }
+}
+
+// runProcessors runs the supported processors on the issue passed as a parameter
+func (p *ReportProcessor) runProcessors(cachedFile fileContentNode, issueToProcess *types.Issue, processedIssues *[]types.Issue) (err error) {
+ // Loop through processors and execute them on the issue passed as a parameter
+ for _, processor := range p.Processors {
+ err = processor.Process(cachedFile.FileContent, issueToProcess, processedIssues)
+ if err != nil {
+ return fmt.Errorf("failed to execute the processor %s with the following error: %s", processor, err)
+ }
+ }
+ return
+}
+
+// If the number of issues in this file is more than a certain number of issues
+// averaged per line, this may be a generated file. Skip processing of further issues
+// in this file
+func (p *ReportProcessor) isGeneratedFile(fileIndex int, cachedFile *fileContentNode, filesWIssueRange []IssueRange, result *types.AnalysisResult) bool {
+ linesInThisFile := len(cachedFile.FileContent) | 1 // bitwise op to ensure no divisionbyzero errs
+ issuesInThisFile := filesWIssueRange[fileIndex].EndIndex - filesWIssueRange[fileIndex].BeginIndex
+ if (issuesInThisFile / linesInThisFile) > maxIssueDensity {
+ log.Printf(
+ "Skipping file %s. Too many issues per line. Lines: %d, issues: %d\n",
+ cachedFile.Filename,
+ linesInThisFile,
+ issuesInThisFile,
+ )
+ result.Errors = append(result.Errors, types.Error{
+ HMessage: fmt.Sprintf(
+ "Skipped file %s because too many issues were raised. "+
+ "Is this a generated file that can be added in [exclude_patterns](https://deepsource.io/docs/config/deepsource-toml.html#exclude-patterns)?",
+ cachedFile.Filename,
+ ),
+ Level: 1,
+ })
+ return true
+ }
+ return false
+}
+
+// cacheBatchOfFiles receives the count of files to be cached and caches them in a batch by spawning goroutines.
+func (p *ReportProcessor) cacheFilesToBeProcessed(totalFiles, processedFiles int, filesWIssueRange []IssueRange) []fileContentNode {
+ fileContentChannel := make(chan fileContentNode, totalFiles)
+ for j := 0; j < totalFiles; j++ {
+ filename := filesWIssueRange[processedFiles+j].Filename
+ go addFileToCache(fileContentChannel, filename, p.CodePath)
+ }
+
+ cachedFiles := []fileContentNode{}
+ for j := 0; j < totalFiles; j++ {
+ cachedFiles = append(cachedFiles, <-fileContentChannel)
+ }
+
+ // sort the cached files by filename, because our issues are sorted by filename
+ sort.Slice(cachedFiles, func(i, j int) bool {
+ return cachedFiles[i].Filename < cachedFiles[j].Filename
+ })
+ return cachedFiles
+}
+
+// addFileToCache reads the file and formats its content into a fileContentNode struct instance
+// and passes that to the cachedFilesChannel channel since this function is run on a goroutine.
+func addFileToCache(cachedFilesChannel chan fileContentNode, filename, codePath string) {
+ fileContentSlice := []string{}
+
+ fileContentBytes, err := ioutil.ReadFile(path.Join(codePath, filename))
+ if err != nil {
+ fmt.Println("Could not process for file: ", filename, ". Err: ", err)
+ } else if string(fileContentBytes) != "" {
+ fileContentSlice = strings.Split(string(fileContentBytes), "\n")
+ } else {
+ fileContentSlice = []string{}
+ }
+
+ cachedFilesChannel <- fileContentNode{
+ Filename: filename,
+ FileContent: fileContentSlice,
+ }
+}
diff --git a/analysis/processor/process.go b/analysis/processor/process.go
new file mode 100644
index 000000000..c2d7ea01a
--- /dev/null
+++ b/analysis/processor/process.go
@@ -0,0 +1,58 @@
+package processor
+
+import (
+ "fmt"
+
+ "github.com/deepsourcelabs/cli/types"
+)
+
+// Processor interface to receive analysis post-processors.
+type IProcessor interface {
+ String() string
+ Process([]string, *types.Issue, *[]types.Issue) error
+}
+
+// ReportProcessor struct contains the processor data needed to process the analysis results.
+type ReportProcessor struct {
+ CodePath string // The source code path where the issues got raised.
+ Processors []IProcessor // The list of supported post-analysis processors.
+ Report types.AnalyzerReport // The report generated by the Analyzer post analysis.
+}
+
+// ProcessAnalyzerReport accepts the result as a byte array and processes the results in the form of a
+// AnalyzerReport struct instance.
+// It sorts the issues in an alphabetical order of filenames just to ensure that all issues getting
+// reported for the same files come together & processes the issues for the various required processors.
+// As of now, there are two processors supported:
+// - skipcq : Processes the issues and checks if some of them should be ignored since they have
+// been ignored by the user through suitable `skipcq` comments.
+// - source_code_load : Processes the issues for the source code snippets, highlights the snippets
+// and adds them to the Analysis result.
+func (p *ReportProcessor) Process() types.AnalysisResult {
+ // Covert the Analyzer report from LSP based format to the default results format.
+ analysisResult := p.formatLSPResultsToDefault()
+
+ // Check if there are issues reported actually.
+ if len(analysisResult.Issues) <= 0 {
+ return analysisResult
+ }
+ fmt.Println("Total issues reported by the Analyzer: ", len(analysisResult.Issues))
+
+ // All the files that appear in the issues are now processed by the processors listed in analyzer conf
+ // We must cache the files in order to not do file IO for every processor.
+ p.sortIssuesByFile(&analysisResult)
+
+ // Get the issues to file range data.
+ filesIndex := createIssueFileRange(analysisResult)
+
+ // Iterate over the filesIndex and read the files in batch and process the issues using the suitable processors.
+ processedIssues := []types.Issue{}
+ p.processIssuesBatch(filesIndex, &analysisResult, &processedIssues)
+ analysisResult.Issues = processedIssues
+
+ // Sort again for consistency (mostly for test to pass).
+ p.sortIssuesByFile(&analysisResult)
+
+ // Return the processed analysis result.
+ return analysisResult
+}
diff --git a/analysis/processor/processors/proc_skip_cq.go b/analysis/processor/processors/proc_skip_cq.go
new file mode 100644
index 000000000..529b2ba92
--- /dev/null
+++ b/analysis/processor/processors/proc_skip_cq.go
@@ -0,0 +1,170 @@
+package processors
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+
+ "github.com/deepsourcelabs/cli/types"
+)
+
+type ProcSkipCQ struct{}
+
+func isSimilarIssue(fileExt, skipCQTag, probableIssueCode, issueCode string) bool {
+ // if it is // skipcq: SCC-S1002 or similar plain skipcq tag, return
+ if skipCQTag == "skipcq" {
+ if probableIssueCode != "" {
+ return strings.EqualFold(strings.TrimSpace(probableIssueCode), issueCode)
+ } else {
+ return true
+ }
+ }
+
+ // if the tag to skip CQ is something else, check here
+ for _, silencer := range languagesMeta[fileExt].Silencers {
+ if strings.EqualFold(strings.TrimSpace(skipCQTag), silencer.SilencerCode) {
+ if len(silencer.Issues) == 0 {
+ // if the silencer doesn't have any issues in it, ignore all the issues
+ return true
+ }
+
+ // similarIssues is a comma separated list of issues corresponding to the raised issue
+ similarIssues, ok := silencer.Issues[strings.Split(issueCode, "-")[1]]
+
+ // if the issue is not found in the silencer's issue map, do not ignore the issue
+ if !ok {
+ return false
+ }
+
+ if probableIssueCode == "" {
+ // if there is no specific issue silenced, ignore all issues
+ return true
+ } else {
+ for _, similarIssue := range strings.Split(similarIssues, ",") {
+ // if the silencer has an issue map that contains this particular issue, ignore it
+ if similarIssue == strings.ToUpper(probableIssueCode) {
+ return true
+ } else {
+ return false
+ }
+ }
+ }
+ }
+ }
+ return false
+}
+
+func checkSkipCQ(fileExt string, skipCQre regexp.Regexp, line, issueCode string) bool {
+ matches := skipCQre.FindAllStringSubmatch(line, -1)
+ skipCQTag := ""
+
+ if matches == nil {
+ return false
+ }
+
+ ignoreIssue := true
+
+ for i, name := range skipCQre.SubexpNames() {
+ for _, match := range matches {
+ if i != 0 && name != "" {
+ // note the name of the issue silencer and move on
+ if name == "skipcq_tag" {
+ skipCQTag = match[i]
+ } else if name == "issue_codes" {
+ if match[i] != "" {
+ for _, probableIssueCode := range strings.Split(match[i], ",") {
+ // if an issue is to be ignored in this line of code is same as
+ // the issue that is raised, we have to ignore the issue
+
+ if isSimilarIssue(fileExt, skipCQTag, probableIssueCode, issueCode) {
+ ignoreIssue = true
+ // since we are only dealing with one issue at a time
+ // break at the first occurrence
+ return ignoreIssue
+ } else {
+ ignoreIssue = false
+ }
+ }
+ } else {
+ // in case there is no issue code associated, check for just the silencer tag
+ ignoreIssue = isSimilarIssue(fileExt, skipCQTag, "", issueCode)
+ }
+ }
+ }
+ }
+ }
+ return ignoreIssue
+}
+
+/* Check if a given line of code is eligible to be checked for skip CQ.
+ * Bare minimum eligibility is that the line should either be empty or
+ * contain a comment only line. */
+func analyzeLineForSkipCQ(line, fileExt string) bool {
+ var commentIdentifier string
+ for _, langMeta := range languagesMeta {
+ if fileExt == langMeta.Extension {
+ commentIdentifier = langMeta.CommentIdentifier
+ break
+ }
+ }
+
+ line = strings.TrimSpace(line)
+
+ if line == "" {
+ return true
+ }
+
+ match, err := regexp.Match(fmt.Sprintf("^%s", commentIdentifier), []byte(line))
+ return err == nil && match
+}
+
+// Returns the name of the processor
+func (p ProcSkipCQ) String() string {
+ return "skip_cq"
+}
+
+// Process checks if the issue passed as an argument should be skipped or not
+// If it should be skipped, it is not appended to the processedIssues slice while if it is not skipped, it is appended.
+func (p ProcSkipCQ) Process(fileContentSlice []string, issue *types.Issue, processedIssues *[]types.Issue) error {
+ filePath := issue.Location.Path
+ lineStart := issue.Location.Position.Begin.Line
+ issueCode := issue.IssueCode
+
+ if lineStart < 1 || lineStart > len(fileContentSlice) {
+ return fmt.Errorf("issue position is weird for file of %d lines", len(fileContentSlice))
+ }
+
+ shouldSkipCQ := false
+ line := strings.TrimSpace(fileContentSlice[lineStart-1])
+
+ fileSupported := false
+ var fileExt string
+ var skipCQregex regexp.Regexp
+ for re := range languagesMeta {
+ match, err := regexp.Match(re, []byte(filePath))
+ if err != nil || !match {
+ continue
+ }
+ fileSupported = true
+ fileExt = re
+ break
+ }
+ if !fileSupported {
+ fileExt = "default_extension"
+ }
+ skipCQregex = regexMap[fileExt]
+
+ // Skip code quality checks for the given issue code on the lineStart
+ shouldSkipCQ = checkSkipCQ(fileExt, skipCQregex, line, issueCode)
+
+ // Continue looking only if the previous line is a comment-only line specifying the skipcq condition,
+ // the lineStart is not the first line of the file and shouldSkipCQ is not already true
+ for index := lineStart - 2; !shouldSkipCQ && index >= 0 && analyzeLineForSkipCQ(fileContentSlice[index], fileExt); index-- {
+ shouldSkipCQ = checkSkipCQ(fileExt, skipCQregex, fileContentSlice[index], issueCode)
+ }
+
+ if !shouldSkipCQ {
+ *processedIssues = append(*processedIssues, *issue)
+ }
+ return nil
+}
diff --git a/analysis/processor/processors/proc_source_code_load.go b/analysis/processor/processors/proc_source_code_load.go
new file mode 100644
index 000000000..b6efdb4fc
--- /dev/null
+++ b/analysis/processor/processors/proc_source_code_load.go
@@ -0,0 +1,225 @@
+package processors
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "strings"
+
+ "github.com/alecthomas/chroma/formatters/html"
+ "github.com/alecthomas/chroma/lexers"
+ "github.com/alecthomas/chroma/styles"
+ "github.com/deepsourcelabs/cli/types"
+)
+
+const sourceCodeOffset int = 3
+
+type ProcSourceCodeLoad struct{}
+
+type formattedFile struct {
+ fileContent []string
+ highlightedContent []string
+}
+
+var (
+ lineStartWithOffset, lineEndWithOffset int
+ formattedFileCache map[string]formattedFile = make(map[string]formattedFile)
+)
+
+// We cache the past file's iterator, taking advantage of the fact that
+// issues are sorted according to filenames
+func getFinalFormattedSlice(fileContentSlice []string, issue *types.Issue) formattedFile {
+ filePath := issue.Location.Path
+
+ // Check if the formatted file data is already present in the cache.
+ // If yes, return the cached data.
+ if formattedFileData, ok := formattedFileCache[filePath]; ok {
+ return formattedFileData
+ }
+
+ // Else, clear the cache.
+ for k := range formattedFileCache {
+ delete(formattedFileCache, k)
+ }
+
+ /* ============================================================
+ * Use alecthomas/chroma to generate syntax highlighted snippet
+ * ============================================================ */
+ fileContentString := strings.Join(fileContentSlice, "\n")
+ lexer := lexers.Match(filePath)
+
+ /* Case: In case of .vue files, use the `html` lexer since the `vue` lexer
+ * breaks in certain cases. The `html` lexer provides comparatively better results.
+ * TODO(SNT): Remove this case if vue lexer is improved in future. */
+ if strings.HasSuffix(filePath, ".vue") {
+ lexer = lexers.Get("html")
+ }
+ if lexer == nil {
+ lexer = lexers.Fallback
+ }
+
+ // Tokenize the file content.
+ iterator, err := lexer.Tokenise(nil, fileContentString)
+ if err != nil {
+ log.Println("Could not tokenize file ", filePath)
+ return formattedFile{
+ fileContent: []string{},
+ highlightedContent: []string{},
+ }
+ }
+
+ // Selecting the chroma format in which we expect the output(html) and use the `monokai` colorscheme to highlight the snippet.
+ formatter := html.New(html.WithLineNumbers(true), html.PreventSurroundingPre(true), html.WithClasses(true))
+ style := styles.Get("monokai")
+ if style == nil {
+ style = styles.Fallback
+ }
+
+ var chromaFormattedBytes bytes.Buffer
+ var chromaFormattedString string
+ err = formatter.Format(&chromaFormattedBytes, style, iterator)
+ if err != nil {
+ fmt.Println(err)
+ return formattedFile{
+ fileContent: []string{},
+ highlightedContent: []string{},
+ }
+ }
+
+ // Convert the generated data in bytes to string and also extract the slice containing
+ // all the lines as the contents.
+ chromaFormattedString = chromaFormattedBytes.String()
+ chromaFormattedSlice := strings.Split(chromaFormattedString, "\n")
+
+ // We need to move the trailing span to the previous line in order.
+ for i := range chromaFormattedSlice {
+ if i != 0 && !strings.HasPrefix(chromaFormattedSlice[i], "") {
+ lineStartIndex := strings.Index(chromaFormattedSlice[i], "")
+
+ if lineStartIndex != -1 {
+ chromaFormattedSlice[i-1] += chromaFormattedSlice[i][:lineStartIndex]
+ chromaFormattedSlice[i] = chromaFormattedSlice[i][lineStartIndex:]
+ }
+ }
+ }
+
+ // Highlight all lines in the file.
+ lexer = lexers.Match(filePath)
+ if lexer == nil {
+ lexer = lexers.Fallback
+ }
+ iterator, err = lexer.Tokenise(nil, fileContentString)
+ if err != nil {
+ fmt.Println("Could not tokenize file ", filePath)
+ return formattedFile{
+ fileContent: []string{},
+ highlightedContent: []string{},
+ }
+ }
+
+ // Specifying the highlight range.
+ lineHighlightRange := [][2]int{{1, len(fileContentSlice)}}
+
+ // Format, style and color the snippet.
+ formatter = html.New(html.WithLineNumbers(true), html.PreventSurroundingPre(true), html.WithClasses(true), html.HighlightLines(lineHighlightRange))
+ style = styles.Get("monokai")
+ if style == nil {
+ style = styles.Fallback
+ }
+ var chromaHighlightedBytes bytes.Buffer
+ err = formatter.Format(&chromaHighlightedBytes, style, iterator)
+ if err != nil {
+ fmt.Println(err)
+ return formattedFile{
+ fileContent: []string{},
+ highlightedContent: []string{},
+ }
+ }
+ chromaHighlightedString := chromaHighlightedBytes.String()
+ chromaHighlightedSlice := strings.Split(chromaHighlightedString, "\n")
+
+ /* Correct the span elements in the slice.
+ * Highlighted lines look like this:
+ *
+ * 1importos
+ * 2importrandom# noqa: F401
+ * 3importthis# noqa
+ * 4importsys */
+
+ // We need to move the trailing span to the previous line in order for our replacement logic to work.
+ for i := range chromaHighlightedSlice {
+ if i != 0 && !strings.HasPrefix(chromaHighlightedSlice[i], "") {
+ lineStartIndex := strings.Index(chromaHighlightedSlice[i], "")
+
+ if lineStartIndex != -1 {
+ chromaHighlightedSlice[i-1] += chromaHighlightedSlice[i][:lineStartIndex]
+ chromaHighlightedSlice[i] = chromaHighlightedSlice[i][lineStartIndex:]
+ }
+ }
+ }
+
+ // Create formattedContent variable of `formattedFile` type and return.
+ formattedContent := formattedFile{
+ fileContent: chromaFormattedSlice,
+ highlightedContent: chromaHighlightedSlice,
+ }
+ formattedFileCache[filePath] = formattedContent
+
+ return formattedContent
+}
+
+// Returns the name of the processor
+func (p ProcSourceCodeLoad) String() string {
+ return "source_code_load"
+}
+
+// Process processes the source code to be highlighted using chroma and writes that into the
+// analysis result post highlighting.
+func (p ProcSourceCodeLoad) Process(fileContentSlice []string, issue *types.Issue, _ *[]types.Issue) error {
+ lineStart := issue.Location.Position.Begin.Line
+ lineEnd := issue.Location.Position.End.Line
+
+ // Count lines in the file
+ numLines := len(fileContentSlice)
+
+ // Calculate the line number from where the highlighting should start
+ if lineStart-sourceCodeOffset < 1 {
+ lineStartWithOffset = 1
+ } else {
+ lineStartWithOffset = lineStart - sourceCodeOffset
+ }
+
+ // Calculate the line number from where the highlighting should end
+ if lineEnd+sourceCodeOffset > numLines {
+ lineEndWithOffset = numLines
+ } else {
+ lineEndWithOffset = lineEnd + sourceCodeOffset
+ }
+
+ formattedFileContent := getFinalFormattedSlice(fileContentSlice, issue)
+ chromaFormattedSlice := formattedFileContent.fileContent
+ chromaHighlightedSlice := formattedFileContent.highlightedContent
+
+ finalFormattedSlice := make([]string, 0)
+ finalFormattedSlice = append(finalFormattedSlice, `
`)
+
+ // Get the file slice to write
+ for i := lineStartWithOffset; i <= lineEndWithOffset; i++ {
+ currentLine := chromaFormattedSlice[i-1]
+
+ // for all lines except the last, append a newline
+ if i < lineEndWithOffset {
+ currentLine = currentLine + "\n"
+ }
+
+ // highlight the lines containing the issue
+ // We need not add a \n at the end of highlighted lines, as chroma does it itself
+ if i >= lineStart && i <= lineEnd {
+ currentLine = chromaHighlightedSlice[i-1]
+ }
+ finalFormattedSlice = append(finalFormattedSlice, currentLine)
+ }
+ finalFormattedSlice = append(finalFormattedSlice, "
")
+ issue.ProcessedData.SourceCode.Rendered = strings.Join(finalFormattedSlice, "")
+ return nil
+}
diff --git a/analysis/processor/processors/silencers.go b/analysis/processor/processors/silencers.go
new file mode 100644
index 000000000..7cfc0e5c5
--- /dev/null
+++ b/analysis/processor/processors/silencers.go
@@ -0,0 +1,106 @@
+package processors
+
+import (
+ "regexp"
+ "strings"
+)
+
+var languagesMeta map[string]LanguageMeta
+
+// for the extension e.g .py, .go, .js etc build a map of compiled
+// regex with the corresponding comment identifier in regex.
+var regexMap map[string]regexp.Regexp
+
+// Silencers data structure
+type IssueSilencer struct {
+ PortName string `json:"port_name"`
+ SilencerCode string `json:"silencer_code"`
+ Issues map[string]string `json:"issues"`
+ TagSeparator string `json:"tag_separator"`
+}
+
+type LanguageMeta struct {
+ Extension string `json:"extension"`
+ CommentIdentifier string `json:"comment_identifier"`
+ Silencers []IssueSilencer `json:"issue_silencers"`
+}
+
+// Reads the `silencers.json` file present in `/toolbox` directory
+// and makes a LanguageMeta map which helps in processing skipcq
+func prepareSilencersMeta() []LanguageMeta {
+ // Sane default meta to use when failed to read the silencers file.
+ // Also, appended to the every config
+ issuesMeta := []LanguageMeta{
+ {
+ Extension: "default_extension",
+ CommentIdentifier: `(\#|\/\/)`,
+ Silencers: []IssueSilencer{},
+ },
+ }
+ return issuesMeta
+}
+
+// generateRegExp generates the regex expression used for matching the skipcq comment
+func generateRegExp(fileExt string) regexp.Regexp {
+ // Analyzer specific issues silencer tags, with `skipcq` tag
+ skipCQTags := []string{"skipcq"}
+
+ // Different analyzers may have different ending token for issue silencing. eg. Pylint has `=` while
+ // most others have `:`
+ separators := map[string]int{
+ ":": 1, // default, for skipcq
+ }
+ for _, silencer := range languagesMeta[fileExt].Silencers {
+ skipCQTags = append(skipCQTags, silencer.SilencerCode)
+ separators[silencer.TagSeparator] = 1
+ }
+
+ separatorsList := []string{}
+ for k := range separators {
+ separatorsList = append(separatorsList, k)
+ }
+
+ commentIdentifier := languagesMeta[fileExt].CommentIdentifier
+ regex := *regexp.MustCompile(
+ // case-insensitive
+ `(?i)` +
+
+ // group the silencer tags with a name, matching one of the many issue silencers (eg, noqa, nosec)
+ commentIdentifier + `.*?(?P(` + strings.Join(skipCQTags, "|") + `))` +
+
+ // zero or more occurrences of the issue codes, ends at `)?` later
+ `(` +
+
+ // separators, like `:` and `=`
+ `?:(` + strings.Join(separatorsList, "|") + `)[\s]?` +
+
+ // create a group named issue_codes, with pattern similar to PYL-W0614 or SA1022
+ `(?P([A-Z]*-?[A-Z]*[0-9]+(?:,(\s+)?)?)+)` +
+
+ // zero or one occurrences of `: issuecode1, issuecode2` and so on
+ `)?`,
+ )
+ return regex
+}
+
+// generateSilencersRegexMap generates the silencers regex expression used for skipcq processing
+func GenerateSilencersRegexMap() {
+ langMeta := make(map[string]LanguageMeta)
+ silencerRegexMap := make(map[string]regexp.Regexp)
+
+ // Fetch the silencers meta for the Analyzer
+ // Keeping it as the default silencer for now
+ silencersData := prepareSilencersMeta()
+
+ // Mapping the silencers data to the file extension
+ // in the above declared map `langMeta`
+ for _, silencerData := range silencersData {
+ langMeta[silencerData.Extension] = silencerData
+ }
+ languagesMeta = langMeta
+
+ for ext := range langMeta {
+ silencerRegexMap[ext] = generateRegExp(ext)
+ }
+ regexMap = silencerRegexMap
+}
diff --git a/analysis/processor/utils.go b/analysis/processor/utils.go
new file mode 100644
index 000000000..53c2dbbd8
--- /dev/null
+++ b/analysis/processor/utils.go
@@ -0,0 +1,106 @@
+package processor
+
+import (
+ "sort"
+
+ "github.com/deepsourcelabs/cli/types"
+)
+
+// sortIssuesByFile sorts the issues in an alphabetical order according to the filenames
+// where they got reported.
+func (p *ReportProcessor) sortIssuesByFile(result *types.AnalysisResult) {
+ sort.Slice(result.Issues, func(i, j int) bool {
+ return result.Issues[i].Location.Path < result.Issues[j].Location.Path
+ })
+}
+
+// Prepare a map with unique filenames as key and the issue range for each file as value
+// This is done to ensure fewer loops when processing issues.
+type IssueRange struct {
+ Filename string // The file which has the issues
+ BeginIndex int // Array index in report.Issues where the particular issue starts
+ EndIndex int // Array index in report.Issues where the particular issue ends
+}
+
+// GenerateIssueRangeSlice generates an array containing the issue ranges with respect to files
+// that helps us to go through them and map them to the files where they got reported instead
+// of opening the file for each of them. The generated index looks like this:
+
+// [{analyzer.go 0 0} {autofix_patch.go 1 1} {difftool.go 2 2} {patch.patch 3 5} {proc_skip_cq_test.go 6 6}]
+
+// Here, the first field if filename and the second and third fields are the index range in which the issues reported
+// in these files lie in the sorted AnalyzerReport slice.
+func createIssueFileRange(report types.AnalysisResult) []IssueRange {
+ fileCount := 0 // for 1 file, 0 based indexing
+ issuesRange := []IssueRange{}
+ prevFilename := report.Issues[0].Location.Path
+
+ issueRange := IssueRange{
+ BeginIndex: 0,
+ EndIndex: len(report.Issues) - 1,
+ Filename: prevFilename,
+ }
+ issuesRange = append(issuesRange, issueRange)
+
+ // Iterating over the issues and creating an array containing issues with index data about
+ // the files in which those issues are present
+ for i := 1; i < len(report.Issues); i++ {
+ issue := report.Issues[i]
+ currentFilename := issue.Location.Path
+
+ // TODO: Check when this condition is implied
+ if issue.Location.Position.End.Line == -1 {
+ issue.Location.Position.End.Line = issue.Location.Position.Begin.Line
+ }
+
+ if currentFilename != prevFilename {
+ fileCount++
+
+ issueRange = issuesRange[fileCount-1]
+ issueRange.EndIndex = i - 1
+ issuesRange[fileCount-1] = issueRange
+
+ // Create for the new file
+ issueRange = IssueRange{
+ Filename: currentFilename,
+ BeginIndex: i,
+ EndIndex: len(report.Issues) - 1,
+ }
+
+ issuesRange = append(issuesRange, issueRange)
+ prevFilename = currentFilename
+ }
+ }
+ return issuesRange
+}
+
+// formatLSPResultsToDefault converts the LSP based analysis results into the default format supported by DeepSource.
+func (p *ReportProcessor) formatLSPResultsToDefault() types.AnalysisResult {
+ analysisResult := types.AnalysisResult{}
+ analysisResult.IsPassed = p.Report.IsPassed
+ analysisResult.Metrics = append(p.Report.Metrics, analysisResult.Metrics...)
+ analysisResult.Errors = append(p.Report.Errors, analysisResult.Errors...)
+
+ // Appending the issues to the default format of Analysis report
+ for _, issue := range p.Report.Issues {
+ analysisIssue := types.Issue{
+ IssueCode: issue.Code,
+ IssueText: issue.Message,
+ Location: types.Location{
+ Path: issue.RelatedInformation[0].Location.URI,
+ Position: types.Position{
+ Begin: types.Coordinate{
+ Line: issue.Range.Start.Line,
+ Column: issue.Range.Start.Character,
+ },
+ End: types.Coordinate{
+ Line: issue.Range.End.Line,
+ Column: issue.Range.End.Character,
+ },
+ },
+ },
+ }
+ analysisResult.Issues = append(analysisResult.Issues, analysisIssue)
+ }
+ return analysisResult
+}
diff --git a/command/analyzer/run/process.go b/command/analyzer/run/process.go
new file mode 100644
index 000000000..f624071ef
--- /dev/null
+++ b/command/analyzer/run/process.go
@@ -0,0 +1,39 @@
+package run
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/deepsourcelabs/cli/analysis/processor"
+ "github.com/deepsourcelabs/cli/analysis/processor/processors"
+ "github.com/deepsourcelabs/cli/types"
+)
+
+// processAnalyzerReport processes the analysis report generated by the Analyzer
+func (a *AnalyzerDryRun) processAnalyzerReport(reportBytes []byte) (types.AnalysisResult, error) {
+ report := types.AnalyzerReport{}
+ skipCQProcessor := processors.ProcSkipCQ{}
+ sourceCodeHighlightingProcessor := processors.ProcSourceCodeLoad{}
+
+ // Initializing the processors using the IProcessor interface provided by the `processor` package
+ var skip_cq, source_code_load processor.IProcessor
+ skip_cq = skipCQProcessor
+ source_code_load = sourceCodeHighlightingProcessor
+
+ processor := processor.ReportProcessor{
+ CodePath: a.SourcePath,
+ Processors: []processor.IProcessor{skip_cq, source_code_load},
+ }
+
+ // Generate the silencers regexMap.
+ processors.GenerateSilencersRegexMap()
+
+ if err := json.Unmarshal(reportBytes, &report); err != nil {
+ fmt.Println(err)
+ return types.AnalysisResult{}, err
+ }
+
+ processor.Report = report
+ analysisResult := processor.Process()
+ return analysisResult, nil
+}
diff --git a/command/analyzer/run/run.go b/command/analyzer/run/run.go
index 9eb04c5f2..61c59b041 100644
--- a/command/analyzer/run/run.go
+++ b/command/analyzer/run/run.go
@@ -4,10 +4,11 @@ import (
"fmt"
"os"
+ "github.com/deepsourcelabs/cli/types"
"github.com/deepsourcelabs/cli/utils"
"github.com/spf13/cobra"
- analysis_config "github.com/deepsourcelabs/cli/analysis/config"
+ "github.com/deepsourcelabs/cli/analysis/config"
"github.com/deepsourcelabs/cli/analyzers/backend/docker"
)
@@ -20,18 +21,19 @@ var (
analysisResultsName string = "analysis_results"
analysisConfigExt string = ".json"
analysisResultsExt string = ".json"
+ // supportedProcessors []string = []string{"skip_cq", "source_code_load"}
)
// The params required while running the Analysis locally
type AnalyzerDryRun struct {
- Client *docker.DockerClient // The client to be used for all docker related ops
- RemoteSource bool // True if the source to be analyzed is a remote VCS repository
- SourcePath string // The path of the directory of source code to be analyzed
- AnalysisFiles []string // The list of analysis files
- TempCloneDirectory string // The temporary directory where the source of the remote VCS will be cloned to
- TempToolBoxDirectory string // The temporary directory where the analysis_config is present
-
- AnalysisConfig *analysis_config.AnalysisConfig // The analysis_config.json file containing the meta for analysis
+ Client *docker.DockerClient // The client to be used for all docker related ops.
+ RemoteSource bool // True if the source to be analyzed is a remote VCS repository.
+ SourcePath string // The path of the directory of source code to be analyzed.
+ TempCloneDirectory string // The temporary directory where the source of the remote VCS will be cloned to.
+ TempToolBoxDirectory string // The temporary directory where the analysis_config is present.
+ AnalysisFiles []string // The list of analysis files.
+ AnalysisConfig *config.AnalysisConfig // The analysis_config.json file containing the meta for analysis.
+ AnalysisResult types.AnalysisResult
}
func NewCmdAnalyzerRun() *cobra.Command {
@@ -42,6 +44,7 @@ func NewCmdAnalyzerRun() *cobra.Command {
opts := AnalyzerDryRun{
SourcePath: cwd,
RemoteSource: false,
+ // Processors: supportedProcessors,
}
cmd := &cobra.Command{
@@ -66,7 +69,6 @@ func NewCmdAnalyzerRun() *cobra.Command {
// Run the Analyzer locally on a certain directory or repository
func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
- // runtime.Breakpoint()
err = a.createDockerClient()
if err != nil {
return err
@@ -91,20 +93,19 @@ func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
return err
}
- /* Create temporary toolbox directory to store analysis config and later analyis results
- * If already passed through --output-file flag, use that one */
+ // Create temporary toolbox directory to store analysis config and later analyis results
+ // If already passed through --output-file flag, use that one
if err = a.createTemporaryToolBoxDir(); err != nil {
return err
}
// Resolve the path of source code to be analyzed based on the user input
- a.Client.AnalysisOpts.HostCodePath, err = a.resolveAnalysisCodePath()
- if err != nil {
+ if a.Client.AnalysisOpts.HostCodePath, err = a.resolveAnalysisCodePath(); err != nil {
return err
}
- /* Generate the analysis_config.json file
- * Also, write the analysis_config data into a temp /toolbox directory to be mounted into the container */
+ // Generate the analysis_config.json file
+ // Also, write the analysis_config data into a temp /toolbox directory to be mounted into the container
if err = a.prepareAnalysisConfig(); err != nil {
return err
}
@@ -114,8 +115,8 @@ func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
return err
}
- /* Starts the Docker container which analyzes the code and stores the analysis results
- * in a variable */
+ // Starts the Docker container which analyzes the code and stores the analysis results
+ // in a variable
if err = a.Client.StartDockerContainer(); err != nil {
return err
}
@@ -127,5 +128,14 @@ func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
}
// Write the analysis results to the file
- return a.writeAnalysisResults(analysisResultBuf, analysisResultFileName)
+ if err = a.writeAnalysisResults(analysisResultBuf, analysisResultFileName); err != nil {
+ return err
+ }
+
+ // Process the analyzer report once it is received.
+ if a.AnalysisResult, err = a.processAnalyzerReport(analysisResultBuf); err != nil {
+ return err
+ }
+ fmt.Println("Issues after processing:", len(a.AnalysisResult.Issues))
+ return nil
}
diff --git a/go.mod b/go.mod
index 59da01294..9842ca1e8 100644
--- a/go.mod
+++ b/go.mod
@@ -69,6 +69,8 @@ require (
gopkg.in/ini.v1 v1.66.4 // indirect
)
+require github.com/alecthomas/chroma v0.10.0
+
require (
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/Microsoft/hcsshim v0.9.2 // indirect
@@ -76,6 +78,7 @@ require (
github.com/containerd/cgroups v1.0.3 // indirect
github.com/containerd/containerd v1.6.3 // indirect
github.com/containerd/continuity v0.3.0 // indirect
+ github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
diff --git a/go.sum b/go.sum
index e8cb80d16..2afaf98e1 100644
--- a/go.sum
+++ b/go.sum
@@ -103,6 +103,8 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:H
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
+github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
+github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -299,6 +301,8 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
+github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
diff --git a/types/result.go b/types/result.go
new file mode 100644
index 000000000..135d74d65
--- /dev/null
+++ b/types/result.go
@@ -0,0 +1,72 @@
+package types
+
+import "github.com/deepsourcelabs/cli/analysis/lsp"
+
+///////////////////////////////////////
+// LSP based Analysis Report Types //
+/////////////////////////////////////
+
+type AnalyzerReport struct {
+ Issues []lsp.Diagnostic `json:"issues"`
+ Metrics []Metric `json:"metrics,omitempty"`
+ IsPassed bool `json:"is_passed"`
+ Errors []Error `json:"errors"`
+ // Errors []lsp.Diagnostic `json:"errors"`
+ ExtraData interface{} `json:"extra_data"`
+}
+
+/////////////////////////////
+// Final Analysis Result //
+///////////////////////////
+
+type AnalysisResult struct {
+ Issues []Issue `json:"issues"`
+ Metrics []Metric `json:"metrics,omitempty"`
+ IsPassed bool `json:"is_passed"`
+ Errors []Error `json:"errors"`
+}
+
+type SourceCode struct {
+ Rendered string `json:"rendered"`
+}
+
+type ProcessedData struct {
+ SourceCode SourceCode `json:"source_code,omitempty"`
+}
+
+type Issue struct {
+ IssueCode string `json:"issue_code"`
+ IssueText string `json:"issue_text"`
+ Location Location `json:"location"`
+ ProcessedData ProcessedData `json:"processed_data,omitempty"`
+}
+
+type Error struct {
+ HMessage string `json:"hmessage"`
+ Level int `json:"level"`
+}
+
+type Namespace struct {
+ Key string `json:"key"`
+ Value float64 `json:"value"`
+}
+
+type Metric struct {
+ MetricCode string `json:"metric_code"`
+ Namespaces []Namespace `json:"namespaces"`
+}
+
+type Coordinate struct {
+ Line int `json:"line"`
+ Column int `json:"column"`
+}
+
+type Position struct {
+ Begin Coordinate `json:"begin"`
+ End Coordinate `json:"end"`
+}
+
+type Location struct {
+ Path string `json:"path"`
+ Position Position `json:"position"`
+}
From 247eab668b641554ceb1a7d54795372851fbea27 Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
<68370997+siddhant-deepsource@users.noreply.github.com>
Date: Mon, 20 Jun 2022 17:38:26 +0530
Subject: [PATCH 09/34] chore(dry-run): improve user interface and other minor
improvements (#153)
---
analysis/processor/batch_process.go | 7 ++--
analysis/processor/process.go | 10 ++---
analysis/processor/utils.go | 8 +++-
analyzers/validator/utils.go | 2 +-
command/analyzer/analyzer.go | 4 +-
.../.deepsource/analyzer/analyzer.toml | 0
command/analyzer/{run => dryrun}/client.go | 2 +-
command/analyzer/{run => dryrun}/config.go | 4 +-
command/analyzer/{run => dryrun}/process.go | 9 ++--
command/analyzer/{run => dryrun}/result.go | 6 +--
command/analyzer/{run => dryrun}/run.go | 42 +++++++++++++++----
command/analyzer/{run => dryrun}/source.go | 12 ++++--
.../analyzer/{run => dryrun}/source_test.go | 4 +-
.../test/expected_analysis_results.json | 0
.../analyzer/{run => dryrun}/test/run_test.go | 2 +-
.../.deepsource/analyzer/analyzer.toml | 0
.../.deepsource/analyzer/issues/I001.toml | 0
.../test/todo-checker/Dockerfile | 0
.../test/todo-checker/config.go | 0
.../{run => dryrun}/test/todo-checker/go.mod | 0
.../{run => dryrun}/test/todo-checker/go.sum | 0
.../{run => dryrun}/test/todo-checker/main.go | 0
.../test/todo-checker/types.go | 0
.../test/todo-checker/utils.go | 0
.../testdata/project1/.deepsource.toml | 0
.../testdata/project1/.gitignore | 0
.../testdata/project1/README.md | 0
.../{run => dryrun}/testdata/project1/bind.go | 0
.../{run => dryrun}/testdata/project1/cmd.go | 0
.../{run => dryrun}/testdata/project1/code.go | 0
.../{run => dryrun}/testdata/project1/go.mod | 0
.../{run => dryrun}/testdata/project1/go.sum | 0
.../testdata/project1/hex_example.go | 0
.../{run => dryrun}/testdata/project1/html.go | 0
.../{run => dryrun}/testdata/project1/main.go | 0
.../testdata/project1/sync_example.go | 0
.../testdata/project1/unsafe_example.go | 0
.../testdata/project1/unsafe_header.go | 0
.../testdata/project1/weak_crypto.go | 0
.../testdata/project2/.deepsource.toml | 0
.../testdata/project2/.rubocop.yml | 0
.../testdata/project2/README.md | 0
.../{run => dryrun}/testdata/project2/code.rb | 0
.../testdata/project3/.deepsource.toml | 0
.../testdata/project3/.gitignore | 0
.../testdata/project3/Cargo.lock | 0
.../testdata/project3/Cargo.toml | 0
.../testdata/project3/README.md | 0
.../testdata/project3/src/main.rs | 0
.../testdata/project4/.deepsource.toml | 0
.../project4/.github/workflows/CI.yml | 0
.../testdata/project4/.gitignore | 0
.../{run => dryrun}/testdata/project4/Pipfile | 0
.../testdata/project4/README.md | 0
.../testdata/project4/assignment.py | 0
.../testdata/project4/demo_code.py | 0
.../testdata/project4/django_issues.py | 0
.../project4/duplicate_bases_class.py | 0
.../testdata/project4/miscellaneous.py | 0
.../project4/return_not_implemented.py | 0
.../testdata/project4/security.py | 0
.../testdata/project4/tests/__init__.py | 0
.../testdata/project4/tests/test_code.py | 0
.../testdata/project4/type_checks.py | 0
.../toolbox/project1/analysis_config.json | 0
.../toolbox/project2/analysis_config.json | 0
.../toolbox/project3/analysis_config.json | 0
.../toolbox/project4/analysis_config.json | 0
command/analyzer/{run => dryrun}/types.go | 2 +-
command/analyzer/{run => dryrun}/utils.go | 2 +-
command/analyzer/verify/verify.go | 16 +++----
go.mod | 5 ++-
utils/prompt.go | 14 ++++---
utils/spinner.go | 16 ++++++-
74 files changed, 108 insertions(+), 59 deletions(-)
rename command/analyzer/{run => dryrun}/.deepsource/analyzer/analyzer.toml (100%)
rename command/analyzer/{run => dryrun}/client.go (98%)
rename command/analyzer/{run => dryrun}/config.go (94%)
rename command/analyzer/{run => dryrun}/process.go (85%)
rename command/analyzer/{run => dryrun}/result.go (83%)
rename command/analyzer/{run => dryrun}/run.go (64%)
rename command/analyzer/{run => dryrun}/source.go (79%)
rename command/analyzer/{run => dryrun}/source_test.go (97%)
rename command/analyzer/{run => dryrun}/test/expected_analysis_results.json (100%)
rename command/analyzer/{run => dryrun}/test/run_test.go (99%)
rename command/analyzer/{run => dryrun}/test/todo-checker/.deepsource/analyzer/analyzer.toml (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/.deepsource/analyzer/issues/I001.toml (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/Dockerfile (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/config.go (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/go.mod (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/go.sum (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/main.go (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/types.go (100%)
rename command/analyzer/{run => dryrun}/test/todo-checker/utils.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/.deepsource.toml (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/.gitignore (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/README.md (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/bind.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/cmd.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/code.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/go.mod (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/go.sum (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/hex_example.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/html.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/main.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/sync_example.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/unsafe_example.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/unsafe_header.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project1/weak_crypto.go (100%)
rename command/analyzer/{run => dryrun}/testdata/project2/.deepsource.toml (100%)
rename command/analyzer/{run => dryrun}/testdata/project2/.rubocop.yml (100%)
rename command/analyzer/{run => dryrun}/testdata/project2/README.md (100%)
rename command/analyzer/{run => dryrun}/testdata/project2/code.rb (100%)
rename command/analyzer/{run => dryrun}/testdata/project3/.deepsource.toml (100%)
rename command/analyzer/{run => dryrun}/testdata/project3/.gitignore (100%)
rename command/analyzer/{run => dryrun}/testdata/project3/Cargo.lock (100%)
rename command/analyzer/{run => dryrun}/testdata/project3/Cargo.toml (100%)
rename command/analyzer/{run => dryrun}/testdata/project3/README.md (100%)
rename command/analyzer/{run => dryrun}/testdata/project3/src/main.rs (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/.deepsource.toml (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/.github/workflows/CI.yml (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/.gitignore (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/Pipfile (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/README.md (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/assignment.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/demo_code.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/django_issues.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/duplicate_bases_class.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/miscellaneous.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/return_not_implemented.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/security.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/tests/__init__.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/tests/test_code.py (100%)
rename command/analyzer/{run => dryrun}/testdata/project4/type_checks.py (100%)
rename command/analyzer/{run => dryrun}/testdata/toolbox/project1/analysis_config.json (100%)
rename command/analyzer/{run => dryrun}/testdata/toolbox/project2/analysis_config.json (100%)
rename command/analyzer/{run => dryrun}/testdata/toolbox/project3/analysis_config.json (100%)
rename command/analyzer/{run => dryrun}/testdata/toolbox/project4/analysis_config.json (100%)
rename command/analyzer/{run => dryrun}/types.go (95%)
rename command/analyzer/{run => dryrun}/utils.go (99%)
diff --git a/analysis/processor/batch_process.go b/analysis/processor/batch_process.go
index d5c6885c2..00de911df 100644
--- a/analysis/processor/batch_process.go
+++ b/analysis/processor/batch_process.go
@@ -4,7 +4,6 @@ import (
"fmt"
"io/ioutil"
"log"
- "path"
"sort"
"strings"
@@ -117,7 +116,7 @@ func (p *ReportProcessor) cacheFilesToBeProcessed(totalFiles, processedFiles int
fileContentChannel := make(chan fileContentNode, totalFiles)
for j := 0; j < totalFiles; j++ {
filename := filesWIssueRange[processedFiles+j].Filename
- go addFileToCache(fileContentChannel, filename, p.CodePath)
+ go addFileToCache(fileContentChannel, filename)
}
cachedFiles := []fileContentNode{}
@@ -134,10 +133,10 @@ func (p *ReportProcessor) cacheFilesToBeProcessed(totalFiles, processedFiles int
// addFileToCache reads the file and formats its content into a fileContentNode struct instance
// and passes that to the cachedFilesChannel channel since this function is run on a goroutine.
-func addFileToCache(cachedFilesChannel chan fileContentNode, filename, codePath string) {
+func addFileToCache(cachedFilesChannel chan fileContentNode, filename string) {
fileContentSlice := []string{}
- fileContentBytes, err := ioutil.ReadFile(path.Join(codePath, filename))
+ fileContentBytes, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println("Could not process for file: ", filename, ". Err: ", err)
} else if string(fileContentBytes) != "" {
diff --git a/analysis/processor/process.go b/analysis/processor/process.go
index c2d7ea01a..4467276bb 100644
--- a/analysis/processor/process.go
+++ b/analysis/processor/process.go
@@ -1,8 +1,6 @@
package processor
import (
- "fmt"
-
"github.com/deepsourcelabs/cli/types"
)
@@ -14,9 +12,10 @@ type IProcessor interface {
// ReportProcessor struct contains the processor data needed to process the analysis results.
type ReportProcessor struct {
- CodePath string // The source code path where the issues got raised.
- Processors []IProcessor // The list of supported post-analysis processors.
- Report types.AnalyzerReport // The report generated by the Analyzer post analysis.
+ LocalSourcePath string // The local source code path which was analyzed by the Analyzer.
+ ContainerCodePath string // The codepath set for the Analysis container.
+ Processors []IProcessor // The list of supported post-analysis processors.
+ Report types.AnalyzerReport // The report generated by the Analyzer post analysis.
}
// ProcessAnalyzerReport accepts the result as a byte array and processes the results in the form of a
@@ -36,7 +35,6 @@ func (p *ReportProcessor) Process() types.AnalysisResult {
if len(analysisResult.Issues) <= 0 {
return analysisResult
}
- fmt.Println("Total issues reported by the Analyzer: ", len(analysisResult.Issues))
// All the files that appear in the issues are now processed by the processors listed in analyzer conf
// We must cache the files in order to not do file IO for every processor.
diff --git a/analysis/processor/utils.go b/analysis/processor/utils.go
index 53c2dbbd8..ad013e6fa 100644
--- a/analysis/processor/utils.go
+++ b/analysis/processor/utils.go
@@ -1,7 +1,9 @@
package processor
import (
+ "path"
"sort"
+ "strings"
"github.com/deepsourcelabs/cli/types"
)
@@ -87,7 +89,7 @@ func (p *ReportProcessor) formatLSPResultsToDefault() types.AnalysisResult {
IssueCode: issue.Code,
IssueText: issue.Message,
Location: types.Location{
- Path: issue.RelatedInformation[0].Location.URI,
+ Path: p.sanitizeFilePath(issue.RelatedInformation[0].Location.URI),
Position: types.Position{
Begin: types.Coordinate{
Line: issue.Range.Start.Line,
@@ -104,3 +106,7 @@ func (p *ReportProcessor) formatLSPResultsToDefault() types.AnalysisResult {
}
return analysisResult
}
+
+func (p *ReportProcessor) sanitizeFilePath(filePath string) string {
+ return path.Join(p.LocalSourcePath, strings.TrimPrefix(filePath, p.ContainerCodePath))
+}
diff --git a/analyzers/validator/utils.go b/analyzers/validator/utils.go
index 01e91629b..7fa291721 100644
--- a/analyzers/validator/utils.go
+++ b/analyzers/validator/utils.go
@@ -40,7 +40,7 @@ func handleTOMLDecodeErrors(err error, filePath string) *ValidationFailure {
// Handle strict mode error when some alien fields are added in the user configured TOML
if strings.HasPrefix(err.Error(), "strict mode") {
- decodeErrorMessage = fmt.Sprintf("failed to parse %s. Invalid fields detected.", path.Base(filePath))
+ decodeErrorMessage = fmt.Sprintf("Failed to parse %s. Invalid fields detected.", path.Base(filePath))
}
validationError := ValidationFailure{
File: filePath,
diff --git a/command/analyzer/analyzer.go b/command/analyzer/analyzer.go
index 7d7d04b9b..24a46d3c6 100644
--- a/command/analyzer/analyzer.go
+++ b/command/analyzer/analyzer.go
@@ -3,8 +3,8 @@ package analyzer
import (
"github.com/spf13/cobra"
+ dryrun "github.com/deepsourcelabs/cli/command/analyzer/dryrun"
initialize "github.com/deepsourcelabs/cli/command/analyzer/initialize"
- "github.com/deepsourcelabs/cli/command/analyzer/run"
verify "github.com/deepsourcelabs/cli/command/analyzer/verify"
)
@@ -17,7 +17,7 @@ func NewCmdAnalyzer() *cobra.Command {
Use: "analyzer",
Short: "Operations related to DeepSource Analyzers",
}
- cmd.AddCommand(run.NewCmdAnalyzerRun())
+ cmd.AddCommand(dryrun.NewCmdAnalyzerRun())
cmd.AddCommand(verify.NewCmdAnalyzerVerify())
cmd.AddCommand(initialize.NewCmdAnalyzerInit())
return cmd
diff --git a/command/analyzer/run/.deepsource/analyzer/analyzer.toml b/command/analyzer/dryrun/.deepsource/analyzer/analyzer.toml
similarity index 100%
rename from command/analyzer/run/.deepsource/analyzer/analyzer.toml
rename to command/analyzer/dryrun/.deepsource/analyzer/analyzer.toml
diff --git a/command/analyzer/run/client.go b/command/analyzer/dryrun/client.go
similarity index 98%
rename from command/analyzer/run/client.go
rename to command/analyzer/dryrun/client.go
index 8c3f77cf3..0a84f1c8b 100644
--- a/command/analyzer/run/client.go
+++ b/command/analyzer/dryrun/client.go
@@ -1,4 +1,4 @@
-package run
+package dryrun
import (
"strings"
diff --git a/command/analyzer/run/config.go b/command/analyzer/dryrun/config.go
similarity index 94%
rename from command/analyzer/run/config.go
rename to command/analyzer/dryrun/config.go
index bf9bc8c8e..71587b7da 100644
--- a/command/analyzer/run/config.go
+++ b/command/analyzer/dryrun/config.go
@@ -1,8 +1,7 @@
-package run
+package dryrun
import (
"encoding/json"
- "fmt"
"os"
"path"
@@ -39,6 +38,5 @@ func (a *AnalyzerDryRun) writeAnalysisConfig() (err error) {
a.Client.AnalysisOpts.AnalysisConfigPath = path.Join(a.TempToolBoxDirectory, analysisConfigName+analysisConfigExt)
// Create a temporary directory
- fmt.Printf("Writing analysis_config to %s\n", a.TempToolBoxDirectory)
return os.WriteFile(path.Join(a.TempToolBoxDirectory, analysisConfigName+analysisConfigExt), analysisConfigJSON, 0o644)
}
diff --git a/command/analyzer/run/process.go b/command/analyzer/dryrun/process.go
similarity index 85%
rename from command/analyzer/run/process.go
rename to command/analyzer/dryrun/process.go
index f624071ef..d688560fd 100644
--- a/command/analyzer/run/process.go
+++ b/command/analyzer/dryrun/process.go
@@ -1,8 +1,7 @@
-package run
+package dryrun
import (
"encoding/json"
- "fmt"
"github.com/deepsourcelabs/cli/analysis/processor"
"github.com/deepsourcelabs/cli/analysis/processor/processors"
@@ -21,15 +20,15 @@ func (a *AnalyzerDryRun) processAnalyzerReport(reportBytes []byte) (types.Analys
source_code_load = sourceCodeHighlightingProcessor
processor := processor.ReportProcessor{
- CodePath: a.SourcePath,
- Processors: []processor.IProcessor{skip_cq, source_code_load},
+ LocalSourcePath: a.SourcePath,
+ ContainerCodePath: a.Client.AnalysisOpts.ContainerCodePath,
+ Processors: []processor.IProcessor{skip_cq, source_code_load},
}
// Generate the silencers regexMap.
processors.GenerateSilencersRegexMap()
if err := json.Unmarshal(reportBytes, &report); err != nil {
- fmt.Println(err)
return types.AnalysisResult{}, err
}
diff --git a/command/analyzer/run/result.go b/command/analyzer/dryrun/result.go
similarity index 83%
rename from command/analyzer/run/result.go
rename to command/analyzer/dryrun/result.go
index 015cc1199..8ce5afb11 100644
--- a/command/analyzer/run/result.go
+++ b/command/analyzer/dryrun/result.go
@@ -1,8 +1,7 @@
-package run
+package dryrun
import (
"errors"
- "fmt"
"os"
"path"
"strings"
@@ -14,12 +13,9 @@ func (a *AnalyzerDryRun) writeAnalysisResults(buf []byte, fileName string) (err
// Ref: https://deepsource.io/directory/analyzers/go/issues/GSC-G305
if !strings.Contains(string(buf), "..") {
- fmt.Println("Writing analysis result to", path.Join(a.Client.AnalysisOpts.AnalysisResultsPath, fileName))
-
// Check if the results file already exists
if _, err := os.Stat(analysisResultsPath); err != nil {
if errors.Is(err, os.ErrNotExist) {
- fmt.Println("File doesn't exist already. Creating it.")
// Create the file and allocate permissions to it
_, err := os.Create(analysisResultsPath)
if err != nil {
diff --git a/command/analyzer/run/run.go b/command/analyzer/dryrun/run.go
similarity index 64%
rename from command/analyzer/run/run.go
rename to command/analyzer/dryrun/run.go
index 61c59b041..b59723799 100644
--- a/command/analyzer/run/run.go
+++ b/command/analyzer/dryrun/run.go
@@ -1,11 +1,13 @@
-package run
+package dryrun
import (
"fmt"
"os"
+ "path"
"github.com/deepsourcelabs/cli/types"
"github.com/deepsourcelabs/cli/utils"
+ "github.com/morikuni/aec"
"github.com/spf13/cobra"
"github.com/deepsourcelabs/cli/analysis/config"
@@ -21,7 +23,6 @@ var (
analysisResultsName string = "analysis_results"
analysisConfigExt string = ".json"
analysisResultsExt string = ".json"
- // supportedProcessors []string = []string{"skip_cq", "source_code_load"}
)
// The params required while running the Analysis locally
@@ -33,7 +34,8 @@ type AnalyzerDryRun struct {
TempToolBoxDirectory string // The temporary directory where the analysis_config is present.
AnalysisFiles []string // The list of analysis files.
AnalysisConfig *config.AnalysisConfig // The analysis_config.json file containing the meta for analysis.
- AnalysisResult types.AnalysisResult
+ AnalysisResult types.AnalysisResult // The analysis result received after post processing Analyzer report.
+ Spinner *utils.SpinnerUtils
}
func NewCmdAnalyzerRun() *cobra.Command {
@@ -42,9 +44,9 @@ func NewCmdAnalyzerRun() *cobra.Command {
// Initializing the run params and setting defaults
opts := AnalyzerDryRun{
+ Spinner: &utils.SpinnerUtils{},
SourcePath: cwd,
RemoteSource: false,
- // Processors: supportedProcessors,
}
cmd := &cobra.Command{
@@ -67,7 +69,7 @@ func NewCmdAnalyzerRun() *cobra.Command {
return cmd
}
-// Run the Analyzer locally on a certain directory or repository
+// AnalyzerRun runs the Analyzer locally on a certain directory or repository.
func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
err = a.createDockerClient()
if err != nil {
@@ -75,7 +77,7 @@ func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
}
// Building the Analyzer image
- fmt.Println("Building Analyzer image...")
+ a.Spinner.StartSpinnerWithLabel("Building Analyzer image...", "Built Analyzer image")
ctxCancelFunc, buildRespReader, buildError := a.Client.BuildAnalyzerDockerImage()
// Cancel the build context and close the reader before exiting this function
@@ -84,58 +86,82 @@ func (a *AnalyzerDryRun) AnalyzerRun() (err error) {
}
defer ctxCancelFunc()
if buildError != nil {
+ a.Spinner.StopSpinnerWithError("Failed to build the Analyzer image", err)
return buildError
}
// Check the docker build response
- // TODO: Tweak the behaviour here when the spinners are added to the run command
if err = docker.CheckBuildResponse(buildRespReader, false); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to build the Analyzer image", err)
return err
}
+ a.Spinner.StopSpinner()
// Create temporary toolbox directory to store analysis config and later analyis results
// If already passed through --output-file flag, use that one
+ a.Spinner.StartSpinnerWithLabel("Creating temporary toolbox directory...", "Temporary toolbox directory created")
if err = a.createTemporaryToolBoxDir(); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to create temporary toolbox directory", err)
return err
}
+ a.Spinner.StopSpinner()
// Resolve the path of source code to be analyzed based on the user input
+ a.Spinner.StartSpinnerWithLabel("Resolving the path of source code to be analyzed...", "")
if a.Client.AnalysisOpts.HostCodePath, err = a.resolveAnalysisCodePath(); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to resolve path of source code to be analyzed", err)
return err
}
+ a.Spinner.StopSpinner()
// Generate the analysis_config.json file
// Also, write the analysis_config data into a temp /toolbox directory to be mounted into the container
+ a.Spinner.StartSpinnerWithLabel("Generating analysis config...", fmt.Sprint("Analysis config (analysis_config.json) generated at ", path.Join(a.TempToolBoxDirectory, "analysis_config.json")))
if err = a.prepareAnalysisConfig(); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to generate analysis_config.json", err)
return err
}
+ a.Spinner.StopSpinner()
// Write the analysis_config.json to local toolbox directory
if err = a.writeAnalysisConfig(); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to write analysis_config.json", err)
return err
}
+ a.Spinner.StopSpinner()
// Starts the Docker container which analyzes the code and stores the analysis results
// in a variable
+
+ fmt.Println(aec.Apply("[+] Starting the Analysis container", aec.LightYellowF))
if err = a.Client.StartDockerContainer(); err != nil {
return err
}
// Fetch the analysis results
+ a.Spinner.StartSpinnerWithLabel("Fetching Analyzer report...", "Successfully fetched Analyzer report")
analysisResultBuf, analysisResultFileName, err := a.Client.FetchAnalysisResults()
if err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to fetch Analyzer report", err)
return err
}
+ a.Spinner.StopSpinner()
// Write the analysis results to the file
+ a.Spinner.StartSpinnerWithLabel("Writing Analyzer report...", fmt.Sprintf("Analyzer report written to %s", path.Join(a.Client.AnalysisOpts.AnalysisResultsPath, analysisResultFileName)))
if err = a.writeAnalysisResults(analysisResultBuf, analysisResultFileName); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to write Analyzer report", err)
return err
}
+ a.Spinner.StopSpinner()
// Process the analyzer report once it is received.
+ a.Spinner.StartSpinnerWithLabel("Processing Analyzer report...", "Successfully processed Analyzer report")
if a.AnalysisResult, err = a.processAnalyzerReport(analysisResultBuf); err != nil {
+ a.Spinner.StopSpinnerWithError("Failed to process Analyzer report", err)
return err
}
- fmt.Println("Issues after processing:", len(a.AnalysisResult.Issues))
+ a.Spinner.StopSpinner()
+ fmt.Println(aec.Apply(fmt.Sprintf("[✔] Issues after processing: %d", len(a.AnalysisResult.Issues)), aec.LightGreenF))
return nil
}
diff --git a/command/analyzer/run/source.go b/command/analyzer/dryrun/source.go
similarity index 79%
rename from command/analyzer/run/source.go
rename to command/analyzer/dryrun/source.go
index d498f6cd5..d4d88d1b7 100644
--- a/command/analyzer/run/source.go
+++ b/command/analyzer/dryrun/source.go
@@ -1,8 +1,8 @@
-package run
+package dryrun
import (
+ "bytes"
"fmt"
- "os"
"path/filepath"
"github.com/go-git/go-git/v5"
@@ -20,6 +20,7 @@ func (a *AnalyzerDryRun) resolveAnalysisCodePath() (string, error) {
}
a.SourcePath = tempCloneDir
} else {
+ // Resolve the path if it is a relative path
a.SourcePath, _ = filepath.Abs(a.SourcePath)
}
return a.SourcePath, nil
@@ -28,17 +29,20 @@ func (a *AnalyzerDryRun) resolveAnalysisCodePath() (string, error) {
// Clones the remote repository which is to be analyzed
func (a *AnalyzerDryRun) cloneRemoteSource() (string, error) {
var err error
+ buf := bytes.NewBuffer(nil)
a.RemoteSource = true
+
+ a.Spinner.SetSuffix(fmt.Sprintf("Creating temporary directory to clone %s", a.SourcePath))
if a.TempCloneDirectory, err = createTemporaryDirectory("code"); err != nil {
return "", err
}
// Clone the repository to a temporary directory
- fmt.Printf("Cloning %s to %s\n", a.SourcePath, a.TempCloneDirectory)
+ a.Spinner.SetSuffix(fmt.Sprintf("Cloning %s to %s", a.SourcePath, a.TempCloneDirectory))
if _, err := git.PlainClone(a.TempCloneDirectory, false, &git.CloneOptions{
URL: a.SourcePath,
Depth: 1,
- Progress: os.Stdout,
+ Progress: buf,
}); err != nil {
return "", err
}
diff --git a/command/analyzer/run/source_test.go b/command/analyzer/dryrun/source_test.go
similarity index 97%
rename from command/analyzer/run/source_test.go
rename to command/analyzer/dryrun/source_test.go
index 520cbe74c..c5c561507 100644
--- a/command/analyzer/run/source_test.go
+++ b/command/analyzer/dryrun/source_test.go
@@ -1,4 +1,4 @@
-package run
+package dryrun
import (
"bytes"
@@ -8,6 +8,7 @@ import (
"testing"
"github.com/deepsourcelabs/cli/analyzers/backend/docker"
+ "github.com/deepsourcelabs/cli/utils"
)
func TestPrepareAnalysisConfig(t *testing.T) {
@@ -116,6 +117,7 @@ func TestResolveAnalysisCodePath(t *testing.T) {
for _, tc := range testCases {
opts := AnalyzerDryRun{
SourcePath: tc.Path,
+ Spinner: &utils.SpinnerUtils{},
}
resolvedPath, err := opts.resolveAnalysisCodePath()
if err != nil && err.Error() != "authentication required" {
diff --git a/command/analyzer/run/test/expected_analysis_results.json b/command/analyzer/dryrun/test/expected_analysis_results.json
similarity index 100%
rename from command/analyzer/run/test/expected_analysis_results.json
rename to command/analyzer/dryrun/test/expected_analysis_results.json
diff --git a/command/analyzer/run/test/run_test.go b/command/analyzer/dryrun/test/run_test.go
similarity index 99%
rename from command/analyzer/run/test/run_test.go
rename to command/analyzer/dryrun/test/run_test.go
index 17babdd2a..98fe4844d 100644
--- a/command/analyzer/run/test/run_test.go
+++ b/command/analyzer/dryrun/test/run_test.go
@@ -1,4 +1,4 @@
-package run
+package dryrun
import (
"bytes"
diff --git a/command/analyzer/run/test/todo-checker/.deepsource/analyzer/analyzer.toml b/command/analyzer/dryrun/test/todo-checker/.deepsource/analyzer/analyzer.toml
similarity index 100%
rename from command/analyzer/run/test/todo-checker/.deepsource/analyzer/analyzer.toml
rename to command/analyzer/dryrun/test/todo-checker/.deepsource/analyzer/analyzer.toml
diff --git a/command/analyzer/run/test/todo-checker/.deepsource/analyzer/issues/I001.toml b/command/analyzer/dryrun/test/todo-checker/.deepsource/analyzer/issues/I001.toml
similarity index 100%
rename from command/analyzer/run/test/todo-checker/.deepsource/analyzer/issues/I001.toml
rename to command/analyzer/dryrun/test/todo-checker/.deepsource/analyzer/issues/I001.toml
diff --git a/command/analyzer/run/test/todo-checker/Dockerfile b/command/analyzer/dryrun/test/todo-checker/Dockerfile
similarity index 100%
rename from command/analyzer/run/test/todo-checker/Dockerfile
rename to command/analyzer/dryrun/test/todo-checker/Dockerfile
diff --git a/command/analyzer/run/test/todo-checker/config.go b/command/analyzer/dryrun/test/todo-checker/config.go
similarity index 100%
rename from command/analyzer/run/test/todo-checker/config.go
rename to command/analyzer/dryrun/test/todo-checker/config.go
diff --git a/command/analyzer/run/test/todo-checker/go.mod b/command/analyzer/dryrun/test/todo-checker/go.mod
similarity index 100%
rename from command/analyzer/run/test/todo-checker/go.mod
rename to command/analyzer/dryrun/test/todo-checker/go.mod
diff --git a/command/analyzer/run/test/todo-checker/go.sum b/command/analyzer/dryrun/test/todo-checker/go.sum
similarity index 100%
rename from command/analyzer/run/test/todo-checker/go.sum
rename to command/analyzer/dryrun/test/todo-checker/go.sum
diff --git a/command/analyzer/run/test/todo-checker/main.go b/command/analyzer/dryrun/test/todo-checker/main.go
similarity index 100%
rename from command/analyzer/run/test/todo-checker/main.go
rename to command/analyzer/dryrun/test/todo-checker/main.go
diff --git a/command/analyzer/run/test/todo-checker/types.go b/command/analyzer/dryrun/test/todo-checker/types.go
similarity index 100%
rename from command/analyzer/run/test/todo-checker/types.go
rename to command/analyzer/dryrun/test/todo-checker/types.go
diff --git a/command/analyzer/run/test/todo-checker/utils.go b/command/analyzer/dryrun/test/todo-checker/utils.go
similarity index 100%
rename from command/analyzer/run/test/todo-checker/utils.go
rename to command/analyzer/dryrun/test/todo-checker/utils.go
diff --git a/command/analyzer/run/testdata/project1/.deepsource.toml b/command/analyzer/dryrun/testdata/project1/.deepsource.toml
similarity index 100%
rename from command/analyzer/run/testdata/project1/.deepsource.toml
rename to command/analyzer/dryrun/testdata/project1/.deepsource.toml
diff --git a/command/analyzer/run/testdata/project1/.gitignore b/command/analyzer/dryrun/testdata/project1/.gitignore
similarity index 100%
rename from command/analyzer/run/testdata/project1/.gitignore
rename to command/analyzer/dryrun/testdata/project1/.gitignore
diff --git a/command/analyzer/run/testdata/project1/README.md b/command/analyzer/dryrun/testdata/project1/README.md
similarity index 100%
rename from command/analyzer/run/testdata/project1/README.md
rename to command/analyzer/dryrun/testdata/project1/README.md
diff --git a/command/analyzer/run/testdata/project1/bind.go b/command/analyzer/dryrun/testdata/project1/bind.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/bind.go
rename to command/analyzer/dryrun/testdata/project1/bind.go
diff --git a/command/analyzer/run/testdata/project1/cmd.go b/command/analyzer/dryrun/testdata/project1/cmd.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/cmd.go
rename to command/analyzer/dryrun/testdata/project1/cmd.go
diff --git a/command/analyzer/run/testdata/project1/code.go b/command/analyzer/dryrun/testdata/project1/code.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/code.go
rename to command/analyzer/dryrun/testdata/project1/code.go
diff --git a/command/analyzer/run/testdata/project1/go.mod b/command/analyzer/dryrun/testdata/project1/go.mod
similarity index 100%
rename from command/analyzer/run/testdata/project1/go.mod
rename to command/analyzer/dryrun/testdata/project1/go.mod
diff --git a/command/analyzer/run/testdata/project1/go.sum b/command/analyzer/dryrun/testdata/project1/go.sum
similarity index 100%
rename from command/analyzer/run/testdata/project1/go.sum
rename to command/analyzer/dryrun/testdata/project1/go.sum
diff --git a/command/analyzer/run/testdata/project1/hex_example.go b/command/analyzer/dryrun/testdata/project1/hex_example.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/hex_example.go
rename to command/analyzer/dryrun/testdata/project1/hex_example.go
diff --git a/command/analyzer/run/testdata/project1/html.go b/command/analyzer/dryrun/testdata/project1/html.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/html.go
rename to command/analyzer/dryrun/testdata/project1/html.go
diff --git a/command/analyzer/run/testdata/project1/main.go b/command/analyzer/dryrun/testdata/project1/main.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/main.go
rename to command/analyzer/dryrun/testdata/project1/main.go
diff --git a/command/analyzer/run/testdata/project1/sync_example.go b/command/analyzer/dryrun/testdata/project1/sync_example.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/sync_example.go
rename to command/analyzer/dryrun/testdata/project1/sync_example.go
diff --git a/command/analyzer/run/testdata/project1/unsafe_example.go b/command/analyzer/dryrun/testdata/project1/unsafe_example.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/unsafe_example.go
rename to command/analyzer/dryrun/testdata/project1/unsafe_example.go
diff --git a/command/analyzer/run/testdata/project1/unsafe_header.go b/command/analyzer/dryrun/testdata/project1/unsafe_header.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/unsafe_header.go
rename to command/analyzer/dryrun/testdata/project1/unsafe_header.go
diff --git a/command/analyzer/run/testdata/project1/weak_crypto.go b/command/analyzer/dryrun/testdata/project1/weak_crypto.go
similarity index 100%
rename from command/analyzer/run/testdata/project1/weak_crypto.go
rename to command/analyzer/dryrun/testdata/project1/weak_crypto.go
diff --git a/command/analyzer/run/testdata/project2/.deepsource.toml b/command/analyzer/dryrun/testdata/project2/.deepsource.toml
similarity index 100%
rename from command/analyzer/run/testdata/project2/.deepsource.toml
rename to command/analyzer/dryrun/testdata/project2/.deepsource.toml
diff --git a/command/analyzer/run/testdata/project2/.rubocop.yml b/command/analyzer/dryrun/testdata/project2/.rubocop.yml
similarity index 100%
rename from command/analyzer/run/testdata/project2/.rubocop.yml
rename to command/analyzer/dryrun/testdata/project2/.rubocop.yml
diff --git a/command/analyzer/run/testdata/project2/README.md b/command/analyzer/dryrun/testdata/project2/README.md
similarity index 100%
rename from command/analyzer/run/testdata/project2/README.md
rename to command/analyzer/dryrun/testdata/project2/README.md
diff --git a/command/analyzer/run/testdata/project2/code.rb b/command/analyzer/dryrun/testdata/project2/code.rb
similarity index 100%
rename from command/analyzer/run/testdata/project2/code.rb
rename to command/analyzer/dryrun/testdata/project2/code.rb
diff --git a/command/analyzer/run/testdata/project3/.deepsource.toml b/command/analyzer/dryrun/testdata/project3/.deepsource.toml
similarity index 100%
rename from command/analyzer/run/testdata/project3/.deepsource.toml
rename to command/analyzer/dryrun/testdata/project3/.deepsource.toml
diff --git a/command/analyzer/run/testdata/project3/.gitignore b/command/analyzer/dryrun/testdata/project3/.gitignore
similarity index 100%
rename from command/analyzer/run/testdata/project3/.gitignore
rename to command/analyzer/dryrun/testdata/project3/.gitignore
diff --git a/command/analyzer/run/testdata/project3/Cargo.lock b/command/analyzer/dryrun/testdata/project3/Cargo.lock
similarity index 100%
rename from command/analyzer/run/testdata/project3/Cargo.lock
rename to command/analyzer/dryrun/testdata/project3/Cargo.lock
diff --git a/command/analyzer/run/testdata/project3/Cargo.toml b/command/analyzer/dryrun/testdata/project3/Cargo.toml
similarity index 100%
rename from command/analyzer/run/testdata/project3/Cargo.toml
rename to command/analyzer/dryrun/testdata/project3/Cargo.toml
diff --git a/command/analyzer/run/testdata/project3/README.md b/command/analyzer/dryrun/testdata/project3/README.md
similarity index 100%
rename from command/analyzer/run/testdata/project3/README.md
rename to command/analyzer/dryrun/testdata/project3/README.md
diff --git a/command/analyzer/run/testdata/project3/src/main.rs b/command/analyzer/dryrun/testdata/project3/src/main.rs
similarity index 100%
rename from command/analyzer/run/testdata/project3/src/main.rs
rename to command/analyzer/dryrun/testdata/project3/src/main.rs
diff --git a/command/analyzer/run/testdata/project4/.deepsource.toml b/command/analyzer/dryrun/testdata/project4/.deepsource.toml
similarity index 100%
rename from command/analyzer/run/testdata/project4/.deepsource.toml
rename to command/analyzer/dryrun/testdata/project4/.deepsource.toml
diff --git a/command/analyzer/run/testdata/project4/.github/workflows/CI.yml b/command/analyzer/dryrun/testdata/project4/.github/workflows/CI.yml
similarity index 100%
rename from command/analyzer/run/testdata/project4/.github/workflows/CI.yml
rename to command/analyzer/dryrun/testdata/project4/.github/workflows/CI.yml
diff --git a/command/analyzer/run/testdata/project4/.gitignore b/command/analyzer/dryrun/testdata/project4/.gitignore
similarity index 100%
rename from command/analyzer/run/testdata/project4/.gitignore
rename to command/analyzer/dryrun/testdata/project4/.gitignore
diff --git a/command/analyzer/run/testdata/project4/Pipfile b/command/analyzer/dryrun/testdata/project4/Pipfile
similarity index 100%
rename from command/analyzer/run/testdata/project4/Pipfile
rename to command/analyzer/dryrun/testdata/project4/Pipfile
diff --git a/command/analyzer/run/testdata/project4/README.md b/command/analyzer/dryrun/testdata/project4/README.md
similarity index 100%
rename from command/analyzer/run/testdata/project4/README.md
rename to command/analyzer/dryrun/testdata/project4/README.md
diff --git a/command/analyzer/run/testdata/project4/assignment.py b/command/analyzer/dryrun/testdata/project4/assignment.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/assignment.py
rename to command/analyzer/dryrun/testdata/project4/assignment.py
diff --git a/command/analyzer/run/testdata/project4/demo_code.py b/command/analyzer/dryrun/testdata/project4/demo_code.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/demo_code.py
rename to command/analyzer/dryrun/testdata/project4/demo_code.py
diff --git a/command/analyzer/run/testdata/project4/django_issues.py b/command/analyzer/dryrun/testdata/project4/django_issues.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/django_issues.py
rename to command/analyzer/dryrun/testdata/project4/django_issues.py
diff --git a/command/analyzer/run/testdata/project4/duplicate_bases_class.py b/command/analyzer/dryrun/testdata/project4/duplicate_bases_class.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/duplicate_bases_class.py
rename to command/analyzer/dryrun/testdata/project4/duplicate_bases_class.py
diff --git a/command/analyzer/run/testdata/project4/miscellaneous.py b/command/analyzer/dryrun/testdata/project4/miscellaneous.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/miscellaneous.py
rename to command/analyzer/dryrun/testdata/project4/miscellaneous.py
diff --git a/command/analyzer/run/testdata/project4/return_not_implemented.py b/command/analyzer/dryrun/testdata/project4/return_not_implemented.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/return_not_implemented.py
rename to command/analyzer/dryrun/testdata/project4/return_not_implemented.py
diff --git a/command/analyzer/run/testdata/project4/security.py b/command/analyzer/dryrun/testdata/project4/security.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/security.py
rename to command/analyzer/dryrun/testdata/project4/security.py
diff --git a/command/analyzer/run/testdata/project4/tests/__init__.py b/command/analyzer/dryrun/testdata/project4/tests/__init__.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/tests/__init__.py
rename to command/analyzer/dryrun/testdata/project4/tests/__init__.py
diff --git a/command/analyzer/run/testdata/project4/tests/test_code.py b/command/analyzer/dryrun/testdata/project4/tests/test_code.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/tests/test_code.py
rename to command/analyzer/dryrun/testdata/project4/tests/test_code.py
diff --git a/command/analyzer/run/testdata/project4/type_checks.py b/command/analyzer/dryrun/testdata/project4/type_checks.py
similarity index 100%
rename from command/analyzer/run/testdata/project4/type_checks.py
rename to command/analyzer/dryrun/testdata/project4/type_checks.py
diff --git a/command/analyzer/run/testdata/toolbox/project1/analysis_config.json b/command/analyzer/dryrun/testdata/toolbox/project1/analysis_config.json
similarity index 100%
rename from command/analyzer/run/testdata/toolbox/project1/analysis_config.json
rename to command/analyzer/dryrun/testdata/toolbox/project1/analysis_config.json
diff --git a/command/analyzer/run/testdata/toolbox/project2/analysis_config.json b/command/analyzer/dryrun/testdata/toolbox/project2/analysis_config.json
similarity index 100%
rename from command/analyzer/run/testdata/toolbox/project2/analysis_config.json
rename to command/analyzer/dryrun/testdata/toolbox/project2/analysis_config.json
diff --git a/command/analyzer/run/testdata/toolbox/project3/analysis_config.json b/command/analyzer/dryrun/testdata/toolbox/project3/analysis_config.json
similarity index 100%
rename from command/analyzer/run/testdata/toolbox/project3/analysis_config.json
rename to command/analyzer/dryrun/testdata/toolbox/project3/analysis_config.json
diff --git a/command/analyzer/run/testdata/toolbox/project4/analysis_config.json b/command/analyzer/dryrun/testdata/toolbox/project4/analysis_config.json
similarity index 100%
rename from command/analyzer/run/testdata/toolbox/project4/analysis_config.json
rename to command/analyzer/dryrun/testdata/toolbox/project4/analysis_config.json
diff --git a/command/analyzer/run/types.go b/command/analyzer/dryrun/types.go
similarity index 95%
rename from command/analyzer/run/types.go
rename to command/analyzer/dryrun/types.go
index 8523d4cc3..0885ce452 100644
--- a/command/analyzer/run/types.go
+++ b/command/analyzer/dryrun/types.go
@@ -1,4 +1,4 @@
-package run
+package dryrun
type AnalysisConfig struct {
Files []string `json:"files"`
diff --git a/command/analyzer/run/utils.go b/command/analyzer/dryrun/utils.go
similarity index 99%
rename from command/analyzer/run/utils.go
rename to command/analyzer/dryrun/utils.go
index e6211c4fb..6c6d900de 100644
--- a/command/analyzer/run/utils.go
+++ b/command/analyzer/dryrun/utils.go
@@ -1,4 +1,4 @@
-package run
+package dryrun
import (
"net/url"
diff --git a/command/analyzer/verify/verify.go b/command/analyzer/verify/verify.go
index c1a39094b..4dc312db5 100644
--- a/command/analyzer/verify/verify.go
+++ b/command/analyzer/verify/verify.go
@@ -35,14 +35,6 @@ type AnalyzerVerifyOpts struct {
* ====================================== */
func NewCmdAnalyzerVerify() *cobra.Command {
- // Configuring the paths of analyzer.toml and issues directory
- projectRoot, err := utils.ExtractProjectRootPath()
- if err != nil {
- fmt.Printf("Couldn't find the root directory of the project. Error:%s", err)
- }
- analyzerTOMLPath = filepath.Join(projectRoot, configFolder, "analyzer.toml")
- issuesDirPath = filepath.Join(projectRoot, configFolder, "issues/")
-
opts := AnalyzerVerifyOpts{
Spinner: &utils.SpinnerUtils{},
Build: AnalyzerBuild{
@@ -76,6 +68,14 @@ func (a *AnalyzerVerifyOpts) verifyAnalyzer() (err error) {
var issuesValidationErrors *[]validator.ValidationFailure
configurationValid := true
+ // Configuring the paths of analyzer.toml and issues directory
+ projectRoot, err := utils.ExtractProjectRootPath()
+ if err != nil {
+ fmt.Printf("Couldn't find the root directory of the project. Error: %s\n", err)
+ }
+ analyzerTOMLPath = filepath.Join(projectRoot, configFolder, "analyzer.toml")
+ issuesDirPath = filepath.Join(projectRoot, configFolder, "issues/")
+
/* ==================================================================================
* Checks for the presence of .deepsource/analyzer directory,
* the analyzer.toml file and issues present in .deepsource/analyzer/issues directory
diff --git a/go.mod b/go.mod
index 9842ca1e8..9f7733dc5 100644
--- a/go.mod
+++ b/go.mod
@@ -69,7 +69,10 @@ require (
gopkg.in/ini.v1 v1.66.4 // indirect
)
-require github.com/alecthomas/chroma v0.10.0
+require (
+ github.com/alecthomas/chroma v0.10.0
+ github.com/morikuni/aec v1.0.0
+)
require (
github.com/Microsoft/go-winio v0.5.2 // indirect
diff --git a/utils/prompt.go b/utils/prompt.go
index de6867727..2b8f14ea2 100644
--- a/utils/prompt.go
+++ b/utils/prompt.go
@@ -6,7 +6,7 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
- "github.com/mgutz/ansi"
+ "github.com/morikuni/aec"
)
type UserInputPrompt struct{}
@@ -104,17 +104,21 @@ func checkInterrupt(err error) error {
}
func GetSuccessMessage(msg string) string {
- greenTickMark := ansi.Color("✔", "green")
+ greenTickMark := aec.Apply("[✔]", aec.LightGreenF)
return greenTickMark + " " + msg
}
func GetFailureMessage(msg, errorMsg string) string {
if errorMsg != "" {
- return ansi.Color("✗"+" "+msg+". "+"Error: "+errorMsg, "red")
+ return aec.Apply("[✗]"+" "+msg+". "+"Error: "+errorMsg, aec.LightRedF)
}
- return ansi.Color("✗"+" "+msg, "red")
+ return aec.Apply("[✗]"+" "+msg, aec.LightRedF)
}
func GetBulletMessage(msg, color string) string {
- return ansi.Color("•"+" "+msg, color)
+ switch color {
+ case "red":
+ return aec.Apply("•"+" "+msg, aec.LightRedF)
+ }
+ return ""
}
diff --git a/utils/spinner.go b/utils/spinner.go
index 8fa474de1..1fcabb587 100644
--- a/utils/spinner.go
+++ b/utils/spinner.go
@@ -24,10 +24,13 @@ func (s *SpinnerUtils) StartSpinnerWithLabel(label, finalMessage string) {
120*time.Millisecond,
spinner.WithWriter(os.Stdout),
spinner.WithWriter(os.Stderr),
- spinner.WithFinalMSG(fmt.Sprintf("%s\n", GetSuccessMessage(finalMessage)))) // Build our new spinner
+ ) // Build our new spinner
if label != "" {
sp.Suffix = " " + label + " "
}
+ if finalMessage != "" {
+ sp.FinalMSG = fmt.Sprintf("%s\n", GetSuccessMessage(finalMessage))
+ }
sp.Start() // Start the spinner
s.Spinner = sp
}
@@ -44,6 +47,17 @@ func (s *SpinnerUtils) StopSpinner() {
s.Spinner = nil
}
+// Stops the spinner
+func (s *SpinnerUtils) SetSuffix(suffix string) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if s.Spinner == nil {
+ return
+ }
+ s.Spinner.Suffix = " " + suffix + " "
+}
+
// Stops the spinner and displays an error message with a cross emoji
func (s *SpinnerUtils) StopSpinnerWithError(msg string, errorMessage error) {
s.mu.Lock()
From 0cf37cb92d0ea2504f7d91520713f92aaefcc2ed Mon Sep 17 00:00:00 2001
From: Siddhant N Trivedi
<68370997+siddhant-deepsource@users.noreply.github.com>
Date: Tue, 28 Jun 2022 19:00:01 +0530
Subject: [PATCH 10/34] feat(dry-run): template to show the analysis results on
browser (#154)
---
.../processors/proc_source_code_load.go | 4 +-
analyzers/backend/docker/container.go | 2 +-
cmd/Dockerfile_new | 2 -
command/analyzer/dryrun/client.go | 1 +
command/analyzer/dryrun/process.go | 8 +-
command/analyzer/dryrun/render/category.go | 26 +
command/analyzer/dryrun/render/metrics.go | 14 +
command/analyzer/dryrun/render/occurences.go | 78 ++
command/analyzer/dryrun/render/render.go | 85 ++
command/analyzer/dryrun/render/route.go | 78 ++
command/analyzer/dryrun/render/types.go | 54 +
command/analyzer/dryrun/render/utils.go | 201 +++
.../dryrun/render/views/assets/cli.css | 1169 +++++++++++++++++
.../analyzer/dryrun/render/views/index.html | 123 ++
.../dryrun/render/views/occurence.html | 111 ++
command/analyzer/dryrun/run.go | 78 +-
command/analyzer/dryrun/test/run_test.go | 85 +-
command/analyzer/dryrun/types.go | 1 +
go.mod | 15 +-
go.sum | 27 +-
types/analyzer.go | 2 +-
types/constants.go | 24 +
types/result.go | 11 +-
23 files changed, 2130 insertions(+), 69 deletions(-)
delete mode 100644 cmd/Dockerfile_new
create mode 100644 command/analyzer/dryrun/render/category.go
create mode 100644 command/analyzer/dryrun/render/metrics.go
create mode 100644 command/analyzer/dryrun/render/occurences.go
create mode 100644 command/analyzer/dryrun/render/render.go
create mode 100644 command/analyzer/dryrun/render/route.go
create mode 100644 command/analyzer/dryrun/render/types.go
create mode 100644 command/analyzer/dryrun/render/utils.go
create mode 100644 command/analyzer/dryrun/render/views/assets/cli.css
create mode 100644 command/analyzer/dryrun/render/views/index.html
create mode 100644 command/analyzer/dryrun/render/views/occurence.html
create mode 100644 types/constants.go
diff --git a/analysis/processor/processors/proc_source_code_load.go b/analysis/processor/processors/proc_source_code_load.go
index b6efdb4fc..7521e3763 100644
--- a/analysis/processor/processors/proc_source_code_load.go
+++ b/analysis/processor/processors/proc_source_code_load.go
@@ -148,8 +148,8 @@ func getFinalFormattedSlice(fileContentSlice []string, issue *types.Issue) forma
// We need to move the trailing span to the previous line in order for our replacement logic to work.
for i := range chromaHighlightedSlice {
- if i != 0 && !strings.HasPrefix(chromaHighlightedSlice[i], "") {
- lineStartIndex := strings.Index(chromaHighlightedSlice[i], "")
+ if i != 0 && !strings.HasPrefix(chromaHighlightedSlice[i], "") {
+ lineStartIndex := strings.Index(chromaHighlightedSlice[i], "")
if lineStartIndex != -1 {
chromaHighlightedSlice[i-1] += chromaHighlightedSlice[i][:lineStartIndex]
diff --git a/analyzers/backend/docker/container.go b/analyzers/backend/docker/container.go
index 250f17898..2ea5f4df0 100644
--- a/analyzers/backend/docker/container.go
+++ b/analyzers/backend/docker/container.go
@@ -20,6 +20,7 @@ import (
type AnalysisParams struct {
AnalyzerName string
+ AnalyzerShortcode string
HostCodePath string
HostToolBoxPath string
AnalysisCommand string
@@ -44,7 +45,6 @@ func (d *DockerClient) StartDockerContainer() error {
* - CMD instruction
* - Environment variables
* ========================================================== */
-
config := container.Config{
Image: fmt.Sprintf("%s:%s", d.ImageName, d.ImageTag),
Cmd: strings.Split(d.AnalysisOpts.AnalysisCommand, " "),
diff --git a/cmd/Dockerfile_new b/cmd/Dockerfile_new
deleted file mode 100644
index 611fc0609..000000000
--- a/cmd/Dockerfile_new
+++ /dev/null
@@ -1,2 +0,0 @@
-
-FROM alpine
diff --git a/command/analyzer/dryrun/client.go b/command/analyzer/dryrun/client.go
index 0a84f1c8b..d0ec39c82 100644
--- a/command/analyzer/dryrun/client.go
+++ b/command/analyzer/dryrun/client.go
@@ -34,6 +34,7 @@ func (a *AnalyzerDryRun) createDockerClient() error {
DockerfilePath: dockerFilePath,
AnalysisOpts: docker.AnalysisParams{
AnalyzerName: analyzerTOMLData.Name,
+ AnalyzerShortcode: analyzerTOMLData.Shortcode,
AnalysisCommand: analyzerTOMLData.Analysis.Command,
ContainerCodePath: containerCodePath,
ContainerToolBoxPath: containerToolBoxPath,
diff --git a/command/analyzer/dryrun/process.go b/command/analyzer/dryrun/process.go
index d688560fd..81a2b922e 100644
--- a/command/analyzer/dryrun/process.go
+++ b/command/analyzer/dryrun/process.go
@@ -11,23 +11,27 @@ import (
// processAnalyzerReport processes the analysis report generated by the Analyzer
func (a *AnalyzerDryRun) processAnalyzerReport(reportBytes []byte) (types.AnalysisResult, error) {
report := types.AnalyzerReport{}
+
+ // Creating instances of skipcq and source code highlighting processors
skipCQProcessor := processors.ProcSkipCQ{}
sourceCodeHighlightingProcessor := processors.ProcSourceCodeLoad{}
// Initializing the processors using the IProcessor interface provided by the `processor` package
var skip_cq, source_code_load processor.IProcessor
+
+ // Assigning the instances to the IProcessor interface
skip_cq = skipCQProcessor
source_code_load = sourceCodeHighlightingProcessor
+ // Start the processors workflow
processor := processor.ReportProcessor{
LocalSourcePath: a.SourcePath,
ContainerCodePath: a.Client.AnalysisOpts.ContainerCodePath,
- Processors: []processor.IProcessor{skip_cq, source_code_load},
+ Processors: []processor.IProcessor{source_code_load, skip_cq},
}
// Generate the silencers regexMap.
processors.GenerateSilencersRegexMap()
-
if err := json.Unmarshal(reportBytes, &report); err != nil {
return types.AnalysisResult{}, err
}
diff --git a/command/analyzer/dryrun/render/category.go b/command/analyzer/dryrun/render/category.go
new file mode 100644
index 000000000..82c6f573d
--- /dev/null
+++ b/command/analyzer/dryrun/render/category.go
@@ -0,0 +1,26 @@
+package render
+
+// fetchIssueCategoryData creates a map of issue category to issue occurences count of that category.
+func (r *ResultRenderOpts) fetchIssueCategoryData() {
+ // Iterate over the map and then keep adding the issue counts.
+ issueCategoryMap := make(map[string]int)
+
+ // Creating a map of issue categories present to their count.
+ for _, occurenceData := range r.AnalysisResultData.IssuesOccurenceMap {
+ if _, ok := issueCategoryMap[occurenceData.IssueMeta.Category]; !ok {
+ issueCategoryMap[occurenceData.IssueMeta.Category] = len(occurenceData.Occurences)
+ continue
+ }
+ issueCategoryMap[occurenceData.IssueMeta.Category] = issueCategoryMap[occurenceData.IssueMeta.Category] + len(occurenceData.Occurences)
+ }
+
+ // Add remaining categories to the map other than what are reported in the issues by the Analyzer since
+ // need to render all the categories.
+ for categoryShortcode := range r.IssueCategoryNameMap {
+ if _, ok := issueCategoryMap[categoryShortcode]; !ok {
+ issueCategoryMap[categoryShortcode] = 0
+ continue
+ }
+ }
+ r.AnalysisResultData.IssueCategoryCountMap = issueCategoryMap
+}
diff --git a/command/analyzer/dryrun/render/metrics.go b/command/analyzer/dryrun/render/metrics.go
new file mode 100644
index 000000000..25fcf9206
--- /dev/null
+++ b/command/analyzer/dryrun/render/metrics.go
@@ -0,0 +1,14 @@
+package render
+
+// fetchIssueMetricsData fetches the metrics data to be rendered.
+func (r *ResultRenderOpts) fetchIssueMetricsData() {
+ metricsMap := make(map[string]float64)
+ for _, metric := range r.AnalysisResultData.AnalysisResult.Metrics {
+ if _, ok := r.MetricNameMap[metric.MetricCode]; !ok {
+ continue
+ }
+ metricName := r.MetricNameMap[metric.MetricCode]
+ metricsMap[metricName] = metric.Namespaces[0].Value
+ }
+ r.AnalysisResultData.MetricsMap = metricsMap
+}
diff --git a/command/analyzer/dryrun/render/occurences.go b/command/analyzer/dryrun/render/occurences.go
new file mode 100644
index 000000000..554a75ac7
--- /dev/null
+++ b/command/analyzer/dryrun/render/occurences.go
@@ -0,0 +1,78 @@
+package render
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+)
+
+// fetchIssueOccurencesData collects all the occurence related data.
+func (r *ResultRenderOpts) fetchIssueOccurencesData(cwd string) {
+ // Create a map of occurences of the issues.
+ issueOccurenceMap := make(map[string]OccurenceData)
+
+ // Iterate over the analysis result issues.
+ for _, issue := range r.AnalysisResultData.AnalysisResult.Issues {
+ currentOccurence := OccurenceData{}
+
+ // Fix path of the issues(remove cwd prefix from them).
+ issue.Location.Path = strings.TrimPrefix(issue.Location.Path, filepath.Join(r.AnalysisResultData.SourcePath, string(filepath.Separator)))
+
+ if _, ok := issueOccurenceMap[issue.IssueCode]; !ok {
+ // Fetch issue meta for the issue code raised.
+ issueMeta, err := getIssueMeta(cwd, issue.IssueCode)
+ if err != nil {
+ fmt.Println("Couldn't resolve issue meta for the issue:", issue.IssueCode)
+ continue
+ }
+ currentOccurence = OccurenceData{
+ IssueMeta: issueMeta,
+ }
+ currentOccurence.Occurences = append(currentOccurence.Occurences, issue)
+ currentOccurence.Files = append(currentOccurence.Files, issue.Location.Path)
+ issueOccurenceMap[issue.IssueCode] = currentOccurence
+ continue
+ }
+
+ // Get past occurences and append to it since maps don't allow direct append to a slice value.
+ pastOccurences := issueOccurenceMap[issue.IssueCode]
+ currentOccurence.IssueMeta = pastOccurences.IssueMeta
+ currentOccurence.Occurences = append(pastOccurences.Occurences, issue)
+ currentOccurence.Files = append(pastOccurences.Files, issue.Location.Path)
+ issueOccurenceMap[issue.IssueCode] = currentOccurence
+ }
+
+ // Remove duplicates from the files array.
+ for issueCode, occurenceData := range issueOccurenceMap {
+ filesMap := make(map[string]int, 0)
+ uniqueFiles := make([]string, 0)
+
+ // Setting the map value to 1 for the files in order to identify unique files.
+ for _, file := range occurenceData.Files {
+ filesMap[file] = 1
+ }
+
+ // Appending the unique files.
+ for file := range filesMap {
+ uniqueFiles = append(uniqueFiles, file)
+ }
+ occurence := issueOccurenceMap[issueCode]
+ occurence.Files = append(occurence.Files, uniqueFiles...)
+ issueOccurenceMap[issueCode] = occurence
+ }
+
+ // Create the files information string.
+ for issueCode, occurenceData := range issueOccurenceMap {
+ occurenceData.FilesInfo = fmt.Sprintf("Found in %s and %d other file(s)", occurenceData.Files[0], len(occurenceData.Files)-1)
+ issueOccurenceMap[issueCode] = occurenceData
+ }
+ r.AnalysisResultData.IssuesOccurenceMap = issueOccurenceMap
+
+ // Find out total number of occurences of all the issues.
+ for _, v := range issueOccurenceMap {
+ r.AnalysisResultData.TotalOccurences = r.AnalysisResultData.TotalOccurences + len(v.Occurences)
+ }
+
+ // Finds the unique issues count(the length of the occurences map since its mapped by issue codes which are unique).
+ r.AnalysisResultData.UniqueIssuesCount = len(r.AnalysisResultData.IssuesOccurenceMap)
+}
diff --git a/command/analyzer/dryrun/render/render.go b/command/analyzer/dryrun/render/render.go
new file mode 100644
index 000000000..6eae9f60e
--- /dev/null
+++ b/command/analyzer/dryrun/render/render.go
@@ -0,0 +1,85 @@
+package render
+
+import (
+ "context"
+ "embed"
+ "fmt"
+ "html/template"
+ "io/fs"
+ "net/http"
+ "os"
+ "os/signal"
+ "time"
+
+ "github.com/cli/browser"
+ "github.com/pterm/pterm"
+)
+
+//go:embed views/*.html views/**/*.css
+var tmplFS embed.FS
+
+// renderResultsOnBrowser renders the results on the browser through a local server,
+// go template and an awesome frontend.
+func (r *ResultRenderOpts) RenderResultsOnBrowser(server IRenderServer) (err error) {
+ // Collect all other data to be rendered.
+ r.collectResultToBeRendered()
+
+ // In order to serve the static css files, this creates a handler to serve any static assets stored under
+ // `views/` at `/static/assets/*`.
+ fsys, err := fs.Sub(tmplFS, "views")
+ if err != nil {
+ return err
+ }
+
+ // Parse the HTML templates.
+ r.Template = template.Must(template.ParseFS(tmplFS, "views/*.html"))
+
+ // Define the routes using echo and start the server.
+ r.EchoServer = server.GetEchoContext()
+ server.DeclareRoutes(http.FS((fsys)))
+ serverPort := getServerPort()
+
+ // Spawn the server in a goroutine.
+ go func() {
+ if err := r.EchoServer.Start(fmt.Sprintf(":%s", serverPort)); err != nil && err != http.ErrServerClosed {
+ r.EchoServer.Logger.Fatal("Shutting down the server")
+ }
+ }()
+ pterm.Success.Printf("Analysis results live at http://localhost:%s..\n", serverPort)
+
+ // Having received the user code, open the browser at the localhost.
+ browser.OpenURL(fmt.Sprintf("http://localhost:%s", serverPort))
+
+ // Wait for interrupt signal to gracefully shutdown the server with a timeout of 10 seconds.
+ // Use a buffered channel to avoid missing signals as recommended for signal.Notify
+ quit := make(chan os.Signal, 1)
+ signal.Notify(quit, os.Interrupt)
+ <-quit
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ return r.EchoServer.Shutdown(ctx)
+}
+
+// collectResultToBeRendered formats all the result received after post-processing and then adds the
+// extra data required for rendering on the browser
+func (r *ResultRenderOpts) collectResultToBeRendered() {
+ cwd, _ := os.Getwd()
+
+ // Fetch the run summary data.
+ r.Summary.RunDuration, r.Summary.TimeSinceRun = fetchRunSummary(r.Summary.AnalysisStartTime, r.Summary.AnalysisEndTime)
+
+ // Inject the Analyzer VCS information.
+ r.VCSInfo.Branch, r.VCSInfo.CommitSHA = fetchVCSDetails(cwd)
+
+ // Fetch the data as to status of Analyzer w.r.t the latest version/tag.
+ r.VCSInfo.VersionDiff = fetchAnalyzerVCSData(cwd)
+
+ // Get occurence data.
+ r.fetchIssueOccurencesData(cwd)
+
+ // Get the category data.
+ r.fetchIssueCategoryData()
+
+ // Fetch metrics data.
+ r.fetchIssueMetricsData()
+}
diff --git a/command/analyzer/dryrun/render/route.go b/command/analyzer/dryrun/render/route.go
new file mode 100644
index 000000000..83ea1bf84
--- /dev/null
+++ b/command/analyzer/dryrun/render/route.go
@@ -0,0 +1,78 @@
+package render
+
+import (
+ "fmt"
+ "html/template"
+ "net/http"
+
+ "github.com/labstack/echo/v4"
+)
+
+type IRenderServer interface {
+ GetEchoContext() *echo.Echo
+ DeclareRoutes(http.FileSystem)
+}
+
+/* Declared Routes:
+ * /
+ * /issues
+ * /issue/{issue_code}/occurences
+ * /issues?category=all
+ * /issues?category={issue_category} */
+
+// getEchoContext returns a new Echo server instance.
+func (r *ResultRenderOpts) GetEchoContext() *echo.Echo {
+ e := echo.New()
+ e.HideBanner = true
+ return e
+}
+
+// declareRoutes declares routes for various incoming requests to the Analyzer dry run local server.
+func (r *ResultRenderOpts) DeclareRoutes(staticFS http.FileSystem) {
+ // Issues page containing all the reported issues.
+ r.EchoServer.GET("/", r.IssuesHandler)
+ r.EchoServer.GET("/issues", r.IssuesHandler)
+
+ // Handle serving static assets.
+ assetHandler := http.FileServer(staticFS)
+ r.EchoServer.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler)))
+
+ // Handle showing issues for a certain category.
+ r.EchoServer.GET("/issue/:issue_code/occurences", r.IssueOccurencesHandler)
+}
+
+// IssuesHandler handles serving the list of issues reported
+func (r *ResultRenderOpts) IssuesHandler(c echo.Context) error {
+ // Check URL query parameters
+ qParams := c.QueryParams()
+
+ if qParams.Has("category") {
+ r.SelectedCategory = qParams.Get("category")
+ } else {
+ r.SelectedCategory = "all"
+ }
+
+ err := r.Template.ExecuteTemplate(c.Response().Writer, "index.html", *r)
+ if err != nil {
+ fmt.Println(err)
+ return c.String(http.StatusOK, "Occurence page served.")
+ }
+ return c.String(http.StatusOK, "Issues page served.")
+}
+
+// IssuesOccurencesHandler handles serving the issue occurences.
+func (r *ResultRenderOpts) IssueOccurencesHandler(c echo.Context) error {
+ // Fetch the issue code from URI.
+ r.SelectedIssueCode = c.Param("issue_code")
+
+ issueOccurences := r.AnalysisResultData.IssuesOccurenceMap[r.SelectedIssueCode]
+ for _, occurence := range issueOccurences.Occurences {
+ r.AnalysisResultData.RenderedSourceCode = append(r.AnalysisResultData.RenderedSourceCode, template.HTML(occurence.ProcessedData.SourceCode.Rendered)) // skipcq: GSC-G203
+ }
+ err := r.Template.ExecuteTemplate(c.Response().Writer, "occurence.html", *r)
+ if err != nil {
+ fmt.Println(err)
+ return c.String(http.StatusOK, "Occurence page served.")
+ }
+ return c.String(http.StatusOK, "Occurence page served.")
+}
diff --git a/command/analyzer/dryrun/render/types.go b/command/analyzer/dryrun/render/types.go
new file mode 100644
index 000000000..e6340fb92
--- /dev/null
+++ b/command/analyzer/dryrun/render/types.go
@@ -0,0 +1,54 @@
+package render
+
+import (
+ "html/template"
+ "time"
+
+ "github.com/deepsourcelabs/cli/types"
+ "github.com/labstack/echo/v4"
+)
+
+type RunSummary struct {
+ RunDuration string // Time taken to complete analysis.
+ TimeSinceRun string // Time elapsed since the completion of the analysis run.
+ AnalysisStartTime time.Time
+ AnalysisEndTime time.Time
+}
+
+type VCSInfo struct {
+ Branch string // VCS branch of the Analyzer.
+ CommitSHA string // The latest commit SHA of the Analyzer.
+ VersionDiff string // The string specifying the status of Analyzer w.r.t previous version.
+}
+
+type OccurenceData struct {
+ IssueMeta types.AnalyzerIssue // Contains the data stored in issue TOMLs for the respective issue.
+ Files []string // Files where this issue has been reported.
+ FilesInfo string // The string containing the data of which files the issue has been reported in.
+ Occurences []types.Issue // The slice of occurences for a certain issue code.
+}
+
+type ResultData struct {
+ UniqueIssuesCount int // The unique issues count.
+ TotalOccurences int // Total issues reported by the Analyzer.
+ SourcePath string // The path where the source code to be analyzer is stored.
+ IssuesOccurenceMap map[string]OccurenceData // The map of issue code to its occurences data.
+ IssueCategoryCountMap map[string]int // The map of issue category to the count of the issues of that category.
+ AnalysisResult types.AnalysisResult // The analysis result post running processors.
+ MetricsMap map[string]float64 // The map of metric names to their values.
+ RenderedSourceCode []template.HTML // The slice containing the source code snippets for each occurence.
+}
+
+type ResultRenderOpts struct {
+ EchoServer *echo.Echo // The Echo server instance to run the renderer server.
+ Template *template.Template // The go template field so that it can be accessible in `route.go` as well.
+ PageTitle string // The title of the HTML page.
+ AnalyzerShortcode string // The shortcode of the Analyzer.
+ VCSInfo VCSInfo // The VCS information of the Analyzer.
+ Summary RunSummary // The run summary.
+ AnalysisResultData ResultData // The analysis result data.
+ SelectedIssueCode string // The field used to recognize which issue code the user has clicked on to check its occurences.
+ SelectedCategory string // The field used to recognize which category the user has clicked to filter the issues based on it.
+ IssueCategoryNameMap map[string]string // The map used to route category names to their codes. Eg: `Documentation`->`doc`.
+ MetricNameMap map[string]string // The map of metrics shortcodes with their names.
+}
diff --git a/command/analyzer/dryrun/render/utils.go b/command/analyzer/dryrun/render/utils.go
new file mode 100644
index 000000000..06cc42156
--- /dev/null
+++ b/command/analyzer/dryrun/render/utils.go
@@ -0,0 +1,201 @@
+package render
+
+import (
+ "fmt"
+ "net"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/deepsourcelabs/cli/types"
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/go-git/go-git/v5/plumbing/object"
+ "github.com/hako/durafmt"
+ "github.com/pelletier/go-toml/v2"
+)
+
+// fetchRunSummary fetches the data for the run summary section involving the time since latest run
+// and the run duration.
+func fetchRunSummary(startTime, endTime time.Time) (string, string) {
+ // Find the time elapsed since the analysis run.
+ timeSinceRun := fmt.Sprintf("%s ago", durafmt.Parse(time.Since(startTime)).LimitFirstN(1).String())
+
+ // Find the run duration i.e. the time between the analysis start and end time.
+ runDuration := durafmt.Parse(endTime.Sub(startTime)).LimitFirstN(1).String()
+ return runDuration, timeSinceRun
+}
+
+// fetchHeadManually fetches the latest commit hash using the command `git rev-parse HEAD`
+// through go-git.
+func fetchHeadManually(directoryPath string) (string, error) {
+ gitOpts := &git.PlainOpenOptions{
+ DetectDotGit: true,
+ }
+
+ // Open a new repository targeting the given path (the .git folder)
+ repo, err := git.PlainOpenWithOptions(directoryPath, gitOpts)
+ if err != nil {
+ return "", err
+ }
+
+ // Resolve revision into a sha1 commit
+ commitHash, err := repo.ResolveRevision(plumbing.Revision("HEAD"))
+ if err != nil {
+ return "", err
+ }
+ return commitHash.String(), nil
+}
+
+// fetchVCSDetails fetches the VCS details to be shown on the dashboard.
+func fetchVCSDetails(dir string) (string, string) {
+ branch := ""
+ latestCommitHash := ""
+
+ repo, err := git.PlainOpen(dir)
+ if err != nil {
+ return "", ""
+ }
+
+ // Fetch the repository HEAD reference.
+ headRef, _ := repo.Head()
+
+ // Fetch the commit SHA of the latest commit
+ latestCommitHash, _ = fetchHeadManually(dir)
+
+ // Fetch the branch name.
+ branchData := headRef.String()
+ branch = branchData[strings.LastIndex(branchData, "/")+1:]
+
+ return branch, latestCommitHash[:7]
+}
+
+// fetchAnalyzerVCSDetails fetches Analyzer VCS details like how many commits is the Analyzer
+// ahead of the latest git tag.
+func fetchAnalyzerVCSData(dir string) string {
+ // Open the Analyzer's git directory.
+ repo, err := git.PlainOpenWithOptions(dir, &git.PlainOpenOptions{
+ DetectDotGit: true,
+ })
+ if err != nil {
+ fmt.Println(err)
+ return ""
+ }
+
+ // Fetch the repo tags list.
+ tagReferences, _ := repo.Tags()
+ currentTagRef := []string{}
+ if err = tagReferences.ForEach(func(t *plumbing.Reference) error {
+ currentTagRef = append(currentTagRef, t.Name().String())
+ return nil
+ }); err != nil {
+ fmt.Println(err)
+ return ""
+ }
+
+ // currentTagRef slice is empty if there are not tags in the Analyzer git directory.
+ if len(currentTagRef) == 0 {
+ return ""
+ }
+
+ // Convert refs/tags/v0.2.1 -> v0.2.1
+ latestTag := strings.TrimPrefix(currentTagRef[len(currentTagRef)-1], "refs/tags/")
+
+ // Fetch the iterator to the tag objects latest git tag.
+ tagsIter, _ := repo.TagObjects()
+
+ // Fetch the current tag and the commit pointed by the current tag.
+ currentTag := ""
+ var currentCommitSHA plumbing.Hash
+ var currentTagPushTime time.Time
+ if err = tagsIter.ForEach(func(t *object.Tag) (err error) {
+ if t.Name != latestTag {
+ return nil
+ }
+ currentTag = t.Name
+ commit, err := t.Commit()
+ if err != nil {
+ fmt.Println(err)
+ return err
+ }
+
+ // Finds the hash of the commit and the timestamp of when the commit was pushed.
+ currentCommitSHA = commit.Hash
+ currentTagPushTime = commit.Author.When
+ return nil
+ }); err != nil {
+ fmt.Println(err)
+ return ""
+ }
+
+ // Retrieve the commit history from the current tag.
+ commitIter, err := repo.Log(&git.LogOptions{
+ Order: git.LogOrderCommitterTime,
+ Since: ¤tTagPushTime,
+ })
+ if err != nil {
+ fmt.Println(err)
+ return ""
+ }
+
+ // Just iterates over the commits and finds the count of how many commits have been
+ // made since the current git tag.
+ commitsSinceCurrentTag := 0
+ if err = commitIter.ForEach(func(c *object.Commit) error {
+ if c.Hash == currentCommitSHA {
+ return nil
+ }
+ commitsSinceCurrentTag++
+ return nil
+ }); err != nil {
+ fmt.Println(err)
+ return ""
+ }
+
+ if commitsSinceCurrentTag == 0 {
+ return fmt.Sprintf("This Analyzer is up to date with %s", currentTag)
+ }
+ return fmt.Sprintf("This Analyzer is %d commits ahead of %s", commitsSinceCurrentTag, currentTag)
+}
+
+// getServerPort returns the port used to render the server.
+func getServerPort() string {
+ serverPort := ":8080"
+
+ // Check if the default port(8080) is available.
+ listener, err := net.Listen("tcp", serverPort)
+ if err == nil {
+ // Close the listener if it starts to listen on the default port.
+ listener.Close()
+ return strings.TrimPrefix(serverPort, ":")
+ }
+
+ // If the port is busy, get a new port.
+ listener, _ = net.Listen("tcp", ":0")
+ // Close the listener if it starts to listen on the default port.
+ serverPort = strings.TrimPrefix(listener.Addr().String(), "[::]:")
+ listener.Close()
+ return serverPort
+}
+
+// getIssueMeta receives the issuecode that is raised and it reads the TOML of that issue and returns
+// its details configured in the TOML like title, description and category.
+func getIssueMeta(cwd, issueCode string) (types.AnalyzerIssue, error) {
+ analyzerIssue := types.AnalyzerIssue{}
+ // Read the toml file of the issue in .deepsource/analyzer/issues directory
+ issueFilePath := filepath.Join(cwd, ".deepsource/analyzer/issues", fmt.Sprintf("%s.toml", issueCode))
+
+ // Read the issue and populate the data of issue category and description
+ issueData, err := os.ReadFile(issueFilePath)
+ if err != nil {
+ return analyzerIssue, err
+ }
+
+ // Unmarshal the data from the issue TOMLs into the struct
+ err = toml.Unmarshal(issueData, &analyzerIssue)
+ if err != nil {
+ return analyzerIssue, err
+ }
+ return analyzerIssue, nil
+}
diff --git a/command/analyzer/dryrun/render/views/assets/cli.css b/command/analyzer/dryrun/render/views/assets/cli.css
new file mode 100644
index 000000000..49345c10b
--- /dev/null
+++ b/command/analyzer/dryrun/render/views/assets/cli.css
@@ -0,0 +1,1169 @@
+/*
+! tailwindcss v3.1.4 | MIT License | https://tailwindcss.com
+*/
+
+/*
+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
+*/
+
+*,
+::before,
+::after {
+ box-sizing: border-box;
+ /* 1 */
+ border-width: 0;
+ /* 2 */
+ border-style: solid;
+ /* 2 */
+ border-color: currentColor;
+ /* 2 */
+}
+
+::before,
+::after {
+ --tw-content: '';
+}
+
+/*
+1. Use a consistent sensible line-height in all browsers.
+2. Prevent adjustments of font size after orientation changes in iOS.
+3. Use a more readable tab size.
+4. Use the user's configured `sans` font-family by default.
+*/
+
+html {
+ line-height: 1.5;
+ /* 1 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */
+ -moz-tab-size: 4;
+ /* 3 */
+ -o-tab-size: 4;
+ tab-size: 4;
+ /* 3 */
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ /* 4 */
+}
+
+/*
+1. Remove the margin in all browsers.
+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
+*/
+
+body {
+ margin: 0;
+ /* 1 */
+ line-height: inherit;
+ /* 2 */
+}
+
+/*
+1. Add the correct height in Firefox.
+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
+3. Ensure horizontal rules are visible by default.
+*/
+
+hr {
+ height: 0;
+ /* 1 */
+ color: inherit;
+ /* 2 */
+ border-top-width: 1px;
+ /* 3 */
+}
+
+/*
+Add the correct text decoration in Chrome, Edge, and Safari.
+*/
+
+abbr:where([title]) {
+ -webkit-text-decoration: underline dotted;
+ text-decoration: underline dotted;
+}
+
+/*
+Remove the default font size and weight for headings.
+*/
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-size: inherit;
+ font-weight: inherit;
+}
+
+/*
+Reset links to optimize for opt-in styling instead of opt-out.
+*/
+
+a {
+ color: inherit;
+ text-decoration: inherit;
+}
+
+/*
+Add the correct font weight in Edge and Safari.
+*/
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/*
+1. Use the user's configured `mono` font family by default.
+2. Correct the odd `em` font sizing in all browsers.
+*/
+
+code,
+kbd,
+samp,
+pre {
+ font-family: ui-monospace, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ /* 1 */
+ font-size: 1em;
+ /* 2 */
+}
+
+/*
+Add the correct font size in all browsers.
+*/
+
+small {
+ font-size: 80%;
+}
+
+/*
+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
+*/
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/*
+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
+3. Remove gaps between table borders by default.
+*/
+
+table {
+ text-indent: 0;
+ /* 1 */
+ border-color: inherit;
+ /* 2 */
+ border-collapse: collapse;
+ /* 3 */
+}
+
+/*
+1. Change the font styles in all browsers.
+2. Remove the margin in Firefox and Safari.
+3. Remove default padding in all browsers.
+*/
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit;
+ /* 1 */
+ font-size: 100%;
+ /* 1 */
+ font-weight: inherit;
+ /* 1 */
+ line-height: inherit;
+ /* 1 */
+ color: inherit;
+ /* 1 */
+ margin: 0;
+ /* 2 */
+ padding: 0;
+ /* 3 */
+}
+
+/*
+Remove the inheritance of text transform in Edge and Firefox.
+*/
+
+button,
+select {
+ text-transform: none;
+}
+
+/*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Remove default button styles.
+*/
+
+button,
+[type='button'],
+[type='reset'],
+[type='submit'] {
+ -webkit-appearance: button;
+ /* 1 */
+ background-color: transparent;
+ /* 2 */
+ background-image: none;
+ /* 2 */
+}
+
+/*
+Use the modern Firefox focus style for all focusable elements.
+*/
+
+:-moz-focusring {
+ outline: auto;
+}
+
+/*
+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
+*/
+
+:-moz-ui-invalid {
+ box-shadow: none;
+}
+
+/*
+Add the correct vertical alignment in Chrome and Firefox.
+*/
+
+progress {
+ vertical-align: baseline;
+}
+
+/*
+Correct the cursor style of increment and decrement buttons in Safari.
+*/
+
+::-webkit-inner-spin-button,
+::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/*
+1. Correct the odd appearance in Chrome and Safari.
+2. Correct the outline style in Safari.
+*/
+
+[type='search'] {
+ -webkit-appearance: textfield;
+ /* 1 */
+ outline-offset: -2px;
+ /* 2 */
+}
+
+/*
+Remove the inner padding in Chrome and Safari on macOS.
+*/
+
+::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Change font properties to `inherit` in Safari.
+*/
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ /* 1 */
+ font: inherit;
+ /* 2 */
+}
+
+/*
+Add the correct display in Chrome and Safari.
+*/
+
+summary {
+ display: list-item;
+}
+
+/*
+Removes the default spacing and border for appropriate elements.
+*/
+
+blockquote,
+dl,
+dd,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+hr,
+figure,
+p,
+pre {
+ margin: 0;
+}
+
+fieldset {
+ margin: 0;
+ padding: 0;
+}
+
+legend {
+ padding: 0;
+}
+
+ol,
+ul,
+menu {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+/*
+Prevent resizing textareas horizontally by default.
+*/
+
+textarea {
+ resize: vertical;
+}
+
+/*
+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
+2. Set the default placeholder color to the user's configured gray 400 color.
+*/
+
+input::-moz-placeholder, textarea::-moz-placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+input:-ms-input-placeholder, textarea:-ms-input-placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+input::placeholder,
+textarea::placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+/*
+Set the default cursor for buttons.
+*/
+
+button,
+[role="button"] {
+ cursor: pointer;
+}
+
+/*
+Make sure disabled buttons don't get the pointer cursor.
+*/
+
+:disabled {
+ cursor: default;
+}
+
+/*
+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
+ This can trigger a poorly considered lint error in some tools but is included by design.
+*/
+
+img,
+svg,
+video,
+canvas,
+audio,
+iframe,
+embed,
+object {
+ display: block;
+ /* 1 */
+ vertical-align: middle;
+ /* 2 */
+}
+
+/*
+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
+*/
+
+img,
+video {
+ max-width: 100%;
+ height: auto;
+}
+
+*, ::before, ::after {
+ --tw-border-spacing-x: 0;
+ --tw-border-spacing-y: 0;
+ --tw-translate-x: 0;
+ --tw-translate-y: 0;
+ --tw-rotate: 0;
+ --tw-skew-x: 0;
+ --tw-skew-y: 0;
+ --tw-scale-x: 1;
+ --tw-scale-y: 1;
+ --tw-pan-x: ;
+ --tw-pan-y: ;
+ --tw-pinch-zoom: ;
+ --tw-scroll-snap-strictness: proximity;
+ --tw-ordinal: ;
+ --tw-slashed-zero: ;
+ --tw-numeric-figure: ;
+ --tw-numeric-spacing: ;
+ --tw-numeric-fraction: ;
+ --tw-ring-inset: ;
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: rgb(59 130 246 / 0.5);
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+ --tw-shadow: 0 0 #0000;
+ --tw-shadow-colored: 0 0 #0000;
+ --tw-blur: ;
+ --tw-brightness: ;
+ --tw-contrast: ;
+ --tw-grayscale: ;
+ --tw-hue-rotate: ;
+ --tw-invert: ;
+ --tw-saturate: ;
+ --tw-sepia: ;
+ --tw-drop-shadow: ;
+ --tw-backdrop-blur: ;
+ --tw-backdrop-brightness: ;
+ --tw-backdrop-contrast: ;
+ --tw-backdrop-grayscale: ;
+ --tw-backdrop-hue-rotate: ;
+ --tw-backdrop-invert: ;
+ --tw-backdrop-opacity: ;
+ --tw-backdrop-saturate: ;
+ --tw-backdrop-sepia: ;
+}
+
+::-webkit-backdrop {
+ --tw-border-spacing-x: 0;
+ --tw-border-spacing-y: 0;
+ --tw-translate-x: 0;
+ --tw-translate-y: 0;
+ --tw-rotate: 0;
+ --tw-skew-x: 0;
+ --tw-skew-y: 0;
+ --tw-scale-x: 1;
+ --tw-scale-y: 1;
+ --tw-pan-x: ;
+ --tw-pan-y: ;
+ --tw-pinch-zoom: ;
+ --tw-scroll-snap-strictness: proximity;
+ --tw-ordinal: ;
+ --tw-slashed-zero: ;
+ --tw-numeric-figure: ;
+ --tw-numeric-spacing: ;
+ --tw-numeric-fraction: ;
+ --tw-ring-inset: ;
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: rgb(59 130 246 / 0.5);
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+ --tw-shadow: 0 0 #0000;
+ --tw-shadow-colored: 0 0 #0000;
+ --tw-blur: ;
+ --tw-brightness: ;
+ --tw-contrast: ;
+ --tw-grayscale: ;
+ --tw-hue-rotate: ;
+ --tw-invert: ;
+ --tw-saturate: ;
+ --tw-sepia: ;
+ --tw-drop-shadow: ;
+ --tw-backdrop-blur: ;
+ --tw-backdrop-brightness: ;
+ --tw-backdrop-contrast: ;
+ --tw-backdrop-grayscale: ;
+ --tw-backdrop-hue-rotate: ;
+ --tw-backdrop-invert: ;
+ --tw-backdrop-opacity: ;
+ --tw-backdrop-saturate: ;
+ --tw-backdrop-sepia: ;
+}
+
+::backdrop {
+ --tw-border-spacing-x: 0;
+ --tw-border-spacing-y: 0;
+ --tw-translate-x: 0;
+ --tw-translate-y: 0;
+ --tw-rotate: 0;
+ --tw-skew-x: 0;
+ --tw-skew-y: 0;
+ --tw-scale-x: 1;
+ --tw-scale-y: 1;
+ --tw-pan-x: ;
+ --tw-pan-y: ;
+ --tw-pinch-zoom: ;
+ --tw-scroll-snap-strictness: proximity;
+ --tw-ordinal: ;
+ --tw-slashed-zero: ;
+ --tw-numeric-figure: ;
+ --tw-numeric-spacing: ;
+ --tw-numeric-fraction: ;
+ --tw-ring-inset: ;
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: rgb(59 130 246 / 0.5);
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+ --tw-shadow: 0 0 #0000;
+ --tw-shadow-colored: 0 0 #0000;
+ --tw-blur: ;
+ --tw-brightness: ;
+ --tw-contrast: ;
+ --tw-grayscale: ;
+ --tw-hue-rotate: ;
+ --tw-invert: ;
+ --tw-saturate: ;
+ --tw-sepia: ;
+ --tw-drop-shadow: ;
+ --tw-backdrop-blur: ;
+ --tw-backdrop-brightness: ;
+ --tw-backdrop-contrast: ;
+ --tw-backdrop-grayscale: ;
+ --tw-backdrop-hue-rotate: ;
+ --tw-backdrop-invert: ;
+ --tw-backdrop-opacity: ;
+ --tw-backdrop-saturate: ;
+ --tw-backdrop-sepia: ;
+}
+
+.absolute {
+ position: absolute;
+}
+
+.relative {
+ position: relative;
+}
+
+.sticky {
+ position: -webkit-sticky;
+ position: sticky;
+}
+
+.top-0 {
+ top: 0px;
+}
+
+.top-2 {
+ top: 0.5rem;
+}
+
+.top-1\.5 {
+ top: 0.375rem;
+}
+
+.left-1\.5 {
+ left: 0.375rem;
+}
+
+.top-1 {
+ top: 0.25rem;
+}
+
+.left-1 {
+ left: 0.25rem;
+}
+
+.left-2 {
+ left: 0.5rem;
+}
+
+.z-20 {
+ z-index: 20;
+}
+
+.col-span-2 {
+ grid-column: span 2 / span 2;
+}
+
+.row-span-2 {
+ grid-row: span 2 / span 2;
+}
+
+.mr-4 {
+ margin-right: 1rem;
+}
+
+.mr-1 {
+ margin-right: 0.25rem;
+}
+
+.mb-3 {
+ margin-bottom: 0.75rem;
+}
+
+.block {
+ display: block;
+}
+
+.inline {
+ display: inline;
+}
+
+.flex {
+ display: flex;
+}
+
+.grid {
+ display: grid;
+}
+
+.hidden {
+ display: none;
+}
+
+.h-12 {
+ height: 3rem;
+}
+
+.h-full {
+ height: 100%;
+}
+
+.h-3 {
+ height: 0.75rem;
+}
+
+.h-8 {
+ height: 2rem;
+}
+
+.min-h-screen {
+ min-height: 100vh;
+}
+
+.w-28 {
+ width: 7rem;
+}
+
+.w-full {
+ width: 100%;
+}
+
+.w-3 {
+ width: 0.75rem;
+}
+
+.max-w-2xl {
+ max-width: 42rem;
+}
+
+.flex-1 {
+ flex: 1 1 0%;
+}
+
+.flex-shrink-0 {
+ flex-shrink: 0;
+}
+
+.flex-grow {
+ flex-grow: 1;
+}
+
+.cursor-pointer {
+ cursor: pointer;
+}
+
+.auto-rows-min {
+ grid-auto-rows: -webkit-min-content;
+ grid-auto-rows: min-content;
+}
+
+.grid-cols-\[48px_1fr\] {
+ grid-template-columns: 48px 1fr;
+}
+
+.grid-cols-\[18rem_1fr_22rem\] {
+ grid-template-columns: 18rem 1fr 22rem;
+}
+
+.grid-cols-1 {
+ grid-template-columns: repeat(1, minmax(0, 1fr));
+}
+
+.flex-col {
+ flex-direction: column;
+}
+
+.flex-wrap {
+ flex-wrap: wrap;
+}
+
+.place-content-center {
+ place-content: center;
+}
+
+.items-center {
+ align-items: center;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.gap-1 {
+ gap: 0.25rem;
+}
+
+.gap-5 {
+ gap: 1.25rem;
+}
+
+.gap-2\.5 {
+ gap: 0.625rem;
+}
+
+.gap-2 {
+ gap: 0.5rem;
+}
+
+.gap-4 {
+ gap: 1rem;
+}
+
+.gap-x-4 {
+ -moz-column-gap: 1rem;
+ column-gap: 1rem;
+}
+
+.gap-y-2\.5 {
+ row-gap: 0.625rem;
+}
+
+.gap-y-2 {
+ row-gap: 0.5rem;
+}
+
+.gap-x-2 {
+ -moz-column-gap: 0.5rem;
+ column-gap: 0.5rem;
+}
+
+.space-y-1 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-y-reverse: 0;
+ margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
+ margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
+}
+
+.space-x-2 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(0.5rem * var(--tw-space-x-reverse));
+ margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
+}
+
+.space-y-4 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-y-reverse: 0;
+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
+}
+
+.divide-x > :not([hidden]) ~ :not([hidden]) {
+ --tw-divide-x-reverse: 0;
+ border-right-width: calc(1px * var(--tw-divide-x-reverse));
+ border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));
+}
+
+.divide-ink-200 > :not([hidden]) ~ :not([hidden]) {
+ --tw-divide-opacity: 1;
+ border-color: rgb(35 38 46 / var(--tw-divide-opacity));
+}
+
+.overflow-hidden {
+ overflow: hidden;
+}
+
+.overflow-ellipsis {
+ text-overflow: ellipsis;
+}
+
+.whitespace-nowrap {
+ white-space: nowrap;
+}
+
+.whitespace-pre {
+ white-space: pre;
+}
+
+.rounded-sm {
+ border-radius: 0.125rem;
+}
+
+.rounded-lg {
+ border-radius: 0.5rem;
+}
+
+.rounded-md {
+ border-radius: 0.375rem;
+}
+
+.border {
+ border-width: 1px;
+}
+
+.border-b {
+ border-bottom-width: 1px;
+}
+
+.border-ink-200 {
+ --tw-border-opacity: 1;
+ border-color: rgb(35 38 46 / var(--tw-border-opacity));
+}
+
+.border-ink-300 {
+ --tw-border-opacity: 1;
+ border-color: rgb(26 29 35 / var(--tw-border-opacity));
+}
+
+.bg-ink-400 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(22 24 29 / var(--tw-bg-opacity));
+}
+
+.bg-ink-200 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(35 38 46 / var(--tw-bg-opacity));
+}
+
+.bg-ink-300 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(26 29 35 / var(--tw-bg-opacity));
+}
+
+.bg-ink-100 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(42 46 55 / var(--tw-bg-opacity));
+}
+
+.stroke-current {
+ stroke: currentColor;
+}
+
+.stroke-1 {
+ stroke-width: 1;
+}
+
+.p-6 {
+ padding: 1.5rem;
+}
+
+.p-4 {
+ padding: 1rem;
+}
+
+.p-3 {
+ padding: 0.75rem;
+}
+
+.p-2 {
+ padding: 0.5rem;
+}
+
+.py-2 {
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+}
+
+.px-6 {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+}
+
+.px-4 {
+ padding-left: 1rem;
+ padding-right: 1rem;
+}
+
+.py-4 {
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+}
+
+.px-2 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+
+.pt-5 {
+ padding-top: 1.25rem;
+}
+
+.pl-5 {
+ padding-left: 1.25rem;
+}
+
+.pl-8 {
+ padding-left: 2rem;
+}
+
+.pl-9 {
+ padding-left: 2.25rem;
+}
+
+.text-sm {
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+}
+
+.text-lg {
+ font-size: 1.125rem;
+ line-height: 1.75rem;
+}
+
+.text-xs {
+ font-size: 0.75rem;
+ line-height: 1rem;
+}
+
+.text-2xl {
+ font-size: 1.5rem;
+ line-height: 2rem;
+}
+
+.font-medium {
+ font-weight: 500;
+}
+
+.font-semibold {
+ font-weight: 600;
+}
+
+.font-normal {
+ font-weight: 400;
+}
+
+.uppercase {
+ text-transform: uppercase;
+}
+
+.leading-tight {
+ line-height: 1.25;
+}
+
+.leading-none {
+ line-height: 1;
+}
+
+.leading-10 {
+ line-height: 2.5rem;
+}
+
+.tracking-wide {
+ letter-spacing: 0.025em;
+}
+
+.tracking-wider {
+ letter-spacing: 0.05em;
+}
+
+.text-vanilla-100 {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
+.text-vanilla-400 {
+ --tw-text-opacity: 1;
+ color: rgb(192 193 195 / var(--tw-text-opacity));
+}
+
+.text-vanilla-200 {
+ --tw-text-opacity: 1;
+ color: rgb(245 245 245 / var(--tw-text-opacity));
+}
+
+.text-ink-200 {
+ --tw-text-opacity: 1;
+ color: rgb(35 38 46 / var(--tw-text-opacity));
+}
+
+.text-ink-50 {
+ --tw-text-opacity: 1;
+ color: rgb(48 53 64 / var(--tw-text-opacity));
+}
+
+.text-vanilla-300 {
+ --tw-text-opacity: 1;
+ color: rgb(238 238 238 / var(--tw-text-opacity));
+}
+
+.button {
+ display: flex;
+ height: 100%;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.125rem;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 0.75rem;
+ line-height: 1rem;
+}
+
+.sidebar {
+ display: flex;
+ height: 2rem;
+ width: 100%;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.125rem;
+ padding: 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ --tw-text-opacity: 1;
+ color: rgb(192 193 195 / var(--tw-text-opacity));
+}
+
+.sidebar:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(35 38 46 / var(--tw-bg-opacity));
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
+.sidebar.selected {
+ display: flex;
+ height: 100%;
+ width: 100%;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.125rem;
+ --tw-bg-opacity: 1;
+ background-color: rgb(26 29 35 / var(--tw-bg-opacity));
+ padding: 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
+.sidebar.selected:hover {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
+.sidebar .tag {
+ justify-self: end;
+ border-radius: 9999px;
+ --tw-bg-opacity: 1;
+ background-color: rgb(35 38 46 / var(--tw-bg-opacity));
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ font-size: 0.75rem;
+ line-height: 1rem;
+ line-height: 1;
+}
+
+.sidebar .label {
+ flex-grow: 1;
+ text-align: left;
+ line-height: 1;
+}
+
+.info {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ --tw-text-opacity: 1;
+ color: rgb(192 193 195 / var(--tw-text-opacity));
+}
+
+.hover\:bg-ink-100:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(42 46 55 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-ink-300:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(26 29 35 / var(--tw-bg-opacity));
+}
+
+.focus\:outline-none:focus {
+ outline: 2px solid transparent;
+ outline-offset: 2px;
+}
+
+.group:hover .group-hover\:border-ink-200 {
+ --tw-border-opacity: 1;
+ border-color: rgb(35 38 46 / var(--tw-border-opacity));
+}
+
+@media (min-width: 640px) {
+ .sm\:flex {
+ display: flex;
+ }
+
+ .sm\:border-l {
+ border-left-width: 1px;
+ }
+}
+
+@media (min-width: 768px) {
+ .md\:mr-2 {
+ margin-right: 0.5rem;
+ }
+
+ .md\:block {
+ display: block;
+ }
+
+ .md\:w-4\/5 {
+ width: 80%;
+ }
+
+ .md\:w-1\/5 {
+ width: 20%;
+ }
+
+ .md\:flex-row {
+ flex-direction: row;
+ }
+
+ .md\:flex-wrap {
+ flex-wrap: wrap;
+ }
+}
+
+@media (min-width: 1024px) {
+ .lg\:gap-y-2 {
+ row-gap: 0.5rem;
+ }
+}
diff --git a/command/analyzer/dryrun/render/views/index.html b/command/analyzer/dryrun/render/views/index.html
new file mode 100644
index 000000000..1934307a5
--- /dev/null
+++ b/command/analyzer/dryrun/render/views/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+ {{ .PageTitle }}
+
+
+
+
+