Search code examples
gogo-modules

What's the Go (mod) equivalent of npm-outdated?


I'd like to keep my go.mod dependencies up to date. With Node.js, I run the npm outdated (and later npm update).

What's the closest for Go mod?

Ideally, I'd see a report of outdated dependencies of my project (not all recursively). Thanks


Solution

  • Listing direct and indirect dependencies

    This is detailed in Go 1.11 Modules: How to Upgrade and Downgrade Dependencies wiki:

    To view available minor and patch upgrades for all direct and indirect dependencies, run go list -u -m all.

    To upgrade to the latest version for all direct and indirect dependencies of the current module:

    • run go get -u to use the latest minor or patch releases
    • run go get -u=patch to use the latest patch releases

    You can read more details here: Command go: List packages or modules.

    There's also a 3rd party app: https://github.com/psampaz/go-mod-outdated:

    An easy way to find outdated dependencies of your Go projects. go-mod-outdated provides a table view of the go list -u -m -json all command which lists all dependencies of a Go project and their available minor and patch updates. It also provides a way to filter indirect dependencies and dependencies without updates.

    Listing only direct dependencies

    If you are not interested in indirect dependencies, we can filter them out. There is no flag to filter out indirect dependencies, but we can do that with custom output format.

    The -f flag specifies an alternate format for the list, using the syntax of package template.

    So you may specify a format being a template document, conforming with text/template.

    When listing modules, the -f flag still specifies a format template applied to a Go struct, but now a Module struct:

    type Module struct {
        Path     string       // module path
        Version  string       // module version
        Versions []string     // available module versions (with -versions)
        Replace  *Module      // replaced by this module
        Time     *time.Time   // time version was created
        Update   *Module      // available update, if any (with -u)
        Main     bool         // is this the main module?
        Indirect bool         // is this module only an indirect dependency of main module?
        Dir      string       // directory holding files for this module, if any
        GoMod    string       // path to go.mod file for this module, if any
        Error    *ModuleError // error loading module
    }
    
    type ModuleError struct {
        Err string // the error itself
    }
    

    Note: this Module struct is defined in an internal package of the command go: https://godoc.org/cmd/go/internal/modinfo

    So for example to list direct and indirect dependencies as before, but now also append an IAMINDIRECT word after indirect dependencies, it could be done with:

    go list -u -m -f '{{.}}{{if .Indirect}} IAMINDIRECT{{end}}' all
    

    Negating the logic, to list direct and indirect dependencies, but this time "mark" only the direct dependencies with IAMDIRECT:

    go list -u -m -f '{{.}}{{if not .Indirect}} IAMDIRECT{{end}}' all
    

    And we're almost there. We now just have to filter out rows that do not contain the IAMDIRECT word:

    go list -u -m -f '{{.}}{{if not .Indirect}} IAMDIRECT{{end}}' all | grep IAMDIRECT
    

    Alternative

    The above solution builds on the grep command. But in fact we don't need that. If the specified template results in an empty document, the line is skipped from the output.

    So we can achieve the same like this:

    go list -u -m -f '{{if not .Indirect}}{{.}}{{end}}' all
    

    Basically we only call Module.String() (we only include a dependency) if it is not indirect. As an extra gain, this solution also works on Windows too.

    Listing only dependencies that have updates

    Similarly how we filtered out indirect dependencies, this is also a "piece of cake" since the Module structure contains an Update field for packages / modules that have updates:

    go list -u -m -f '{{if .Update}}{{.}}{{end}}' all
    

    Also see related question: How to list installed go packages