digitalocean / gta

gta: do transitive analysis to find packages whose dependencies have changed
Apache License 2.0
202 stars 21 forks source link

Add support for go modules by switching over to go/packages #8

Closed nanzhong closed 3 years ago

nanzhong commented 4 years ago

I took a stab at switching over to go/packages so that we can support go modules. See the link for more detailed information about go/packages, but below is a summary of the big differences in how go/packages and their impact on the implementation changes to gta in this PR:

High Level Overview of Implementation

  1. Using the differ, determine the set of changed files
  2. Load all the packages matching the provided -include flag
  3. Construct dependency graph using the loaded packages
    • the dependency graph holds package nodes that each have a set of dependencies and dependents
    • a few auxiliary maps are built for lookups
    • keep track of package ID -> package mapping
    • keep track of package path -> packages mapping
    • keep track of file -> package mapping
    • keep track of best effort directory -> package mapping
  4. Use the dependency graph to determine the set of transitive dependents

Todo and Known Limitations

Verification

Because I haven't yet reworked all the existing tests to pass, I've been relying on comparing results between the existing implementation of gta and the new implementation, using cthluhu merge commits test cases. This is definitely a crutch, but it was a good way to validate progress.

https://github.internal.digitalocean.com/gist/nanzhong/a32eba444a7bef260a5193efa26cc4a3 contains the test script as well some initial results of the latest ~70 merge commits.

Differing Cases

Out of the ~70 test cases, 2 have differing results.

Handling *_test Packages

Cthulhu merge commit 97a167826ac22d64476b130cbf215a3e418a382d.

The first I think is hitting an edge case that the existing gta implementation doesn't quite handle correctly. The following is a simplified example case: -- foo/foo.go

package foo

const Foo = "foo"

-- foo/foo_test.go

package foo_test

-- bar/bar.go

package bar

import "foo"

const import_foo = foo.Foo

If foo/foo_test.go changed what should the dirty packages be?

The existing gta implementation says both foo and bar are dirty. The new implementation says only foo is dirty. A file change that maps to the foo_test package should only ever affect the foo package. @bhcleek pointed out to me that this is an edge case that gta currently does not handle well.

Dirty vendor packages

Cthulhu merge commit 8bbfdc2ca9b728da4c90f166cfbc69efe10642d9.

I haven't had a chance to dig into this yet, but the existing implementation reported dirty vendor packages. I'm not sure I fully understand the reason for this.

bhcleek commented 3 years ago

Closing in favor of #11.