gomodguard

package module
v1.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2024 License: MIT Imports: 12 Imported by: 11

README

gomodguard

License Codecov GitHub Workflow Status GitHub release (latest SemVer) Docker Github Releases Stats of golangci-lint

Allow and block list linter for direct Go module dependencies. This is useful for organizations where they want to standardize on the modules used and be able to recommend alternative modules.

Description

Allowed and blocked modules are defined in a ./.gomodguard.yaml or ~/.gomodguard.yaml file.

Modules can be allowed by module or domain name. When allowed modules are specified any modules not in the allowed configuration are blocked.

If no allowed modules or domains are specified then all modules are allowed except for blocked ones.

The linter looks for blocked modules in go.mod and searches for imported packages where the imported packages module is blocked. Indirect modules are not considered.

Alternative modules can be optionally recommended in the blocked modules list.

If the linted module imports a blocked module but the linted module is in the recommended modules list the blocked module is ignored. Usually, this means the linted module wraps that blocked module for use by other modules, therefore the import of the blocked module should not be blocked.

Version constraints can be specified for modules as well which lets you block new or old versions of modules or specific versions.

Results are printed to stdout.

Logging statements are printed to stderr.

Results can be exported to different report formats. Which can be imported into CI tools. See the help section for more information.

Configuration

allowed:
  modules:                                                      # List of allowed modules
    - gopkg.in/yaml.v2
    - github.com/go-xmlfmt/xmlfmt
    - github.com/phayes/checkstyle
    - github.com/mitchellh/go-homedir
  domains:                                                      # List of allowed module domains
    - golang.org

blocked:
  modules:                                                      # List of blocked modules
    - github.com/uudashr/go-module:                             # Blocked module
        recommendations:                                        # Recommended modules that should be used instead (Optional)
          - golang.org/x/mod                           
        reason: "`mod` is the official go.mod parser library."  # Reason why the recommended module should be used (Optional)
  versions:                                                     # List of blocked module version constraints.
    - github.com/mitchellh/go-homedir:                          # Blocked module with version constraint.
        version: "<= 1.1.0"                                     # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons.
        reason: "testing if blocked version constraint works."  # Reason why the version constraint exists.

Usage

╰─ ./gomodguard -h
Usage: gomodguard <file> [files...]
Also supports package syntax but will use it in relative path, i.e. ./pkg/...
Flags:
  -f string
    	Report results to the specified file. A report type must also be specified
  -file string

  -h	Show this help text
  -help

  -i int
    	Exit code when issues were found (default 2)
  -issues-exit-code int 
      (default 2)
  
  -n	Don't lint test files
  -no-test

  -r string
    	Report results to one of the following formats: checkstyle. A report file destination must also be specified
  -report string

Example

╰─ ./gomodguard -r checkstyle -f gomodguard-checkstyle.xml ./...

info: allowed modules, [gopkg.in/yaml.v2 github.com/go-xmlfmt/xmlfmt github.com/phayes/checkstyle github.com/mitchellh/go-homedir]
info: allowed module domains, [golang.org]
info: blocked modules, [github.com/uudashr/go-module]
info: found `2` blocked modules in the go.mod file, [github.com/gofrs/uuid github.com/uudashr/go-module]
blocked_example.go:6: import of package `github.com/gofrs/uuid` is blocked because the module is not in the allowed modules list.
blocked_example.go:7: import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library.

Resulting checkstyle file

╰─ cat gomodguard-checkstyle.xml

<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="1.0.0">
  <file name="blocked_example.go">
    <error line="6" column="1" severity="error" message="import of package `github.com/gofrs/uuid` is blocked because the module is not in the allowed modules list." source="gomodguard">
    </error>
    <error line="7" column="1" severity="error" message="import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library." source="gomodguard">
    </error>
  </file>
</checkstyle>

Install

go install github.com/ryancurrah/gomodguard/cmd/gomodguard

Develop

git clone https://github.com/ryancurrah/gomodguard.git && cd gomodguard

go build -o gomodguard cmd/gomodguard/main.go

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Allowed

type Allowed struct {
	Modules []string `yaml:"modules"`
	Domains []string `yaml:"domains"`
}

Allowed is a list of modules and module domains that are allowed to be used.

func (*Allowed) IsAllowedModule

func (a *Allowed) IsAllowedModule(moduleName string) bool

IsAllowedModule returns true if the given module name is in the allowed modules list.

func (*Allowed) IsAllowedModuleDomain

func (a *Allowed) IsAllowedModuleDomain(moduleName string) bool

IsAllowedModuleDomain returns true if the given modules domain is in the allowed module domains list.

type Blocked

type Blocked struct {
	Modules                BlockedModules  `yaml:"modules"`
	Versions               BlockedVersions `yaml:"versions"`
	LocalReplaceDirectives bool            `yaml:"local_replace_directives"`
}

Blocked is a list of modules that are blocked and not to be used.

type BlockedModule

type BlockedModule struct {
	Recommendations []string `yaml:"recommendations"`
	Reason          string   `yaml:"reason"`
}

BlockedModule has alternative modules to use and a reason why the module is blocked.

func (*BlockedModule) HasRecommendations added in v1.1.0

func (r *BlockedModule) HasRecommendations() bool

HasRecommendations returns true if the blocked package has recommended modules.

func (*BlockedModule) IsCurrentModuleARecommendation added in v1.2.0

func (r *BlockedModule) IsCurrentModuleARecommendation(currentModuleName string) bool

IsCurrentModuleARecommendation returns true if the current module is in the Recommendations list.

If the current go.mod file being linted is a recommended module of a blocked module and it imports that blocked module, do not set as blocked. This could mean that the linted module is a wrapper for that blocked module.

func (*BlockedModule) Message added in v1.1.0

func (r *BlockedModule) Message() string

Message returns the reason why the module is blocked and a list of recommended modules if provided.

type BlockedModules

type BlockedModules []map[string]BlockedModule

BlockedModules a list of blocked modules.

func (BlockedModules) Get

func (b BlockedModules) Get() []string

Get returns the module names that are blocked.

func (BlockedModules) GetBlockReason added in v1.1.0

func (b BlockedModules) GetBlockReason(lintedModuleName string) *BlockedModule

GetBlockReason returns a block module if one is set for the provided linted module name.

type BlockedVersion added in v1.1.0

type BlockedVersion struct {
	Version string `yaml:"version"`
	Reason  string `yaml:"reason"`
}

BlockedVersion has a version constraint a reason why the module version is blocked.

func (*BlockedVersion) IsLintedModuleVersionBlocked added in v1.2.0

func (r *BlockedVersion) IsLintedModuleVersionBlocked(lintedModuleVersion string) (bool, error)

IsLintedModuleVersionBlocked returns true if a version constraint is specified and the linted module version matches the constraint.

func (*BlockedVersion) Message added in v1.1.0

func (r *BlockedVersion) Message(lintedModuleVersion string) string

Message returns the reason why the module version is blocked.

type BlockedVersions added in v1.1.0

type BlockedVersions []map[string]BlockedVersion

BlockedVersions a list of blocked modules by a version constraint.

func (BlockedVersions) Get added in v1.1.0

func (b BlockedVersions) Get() []string

Get returns the module names that are blocked.

func (BlockedVersions) GetBlockReason added in v1.1.0

func (b BlockedVersions) GetBlockReason(lintedModuleName string) *BlockedVersion

GetBlockReason returns a block version if one is set for the provided linted module name.

type Configuration

type Configuration struct {
	Allowed Allowed `yaml:"allowed"`
	Blocked Blocked `yaml:"blocked"`
}

Configuration of gomodguard allow and block lists.

type Issue added in v1.2.1

type Issue struct {
	FileName   string
	LineNumber int
	Position   token.Position
	Reason     string
}

Issue represents the result of one error.

func (*Issue) String added in v1.2.1

func (r *Issue) String() string

String returns the filename, line number and reason of a Issue.

type Processor

type Processor struct {
	Config  *Configuration
	Modfile *modfile.File
	// contains filtered or unexported fields
}

Processor processes Go files.

func NewProcessor

func NewProcessor(config *Configuration) (*Processor, error)

NewProcessor will create a Processor to lint blocked packages.

func (*Processor) ProcessFiles

func (p *Processor) ProcessFiles(filenames []string) (issues []Issue)

ProcessFiles takes a string slice with file names (full paths) and lints them.

func (*Processor) SetBlockedModules added in v1.2.0

func (p *Processor) SetBlockedModules()

SetBlockedModules determines and sets which modules are blocked by reading the go.mod file of the module that is being linted.

It works by iterating over the dependant modules specified in the require directive, checking if the module domain or full name is in the allowed list.

Directories

Path Synopsis
cmd
internal
cli

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL