Skip to content

Commit

Permalink
Add new git "count-contributors" command. (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
gailazar300 authored Jun 30, 2024
1 parent 4aca7e8 commit 17e4c19
Show file tree
Hide file tree
Showing 9 changed files with 2,378 additions and 7 deletions.
6 changes: 6 additions & 0 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@ func GetJfrogCliSecurityApp() components.App {
Commands: getXrayNameSpaceCommands(),
Category: "Command Namespaces",
})
app.Subcommands = append(app.Subcommands, components.Namespace{
Name: "git",
Description: "Git commands.",
Commands: getGitNameSpaceCommands(),
Category: "Command Namespaces",
})
return app
}
37 changes: 30 additions & 7 deletions cli/docs/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package docs

import (
"fmt"
"github.com/jfrog/jfrog-cli-security/commands/git"
"strings"

"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
Expand All @@ -13,13 +14,14 @@ import (

const (
// Security Commands Keys
XrCurl = "xr-curl"
OfflineUpdate = "offline-update"
XrScan = "xr-scan"
BuildScan = "build-scan"
DockerScan = "docker scan"
Audit = "audit"
CurationAudit = "curation-audit"
XrCurl = "xr-curl"
OfflineUpdate = "offline-update"
XrScan = "xr-scan"
BuildScan = "build-scan"
DockerScan = "docker scan"
Audit = "audit"
CurationAudit = "curation-audit"
GitCountContributors = "count-contributors"

// TODO: Deprecated commands (remove at next CLI major version)
AuditMvn = "audit-maven"
Expand Down Expand Up @@ -113,6 +115,15 @@ const (

// Unique curation flags
CurationOutput = "curation-format"

// Unique git flags
ScmType = "scm-type"
ScmApiUrl = "scm-api-url"
Token = "token"
Owner = "owner"
RepoName = "repo-name"
Months = "months"
DetailedSummary = "detailed-summary"
)

// Mapping between security commands (key) and their flags (key).
Expand All @@ -138,6 +149,9 @@ var commandFlags = map[string][]string{
CurationAudit: {
CurationOutput, WorkingDirs, Threads, RequirementsFile,
},
GitCountContributors: {
ScmType, ScmApiUrl, Token, Owner, RepoName, Months, DetailedSummary,
},
// TODO: Deprecated commands (remove at next CLI major version)
AuditMvn: {
url, user, password, accessToken, ServerId, InsecureTls, Project, ExclusionsAudit, Watches, RepoPath, Licenses, OutputFormat, Fail, ExtendedTable, useWrapperAudit,
Expand Down Expand Up @@ -233,6 +247,15 @@ var flagsMap = map[string]components.Flag{
Sast: components.NewBoolFlag(Sast, fmt.Sprintf("Selective scanners mode: Execute SAST sub-scan. Can be combined with --%s, --%s and --%s.", Sca, Secrets, Iac)),
Secrets: components.NewBoolFlag(Secrets, fmt.Sprintf("Selective scanners mode: Execute Secrets sub-scan. Can be combined with --%s, --%s and --%s.", Sca, Sast, Iac)),
WithoutCA: components.NewBoolFlag(WithoutCA, fmt.Sprintf("Selective scanners mode: Disable Contextual Analysis scanner after SCA. Relevant only with --%s flag.", Sca)),

// Git flags
ScmType: components.NewStringFlag(ScmType, fmt.Sprintf("SCM type. Possible values are: %s.", git.NewScmType().GetValidScmTypeString()), components.SetMandatory()),
ScmApiUrl: components.NewStringFlag(ScmApiUrl, "SCM API URL. For example: 'https://api.github.com'.", components.SetMandatory()),
Token: components.NewStringFlag(Token, fmt.Sprintf("SCM API token. In the absence of a flag, tokens should be passed in the %s enviroment variable, or in the corresponding environment variables '%s'.", git.GenericGitTokenEnvVar, git.NewScmType().GetOptionalScmTypeTokenEnvVars())),
Owner: components.NewStringFlag(Owner, "The owner of the repository. Depends on the git provider - on github and gitlab the owner is usually an individual or an organization, on bitbucket it is a project.", components.SetMandatory()),
RepoName: components.NewStringFlag(RepoName, "Specific repository name to analyze, If not provided all repositories in the project will be analyzed."),
Months: components.NewStringFlag(Months, "Number of months to analyze.", components.WithIntDefaultValue(git.DefaultContContributorsMonths)),
DetailedSummary: components.NewBoolFlag(DetailedSummary, "Set to true to get a contributors detailed summary."),
}

func GetCommandFlags(cmdKey string) []components.Flag {
Expand Down
5 changes: 5 additions & 0 deletions cli/docs/git/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package git

func GetContContributorsDescription() string {
return "List all GIT providers' contributing developers."
}
109 changes: 109 additions & 0 deletions cli/gitcommands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cli

import (
"github.com/jfrog/froggit-go/vcsutils"
"github.com/jfrog/jfrog-cli-core/v2/common/progressbar"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
flags "github.com/jfrog/jfrog-cli-security/cli/docs"
gitDocs "github.com/jfrog/jfrog-cli-security/cli/docs/git"
"github.com/jfrog/jfrog-cli-security/commands/git"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"os"
)

func getGitNameSpaceCommands() []components.Command {
return []components.Command{
{
Name: "count-contributors",
Aliases: []string{"cc"},
Flags: flags.GetCommandFlags(flags.GitCountContributors),
Description: gitDocs.GetContContributorsDescription(),
Hidden: true,
Action: GitCountContributorsCmd,
},
}
}

func GetCountContributorsParams(c *components.Context) (*git.CountContributorsParams, error) {
params := git.CountContributorsParams{}
// Mandatory flags
scmTypes := git.NewScmType()
// ScmType
scmType := c.GetStringFlagValue(flags.ScmType)
if scmType == "" {
return nil, errorutils.CheckErrorf("The --%s option is mandatory", flags.ScmType)
} else {
if scmTypeVal, ok := scmTypes.ScmTypeMap[scmType]; ok {
params.ScmType = scmTypeVal
} else {
return nil, errorutils.CheckErrorf("Unsupported SCM type: %s, Possible values are: %v", scmType, scmTypes.GetValidScmTypeString())
}
}
// Token
params.Token = c.GetStringFlagValue(flags.Token)
if params.Token == "" {
var envVarToken string
switch params.ScmType {
case vcsutils.BitbucketServer:
envVarToken = os.Getenv(git.BitbucketTokenEnvVar)
case vcsutils.GitLab:
envVarToken = os.Getenv(git.GitlabTokenEnvVar)
case vcsutils.GitHub:
envVarToken = os.Getenv(git.GithubTokenEnvVar)
default:
return nil, errorutils.CheckErrorf("Unsupported SCM type: %s, Possible values are: %v", scmType, scmTypes.GetValidScmTypeString())
}
if envVarToken != "" {
params.Token = envVarToken
} else {
envVarToken = os.Getenv(git.GenericGitTokenEnvVar)
if envVarToken != "" {
params.Token = envVarToken
} else {
return nil, errorutils.CheckErrorf("Providing a token is mandatory. should use --%s flag, the token enviromment variable %s, or coresponding provider enviromment variable %s.", flags.Token, git.GenericGitTokenEnvVar, scmTypes.GetOptionalScmTypeTokenEnvVars())
}
}
}
// Owner
params.Owner = c.GetStringFlagValue(flags.Owner)
if params.Owner == "" {
return nil, errorutils.CheckErrorf("The --%s option is mandatory", flags.Owner)
}
// ScmApiUrl
params.ScmApiUrl = c.GetStringFlagValue(flags.ScmApiUrl)
if params.ScmApiUrl == "" {
return nil, errorutils.CheckErrorf("The --%s option is mandatory", flags.ScmApiUrl)
}

// Optional flags
// Repository name
params.Repository = c.GetStringFlagValue(flags.RepoName)
// Months
if !c.IsFlagSet(flags.Months) {
params.MonthsNum = git.DefaultContContributorsMonths
} else {
months, err := c.GetIntFlagValue(flags.Months)
if err != nil {
return nil, err
}
if months <= 0 {
return nil, errorutils.CheckErrorf("Invalid value for '--%s=%d'. If set, should be positive number.", flags.Months, months)
}
params.MonthsNum = months
}
// DetailedSummery
params.DetailedSummery = c.GetBoolFlagValue(flags.DetailedSummary)
return &params, nil
}

func GitCountContributorsCmd(c *components.Context) error {
gitContrParams, err := GetCountContributorsParams(c)
if err != nil {
return err
}
gitContributionCommand, err := git.NewCountContributorsCommand(gitContrParams)
if err != nil {
return err
}
return progressbar.ExecWithProgress(gitContributionCommand)
}
Loading

0 comments on commit 17e4c19

Please sign in to comment.