Skip to content

Commit

Permalink
🐛 Support *, qodana.yaml, qodana.yml names
Browse files Browse the repository at this point in the history
  • Loading branch information
tiulpin committed Jun 24, 2022
1 parent b41d78f commit 8021b52
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 63 deletions.
40 changes: 24 additions & 16 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ func isGitHubAction() bool {
return os.Getenv("GITHUB_ACTIONS") == "true"
}

func createPythonProject(t *testing.T, name string) string {
location := "/tmp/" + name
err := os.MkdirAll(location, 0o755)
if err != nil {
t.Fatal(err)
}
err = ioutil.WriteFile(location+"/hello.py", []byte("print(\"Hello\")"), 0o755)
if err != nil {
t.Fatal(err)
}
return location
}

// TestVersion verifies that the version command returns the correct version
func TestVersion(t *testing.T) {
b := bytes.NewBufferString("")
Expand Down Expand Up @@ -119,12 +132,8 @@ func TestHelp(t *testing.T) {
}

func TestInitCommand(t *testing.T) {
projectPath := "/tmp/qodana_init"
err := os.MkdirAll(projectPath, 0o755)
if err != nil {
t.Fatal(err)
}
err = ioutil.WriteFile("/tmp/qodana_init/hello.py", []byte("print(\"Hello\")"), 0o755)
projectPath := createPythonProject(t, "qodana_init")
err := ioutil.WriteFile(projectPath+"/qodana.yml", []byte("version: 1.0"), 0o755)
if err != nil {
t.Fatal(err)
}
Expand All @@ -137,7 +146,13 @@ func TestInitCommand(t *testing.T) {
t.Fatal(err)
}

qodanaYaml := core.LoadQodanaYaml(projectPath)
filename := core.FindQodanaYaml(projectPath)

if filename != "qodana.yml" {
t.Fatalf("expected \"qodana.yml\" got \"%s\"", filename)
}

qodanaYaml := core.LoadQodanaYaml(projectPath, filename)

if qodanaYaml.Linter != core.QDPY {
t.Fatalf("expected \"%s\", but got %s", core.QDPY, qodanaYaml.Linter)
Expand Down Expand Up @@ -189,15 +204,8 @@ func TestAllCommands(t *testing.T) {
if err != nil {
t.Fatal(err)
}
projectPath := "/tmp/qodana_scan"
err = os.MkdirAll(projectPath, 0o755)
if err != nil {
t.Fatal(err)
}
err = ioutil.WriteFile(filepath.Join(projectPath, "hello.py"), []byte("println(\"Hello\")\n123"), 0o755)
if err != nil {
t.Fatal(err)
}

projectPath := createPythonProject(t, "qodana_scan")

// pull
out := bytes.NewBufferString("")
Expand Down
11 changes: 8 additions & 3 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
type InitOptions struct {
ProjectDir string
Force bool
YamlName string
}

// NewInitCommand returns a new instance of the show command.
Expand All @@ -35,18 +36,22 @@ func NewInitCommand() *cobra.Command {
Short: "Configure a project for Qodana",
Long: `Configure a project for Qodana: prepare Qodana configuration file by analyzing the project structure and generating a default configuration qodana.yaml file.`,
Run: func(cmd *cobra.Command, args []string) {
qodanaYaml := core.LoadQodanaYaml(options.ProjectDir)
if options.YamlName == "" {
options.YamlName = core.FindQodanaYaml(options.ProjectDir)
}
qodanaYaml := core.LoadQodanaYaml(options.ProjectDir, options.YamlName)
if qodanaYaml.Linter == "" || options.Force {
core.GetLinter(options.ProjectDir)
core.GetLinter(options.ProjectDir, options.YamlName)
} else {
core.EmptyMessage()
core.SuccessMessage("The linter was already configured before: %s", core.PrimaryBold(qodanaYaml.Linter))
}
core.WarningMessage("Run %s to analyze the project. The configuration is stored in qodana.yaml and can be changed later", core.PrimaryBold("qodana scan"))
core.WarningMessage("Run %s to analyze the project. The configuration is stored in %s and can be changed later", core.PrimaryBold("qodana scan"), core.PrimaryBold(options.YamlName))
},
}
flags := cmd.Flags()
flags.StringVarP(&options.ProjectDir, "project-dir", "i", ".", "Root directory of the project to configure")
flags.BoolVarP(&options.Force, "force", "f", false, "Force initialization (overwrite existing valid qodana.yaml)")
flags.StringVar(&options.YamlName, "yaml-name", "", "Override qodana.yaml name")
return cmd
}
9 changes: 7 additions & 2 deletions cmd/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
type PullOptions struct {
Linter string
ProjectDir string
YamlName string
}

// NewPullCommand returns a new instance of the show command.
Expand All @@ -42,14 +43,17 @@ func NewPullCommand() *cobra.Command {
core.CheckDockerHost()
},
Run: func(cmd *cobra.Command, args []string) {
if options.YamlName == "" {
options.YamlName = core.FindQodanaYaml(options.ProjectDir)
}
if options.Linter == "" {
qodanaYaml := core.LoadQodanaYaml(options.ProjectDir)
qodanaYaml := core.LoadQodanaYaml(options.ProjectDir, options.YamlName)
if qodanaYaml.Linter == "" {
core.WarningMessage(
"No valid qodana.yaml found. Have you run %s? Running that for you...",
core.PrimaryBold("qodana init"),
)
options.Linter = core.GetLinter(options.ProjectDir)
options.Linter = core.GetLinter(options.ProjectDir, options.YamlName)
core.EmptyMessage()
} else {
options.Linter = qodanaYaml.Linter
Expand All @@ -66,5 +70,6 @@ func NewPullCommand() *cobra.Command {
flags := cmd.Flags()
flags.StringVarP(&options.Linter, "linter", "l", "", "Override linter to use")
flags.StringVarP(&options.ProjectDir, "project-dir", "i", ".", "Root directory of the inspected project")
flags.StringVarP(&options.YamlName, "yaml-name", "y", "", "Override qodana.yaml name")
return cmd
}
10 changes: 7 additions & 3 deletions cmd/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,17 @@ But you can always override qodana.yaml options with the following command-line
},
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
if options.YamlName == "" {
options.YamlName = core.FindQodanaYaml(options.ProjectDir)
}
if options.Linter == "" {
qodanaYaml := core.LoadQodanaYaml(options.ProjectDir)
qodanaYaml := core.LoadQodanaYaml(options.ProjectDir, options.YamlName)
if qodanaYaml.Linter == "" {
core.WarningMessage(
"No valid qodana.yaml found. Have you run %s? Running that for you...",
core.PrimaryBold("qodana init"),
)
options.Linter = core.GetLinter(options.ProjectDir)
options.Linter = core.GetLinter(options.ProjectDir, options.YamlName)
core.EmptyMessage()
} else {
options.Linter = qodanaYaml.Linter
Expand Down Expand Up @@ -117,6 +120,7 @@ But you can always override qodana.yaml options with the following command-line
flags.BoolVar(&options.ClearCache, "clear-cache", false, "Clear the local Qodana cache before running the analysis")
flags.BoolVarP(&options.ShowReport, "show-report", "w", false, "Serve HTML report on port")
flags.IntVar(&options.Port, "port", 8080, "Port to serve the report on")
flags.StringVar(&options.YamlName, "yaml-name", "", "Override qodana.yaml name to use: 'qodana.yaml' or 'qodana.yml'")

flags.StringVarP(&options.AnalysisId, "analysis-id", "a", "", "Unique report identifier (GUID) to be used by Qodana Cloud")
flags.StringVarP(&options.Baseline, "baseline", "b", "", "Provide the path to an existing SARIF report to be used in the baseline state calculation")
Expand All @@ -133,7 +137,7 @@ But you can always override qodana.yaml options with the following command-line

flags.StringArrayVar(&options.Property, "property", []string{}, "Set a JVM property to be used while running Qodana using the --property property.name=value1,value2,...,valueN notation")
flags.BoolVarP(&options.SaveReport, "save-report", "s", true, "Generate HTML report")
flags.BoolVar(&options.SendReport, "send-report", false, "Send the inspection report to Qodana Cloud, requires the '--token' option to be specified")
flags.BoolVar(&options.SendReport, "send-report", false, "Send the inspection report to Qodana Cloud, requires the 'QODANA_TOKEN' environment variable to be declared")

flags.SortFlags = false

Expand Down
7 changes: 6 additions & 1 deletion cmd/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type ShowOptions struct {
ReportDir string
Port int
OpenDir bool
YamlName string
}

// NewShowCommand returns a new instance of the show command.
Expand All @@ -46,8 +47,11 @@ be viewed via the file:// protocol (by double-clicking the index.html file).
https://www.jetbrains.com/help/qodana/html-report.html
This command serves the Qodana report locally and opens a browser to it.`,
Run: func(cmd *cobra.Command, args []string) {
if options.YamlName == "" {
options.YamlName = core.FindQodanaYaml(options.ProjectDir)
}
if options.ReportDir == "" {
linter := core.LoadQodanaYaml(options.ProjectDir).Linter
linter := core.LoadQodanaYaml(options.ProjectDir, options.YamlName).Linter
if linter == "" {
log.Fatalf("Can't automatically find the report...\n" +
"Please specify the report directory with the --report-dir flag.")
Expand All @@ -74,5 +78,6 @@ This command serves the Qodana report locally and opens a browser to it.`,
"Specify HTML report path (the one with index.html inside) (default <userCacheDir>/JetBrains/<linter>/results/report)")
flags.IntVarP(&options.Port, "port", "p", 8080, "Specify port to serve report at")
flags.BoolVarP(&options.OpenDir, "dir-only", "d", false, "Open report directory only, don't serve it")
flags.StringVarP(&options.YamlName, "yaml-name", "y", "", "Override qodana.yaml name")
return cmd
}
21 changes: 13 additions & 8 deletions core/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,29 @@ type QodanaOptions struct {
PrintProblems bool
SkipPull bool
ClearCache bool
YamlName string
}

var Version = "dev"

// GetLinter gets linter for the given path
func GetLinter(path string) string {
// GetLinter gets linter for the given path and saves configName
func GetLinter(path string, yamlName string) string {
var linters []string
var linter string
printProcess(func() {
languages := readIdeaDir(path)
if len(languages) == 0 {
languages, _ = recognizeDirLanguages(path)
}
WarningMessage("Detected technologies: " + strings.Join(languages, ", ") + "\n")
for _, language := range languages {
if linter, err := langsLinters[language]; err {
for _, l := range linter {
linters = Append(linters, l)
if len(languages) == 0 {
WarningMessage("No technologies detected (no source code files?)\n")
} else {
WarningMessage("Detected technologies: " + strings.Join(languages, ", ") + "\n")
for _, language := range languages {
if linter, err := langsLinters[language]; err {
for _, l := range linter {
linters = Append(linters, l)
}
}
}
}
Expand All @@ -95,7 +100,7 @@ func GetLinter(path string) string {
}
if linter != "" {
log.Infof("Detected linters: %s", strings.Join(linters, ", "))
WriteQodanaYaml(path, linter)
SetQodanaLinter(path, linter, yamlName)
}
SuccessMessage("Added %s", linter)
return linter
Expand Down
17 changes: 9 additions & 8 deletions core/configurator.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ import (
)

const (
version = "2022.1"
eap = "-eap"
QDJVMC = "jetbrains/qodana-jvm-community:" + version
QDJVM = "jetbrains/qodana-jvm:" + version + eap
QDAND = "jetbrains/qodana-jvm-android:" + version + eap
QDPHP = "jetbrains/qodana-php:" + version + eap
QDPY = "jetbrains/qodana-python:" + version + eap
QDJS = "jetbrains/qodana-js:" + version + eap
configName = "qodana"
version = "2022.1"
eap = "-eap"
QDJVMC = "jetbrains/qodana-jvm-community:" + version
QDJVM = "jetbrains/qodana-jvm:" + version + eap
QDAND = "jetbrains/qodana-jvm-android:" + version + eap
QDPHP = "jetbrains/qodana-php:" + version + eap
QDPY = "jetbrains/qodana-python:" + version + eap
QDJS = "jetbrains/qodana-js:" + version + eap
)

var langsLinters = map[string][]string{
Expand Down
45 changes: 23 additions & 22 deletions core/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ type QodanaYaml struct {
// FailThreshold is a number of problems to fail the analysis (to exit from Qodana with code 255).
FailThreshold int `yaml:"failThreshold,omitempty"`

// Exclude property to disable the wanted checks on the wanted paths.
Excludes []Exclude `yaml:"exclude,omitempty"`
// Clude property to disable the wanted checks on the wanted paths.
Excludes []Clude `yaml:"exclude,omitempty"`

// Include property to enable the wanted checks.
Includes []Include `yaml:"include,omitempty"`
Includes []Clude `yaml:"include,omitempty"`

// Properties property to override IDE properties.
Properties map[string]string `yaml:"properties,omitempty"`
Expand Down Expand Up @@ -80,21 +80,15 @@ type Profile struct {
Path string `yaml:"path,omitempty"`
}

// Exclude A check id to disable.
type Exclude struct {
// The name of check to exclude.
// Clude A check id to enable/disable for include/exclude YAML field.
type Clude struct {
// The name of check to include/exclude.
Name string `yaml:"name"`

// Relative to the project root path to disable analysis.
// Relative to the project root path to enable/disable analysis.
Paths []string `yaml:"paths,omitempty"`
}

// Include A check id to enable.
type Include struct {
// The name of check to exclude.
Name string `yaml:"name"`
}

// Plugin to be installed during the Qodana run.
type Plugin struct {
// Id plugin id to install.
Expand Down Expand Up @@ -158,13 +152,20 @@ type CustomDependency struct {
Licenses []License `yaml:"licenses"`
}

// FindQodanaYaml checks whether qodana.yaml exists or not
func FindQodanaYaml(project string) string {
filename := configName + ".yml"
if info, _ := os.Stat(filepath.Join(project, filename)); info != nil {
return filename
} else {
return configName + ".yaml"
}
}

// LoadQodanaYaml gets Qodana YAML from the project.
func LoadQodanaYaml(project string) *QodanaYaml {
func LoadQodanaYaml(project string, filename string) *QodanaYaml {
q := &QodanaYaml{}
qodanaYamlPath := filepath.Join(project, "qodana.yaml")
if _, err := os.Stat(qodanaYamlPath); errors.Is(err, os.ErrNotExist) {
qodanaYamlPath = filepath.Join(project, "qodana.yml")
}
qodanaYamlPath := filepath.Join(project, filename)
if _, err := os.Stat(qodanaYamlPath); errors.Is(err, os.ErrNotExist) {
return q
}
Expand Down Expand Up @@ -210,9 +211,9 @@ func (q *QodanaYaml) sort() *QodanaYaml {
return q
}

// WriteQodanaYaml writes the qodana.yaml file to the given path.
func WriteQodanaYaml(path string, linter string) {
q := LoadQodanaYaml(path)
// SetQodanaLinter writes the qodana.yaml file to the given path.
func SetQodanaLinter(path string, linter string, filename string) {
q := LoadQodanaYaml(path, filename)
if q.Version == "" {
q.Version = "1.0"
}
Expand All @@ -225,7 +226,7 @@ func WriteQodanaYaml(path string, linter string) {
if err != nil {
return
}
err = ioutil.WriteFile(filepath.Join(path, "qodana.yaml"), b.Bytes(), 0o600)
err = ioutil.WriteFile(filepath.Join(path, filename), b.Bytes(), 0o600)
if err != nil {
log.Fatalf("Marshal: %v", err)
}
Expand Down

0 comments on commit 8021b52

Please sign in to comment.