Skip to content

Commit

Permalink
Merge pull request #17 from loftwah/dl/advanced-analysis
Browse files Browse the repository at this point in the history
Dl/advanced analysis
  • Loading branch information
loftwah authored Sep 11, 2024
2 parents ace9a05 + 15f6929 commit 7df164e
Show file tree
Hide file tree
Showing 13 changed files with 590 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,4 @@ This project is licensed under the terms of the license included in the [LICENSE

## Contact

For any queries or suggestions, please open an issue on the GitHub repository.
For any queries or suggestions, please open an issue on the GitHub repository.
46 changes: 46 additions & 0 deletions cmd/grabitsh/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package grabitsh

import (
"os"
"path/filepath"
"regexp"
)

type APIInfo struct {
Files []string `json:"files"`
Swagger bool `json:"swagger"`
GraphQL bool `json:"graphql"`
Endpoints []string `json:"endpoints"`
HTTPMethods []string `json:"http_methods"`
}

func analyzeAPIStructure() APIInfo {
var apiInfo APIInfo

apiPatterns := []string{"*api*.go", "*controller*.rb", "*views*.py", "routes/*.js", "controllers/*.js"}
for _, pattern := range apiPatterns {
files, _ := filepath.Glob(pattern)
apiInfo.Files = append(apiInfo.Files, files...)
}

apiInfo.Swagger = fileExists("swagger.json") || fileExists("swagger.yaml")
apiInfo.GraphQL = fileExists("schema.graphql") || fileExists("schema.gql")

// Analyze API endpoints and HTTP methods
for _, file := range apiInfo.Files {
content, err := os.ReadFile(file)
if err != nil {
continue
}

// Extract endpoints (this is a simple example, you might need more sophisticated regex for your specific use case)
endpointRegex := regexp.MustCompile(`(GET|POST|PUT|DELETE|PATCH)\s+["']([^"']+)["']`)
matches := endpointRegex.FindAllStringSubmatch(string(content), -1)
for _, match := range matches {
apiInfo.HTTPMethods = appendUnique(apiInfo.HTTPMethods, match[1])
apiInfo.Endpoints = appendUnique(apiInfo.Endpoints, match[2])
}
}

return apiInfo
}
19 changes: 19 additions & 0 deletions cmd/grabitsh/architecture.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package grabitsh

func detectArchitecture() string {
if dirExists("services") || dirExists("microservices") {
return "Microservices"
} else if fileExists("serverless.yml") || fileExists("serverless.yaml") {
return "Serverless"
} else if dirExists("app") && dirExists("config") && dirExists("db") {
return "Monolithic (Rails-like)"
} else if fileExists("package.json") && fileExists("server.js") {
return "Monolithic (Node.js)"
} else if fileExists("pom.xml") || fileExists("build.gradle") {
return "Monolithic (Java)"
} else if fileExists("manage.py") && dirExists("apps") {
return "Monolithic (Django)"
}

return "Undetermined"
}
93 changes: 93 additions & 0 deletions cmd/grabitsh/cicd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package grabitsh

import (
"fmt"
"os"
"path/filepath"
"strings"
)

type Step struct {
Name string `json:"name"`
Description string `json:"description"`
}

type CICDSystem struct {
Name string `json:"name"`
File string `json:"file"`
Steps []Step `json:"steps"`
}

func analyzeCICDWorkflows() ([]CICDSystem, error) {
cicdSystems := []struct {
name string
files []string
}{
{"GitHub Actions", []string{".github/workflows/*.yml", ".github/workflows/*.yaml"}},
{"GitLab CI", []string{".gitlab-ci.yml"}},
{"Jenkins", []string{"Jenkinsfile"}},
{"CircleCI", []string{".circleci/config.yml"}},
{"Travis CI", []string{".travis.yml"}},
{"Azure Pipelines", []string{"azure-pipelines.yml"}},
{"Bitbucket Pipelines", []string{"bitbucket-pipelines.yml"}},
{"AWS CodeBuild", []string{"buildspec.yml"}},
{"Drone CI", []string{".drone.yml"}},
{"Semaphore", []string{".semaphore/semaphore.yml"}},
}

var results []CICDSystem

for _, system := range cicdSystems {
for _, filePattern := range system.files {
files, err := filepath.Glob(filePattern)
if err != nil {
return nil, fmt.Errorf("error globbing files: %w", err)
}
for _, file := range files {
content, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("error reading file %s: %w", file, err)
}
steps, err := analyzeCICDSteps(string(content))
if err != nil {
return nil, fmt.Errorf("error analyzing steps in file %s: %w", file, err)
}
results = append(results, CICDSystem{
Name: system.name,
File: filepath.Base(file),
Steps: steps,
})
}
}
}

return results, nil
}

func analyzeCICDSteps(content string) ([]Step, error) {
var steps []Step

if strings.Contains(content, "npm test") || strings.Contains(content, "yarn test") {
steps = append(steps, Step{Name: "Testing", Description: "Runs tests"})
}
if strings.Contains(content, "npm run build") || strings.Contains(content, "yarn build") {
steps = append(steps, Step{Name: "Build", Description: "Builds the project"})
}
if strings.Contains(content, "docker build") || strings.Contains(content, "docker-compose") {
steps = append(steps, Step{Name: "Docker operations", Description: "Performs Docker operations"})
}
if strings.Contains(content, "deploy") || strings.Contains(content, "kubectl") {
steps = append(steps, Step{Name: "Deployment", Description: "Deploys the project"})
}
if strings.Contains(content, "lint") || strings.Contains(content, "eslint") {
steps = append(steps, Step{Name: "Linting", Description: "Runs linter"})
}
if strings.Contains(content, "security") || strings.Contains(content, "scan") {
steps = append(steps, Step{Name: "Security scanning", Description: "Performs security scanning"})
}
if strings.Contains(content, "coverage") || strings.Contains(content, "codecov") {
steps = append(steps, Step{Name: "Code coverage", Description: "Checks code coverage"})
}

return steps, nil
}
33 changes: 33 additions & 0 deletions cmd/grabitsh/code_quality.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package grabitsh

func analyzeCodeQuality() []string {
var tools []string

lintConfigs := map[string]string{
".eslintrc": "ESLint",
".rubocop.yml": "RuboCop",
".golangci.yml": "golangci-lint",
"pylintrc": "Pylint",
".checkstyle": "Checkstyle (Java)",
"tslint.json": "TSLint",
".stylelintrc": "Stylelint",
".prettierrc": "Prettier",
".scalafmt.conf": "Scalafmt",
}

for config, tool := range lintConfigs {
if fileExists(config) {
tools = append(tools, tool)
}
}

if fileExists("sonar-project.properties") {
tools = append(tools, "SonarQube")
}

if fileExists(".codeclimate.yml") {
tools = append(tools, "CodeClimate")
}

return tools
}
88 changes: 88 additions & 0 deletions cmd/grabitsh/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package grabitsh

import (
"os"
"path/filepath"
"strings"
)

type DatabaseInfo struct {
MigrationsPresent bool `json:"migrations_present"`
ConfigFiles []string `json:"config_files"`
ORMUsed bool `json:"orm_used"`
DatabaseTypes []string `json:"database_types"`
}

func analyzeDatabaseUsage() DatabaseInfo {
var dbInfo DatabaseInfo

dbInfo.MigrationsPresent = dirExists("migrations") || dirExists("db/migrate")

dbConfigFiles := []string{
"config/database.yml",
"knexfile.js",
"ormconfig.json",
"sequelize.config.js",
"database.json",
"dbconfig.json",
"mongo.config.js",
"redis.config.js",
}

for _, file := range dbConfigFiles {
if fileExists(file) {
dbInfo.ConfigFiles = append(dbInfo.ConfigFiles, file)
}
}

ormFiles := []string{
"models.py",
"*.model.ts",
"*.rb",
"entity/*.go",
"*.entity.ts",
"models/*.java",
"entities/*.cs",
}

for _, pattern := range ormFiles {
files, _ := filepath.Glob(pattern)
if len(files) > 0 {
dbInfo.ORMUsed = true
break
}
}

// Detect database types
dbTypes := map[string][]string{
"PostgreSQL": {"postgres", "postgresql", "pg"},
"MySQL": {"mysql", "mariadb"},
"SQLite": {"sqlite", "sqlite3"},
"MongoDB": {"mongodb", "mongo", "mongoose"},
"Redis": {"redis", "rediss"},
"Cassandra": {"cassandra", "cql"},
"Oracle": {"oracle", "orcl"},
"SQL Server": {"sqlserver", "mssql"},
"DB2": {"db2", "ibm"},
"Couchbase": {"couchbase"},
"Firebird": {"firebird"},
"ClickHouse": {"clickhouse"},
}

for dbType, keywords := range dbTypes {
for _, file := range dbInfo.ConfigFiles {
content, err := os.ReadFile(file)
if err != nil {
continue
}
for _, keyword := range keywords {
if strings.Contains(string(content), keyword) {
dbInfo.DatabaseTypes = appendUnique(dbInfo.DatabaseTypes, dbType)
break
}
}
}
}

return dbInfo
}
27 changes: 27 additions & 0 deletions cmd/grabitsh/dependency_management.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package grabitsh

func analyzeDependencyManagement() []string {
var tools []string

depManagement := map[string]string{
"package-lock.json": "npm",
"yarn.lock": "Yarn",
"Gemfile.lock": "Bundler (Ruby)",
"poetry.lock": "Poetry (Python)",
"go.sum": "Go Modules",
"composer.lock": "Composer (PHP)",
"Pipfile.lock": "Pipenv (Python)",
"pom.xml": "Maven (Java)",
"build.gradle": "Gradle (Java)",
"requirements.txt": "pip (Python)",
"Cargo.lock": "Cargo (Rust)",
}

for file, tool := range depManagement {
if fileExists(file) {
tools = append(tools, tool)
}
}

return tools
}
Loading

0 comments on commit 7df164e

Please sign in to comment.