Skip to content

Commit

Permalink
allow passing of commit hash on the cli (#278)
Browse files Browse the repository at this point in the history
Signed-off-by: Benji Visser <benji@093b.org>
  • Loading branch information
noqcks authored Jan 23, 2024
1 parent d609554 commit b7ce660
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 1 deletion.
30 changes: 29 additions & 1 deletion cmd/xeol/cli/options/xeol.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
git "github.com/go-git/go-git/v5"
"github.com/karrick/tparse"

"github.com/xeol-io/xeol/cmd/xeol/internal/types"
"github.com/xeol-io/xeol/internal/format"
)

Expand Down Expand Up @@ -99,6 +100,11 @@ func (o *Xeol) AddFlags(flags clio.FlagSet) {
"manually set the name of the project being analyzed for xeol.io. If you are running xeol inside a git repository, this will be automatically detected.",
)

flags.StringVarP(&o.CommitHash,
"commit-hash", "",
"manually set the commit hash of the project being analyzed for xeol.io. If you are running xeol inside a git repository, this will be automatically detected.",
)

flags.StringVarP(&o.APIKey,
"api-key", "",
"set the API key for xeol.io. When this is set, scans will be uploaded to xeol.io.",
Expand Down Expand Up @@ -149,6 +155,28 @@ func (o *Xeol) parseLookaheadOption() (err error) {
return nil
}

func (o *Xeol) parseProjectAndCommitOption() (err error) {
if o.APIKey != "" {
if o.ProjectName == "" {
return fmt.Errorf("must specify a project name when using --api-key. This is usually inferred automatically when running inside a git repository, but you may also pass it manually with --project-name")
}
if err := types.ProjectName(o.ProjectName).IsValid(); err != nil {
return err
}

if o.CommitHash == "" {
return fmt.Errorf("must specify a commit hash when using --api-key. This is usually inferred automatically when running inside a git repository, but you may also pass it manually with --commit-hash")
}
if err := types.CommitHash(o.CommitHash).IsValid(); err != nil {
return err
}
}
return nil
}

func (o *Xeol) PostLoad() error {
return o.parseLookaheadOption()
if err := o.parseLookaheadOption(); err != nil {
return err
}
return o.parseProjectAndCommitOption()
}
16 changes: 16 additions & 0 deletions cmd/xeol/internal/types/commit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package types

import (
"fmt"
"regexp"
)

type CommitHash string

func (c CommitHash) IsValid() error {
re := regexp.MustCompile(`^[a-fA-F0-9]{40}$`)
if !re.MatchString(string(c)) {
return fmt.Errorf("invalid SHA1 hash format for commit hash '%s'", string(c))
}
return nil
}
27 changes: 27 additions & 0 deletions cmd/xeol/internal/types/commit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package types

import (
"testing"
)

func TestCommitHash_IsValid(t *testing.T) {
tests := []struct {
name string
hash CommitHash
wantErr bool
}{
{"Valid SHA1", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", false},
{"Invalid SHA1 - Short", "a94a8fe5cc", true},
{"Invalid SHA1 - Long", "a94a8fe5ccb19ba61c4c0873d391e9879", true},
{"Invalid SHA1 - Special Characters", "a94a8fe5cc#19ba61c4c0873d391e9$", true},
{"Invalid SHA1 - Empty", "", true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.hash.IsValid(); (err != nil) != tt.wantErr {
t.Errorf("CommitHash.IsValid() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
16 changes: 16 additions & 0 deletions cmd/xeol/internal/types/projectname.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package types

import (
"fmt"
"regexp"
)

type ProjectName string

func (p ProjectName) IsValid() error {
re := regexp.MustCompile(`^(gitlab|github|azure)//([a-zA-Z0-9\-_]+/[a-zA-Z0-9\-_]+(/[a-zA-Z0-9\-_]+)?)$`)
if ok := re.MatchString(string(p)); !ok {
return fmt.Errorf("invalid project name. Accepted formats: 'gitlab//<owner>/<repo>', 'github//<owner>/<repo>', 'azure//<owner>/<project>/<repo>'")
}
return nil
}
46 changes: 46 additions & 0 deletions cmd/xeol/internal/types/projectname_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package types

import "testing"

func TestIsValidProjectName(t *testing.T) {
tests := []struct {
projectName string
wantErr bool
}{
{
projectName: "gitlab//noqcks/test",
wantErr: false,
},
{
projectName: "github//noqcks/test",
wantErr: false,
},
{
projectName: "azure//noqcks/test",
wantErr: false,
},
{
projectName: "azure//noqcks/test/test",
wantErr: false,
},
{
projectName: "azure//noqcks/test/test/test",
wantErr: true,
},
{
projectName: "azure//noqcks",
wantErr: true,
},
{
projectName: "test//test",
wantErr: true,
},
}

for _, test := range tests {
err := ProjectName(test.projectName).IsValid()
if test.wantErr && err == nil {
t.Errorf("Expected error for '%s', but got nil", test.projectName)
}
}
}

0 comments on commit b7ce660

Please sign in to comment.