Skip to content

Commit

Permalink
Fix bug that added overrides to list of deletions during glice audit
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Schinkel committed Oct 21, 2022
1 parent d98eb52 commit 4cd8c6b
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 91 deletions.
2 changes: 1 addition & 1 deletion cmd/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func RunAudit(cmd *cobra.Command, args []string) {
glice.Notef("\n")
glice.Notef("\nBeginning License Audit")
deps := ScanningDependencies(ctx)
pf := AuditingProjectDependencies(ctx, "run", deps)
pf := AuditingProjectDependencies(ctx, deps)
glice.Notef("\n\n")
HandleChanges(ctx, pf)
exceptions := HasDisalloweds(ctx, pf)
Expand Down
2 changes: 1 addition & 1 deletion cmd/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func RunOverrides(cmd *cobra.Command, args []string) {
glice.Notef("\n")
glice.Notef("\nGenerating Overrides file")
deps := ScanningDependencies(ctx)
pf := AuditingProjectDependencies(ctx, "generate", deps)
pf := AuditingProjectDependencies(ctx, deps)
glice.Notef("\n\n")
GeneratingOverrides(ctx, cmd, pf, glice.ErrorLevel)
}
48 changes: 29 additions & 19 deletions cmd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,24 @@ func SavingOverridesFile(ctx context.Context, of *glice.OverridesFile) {
glice.Notef("\nSaving %s", of.Filepath)
err := of.Save()
if err != nil {
glice.Failf(glice.ExitCannotSaveFile,
Failf(glice.ExitCannotSaveFile,
"Failed to create file %s: %s",
of.Filepath,
err.Error())
}
glice.Notef("\nOverrides files saved.")
}

func LoadingProfileFile(ctx context.Context, task string) *glice.ProjectFile {
func LoadingProfileFile(ctx context.Context) *glice.ProjectFile {
glice.Notef("\nLoading `%s`", glice.ProjectFilename)
pf, err := glice.LoadProjectFile(glice.GetOptions().SourceDir)
if err != nil {
glice.Failf(glice.ExitFileDoesNotExist,
"Cannot %s %s; %s",
task,
Failf(glice.ExitFileDoesNotExist,
"Cannot run %s; %s",
glice.CallerName(),
err.Error())
}
glice.Notef("\nLoaded `%s`", pf.Filepath)
Notef("\nLoaded `%s`", pf.Filepath)
return pf
}

Expand All @@ -44,7 +43,7 @@ func ScanningDependencies(ctx context.Context) (deps glice.Dependencies) {
glice.Notef("\nScanning dependencies...")
deps, err = glice.ScanDependencies(ctx, glice.GetOptions())
if err != nil {
glice.Failf(glice.ExitCannotScanDependencies,
Failf(glice.ExitCannotScanDependencies,
"Failed while scanning dependencies: %s",
err.Error())
}
Expand All @@ -55,7 +54,7 @@ func SavingProjectFile(ctx context.Context, pf *glice.ProjectFile) {
glice.Notef("\nSaving %s", glice.ProjectFilename)
err := pf.Save()
if err != nil {
glice.Failf(glice.ExitCannotSaveFile,
Failf(glice.ExitCannotSaveFile,
"Failed to save %s: %s",
pf.Filepath,
err.Error())
Expand All @@ -67,7 +66,7 @@ func CreatingProjectFile(ctx context.Context) (pf *glice.ProjectFile) {
glice.Notef("\nCreating %s", glice.ProjectFilename)
pf = glice.NewProjectFile(glice.GetOptions().SourceDir)
if pf.Exists() {
glice.Failf(glice.ExitFileExistsCannotOverwrite,
Failf(glice.ExitFileExistsCannotOverwrite,
"Cannot overwrite existing file %s.\nRename or delete file then re-run 'glice init'.",
pf.Filepath)
}
Expand All @@ -76,11 +75,11 @@ func CreatingProjectFile(ctx context.Context) (pf *glice.ProjectFile) {
}
pf.Overrides = glice.Overrides{
{
DependencyImport: "https://github.com/example.com/sample",
LicenseID: "MIT",
VerifiedBy: "*email-alias",
LastVerified: glice.Timestamp()[:10],
Notes: "This is a sample override added by 'glice init' command",
Import: "https://github.com/example.com/sample",
LicenseID: "MIT",
VerifiedBy: "*email-alias",
LastVerified: glice.Timestamp()[:10],
Notes: "This is a sample override added by 'glice init' command",
},
}
glice.Notef("\nFile %s created", pf.Filepath)
Expand All @@ -96,20 +95,20 @@ func CreatingOverridesFile(ctx context.Context, onExists int) *glice.OverridesFi
}
switch onExists {
case glice.WarnLevel:
glice.Warnf(
Warnf(
"\nCannot overwrite existing file %s.\nRename or delete file then re-run 'glice overrides'.",
of.Filepath)
default:
glice.Failf(glice.ExitFileExistsCannotOverwrite,
Failf(glice.ExitFileExistsCannotOverwrite,
"\nCannot overwrite existing file %s.\nRename or delete file then re-run 'glice overrides'.",
of.Filepath)
}
end:
return of
}

func AuditingProjectDependencies(ctx context.Context, task string, deps glice.Dependencies) (pf *glice.ProjectFile) {
pf = LoadingProfileFile(ctx, task)
func AuditingProjectDependencies(ctx context.Context, deps glice.Dependencies) (pf *glice.ProjectFile) {
pf = LoadingProfileFile(ctx)
glice.Notef("\nAuditing dependencies...")
pf.Changes, pf.Disalloweds = pf.AuditDependencies(deps)
glice.Notef("\nAudit complete.")
Expand All @@ -120,7 +119,7 @@ func HasDisalloweds(ctx context.Context, pf *glice.ProjectFile) (has bool) {
if len(pf.Disalloweds) == 0 {
glice.Notef("\n")
glice.Notef("\nOnly allowed licenses detected")
glice.Notef("\nAudit completed successfully\n")
glice.Notef("\nAudit completed successfully")
goto end
}
has = true
Expand Down Expand Up @@ -160,3 +159,14 @@ func GeneratingOverrides(ctx context.Context, cmd *cobra.Command, pf *glice.Proj
glice.Notef("\n\n")
}
}

func Warnf(format string, args ...interface{}) {
glice.Warnf(format, args...)

}
func Notef(format string, args ...interface{}) {
glice.Notef(format, args...)
}
func Failf(level int, format string, args ...interface{}) {
glice.Failf(level, format, args...)
}
25 changes: 25 additions & 0 deletions cmd/verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import (
"context"
"github.com/spf13/cobra"
)

// VerifyCmd represents the Verify command
var VerifyCmd = &cobra.Command{
Use: "verify",
Run: RunVerify,
Short: "Verify your project's `glice.yaml` file",
Long: "Verify your project's `glice.yaml` file by loading it",
}

func init() {
rootCmd.AddCommand(VerifyCmd)
}

func RunVerify(cmd *cobra.Command, args []string) {
ctx := context.Background()
Notef("\n")
LoadingProfileFile(ctx)
Notef("\n\n")
}
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.18
require (
github.com/fatih/color v1.13.0
github.com/google/go-github v17.0.0+incompatible
github.com/mikeschinkel/go-phpcereal v0.0.0-20220731232732-62bf5394d863
github.com/olekukonko/tablewriter v0.0.5
github.com/spf13/cobra v1.6.0
golang.org/x/mod v0.5.1
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mikeschinkel/go-phpcereal v0.0.0-20220731232732-62bf5394d863 h1:6XVWb/g5RerLSG0Yzd1W/LQPRWbU0fGSQPVCFmtYD5s=
github.com/mikeschinkel/go-phpcereal v0.0.0-20220731232732-62bf5394d863/go.mod h1:q9EQUR9CyWvL0qiKqc/VM6RtnOEphwm3FzqedlmrlW8=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
35 changes: 15 additions & 20 deletions pkg/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import (
type Editors []*Editor
type EditorMap map[string]*Editor
type Editor struct {
Name string `yaml:"name"`
Email string `yaml:"email"`
Reference string `yaml:"ref"`
Name string
Email string
Anchor string
}

var (
defaultName = "Username Goes Here"
defaultEmail = "email-alias@example.com"
)

const numProperties = 3
const numProperties = 2

var _ yaml.Marshaler = (*Editor)(nil)
var _ yaml.Unmarshaler = (*Editor)(nil)
Expand All @@ -39,14 +39,14 @@ func (e *Editor) MarshalYAML() (interface{}, error) {
return e.String(), nil
}

var regexParseEditor = regexp.MustCompile(`^\s*&(\S+)\s+(.+)\s+<([^>]+)>\s*$`)
var regexParseEditor = regexp.MustCompile(`^\s*(.+)\s+<([^>]+)>\s*$`)

var errMsg = "editor value '%s' is incomplete, or is not formatted correctly"

func (e *Editor) UnmarshalYAML(node *yaml.Node) (err error) {
var editor []string

segments := regexParseEditor.FindAllStringSubmatch(node.Value, -1)
segments := regexParseEditor.FindAllStringSubmatch(node.Value, 1)
if segments == nil || len(segments) == 0 {
err = fmt.Errorf(errMsg, node.Value)
goto end
Expand All @@ -62,38 +62,33 @@ func (e *Editor) UnmarshalYAML(node *yaml.Node) (err error) {
if len(editor) > 2 {
e.Email = editor[2]
}
if len(editor) > 3 {
e.Reference = editor[3]
}
if e.Reference == "" {
err = AppendError(err, "editor reference must not be empty")
}
if e.Name == "" {
err = AppendError(err, "editor name must not be empty")
}
if e.Email == "" {
err = AppendError(err, "editor email must not be empty")
}
e.Anchor = node.Anchor
end:
if err != nil {
err = fmt.Errorf("%s; %s", err.Error(),
"should be formatted as '&reference FirstName LastName <email@example.com>'")
"should be formatted as '&anchor FirstName LastName <email@example.com>'")
}
return err
}

func (e *Editor) Alias() string {
e.ensureReference()
return fmt.Sprintf("*%s", e.Reference)
e.ensureAnchor()
return fmt.Sprintf("*%s", e.Anchor)
}

func (e *Editor) String() string {
e.ensureReference()
return fmt.Sprintf("&%s %s <%s>", e.Reference, e.Name, e.Email)
e.ensureAnchor()
return fmt.Sprintf("&%s %s <%s>", e.Anchor, e.Name, e.Email)
}

func (e *Editor) ensureReference() {
if e.Reference == "" {
e.Reference = UpToN(e.Email, '@', 1)
func (e *Editor) ensureAnchor() {
if e.Anchor == "" {
e.Anchor = UpToN(e.Email, '@', 1)
}
}
2 changes: 1 addition & 1 deletion pkg/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (c *GitHubRepoClient) GetRepositoryLicense(ctx context.Context, options *Op
switch _err.Response.StatusCode {
case http.StatusUnauthorized:
// Bad credentials?
err = fmt.Errorf("unauthorized; %w", _err)
err = fmt.Errorf("unauthorized (is your GITHUB_API_KEY correct?); %w", _err)

case http.StatusNotFound:
// Anything other than a Not Found or Unauthorized
Expand Down
32 changes: 21 additions & 11 deletions pkg/override.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
package glice

type Overrides []*Override
type OverrideMap map[string]*Override
type Override struct {
DependencyImport string `yaml:"dependency"`
LicenseID string `yaml:"license,omitempty"`
LicenseIDs []string `yaml:"licenses,omitempty"`
VerifiedBy string `yaml:"verifier"`
LastVerified string `yaml:"verified"`
Notes string `yaml:"notes,omitempty"`
Import string `yaml:"dependency"`
LicenseID string `yaml:"license,omitempty"`
LicenseIDs []string `yaml:"licenses,omitempty"`
VerifiedBy string `yaml:"verifier"`
LastVerified string `yaml:"verified"`
Notes string `yaml:"notes,omitempty"`
}

func NewOverride(dep *Dependency, ed *Editor) *Override {
return &Override{
DependencyImport: dep.Import,
LicenseID: dep.LicenseID,
LicenseIDs: []string{},
VerifiedBy: ed.Alias(),
LastVerified: Timestamp()[:10],
Import: dep.Import,
LicenseID: dep.LicenseID,
LicenseIDs: []string{},
VerifiedBy: ed.Alias(),
LastVerified: Timestamp()[:10],
Notes: "Your dependency-specific notes go here,\n" +
"e.g. links where you read the license you verified, etc.",
}
}

// ToMap creates a map of Overrides indexed by Dependency Import
func (ors Overrides) ToMap() OverrideMap {
newOrs := make(OverrideMap, len(ors))
for _, or := range ors {
newOrs[or.Import] = or
}
return newOrs
}
33 changes: 12 additions & 21 deletions pkg/project_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type ProjectFile struct {
Overrides Overrides `yaml:"overrides"`
Dependencies Dependencies `yaml:"dependencies"`
allowedMap LicenseIDMap `yaml:"-"`
overrideMap OverrideMap `yaml:"-"`
Disalloweds Dependencies `yaml:"-"`
Changes *Changes `yaml:"-"`
}
Expand Down Expand Up @@ -79,36 +80,27 @@ func (pf *ProjectFile) Save() (err error) {
return SaveYAMLFile(pf)
}

// removeOverridden accepts a DependencyMap and removes any found to be
// overridden in the `glice.yaml` file, returning the smaller map.
func (pf *ProjectFile) removeOverridden(depMap DependencyMap) DependencyMap {
// First scan the overrides from the glice.yaml file
for _, _or := range pf.Overrides {
// If none found in the deps provided as overridden
if _, ok := depMap[_or.DependencyImport]; !ok {
// continue looking
continue
}
// If any deps provides WERE found to be overridden
// then let's remove them from the list of deps
// TODO: Address when license changes to unacceptable AFTER it was
// overridden as acceptable
delete(depMap, _or.DependencyImport)
}
return depMap
}

// IsLicenseAllowed inspects a single scanned dependency to ensure
// it has a proper license, returning false if not.
func (pf *ProjectFile) IsLicenseAllowed(dep *Dependency) (ok bool) {
if pf.overrideMap == nil {
pf.overrideMap = pf.Overrides.ToMap()
}
if _, ok = pf.overrideMap[dep.Import]; ok {
goto end
}
if pf.allowedMap == nil {
pf.allowedMap = pf.AllowedLicenses.ToMap()
}
_, ok = pf.allowedMap[dep.LicenseID]
end:
return ok
}

// AuditDependencies returns any disallowed licenses found in the provided dependencies.
// Also returns changes based on the dependencies there were in the glice.yaml file.
func (pf *ProjectFile) AuditDependencies(deps Dependencies) (changes *Changes, disalloweds Dependencies) {
var scanDeps = pf.removeOverridden(deps.ToMap())
var scanDeps = deps.ToMap()
var fileDeps = pf.Dependencies.ToMap()

// Review the file dependencies to see if there are any dependencies not found
Expand All @@ -123,7 +115,6 @@ func (pf *ProjectFile) AuditDependencies(deps Dependencies) (changes *Changes, d

// Review the if there are any with disallowed licenses and
// also to see if we found new dependencies when scanning.
pf.allowedMap = pf.AllowedLicenses.ToMap()
disalloweds = make(Dependencies, 0)
for imp, dep := range scanDeps {
if !pf.IsLicenseAllowed(dep) {
Expand Down
Loading

0 comments on commit 4cd8c6b

Please sign in to comment.